MIDlet类代码如下
public class DesertMIDlet extends MIDlet implements CommandListener{
private Command exitCommand = new Command("Exit" , Command.EXIT, 1);
protected void destroyApp(boolean arg0) throws MIDletStateChangeException { // TODO Auto-generated method stub
}
protected void pauseApp() { // TODO Auto-generated method stub
}
//初始化
protected void startApp() throws MIDletStateChangeException { DesertCanvas dCanvas = new DesertCanvas(); dCanvas.addCommand(exitCommand); dCanvas.setCommandListener(this); Display.getDisplay(this).setCurrent(dCanvas);
}
//处理退出 public void commandAction(Command command, Displayable displayable) { if(command == exitCommand) { try { destroyApp(true); } catch (MIDletStateChangeException e) { // TODO Auto-generated catch block e.printStackTrace(); } notifyDestroyed(); } }
}
等高地图创建的场景如果铺上纹理显得更加真是,在HeightMap类添加createTexure方法来创建纹理
HeightMap类代码如下:
public class HeightMap { private short[] heightMap; private int[] data; // 加载的地图大小 private int mapWidth; private int mapHeight; // 四边形 private Mesh[][] map; private static final String TerrainImgFn ="/Terrain0.png" ; private float resolution = 0.25f; private int imgw, imgh; private static VertexArray POSITION_ARRAY; private static VertexArray COLOR_ARRAY ; private static VertexArray TEXCOORD_ARRAY; private static VertexBuffer vertexBuffer; private static IndexBuffer indexBuffer; private static Appearance appearance; private static PolygonMode polygonmode; private static Texture2D texture; // 创建转换对象 private Transform localTransform = new Transform(); public HeightMap() throws IOException { if(resolution <= 0.0001f || resolution > 1.0f) throw new IllegalArgumentException("Resolution too small or too large"); // 加载图片 loadMapImage(); createTexture(); // 创建四边形 createQuads();
} public Mesh[][]getQuads(){ return map; } public int getMapWidth(){ return mapWidth; }
public int getMapHeight(){ return mapHeight; } //创建纹理的方法 private static void createTexture(){ Image2D waterIm = null; try { waterIm = (Image2D)Loader.load("/SAND1.PNG")[0]; } catch (Exception e) { System.out.println("Cannot make image " ); } texture = new Texture2D(waterIm); texture.setFiltering(Texture2D.FILTER_NEAREST, Texture2D.FILTER_NEAREST); texture.setWrapping(Texture2D.WRAP_CLAMP, Texture2D.WRAP_CLAMP); } //创建四边形的方法 private void createQuads() { map = new Mesh[mapWidth][mapHeight]; short[] heights = new short[4]; for(int x = 0; x < (mapWidth - 1); x++) { for(int y = 0; y < (mapHeight - 1); y++) { // 设置顶点 heights[0] = heightMap[x + y * mapWidth]; heights[1] = heightMap[x + y * mapWidth + 1]; heights[3] = heightMap[x + (y + 1) * mapWidth]; heights[2] = heightMap[x + (y + 1) * mapWidth + 1]; // 创建网格 map[x][y] = createQuad(heights); } } }
private void loadMapImage() throws IOException { // 加载地图资源 Image img = Image.createImage(TerrainImgFn); //设定data大小 data = new int[img.getWidth() * img.getHeight()]; // 获取颜色并存在data中 img.getRGB(data, 0, img.getWidth(), 0, 0, img.getWidth(), img.getHeight()); imgw = img.getWidth(); imgh = img.getHeight(); // 释放 img = null; System.gc(); // 计算新的宽度和高度 mapWidth = (int)(resolution * imgw); mapHeight = (int)(resolution * imgh); // 计算heightMap大小 heightMap = new short[mapWidth * mapHeight]; // 计算高度和宽度的位置偏移 int xoff = imgw / mapWidth; int yoff = imgh / mapHeight; // 设置高度 for(int y = 0; y < mapHeight; y++) { for(int x = 0; x < mapWidth; x++) { heightMap[x + y * mapWidth] = (short)((data[x * xoff + y * yoff * imgw] & 0x000000ff) * 10); } }
// 释放 data = null; img = null; System.gc(); } //在xz平面平移转换 public void setTransform(Transform t) { for(int x = 0; x < map.length - 1; x++) { for(int y = 0; y < map[x].length - 1; y++) { localTransform.setIdentity(); localTransform.postTranslate(x * 20.4f, 0.0f, (mapHeight - y) * -20.4f); localTransform.postScale(0.04f, 0.04f, 0.04f); localTransform.postMultiply(t); map[x][y].setTransform(localTransform); } } } public static Mesh createQuad(short[] heights) { // 四边形顶点 short[] POINTS = {-255, heights[0], -255, 255, heights[1], -255, 255, heights[2], 255, -255, heights[3], 255};
POSITION_ARRAY = new VertexArray(POINTS.length/3, 3, 2); POSITION_ARRAY.set(0, POINTS.length/3, POINTS); byte[] COLORS = new byte[12]; short[] TEXCOORDS = { 0,0, 1,0, 1,1, 0,1 }; TEXCOORD_ARRAY = new VertexArray(TEXCOORDS.length/2, 2, 2); TEXCOORD_ARRAY.set(0, TEXCOORDS.length/2, TEXCOORDS);
vertexBuffer = new VertexBuffer(); vertexBuffer.setPositions(POSITION_ARRAY, 1.0f, null);
vertexBuffer.setTexCoords(0, TEXCOORD_ARRAY, 1.0f, null); int INDICES[] = new int[] {0, 1, 3, 2}; int[] LENGTHS = new int[] {4}; //创建索引缓冲 indexBuffer = new TriangleStripArray(INDICES, LENGTHS);
appearance = new Appearance(); polygonmode = new PolygonMode(); polygonmode.setCulling(PolygonMode.CULL_NONE); polygonmode.setPerspectiveCorrectionEnable(true); polygonmode.setShading(PolygonMode.SHADE_SMOOTH); appearance.setPolygonMode(polygonmode); createTexture(); appearance.setTexture(0, texture); Mesh mesh = new Mesh(vertexBuffer, indexBuffer, appearance);
return mesh; }
}
下面是屏幕控制类Canvas的代码:
public class DesertCanvas extends GameCanvas implements Runnable {
//新建场景对象 private World world; // 状态量 public static boolean gameOver = false; // 渲染 public static final int STRONG_RENDERING_HINTS = Graphics3D.TRUE_COLOR | Graphics3D.DITHER; public static final int WEAK_RENDERING_HINTS = 0; public static int RENDERING_HINTS = STRONG_RENDERING_HINTS; boolean[] key = new boolean[9]; private Transform identity = new Transform(); // 3D画笔对象 private Graphics3D g3d = null; // 背景 private Background back = null; // 摄像机对象 private Camera camera = null; private Transform camTrans = new Transform(); private HeightMap heightmap; private Transform t = new Transform(); private Mesh[][] map; public DesertCanvas() { super(true); setFullScreenMode(true); g3d = Graphics3D.getInstance(); world = new World(); createMap(); map = heightmap.getQuads(); for(int x = 0; x < heightmap.getMapWidth()-1; x++) { for(int y = 0; y < heightmap.getMapHeight()-1; y++) { world.addChild(map[x][y]); } } camera = new Camera(); float aspect = (float) getWidth() / (float) getHeight(); camera.setPerspective(60.0f, aspect, 0.1f, 150.0f); camTrans.postTranslate(0.0f, 20.0f, 0.0f); camera.setTransform(camTrans); world.addChild(camera); world.setActiveCamera(camera); back = new Background(); back.setColor(0); world.setBackground(back);
Thread t = new Thread(this); t.start(); } private void createMap() { try { heightmap = new HeightMap(); Transform t = new Transform(); t.postTranslate(0.0f, -5.0f, -5.0f); heightmap.setTransform(t);
} catch(Exception e) { System.out.println("Heightmap error: " + e.getMessage()); e.printStackTrace();
} }
private void draw(Graphics g) { try { g3d = Graphics3D.getInstance(); g3d.bindTarget(g, true, RENDERING_HINTS);
g3d.render(world);
} catch(Exception e) { System.out.println(e.getMessage()); System.out.println(e); e.printStackTrace(); } finally { g3d.releaseTarget(); } }
public void run() { while(true) { try { input(); draw(getGraphics()); flushGraphics(); try{ Thread.sleep(30); } catch(Exception e) {} } catch(Exception e) { System.out.println(e.getMessage()); System.out.println(e); e.printStackTrace(); } }
}
protected void input() { int keys = getKeyStates(); if((keys & GameCanvas.FIRE_PRESSED) != 0) camTrans.postTranslate(0.0f, 0.0f, -1.0f); if((keys & GameCanvas.UP_PRESSED) != 0) camTrans.postTranslate(0.0f, 1.0f, 0.0f); if((keys & GameCanvas.DOWN_PRESSED) != 0) camTrans.postTranslate(0.0f, -1.0f, 0.0f); if((keys & GameCanvas.LEFT_PRESSED) != 0) camTrans.postRotate(5, 0.0f, 1.0f, 0.0f); if((keys & GameCanvas.RIGHT_PRESSED) != 0) camTrans.postRotate(-5, 0.0f, 1.0f, 0.0f); camera.setTransform(camTrans) ;
}
}