继续前两天的博客内容,接着写Java中的ACT游戏实现,本来记得手里有C++版马里奥的角色和地图的,突然找不到丢那里了,凑活ps个GBA火影的图代替下……
运行效果如下:

此次重点演示了角色和地图的绘制……其实看过我以前写JAVA的RPG开发blog文章的早知道怎么弄的了……所以此次只帖代码……
Role.java:
package org.test.mario;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;

import org.loon.framework.game.image.Bitmap;

/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:角色描述及绘制用类
* </p>
* <p>
* Copyright: Copyright (c) 2008
* </p>
* <p>
* Company: LoonFramework
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class Role {

private double _x;

private double _y;

private double _vx;

private double _vy;

private boolean isFlat;

private int _dir;

private int _count;

final static private Image role = new Bitmap("./role.gif").getImage();

private Map _map;

final static public int WIDTH = 40;

final static public int HEIGHT = 40;

final static private int SPEED = 6;

final static private int JUMP_SPEED = 16;

final static private int RIGHT = 0;

final static private int LEFT = 1;

public Role(double _x, double _y, Map _map) {
this._x = _x;
this._y = _y;
this._map = _map;
_vx = 0;
_vy = 0;
isFlat = false;
_dir = RIGHT;
_count = 0;

AnimationThread thread = new AnimationThread();
thread.start();
}

public void stop() {
_vx = 0;
}

public void left() {
_vx = -SPEED;
_dir = LEFT;
}

public void right() {
_vx = SPEED;
_dir = RIGHT;
}

public void jump() {
if (isFlat) {
_vy = -JUMP_SPEED;
isFlat = false;
}
}

public void update() {
//0.6为允许跳跃的高度限制,反值效果
_vy += 0.6;

double newX = _x + _vx;

Point tile = _map.getTileHit(this, newX, _y);
if (tile == null) {
_x = newX;
} else {
if (_vx > 0) {

_x = Map.tilesToPixels(tile.x) - WIDTH;
} else if (_vx < 0) {
_x = Map.tilesToPixels(tile.x + 1);
}
_vx = 0;
}

double newY = _y + _vy;
tile = _map.getTileHit(this, _x, newY);
if (tile == null) {
_y = newY;
isFlat = false;
} else {
if (_vy > 0) {
_y = Map.tilesToPixels(tile.y) - HEIGHT;
_vy = 0;
isFlat = true;
} else if (_vy < 0) {
_y = Map.tilesToPixels(tile.y + 1);
_vy = 0;
}
}
}

public void draw(Graphics g, int offsetX, int offsetY) {
g.drawImage(role, (int) _x + offsetX, (int) _y + offsetY, (int) _x
+ offsetX + WIDTH, (int) _y + offsetY + HEIGHT, _count * WIDTH,
_dir * HEIGHT, _count * WIDTH + WIDTH, _dir * HEIGHT + HEIGHT,
null);
}

public double getX() {
return _x;
}

public double getY() {
return _y;
}

private class AnimationThread extends Thread {
public void run() {
while (true) {
if (_count == 0) {
_count = 1;
} else if (_count == 1) {
_count = 0;
}

try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

}
Map.java:
package org.test.mario;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;

import org.loon.framework.game.image.Bitmap;

/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:地图绘制及描述用类
* </p>
* <p>
* Copyright: Copyright (c) 2008
* </p>
* <p>
* Company: LoonFramework
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class Map {

// 在以前的blog文章中我介绍过,游戏开发中通常以数组描述地图
// 此处1描绘为一个障碍物,0描绘为一个可通行空间
final static public int TILE_SIZE = 32;

final static public int ROW = 20;

final static public int COL = 30;

final static public int WIDTH = TILE_SIZE * COL;

final static public int HEIGHT = TILE_SIZE * ROW;

final static public double GRAVITY = 0.6;

// 地图描述
final static private int[][] map = {
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 1 },
{ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 1, 0, 0,
0, 0, 0, 0, 0, 0, 2, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 1 } };

final static private Image tile = new Bitmap("./tile_0.gif").getImage();

final static private Image tile2 = new Bitmap("./tile_1.gif").getImage();

/**
* 构造函数
*
*/
public Map() {
}

public void draw(Graphics g, int offsetX, int offsetY) {
int firstTileX = pixelsToTiles(-offsetX);
int lastTileX = firstTileX + pixelsToTiles(Main._WIDTH) + 1;
lastTileX = Math.min(lastTileX, COL);
int firstTileY = pixelsToTiles(-offsetY);
int lastTileY = firstTileY + pixelsToTiles(Main._HEIGHT) + 1;
lastTileY = Math.min(lastTileY, ROW);

for (int i = firstTileY; i < lastTileY; i++) {
for (int j = firstTileX; j < lastTileX; j++) {
// 转换map标识
switch (map[i][j]) {
case 1: // 绘制砖地

g.drawImage(tile, tilesToPixels(j) + offsetX,
tilesToPixels(i) + offsetY, null);
break;
case 2:
g.drawImage(tile2, tilesToPixels(j) + offsetX,
tilesToPixels(i) + offsetY, null);
break;
}
}
}
}

/**
* 换算角色与地板的撞击,并返回Point用以描述新的x,y
*
* @param player
* @param newX
* @param newY
* @return
*/
public Point getTileHit(Role player, double newX, double newY) {

newX = Math.ceil(newX);
newY = Math.ceil(newY);

double fromX = Math.min(player.getX(), newX);
double fromY = Math.min(player.getY(), newY);
double toX = Math.max(player.getX(), newX);
double toY = Math.max(player.getY(), newY);

int fromTileX = pixelsToTiles(fromX);
int fromTileY = pixelsToTiles(fromY);
int toTileX = pixelsToTiles(toX + Role.WIDTH - 1);
int toTileY = pixelsToTiles(toY + Role.HEIGHT - 1);

for (int x = fromTileX; x <= toTileX; x++) {
for (int y = fromTileY; y <= toTileY; y++) {

if (x < 0 || x >= COL) {
return new Point(x, y);
}
if (y < 0 || y >= ROW) {
return new Point(x, y);
}
if (map[y][x] == 1 || map[y][x] == 2) {
return new Point(x, y);
}
}
}

return null;
}

/**
* 将Tiles转为Pixels
*
* @param pixels
* @return
*/
public static int pixelsToTiles(double pixels) {
return (int) Math.floor(pixels / TILE_SIZE);
}

/**
* 将Pixels转为Tiles
*
* @param pixels
* @return
*/
public static int tilesToPixels(int tiles) {
return tiles * TILE_SIZE;
}
}
Main.java
package org.test.mario;

import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import org.loon.framework.game.image.Bitmap;

/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:
* </p>
* <p>
* Copyright: Copyright (c) 2008
* </p>
* <p>
* Company: LoonFramework
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class Main extends Panel implements Runnable, KeyListener {

/**
*
*/
private static final long serialVersionUID = 1L;

public static final int _WIDTH = 640;

public static final int _HEIGHT = 480;

private Map _map;

private Role _role;

private Thread _sleep;

private Image _screen = null;

private Graphics _graphics = null;

// 方向控制,由于是自然落体所以没有down
private boolean LEFT;

private boolean RIGHT;

private boolean UP;

public Main() {
setSize(_WIDTH, _HEIGHT);
setFocusable(true);
_screen = new Bitmap(_WIDTH, _HEIGHT).getImage();
_graphics = _screen.getGraphics();
_map = new Map();
_role = new Role(190, 40, _map);

// 监听窗体
addKeyListener(this);

// 启动线程
_sleep = new Thread(this);
_sleep.start();
}

/**
* 运行
*/
public void run() {
while (true) {
//改变方向
if (LEFT) {
_role.left();
} else if (RIGHT) {
_role.right();
} else {
_role.stop();
}
if (UP) {
_role.jump();
}
_role.update();
repaint();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public void update(Graphics g) {
paint(g);
}

public void paint(Graphics g) {
_graphics.setColor(Color.BLACK);
_graphics.fillRect(0, 0, _WIDTH, _HEIGHT);

int offsetX = _WIDTH / 2 - (int)_role.getX();
offsetX = Math.min(offsetX, 0);
offsetX = Math.max(offsetX, _WIDTH - Map.WIDTH);

int offsetY =_HEIGHT / 2 - (int)_role.getY();
offsetY = Math.min(offsetY, 0);
offsetY = Math.max(offsetY, _HEIGHT - Map.HEIGHT);


_map.draw(_graphics, offsetX, offsetY);

_role.draw(_graphics, offsetX, offsetY);
g.drawImage(_screen, 0,0,null);
}

public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
LEFT = true;
}
if (key == KeyEvent.VK_RIGHT) {
RIGHT = true;
}
if (key == KeyEvent.VK_UP) {
UP = true;
}
}

public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
LEFT = false;
}
if (key == KeyEvent.VK_RIGHT) {
RIGHT = false;
}
if (key == KeyEvent.VK_UP) {
UP = false;
}
}

public void keyTyped(KeyEvent e) {
}

public static void main(String[] args) {
Frame frame = new Frame();
frame.setTitle("Java来做马里奥(2)—木叶传承");
frame.setSize(_WIDTH, _HEIGHT+20);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.add(new Main());
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}

}
以上……
突然觉得这样做也挺有意思的,准备让木叶丸踩三代玩,啊哈哈哈……(众人曰:神经病)||||
运行效果如下:

此次重点演示了角色和地图的绘制……其实看过我以前写JAVA的RPG开发blog文章的早知道怎么弄的了……所以此次只帖代码……
Role.java:




































































































































































Map.java:
























































































































































































Main.java

















































































































































































以上……
突然觉得这样做也挺有意思的,准备让木叶丸踩三代玩,啊哈哈哈……(众人曰:神经病)||||