📄 mazecanvas.java
字号:
wallTextureImage));
wallTexture
.setWrapping(Texture2D.WRAP_REPEAT, Texture2D.WRAP_CLAMP);
wallTexture.setBlending(Texture2D.FUNC_REPLACE);
wallTexture.setFiltering(Texture2D.FILTER_LINEAR,
Texture2D.FILTER_NEAREST);
wallAppearance.setTexture(0, wallTexture);// 将墙壁纹理添加到墙壁的外观属性中
wallClearAppearance.setTexture(0, wallTexture);// 将墙壁纹理添加到半透明外观属性中
}
Enumeration wallsEnum = maze.createPlanes();// 调用maze类的createPlanes创建所有Plane对象
while (wallsEnum.hasMoreElements()) {// 遍历所有的Plane对象
Mesh wallMesh = ((Plane) wallsEnum.nextElement()).createMesh();// 用Plane对象创建Mesh平面
wallMesh.setAppearance(0, wallAppearance);// 将墙壁设置为基本外观
world.addChild(wallMesh);// 将墙壁添加到游戏场景中
}
}
// decides whether it is allowed to move to a given place
// otherwise it is possible to cross walls and go outside the maze
private boolean canMove(float stepx, float stepz, boolean forward) {
float x = locationx + stepx;
float z = locationz + stepz;
// First check if inside the maze area
float mazeSize = MAZE_SIDE_LENGTH / 2 - 2;
if (x <= -mazeSize || z <= -mazeSize || x > mazeSize || z > mazeSize) {
return false;
}
// collision with walls is easily implemented using picking
// if there is something in front of the camera and the distance is too
// small, the movement is not allowed
RayIntersection ri = new RayIntersection();
// inverse the point of view to detect if it is moving
// bacwards
if (!forward) {
normalCamera.postRotate(180, 0f, 1f, 0f);
}
if (world.pick(-1, 0.5f, 0.5f, normalCamera, ri)) {
Node selected = ri.getIntersected();
if (selected instanceof Mesh) {
// multiply per 9 since that's the size of a step
float distance = ri.getDistance() * 9;
if (distance <= 0.1) {
return false;
}
}
}
if (!forward) {
// revert to the original view
normalCamera.postRotate(-180, 0f, 1f, 0f);
}
return true;
}
private static boolean moved = false;
// the method checks whenever the keys are pressed
private void checkKeys() {
int keyState = getKeyStates();
moved = false;
// 如果按下Fire键,则将拾取到的Mesh对象设为半透明外观
if ((keyState & FIRE_PRESSED) != 0) {
seeThrough();
}
// here we assume only one button is pressed otherwise the "second"
// press is ignored
if ((keyState & LEFT_PRESSED) != 0) {
turnLeft();
} else if ((keyState & RIGHT_PRESSED) != 0) {
turnRight();
} else if ((keyState & UP_PRESSED) != 0) {
moveForward();
} else if ((keyState & DOWN_PRESSED) != 0) {
moveBack();
}
// if moved we make the last transparent wall normal
// and reset the view
if (moved) {
if (!finished && maze.isAtTheEnd(locationx, locationz, 4f)) {
finished = true;
}
// if there was a mesh semi transparent
// return to normal
if (transparentMesh != null) {
transparentMesh.setAppearance(0, wallAppearance);
transparentMesh.setAlphaFactor(1f);
transparentMesh = null;
}
// if we move we reset the top view state
if (topView) {
switchView();
}
setupCamera();
}
}
protected void seeThrough() {
RayIntersection ri = new RayIntersection();// 创建一个拾取光束
if (world.pick(-1, 0.5f, 0.5f, normalCamera, ri)) {// 用该光束对场景拾取Mesh对象
Node selected = ri.getIntersected();// 获取光束所拾取到的内容
if (selected instanceof Mesh) {// 如果拾取到的是Mesh对象(前面已经将开始结束标志设为不可拾取)
transparentMesh = ((Mesh) selected);
transparentMesh.setAppearance(0, wallClearAppearance);// 将该墙壁设置为半透明外观属性
transparentMesh.setAlphaFactor(0.8f);// 透明alpha因子为0.8
}
}
}
protected void moveForward() {
// move forward, but first check if it is allowed
if (canMove(-stepx, -stepz, true)) {
locationx -= stepx;
locationz -= stepz;
}
moved = true;
}
protected void moveBack() {
// move backwards, but first check if it is allowed
if (canMove(stepx, stepz, false)) {
locationx += stepx;
locationz += stepz;
}
moved = true;
}
protected void turnLeft() {
// 当游戏左键被按下
angley += ANGLE_STEP; // 当前角度增加旋转角度
stepx = STEP * (float) Math.sin(Math.toRadians(angley)); // 计算x方向的偏移量
stepz = STEP * (float) Math.cos(Math.toRadians(angley)); // 计算z方向的偏移量
// 设置背景的裁剪区域向右偏移一点
background.setCrop(background.getCropX() + 3, 0, getWidth(),
getHeight());
flagX1 = flagX1 + (int) stepx;
flagY1 = flagY1 + (int) stepz;
flagX2 = flagX2 - (int) stepx;
flagY2 = flagY2 - (int) stepz;
moved = true; // 已经成功移动
System.out.println("stepx=" + stepx);
System.out.println("stepz=" + stepz);
}
protected void turnRight() {
// 当游戏右键被按下
angley -= ANGLE_STEP;
stepx = STEP * (float) Math.sin(Math.toRadians(angley));
stepz = STEP * (float) Math.cos(Math.toRadians(angley));
// 设置背景的裁剪区域向左偏移一点
background.setCrop(background.getCropX() - 3, 0, getWidth(),
getHeight());
flagX1 = flagX1 + (int) stepx;
flagY1 = flagY1 + (int) stepz;
flagX2 = flagX2 - (int) stepx;
flagY2 = flagY2 - (int) stepz;
moved = true; // 已经成功移动
System.out.println("stepx=" + stepx);
System.out.println("stepz=" + stepz);
}
// key pressed used to show the main menu
protected void keyPressed(int keyCode) {
if (keyCode < 0) {
// MyGame.showMenu();
if (MyGame.isShowingPopup()) {
MyGame.getCurrentPopup().dispose();
}
MyGame.exitGame();
}
if (keyCode == KEY_POUND) {
switchView();
}
if (keyCode == KEY_STAR) {
switchWeapon();
}
if (keyCode == KEY_NUM0) {
seeThrough();
}
}
public static int weapon_index = 0;
private void switchWeapon() {
// 换武器
if (weapon_index >= weapons.length)
weapon_index = 0;
mainWeapon = weapons[weapon_index++];
}
private void reloading() {
// 换弹夹
}
// 设置摄像机位置
private void setupCamera() {
normalCamera.setOrientation(angley, 0f, 1f, 0f);
normalCamera.setTranslation(locationx, 10f, locationz);
}
// 绘制指南针
// 初始化指南针的坐标
final int X1 = getWidth() - 22, X2 = getWidth() - 22, Y1 = 39, Y2 = 14;
int flagX1 = X1, flagY1 = Y1, flagX2 = X2, flagY2 = Y2;
private void drawCompass(Graphics g) {
// 绘制指南针
int screenWidth = getWidth();
g.setColor(0x8000ff00);
g.drawRoundRect(screenWidth - 42, 7, 40, 40, 40, 40);
g.setColor(0xff0000);
g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD,
Font.SIZE_MEDIUM));
g.drawString("N", screenWidth - 25, 0, Graphics.TOP | Graphics.LEFT);
g.drawString("W", screenWidth - 25, 40, Graphics.TOP | Graphics.LEFT);
g.drawString("S", screenWidth - 44, 18, Graphics.TOP | Graphics.LEFT);
g.drawString("E", screenWidth - 5, 18, Graphics.TOP | Graphics.LEFT);
g.setColor(0x0000ff);
g.drawLine(flagX1, flagY1, flagX2, flagY2);
g.setColor(0xffff00);
// g.fillTriangle(flagX1, flagY1, flagX1 - 3, flagY1 -3, flagX1 + 3,
// flagY1 -3);
g.fillRoundRect(flagX1 - 2, flagY1, 5, 5, 5, 5);
}
public static Image[] weapons = new Image[2];
private static Image mainWeapon = MyGameMIDlet
.makeImage("/weapons/AK47.png");
public static void loadWeapons() {
weapons[0] = MyGameMIDlet.makeImage("/weapons/AK47.png");
weapons[1] = MyGameMIDlet.makeImage("/weapons/dagger.png");
}
// 在GameCanvas上绘制2D信息
private void draw2D(Graphics g) {
// text color
StringBuffer status = new StringBuffer(finished ? "Done" : "");
if (finished) {
duration = System.currentTimeMillis() - gameStart;
status.append(" Time:").append(duration / 1000);
} else {
status.append(" Time:");
status.append((System.currentTimeMillis() - gameStart) / 1000);
}
// 绘制游戏时间(左上角)
g.setColor(255, 255, 45);
g.drawString(status.toString() + "Mem:" + Runtime.getRuntime().freeMemory() / 1024
, 0, 0, Graphics.TOP | Graphics.LEFT);
// 绘制FPS(左下角)
g.setColor(45, 235, 45);
g.drawString("FPS: " + fps, 0, getHeight(), Graphics.BOTTOM
| Graphics.LEFT);
// 绘制指南针(右上角)
drawCompass(g);
// 绘制自动准心
if (!topView)
drawAutoAimingRule(g);
// 绘制手枪
if (!topView)
g.drawImage(mainWeapon, getWidth(), getHeight(), Graphics.BOTTOM
| Graphics.RIGHT);
}
// 绘制自动准心
private void drawAutoAimingRule(Graphics g) {
int x = screen_width / 2;
int y = screen_height / 2;
g.setColor(0x00ff00);
g.drawLine(x - 10, y, x - 4, y);
g.drawLine(x + 10, y, x + 4, y);
g.drawLine(x, y - 10, x, y - 4);
g.drawLine(x, y + 10, x, y + 4);
}
// 绘制三位场景
private void draw3D(Graphics g) {
boolean bound = false;
try {
// binds the target
g3d.bindTarget(g);
bound = true;
// advance the animation
world.animate((int) (System.currentTimeMillis() - gameStart));
// do the rendering
g3d.render(world);
} finally {
// release the target
if (bound) {
g3d.releaseTarget();
}
}
}
public void run() {
Graphics g = getGraphics();// 获得Graphics对象,注意Graphics3D对象必须绑定它才能绘制
while (playing) {
try {
long startTime = System.currentTimeMillis();// 获取系统的当前时间作为每帧的初始时间
if (isShown()) {// 如果游戏画布处于显示状态
checkKeys();// 按键响应,与玩家进行交互
long drawingTime = System.currentTimeMillis();
draw3D(g);// 绘制3D部分
drawingTime = System.currentTimeMillis() - drawingTime;
fps = 1000 / drawingTime;// 计算每秒帧数
draw2D(g);// 绘制2D部分
flushGraphics();// 用缓冲区的内容刷新当前屏幕
}
long timeTaken = System.currentTimeMillis() - startTime;// 计算实际耗费的时间
if (timeTaken < MILLIS_PER_TICK) {// 如果小于预计的时间戳,线程等待一定时间,保证帧频率稳定
synchronized (this) {
wait(MILLIS_PER_TICK - timeTaken);
}
} else {
Thread.yield();// 否则将线程挂起
}
} catch (Exception e) {
// ignore. Not much to but we want to keep the loop running
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -