程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2ME >> J2ME游戲之旅——場景繪制

J2ME游戲之旅——場景繪制

編輯:J2ME
前面我已經完成了直升飛機,現在到了整個游戲中最關鍵的部分,場景生成。
有專門的場景類Layer,其派生類TileLayer可以完成用圖塊拼合成場景的工作。先看看TiledLayer是怎麼使用的
Constructor Summary TiledLayer(int columns, int rows, Image image, int tileWidth, int tileHeight)
          Creates a new TiledLayer.

 int createAnimatedTile(int staticTileIndex)
          Creates a new animated tile and returns the index that refers to the new animated tile.  void fillCells(int col, int row, int numCols, int numRows, int tileIndex)
          Fills a region cells with the specific tile.  int getAnimatedTile(int animatedTileIndex)
          Gets the tile referenced by an animated tile.  int getCell(int col, int row)
          Gets the contents of a cell.  int getCellHeight()
          Gets the height of a single cell, in pixels.  int getCellWidth()
          Gets the width of a single cell, in pixels.  int getColumns()
          Gets the number of columns in the TiledLayer grid.  int getRows()
          Gets the number of rows in the TiledLayer grid.  void paint(Graphics g)
          Draws the TiledLayer.  void setAnimatedTile(int animatedTileIndex, int staticTileIndex)
          Associates an animated tile with the specifIEd static tile.  void setCell(int col, int row, int tileIndex)
          Sets the contents of a cell.  void setStaticTileSet(Image image, int tileWidth, int tileHeight)
          Change the static tile set.

使用的一般步驟
1。先調用creataAnimatedTile構造函數,columns 和rows指的是屏幕上橫向和縱向分別由多少圖塊,這點一定要記住,image是png圖片,用相同大小圖塊構成,tileWidht和tileHeight則定義了圖塊的大小。
在我們這個游戲裡,場景要用的圖塊只要一種就可以了。我們重復往tileLayer裡面填這個圖塊,就可以構成復雜的場景,用隨機來模擬地形的變化

2。構造一場景矩陣。為了模擬場景滾動,需要一個矩陣來完成這個工作,這樣定義它int[][] gameMap=new int[rows][columns],該矩陣中存儲圖塊的編號,對應image中的圖塊,從1開始,0則代表此單元在tiledLayer上是透明的。然後我們使用一個二重循環,調用setCell(int col,int row,int tileIndex)來完成將場景矩陣映射到屏幕上去的工作。我們可以發現,如果按一定規律對矩陣裡的內容進行移動,就可以達到場景滾動的效果,這在我下面給出的源代碼中可以看到,同時,如果我們只要按行或者按列來滾動場景,實際上只要專門准備一個對應於 行或者列的下標數組,循環的滾動下標就可以了,而不用非常低效地一點一點交換矩陣中的元素。我在Terrain.Java中用了int mapIndex[]來做這個工作。

3.每一個游戲周期調用TiledLayer的paint方法,繪出矩陣。

我擴展了TiledLayer類為Terrain類,以滿足我們這個游戲的需要。

附加模塊:碰撞檢測,每個周期都檢測飛機所占據的單元是否跟磚塊所占據的單元重疊即可。使用public boolean collides()實現。

源代碼如下:

import Javax.microedition.lcdui.game.*;
import Javax.microedition.lcdui.Image;
import Java.util.Random;

public class Terrain extends TiledLayer{
   
    public int milemeter;
   
    public int speed;          // it is public so we could set the speed in main menu;
   
    private int timestamp;     // 時間戳,用來控制調整場景更新周期
   
    private int tileWidth,tileHeight;
   
    private int [][] gameMap = null;
   
    private int screenWidth,screenHeight;
   
    private int wallHeight;
   
    private int Rows, Cols;
   
    private Random random = null;        // 隨機數類
   
    private int layerTop;                             // 保存場景在屏幕上的相對位置,用於平滑滾動場景。
   
    private int [] indexMap = null;
   
    private boolean up_down;              // 地勢是上升還是下降
   
    private int alterSpeed;                    //地形變化速度
   
    private int alterExtent;                     //地形變化持續周期
   
    private int upBound,lowBound,wallPos;   //當前地形上界和下界,牆壁的位置
   
    private Helicopter player;                            //保存helicopter的引用,檢測碰撞時用到
   
    public Terrain(int columns,int rows,Image image,int tileWidth,int tileHeight,Helicopter player){
       
        super(columns,rows,image,tileWidth,tileHeight);  //TiledLayer構造函數
       
        this.player = player;
       
        speed = 0 ; //////////////
       
        random = new Random();
       
        layerTop = -1* tileHeight;
       
        speed = 0;
        timestamp = 0;
       
        this.tileHeight = tileHeight;
        this.tileWidth = tileWidth;
       
        screenWidth = getWidth();
        screenHeight = getHeight();
       
        wallHeight = screenWidth / 4 /tileWidth;
       
        Rows = rows;
        Cols = columns;
       
       
        indexMap = new int[Rows];
        for(int i=0;i<Rows;i++)indexMap[i] = i;
       
        gameMap = new int[rows][columns];
        for(int i=0;i<Rows;i++){
            for(int j=0;j<Cols;j++){
                if(j<(Cols/7) || (Cols-j)<=(Cols/7))              // 初始化場景矩陣,初始狀況下上下邊都有等厚度的牆壁
                    gameMap[i][j]=1;
            }
        }
       
        for(int i=0;i<Rows;i++){
            for(int j=0;j<Cols;j++){
                this.setCell(j,i,gameMap[indexMap[i]][j]);  // 將場景矩陣映射到TiledLayer上
            }
        }
       
        alterSpeed = alterExtent = 0;
       
        upBound = Cols/7;
        lowBound = Cols-Cols/7;
       
    }
   
    public void update(){                                     // 更新場景
        if (++timestamp > speed) {                     // 判斷是否達到跟新周期
            timestamp = 0;
            if(layerTop == 0){
                milemeter += 1;
                for(int i=upBound+1;i<lowBound;i++)gameMap[indexMap[Rows-1]][i] = 0;
                if(alterExtent > 0){
                   
                    if(up_down == true){upBound -= alterSpeed;lowBound -= alterSpeed;}
                    else {upBound += alterSpeed; lowBound += alterSpeed;}
                    if(upBound<0){upBound += alterSpeed;lowBound+= alterSpeed; }
                    if(lowBound >= Cols-1){upBound -= alterSpeed;lowBound -= alterSpeed; }
                    for(int i=0;i<Cols;i++){
                        if(i<=upBound || i>=lowBound)
                            gameMap[indexMap[Rows-1]][i] = 1;
                    }
                    alterExtent--;
                }
                else {                   //產生新場景,存到已經滾出屏幕的那一列中,然後滾動下標,使其映射到屏幕最上一列
                    alterExtent = random.nextInt()%10; //產生地勢變化持續時間,為正則地勢上升,反之下降
                    if(alterExtent == 0)alterExtent=5;      //避免時間為0的情況
                    if(alterExtent > 0){
                        up_down = true;
                    }
                    else {
                        up_down = false;
                        alterExtent *= -1;
                    }
                    alterSpeed = Math.abs(random.nextInt())%3+1;       // 隨即生成地勢變化速度, 1~3
                    return;
                }
               
                // produces the wall barrIEr
                if(milemeter % 10 == 0){                                                     //隔定長距離產生一個牆壁
                    wallPos  = Math.abs(random.nextInt())%(Cols-wallHeight);
                    for(int i=0;i<Cols;i++){
                        if(i==wallPos){
                            for(int j=0;j<wallHeight;j++)gameMap[indexMap[Rows-1]][i+j]=1;
                            break;
                        }
                    }
                }
                //:~ produce the barrIEr
               
                // 調整場景矩陣的下標數組,實現滾屏
                for(int i=0;i<Rows;i++){
                    indexMap[i]=indexMap[i]-1;
                    if(indexMap[i] == -1)indexMap[i] = Rows-1;
                }
                //:~ row mapping
               
                // apply the new matrix to the tiledLayer
                for(int i=0;i<Rows;i++){
                    for(int j=0;j<Cols;j++){
                        this.setCell(j,i,gameMap[indexMap[i]][j]);
                    }
                }
                //:~ apply
               
               //將滾動映射到TiledLayer上
                layerTop = -1 * tileHeight;
                this.setPosition(0,layerTop);
                //:~ update
               
            }
            else this.setPosition(0,layerTop++);
        }
    }
   
    public boolean collides(){             //碰撞檢測
        for(int i=player.getPlayerRect().top / tileHeight;i<=player.getPlayerRect().bottom / tileHeight;i++){
            for(int j=player.getPlayerRect().left / tileWidth;j<=player.getPlayerRect().right / tileWidth;j++){
                if( gameMap[indexMap[i]][j] == 1){
                    return true;
                }
            }
        }
        return false;
    }

}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved