Facebook Twitter LinkedIn E-mail
magnify
Home Archive for category "Java ME"

Java ME引路蜂地图开发包Ver2.1下载

Java ME -MIDP地图开发包下载。

JavaDoc 下载
Java ME引路蜂地图开发库 下载
Java ME引路蜂地图开发示例 下载
引路蜂地图开发指南 下载
  1. Java ME地图应用开发环境
  2. Java ME引路蜂地图开发示例:第一个地图应用 
  3. Java ME引路蜂地图开发示例:设置地图类型
  4. Java ME引路蜂地图开发示例:放大、缩小
  5. Java ME引路蜂地图开发示例:地图平移
  6. Java ME引路蜂地图开发示例:地址查询
  7. Java ME引路蜂地图开发示例:路径查询
  8. Java ME引路蜂地图开发示例:本地查询
  9. Java ME引路蜂地图开发示例:IP地址查询
  10. Java ME引路蜂地图开发示例:地址反编码
  11. Java ME引路蜂地图开发示例:选择地图服务
  12. Java ME引路蜂地图开发示例:叠加自定义图层
  13. Java ME引路蜂地图开发示例:离线地图示例
  14. 自定义地图示例:天地图(一)
  15. 自定义地图示例:天地图(二)

 

离线地图下载方法解析

在使用Google Map, Microsoft Map 等在线地图时,常常想知道这些地图在服务器上是如何存放的,目前大部分地图服务器都是将地图以图片存储以提高响应速度。 一般大小为256X256个像素。
如果知道每个图片的URL,自己写个地图下载软件并不困难。从而做成离线地图。
下面程序片段给出了常用地图服务器上地图图片存取的URL计算方法。

using System.Collections.Generic;
using System.Text;
namespace MapTileURL
{
    class Program
    {
        private static Dictionary<string, string> MapTypeURLs = new Dictionary<string, string>
        {
            { "GoogleSatURL", "<a href="http://khm{GOOG_DIGIT}.google.com/kh/v=58&x={X}&y={Y}&z={ZOOM}&s={GALILEO">http://khm{GOOG_DIGIT}.google.com/kh/v=58&x={X}&y={Y}&z={ZOOM}&s={GALILEO</a>}" },
            { "GoogleMapURL", "<a href="http://mt{GOOG_DIGIT}.google.com/vt/lyrs=m@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO">http://mt{GOOG_DIGIT}.google.com/vt/lyrs=m@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO</a>}" },
            { "GoogleHybURL", "<a href="http://mt{GOOG_DIGIT}.google.com/vt/lyrs=h@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO">http://mt{GOOG_DIGIT}.google.com/vt/lyrs=h@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO</a>}" },
            { "GoogleTerURL", "<a href="http://mt{GOOG_DIGIT}.google.com/vt/lyrs=t@108,r@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO">http://mt{GOOG_DIGIT}.google.com/vt/lyrs=t@108,r@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO</a>}" },
            { "GoogleChinaURL", "<a href="http://mt{GOOG_DIGIT}.google.cn/vt/lyrs=m@121&hl=en&gl=cn&x={X}&y={Y}&z={ZOOM}&s={GALILEO">http://mt{GOOG_DIGIT}.google.cn/vt/lyrs=m@121&hl=en&gl=cn&x={X}&y={Y}&z={ZOOM}&s={GALILEO</a>}" },
            { "YahooMapURL", "<a href="http://maps{Y_DIGIT}.yimg.com/hx/tl?v=4.3&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1">http://maps{Y_DIGIT}.yimg.com/hx/tl?v=4.3&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1</a>" },
            { "YahooSatURL", "<a href="http://maps{Y_DIGIT}.yimg.com/ae/ximg?v=1.9&t=a&s=256&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1">http://maps{Y_DIGIT}.yimg.com/ae/ximg?v=1.9&t=a&s=256&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1</a>" },
            { "YahooInMapURL", "<a href="http://maps.yimg.com/hw/tile?locale=en&imgtype=png&yimgv=1.2&v=4.1&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM_2">http://maps.yimg.com/hw/tile?locale=en&imgtype=png&yimgv=1.2&v=4.1&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM_2</a>}" },
            { "YahooInHybURL", "<a href="http://maps.yimg.com/hw/tile?imgtype=png&yimgv=0.95&t=h&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM_2">http://maps.yimg.com/hw/tile?imgtype=png&yimgv=0.95&t=h&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM_2</a>}" },
            { "YahooHybURL", "<a href="http://maps{Y_DIGIT}.yimg.com/hx/tl?v=4.3&t=h&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1">http://maps{Y_DIGIT}.yimg.com/hx/tl?v=4.3&t=h&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1</a>" },
            { "MicrosoftBrMapURL", "<a href="http://imakm{MS_DIGITBR}.maplink3.com.br/maps.ashx?v={QUAD}|t&call=2.2.4">http://imakm{MS_DIGITBR}.maplink3.com.br/maps.ashx?v={QUAD}|t&call=2.2.4</a>" },
            { "MicrosoftHybURL", "<a href="http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/h{QUAD}.png?g=441&mkt=en-us&n=z">http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/h{QUAD}.png?g=441&mkt=en-us&n=z</a>" },
            { "MicrosoftSatURL", "<a href="http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/a{QUAD}.png?g=441&mkt=en-us&n=z">http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/a{QUAD}.png?g=441&mkt=en-us&n=z</a>" },
            { "MicrosoftMapURL", "<a href="http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/r{QUAD}.png?g=441&mkt=en-us&n=z">http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/r{QUAD}.png?g=441&mkt=en-us&n=z</a>" },
            { "MicrosoftTerURL", "<a href="http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/r{QUAD}.png?g=441&mkt=en-us&shading=hill&n=z">http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/r{QUAD}.png?g=441&mkt=en-us&shading=hill&n=z</a>" },
            { "OpenStreetMapURL", "<a href="http://tile.openstreetmap.org/{ZOOM}/{X}/{Y}.png">http://tile.openstreetmap.org/{ZOOM}/{X}/{Y}.png</a>" },
            { "OSMARenderURL", "<a href="http://tah.openstreetmap.org/Tiles/tile/{ZOOM}/{X}/{Y}.png">http://tah.openstreetmap.org/Tiles/tile/{ZOOM}/{X}/{Y}.png</a>" },
            { "OpenAerialMapURL", "<a href="http://tile.openaerialmap.org/tiles/?v=mgm&layer=openaerialmap-900913&x={X}&y={Y}&zoom={OAM_ZOOM">http://tile.openaerialmap.org/tiles/?v=mgm&layer=openaerialmap-900913&x={X}&y={Y}&zoom={OAM_ZOOM</a>}" },
            { "OpenCycleMapURL", "<a href="http://andy.sandbox.cloudmade.com/tiles/cycle/{ZOOM}/{X}/{Y}.png">http://andy.sandbox.cloudmade.com/tiles/cycle/{ZOOM}/{X}/{Y}.png</a>" }
        };
        readonly static char[] Lookup = new[] { 'q', 't', 'r', 's' };
        public static string GetQuadtreeFromXYZoom(int x, int y, int zoom)
        {
            var quad = new StringBuilder();
            for (int i = 0; i < zoom; i++)
            {
                int rx = x % 2;
                int ry = y % 2;
                x /= 2;
                y /= 2;
                quad.Insert(0, Lookup[rx * 2 + ry]);
            }
            quad.Insert(0, 't');
            return quad.ToString();
        }
        public static string BuildUrl(string tileType, int x,int y,int zoom)
        {
    
            string url = "";
            // Edited by Shustrik - compacted the switch statement
            switch (tileType)
            {
                case "GoogleSat":
                case "GoogleSatH":
                    url = MapTypeURLs["GoogleSatURL"];
                    break;
                case "GoogleMap":
                    url = MapTypeURLs["GoogleMapURL"];
                    break;
                case "GoogleHyb":
                    url = MapTypeURLs["GoogleHybURL"];
                    break;
                case "GoogleTer":
                    url = MapTypeURLs["GoogleTerURL"];
                    break;
                case "GoogleChina":
                    url = MapTypeURLs["GoogleChinaURL"];
                    break;
                case "MicrosoftMap":
                    url = MapTypeURLs["MicrosoftMapURL"];
                    break;
                case "MicrosoftSat":
                    url = MapTypeURLs["MicrosoftSatURL"];
                    break;
                case "MicrosoftHyb":
                    url = MapTypeURLs["MicrosoftHybURL"];
                    break;
                case "MicrosoftTer":
                    url = MapTypeURLs["MicrosoftTerURL"];
                    break;
                case "MicrosoftBrMap":
                    if (zoom <= 10)
                        url =  MapTypeURLs["MicrosoftMapURL"];
                    else
                        url = MapTypeURLs["MicrosoftBrMapURL"];
                    break;
                case "YahooMap":
                    url = MapTypeURLs["YahooMapURL"];
                    break;
                case "YahooSat":
                case "YahooSatH":
                case "YahooSatH2":
                    url = MapTypeURLs["YahooSatURL"];
                    break;
                case "YahooHyb":
                    url = MapTypeURLs["YahooHybURL"];
                    break;
                case "YahooInMap":
                    url = MapTypeURLs["YahooInMapURL"];
                    break;
                case "YahooInHyb":
                    url = MapTypeURLs["YahooInHybURL"];
                    break;
                case "OpenStreetMap":
                    url = MapTypeURLs["OpenStreetMapURL"];
                    break;
                case "OSMARender":
                    url = MapTypeURLs["OSMARenderURL"];
                    break;
                case "OpenAerialMap":
                    url = MapTypeURLs["OpenAerialMapURL"];
                    break;
                case "OpenCycleMap":
                    url = MapTypeURLs["OpenCycleMapURL"];
                    break;
            }
          
            // Edited by Shustrik - added variables for configuration settings other than Google
            string quadcode = "";
            for (int i = (int)zoom - 1; i >= 0; i--)
                quadcode = quadcode + (((((y >> i) & 1) << 1) + ((x >> i) & 1)));
            url = url.Replace("{X}", x.ToString());
            url = url.Replace("{Y}", y.ToString());
            url = url.Replace("{Z}", ((int)zoom).ToString());
            url = url.Replace("{ZOOM}", ((int)zoom).ToString());
            url = url.Replace("{QUAD}", quadcode);
            url = url.Replace("{YAHOO_Y}", (((1 << ((int)zoom)) >> 1) - 1 - y).ToString());
            url = url.Replace("{YAHOO_ZOOM}", ((int)zoom + 1).ToString());
            url = url.Replace("{YAHOO_ZOOM_2}", (17 - (int)zoom + 1).ToString());
            url = url.Replace("{OAM_ZOOM}", (17 - (int)zoom).ToString());
            url = url.Replace("{GOOG_DIGIT}", ((x + y) & 3).ToString());
            url = url.Replace("{GOOG_QUAD}", GetQuadtreeFromXYZoom(x, y, zoom));
            url = url.Replace("{MS_DIGITBR}", ((((y & 1) << 1) + (x & 1)) + 1).ToString());
            url = url.Replace("{MS_DIGIT}", ((((y & 3) << 1) + (x & 1))).ToString());
            url = url.Replace("{Y_DIGIT}", ((x + y + zoom) % 3 +1).ToString());
            url = url.Replace("{GALILEO}", "Galileo".Substring(0, ((3 * x + y) & 7)));
            // support old style {} vars
            url = url.Replace("QQQQ", GetQuadtreeFromXYZoom(x,y,zoom));
            url = url.Replace("XXXX", x.ToString());
            url = url.Replace("YYYY", y.ToString());
            url = url.Replace("ZZZZ", (17 - (int)zoom).ToString());
            url = url.Replace("{OSM_ZOOM}", ((int)zoom).ToString());
            url = url.Replace("{MS_QUADCODE}", quadcode);
            url = url.Replace("*", ((x+y+zoom) %4).ToString());
            return url;
        }
        static void Main(string[] args)
        {
            string url = BuildUrl("GoogleMap", 1, 1, 1);
            //return <a href="http://mt2.google.com/vt/lyrs=m@121&hl=en&x=1&y=1&z=1&s=Gali">http://mt2.google.com/vt/lyrs=m@121&hl=en&x=1&y=1&z=1&s=Gali</a>
        }
    }
}

例子中取出 google map ,在 zoom=1 及 x=1,y=1是的图片。
http://mt2.google.com/vt/lyrs=m@121&hl=en&x=1&y=1&z=1&s=Gali

下载工具  http://www.mapdigit.com/forum/viewthread.php?tid=43&extra=page%3D1 中文说明参见离线地图生成工具结构图离线地图生成工具使用方法

 

Android坦克大战游戏设计解析八

这是本系列最后一篇,最后就是将整个程序组成起来。坦克大战游戏中有六个用户界面:
音效设置
开始界面
选择关卡界面
游戏主界面
分数界面
游戏结束界面
按照Android程序一般设计方法,一般一个界面对应一个Activity。这样就需要设计6个Activity子类对实现各个界面。
在移植的过程,这里采用了一个简单的方法,采用一个Activity对就于 Java ME中的Midlet。
主Activity采用FrameLayout

<?xml version=”1.0″ encoding=”utf-8″?>
<FrameLayout xmlns:android=”http://schemas.android.com/apk/res/android
    android:id=”@+id/mainwindow”
    android:layout_width=”fill_parent”
    android:layout_height=”fill_parent”
    >
</FrameLayout>
FrameLayout 可以将它其中的其它View象扑克牌一样叠放在一起,这样将六个界面都放在主Activity的FrameLayout中,开始将它们都设置为不可见,需要显示某个界面时,设为可见并放在最前面,也就实现了多个用户界面。

public static void setCurrentScreen(View newScreen){
 currentScreen.setVisibility(View.INVISIBLE);
 currentScreen=newScreen;
 currentScreen.setVisibility(View.VISIBLE);
 theDisplay.bringChildToFront(currentScreen);
}

就是用于屏幕切换。
另外,有于程序主要移植于JavaME,并且主要目的是为了了解Android 平台,和 JavaME版相比不够完善,但基本功能是实现了,如有兴趣的可以进一步完善。

代码下载 Android版坦克大战    http://www.guidebee.info/download/android/battlecity/AndroidBattleCity.zip

                  Java ME版坦克大战 http://www.guidebee.info/download/android/battlecity/BattleCityJavaME.zip

 

Android坦克大战游戏设计解析七

本篇介绍坦克大战游戏中的主角,坦克类。游戏中坦克种类有多种,但主要特性大同小异。下图为游戏中定义的坦克类层次图。

Tank为所有坦克类的基类,它定义了几个主要的方法
  think() 思考,如有AI,算法在这里实现,对于简单坦克SimpleTank,可能随机选择一步,而对SmartTank来说,向靠近玩家坦克的方向前进一步。
  drive()  根据Think决定前进一步
 shoot() 根据当前条件决定发射一棵子弹。PlayerTank由玩家和可同时发射的子弹来控制,Enemy坦克一般随机控制是否要发射子弹。
基类每个游戏帧的操作如下

/**
 * Operation be done in each tick.
 */
public void tick(){
 if(isVisible()){
  think();
  drive();
  shoot();
 }
}

派生类中PlayerTank 和 SmartTank逻辑相对复杂一些,FastTank,和HeavyTank都是SimpleTank的子类,FastTank行驶速度较快,而HeavyTank可以承受多次子弹才会被击毁。
PlayerTank中需要处理玩家按键事件,用于控制上下左右以及发射子弹,还要处理升级功能,如吃到增加宝贝。它的
public void upgrade(Powerup powerup)用于处理升级功能。
而在SmartTank的Think方法,它要根据玩家坦克当前位置算出下一步的方向,以便可以不断向玩家坦克靠近,并发射子弹试图击毁玩家坦克。
这些坦克类都定义在om.pstreets.game.battlecity.actors.tank,代码中有较详细的注释,这里不详细一一说明了。

 

Android坦克大战游戏设计解析六

本篇介绍坦克大战游戏除坦克之外的几个角色。
1. Bullet 子弹类        坦克发射出的子弹在游戏中飞行
2.Explosion 爆炸类   子弹击中子弹,障碍物,或是坦克显示爆炸
3. Powerup 增强宝贝类  星星,加坦克,定时器等
4. Score 分数类。         击中坦克或是攻取增强宝贝,加分显示,分数有100,200,300,400,500,击中不同坦克分数不同。
为直观起见,参见下图,红圈里从上到下分别是Bullet, Powerup, Explosion, Score.

子弹类,屏幕中所有显示子弹从一个子弹池BULLET_POOL中取出,子弹有方向,速度,及强度等属性,高强度的子弹可以击破石块。
它每个游戏帧所要完成的操作如下。

/**
 * Operation be done in each tick.
 */
public void tick(){
 if (!isVisible() || direction==BattleField.NONE)
  return;
 // Move the bullet.
 move(dx, dy);
 int x = getRefPixelX();
 int y = getRefPixelY();
 PlayerTank playerTank=(PlayerTank)Tank.getTank(0);
 //outside the battle field, hitting the border
 if (x <= 0 || x >= battleField.getWidth() || y <= 0
   || y >= battleField.getHeight()) {

  //this is to avoid explosition outside the battlefield.
  if(x<=0) x=0;
  if(x >= battleField.getWidth()) x= battleField.getWidth();
  if(y<=0) y=0;
  if(y>= battleField.getHeight())y=battleField.getHeight();
  setPosition(x,y);
  explode();
  return;
 }
 
 // See if it hit a tank.
 if (friendly) {
  // See if it hit an enemy tank.
  for (int i = 1; i < Tank.POOL_SIZE; i++) {
   EnemyTank enemy = (EnemyTank)Tank.getTank(i);
   if (enemy!=null && enemy.isVisible() &&
     collidesWith(enemy, false)) {
    enemy.explode();
    explode();
    return;
   }
  }
 } else {
  // See if it hit player tank.
  
  if (collidesWith(playerTank, false)) {
   playerTank.explode();
   explode();
   return;
  }
 }
 
 //check to see if hit player's home
 if(Powerup.isHittingHome(this)){
  //TODO: Game Over
  explode();
  return;
 }
 // See if it hit a wall.
 if (battleField.hitWall(x, y, strength)) {
  explode();
  return;
 }
 
 // See if it hit another bullet.
 for (int i = 0; i < POOL_SIZE; i++) {
  Bullet anotherBullet=BULLET_POOL;
  if(this!=anotherBullet && anotherBullet.isVisible()){
   if (collidesWith(anotherBullet, false)) {
    explode();
    BULLET_POOL.explode();
    return;
   }
  }
 }
}

要判断是否击中墙壁,对方坦克,或是对方子弹,是否击中“家”,如果有,则爆炸,如都没有,则同方向前行一步。
爆炸类,子弹击中障碍物(墙,子弹,坦克)时显示爆炸动画效果。它有两种一个是大爆炸,一个是小爆炸。
它每个游戏帧所要完成的操作比较简单,每步显示一个动画帧,直到显示完。

/**
 * Operation be done in each tick.
 */
public void tick() {
 if (!isVisible())
  return;
 nextFrame();
 if (getFrame() == 0){
  setVisible(false);
 }
}

增强宝贝类,有多种,无敌,加坦克,地雷,定时器等。不同的增强宝贝可以使玩家获得不同的能力,玩过坦克大战游戏的人都比较熟悉。
在游戏进行中, 会不时或者当玩家打中红色坦克时,会有游戏中随机出现不同增强宝贝。
它每个游戏帧所要完成的操作如下:
如果玩家得到“无敌”增强功能时,“无敌”具有一定的时效性,需要判断无敌是否过时,其它时候则让该增强宝贝有闪烁效果,引起玩家注意。

/**
 * Operation be done in each tick.
 */
public void tick(){
 if(type==NOTHING || !isVisible()) return;
 long tickTime = System.currentTimeMillis();
 long refreshPeriod=MILLIS_PER_TICK;
 
 //invulnerable powerup is controlled by the player tank.
 if(type!=INVULNERABLE &&type!=HOME && type!=HOME_DESTROYED){
  if(tickTime-startTime>livePeriod){
   setFrame(NOTHING);
   setVisible(false);
   return;
  }
 }else{
  refreshPeriod=MILLIS_PER_TICK/10;
 }
 if(timeTaken>=refreshPeriod){
  showNextFrame=!showNextFrame;
  if(type==INVULNERABLE){
     if(showNextFrame){
    setFrame(0);
   }else{
    setFrame(1);
   }
  }else if(type==HOME || type==HOME_DESTROYED){
     setFrame(type);
  }else{
   if(showNextFrame){
    setFrame(type);
   }else{
    setFrame(NOTHING);
   }
  }
  timeTaken = System.currentTimeMillis() - tickTime;
 } else{
  timeTaken+=1;
 }
}

最后一个是分数类,比较简单,它每个游戏帧所要完成的操作如下

/**
 * Operation be done in each tick.
 */
public void tick(){
 if(isVisible()){
  long tickTime = System.currentTimeMillis();
  if(startTime>0){
   if(tickTime-startTime>livePeriod){
    setVisible(false);
    startTime=0;
    return;
   }
  }
 }
}

在屏幕上显示几秒种后消失。

 

Android坦克大战游戏设计解析五

本篇介绍坦克大战游戏场景类BattleField的设计思路。

BattleField 是Game API中TiledLayer的子类。TiledLayer实现了由小的图形(称为tile)拼接成大的背景,坦克大战游戏的背景是由砖块,石块,树林,水面,雪地等小的图片拼接而成。TiledLayer可以很容易的实现这种类型的背景,包括水面波汶的动态效果。

下面的图片是一个简单由多个小tile组成的游戏背景。

理论上TiledLayer可以实现无限大的背景。为简单起见坦克大战游戏中采用了半随机的方法来生成游戏背景,同时也提供了从文件读取游戏背景的方法,如果想完全复现FC的每一关,可以使用地图编辑器或是文本编辑器生成文件,然后从文件中读取背景。
这里给出一个关口的例子文件。

0000000000000
0202020202020
0202020202020
0202026202020
0202020202020
0000020200000
6022000002206
0000020200000
0202020202020
0202020202020
0202000002020
0000000000000

其中0代表空白,1代表雪地,2代表砖块,3代表树林,4,5代表水面,6代表石块。由于每个tile比较小,这里每个数据代表一个2X2的区块,下面代表实现从文件生成游戏背景

/**
 * Read the battle from an input stream.
 * @param is input stream stores the battle field information.
 */
private void readBattlefield(java.io.InputStream is) throws IOException {
 int c = -1;
 int x0 = (WIDTH_IN_TILES-NUMBER_IN_TILES)/2;
 int y0 = (HEIGHT_IN_TILES-NUMBER_IN_TILES)/2;
 int x=0,y=0;
 while ((c = is.read()) != -1 && y < NUMBER_IN_TILES) {
  switch (c) {
   case ' '://empty
   case '0':
    duplicateCell(x+x0, y+y0, 0);x+=2;
    break;
   case '1'://snow field
    duplicateCell(x+x0, y+y0,SNOW);x+=2;
    break;
   case '2'://brick wall
    duplicateCell(x+x0, y+y0, BRICK_WALL);x+=2;
    break;
   case '3'://forest
    duplicateCell(x+x0, y+y0, FOREST);x+=2;
    break;
   case '4':
   case '5'://water
    duplicateCell(x+x0, y+y0, -1 - ((x ^ y) & 1));x+=2;
    break;
   case '6': //Concrete wall
    duplicateCell(x+x0, y+y0, CONCRETE_WALL);x+=2;
    break;
   case '\n'://new line
    y+=2;
    x = 0;
    break;
   default:
  }
 }
}

实现在游戏中采用了半随机的方法,这样游戏关卡可以有无限多,半随机是指一半的砖块是从HZK16(16点阵汉字库)读取一个汉字,用其点阵显示为砖块,其它雪地,树林等采用随机数随机分布在游戏场景中。前几关的汉字是“引路蜂软件”。

坦克大战游戏中还会随机出现一些增强法宝,比如定时器可以让敌方坦克停止运动,地雷可以使屏幕中敌方坦克全部炸毁。铁锹可以让“家”全部被石块包住从而使敌方子弹无法打穿。星星可以让已方坦克加速,同时发射的子弹数增加并增加打击能力(比如可以打穿石块甚至树林等等)。

所以BattleField中同时也定义了显示PowerUp(增强法宝),初始化敌方坦克位置(一般是从最上方的左,中,右依次出现)。另外还要判断某个位置坦克是否可能通过(有砖块,石头,水面不能通过),雪地要加速,其它地方可以通行。另外还要判断子弹是否击中墙壁(子弹击中墙壁后要爆炸等等)。

最后来看看它的tick()中主要做些什么

public void tick() {
 int tickState = (tickCount++ >> 3); // slow down x8
 int tile = tickState % 2;
 setAnimatedTile(-1 - tile, waterFrames[tile][(tickState % 4) / 2]);
 if(concreteWallStartTime>0){
  long tickTime=System.currentTimeMillis();
  if(tickTime-concreteWallStartTime>concreteWallPeriod){
   makeHomeBrickWall();
   concreteWallStartTime=0;
  }
 }
}

它主要显示水面的动态效果,如果当前需要显示石块做的家,则将相应的cell中填入石块,由于宝贝有时效性,到了一定时间后将“家”变回普通砖块做成。