Có chuyện gì xảy ra với blog của Devlin không biết, sáng nay tôi vào không được. Hi vọng blog không sao chứ nếu có sao thì tiếc lắm... Nếu còn vào được tôi sẽ copy hết sang rồi dịch sau. Đúng là dại quá. Sau đây là bài học về TiledLayer, tôi chôm được trên mạng.
P/S: À mà thôi, đã vào lại được Devlinsblog, tôi tranh thủ copy bài luôn. Bài này cứ để Tiếng Anh, khi nào xong của Devlin tôi sẽ dịch sau.
P/S: À mà thôi, đã vào lại được Devlinsblog, tôi tranh thủ copy bài luôn. Bài này cứ để Tiếng Anh, khi nào xong của Devlin tôi sẽ dịch sau.
A common technique used in video games is to have a large scrolling background formed by a grid of smaller, reusable images. In MIDP 1.0, such a feature would need to be implemented from scratch or with a third-party library. However, MIDP 2.0 provides the convenient TiledLayer class to address this specific need. In this article we will look at a simple example of how to use the TiledLayer class in a Java ME application.
TiledLayer is part of the
javax.microedition.lcdui.game
package that was introduced with MIDP 2.0. The constructor for the TiledLayer class accepts five parameters: the number of columns and rows in the grid, an Image object containing the tiles, and the width and height in pixels of each tile.TiledLayer(int columns, int rows, Image image, int tileWidth, int tileHeight)
The image can have multiple rows of tiles. The tileWidth and tileHeight properties are used to break up the image into individual tiles. The tiles are numbered starting with 1 and incrementing in row-major order. Index 0 is reserved for transparency; TiledLayer won’t draw anything for cells with index 0.
For our example application, we’ll start by creating a class that extends GameCanvas. Extending GameCanvas will allow us to take advantage of the off-screen buffer that this class provides.
import javax.microedition.lcdui.*; import javax.microedition.lcdui.game.*; public class DemoCanvas extends GameCanvas {
Next, we’ll add an instance variable for our TiledLayer object, along with the customary setter and getter methods.
public TiledLayer getTiledLayer() { return tiledLayer; } public void setTiledLayer(TiledLayer tiledLayer) { this.tiledLayer = tiledLayer; } // Instance variables private TiledLayer tiledLayer; // The TiledLayer object
We will also add some constants to store the size of our tiles in pixels, and the background color. Remember that the 0 index tiles are transparent, so we will be responsible for clearing the background ourselves.
// Constants public static final int TILE_WIDTH = 16; public static final int TILE_HEIGHT = 16; public static final int BACKGROUND_COLOR = 0x00000000;
We will need to provide some data for the grid. For the purposes of this example, we can hard code some data into a two-dimensional array. In a real-life application, you would probably read this data from a resource, generated from some sort of map editor software.
public byte[][] getGridData() { // Create and populate a two-dimensional // array with sample grid data byte gridData[][] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,1,2,2,2,3,0,0,0,0,10,10,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,10,10,0,0,0,1,2,2,3,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,1,2,2,3,0,0,0,0,0,4,5,6,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0}, {7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,9} }; return gridData; }
Now, we will add a method to create and initialize our TiledLayer object. To initialize the cells, we will simply iterate through the byte array we created above and call the TiledLayer.setCell() for each value.
public void initTiledLayer() { // Get the grid data byte[][] gridData = getGridData(); // Derive number of columns and rows // from grid data array sizes int rows = gridData.length; int columns = gridData[0].length; // Get the tile Image object Image tileImage; try { tileImage = Image.createImage("/tiledlayer-tiles.png"); } catch(java.io.IOException e) { System.err.println("Unable to create image"); e.printStackTrace(); return; } // Create a TiledLayer object TiledLayer tiledLayer = new TiledLayer( columns, rows, tileImage, TILE_WIDTH, TILE_HEIGHT); // Transfer grid data to TiledLayer object for(int y = 0; y < rows; y++) { for(int x = 0; x < columns; x++) { int tileIndex = gridData[y][x]; if(tileIndex > 0) tiledLayer.setCell(x, y, tileIndex); } } // Set the TiledLayer instance variable setTiledLayer(tiledLayer); }
Next, we need a method to draw the background. In addition to rendering the TiledLayer object, it will also need to clear the background. Note that since GameCanvas provides an off-screen buffer, there is no need to override the paint() method; GameCanvas already provides an adequate implementation.
public void drawBackground() { // Get off-screen buffer Graphics g = getGraphics(); // Clear the background g.setColor(BACKGROUND_COLOR); g.fillRect(0, 0, getWidth(), getHeight()); // Paint the tiled layer TiledLayer tiledLayer = getTiledLayer(); if(tiledLayer != null) { tiledLayer.paint(g); } }
Now we’ll add a custom constructor to call our initialization method, and to perform the initial drawing of the off-screen buffer. Since we’ll be overriding the keyPressed() method in the next step, we will pass false for the suppressKeyEvents parameter of the GameCanvas constructor.
protected DemoCanvas() { // We will be overriding keyPressed, // so do not suppress key events super(false); // Initialize the TiledLayer initTiledLayer(); // Draw to the off-screen buffer drawBackground(); }
Lastly, we’ll implement an extremely simple keyPressed() method that will scroll the background when the direction keys are pressed using the convenient TiledLayer.move() method. It will also force a repaint of the off-screen buffer and flush it to the display.
protected void keyPressed(int keyCode) { // Handle scrolling in response to key presses TiledLayer tiledLayer = getTiledLayer(); if(tiledLayer != null) { // Get game action from key code int gameAction = getGameAction(keyCode); switch(gameAction) { case UP: tiledLayer.move(0, -16); break; case DOWN: tiledLayer.move(0, 16); break; case LEFT: tiledLayer.move(-16, 0); break; case RIGHT: tiledLayer.move(16, 0); break; } // Repaint the off-screen buffer paintBackground(getGraphics()); // Flush the off-screen buffer to the display flushGraphics(); } }
Dich bai nay di p oi
Trả lờiXóa