📄 world.java
字号:
/**
* A game world (or level) contains two layers of entities: unmoving tiles
* drawn in the background and dynamic actors drawn over the top. Levels are
* generated usign the LevelGenerator. Note that certain tile types can
* become Actors when they are encountered by the player.
*/
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.rms.*;
import java.io.*;
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 tilesWide;
private int tilesHigh;
private int viewWidth;
private int viewHeight;
// tile types
public static final byte NO_TILE = 0;
public static final byte START_REAL_TILE = 1;
public static final byte WALL_TILE = 1;
public static final byte GATEWAY_TILE = 2;
public static final byte END_REAL_TILE = 2;
// activator tiles "become" an actor when the player gets in range
// they're used so we don't have to bother with cycling actors in the
// world before the player has encountered them.
public static final byte START_ACTIVATOR_TILE = 100;
public static final byte DRONE_ACTIVATOR_TILE = 100;
public static final byte TURRET_ACTIVATOR_TILE = 101;
public static final byte FIGHTER_ACTIVATOR_TILE = 102;
public static final byte END_ACTIVATOR_TILE = 102;
private int viewX;
private int viewY;
private int startX; // start position on tilemap
private int startY;
private int levelNum; // current levelNum player is on
private Sprite gatewaySprite; // graphics for gateway to next level
private byte[][] tileMap;
private ActorPool enemyShipPool;
private ActorPool bulletPool; // given their transient lives we use a pre-built
// pool of objects
private long lastCycleTime;
private Ship playerShip; // a link to the player's object
private boolean wantLevelOver;
public World(int viewWidthArg, int viewHeightArg)
{
viewWidth = viewWidthArg;
viewHeight = viewHeightArg;
levelNum = 1;
//tileMap = new int[tilesHigh][tilesWide];
// load up the tileMap
Image tileGraphics = ImageSet.loadClippedImage("/world.png", 0, 0, 16, 16);
tiles = new ImageSet(1);
tiles.addState(new Image[]{tileGraphics}, 0);
// construct the objects pools for ships and bullets
Ship ships[] = new Ship[20];
for (int i = 0; i < ships.length; i++)
ships[i] = new Ship(this);
enemyShipPool = new ActorPool(ships);
Bullet bullets[] = new Bullet[20];
for (int i = 0; i < bullets.length; i++)
bullets[i] = new Bullet(this);
bulletPool = new ActorPool(bullets);
gatewaySprite = new Sprite(Ship.getShieldImageSet(), 0, 0);
}
/**
* Generate a new level (creates a new map, resets all actors then saves
* the level data to RMS)
*/
public void generateLevel()
{
restart();
LevelGenerator lg = new LevelGenerator();
tileMap = lg.generateLevel(levelNum);
tilesWide = tileMap[0].length;
tilesHigh = tileMap.length;
startX = lg.getPlayerStartX();
startY = lg.getPlayerStartY();
playerShip.setStartingPos(startX * TILE_WIDTH, startY * TILE_HEIGHT);
playerShip.setX(startX * TILE_WIDTH);
playerShip.setY(startY * TILE_HEIGHT);
// save the level to the RMS
saveLevel();
}
public int getLevelNum()
{
return levelNum;
}
public void setLevelNum(int levelNum)
{
this.levelNum = levelNum;
}
public final Bullet getBulletFromPool()
{
return (Bullet) bulletPool.getNextFree();
}
public final void releaseBullet(Bullet b)
{
b.deactivate();
bulletPool.release(b);
}
public final Ship getEnemyShipFromPool()
{
return (Ship) enemyShipPool.getNextFree();
}
public final void releaseShip(Ship s)
{
s.deactivate();
enemyShipPool.release(s);
}
/**
* @return The player's Actor.
*/
public final Ship getPlayerShip()
{
return playerShip;
}
/**
* @param a The Actor object that represents the player in the game.
*/
public final void setPlayerShip(Ship a)
{
playerShip = a;
}
/**
* Set the current view port position (relative to world coordinates).
* @param viewXArg The x position of the view.
* @param viewYArg The y position of the view.
*/
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
final int t1 = getTile(x, y);
if (w == 1 && h == 1)
{
// faster version if the object is one pixel
if (t1 >= START_REAL_TILE && t1 <= END_REAL_TILE)
{
hitter.onCollision(null);
return true;
}
}
else
{
// otherwise we check all four corners
final int t2 = getTile(x + w, y);
final int t3 = getTile(x, y + h);
final int t4 = getTile(x + w, y + h);
if ((t1 >= START_REAL_TILE && t1 <= END_REAL_TILE) ||
(t2 >= START_REAL_TILE && t2 <= END_REAL_TILE) ||
(t3 >= START_REAL_TILE && t3 <= END_REAL_TILE) ||
(t4 >= START_REAL_TILE && t4 <= END_REAL_TILE))
{
if (t1 == GATEWAY_TILE || t2 == GATEWAY_TILE ||
t3 == GATEWAY_TILE || t4 == GATEWAY_TILE)
{
if (hitter == playerShip)
{
GameScreen.getGameScreen().notifyLevelOver();
}
}
else
{
hitter.onCollision(null);
return true;
}
}
}
// if this is the playerShip then we check if we hit another
// enemy ship (we don't care if enemy ships hit each other)
if (hitter == playerShip)
{
Actor a = enemyShipPool.getFirstUsed();
while (a != null)
{
if (a.isCollidable() && a.isCollidingWith(playerShip))
{
a.onCollision(playerShip);
playerShip.onCollision(a);
return true;
}
a = a.getNextLinked();
}
}
// if this is a bullet then we test if its hit any of the enemy ships
// (we do the playerShip at the end)
if (hitter.isBullet())
{
// if i was fired by the player, then test against enemy
if (hitter.getOwner().getType() == Actor.PLAYER_SHIP)
{
Actor a = enemyShipPool.getFirstUsed();
while (a != null)
{
if (a.isCollidable() && a.isCollidingWith(hitter))
{
// enemy bullets only hit enemy ships
hitter.onCollision(a);
a.onCollision(hitter);
return true;
}
a = a.getNextLinked();
}
}
else
{
// bullet fired by an enemy, test against the player
if (playerShip.isCollidable() && playerShip.isCollidingWith(hitter))
{
hitter.onCollision(playerShip);
playerShip.onCollision(hitter);
return true;
}
}
}
return false;
}
protected final void cycle(long msSinceLastCycle)
{
if (msSinceLastCycle > 0)
{
// cycle all the (used) ship objects from the enemyShipPool
Actor a = enemyShipPool.getFirstUsed();
while (a != null)
{
a.cycle(msSinceLastCycle);
a = a.getNextLinked();
}
gatewaySprite.cycle(msSinceLastCycle);
playerShip.cycle(msSinceLastCycle);
//if (GameScreen.getGameScreen().getLevelNum() > 1)
// System.out.println("pos=" + playerShip.getX() + ", " + playerShip.getY());
// now cycle all the bullets (we only cycle used ones)
Actor bullet = bulletPool.getFirstUsed();
while (bullet != null)
{
bullet.cycle(msSinceLastCycle);
bullet = bullet.getNextLinked();
}
}
lastCycleTime = System.currentTimeMillis();
if (wantLevelOver)
{
GameScreen.getGameScreen().notifyLevelOver();
wantLevelOver = false;
}
}
/**
* Restart the level
*/
public void restart()
{
// reset all the ships (used only of course)
Ship s = (Ship) enemyShipPool.getFirstUsed();
while (s != null)
{
Actor next = s.getNextLinked();
// Final check used to remove any inactive or exploding actors.
// This can happen sometimes if actors were not given enough time
// to complete their death sequence before this restart method was
// called. For example, if the player collides with an enemy ship
// before dying it wont have time to finish its exploding state and
// suicide before we get this call in here. Without this check we
// could end up with floating, half-dead phantom objects.
if (!s.isVisible() || s.isExploding())
releaseShip(s);
else
s.reset();
s = (Ship) next;
}
playerShip.reset();
// release all the bullets
Actor a = bulletPool.getFirstUsed();
while (a != null)
{
Actor next = a.getNextLinked();
releaseBullet((Bullet) a);
a = next;
}
}
/**
* Clear all actors from the levelNum
*/
public void clear()
{
// reset all the ships (used only of course)
Actor a = enemyShipPool.getFirstUsed();
while (a != null)
{
Actor next = a.getNextLinked();
releaseShip((Ship) a);
a = next;
}
playerShip.reset();
// release all the bullets
a = bulletPool.getFirstUsed();
while (a != null)
{
Actor next = a.getNextLinked();
releaseBullet((Bullet) a);
a = next;
}
}
public final int getTileAtX(int x)
{
return x / TILE_WIDTH;
}
public final int getTileAtY(int y)
{
return y / TILE_HEIGHT;
}
public final int getTileCenterPosX(int x)
{
return (getTileAtX(x) * TILE_WIDTH) + (TILE_WIDTH / 2);
}
public final int getTileCenterPosY(int y)
{
return (getTileAtY(y) * TILE_HEIGHT) + (TILE_HEIGHT / 2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -