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

📄 mazecanvas.java

📁 J2ME 3D 第一人称射击迷宫类手机游戏源码。
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package myGame.main;

import MyGameMIDlet;

import java.util.Enumeration;
import java.util.Random;

import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.m3g.AnimationController;
import javax.microedition.m3g.AnimationTrack;
import javax.microedition.m3g.Appearance;
import javax.microedition.m3g.Background;
import javax.microedition.m3g.Camera;
import javax.microedition.m3g.CompositingMode;
import javax.microedition.m3g.Graphics3D;
import javax.microedition.m3g.Image2D;
import javax.microedition.m3g.KeyframeSequence;
import javax.microedition.m3g.Mesh;
import javax.microedition.m3g.Node;
import javax.microedition.m3g.PolygonMode;
import javax.microedition.m3g.RayIntersection;
import javax.microedition.m3g.Texture2D;
import javax.microedition.m3g.Transform;
import javax.microedition.m3g.World;

// Main class. It setups the 3D scene and does the movements
// and rendering 
public class MazeCanvas extends GameCanvas implements Runnable {
	private final static float WALL_HEIGHT = 10.f;// 迷宫墙壁的高度

	public static float MAZE_SIDE_LENGTH = 250f;// 迷宫的总长

	private final static float STEP = 3.0f;// 前进的每个步长

	private final static float ANGLE_STEP = 8.0f;// 每次旋转的角度

	private final static int MILLIS_PER_TICK = 5;// 每个循环所消耗的最小时间

	private float stepz = -STEP, stepx = 0f;// 事先定义x和z方向上的步长

	private float locationx = 0f, locationz = 0;// 玩家的位置

	private float angley = 0f;// 玩家的旋转角度

	private boolean topView = false;// 是否处于俯瞰模式

	private volatile boolean playing = true;// 是否线程正在运行

	private volatile float fps = 0;// 每秒所能运行的帧数

	private volatile long gameStart = 0;// 在迷宫中已经消耗的时间

	private volatile long duration = 0;// 走通迷宫所耗费的时间

	private boolean finished;// 是否完成游戏

	private Graphics3D g3d;// Graphics3D的全局实例

	private World world;// 3D场景中的World根节点

	private Camera normalCamera, topCamera;// 玩家摄像机和顶部用于俯瞰模式的摄像机

	private Background background = null;// 3D场景的背景

	private Mesh locationSquare = null;// 定位玩家方位的红色小正方形

	private Appearance wallClearAppearance = new Appearance();// 墙壁的透明外观

	private Appearance wallAppearance = new Appearance();// 墙壁的正常外观

	private Mesh transparentMesh = null;// 指向上一个被透视的Mesh对象

	private static Maze maze = null;// new Maze(10, MAZE_SIDE_LENGTH,
									// WALL_HEIGHT);// 创建迷宫

	private Thread mainThread = null;// 游戏的主线程

	public static byte corridorCount = 5;// 迷宫的走廊数

	public static int timeLimit = 120;

	public static int screen_width = 0, screen_height = 0;

	// Construct the Displayable
	public MazeCanvas() {
		super(true);
		// corridorCount = (byte)MyGame.getInt(MyGame.DIFFICULT_SET);
		// timeLimit = MyGame.getInt(MyGame.TIMELIMIT_SET);
		screen_width = getWidth();
		screen_height = getHeight();
		loadWeapons();
	}

	public static void newMaze() {
		if (maze != null)
			maze = null;
		maze = new Maze(corridorCount, MAZE_SIDE_LENGTH, WALL_HEIGHT);// 创建迷宫
	}

	// (Re)Starts the game
	void start() {
		this.setFullScreenMode(true);
		playing = true;
		gameStart = System.currentTimeMillis() - duration;
		mainThread = new Thread(this);
		mainThread.start();
	}

	// stops/pauses the game
	public void stop() {
		duration = System.currentTimeMillis() - gameStart;
		playing = false;
	}

	// switches from top view to normal view and vice versa
	void switchView() {
		topView = !topView;// 将切换标志位取反
		setView();// 根据标志位重新设置游戏视角
		// informs the MIDLet since this can be switched internally
		// MyGame.switchView();
	}

	void setView() {
		// 根据玩家当前的位置,重新设置定位标志的位置
		locationSquare.setTranslation(locationx, 2 * WALL_HEIGHT + 3f,
				locationz);
		locationSquare.setRenderingEnable(topView);// 这个定位标志置只有俯瞰模式摄像机可见
		world.setBackground(topView ? null : background);// 如果是俯瞰模式则背景设置位null
		if (topView) {
			world.setActiveCamera(topCamera);// 将当前摄像机设置位俯瞰模式摄像机
		} else {
			world.setActiveCamera(normalCamera);// 将当前摄像机设置位玩家模式摄像机
		}
	}

	// 初始化虚拟世界
	void init() {
		setFullScreenMode(true);// 设置全屏模式
		duration = 0;
		g3d = Graphics3D.getInstance();// 获得Graphics3D实例
		world = new World();// 创建场景根节点World对象
		normalCamera = new Camera();// 创建常规模式下的摄像机
		topCamera = new Camera();// 创建用于俯瞰模式的摄像机
		world.addChild(normalCamera);// 将常规模式下的摄像机添加到场景中
		world.addChild(topCamera);// 将俯瞰模式下的摄像机添加到场景中
		float w = (float) getWidth();// 获取游戏画布的宽度
		float h = (float) getHeight();// 获取游戏画布的高度
		normalCamera.setPerspective(60.f, w / h, 0.1f, 1000.f);// 设置玩家摄像机的透视投影矩阵
		topCamera.setPerspective(60.f, w / h, 0.1f, 1000.f);// 设置俯瞰摄像机的透视投影矩阵
		Transform topCameraTransform = new Transform();// Transform对象用来定位俯瞰摄像机
		topCameraTransform.postRotate(90, -1f, 0f, 0f);// 旋转摄像机,使它朝下
		topCameraTransform.postTranslate(0f, 0f, MAZE_SIDE_LENGTH);// 平移摄像机到迷宫的顶部
		topCamera.setTransform(topCameraTransform);// 定位摄像机
		background = new Background();// 创建场景的背景
		Image backgroundImage = MyGameMIDlet.makeImage("/background"
				+ String.valueOf(Math.abs(new Random().nextInt())
						% Integer.parseInt(MyGameMIDlet.getInstance()
								.getAppProperty("CountBackground"))) + ".png");// 随机加载场景的背景图片
		if (backgroundImage != null) {
			background.setImage(new Image2D(Image2D.RGB, backgroundImage));// 将背景图片添加到背景中
			background.setImageMode(Background.REPEAT, Background.REPEAT);// 背景图片设置为重复模式
		}
		world.setBackground(background);// 将背景添加到场景中去
		createFloor();// 构建迷宫的地板
		createLocationSquare();// 构建定位玩家方位的标志
		setUpMaze();// 构建迷宫的墙壁
		createStartEndMarks();// 构建开始结束标志
		setView();// 设置游戏视角,可能为玩家模式或者俯瞰模式
		locationx = maze.findStartLocationX();// 设置初始方位的X坐标
		locationz = maze.findStartLocationZ();// 设置初始方位的Z坐标
		angley = -180f;
		setupCamera();
		start();// 开始游戏线程
	}

	// creates the labeld at the start and at the end of the maze
	private void createStartEndMarks() {
		Appearance startMarkAppearance = new Appearance();// 创建开始标志外观属性
		Appearance endMarkAppearance = new Appearance();// 创建结束标志外观属性

		// 外观属性的融合方式为ALPHA,这样设置是为了使开始标志结束标志只显示字样,其余部分为透明
		CompositingMode markCompositeMode = new CompositingMode();
		markCompositeMode.setBlending(CompositingMode.ALPHA);
		startMarkAppearance.setCompositingMode(markCompositeMode);
		endMarkAppearance.setCompositingMode(markCompositeMode);

		Texture2D startMarkTexture = null;
		Image startMarkTextureImage = MyGameMIDlet
				.makeImage("/start_label.png");// 加载纹理图片
		if (startMarkTextureImage != null) {
			startMarkTexture = new Texture2D(new Image2D(Image2D.RGBA,
					startMarkTextureImage));
			startMarkTexture.setWrapping(Texture2D.WRAP_CLAMP,
					Texture2D.WRAP_CLAMP);// 钳位模式
			startMarkTexture.setBlending(Texture2D.FUNC_REPLACE);// 纹理的融合方式
			startMarkTexture.setFiltering(Texture2D.FILTER_NEAREST,
					Texture2D.FILTER_NEAREST);// 缩放方式
			startMarkAppearance.setTexture(0, startMarkTexture);
		}

		Texture2D endMarkTexture = null;
		Image endMarkTextureImage = MyGameMIDlet.makeImage("/end_label.png");// 加载纹理图片
		if (endMarkTextureImage != null) {
			endMarkTexture = new Texture2D(new Image2D(Image2D.RGBA,
					endMarkTextureImage));
			endMarkTexture.setWrapping(Texture2D.WRAP_CLAMP,
					Texture2D.WRAP_CLAMP);// 钳位模式
			endMarkTexture.setBlending(Texture2D.FUNC_REPLACE);// 纹理的融合方式
			endMarkTexture.setFiltering(Texture2D.FILTER_NEAREST,
					Texture2D.FILTER_NEAREST);// 缩放方式
			endMarkAppearance.setTexture(0, endMarkTexture);
		}
		Plane startMarkPlane = maze.createStartMark();// 调用Maze类的方法来创建Plane对象
		Mesh startMarkMesh = startMarkPlane.createMesh();// 用Plane对象创建Mesh对象
		startMarkMesh.setAppearance(0, startMarkAppearance);// 将外观属性添加到Mesh对象中
		startMarkMesh.setPickingEnable(false);// 不允许对开始标志进行拾取
		world.addChild(startMarkMesh);// 将开始标志添加到场景中

		Plane endMarkPlane = maze.createEndMark();// 创建一个具有结束位置特性的Plane对象
		Mesh endMarkMesh = endMarkPlane.createMesh();// 调用Plane类中方法创建一个结束标志的Mesh对象
		endMarkMesh.setAppearance(0, endMarkAppearance);// 将外观属性添加到Mesh对象中
		endMarkMesh.setPickingEnable(false);// 不允许对开始标志进行拾取

		KeyframeSequence keyframes = new KeyframeSequence(4, 3,
				KeyframeSequence.LINEAR);// 创建带有四个关键帧的帧序列,并使用线性插值
		keyframes.setDuration(12000);// 设置动画持续时间
		keyframes.setRepeatMode(KeyframeSequence.LOOP);// 动画循环动作
		float[] trans = new float[4];
		endMarkMesh.getOrientation(trans);// 用getOrientation方法获得结束标志的位置
		// 创建动画的关键帧,保持x、z轴坐标不变,改变y轴坐标,使它上下运动
		keyframes.setKeyframe(0, 0,
				new float[] { trans[0], trans[1], trans[2] });
		keyframes.setKeyframe(1, 4000, new float[] { trans[0],
				trans[1] - WALL_HEIGHT / 4, trans[2] });
		keyframes.setKeyframe(2, 8000, new float[] { trans[0],
				trans[1] + WALL_HEIGHT / 4, trans[2] });
		keyframes.setKeyframe(3, 12000, new float[] { trans[0], trans[1],
				trans[2] });
		AnimationTrack animationTrack = new AnimationTrack(keyframes,
				AnimationTrack.TRANSLATION);

		AnimationController anim = new AnimationController();// 创建一个游戏控制器对象anim
		animationTrack.setController(anim);// 将anim绑定到动画轨迹中
		endMarkMesh.addAnimationTrack(animationTrack);// 将动画轨迹添加到结束标志中去
		world.addChild(endMarkMesh);// 将结束标志添加到场景中去
	}

