📄 gamecanvas.java
字号:
import javax.microedition.lcdui.Canvas; //引入“画布”Canvas类
import javax.microedition.lcdui.Graphics;//引入“画笔”Graphics类
import javax.microedition.lcdui.Image;
import java.io.*;
import javax.microedition.lcdui.Font;
public class GameCanvas
extends Canvas
implements Runnable {
//定义GameCanvas类继承Cancas并且实现Runnable接口
public GameCanvas()
{
setFullScreenMode(true); //设置全屏
new Thread(this).start(); //启动线程
}
public void run()
{ //线程开始
long begin; //用来临时记录时间
while (!isRunning)
{
begin = System.currentTimeMillis(); //获得系统时间
gameLogic(); //整个游戏运行的逻辑处理部分
repaint(); //重新刷新屏幕
serviceRepaints(); //强制线程重新刷新屏幕
while (System.currentTimeMillis() - begin < 100);
//为保证线程每次刷新平面均衡、以达到屏幕稳定的更新速度
//设定屏幕更新速度为0.100秒每次(10FPS即每秒刷新10次)
/*线程的每次循环过程都需要处理两个部分,一是逻辑处理部分gameLoop(),二是屏幕绘制部分repaint()及serviceRepaints();那么每次的屏幕更新需要保持游戏的稳定。就需要每次刷新速度恒定,才可以保证逻辑处理过程的准确(例如线程每循环一次,游戏中的主角向前行动一步,如果时快时慢就不能保证主角行走动作的流畅,这点在ACT游戏中体现的尤其重要。)所以我们需要对线程的每次循环做出一个恒定的判定,所采取的操作就是,循环开始就获得一次系统时间,在执行完逻辑处理部分和屏幕绘制部分的时候再一次获得系统时间。当两次时间差大于0.0100秒(预先设定的屏幕刷新速度)才可以进行下一次循环。*/
}
GameMIDlet.midlet.notifyDestroyed();
}
Menu menu = null;
protected static boolean isRunning; //线程标记
protected static final int SCREEN_WIDTH = 176; //屏幕宽度(当前实例以NOKIA S60系列为主)
protected static final int SCREEN_HEIGHT = 208; //屏幕高度(同上)
//游戏状态集
protected static byte iGameState; //游戏状态标记量(标识程序运行在某个状态(下面定义的基本状态集上的某个状态))
//以下是游戏基本状态集
protected static final byte GS_LOGO = 0; //LOGO显示状态
protected static final byte GS_MENU = 1; //主菜单状态
protected static final byte GS_GAME = 2; //游戏中状态(正式进入游戏中)
protected static final byte GS_GAME_END = 3; //游戏结束
protected static final byte GS_CONTROL = 4; //游戏控制
protected static final byte GS_ABOUT = 5; //游戏关于信息
//按键状态集
protected static int keyCode; //记录按键值
protected static int keyState; //当前按键状态
public static final int KEY_SOFTKEY1 = -6;
public static final int KEY_SOFTKEY2 = -7;
private static int iCount;//计数器
private static Image logo;//游戏闪屏的image对象
private static Image other;
Engine engine;//游戏的核心(驱动整个游戏)
protected final void gameLogic()
{ //主逻辑处理部分
switch (iGameState)
{ //根据不同的状态处理不同状态下的逻辑
case GS_LOGO: //闪屏
if (logo == null)
{
try
{
logo = Image.createImage("/menu.png");
other = Image.createImage("/other.png");
}
catch (IOException ex)
{
}
}
iCount++; //计数器自加
if (iCount > 176/5+1) //当计数器大于10
{
other = null;
setGameState(GS_MENU); // 则切换到主菜单状态
}
break;
case GS_MENU: //菜单状态
if(keyCode != 0){
getKeyState();
switch (menu.keyPress(keyState))
{
case 0:
setGameState(GS_GAME);
break;
case 1:
setGameState(GS_ABOUT);
break;
case 2:
setGameState(GS_CONTROL);
break;
case 3:
isRunning = true;
break;
}
keyCode = 0;
}
break;
case GS_GAME: //游戏中状态
engine.runGame();//执行游戏中的逻辑
break;
case GS_GAME_END:
engine.runGame();//执行游戏中的逻辑
break;
case GS_ABOUT:
case GS_CONTROL:
if (keyCode != 0)
{
if (keyCode == KEY_SOFTKEY2)
{
setGameState(GS_MENU);
}
}
break;
}
}
protected void paint(Graphics g)
{ //屏幕显示部分
switch (iGameState)
{ //根据不同的状态显示不同的内容
case GS_LOGO: //闪屏
if (logo != null){ //logo加载成功
g.drawImage(logo, SCREEN_WIDTH >> 1, SCREEN_HEIGHT >> 1, Graphics.HCENTER | Graphics.VCENTER); //将logo图片显示在屏幕中间
int w = iCount*5;
if(w > Menu.data[0][3])
w = Menu.data[0][3];
g.setClip(Menu.data[0][1],Menu.data[0][2],w,Menu.data[0][4]);
g.drawImage(other, 0,0,0); //将logo图片显示在屏幕中间
}
break;
case GS_MENU: //菜单状态
menu.paint(g);
break;
case GS_GAME: //游戏中状态
engine.drawGame(g); //显示游戏中的内容
break;
case GS_GAME_END:
engine.drawGame(g); //显示游戏中的内容
closeScreen(g);
break;
case GS_ABOUT:
drawAbout(g);
break;
case GS_CONTROL:
drawControl(g);
break;
}
}
protected final void getKeyState()
{ //获得当前的按键状态
keyState = getGameAction(keyCode);
}
protected void keyPressed(int keys)
{ //按键按下的处理部分
keyCode = keys;
if(engine != null){
if(engine.role != null)
engine.role.controlRole(getGameAction(keyCode));
}
}
protected void keyReleased(int keys)
{ //按键松开的处理部分
keyCode = 0;
if(engine != null){
if(engine.role != null)
engine.role.controlReleased();
}
}
protected final void setGameState(byte nowState)
{ //利用此方法来切换状态
switch (nowState) {
case GS_LOGO: //GS_LOGO状态下初始化的数据
iCount = 0;
break;
case GS_MENU:
menu = new Menu();
engine = new Engine();
engine.init();
break;
case GS_GAME://进入游戏前初始化engine
engine = new Engine();
engine.init();
break;
case GS_GAME_END:
closeIndex = 0;
break;
}
iGameState = nowState; //设置当前的游戏状态为参数nowState值
}
int closeIndex;
void closeScreen(Graphics g){
closeIndex ++;
g.setColor(0);
g.fillRect(0,0,SCREEN_WIDTH,closeIndex*5);
g.fillRect(0,SCREEN_HEIGHT-closeIndex*5,SCREEN_WIDTH,closeIndex*5);
if(closeIndex * 5 * 2 > SCREEN_HEIGHT){
g.setColor(0x00ff00);
if(engine.isPass)
g.drawString("恭喜过关...",SCREEN_WIDTH>>1,SCREEN_HEIGHT>>1,Graphics.HCENTER|Graphics.TOP);
else
g.drawString("游戏结束...",SCREEN_WIDTH>>1,SCREEN_HEIGHT>>1,Graphics.HCENTER|Graphics.TOP);
}
if(closeIndex * 5 * 2 > SCREEN_HEIGHT*2){
engine = null;
System.gc();
setGameState(GS_MENU);
}
}
void drawAbout(Graphics g)
{
String[] about =
{
"游戏名称: ",
"EidolonKingdom",
"版本:v1.0.0",
"××工作室"
};
g.setFont(Font.getFont(0,0,8));
g.drawImage(logo,0,0,0);//背景图片
g.setColor(0x0);
final int distance = 20;
for (int i = 0; i < about.length; i++)
{
g.drawString(about[i], SCREEN_WIDTH >> 1, distance*2 + i * distance, Graphics.HCENTER | Graphics.TOP);
}
g.drawString("返回",SCREEN_WIDTH,SCREEN_HEIGHT,Graphics.RIGHT|Graphics.BOTTOM);
}
void drawControl(Graphics g)
{
String[] about =
{
"左右键控制主角移动",
"上键控制主角上跳 ",
"中间键攻击。 ",
};
g.setFont(Font.getFont(0,0,8));
g.drawImage(logo,0,0,0);//背景图片
g.setColor(0x0);
final int distance = 20;
for (int i = 0; i < about.length; i++)
{
g.drawString(about[i], SCREEN_WIDTH >> 1, distance*2 + i * distance, Graphics.HCENTER | Graphics.TOP);
}
g.drawString("返回",SCREEN_WIDTH,SCREEN_HEIGHT,Graphics.RIGHT|Graphics.BOTTOM);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -