Có một trò chơi loại giải đố trong các ví dụ demo của NetBeans. Đó là trò đẩy hộp. Trò chơi này cho bạn ví dụ về load dữ liệu map từ file text. Nhưng thứ mà tôi nhớ nhất đó là code game đó làm tôi hoa hết cả mắt, heh.
Sau đây là giải pháp của tôi về việc này. Thay vì load dữ liệu map từ text file chúng ta sẽ load từ file dạng nhị phân.
Bài này sử dụng tiếp code của bài trước Dùng lớp TiledLayer hiển thị tilemap. Nếu chưa học qua bạn nên bắt đầu từ bài đó trước và hãy nắm chắc trước khi sang bài này.
Bạn hãy down map dạng SMP sau về. Đó là map tạo từ phần mềm Simple Tile Map Editor của Devlin.
samplemap.smp (155 bytes) - Download
Tạo folder maps trong folder src và save map vào đó.
Bạn có thể mở ra xem, sửa map bằng phần mềm của Devlin, download tại đây.
Để xem trước map, bấm nút Open và chọn đến file map trên bạn vừa down về. Kế tiếp, chọn tileset1.png là file tileset của bạn (nếu chưa biết là gì thì hãy đọc bài trước để biết thêm chi tiết). Bạn sẽ thấy như sau:
Khi đã xong mọi việc, bắt tay vào chỉnh sửa code lớp clsCanvas. Thêm phương thức sau vào trước phương thức loadBlockMap( ):
Giờ ta thay lời gọ phương thức loadBlockMap( ) trong phương thức load( ) bằng loadBlockMapFile( )
Bạn chạy thử chương trình sẽ thấy như sau:
Map này chỉ khác với ví dụ trước ở vị trí chướng ngại vật và màu sắc, không có gì đáng kể.
Sau đây là clsCanvas hoàn chỉnh cho các bạn tham khảo:
Bạn cũng có thể tìm các phần mềm tạo tilemap trên mạng, thậm chí có thể save dữ liệu map vào file xml, vân vân...
Link vài phần mềm làm map:
Cuối cùng, bạn cũng có thể dùng chức năng Game Builder trong NetBeans 6 và gói Mobility.
Chúc các bạn thành công !!
Sau đây là giải pháp của tôi về việc này. Thay vì load dữ liệu map từ text file chúng ta sẽ load từ file dạng nhị phân.
Bài này sử dụng tiếp code của bài trước Dùng lớp TiledLayer hiển thị tilemap. Nếu chưa học qua bạn nên bắt đầu từ bài đó trước và hãy nắm chắc trước khi sang bài này.
Bạn hãy down map dạng SMP sau về. Đó là map tạo từ phần mềm Simple Tile Map Editor của Devlin.
samplemap.smp (155 bytes) - Download
Tạo folder maps trong folder src và save map vào đó.
Bạn có thể mở ra xem, sửa map bằng phần mềm của Devlin, download tại đây.
Để xem trước map, bấm nút Open và chọn đến file map trên bạn vừa down về. Kế tiếp, chọn tileset1.png là file tileset của bạn (nếu chưa biết là gì thì hãy đọc bài trước để biết thêm chi tiết). Bạn sẽ thấy như sau:
Khi đã xong mọi việc, bắt tay vào chỉnh sửa code lớp clsCanvas. Thêm phương thức sau vào trước phương thức loadBlockMap( ):
public TiledLayer getMap(String fpath, Image ftiles){ TiledLayer tMap = null; try { // open the file InputStream is = this.getClass().getResourceAsStream(fpath); DataInputStream ds = new DataInputStream(is); try { // skip the descriptor ds.skipBytes(8); // read map width int mW = ds.readByte(); // read map height int mH = ds.readByte(); // read tile width int tW = ds.readByte(); // read tile height int tH = ds.readByte(); // create a new tiled layer tMap = new TiledLayer(mW, mH, ftiles, tW, tH); // loop through the map data for (int rCtr = 0; rCtr < mH; rCtr++){ for (int cCtr = 0; cCtr < mW; cCtr++){ // read a tile index byte nB = ds.readByte(); // if tile index is non-zero // tile index 0 is usually a blank tile if (nB > 0) { // assign (tile index + 1) to the current cell // TiledLayer objects start tile index at 1 // instead of 0 tMap.setCell(cCtr, rCtr, nB + 1); } } } } catch (Exception ex) { tMap = null; System.err.println("map loading error : " + ex.getMessage()); } // close the file ds.close(); ds = null; is = null; } catch (Exception ex) { tMap = null; System.err.println("map loading error : " + ex.getMessage()); } // return the newly created map or null if loading failed return tMap; }
Bấm Alt+Shift+F nếu dùng NetBeans để import các statements còn thiếu.
Chúng ta thêm một phương thức nữa là loadBlockMapFile( ) dùng getMap( ) để load dữ liệu map lên và khởi tạo cho tiled layer blockMap. Việc này giúp bạn bảo vệ phương thức loadBlockMap( ) để tham khảo sau. Thêm đoạn code sau vào dưới phương thức loadBlockMap( ):
public void loadBlockMapFile(){ //initialize blockMap blockMap = getMap("/maps/samplemap.smp", imgTileset); }
Giờ ta thay lời gọ phương thức loadBlockMap( ) trong phương thức load( ) bằng loadBlockMapFile( )
loadRoadMap();
loadBlockMapFile();
}
Bạn chạy thử chương trình sẽ thấy như sau:
Map này chỉ khác với ví dụ trước ở vị trí chướng ngại vật và màu sắc, không có gì đáng kể.
Sau đây là clsCanvas hoàn chỉnh cho các bạn tham khảo:
package MyGame;
import java.io.DataInputStream;
import java.io.InputStream;
import java.util.Random;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.lcdui.game.TiledLayer;
public class clsCanvas extends GameCanvas implements Runnable {
// key repeat rate in milliseconds
public static final int keyDelay = 250;
//key constants
public static final int upKey = 0;
public static final int leftKey = 1;
public static final int downKey = 2;
public static final int rightKey = 3;
public static final int fireKey = 4;
//key states for up, left, down, right, and fire key
private boolean[] isDown = {
false, false, false, false, false
};
//last time the key changed state
private long[] keyTick = {
0, 0, 0, 0, 0
};
//lookup table for key constants :P
private int[] keyValue = {
GameCanvas.UP_PRESSED, GameCanvas.LEFT_PRESSED,
GameCanvas.DOWN_PRESSED, GameCanvas.RIGHT_PRESSED,
GameCanvas.FIRE_PRESSED
};
private boolean isRunning = true;
private Graphics g;
private midMain fParent;
private Image imgVan;
private Sprite Van;
private int vanSpeed = 2;
private Image imgTileset;
private TiledLayer roadMap;
private TiledLayer blockMap;
/** Creates a new instance of clsCanvas */
public clsCanvas(midMain m) {
super(true);
fParent = m;
setFullScreenMode(true);
}
public void start(){
Thread runner = new Thread(this);
runner.start();
}
public void loadRoadMap(){
//initialize the roadMap
roadMap = new TiledLayer(11, 13, imgTileset, 16, 16);
// Create a new Random for randomizing numbers
Random Rand = new Random();
//loop through all the map cells
for (int y = 0; y < 13; y++){
for (int x = 0; x < 11; x++){
// get a random tile index between 2 and 5
int index = (Math.abs(Rand.nextInt()>>>1) % (3)) + 2;
// set the tile index for the current cell
roadMap.setCell(x, y, index);
}
}
Rand = null;
}
public void loadBlockMap(){
// define the tile indexes to be used for each map cell
byte[][] blockData = {
{10, 8 , 7 , 6 , 10, 9 , 8 , 7 , 6 , 10, 9 },
{6 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 8 },
{7 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 7 },
{8 , 0 , 0 , 10, 6 , 0 , 0 , 7 , 0 , 0 , 6 },
{9 , 0 , 0 , 0 , 0 , 0 , 0 , 8 , 0 , 0 , 10},
{10, 0 , 0 , 0 , 0 , 0 , 0 , 9 , 0 , 0 , 9 },
{6 , 0 , 0 , 8 , 0 , 0 , 0 , 0 , 0 , 0 , 8 },
{7 , 0 , 0 , 7 , 0 , 0 , 0 , 0 , 0 , 0 , 7 },
{8 , 0 , 0 , 6 , 0 , 0 , 0 , 10, 0 , 0 , 6 },
{9 , 0 , 0 , 10, 0 , 0 , 7 , 6 , 0 , 0 , 10},
{10, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 9 },
{6 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 8 },
{7 , 8 , 9 , 10, 6 , 7 , 8 , 9 , 10, 6 , 7 }
};
//initialize blockMap
blockMap = new TiledLayer(11, 13, imgTileset, 16, 16);
//loop through all the map cells
for (int y = 0; y < 13; y++){
for (int x = 0; x < 11; x++){
// set the tile index for the current cell
// take note of the reversed indexes for blockData
blockMap.setCell(x, y, blockData[y][x]);
}
}
blockData = null;
}
public void loadBlockMapFile(){
//initialize blockMap from a binary file
blockMap = getMap("/maps/samplemap.smp", imgTileset);
}
public TiledLayer getMap(String fpath, Image ftiles){
TiledLayer tMap = null;
try {
// open the file
InputStream is = this.getClass().getResourceAsStream(fpath);
DataInputStream ds = new DataInputStream(is);
try {
// skip the descriptor
ds.skipBytes(8);
// read map width
int mW = ds.readByte();
// read map height
int mH = ds.readByte();
// read tile width
int tW = ds.readByte();
// read tile height
int tH = ds.readByte();
// create a new tiled layer
tMap = new TiledLayer(mW, mH, ftiles, tW, tH);
// loop through the map data
for (int rCtr = 0; rCtr < mH; rCtr++){
for (int cCtr = 0; cCtr < mW; cCtr++){
// read a tile index
byte nB = ds.readByte();
// if tile index is non-zero
// tile index 0 is usually a blank tile
if (nB > 0) {
//assign (tile index + 1) to the current cell
tMap.setCell(cCtr, rCtr, nB + 1);
}
}
}
} catch (Exception ex) {
tMap = null;
System.err.println("map loading error : " + ex.getMessage());
}
// close the file
ds.close();
ds = null;
is = null;
} catch (Exception ex) {
tMap = null;
System.err.println("map loading error : " + ex.getMessage());
}
// return the newly created map or null if loading failed
return tMap;
}
public void load(){
try{
// load the images here
imgVan = Image.createImage("/images/van.png");
imgTileset = Image.createImage("/images/tileset1.png");
}catch(Exception ex){
// exit the app if it fails to load the image
isRunning = false;
return;
}
// initialize the Sprite object
Van = new Sprite(imgVan, 18, 18);
// show the frame 1 - the second frame
Van.setFrame(1);
// move to 50, 50 (X, Y)
Van.setPosition(16, 16);
loadRoadMap();
loadBlockMapFile();
}
public void unload(){
// make sure the object gets destroyed
blockMap = null;
roadMap = null;
Van = null;
imgTileset = null;
imgVan = null;
}
public void checkKeys(int iKey, long currTick){
long elapsedTick = 0;
//loop through the keys
for (int i = 0; i < 5; i++){
// by default, key not pressed by user
isDown[i] = false;
// is user pressing the key
if ((iKey & keyValue[i]) != 0){
elapsedTick = currTick - keyTick[i];
//is it time to toggle key state?
if (elapsedTick >= keyDelay){
// save the current time
keyTick[i] = currTick;
// toggle the state to down or pressed
isDown[i] = true;
}
}
}
}
public void run() {
int iKey = 0;
int screenW = getWidth();
int screenH = getHeight();
long lCurrTick = 0; // current system time in milliseconds;
load();
g = getGraphics();
while(isRunning){
lCurrTick = System.currentTimeMillis();
iKey = getKeyStates();
checkKeys(iKey, lCurrTick);
if (isDown[fireKey]){
isRunning = false;
}
// get the current position of the van
int cx = Van.getX();
int cy = Van.getY();
// save the current position in temporary vars
// so we can restore it when we hit a block
int tx = cx;
int ty = cy;
if ((iKey & GameCanvas.UP_PRESSED) != 0){
// show the van facing up
Van.setFrame(0);
// move the van upwards
cy -= vanSpeed;
} else if ((iKey & GameCanvas.DOWN_PRESSED) != 0){
// show the van facing down
Van.setFrame(1);
// move the van downwards
cy += vanSpeed;
} else if ((iKey & GameCanvas.LEFT_PRESSED) != 0){
// show the van facing left
Van.setFrame(2);
// move the van to the left
cx -= vanSpeed;
} else if ((iKey & GameCanvas.RIGHT_PRESSED) != 0){
// show the van facing right
Van.setFrame(3);
// move the van to the right
cx += vanSpeed;
}
// update the vans position
Van.setPosition(cx, cy);
//check if the van hits a block
if (Van.collidesWith(blockMap, true)){
//reset the van to the original position
Van.setPosition(tx, ty);
}
//restore the clipping rectangle to full screen
g.setClip(0, 0, screenW, screenH);
/* comment out or remove this code
set drawing color to black
g.setColor(0x000000);
fill the screen with blackness
g.fillRect(0, 0, screenW, screenH);
*/
//draw the road
roadMap.paint(g);
//draw the blocks
blockMap.paint(g);
// draw the sprite
Van.paint(g);
flushGraphics();
try{
Thread.sleep(30);
} catch (Exception ex){
}
}
g = null;
unload();
fParent.destroyApp(false);
fParent = null;
}
}
Bạn cũng có thể tìm các phần mềm tạo tilemap trên mạng, thậm chí có thể save dữ liệu map vào file xml, vân vân...
Link vài phần mềm làm map:
Cuối cùng, bạn cũng có thể dùng chức năng Game Builder trong NetBeans 6 và gói Mobility.
Chúc các bạn thành công !!
Không có nhận xét nào:
Đăng nhận xét