作者:潇潇  出处:www.j2mefans.com
该文章为本站原创,如有引用,请注明出处和作者


    前一节我们使用图层建立一个背景地图,使用该技术,如果仅仅表示陆地的话倒还可以,对于像太空中闪烁的群星和波澜壮阔的大海就显得太单调了。那么我们怎样实现太空中闪烁的群星呢?
    一个直接的想法就是,继续调用TiledLayer类的setCell方法,不断的改变背景贴图。当然这也是一个方法,但并不是一个好的方法。试想如果游戏中同时有许多动态背景,那么我们的工作量就大了。有没有更好的方法呢?
    通过前面的的例子,我们看到静态背景的贴图索引(包括空白)都是大于等于0的数值,所以要实现背景图层动画,在TiledLayer类中就要求我们使用负数作为动态背景贴图的索引。这样我们就可以设定贴图索引相同的负值统一进行更改背景图层,进而形成动画。

    具体地说,需要注意下面几点:

(1)动画贴图是需要额外创建的,并且它的贴图索引必须为负数。创建的第一个动画贴图的序号为-1,第二个为-2,依此类推。
(2)在创建动画贴图时,需要设定一个静态贴图(也就是题图索引为正数的贴图),作为初始图像,然后在要变换图像画面的时候,用另一个静态贴图替换贴图索引为负数的图像。并多次的重复更换贴图,从而实现动态的效果。
(3)在TiledLayer类中对动态贴图支持,表现在下面的两个方法中:
create-1matedTile(),用来创建一个动画贴图。
set-1matedTile(),用来为指定的动画贴图索引设置静态贴图。

    还是看一个实例吧!下面我们应用TiledLayer类来创建一个动态背景,背景内容为夜空中闪烁的星星。
    首先我们来看一下我们要使用的图片:
          

    其中是5张32*32的图片。

设置动画贴图的步骤如下:
(1)加在图像。
Image image = Image.createImage("/star.png");//加载背景图片
(2)创建背景贴图对象tiledLayer。设定单元数组为6*6。
    TiledLayer tiledLayer = new TiledLayer(6, 6, image, 32, 32);
(3)创建动态贴图,并将其与第三帧图像相关联。该方法的参数就是为动画贴图而显示得初始静态贴图。A为整形变量,用来记录create-1matedTile方法的返回值,该值表示新创建的动画贴图的索引。
A =  tiledLayer.create-1matedTile(3);
(4)设定地图,然后将地图数组所对应的贴图填充进单元中。
    int[] map = {//地图数组
       4,4,4,4,4, 4,
       4,-1,4,4, 3,4,
       4,4,3,4,, -1,4,
       ,4,4,1, 4,3,4,
       4,4,3,3,4, 4,
       4,4,3,4,-1, 4,      
    };//显示地图
    for (int i = 0; i < map.length; i++) {
      int column = i % 6;
      int row = (i - column) / 6;
      tiledLayer.setCell(column, row, map[i]);//通过一个循环来设置tiledLayer
    }

(5)将动态贴图与其他动态贴图相关联,形成动画。在这里就是要让他与第2帧贴图和第5帧贴图相关联,产生一闪一闪的星星效果。
aniCounter++;//计数器,每次游戏线程,自动加1
     if(aniCounter%6) 
               mBackground.setAnimatedTile(-1,2);//当计数器增加到6,显示一次动画
     else
    mBackground.setAnimatedTile(-1,3);//设置动画背景为不闪烁的星星
        
(6)绘制背景,并将缓冲区内容强制输出到屏幕上。
mBackground.paint(g);
    flushGraphics();


下面是源代码:
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import java.util.*;
import java.io.*;

public class OCanvas extends GameCanvas implements Runnable {
  private Display    display;
  private boolean    sleeping;
  private long       frameDelay;
  
  private TiledLayer backgroundLayer;
  private LayerManager mLayerManager;
  private int aniCounter;


  public OCanvas(Display d) {
    super(true);
    display = d;

    // 设定帧频 (30 fps)
    frameDelay = 33;

   
  }
  
  public void start() {
    // 设定这个画布为当前屏幕显示
    display.setCurrent(this);

    // 创建背景图层
    try {
      backgroundLayer = new TiledLayer(6, 6, Image.createImage("/star.png"), 32, 32);
    }
    catch (IOException e) {
      System.err.println("Failed loading images!");
    }

    backgroundLayer.createAnimatedTile(3);
 
   // 设定背景图层地图
   int[] layerMap = {
       4,-1,4,4,3, 4,
       -1,4,4,3, 4,3,
       4,4,1,4, -1,4,
       4,-1,3, 4,3,4,
       3,4,3,4,4, 4,
       4,4,3,4,-1, 3,
    };
    for (int i = 0; i < layerMap.length; i++) {
      int column = i % 6;
      int row = (i - column) / 6;
      backgroundLayer.setCell(column, row, layerMap[i]);
    }
    backgroundLayer.setPosition((getWidth() - backgroundLayer.getWidth()) / 2,
      (getHeight() - backgroundLayer.getHeight()) / 2);

    // 开始动画线程
    sleeping = false;
    Thread t = new Thread(this);
    t.start();
  }
  
  public void stop() {
    // 停止动画
    sleeping = true;
  }
  
  public void run() {
    Graphics g = getGraphics();
    
    // 游戏主循环
    while (!sleeping) {
      //更新数据
    update();
     //显示图像
      draw(g);
      try {
        Thread.sleep(frameDelay);
      }
      catch (InterruptedException ie) {}
    }
  }

  private void update() 
{
      aniCounter++;
     if(aniCounter<6)
     { 
    backgroundLayer.setAnimatedTile(-1,3);
//设置动画背景为不闪烁的星星
      }          
     else if(aniCounter>6 && aniCounter<12)
     {
    backgroundLayer.setAnimatedTile(-1,2);
//当计数器增加到6,显示一次动画
            
    }
     else if(aniCounter>12 && aniCounter<18)
     {
    backgroundLayer.setAnimatedTile(-1,5); 
//当计数器增加到6,再次显示一次动画
    aniCounter=0;
     } 
         
  }

  private void draw(Graphics g) {
    // 绘制背景图层 
   backgroundLayer.paint(g);
       
    //刷新屏幕显示缓冲区
    flushGraphics();
  }
  
}