/*
* 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;
}
评论