/* * Author: Huang ye(www.hyweb.net) * 代码开源, 引用请注明出处 * * 创建日期 2005-2-24 */ package net.hyweb; import javax.microedition.lcdui.*; import javax.microedition.lcdui.game.GameCanvas; import javax.microedition.lcdui.game.*; import javax.microedition.lcdui.game.LayerManager; import java.util.*; /** * @author Huang ye */ public class SubCanvas extends GameCanvas implements Runnable, CommandListener { /** * * @uml.property name="subMIDlet" * @uml.associationEnd multiplicity="(0 1)" */ private Controller controller; private Graphics graphics; private Thread thread; private boolean threadAlive = false; private Command startCommand; private Command exitCommand; private Command pauseCommand; //图层数据 private LayerManager layerManager; private TiledLayer layerSeaback; private Sprite spriteMap; public final int GAME_INIT = 0; //游戏初始状态 public final int GAME_RUN = 1; //游戏运行状态 public final int GAME_OVER = 4; //游戏结束状态 public final int GAME_PAUSE = 5; public final int GAME_SUSPEND = 9; //暂停状态 public boolean COMMAND_ADD_FLAG = false; //是否已经添加Command标识 public static final int TROOP_PLAYER = 0; //敌我标识 public static final int TROOP_ENEMY = 1; public static int PLAYER_LEVEL = 1; //当前玩家水平 public static int ENEMY_MAX = PLAYER_LEVEL * 10; //最大敌人数量 public static int ENEMY_CURRENT = 0; //当前敌人数量 public static int ENEMY_CURRENT_LIMIT = 0; //当前敌人数量限制 protected int TRIGGER_COUNT = 0; //拖延标识,避免敌人新潜艇同一时刻全部产生 protected int TICK_COUNT = 0; public static int mainWidth; //屏幕宽度 public static int mainHeight; //屏幕高度 public int gameState; //游戏状态 public final static int TILE_WIDTH = 10; //背景 单元宽度 10px public final static int TILE_HEIGHT = 10; //背景 单元高度 10px /** 动画变化频率(200ms) * <code>MILLIS_PER_TICK</code> 的注释 */ public final static int MILLIS_PER_TICK = 200; private final static int WIDTH_IN_TILES = 45; //游戏域宽度(以单元宽度计算) 16 .. N private final static int HEIGHT_IN_TILES = 24; //游戏域高度(以单元高度计算) private final static int NUM_DENSITY_LAYERS = 4; //海面密度(背景图层) private int[] rotations = { Sprite.TRANS_NONE, Sprite.TRANS_MIRROR, Sprite.TRANS_MIRROR_ROT90, Sprite.TRANS_MIRROR_ROT180, Sprite.TRANS_MIRROR_ROT270, Sprite.TRANS_ROT90, Sprite.TRANS_ROT180, Sprite.TRANS_ROT270 }; /** 整个游戏背景宽度(以象素计算 : 宽度单元数 * 宽度单元象素) * <code>WORLD_WIDTH</code> 的注释 */ public final static int WORLD_WIDTH = WIDTH_IN_TILES * TILE_WIDTH; /** 整个游戏背景高度(以象素计算 : 高度单元数 * 高度单元象素) * <code>WORLD_HEIGHTH</code> 的注释 */ public final static int WORLD_HEIGHT = HEIGHT_IN_TILES * TILE_HEIGHT; private final static int NUM_DENSITY_LAYER_TILES = 4; //每一个密度层的TILE单元数 private final static int FRACT_DENSITY_LAYER_ANIMATE = 20; private int SEABACK_DENSITY; //游戏初始海水密度为0 //private final Vector oceanLayersVector = new Vector(); private Vector fishCollectionVector = new Vector(); public Vector enemyCollectionVector = new Vector(); public Vector tinfishCollectionVector = new Vector(); /** * * @uml.property name="mySub" * @uml.associationEnd multiplicity="(0 1)" */ private Sub mySub = null; private Runtime rt = null; //初始化为不使用窗口区域视野 private boolean userViewWindow = false; //创建不稳定的动画线程 private volatile Thread animationThread = null; //LayerManager的偏移坐标 private int xViewWindow; private int yViewWindow; private int wViewWindow; private int hViewWindow; public SubCanvas(Controller controller){ //不屏蔽键盘事件(潜艇运动采用主动轮询,而开火则采用捕获方式) super(false); this.controller = controller; this.graphics = getGraphics(); this.layerManager = new LayerManager(); //决定图层显示方式 init(); //画布构造即建立玩家潜艇 //初始位置为屏幕的(1/3, 1/3)位置 mySub = new Sub(this, SubMIDlet.createImage("/res/sub.png"), mainWidth / 3, mainHeight / 3, layerManager); //监测运行时,以便及时运行垃圾回收 rt = Runtime.getRuntime(); startCommand = new Command("Start", Command.OK, 1); pauseCommand = new Command("Pause", Command.OK, 1); exitCommand = new Command("Exit", Command.EXIT, 2); //初始化其它类及图层 //初始化游戏状态 this.gameState = this.GAME_INIT; //游戏处于demo画面状态 //启动应用程序 threadAlive = true; thread = new Thread(this); thread.start(); } /** * 初始化地图数据 和 地图窗口显示方式 */ private void init(){ //清理数据 this.clearData(); mainWidth = getWidth(); mainHeight = getHeight(); //判断是否使用预览模式窗口 //根据显示设备,设置合适的最大区和显示视野 this.xViewWindow = 0; if(WORLD_WIDTH > mainWidth){ //现有设备不能容纳所有游戏区域 userViewWindow = true; this.wViewWindow = mainWidth; }else{ //现有设备可以容纳所有游戏区域 this.wViewWindow = WORLD_WIDTH; } this.yViewWindow = 0; if(WORLD_HEIGHT > mainHeight){ userViewWindow = true; this.hViewWindow = mainHeight; }else{ this.hViewWindow = WORLD_HEIGHT; } //设定图层显示方式 if(userViewWindow){ this.layerManager.setViewWindow(xViewWindow, yViewWindow, wViewWindow, hViewWindow); } } protected void clearData(){ PLAYER_LEVEL = 1; ENEMY_MAX = PLAYER_LEVEL * 10; ENEMY_CURRENT = 0; TRIGGER_COUNT = 0; SEABACK_DENSITY = 0; ENEMY_CURRENT_LIMIT = PLAYER_LEVEL * 2; } /** * 程序作为线程, 每50ms运行刷新一次 */ public void run() { //利用条件驱动线程 while(threadAlive){ try { Thread.sleep(25); } catch (InterruptedException e) { e.printStackTrace(); } //分离对玩家潜艇和普通物体的响应速度(一倍) if(gameState == GAME_RUN){ mySub.movePosition(getKeyStates()); } if((TICK_COUNT % 2) == 0){ // 重画事件 this.paintCanvas(graphics); this.tick(); } TICK_COUNT ++; } } protected synchronized void keyPressed(int keyCode){ int action = getGameAction(keyCode); if(action == Canvas.FIRE && gameState == GAME_RUN){ //玩家潜艇开火 if(mySub != null){ mySub.fire(); } } } /** * 秒触发器 */ public synchronized void tick(){ //主动查询状态 int keyState = getKeyStates(); if(gameState != GAME_OVER){ //执行鱼类图形运动 this.tickFishes(); //执行鱼雷触发 this.tickTinfish(); if(gameState == GAME_RUN){ //替代Canvas中的KeyPressed()捕获事件 //mySub.movePosition(keyState); //创建并执行敌人潜艇行为 this.tickSub(); this.tickEnemySub(); if(ENEMY_CURRENT ==0 && ENEMY_MAX == 0){ gameState = GAME_SUSPEND; } } } } /** * 鱼类图形运动 */ private void tickFishes() { for(int i = 0; i < fishCollectionVector.size(); i++){ FishCollection collection = (FishCollection)fishCollectionVector.elementAt(i); collection.tick(); } } /** * 执行鱼雷触发 */ protected void tickTinfish() { //鱼雷 图形运动 //如果某个鱼雷元素已经结束生命周期, 则置null, 并从数组中删除 for(int j = 0; j < tinfishCollectionVector.size(); j++){ Tinfish tinfish = (Tinfish)tinfishCollectionVector.elementAt(j); //当生命周期结束 if(!tinfish.isLifeState()){ tinfishCollectionVector.removeElementAt(j); this.layerManager.remove(tinfish); tinfish = null; }else{ tinfish.tick(); } } } /** * 玩家潜艇运动及生命状态 */ private void tickSub() { if(!mySub.isLifeState()){ gameState = GAME_OVER; } } /** * 创建并执行敌人潜艇的运行操作 */ protected void tickEnemySub(){ //当敌人剩余最大数量大于0,并且敌人当前数量小于并行敌人上限时 //可以添加新的敌人潜艇 if(ENEMY_MAX >= 0 && ENEMY_CURRENT <= ENEMY_CURRENT_LIMIT && ENEMY_CURRENT < 10){ int iLeft = ENEMY_MAX - ENEMY_CURRENT; //当剩余敌人量(最大量 - 当前量)大于0的时候 if(iLeft > 0){ int n = SubMIDlet.createRandom(iLeft) + 1; Image image = SubMIDlet.createImage("/res/enemysub_f.png"); int xPosition = 0; int yPosition = (SubMIDlet.createRandom(5) * WORLD_HEIGHT) / 5; for(int i = 0; i < n; i++){ //拖延标识,避免敌人新潜艇同一时刻全部产生 if(TRIGGER_COUNT >= 20){ yPosition = (WORLD_HEIGHT * (i % 5)) / 5; if(i % 2 == 0){ xPosition = 0; }else{ xPosition = WORLD_WIDTH - image.getWidth(); } //创建一艘敌人潜艇, 同时更新监听数组 EnemySub enemySub = new EnemySub(this, image, xPosition, yPosition, PLAYER_LEVEL); ENEMY_CURRENT++; layerManager.insert(enemySub, 0); this.enemyCollectionVector.addElement(enemySub); TRIGGER_COUNT = 0; }else{ TRIGGER_COUNT++; } } image = null; } } //对所有已经存在的敌人潜艇进行tick触发 Image imageDestroyed = null; for(int j = 0; j < enemyCollectionVector.size(); j++){ EnemySub enemySub = (EnemySub)enemyCollectionVector.elementAt(j); int iCount = 0; //当生命周期结束 if(!enemySub.isLifeState()){ imageDestroyed = SubMIDlet.createImage("/res/enemysub_die.png"); enemySub.setImage(imageDestroyed, imageDestroyed.getWidth(), imageDestroyed.getHeight()); if(enemySub.getVx() >= 0){ enemySub.setTransform(Sprite.TRANS_NONE); }else{ enemySub.setTransform(Sprite.TRANS_MIRROR); } enemyCollectionVector.removeElementAt(j); //消灭一艘敌人潜艇, 同时更新监听数组 SpriteChanged spriteChanged = new SpriteChanged(enemySub, layerManager); spriteChanged.start(); spriteChanged = null; enemySub = null; ENEMY_CURRENT--; ENEMY_MAX--; }else{ enemySub.tick(); } } imageDestroyed = null; }

评论