J2ME實踐之地圖篇

最近三個星期利用業餘時間開發了一款J2ME橫向滾軸的2D FPS遊戲,自我感覺項目不是很成功,最主要的原因是圖片太多。但是通過實踐,還是收穫不少。下面就地圖處理髮表一點淺見。

javax.microedition.lcdui.game.TiledLayer是一個保存和繪製地圖的好工具,通過腳本的方式可以將地圖信息轉化爲數字信息保存在TiledLayer對象中(實際上TiledLayer內部採用是數組的方式來保存地圖的數字化信息)。

上面這張地圖中每一個地圖元素的尺寸爲32×32,爲此我們可以對其進行編號:

這樣,一個編號對應的就是一個地圖元,顯然下面這些數字:

00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00
00|00|00|00|00|00|00|00|00|00|04|05|06|07|00|00|00|00|00|00
00|00|00|00|00|04|05|06|07|00|14|15|16|17|00|00|00|00|00|00
34|35|35|36|00|14|15|16|17|00|00|00|00|00|34|35|35|35|35|36
37|38|38|39|00|00|00|00|00|00|00|00|00|00|37|38|38|38|38|39

對應下面的地圖:

將地圖數字化以後,可以在地圖腳本文件中加入地圖的尺寸信息(長度|寬度),以上面的地圖爲例可以在第一行加入20|6,這樣在讀取第一行之後我們就知道需要分配多大的數組以及用這個尺寸初始化TiledLayer對象。

下面是一個腳本抽象類,所有類型的腳本(地圖、怪物、物品)都繼承自它。

package game;

import java.io.*
;

public abstract class
 Script 
{    
    InputStreamReader input;
        
    
protected void
 close() 
    
{
        
if (input != null
)
        
{
            
try {input.close();} catch (Exception e) {}

            input 
= null;
        }

    }

        
    
protected String readLine()
    
{
        
if (input == null{return null;}

        
        
int temp;
        StringBuffer buffer 
= new
 StringBuffer();
        
        
try
 
        
{
            
while ((temp = input.read()) != 13
)
            
{
                
if ((int)temp == -1
)
                
{
                    close();
                    
break
;
                }

                
else if ((int)temp != 10)
                
{
                    buffer.append((
char
)temp);
                }

            }

        }
 catch (Exception e) { close(); }
        
        
return buffer.toString();    
    }

    
    
protected String[] readArrayLine(char delimit)
    
{
        String line;
        String[] array;
        StringBuffer buffer;
        
int
 index, count;
        
char
 c;
        
        
// Count number of items in the array

        line = readLine();
        
        
if (line.length() == 0
)
        
{
            array 
= new String[1
];
            array[
0= ""
;
        }

        
        index 
= 0;
        count 
= 0
;
        
while (index <
 line.length())
        
{
            
if (line.charAt(index++== delimit) {count++;}

        }

        
        
// Parse items into the array
        array = new String[count+1];
        buffer 
= new
 StringBuffer();
        index 
= 0
;
        count 
= 0
;
        
while (index <
 line.length())
        
{
            c 
= line.charAt(index++
);
            
if (c ==
 delimit)
            
{
                array[count
++=
 buffer.toString();
                buffer 
= new
 StringBuffer();
            }

            
else
            
{
                buffer 
=
 buffer.append(c);
            }

        }

        array[count
++= buffer.toString();
        
        
return
 array;
    }

}

下面是專門負責讀取地圖腳本的代碼:

package game;

import java.io.*
;

public class MapFile extends
 Script
{
    
protected int
 iMapRow;
    
protected int
 iMapCol;
        
    
public int[] Load(int
 level)
    
{
        input 
= new InputStreamReader(getClass().getResourceAsStream("/script/map/level"+level+".map"
));
        
int cnt = 0
;
        String[] size 
= readArrayLine('|'
);
        String[] mapline;
        
if(size.length < 2
)
        
{
            System.out.println(
"map size error!"
);
            
return null
;
        }

        iMapCol 
= Integer.parseInt(size[0]);
        iMapRow 
= Integer.parseInt(size[1
]);
        
int[] map = new int[iMapCol*
iMapRow];
        
while(input != null
)
        
{
            mapline 
= readArrayLine('|'
);
            
if(mapline.length <
 iMapCol)
            
{
                System.out.println(
"map column error!"
);
                
return null
;                
            }

            
for (int n = 0; n < mapline.length; n++)
                map[cnt
++=
 (Integer.valueOf(mapline[n])).intValue();
        }

        close();
        
return map;
    }

    
    
public int getCol()
    
{
        
return
 iMapCol;
    }

    
    
public int getRow()
    
{
        
return
 iMapRow;
    }

}

最後在遊戲渲染主類中加入載入地圖代碼:

    protected TiledLayer createMap(int level)
    
{
        Image img 
= null
;
        
try

        
{
            img 
= Image.createImage("/res/map/map.png"
);
        }
catch(java.io.IOException e) {System.out.println("createMap"+e);}
        
int[] map = mapfile.Load(level);
        TiledLayer tl 
= new TiledLayer(mapfile.getCol() , mapfile.getRow() , img , 32 , 32
);
        
for(int i = 0;i < map.length;i++
)
        
{
            
int col = i %
 mapfile.getCol();
            
int row = (i - col) /
 mapfile.getCol();
            tl.setCell(col , row , map[i]);
        }

        
return tl;
    }

遊戲渲染最好能夠由LayerManager來管理,通過其append方法將TiledLayer對象加入其中,在渲染方法中加入:

LayerManangerObject.setViewWindow(PlayerObject.iPosX , StartY , ViewWidth , ViewHeight);
LayerManangerObject.paint(GraphicsObject , StartX , StartY);

在setViewWindow中,將玩家的橫座標作爲視口的起始x座標,只要玩家走動,就會有橫向滾軸的效果。

發佈了69 篇原創文章 · 獲贊 2 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章