📄 playerbullet.java
字号:
package com.ipanel.games.tank;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
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;
import javax.microedition.lcdui.game.TiledLayer;
public class PlayerBullet implements bulletTarget {
private Image imageBullet = null;
private Sprite spriteBullet = null;
final int DIRECTION_UP = 1;
final int DIRECTION_DOWN = 2;
final int DIRECTION_LEFT = 3;
final int DIRECTION_RIGHT = 4;
private GameLayer layer = null;
private PlayerTank tank = null;
private int iDirection;
private int X;
private int Y;
private final int STEP;
private Timer timer = new Timer();
private final int TIMER_INTERVAL = 1;
/**
* 在Bullet的生命周期中,此boolean仅翻转一次,所以是可以接受的。
*/
private boolean isOverStatus = false;
public PlayerBullet(GameLayer layer, PlayerTank tank, int iDirection,
int X, int Y) {
super();
this.layer = layer;
try {
imageBullet = Image.createImage("/res/bullets1.png");
} catch (IOException e) {
layer
.paintException("Exception when createImage in PlayerBullet()!");
}
spriteBullet = new Sprite(imageBullet);
this.tank = tank;
this.iDirection = iDirection;
this.X = X;
this.Y = Y;
STEP = GameLayer.SPRITE_COLLISION_MIN_SIZE;
layer.registPlayerBullets(this);
Fire();
}
private void Fire() {
timer.schedule(new BulletTask(), 0, TIMER_INTERVAL);
}
class BulletTask extends TimerTask {
public void run() {
try {
Thread.currentThread().sleep(50);
} catch (InterruptedException e) {
layer.paintException("Exception from Thread.sleep()!");
}
/**
* 所有Timer调度的线程,应该被synchronized(GameLayer)。
*/
synchronized (layer) {
spriteBullet.setPosition(X, Y);
/**
* 出界否。
*/
if (GameLayer.isOutsideLayer(spriteBullet)) {
bulletOver();
}/**
* 与Layer碰撞否。
*/
else if (isLayerCollision()) {
layerCollision();
}/**
* 与target碰撞否。
*/
else {
Vector vTargets = getTargetsCollidesWith();
if (vTargets.size() > 0) {
Enumeration em = vTargets.elements();
while (em.hasMoreElements()) {
((bulletTarget) em.nextElement()).hit();
}
/**
* 多次bulletOver()不会有异常。
*/
bulletOver();
}
}
switch (iDirection) {
case DIRECTION_DOWN:
Y += STEP;
break;
case DIRECTION_LEFT:
X -= STEP;
break;
case DIRECTION_RIGHT:
X += STEP;
break;
case DIRECTION_UP:
Y -= STEP;
break;
}
}
}
}
private boolean isLayerCollision() {
return spriteBullet.collidesWith(layer.getBulletLayer(), true);
}
private void layerCollision() {
TiledLayer targetLayer = layer.getBulletLayer();
if (isLayerCollision()) {
/**
* 获得Layer中"被碰撞"的Cells的X、Y坐标值。
*/
Hashtable htX = GameLayer.dimensionCollision(targetLayer
.getCellWidth(), spriteBullet.getX(), imageBullet
.getWidth());
Hashtable htY = GameLayer.dimensionCollision(targetLayer
.getCellHeight(), spriteBullet.getY(), imageBullet
.getHeight());
handleLayerCollision(targetLayer, htX, htY);
}
}
/**
* 处理targetLayer的更新: 在指定的X、Y坐标处的Cells,如果是Brick则炸毁,否则。。。
*/
private void handleLayerCollision(TiledLayer targetLayer, Hashtable htX,
Hashtable htY) {
int X, Y;
int iContent;
/**
* 遍历两个Hashtable,根据由其指定的Layer的坐标对应的Content,进行处理。
*
* 仅从算法来看,存在不合理的地方,但是结合Layer的Grid排列,以及Bullet的单向运动性, 这样的算法不会产生错误,虽然会较低效率;
* 这样的算法,优点是简单、直观。
*/
Enumeration emX = htX.elements();
Enumeration emY = null;
while (emX.hasMoreElements()) {
X = ((Integer) emX.nextElement()).intValue();
emY = htY.elements();
while (emY.hasMoreElements()) {
Y = ((Integer) emY.nextElement()).intValue();
iContent = targetLayer.getCell(X, Y);
/**
* 对于Bullet以及BulletLayer而言,只有Brick和Iron是可见且需要处理的。
*/
if (iContent == GameLayer.CELL_BRICK) {
bulletOver();
layer.setLayersCell(X, Y, GameLayer.CELL_EMPTY);
} else if (iContent == GameLayer.CELL_IRON) {
bulletOver();
}
}
}
}
/**
* @return Vector 存放有当前发生collision的所有target(Sprite)的引用。
* 遍历所有target,如果发生collision,就存放引用至Vector。
* 所有相关的处理线程都应该处于synchronized(GameLayer)之中, 所以以下的遍历,不会引起时间上的错误。
*/
private Vector getTargetsCollidesWith() {
Vector vTargets = new Vector();
Enumeration em = null;
GameBullet targetGameBullet = null;
GameTank targetGameTank = null;
em = layer.getVGameBullets().elements();
while (em.hasMoreElements()) {
targetGameBullet = (GameBullet) em.nextElement();
if (spriteBullet.collidesWith(targetGameBullet.getSpriteBullet(),
true)) {
vTargets.addElement(targetGameBullet);
}
}
em = layer.getVGameTanks().elements();
while (em.hasMoreElements()) {
targetGameTank = (GameTank) em.nextElement();
if (spriteBullet.collidesWith(targetGameTank.getSpriteTank(), true)) {
vTargets.addElement(targetGameTank);
}
}
return vTargets;
}
private void bulletOver() {
synchronized (this) {
if (!isOverStatus) {
isOverStatus = true;
spriteBullet.setVisible(false);
layer.unRegistPlayerBullets(this);
tank.releaseFireNumber();
timer.cancel();
}
}
}
void paintPlayerBullet(Graphics g) {
spriteBullet.paint(g);
}
Sprite getSpriteBullet() {
return spriteBullet;
}
public void hit() {
bulletOver();
}
void pausePlayerBullet() {
timer.cancel();
}
void restartPlayerBullet() {
timer = new Timer();
timer.schedule(new BulletTask(), 0, TIMER_INTERVAL);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -