J2ME RPG游戏边学边做(一)

笔者以前是做j2ee的,一个月前由于兴趣所致开始利用业余时间学习j2me游戏开发。在网上看了一通教程后,便准备动手一边学一边做一个简单的rpg游戏。虽然起点比较高,但感觉游戏难度越大,遇到的问题也就越多。这样待全部解决后,也就学的差不多了。另外只有做这种游戏才有学下去的兴趣。以后我会每次把写成的源码及思路发上来,供大家指正。希望各位高人可以无私的帮助我。

下面是游戏中所需要的部分图片,还有的图片下次写到了再上传:

hero_left.png:

hero_right.png:

hero_up.png:

hero_down.png:


整个程序的主体在BraveCanvas类中完成,该类继承于GameCanvas实现Runnable接口,由BraveMIDlet类启动他, BraveMIDlet继承MIDlet实现CommandListener接口。BraveMIDlet类代码如下:(由于只是一个简单的rpg,开头画面和菜单全部省略了,改为由一个按扭启动游戏)

 

BraveMIDlet.java

package brave;

import javax.microedition.lcdui.*;

import javax.microedition.midlet.*;

public class BraveMIDlet extends MIDlet implements CommandListener

{

 private Display d ;

 private Command exitCommand ;

 private Command startCommand ;

    private BraveCanvas braveCanvas;

 public BraveMIDlet()

 {

 d = Display.getDisplay(this);

 exitCommand = new Command("退出",Command.EXIT,1);

 startCommand = new Command("开始",Command.SCREEN,1);

 }

 public void startApp()

 {

 //创建BraveCanvas

 braveCanvas = new BraveCanvas();

 braveCanvas.addCommand(exitCommand);

 braveCanvas.addCommand(startCommand);

 braveCanvas.setCommandListener(this);

 //装载BraveCanvas

 d.setCurrent(braveCanvas);

 }

 public void pauseApp()

 {

 }

 public void destroyApp(boolean unconditional)

 {

 }

 public void commandAction(Command c , Displayable dpa)

 {

 String str_co = c.getLabel();

 if(str_co.equals("开始"))

 {

  //运行BraveCanvas中的线程(启动游戏)

  braveCanvas.startup();

 }

 else if(str_co.equals("退出"))

 {

  destroyApp(false);

  notifyDestroyed();

 }

 }

}

BraveCanvas.java

package brave;

import javax.microedition.lcdui.game.GameCanvas;

import javax.microedition.lcdui.Graphics;

import java.io.IOException;

public class BraveCanvas extends GameCanvas implements Runnable

{

 private boolean sign;

 private Graphics g;

 //设置@符号的当前位置

 private int x,y;

 public BraveCanvas()

 {

 super(true);

 //初始化@位置

 x = getWidth()/2;

  y = getHeight()/2;

 }

 

 public void startup()

 {

 this.sign = true;

 Thread thread = new Thread(this);

 //启动线程

 thread.start();

 }

 public void run()

 {

 g = getGraphics();

 while(sign)

 {

  try

  {

    //@符号的移动

    input(g);

    //@符号的显示

    paint(g);

    //这里应该有详细的计算,方便为上,置为15

    Thread.sleep(15);

  }

  catch(Exception e)

  {

    System.out.println("2:"+e);

  }

 }

 }

 public void input(Graphics g) throws IOException

 {

 int keystates = getKeyStates();

 switch(keystates)

 {

  case UP_PRESSED:

    y = Math.max(0, y - 1);

    break;

  case DOWN_PRESSED:

    y = Math.min(getHeight(), y + 1);

    break;

  case LEFT_PRESSED:

    x = Math.max(0, x - 1);

    break;

  case RIGHT_PRESSED:

    x = Math.min(getWidth(), x + 1);

    break;

 }

 }

 public void paint(Graphics g)

 {

 //设置画布的背景色

 g.setColor(0x000000);

 //把背景色画满画布

 g.fillRect(0, 0, getWidth(), getHeight());

 //设置画布的前景色

 g.setColor(0xffffff);

 //在画布上写上@

 g.drawString("@", x, y, Graphics.TOP|Graphics.LEFT);

 //刷新画布

 flushGraphics();

 }

}

上面代码运行后,画面上会出现一个"@"字符随着键盘的左右而移动。虽然这离rpg游戏相差很远,但这是一个游戏的基本框架。下面我们要做的就是把"@"换成我们的英雄。为了程序清晰,我们还要设计一个英雄类Hero,该类继承于Sprite,这个类里面要用到上面的图片。

Hero.java


package brave;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.lcdui.Image;
import java.io.IOException;
public class Hero extends Sprite
{
 //设置英雄的当前位置
 private int x, y;
 private BraveCanvas braveCanvas;
 public Hero(Image image, int frameWidth, int frameHeight)
 {
  //英雄的初始化
  super(image, frameWidth, frameHeight);
 }
 public void setBraveCanvas(BraveCanvas braveCanvas)
 {
  this.braveCanvas = braveCanvas;
 }
 public void init(int x, int y)
 {
  //英雄位置的初始化
  this.x = x;
  this.y = y;
 }
 public void afresh()
 {
  //刷新英雄的位置
  setPosition(this.x, this.y);
 }
 public void moveUp() throws IOException
 {
  //英雄上移,并改为相应的图片
  setImage(Image.createImage("/hero_up.png"), 17, 26);
  nextFrame();
  this.y = Math.max(0, y - 1);
 }
 public void moveDown() throws IOException
 {
  //英雄下移,并改为相应的图片
  setImage(Image.createImage("/hero_down.png"), 17, 26);
  nextFrame();
  this.y = Math.min(braveCanvas.getHeight(), y + 1);
 }
 public void moveLeft() throws IOException
 {
  //英雄左移,并改为相应的图片
  setImage(Image.createImage("/hero_left.png"), 17, 26);
  nextFrame();
  this.x = Math.max(0, x - 1);
 }
 public void moveRight() throws IOException
 {
  //英雄右移,并改为相应的图片
  setImage(Image.createImage("/hero_right.png"), 17, 26);
  nextFrame();
  this.x = Math.min(braveCanvas.getWidth(), x + 1);
 }
}
然后把BraveCanvas类稍做修改,把"@"换成英雄
BraveCanvas.java
package brave;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.Graphics;
import java.io.IOException;
import javax.microedition.lcdui.Image;
public class BraveCanvas extends GameCanvas implements Runnable
{
 private boolean sign;
 private Graphics g;
 private Hero hero;
 public BraveCanvas()
 {
  super(true);
 }
 
