📄 gametank.java
字号:
package com.ipanel.games.tank;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.Sprite;
public class GameTank implements bulletTarget, boomDrawer {
private static Image imageTank = null;
private Sprite spriteTank = null;
private final int FRAME_SEQUENCE_UP = 0;
private final int FRAME_SEQUENCE_RIGHT = 1;
private final int FRAME_SEQUENCE_DOWN = 2;
private final int FRAME_SEQUENCE_LEFT = 3;
private static Image imageBoom = null;
/**
* 程序中所有N处不同地方使用的Random,应该是各不相同的,所以用这个数组来存储。 但是由此引发的是,必须保证不会出现数组越界的行为。
*/
private IPTankRandom[] tankRandoms = null;
private Timer timer = new Timer();
private int X_INIT;
private int Y_INIT;
private final int NO_ACTION = 0;
private final int ACTION_DIRECTION_UP = 1;
private final int ACTION_DIRECTION_DOWN = 2;
private final int ACTION_DIRECTION_LEFT = 3;
private final int ACTION_DIRECTION_RIGHT = 4;
private final int ACTION_MOVE = 5;
private final int ACTION_FIRE = 6;
private final int DIRECTION_UP = 1;
private final int DIRECTION_DOWN = 2;
private final int DIRECTION_LEFT = 3;
private final int DIRECTION_RIGHT = 4;
private final GameLayer layer;
private int iDirection;
private int X;
private int Y;
private final int STEP;
private final int MAX_FIRE_NUMBER = 2;
private int iFireNumber = 0;
/**
* 调度时间的间隔。 这同时影响到ACTION的速度,和对canvas.paint()的配合。
*/
private final int TIMER_INTERVAL = 50;
static {
/*
* try { // imageTank = Image.createImage("/res/TankAll.png"); imageTank =
* Image.createImage("/res/Tank.png"); imageBoom =
* Image.createImage("/res/explosion13.png"); } catch (IOException e) {
* System.out.println("Exception when createImage in GameTank()!"); }
*/
}
public GameTank(GameLayer layer, long lRandomSeed) throws IOException {
super();
this.layer = layer;
try {
imageTank = Image.createImage("/res/EnemyTankAll.png");
// imageTank = Image.createImage("/res/TankAll.png");
imageBoom = Image.createImage("/res/explosion13.png");
} catch (IOException e) {
layer.paintException("Exception when createImage in GameTank()!");
throw e;
}
// spriteTank = new Sprite(imageTank);
spriteTank = new Sprite(imageTank, 32, 32);
spriteTank
.setFrameSequence(new int[] { FRAME_SEQUENCE_UP,
FRAME_SEQUENCE_RIGHT, FRAME_SEQUENCE_DOWN,
FRAME_SEQUENCE_LEFT });
tankRandoms = new IPTankRandom[] { new IPTankRandom(lRandomSeed),
new IPTankRandom(lRandomSeed / 2),
new IPTankRandom(lRandomSeed * 3),
new IPTankRandom(lRandomSeed / 5),
new IPTankRandom(lRandomSeed * 10) };
initPosition();
X = X_INIT;
Y = Y_INIT;
spriteTank.setPosition(X, Y);
iDirection = DIRECTION_DOWN;
spriteTank.setFrame(FRAME_SEQUENCE_DOWN);
layer.registGameTank(this);
STEP = 3;
tankBusiness();
}
private void initPosition() {
Y_INIT = 0;
/**
* 2^2=4
*/
switch (tankRandoms[0].next(2)) {
case 0:
X_INIT = GameLayer.AREA_UP_LEFT_X;
break;
case 1:
X_INIT = GameLayer.AREA_UP_LEFT_X + GameLayer.AREA_WIDTH / 2
- spriteTank.getWidth() / 2;
break;
case 2:
X_INIT = GameLayer.AREA_UP_LEFT_X + GameLayer.AREA_WIDTH
- spriteTank.getWidth();
break;
case 4:
X_INIT = GameLayer.AREA_UP_LEFT_X + GameLayer.AREA_WIDTH / 2
- spriteTank.getWidth() / 2;
break;
}
}
/**
* 因为timer.schdule()会顺延TimerTask的执行,所以以下所有ACTION的执行不会有时间上的重叠。
* 同时,因为需要和IPTankGameCanvas.GameTask.run()的同步
* (比如不能让GameTank正处于"界外"的情况下被flushGraphics()出来), 这里仍然采用了synchronized。
*/
private void tankBusiness() {
timer.schedule(new GameTankTask(), 0, TIMER_INTERVAL);
}
class GameTankTask extends TimerTask {
public void run() {
try {
Thread.currentThread().sleep(50);
} catch (InterruptedException e) {
layer.paintException("Exception from Thread.sleep()!");
}
/**
* 所有Timer调度的线程,应该被synchronized(GameLayer)。
*/
synchronized (layer) {
switch (generateAction()) {
case NO_ACTION:
break;
case ACTION_DIRECTION_UP:
directionUP();
break;
case ACTION_DIRECTION_DOWN:
directionDOWN();
break;
case ACTION_DIRECTION_LEFT:
directionLEFT();
break;
case ACTION_DIRECTION_RIGHT:
directionRIGHT();
break;
case ACTION_MOVE:
Move();
break;
case ACTION_FIRE:
Fire();
break;
}
}
}
}
private void directionUP() {
int iLastDirection = iDirection;
iDirection = DIRECTION_UP;
spriteTank.setFrame(FRAME_SEQUENCE_UP);
adjustDirection(iLastDirection);
}
private void directionDOWN() {
int iLastDirection = iDirection;
iDirection = DIRECTION_DOWN;
spriteTank.setFrame(FRAME_SEQUENCE_DOWN);
adjustDirection(iLastDirection);
}
private void directionLEFT() {
int iLastDirection = iDirection;
iDirection = DIRECTION_LEFT;
spriteTank.setFrame(FRAME_SEQUENCE_LEFT);
adjustDirection(iLastDirection);
}
private void directionRIGHT() {
int iLastDirection = iDirection;
iDirection = DIRECTION_RIGHT;
spriteTank.setFrame(FRAME_SEQUENCE_RIGHT);
adjustDirection(iLastDirection);
}
private void adjustDirection(int iLastDirection) {
if (isUnAvailablePosition()) {
iDirection = iLastDirection;
switch (iDirection) {
case DIRECTION_UP:
spriteTank.setFrame(FRAME_SEQUENCE_UP);
break;
case DIRECTION_DOWN:
spriteTank.setFrame(FRAME_SEQUENCE_DOWN);
break;
case DIRECTION_LEFT:
spriteTank.setFrame(FRAME_SEQUENCE_LEFT);
break;
case DIRECTION_RIGHT:
spriteTank.setFrame(FRAME_SEQUENCE_RIGHT);
break;
}
}
}
private void Move() {
switch (iDirection) {
case DIRECTION_UP:
Y -= STEP;
spriteTank.setPosition(X, Y);
if (isUnAvailablePosition()) {
Y += STEP;
spriteTank.setPosition(X, Y);
}
break;
case DIRECTION_DOWN:
Y += STEP;
spriteTank.setPosition(X, Y);
if (isUnAvailablePosition()) {
Y -= STEP;
spriteTank.setPosition(X, Y);
}
break;
case DIRECTION_LEFT:
X -= STEP;
spriteTank.setPosition(X, Y);
if (isUnAvailablePosition()) {
X += STEP;
spriteTank.setPosition(X, Y);
}
break;
case DIRECTION_RIGHT:
X += STEP;
spriteTank.setPosition(X, Y);
if (isUnAvailablePosition()) {
X -= STEP;
spriteTank.setPosition(X, Y);
}
break;
}
}
private void Fire() {
synchronized (this) {
if (iFireNumber < MAX_FIRE_NUMBER) {
iFireNumber++;
int X_Bullet = 0;
int Y_Bullet = 0;
switch (iDirection) {
case DIRECTION_UP:
X_Bullet = X + spriteTank.getWidth() / 2 - 2;
Y_Bullet = Y;
break;
case DIRECTION_DOWN:
X_Bullet = X + spriteTank.getWidth() / 2 - 2;
Y_Bullet = Y + spriteTank.getHeight();
break;
case DIRECTION_RIGHT:
X_Bullet = X + spriteTank.getWidth();
Y_Bullet = Y + spriteTank.getHeight() / 2 - 2;
break;
case DIRECTION_LEFT:
X_Bullet = X;
Y_Bullet = Y + spriteTank.getHeight() / 2 - 2;
break;
}
new GameBullet(layer, this, iDirection, X_Bullet, Y_Bullet);
}
}
}
void releaseFireNumber() {
synchronized (this) {
iFireNumber--;
}
}
private boolean isLayerCollision() {
return spriteTank.collidesWith(layer.getTankLayer(), true);
}
private boolean isGameTankCollision() {
Enumeration em = layer.getVGameTanks().elements();
GameTank target = null;
while (em.hasMoreElements()) {
target = (GameTank) em.nextElement();
if (this == target) {
/**
* 不检查自己。
*/
continue;
} else {
if (getSpriteTank().collidesWith(target.getSpriteTank(), true)) {
return true;
}
}
}
return false;
}
private boolean isPlayerTankCollision() {
Enumeration em = layer.getVPlayerTanks().elements();
GameTank target = null;
while (em.hasMoreElements()) {
target = (GameTank) em.nextElement();
if (getSpriteTank().collidesWith(target.getSpriteTank(), true)) {
return true;
}
}
return false;
}
void paintGameTank(Graphics g) {
spriteTank.paint(g);
}
private boolean isUnAvailablePosition() {
return isLayerCollision() || GameLayer.isOutsideLayer(spriteTank);
}
/**
* 分配Random(多次)产生的随机数来得到所需概率和ACTION值。 NO_ACTION: 1/16 四个DIRECTION:
* 1/64*4=1/16 MOVE: 3/4=6/8 FIRE: 1/8
*/
private int generateAction() {
/**
* 2^2=4
*/
switch (tankRandoms[1].next(2)) {
case 0:
/**
* 2^1=2
*/
switch (tankRandoms[2].next(1)) {
case 0:
/**
* 得到"1/8"。
*/
return ACTION_FIRE;
case 1:
/**
* 2^1=2
*/
switch (tankRandoms[3].next(1)) {
/**
* 得到"1/16"。
*/
case 0:
/**
* 四个DIRECTIOIN各自为1/64。
*
* 2^2=4
*/
switch (tankRandoms[4].next(2)) {
case 0:
return ACTION_DIRECTION_UP;
case 1:
return ACTION_DIRECTION_DOWN;
case 2:
return ACTION_DIRECTION_LEFT;
case 3:
return ACTION_DIRECTION_RIGHT;
}
case 1:
return NO_ACTION;
}
}
case 1:
case 2:
case 3:
/**
* 得到"3/4"。
*/
return ACTION_MOVE;
}
return 0;
}
Sprite getSpriteTank() {
return spriteTank;
}
public void hit() {
registBoomDrawer();
layer.unRegistGameTank(this);
spriteTank.setVisible(false);
timer.cancel();
}
private void registBoomDrawer() {
layer.registMultipleDrawer(this);
}
public void drawBoom(Graphics graphic) {
graphic.drawImage(imageBoom, X, Y, 0);
}
void pauseGameTank() {
timer.cancel();
}
void restartGameTank() {
timer = new Timer();
timer.schedule(new GameTankTask(), 0, TIMER_INTERVAL);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -