⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 playerbullet.java

📁 一个非常不错的J2ME坦克大战的游戏,可以在机顶盒上实际运行.
💻 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 + -