📄 world.java
字号:
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
public class World
{
public static final int TILE_HEIGHT=16;
public static final int TILE_WIDTH=16;
public static final int TILE_HALF_HEIGHT = TILE_HEIGHT / 2;
public static final int TILE_HALF_WIDTH = TILE_WIDTH / 2;
private ImageSet tiles;
private int tilesDeep = 2;
private int tilesWide = 50;
private int tilesHigh = 50;
private byte[][][] tileMap;
private Actor[] actorZMap; // linked list of references to actors updated
// whenever an actor moves (if tile changes)
private int viewWidth;
private int viewHeight;
// tile types
public static final byte NO_TILE = 0;
public static final byte GRASS1_TILE = 1;
public static final byte GRASS2_TILE = 2;
public static final byte GRASS3_TILE = 3;
public static final byte TREE_TILE = 4;
private int viewX;
private int viewY;
private long lastCycleTime;
private Tank playerTank;
public World(int viewWidthArg, int viewHeightArg)
{
viewWidth = viewWidthArg;
viewHeight = viewHeightArg;
tiles = new ImageSet(5); // 3 x grass, 1 x barrier, 1 x tree
// add the grass to the world tiles
Image grassImage = ImageSet.loadClippedImage("/grass.png", 0, 0);
Image[] grassImages = ImageSet.extractFrames(grassImage, 0, 0, 1, 3, 16, 16);
for (int i=0; i < 3; i++)
tiles.addState(new Image[]{grassImages[i]}, 0);
// add the tree
Image treeImage = ImageSet.loadClippedImage("/tree.png", 0, 0);
tiles.addState(new Image[]{treeImage}, 0);
// setup the map
tileMap = new byte[tilesDeep][tilesHigh][tilesWide];
actorZMap = new Actor[tilesHigh];
// setup the map with grass on the ground layer
for (int ty=0; ty < tilesHigh; ty++)
{
for (int tx=0; tx < tilesWide; tx++)
{
// fill with normal grass
tileMap[0][ty][tx] = (byte)Tools.getRand(GRASS1_TILE, GRASS2_TILE);
// then randomly add some special grass
if (Tools.getRand(0, 10)==0)
tileMap[0][ty][tx] = GRASS3_TILE;
//now add some trees
if (Tools.getRand(0, 25)==0)
tileMap[1][ty][tx] = TREE_TILE;
}
}
}
public final Tank getPlayerTank()
{
return playerTank;
}
public final void setPlayerTank(Tank a)
{
playerTank = a;
// clear away any tree tiles around the tank so we are clear when we start
int sx = getTileX(playerTank.getX());
int sy = getTileY(playerTank.getY());
for (int i=0; i < 9; i++)
tileMap[1][sy+(i/3)][sx+(i%3)] = NO_TILE;
}
public final void setView(int viewXArg, int viewYArg)
{
viewX = viewXArg;
viewY = viewYArg;
}
public final boolean checkCollision(Actor hitter, int x, int y, int w, int h)
{
// test if this actor object has hit a tile on layer 1 (we ignore layer 0)
// we look at all the tiles under the actor (we do a <= comparison so we
// include the bounding edge of the actor's rectangle
for (int iy=y; iy <= y+h; iy += TILE_HEIGHT)
{
for (int ix=x; ix <= x+w; ix += TILE_WIDTH)
{
if (getTile(1, ix, iy) > 0)
{
hitter.onCollision(null);
return true;
}
}
}
// now test if this actor hit another actor in this or an adjacent
// sector
int sector = getTileY(y);
Actor weHit = checkSectorCollision(hitter, sector, x, y, w, h);
if (sector + 1 < actorZMap.length && weHit == null)
weHit = checkSectorCollision(hitter, sector+1, x, y, w, h);
if (sector - 1 >= 0 && weHit == null)
weHit = checkSectorCollision(hitter, sector-1, x, y, w, h);
if (weHit != null)
{
hitter.onCollision(weHit);
return true;
}
return false;
}
private Actor checkSectorCollision(Actor hitter, int sector, int x, int y, int w, int h)
{
// check to see if we hit another actor in this sector (we ignore ourselves)
Actor a = actorZMap[sector];
while (a != null)
{
if (a.isCollidingWith(x, y, w, h) && a != hitter)
return a;
a = a.getNextInZMap();
}
return null;
}
protected final void cycle()
{
if (lastCycleTime > 0)
{
long msSinceLastCycle = System.currentTimeMillis() - lastCycleTime;
playerTank.cycle(msSinceLastCycle);
}
lastCycleTime = System.currentTimeMillis();
}
public final int getTileX(int x) { return x / TILE_WIDTH; }
public final int getTileY(int y) { return y / TILE_HEIGHT; }
public final int getTileXCenter(int x)
{
return (getTileX(x) * TILE_WIDTH) + (TILE_WIDTH / 2);
}
public final int getTileYCenter(int y)
{
return (getTileY(y) * TILE_HEIGHT) + (TILE_HEIGHT / 2);
}
public 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 final void render(Graphics g)
{
try
{
int startX = (viewX / TILE_WIDTH) - 5;
int startY = (viewY / TILE_HEIGHT) - 5;
int tw = ((Math.abs(viewX) + viewWidth) / TILE_WIDTH) + 5;
int th = ((Math.abs(viewY) + viewHeight) / TILE_HEIGHT) + 5;
if (tw > tilesWide) tw = tilesWide;
if (th > tilesHigh) th = tilesHigh;
int t=0;
int xpos=0;
int ypos=0;
for (int td=0; td < tilesDeep; td++)
{
for (int ty=startY; ty < th; ty++)
{
for (int tx=startX; tx < tw; tx++)
{
if (ty >= 0 && tx >= 0)
{
t = tileMap[td][ty][tx];
// quick abort if it's nothing and we抮e only doing the
// ground layer (no actors to worry about)
if (td == 0 && t == NO_TILE) continue;
xpos = (tx * TILE_WIDTH)- viewX;
ypos = (ty * TILE_HEIGHT) - viewY;
if (t > 0)
{
if (t == TREE_TILE)
tiles.draw(g, t-1, 0, xpos-16, ypos-42);
else
tiles.draw(g, t-1, 0, xpos, ypos);
}
// if this is the second pass then we draw the actors
// at this z-order
if (td==1)
{
Actor a = actorZMap[ty];
while (a != null)
{
// debug rectangle
//g.setColor(0xff0000);
//g.drawRect(a.getX()-viewX, a.getY()-viewY, a.getWidth(), a.getHeight());
a.render(g, viewX, viewY);
a = a.getNextInZMap();
}
}
}
}
}
}
}
catch (Exception e)
{
System.out.println("App exception: " + e);
e.printStackTrace();
}
}
/**
* Called by the actor class to notify us an actor changed position. We
* use this to move the actor to a diff z-order position if their y-tile
* position changed.
*/
public void notifyActorMoved(Actor a, int oldX, int oldY, int x, int y)
{
// figure out the z-order positions (Y tile position)
int oldYTilePos = getTileY(oldY);
int yTilePos = getTileY(y);
// if they have indeed moved to another sector (vertical row) then
// we need to move them from one linked list to another
if (oldYTilePos != yTilePos)
{
// go through all the actors in this sector's list until you find
// this one - try the very fast case first (one item in list)
if (actorZMap[oldYTilePos] == a && a.getNextInZMap() == null)
actorZMap[oldYTilePos]=null;
else
{
if (actorZMap[oldYTilePos] != null)
{
// we assume in this case that there must be at least two entries
// in this linked list (since the above test failed)
Actor actorToRemove = actorZMap[oldYTilePos];
while (actorToRemove != a && actorToRemove != null)
actorToRemove = actorToRemove.getNextInZMap();
// if there was an entry matching the actor
if (actorToRemove != null)
{
// set my next's prev to my prev (thus replacing me)
if (actorToRemove.getNextInZMap() != null)
actorToRemove.getNextInZMap().setPrevInZMap(actorToRemove.getPrevInZMap());
// set my prev's next to my next
if (actorToRemove.getPrevInZMap() != null)
actorToRemove.getPrevInZMap().setNextInZMap(actorToRemove.getNextInZMap());
// replace the head of the list if it was removed
if (actorZMap[oldYTilePos] == actorToRemove)
actorZMap[oldYTilePos] = actorToRemove.getNextInZMap();
// **NOTE: we don't bother updating a's next and prev because it will
// be fixed up when we add it into another list (this is a move
// function, not a remove)
}
}
}
// add the actor into the new spot. do the empty list case first
// (the most common case).
if (actorZMap[yTilePos] == null)
{
a.setNextInZMap(null);
a.setPrevInZMap(null);
actorZMap[yTilePos] = a;
} else
{
// one or more, find the tail of the list and append this ref
Actor tail = actorZMap[yTilePos];
while (tail.getNextInZMap() != null)
tail = tail.getNextInZMap();
tail.setNextInZMap(a);
a.setPrevInZMap(tail);
a.setNextInZMap(null);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -