效果图如下:
在ACT类游戏中,你所扮演的角色时常会与各种杂兵发生这样或者那样的冲突,以此来增强游戏性。本回将例举一种Java游戏的杂兵制造方式。
在此例中将原来的 getTileHit改为注入Sprite,以此统一处理角色及杂兵的碰撞。
Food.java(扮演食物的角色)
Sandaime.java(扮演杂兵的角色)
Role.java(扮演主角)
Sprite.java(抽象的精灵类)
Map.java(地图描述)
Main.java(部署及运行)
在ACT类游戏中,你所扮演的角色时常会与各种杂兵发生这样或者那样的冲突,以此来增强游戏性。本回将例举一种Java游戏的杂兵制造方式。
在此例中将原来的 getTileHit改为注入Sprite,以此统一处理角色及杂兵的碰撞。
public
Point getTileHit(Sprite sprite,
double
newX,
double
newY)
Food.java(扮演食物的角色)
package
org.test.mario;
/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:食物用类
* </p>
* <p>
* Copyright: Copyright (c) 2008
* </p>
* <p>
* Company: LoonFramework
* </p>
* <p>
* License: http://www.apache.org/licenses/LICENSE-2.0
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class Food extends Sprite {
public Food(String fileName, double x, double y, Map map) {
super(fileName, x, y, map);
}
public void update() {
}
}
/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:食物用类
* </p>
* <p>
* Copyright: Copyright (c) 2008
* </p>
* <p>
* Company: LoonFramework
* </p>
* <p>
* License: http://www.apache.org/licenses/LICENSE-2.0
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class Food extends Sprite {
public Food(String fileName, double x, double y, Map map) {
super(fileName, x, y, map);
}
public void update() {
}
}
Sandaime.java(扮演杂兵的角色)
package
org.test.mario;
import java.awt.Point;
/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:
* </p>
* <p>
* Copyright: Copyright (c) 2008
* </p>
* <p>
* Company: LoonFramework
* </p>
* <p>
* License: http://www.apache.org/licenses/LICENSE-2.0
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class Sandaime extends Sprite {
private static final double SPEED = 1;
private double _vx;
private double _vy;
public Sandaime(String filename, double x, double y, Map map) {
super(filename, x, y, map);
width = 80;
height = 75;
_vx = -SPEED;
_vy = 0;
}
public void update() {
_vy += 0.1;
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 = -_vx;
}
double newY = _y + _vy;
tile = _map.getTileHit(this, _x, newY);
if (tile == null) {
_y = newY;
} else {
if (_vy > 0) {
_y = Map.tilesToPixels(tile.y) - height;
_vy = 0;
} else if (_vy < 0) {
_y = Map.tilesToPixels(tile.y + 1);
_vy = 0;
}
}
}
}
import java.awt.Point;
/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:
* </p>
* <p>
* Copyright: Copyright (c) 2008
* </p>
* <p>
* Company: LoonFramework
* </p>
* <p>
* License: http://www.apache.org/licenses/LICENSE-2.0
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public class Sandaime extends Sprite {
private static final double SPEED = 1;
private double _vx;
private double _vy;
public Sandaime(String filename, double x, double y, Map map) {
super(filename, x, y, map);
width = 80;
height = 75;
_vx = -SPEED;
_vy = 0;
}
public void update() {
_vy += 0.1;
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 = -_vx;
}
double newY = _y + _vy;
tile = _map.getTileHit(this, _x, newY);
if (tile == null) {
_y = newY;
} else {
if (_vy > 0) {
_y = Map.tilesToPixels(tile.y) - height;
_vy = 0;
} else if (_vy < 0) {
_y = Map.tilesToPixels(tile.y + 1);
_vy = 0;
}
}
}
}
Role.java(扮演主角)
package
org.test.mario;
import java.awt.Graphics;
import java.awt.Point;
/**
* <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 extends Sprite {
private double _vx;
private double _vy;
private boolean _isFlat;
private int _dir;
// 强制跳跃
private boolean _forceJump;
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;
/**
* 构造函数,以角色图位置,初始的x、y坐标,地图四项参数创建一个可用的角色
*
* @param filename
* @param x
* @param y
* @param map
*/
public Role(String filename, double x, double y, Map map) {
super(filename, x, y, map);
width=40;
height=40;
_vx = 0;
_vy = 0;
_isFlat = false;
_forceJump = false;
_dir = RIGHT;
}
public void setJump(boolean forceJump) {
_forceJump = forceJump;
}
public void stop() {
_vx = 0;
}
public void left() {
_vx = -SPEED;
_dir = LEFT;
}
public void right() {
_vx = SPEED;
_dir = RIGHT;
}
public void jump() {
if (_isFlat || _forceJump) {
_vy = -JUMP_SPEED;
_isFlat = false;
_forceJump = 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(_image, (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);
}
}
import java.awt.Graphics;
import java.awt.Point;
/**
* <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 extends Sprite {
private double _vx;
private double _vy;
private boolean _isFlat;
private int _dir;
// 强制跳跃
private boolean _forceJump;
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;
/**
* 构造函数,以角色图位置,初始的x、y坐标,地图四项参数创建一个可用的角色
*
* @param filename
* @param x
* @param y
* @param map
*/
public Role(String filename, double x, double y, Map map) {
super(filename, x, y, map);
width=40;
height=40;
_vx = 0;
_vy = 0;
_isFlat = false;
_forceJump = false;
_dir = RIGHT;
}
public void setJump(boolean forceJump) {
_forceJump = forceJump;
}
public void stop() {
_vx = 0;
}
public void left() {
_vx = -SPEED;
_dir = LEFT;
}
public void right() {
_vx = SPEED;
_dir = RIGHT;
}
public void jump() {
if (_isFlat || _forceJump) {
_vy = -JUMP_SPEED;
_isFlat = false;
_forceJump = 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(_image, (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);
}
}
Sprite.java(抽象的精灵类)
package
org.test.mario;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import org.loon.framework.game.image.Bitmap;
/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:精灵类(为了批量制造角色,将Role中通用设定抽象成此类)
* </p>
* <p>
* Copyright: Copyright (c) 2008
* </p>
* <p>
* Company: LoonFramework
* </p>
* <p>
* License: http://www.apache.org/licenses/LICENSE-2.0
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public abstract class Sprite {
// 坐标
protected double _x;
protected double _y;
// 宽
protected int width;
// 高
protected int height;
// 图像
protected Image _image;
// 步数
protected int _count;
// 地图
protected Map _map;
/**
* 构造函数,以角色图位置,初始的x、y坐标,地图四项参数创建一个可用的角色
*
* @param fileName
* @param _x
* @param _y
* @param map
*/
public Sprite(String fileName,double _x, double _y, Map map) {
this._x = _x;
this._y = _y;
this._map = map;
width = 32;
height = 32;
loadImage(fileName);
_count = 0;
AnimationThread thread = new AnimationThread();
thread.start();
}
public abstract void update();
public void draw(Graphics g, int offsetX, int offsetY) {
g.drawImage(_image, (int) _x + offsetX, (int) _y + offsetY, (int) _x
+ offsetX + width, (int) _y + offsetY + height, _count * width,
0, _count * width + width, height, null);
}
public boolean isHit(Sprite sprite) {
Rectangle playerRect = new Rectangle((int) _x, (int) _y, width, height);
Rectangle spriteRect = new Rectangle((int) sprite.getX(), (int) sprite
.getY(), sprite.getWidth(), sprite.getHeight());
// 判定两者边框是否相交
if (playerRect.intersects(spriteRect)) {
return true;
}
return false;
}
public double getX() {
return _x;
}
public double getY() {
return _y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
private void loadImage(String filename) {
_image = new Bitmap(filename).getImage();
}
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();
}
}
}
}
public void setHeight(int height) {
this.height = height;
}
public void setWidth(int width) {
this.width = width;
}
}
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import org.loon.framework.game.image.Bitmap;
/**
* <p>
* Title: LoonFramework
* </p>
* <p>
* Description:精灵类(为了批量制造角色,将Role中通用设定抽象成此类)
* </p>
* <p>
* Copyright: Copyright (c) 2008
* </p>
* <p>
* Company: LoonFramework
* </p>
* <p>
* License: http://www.apache.org/licenses/LICENSE-2.0
* </p>
*
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
public abstract class Sprite {
// 坐标
protected double _x;
protected double _y;
// 宽
protected int width;
// 高
protected int height;
// 图像
protected Image _image;
// 步数
protected int _count;
// 地图
protected Map _map;
/**
* 构造函数,以角色图位置,初始的x、y坐标,地图四项参数创建一个可用的角色
*
* @param fileName
* @param _x
* @param _y
* @param map
*/
public Sprite(String fileName,double _x, double _y, Map map) {
this._x = _x;
this._y = _y;
this._map = map;
width = 32;
height = 32;
loadImage(fileName);
_count = 0;
AnimationThread thread = new AnimationThread();
thread.start();
}
public abstract void update();
public void draw(Graphics g, int offsetX, int offsetY) {
g.drawImage(_image, (int) _x + offsetX, (int) _y + offsetY, (int) _x
+ offsetX + width, (int) _y + offsetY + height, _count * width,
0, _count * width + width, height, null);
}
public boolean isHit(Sprite sprite) {
Rectangle playerRect = new Rectangle((int) _x, (int) _y, width, height);
Rectangle spriteRect = new Rectangle((int) sprite.getX(), (int) sprite
.getY(), sprite.getWidth(), sprite.getHeight());
// 判定两者边框是否相交
if (playerRect.intersects(spriteRect)) {
return true;
}
return false;
}
public double getX() {
return _x;
}
public double getY() {
return _y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
private void loadImage(String filename) {
_image = new Bitmap(filename).getImage();
}
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();
}
}
}
}
public void setHeight(int height) {
this.height = height;
}
public void setWidth(int width) {
this.width = width;
}
}
Map.java(地图描述)
package
org.test.mario;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.util.LinkedList;
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;
//缓存精灵的list
private LinkedList sprites;
// 地图描述
final static private int[][] map = {
{ 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, 0, 2 },
{ 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, 0, 1 },
{ 2, 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, 3, 3, 3, 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, 2, 2, 2, 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, 3, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 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, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 4, 3, 3, 1, 2, 2,
0, 0, 0, 0, 0, 0, 3, 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() {
//精灵list
sprites=new LinkedList();
//注入兵粮丸
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
switch (map[i][j]) {
case 3:
sprites.add(new Food("./food.gif",tilesToPixels(j), tilesToPixels(i),this));
break;
case 4:
sprites.add(new Sandaime("./sdm.gif",tilesToPixels(j), tilesToPixels(i),this));
break;
}
}
}
}
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 sprite
* @param newX
* @param newY
* @return
*/
public Point getTileHit(Sprite sprite, double newX, double newY) {
newX = Math.ceil(newX);
newY = Math.ceil(newY);
double fromX = Math.min(sprite.getX(), newX);
double fromY = Math.min(sprite.getY(), newY);
double toX = Math.max(sprite.getX(), newX);
double toY = Math.max(sprite.getY(), newY);
int fromTileX = pixelsToTiles(fromX);
int fromTileY = pixelsToTiles(fromY);
int toTileX = pixelsToTiles(toX + sprite.getWidth() - 1);
int toTileY = pixelsToTiles(toY + sprite.getHeight() - 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;
}
/**
* 返回Sprite list
* @return
*/
public LinkedList getSprites() {
return sprites;
}
public void setSprites(LinkedList sprites) {
this.sprites = sprites;
}
}
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.util.LinkedList;
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;
//缓存精灵的list
private LinkedList sprites;
// 地图描述
final static private int[][] map = {
{ 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, 0, 2 },
{ 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, 0, 1 },
{ 2, 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, 3, 3, 3, 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, 2, 2, 2, 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, 3, 0,
0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 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, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 4, 3, 3, 1, 2, 2,
0, 0, 0, 0, 0, 0, 3, 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() {
//精灵list
sprites=new LinkedList();
//注入兵粮丸
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
switch (map[i][j]) {
case 3:
sprites.add(new Food("./food.gif",tilesToPixels(j), tilesToPixels(i),this));
break;
case 4:
sprites.add(new Sandaime("./sdm.gif",tilesToPixels(j), tilesToPixels(i),this));
break;
}
}
}
}
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 sprite
* @param newX
* @param newY
* @return
*/
public Point getTileHit(Sprite sprite, double newX, double newY) {
newX = Math.ceil(newX);
newY = Math.ceil(newY);
double fromX = Math.min(sprite.getX(), newX);
double fromY = Math.min(sprite.getY(), newY);
double toX = Math.max(sprite.getX(), newX);
double toY = Math.max(sprite.getY(), newY);
int fromTileX = pixelsToTiles(fromX);
int fromTileY = pixelsToTiles(fromY);
int toTileX = pixelsToTiles(toX + sprite.getWidth() - 1);
int toTileY = pixelsToTiles(toY + sprite.getHeight() - 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;
}
/**
* 返回Sprite list
* @return
*/
public LinkedList getSprites() {
return sprites;
}
public void setSprites(LinkedList sprites) {
this.sprites = sprites;
}
}
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 java.util.Iterator;
import java.util.LinkedList;
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;
// 底层背景
final static private Image back = new Bitmap("./雕像.png").getImage();
public Main() {
setSize(_WIDTH, _HEIGHT);
setFocusable(true);
_screen = new Bitmap(_WIDTH, _HEIGHT).getImage();
_graphics = _screen.getGraphics();
_map = new Map();
// 设置扮演的角色
_role = new Role("role.gif", 190, 40, _map);
// 监听窗体
addKeyListener(this);
// 启动线程
_sleep = new Thread(this);
_sleep.start();
}
public void gameOver() {
_map = new Map();
_role = new Role("role.gif", 190, 40, _map);
}
/**
* 运行
*/
public void run() {
while (true) {
// 改变方向
if (LEFT) {
_role.left();
} else if (RIGHT) {
_role.right();
} else {
_role.stop();
}
if (UP) {
_role.jump();
}
_role.update();
LinkedList sprites = _map.getSprites();
for (Iterator it = sprites.iterator(); it.hasNext();) {
// 还原为sprite
Sprite sprite = (Sprite) it.next();
// 变更精灵状态
sprite.update();
// 碰撞检测
if (_role.isHit(sprite)) {
// 对象检测,为兵粮丸时
if (sprite instanceof Food) {
Food coin = (Food) sprite;
// 删除对象
// it.remove();
sprites.remove(coin);
break;
//为三代目时
}else if (sprite instanceof Sandaime) {
Sandaime sdm = (Sandaime)sprite;
if ((int)_role.getY() < (int)sdm.getY()) {
sprites.remove(sdm);
_role.setJump(true);
_role.jump();
break;
} else {
gameOver();
}
}
}
}
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);
_graphics.drawImage(back, 0, 0, this);
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);
// 遍历精灵对象并绘制
LinkedList sprites = _map.getSprites();
for (Iterator it = sprites.iterator(); it.hasNext();) {
Sprite sprite = (Sprite) it.next();
sprite.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来做马里奥(4)—杂兵登场");
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);
}
});
}
}
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 java.util.Iterator;
import java.util.LinkedList;
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;
// 底层背景
final static private Image back = new Bitmap("./雕像.png").getImage();
public Main() {
setSize(_WIDTH, _HEIGHT);
setFocusable(true);
_screen = new Bitmap(_WIDTH, _HEIGHT).getImage();
_graphics = _screen.getGraphics();
_map = new Map();
// 设置扮演的角色
_role = new Role("role.gif", 190, 40, _map);
// 监听窗体
addKeyListener(this);
// 启动线程
_sleep = new Thread(this);
_sleep.start();
}
public void gameOver() {
_map = new Map();
_role = new Role("role.gif", 190, 40, _map);
}
/**
* 运行
*/
public void run() {
while (true) {
// 改变方向
if (LEFT) {
_role.left();
} else if (RIGHT) {
_role.right();
} else {
_role.stop();
}
if (UP) {
_role.jump();
}
_role.update();
LinkedList sprites = _map.getSprites();
for (Iterator it = sprites.iterator(); it.hasNext();) {
// 还原为sprite
Sprite sprite = (Sprite) it.next();
// 变更精灵状态
sprite.update();
// 碰撞检测
if (_role.isHit(sprite)) {
// 对象检测,为兵粮丸时
if (sprite instanceof Food) {
Food coin = (Food) sprite;
// 删除对象
// it.remove();
sprites.remove(coin);
break;
//为三代目时
}else if (sprite instanceof Sandaime) {
Sandaime sdm = (Sandaime)sprite;
if ((int)_role.getY() < (int)sdm.getY()) {
sprites.remove(sdm);
_role.setJump(true);
_role.jump();
break;
} else {
gameOver();
}
}
}
}
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);
_graphics.drawImage(back, 0, 0, this);
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);
// 遍历精灵对象并绘制
LinkedList sprites = _map.getSprites();
for (Iterator it = sprites.iterator(); it.hasNext();) {
Sprite sprite = (Sprite) it.next();
sprite.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来做马里奥(4)—杂兵登场");
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);
}
});
}
}