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) ;
}
}