	// creates the floor
	private void createFloor() {
		float floorSide = MAZE_SIDE_LENGTH / 2;
		Transform floorTransform = new Transform();
		floorTransform.postRotate(90.0f, -1.0f, 0.0f, 0.0f);// 从xy平面旋转到xz平面上
		floorTransform.postScale(floorSide, floorSide, 1.0f);// 缩放比例
		Appearance floorAppearance = new Appearance();
		PolygonMode floorPolygonMode = new PolygonMode();
		floorPolygonMode.setPerspectiveCorrectionEnable(true);// 启用透视修正
		floorAppearance.setPolygonMode(floorPolygonMode);
		Texture2D floorTexture = null;
		int rand = Math.abs(new Random().nextInt()
				% Integer.parseInt(MyGameMIDlet.getInstance().getAppProperty(
						"CountFloor")));
		Image floorTextureImage = MyGameMIDlet.makeImage("/floor"
				+ String.valueOf(rand) + ".png");// 随机加载纹理图片
		if (floorTextureImage != null) {
			floorTexture = new Texture2D(new Image2D(Image2D.RGB,
					floorTextureImage));// 创建纹理
			floorTexture.setWrapping(Texture2D.WRAP_REPEAT,
					Texture2D.WRAP_REPEAT);// 重复模式
			floorTexture.setBlending(Texture2D.FUNC_REPLACE);// 纹理融合模式
			floorTexture.setFiltering(Texture2D.FILTER_LINEAR,
					Texture2D.FILTER_NEAREST);// 纹理滤波方式
			floorAppearance.setTexture(0, floorTexture);// 设置纹理
		}
		Plane floor = new Plane(floorTransform, 10);// 创建Plane对象,并指定纹理重复10次
		Mesh floorMesh = floor.createMesh();// 用Plane对象创建地板的地板Mesh对象
		floorMesh.setAppearance(0, floorAppearance);// 将外观属性添加到Mesh对象中
		floorMesh.setPickingEnable(false);// 不允许对地板拾取
		world.addChild(floorMesh);// 将地板添加到场景中
	}

	public static float multiple = 8;

	// create the player location square
	private void createLocationSquare() {
		Transform locationSquareTransform = new Transform();// 创建一个Transform对象,用来翻转
		locationSquareTransform.postRotate(90.0f, -1.0f, 0.0f, 0.0f);// 从xy平面旋转到xz平面
		locationSquareTransform.postScale(multiple, multiple, 1.0f);// 放大8倍
		// 定位标志的外观属性特别简单,仅仅使用到纹理属性
		Appearance locationSquareAppearance = new Appearance();// 创建一个外观属性对象
		Texture2D locationSquareTexture = null;
		Image locationSquareImage = MyGameMIDlet.makeImage("/location.png");// 加载纹理图片
		if (locationSquareImage != null) {
			// 用纹理图片创建Image2D对象,并用Image2D对象创建纹理对象
			locationSquareTexture = new Texture2D(new Image2D(Image2D.RGBA,
					locationSquareImage)); // 纹理对象采用钳位映射方式
			locationSquareTexture.setWrapping(Texture2D.WRAP_CLAMP,
					Texture2D.WRAP_CLAMP);
			locationSquareTexture.setBlending(Texture2D.FUNC_REPLACE);// 替换
			locationSquareTexture.setFiltering(Texture2D.FILTER_NEAREST,
					Texture2D.FILTER_NEAREST);// 插值
			locationSquareAppearance.setTexture(0, locationSquareTexture);// 将纹理属性添加到外观属性中
		}
		Plane locationPlane = new Plane(locationSquareTransform, 1);// 根据翻转矩阵创建标志平面,纹理重复为1
		locationSquare = locationPlane.createMesh();// 用Plane对象创建Mesh对象
		locationSquare.setAppearance(0, locationSquareAppearance);// 将外观属性添加到定位标志平面中
		locationSquare.setRenderingEnable(false);// 初始情况下不可显示
		locationSquare.setPickingEnable(false);// 定位标志不可拾取
		world.addChild(locationSquare);// 将定位标志添加到游戏场景中去
	}

	private void setUpMaze() {
		PolygonMode wallPolygonMode = new PolygonMode();
		wallPolygonMode.setPerspectiveCorrectionEnable(true);// 启用透明修正
		wallClearAppearance.setPolygonMode(wallPolygonMode);// 墙壁半透明的外观属性
		CompositingMode wallClearCompositeMode = new CompositingMode();// 用于处理半透明
		wallClearCompositeMode.setBlending(CompositingMode.ALPHA_ADD);// 颜色融合模式为ALPHA_ADD
		wallClearAppearance.setCompositingMode(wallClearCompositeMode);// 透明墙壁的外观
		wallAppearance.setPolygonMode(wallPolygonMode);// 普通墙壁的外观
		int rand = Math.abs(new Random().nextInt()
				% Integer.parseInt(MyGameMIDlet.getInstance().getAppProperty(
						"CountWall")));
		Image wallTextureImage = MyGameMIDlet.makeImage("/wall"
				+ String.valueOf(rand) + ".png");// 随机加载纹理图片
		System.out.println(rand);
		if (wallTextureImage != null) {
			Texture2D wallTexture = null;
			wallTexture = new Texture2D(new Image2D(Image2D.RGB,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -