// World.java import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.Image; import java.io.*; /** * This class accepts data from the server that defines where remote players should * be rendered, or if they have timedout , or if they need to be added as a new remote user. * It also defines the shared resources for all AnimationPoints (specifically sprite data). * * @author Jack Wootton * @version Last modified 10/03/05 **/ public class World { public static final int TILE_WIDTH = 16; public static final int TILE_HEIGHT = 16; private static final int TREE_HEIGHT = 48; private static final int TREE_WIDTH = 48; private static final int FULL_TREE_SIZE = 3; public static final byte NO_TILE = 0; public static final byte GRASS_TILE = 1; public static final byte TREE_STONE_TILE = 2; public static final byte MOUND_TILE = 3; public static final byte BORDER_LEFT_TILE = 4; public static final byte BORDER_RIGHT_TILE = 5; public static final byte BORDER_TOP_TILE = 6; public static final byte BORDER_BOTTOM_TILE = 7; public static final byte CORNER_TL_TILE = 8; public static final byte CORNER_TR_TILE = 9; public static final byte CORNER_BL_TILE = 10; public static final byte CORNER_BR_TILE = 11; public static final byte WALL_V_TILE = 12; public static final byte WALL_H_TILE = 13; public static final byte STONES_TILE = 14; public static final byte HOUSE_LEFT_TILE = 15; public static final byte HOUSE_RIGHT_TILE = 16; public static final byte WELL_TILE = 17; public static final byte EMPTY_TILE = 26; private static int viewX, viewY; // Current viewport coordinates. private static int viewWidth, viewHeight; // Size of the current viewport. private static int tilesWide = 50; // Number of tiles in tile world private static int tilesHigh = 50; private static int tilesDeep = 2; // Number of layers private static int halfTreeWidth = 16; // To center static object private static int halfTreeHeight = 16; private static int halfMoundWidth = 16; private static int halfMoundHeight = 16; private static int halfHouseWidth = 32; private static int halfHouseHeight = 32; private static int halfStonesWidth = 32; private static int halfStonesHeight = 16; public static final int WORLD_WIDTH = tilesWide * TILE_WIDTH; public static final int WORLD_HEIGHT = tilesHigh * TILE_HEIGHT; private static ImageSet tiles; // Images for the tiles. private static byte tileMap[][][]; // Array of bytes representing the map private static Player player; World() { } /** * initWorld loads images and creates the world and tiling map. * @param viewWidthArg The width of device screen. * @param viewHeightArg The height of device screen. */ public static void init(int viewWidthArg, int viewHeightArg) { viewWidth = viewWidthArg; viewHeight = viewHeightArg; tiles = new ImageSet(9); // canvas items Image canvasItems = ImageSet.loadClippedImage("/canvasItems.png", 0, 0); Image[] treeWithStone = ImageSet.extractFrames(canvasItems, 32, 0, 1, 1, 48, 48); Image[] earthMound = ImageSet.extractFrames(canvasItems, 0, 48, 1, 1, 32, 32); Image[] stones = ImageSet.extractFrames(canvasItems, 32, 48, 1, 1, 48, 32); Image[] houseLeft = ImageSet.extractFrames(canvasItems, 80, 0, 1, 1, 64, 64); Image[] houseRight = ImageSet.extractFrames(canvasItems, 144, 0, 1, 1, 64, 64); Image[] fireWallV = ImageSet.extractFrames(canvasItems, 0, 0, 1, 1, 16, 16); Image[] fireWallH = ImageSet.extractFrames(canvasItems, 16, 0, 1, 1, 16, 16); Image[] well = ImageSet.extractFrames(canvasItems, 0, 16, 1, 1, 32, 32); // borders and grass Image borderImage = ImageSet.loadClippedImage("/borders.png", 0, 0); Image[] grass = ImageSet.extractFrames(borderImage, 16, 16, 1, 1, 16, 16); Image[] borderLeft = ImageSet.extractFrames(borderImage, 0, 16, 1, 1, 16, 16); Image[] borderRight = ImageSet.extractFrames(borderImage, 32, 16, 1, 1, 16, 16); Image[] borderTop = ImageSet.extractFrames(borderImage, 16, 0, 1, 1, 16, 16); Image[] borderBottom = ImageSet.extractFrames(borderImage, 16, 32, 1, 1, 16, 16); Image[] cornerTL = ImageSet.extractFrames(borderImage, 0, 0, 1, 1, 16, 16); Image[] cornerTR = ImageSet.extractFrames(borderImage, 32, 0, 1, 1, 16, 16); Image[] cornerBL = ImageSet.extractFrames(borderImage, 0, 32, 1, 1, 16, 16); Image[] cornerBR = ImageSet.extractFrames(borderImage, 32, 32, 1, 1, 16, 16); // add states, order important! tiles.addState(grass , 0); // state 0 tiles.addState(treeWithStone, 0); // state 1 tiles.addState(earthMound, 0); // state 2 tiles.addState(borderLeft, 0); // state 3 tiles.addState(borderRight, 0); // state 4 tiles.addState(borderTop, 0); // state 5 tiles.addState(borderBottom, 0); // state 6 tiles.addState(cornerTL, 0); // state 7 tiles.addState(cornerTR, 0); // state 8 tiles.addState(cornerBL, 0); // state 9 tiles.addState(cornerBR, 0); // state 10 tiles.addState(fireWallV, 0); // state 11 tiles.addState(fireWallH, 0); // state 12 tiles.addState(stones, 0); // state 13 tiles.addState(houseLeft, 0); // state 14 tiles.addState(houseRight, 0); // state 15 tiles.addState(well, 0); // state 16 // create tile map tileMap = new byte[tilesDeep][tilesHigh][tilesWide]; // grass and boundary for (int ty = 0 ; ty < tilesHigh; ty++) { for (int tx = 0; tx < tilesWide; tx++) { if (tx == 0) { tileMap[0][ty][tx] = BORDER_LEFT_TILE; } else if (ty == 0) { tileMap[0][ty][tx] = BORDER_TOP_TILE; } else if (ty == tilesHigh -1) { tileMap[0][ty][tx] = BORDER_BOTTOM_TILE; } else if (tx == tilesWide -1) { tileMap[0][ty][tx] = BORDER_RIGHT_TILE; } else { tileMap[0][ty][tx] = GRASS_TILE; } } } // corners tileMap[0][0][0] = CORNER_TL_TILE; tileMap[0][tilesHigh -1][0] = CORNER_BL_TILE; tileMap[0][tilesHigh -1][tilesWide -1] = CORNER_BR_TILE; tileMap[0][0][tilesWide -1] = CORNER_TR_TILE; // trees tileMap[1][2][2] = TREE_STONE_TILE; tileMap[1][10][9] = TREE_STONE_TILE; tileMap[1][10][12] = TREE_STONE_TILE; tileMap[1][13][22] = TREE_STONE_TILE; tileMap[1][8][26] = TREE_STONE_TILE; tileMap[1][35][23] = TREE_STONE_TILE; tileMap[1][23][34] = TREE_STONE_TILE; tileMap[1][22][37] = TREE_STONE_TILE; tileMap[1][23][31] = TREE_STONE_TILE; tileMap[1][23][28] = TREE_STONE_TILE; tileMap[1][25][38] = TREE_STONE_TILE; tileMap[1][39][34] = TREE_STONE_TILE; tileMap[1][47][36] = TREE_STONE_TILE; tileMap[1][19][15] = TREE_STONE_TILE; tileMap[1][22][18] = TREE_STONE_TILE; tileMap[1][27][11] = TREE_STONE_TILE; tileMap[1][34][46] = TREE_STONE_TILE; tileMap[1][13][38] = TREE_STONE_TILE; tileMap[1][2][26] = TREE_STONE_TILE; tileMap[1][29][31] = TREE_STONE_TILE; tileMap[1][33][37] = TREE_STONE_TILE; tileMap[1][30][18] = TREE_STONE_TILE; // houses tileMap[1][39][3] = HOUSE_RIGHT_TILE; tileMap[1][29][3] = HOUSE_RIGHT_TILE; tileMap[1][3][14] = HOUSE_RIGHT_TILE; tileMap[1][16][47] = HOUSE_LEFT_TILE; tileMap[1][3][47] = HOUSE_LEFT_TILE; tileMap[1][38][20] = HOUSE_LEFT_TILE; tileMap[1][43][47] = HOUSE_LEFT_TILE; tileMap[1][3][23] = HOUSE_LEFT_TILE; tileMap[1][18][3] = HOUSE_RIGHT_TILE; // well tileMap[1][13][32] = WELL_TILE; // lava walls (counting down is fatser) for (int i=8; i >= 1; i--) tileMap[1][i][10] = WALL_V_TILE; for (int i=7; i >= 1; i--) tileMap[1][i][32] = WALL_V_TILE; for (int i=48; i >= 35; i--) tileMap[1][9][i] = WALL_H_TILE; for (int i=33; i >= 1; i--) tileMap[1][15][i] = WALL_H_TILE; for (int i=21; i >= 1; i--) tileMap[1][35][i] = WALL_H_TILE; for (int i=33; i >= 22; i--) tileMap[1][i][23] = WALL_V_TILE; for (int i=48; i >= 41; i--) tileMap[1][i][34] = WALL_V_TILE; // small mound tileMap[1][14][2] = MOUND_TILE; // stones on layer 0 tileMap[0][5][5] = STONES_TILE; tileMap[0][26][19] = STONES_TILE; tileMap[0][29][36] = STONES_TILE; tileMap[0][44][15] = STONES_TILE; tileMap[0][23][11] = STONES_TILE; } public static int getViewX() { return viewX; } public static int getViewY() { return viewY; } public static void clearGrass(int z, int y, int x, int numTiles ) { int endX = x - numTiles; int endY = y - numTiles; int startX = x; int startY = y; boolean firstTime = true; // so we don't clear the REAL tile while (y > endY) { while (x > endX) { if (! firstTime ) tileMap[z][y][x] = EMPTY_TILE; x--; firstTime = false; } x = startX; y--; } } public static void clearTile(int z, int y, int x) { tileMap[z][y][x] = EMPTY_TILE; } /* #Debug# */ public static void printMap() { for (int ty = 0; ty < tilesHigh; ty++) { for (int tx = 0; tx < tilesWide; tx++) { System.out.print(tileMap[ty][tx] + " "); } System.out.println(""); } } public static final int getTileX(int x) { return x / TILE_WIDTH; } public static final int getTileY(int y) { return y / TILE_HEIGHT; } public static void cycle() { Player.cycle(); } public static final void setView(int viewXArg, int viewYArg) { viewX = viewXArg; viewY = viewYArg; } public static final byte getTile(int depth, int x, int y) { int tx = getTileX(x); int ty = getTileY(y); if (tx < 0 || tx >= tilesWide || ty < 0 || ty >= tilesHigh) return -1; return tileMap[depth][ y / TILE_WIDTH ][ x / TILE_WIDTH ]; } public static final void render(Graphics g) { int startX = (viewX / TILE_WIDTH) -4; int startY = (viewY / TILE_HEIGHT) -4; int endX = ((viewX + viewWidth) / TILE_WIDTH) + 4; int endY = ((viewY + viewHeight) / TILE_HEIGHT) + 4; if (endX > tilesWide) endX = tilesWide; if (endY > tilesHigh) endY = tilesHigh; int tileType=0; int xpos=0; int ypos=0; for (int td=0; td < tilesDeep; td++) { for (int tileY = startY; tileY < endY; tileY++) { for (int tileX = startX; tileX < endX; tileX++) { if (tileY >= 0 && tileX >= 0) { xpos = (tileX * TILE_WIDTH)- viewX; ypos = (tileY * TILE_HEIGHT) - viewY; tileType = tileMap[td][tileY][tileX]; /** * Sometimes we subtract half the height or width of a static object so * the center of the sprite is drawn on the x and y, not the top left on the x and y. */ if (tileType == TREE_STONE_TILE) { tiles.draw(g, tileType -1, 0, xpos - halfTreeWidth, ypos - halfTreeHeight); } else if (tileType == MOUND_TILE) { tiles.draw(g, tileType -1, 0, xpos - halfMoundWidth, ypos - halfMoundHeight); } else if (tileType == STONES_TILE) { tiles.draw(g, tileType -1, 0, xpos - halfStonesWidth, ypos - halfStonesHeight); } else if (tileType == HOUSE_RIGHT_TILE || tileType == HOUSE_LEFT_TILE) { tiles.draw(g, tileType -1, 0, xpos - halfHouseWidth, ypos - halfHouseHeight); } else if (tileType == EMPTY_TILE) { /* #Debug# */ //g.setColor(0xff0000); //g.drawRect(xpos, ypos, 16, 16); } else if (tileType != NO_TILE) { tiles.draw(g, tileType -1, 0, xpos, ypos); } } } } } // If the user has global player settings on, then render all other players if (PollThread.getPollServer()) { TheOthers.paint(g); } Player.render(g); } /* * Player no longer inherits from Actor because everything is static apart from Actors * So we need an extra collision method, but worth it for the optimisation the use * of static provides. */ public static final boolean checkCollision(Player hitter, int xpos, int ypos, int width, int height) { for (int iy = ypos; iy <= ypos + height; iy += TILE_HEIGHT) { for (int ix = xpos; ix <= xpos + width; ix += TILE_WIDTH) { if (getTile(1, ix, iy) > 0) { // Player takes care of what to do Player.onCollision(ix / TILE_WIDTH, iy / TILE_HEIGHT); return true; } } } return false; } }