 public void startup()
 {
  this.sign = true;
  try
  {
   Image heroimage = Image.createImage("/hero_up.png");
   hero = new Hero(heroimage, 17, 26);
   hero.setBraveCanvas(this);
   hero.init(40,40);
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
  Thread thread = new Thread(this);
  thread.start();
 }
 public void run()
 {
  g = getGraphics();
  while(sign)
  {
   try
   {
    input(g);
    paint(g);
    Thread.sleep(15);
   }
   catch(Exception e)
   {
    System.out.println("2:"+e);
   }
  }
 }
 public void input(Graphics g) throws IOException
 {
  int keystates = getKeyStates();
  switch(keystates)
  {
   case UP_PRESSED:
    hero.moveUp();
    break;
   case DOWN_PRESSED:
    hero.moveDown();
    break;
   case LEFT_PRESSED:
    hero.moveLeft();
    break;
   case RIGHT_PRESSED:
    hero.moveRight();
    break;
  }
  hero.afresh();
 }
 public void paint(Graphics g)
 {
  g.setColor(0x000000);
  g.fillRect(0, 0, getWidth(), getHeight());
  g.setColor(0xffffff);
  hero.paint(g);
  flushGraphics();
 }
}


这样,我们的英雄就可以在画面上移动了,不过英雄比较简单,没有hp,mp等等,只是一个图片。而且如果大家感觉英雄的脚步过快,可以在BraveCanvas类中的Hero初始化时设置:
hero.setFrameSequence(new int[]{0, 0, 1, 1, 0, 0, 2, 2 });

J2ME RPG游戏边学边做(二)
1、
public void moveDown() throws IOException
{
  //英雄下移,并改为相应的图片
  setImage(Image.createImage("/hero_down.png"), 17, 26);
  nextFrame();
  this.y = Math.min(braveCanvas.getHeight(), y + 1);
}

在io包中的读取是非常耗内存的,所以Image.createImage("/hero_down.png")放在线程的循环中确实不好,现在已经改成图象在BraveCanvas类中创建(下面的代码已更改),然后由moveDown(Image image)方法接收传递进来的图象。

2、RPG是个大工程,一个人的力量是很难完成的,我只想实现基本的RPG功能,比如人物的对话,场景的转换,战斗等等,希望大家多多给予帮助。

这一篇我将给游戏加入地图,以下是该篇所需要的图片:

background.png

foreground.png


一个RPG中的游戏地图是非常大而且多的,为了方便以后的维护,我创建了一个Scene类,该类主要是产生游戏所需要的地图。

Scene.java


package brave;
import javax.microedition.lcdui.game.TiledLayer;
import javax.microedition.lcdui.Image;
public class Scene
{
 public static TiledLayer createTiledLayerByBackground(Image image)
 {
  //使用TiledLayer创建地图
  TiledLayer tiledLayer = new TiledLayer(10, 8, image, 48, 64);
  tiledLayer.fillCells(0, 0, 10, 8, 2);
  return tiledLayer;
 }
}

修改BraveCanvas类,加入地图
BraveCanvas.java
package brave;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.Graphics;
import java.io.IOException;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.TiledLayer;

public class BraveCanvas extends GameCanvas implements Runnable
{
 private boolean sign;
 private Graphics g;
 private Hero hero;
 private Image upimage;
 private Image downimage;
 private Image leftimage;
 private Image rightimage;
 private TiledLayer backgroundMap;
 public BraveCanvas()
 {
  super(true);
 }
 public void startup()
 {
  this.sign = true;
  try
  {
   //产生地图
   backgroundMap = Scene.createTiledLayerByBackground(
    Image.createImage("/background.png"));
   
   //改正上一篇的错误
   upimage = Image.createImage("/hero_up.png");
   downimage = Image.createImage("/hero_down.png");
   leftimage = Image.createImage("/hero_left.png");
   rightimage = Image.createImage("/hero_right.png");
   hero = new Hero(upimage, 17, 26);
   hero.setFrameSequence(new int[]{1, 1, 0, 0, 1, 1, 2, 2});
   hero.setBraveCanvas(this);
   hero.init(40,40);
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
  Thread thread = new Thread(this);
  thread.start();
 }
 public void run()
 {
  g = getGraphics();
  while(sign)
  {
   try
   {
    input(g);
    paint(g);
    Thread.sleep(15);
   }
   catch(Exception e)
   {
    e.printStackTrace();
   }
  }
 }
 public void input(Graphics g) throws IOException
 {
  int keystates = getKeyStates();
  switch(keystates)
  {
   case UP_PRESSED:
    //由这里传入需要改变的图片
    hero.moveUp(upimage);
    break;
   case DOWN_PRESSED:
    hero.moveDown(downimage);
    break;
   case LEFT_PRESSED:
    hero.moveLeft(leftimage);
    break;
   case RIGHT_PRESSED:
    hero.moveRight(rightimage);
    break;
  }
  hero.afresh();
 }
 public void paint(Graphics g)
 {
  g.setColor(0x000000);
  g.fillRect(0, 0, getWidth(), getHeight());
  g.setColor(0xffffff);
  //显示地图
  backgroundMap.paint(g);
  hero.paint(g);
  flushGraphics();
 }
}

现在我们的英雄虽然能在草地上行走了,但感觉给他移动的空间太小了。而且我们在创建背景地图的时候,地图大小明明是512*480的。好,接下来我们要做的就是让英雄可以在更大的天地中活动。这里就需要一个BraveManager类来管理这些屏幕上的Sprite和TiledLayer,该类继承 LayerManager。

BraveManager.java

package brave;

import javax.microedition.lcdui.game.LayerManager;

public class BraveManager extends LayerManager

{

 private BraveCanvas braveCanvas;

 public void setBraveCanvas(BraveCanvas braveCanvas)

 {

 this.braveCanvas = braveCanvas;

 }

 public void afresh()

 {

 //确定当前试图的坐标

 //这里用一个比较简单的算法来使英雄永远在屏幕的中央

 int viewX = Math.max(0, getLayerAt(0).getX() - braveCanvas.getWidth()/2);

 int viewY = Math.max(0, getLayerAt(0).getY() - braveCanvas.getHeight()/2);

 viewX = Math.min(viewX, getLayerAt(1).getWidth() - braveCanvas.getWidth());

 viewY = Math.min(viewY, getLayerAt(1).getHeight() - braveCanvas.getHeight());

 setViewWindow(viewX, viewY, braveCanvas.getWidth(), braveCanvas.getHeight());

 }

}

修改BraveCanvas

BraveCanvas.java

package brave;

import javax.microedition.lcdui.game.GameCanvas;

import javax.microedition.lcdui.Graphics;

import java.io.IOException;

import javax.microedition.lcdui.Image;

import javax.microedition.lcdui.game.TiledLayer;

 

public class BraveCanvas extends GameCanvas implements Runnable

{

 private boolean sign;

 private Graphics g;

 private Hero hero;

 private Image upimage;

 private Image downimage;

 private Image leftimage;

 private Image rightimage;

 private TiledLayer backgroundMap;

 //创建Layer管理视图类

 private BraveManager braveManager;

 public BraveCanvas()

 {

 super(true);

 }

 public void startup()

 {

 this.sign = true;

 try

 {

  backgroundMap = Scene.createTiledLayerByBackground(

   Image.createImage("/background.png"));

  upimage = Image.createImage("/hero_up.png");

  downimage = Image.createImage("/hero_down.png");

  leftimage = Image.createImage("/hero_left.png");

  rightimage = Image.createImage("/hero_right.png");

  //创建Layer管理视图类

  braveManager = new BraveManager();

  braveManager.setBraveCanvas(this);

  hero = new Hero(upimage, 17, 26);

  hero.setFrameSequence(new int[]{1, 1, 0, 0, 1, 1, 2, 2});

  hero.setBraveCanvas(this);

  hero.setBraveManager(braveManager);

  hero.init(0,0);

 }

 catch(Exception e)

 {

  e.printStackTrace();

 }

 Thread thread = new Thread(this);

 thread.start();

 }

 public void run()

 {

 g = getGraphics();

 //插入图层

 braveManager.insert(hero, 0);

 braveManager.insert(backgroundMap, 1);

 while(sign)

 {

  try

  {

    input(g);

    paint(g);

    Thread.sleep(15);

  }

  catch(Exception e)

  {

    e.printStackTrace();

  }

 }

 }

 public void input(Graphics g) throws IOException

 {

 int keystates = getKeyStates();

 switch(keystates)

 {

  case UP_PRESSED:

    hero.moveUp(upimage);

    break;

  case DOWN_PRESSED:

    hero.moveDown(downimage);

    break;

  case LEFT_PRESSED:

    hero.moveLeft(leftimage);

    break;

  case RIGHT_PRESSED:

    hero.moveRight(rightimage);

    break;

 }

 hero.afresh();

 //刷新视图的位置

 braveManager.afresh();

 }

 public void paint(Graphics g)

 {

 g.setColor(0x000000);

 g.fillRect(0, 0, getWidth(), getHeight());

 g.setColor(0xffffff);

 //显示视图

 braveManager.paint(g, 0, 0);

 flushGraphics();

 }

}

 


这样英雄就可以在地图上任何地方行动了,不过还得改一个小地方:不知道大家还记的不,在Hero类中,我们定义英雄移动的范围最大为屏幕的尺寸。
这显然是不行的,最大的移动范围应改成地图的大小:

this.y = Math.min(braveManager.getLayerAt(1).getHeight(), y + 1);

this.x = Math.min(braveManager.getLayerAt(1).getWidth(), x + 1);


代码如下:

Hero.java


package brave;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.lcdui.Image;
import java.io.IOException;
import javax.microedition.lcdui.Graphics;
public class Hero extends Sprite
{
 private int x;
 private int y;
 private BraveCanvas braveCanvas;
 private BraveManager braveManager;
 public Hero(Image image, int frameWidth, int frameHeight)
 {
  super(image, frameWidth, frameHeight);
 }
 public void setBraveCanvas(BraveCanvas braveCanvas)
 {
  this.braveCanvas = braveCanvas;
 }
 public void setBraveManager(BraveManager braveManager)
 {
  this.braveManager = braveManager;
 }
 public void setManager(BraveCanvas braveCanvas)
 {
  this.braveCanvas = braveCanvas;
 }
 public void init(int x, int y)
 {
  this.x = x;
  this.y = y;
 }
 public void afresh()
 {
  setPosition(this.x, this.y);
 }
 public void moveUp(Image image) throws IOException
 {
  setImage(image, 17, 26);
  nextFrame();
  this.y = Math.max(0, y - 1);
 }
 public void moveDown(Image image) throws IOException
 {
  setImage(image, 17, 26);
  nextFrame();
  this.y = Math.min(braveManager.getLayerAt(1).getHeight(), y + 1);
 }
 public void moveLeft(Image image) throws IOException
 {
  setImage(image, 17, 26);
  nextFrame();
  this.x = Math.max(0, x - 1);
 }
 public void moveRight(Image image) throws IOException
 {
  setImage(image, 17, 26);
  nextFrame();
  this.x = Math.min(braveManager.getLayerAt(1).getWidth(), x + 1);
 }
}

现在英雄的移动范围大了,但只英雄一人,也太孤单了,我们给他创造一个小镇吧。

修改Scene类如下:
Scene.java
package brave;
import javax.microedition.lcdui.game.TiledLayer;
import javax.microedition.lcdui.Image;
public class Scene
{
 public static TiledLayer createTiledLayerByBackground(Image image)
 {
  TiledLayer tiledLayer = new TiledLayer(10, 8, image, 48, 64);
  tiledLayer.fillCells(0, 0, 10, 8, 2);
  return tiledLayer;
 }
 public static TiledLayer createTiledLayerByForeground(Image image)
 {
  TiledLayer tiledLayer = new TiledLayer(30, 32, image, 16, 16);
  // 30 * 32
  int[] maplist =
  {
    //0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
26 27 28 29
   0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,//0
   0
,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
30,0 ,//1
   0 ,34,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,36,0 ,//2
   0 ,34,0 ,1 ,2 ,3 ,4 ,5 ,0 ,0 ,0 ,1 ,2 ,3 ,3 ,26,3 ,3 ,4 ,5 ,0 ,0 ,1 ,2 ,3
,4 ,5 ,0 ,36,0 ,//3
   0 ,34,0 ,7 ,8 ,46,10,11,0 ,0 ,0 ,7 ,8 ,47,31,32,33,47,10,11,0 ,0 ,7 ,8
,46,10,11,0 ,36,0 ,//4
   0 ,34,0 ,13,14,15,16,17,0 ,0 ,0 ,13,14,14,37,38,39,14,16,17,0 ,0
,13,14,15,16,17,0 ,36,0 ,//5
   0 ,34,0 ,19,20,21,22,23,6 ,0 ,0 ,19,20,20,43,44,45,20,20,23,0 ,0
,19,20,21,22,23,0 ,36,0 ,//6
   0 ,34,0 ,0 ,0 ,12,0 ,0 ,0 ,0 ,0 ,24,24,24,13,15,17,24,24,24,0 ,0 ,0 ,0
,12,0 ,0 ,0 ,36,0 ,//7
   0 ,34,0 ,0 ,0 ,12,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,19,21,23,0 ,0 ,0 ,0 ,0 ,0 ,0
,12,0 ,0 ,0 ,36,0 ,//8
   0 ,34,0 ,0 ,0 ,12,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,12,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,12,0 ,0 ,0 ,36,0 ,//9
   0 ,34,0 ,0 ,0
,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,0 ,0 ,0 ,36,0 ,//10
   0 ,34,0 ,0 ,0 ,0 ,0 ,0 ,0 ,12,25,25,25,25,25,25,25,25,25,25,12,0 ,0 ,0 ,0
,0 ,0 ,0 ,36,0 ,//11
   0 ,34,0 ,1 ,2 ,3 ,4 ,5 ,0 ,12,25,25,25,25,25,25,25,25,25,25,12,0 ,1 ,2 ,3
,4 ,5 ,0 ,36,0 ,//12
   0 ,34,0 ,7 ,8 ,46,10,11,0 ,12,25,25,25,25,25,25,25,25,25,25,12,0 ,7 ,8
,46,10,11,0 ,36,0 ,//13
   0 ,34,0 ,13,14,15,16,17,0 ,12,25,25,25,25,25,25,25,25,25,25,12,0
,13,14,15,16,17,0 ,36,0 ,//14
   0 ,34,0 ,19,20,21,22,23,0 ,12,25,25,25,25,25,25,25,25,25,25,12,0
,19,20,21,22,23,0 ,36,0 ,//15
   0 ,34,0 ,0 ,0 ,12,0 ,0 ,0 ,12,25,25,25,25,25,25,25,25,25,25,12,0 ,0 ,0
,12,0 ,0 ,0 ,36,0 ,//16
   0 ,34,0 ,0 ,0 ,12,0 ,0 ,0 ,12,25,25,25,25,25,25,25,25,25,25,12,0 ,0 ,0
,12,0 ,0 ,0 ,36,0 ,//17
   0 ,34,0 ,0 ,0 ,12,0 ,0 ,0 ,12,25,25,25,25,25,25,25,25,25,25,12,0 ,0 ,0
,12,0 ,0 ,0 ,36,0 ,//18
   0 ,34,0 ,0 ,0
,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,0 ,0 ,0 ,36,0 ,//19
   0 ,34,0 ,0 ,0 ,0 ,0 ,0 ,0 ,12,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,12,0 ,0 ,0 ,0
,0 ,0 ,0 ,36,0 ,//20
   0 ,34,0 ,0 ,0 ,0 ,0 ,0 ,0 ,12,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,12,0 ,0 ,0 ,0
,0 ,0 ,0 ,36,0 ,//21
   0 ,34,0 ,1 ,2 ,3 ,4 ,5 ,0 ,12,0 ,0 ,0 ,0 ,1 ,3 ,5 ,0 ,0 ,0 ,12,0 ,1 ,2 ,3
,4 ,5 ,0 ,36,0 ,//22
   0 ,34,0 ,7 ,8 ,46,10,11,0 ,12,0 ,0 ,0 ,0 ,7 ,48,11,0 ,0 ,0 ,12,0 ,7 ,8
,46,10,11,0 ,36,0 ,//23
   0 ,34,0 ,13,14,15,16,17,0 ,12,0 ,0 ,0 ,6 ,13,15,17,0 ,0 ,0 ,12,0
,13,14,15,16,17,0 ,36,0 ,//24
   0 ,34,0 ,19,20,21,22,23,0 ,12,0 ,0 ,0 ,6 ,19,21,23,0 ,0 ,0 ,12,0
,19,20,21,22,23,0 ,36,0 ,//25
   0 ,34,0 ,0 ,0 ,12,0 ,0 ,0 ,12,18,0 ,0 ,0 ,0 ,12,0 ,0 ,0 ,0 ,12,0 ,0 ,0
,12,0 ,0 ,0 ,36,0 ,//26
   0 ,34,0 ,0 ,0
,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,0 ,0 ,0 ,36,0 ,//27
   0 ,34,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,12,12,12,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,36,0 ,//28
   0 ,34,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,12,12,12,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,36,0 ,//29
   0
,40,29,29,29,29,29,29,29,29,29,29,29,29,12,12,12,29,29,29,29,29,29,29,29,29,29,29,
42,0 ,
//30
   0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0  //31
  };
  for(int i = 0 ; i < maplist.length ; i++)
  {
   int col = i % 30;
   int row = (i - col) / 30;
   tiledLayer.setCell(col, row, maplist[i]);
  }
  return tiledLayer;
 }
}
修改BraveCanvas类如下:
BraveCanvas.java
package brave;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.Graphics;
import java.io.IOException;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.TiledLayer;

public class BraveCanvas extends GameCanvas implements Runnable
{
 private boolean sign;
 private Graphics g;
 private Hero hero;
 private Image upimage;
 private Image downimage;
 private Image leftimage;
 private Image rightimage;
 private TiledLayer backgroundMap;
 private TiledLayer foregroundMap;
 private BraveManager braveManager;
 public BraveCanvas()
 {
  super(true);
 }
 public void startup()
 {
  this.sign = true;
  try
  {
   backgroundMap = Scene.createTiledLayerByBackground(
    Image.createImage("/background.png"));
   //生成小镇地图
   foregroundMap = Scene.createTiledLayerByForeground(
    Image.createImage("/foreground.png"));
   upimage = Image.createImage("/hero_up.png");
   downimage = Image.createImage("/hero_down.png");
   leftimage = Image.createImage("/hero_left.png");
   rightimage = Image.createImage("/hero_right.png");
   braveManager = new BraveManager();
   braveManager.setBraveCanvas(this);
   hero = new Hero(upimage, 17, 26);
   hero.setFrameSequence(new int[]{1, 1, 0, 0, 1, 1, 2, 2});
   hero.setBraveCanvas(this);
   hero.setBraveManager(braveManager);
   hero.init(0,0);
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
  Thread thread = new Thread(this);
  thread.start();
 }
 public void run()
 {
  g = getGraphics();
  braveManager.insert(hero, 0);
  //插入小镇地图
  braveManager.insert(foregroundMap, 1);
  braveManager.insert(backgroundMap, 2);
  while(sign)
  {
   try
   {
    input(g);
    paint(g);
    Thread.sleep(15);
   }
   catch(Exception e)
   {
    e.printStackTrace();
   }
  }
 }
 public void input(Graphics g) throws IOException
 {
  int keystates = getKeyStates();
  switch(keystates)
  {
   case UP_PRESSED:
    hero.moveUp(upimage);
    break;
   case DOWN_PRESSED:
    hero.moveDown(downimage);
    break;
   case LEFT_PRESSED:
    hero.moveLeft(leftimage);
    break;
   case RIGHT_PRESSED:
    hero.moveRight(rightimage);
    break;
  }
  hero.afresh();
  braveManager.afresh();
 }
 public void paint(Graphics g)
 {
  g.setColor(0x000000);
  g.fillRect(0, 0, getWidth(), getHeight());
  g.setColor(0xffffff);
  braveManager.paint(g, 0, 0);
  flushGraphics();
 }
}

运行结果如图: