📄 gamescreen.java
字号:
/**
* The central game control class managing: rendering, cycling of world (which
* includes actors) and other game state.
*/
//#ifdef nokia
//# import com.nokia.mid.ui.FullCanvas;
//#endif
import javax.microedition.lcdui.*;
import net.jscience.math.kvm.MathFP;
//#ifdef nokia
//#
//# public class GameScreen extends FullCanvas implements Runnable
//#
//#else
public class GameScreen extends Canvas implements Runnable, CommandListener
//#endif
{
private static GameScreen theGameScreen; // "there can be only one..."
private static int t = 0;
public static final int NOT_STARTED = t++; // game state
public static final int STARTING_UP = t++; // delay prior to action
public static final int PLAYING = t++; // game in progress
public static final int PAUSED = t++; // paused
public static final int DYING = t++; // we pause after they die
public static final int GAME_OVER = t++; // showing "game over..."
public static final int GAME_DONE = t++; // game is finished
private StarAssault theMidlet;
private int cps;
private int cyclesThisSecond;
private long lastCPSTime = 0;
private int score;
private World world;
private Ship playerShip;
private int leftKeyCode; // key config (set from app)
private int rightKeyCode;
private int fireKeyCode;
private Command menu;
// Rendering setup
private int barWidth;
private int barHeight;
private Image osb;
private Graphics osg;
private Font defaultFont;
private int defaultFontHeight;
private int screenWidth;
private int screenHeight;
private int halfScreenWidth;
private int halfScreenHeight;
private Image energyBarImage; // a cached image of the energy bar
private int lastDrawnBarValue; // last value we drew the bar at
// Game state
private boolean running; // thread controller
private int state;
private long timeStateChanged;
private int statePriorToPause;
private int lives;
// Used to pan the view position based on which way the player is facing.
private int currentViewPosX;
private int currentViewPosY;
private int pixelsPerMSFP = MathFP.div(30, 1000);
public GameScreen(StarAssault midlet)
{
theGameScreen = this;
theMidlet = midlet;
running = true;
setState(NOT_STARTED);
screenWidth = getWidth();
screenHeight = getHeight();
halfScreenWidth = screenWidth / 2;
halfScreenHeight = screenHeight / 2;
setKeyBindings();
lastCycleTime = System.currentTimeMillis();
//#ifndef nokia
menu = new Command("Menu", Command.SCREEN, 1);
addCommand(menu);
setCommandListener(this);
//#endif
initResources();
// create the game thread
Thread t = new Thread(this);
t.start();
}
public void setKeyBindings()
{
leftKeyCode = StarAssault.getKeyCodeFromNum(theMidlet.getLeftKeyNum());
rightKeyCode = StarAssault.getKeyCodeFromNum(theMidlet.getRightKeyNum());
fireKeyCode = StarAssault.getKeyCodeFromNum(theMidlet.getFireKeyNum());
}
public final static GameScreen getGameScreen()
{
return theGameScreen;
}
public final void setState(int newState)
{
state = newState;
timeStateChanged = System.currentTimeMillis();
}
public final int getState()
{
return state;
}
public final int getLevel()
{
return world.getLevelNum();
}
public void incScore(int i)
{
score += i;
}
private void initResources()
{
//System.out.println("1: freemem=" + Runtime.getRuntime().freeMemory());
try
{
barWidth = screenWidth / 5;
barHeight = 6;
energyBarImage = Image.createImage(barWidth, barHeight);
defaultFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
defaultFontHeight = defaultFont.getHeight();
// setup the screen
if (!isDoubleBuffered())
{
osb = Image.createImage(screenWidth, screenHeight);
osg = osb.getGraphics();
osg.setFont(defaultFont);
}
// create the world and playerShip
world = new World(screenWidth, screenHeight);
playerShip = new Ship(world);
playerShip.init(Ship.PLAYER_SHIP, 0, 0);
world.setPlayerShip(playerShip);
}
catch (Exception e)
{
System.out.println("App exception: " + e);
e.printStackTrace();
}
}
private static final int MAX_CPS = 100;
private static final int MS_PER_FRAME = 1000 / MAX_CPS;
private long cycleStartTime;
private long timeSinceStart;
private long lastCycleTime;
private long msSinceLastCycle;
private int panPixelsToMoveFP;
public void run()
{
try
{
while (running)
{
// remember the starting time
cycleStartTime = System.currentTimeMillis();
msSinceLastCycle = System.currentTimeMillis() - lastCycleTime;
// run the cycle
if (state == PLAYING)
world.cycle(msSinceLastCycle);
if (state == STARTING_UP)
{
long timeSinceStateChange = System.currentTimeMillis() -
timeStateChanged;
if (timeSinceStateChange > 3000)
setState(PLAYING);
}
if (state == GAME_OVER)
{
long timeSinceStateChange = System.currentTimeMillis() -
timeStateChanged;
if (timeSinceStateChange > 3000)
{
setState(GAME_DONE);
StarAssault.getApp().activateDisplayable(
new OnlineScoring(score));
}
}
if (state == DYING)
{
long timeSinceStateChange = System.currentTimeMillis() -
timeStateChanged;
if (timeSinceStateChange > 1000)
{
//if (shipsLeft == 0) ...
setState(STARTING_UP);
}
}
if (state != PAUSED && state != GAME_DONE && state != NOT_STARTED)
{
repaint();
// update the view pan
panPixelsToMoveFP += MathFP.mul(pixelsPerMSFP,
MathFP.toFP((int)msSinceLastCycle));
// Figure out how many whole pixels to move.
int wholePixels = MathFP.toInt(panPixelsToMoveFP);
if (wholePixels > 0)
{
// Calculate the ideal position for the view based on the
// direction the player's ship is facing.
int[] targetViewPos = Actor.getProjectedPos(
playerShip.getX(), playerShip.getY(),
playerShip.getDirection(), screenWidth / 3);
// Adjust the current move slightly towards the ideal view
// point.
if (currentViewPosX < targetViewPos[0])
currentViewPosX += wholePixels;
if (currentViewPosX > targetViewPos[0])
currentViewPosX -= wholePixels;
if (currentViewPosY < targetViewPos[1])
currentViewPosY += wholePixels;
if (currentViewPosY > targetViewPos[1])
currentViewPosY -= wholePixels;
// Take away the pixels that were moved.
panPixelsToMoveFP = MathFP.sub(panPixelsToMoveFP,
MathFP.toFP(wholePixels));
}
// update the CPS
if (System.currentTimeMillis() - lastCPSTime > 1000)
{
lastCPSTime = System.currentTimeMillis();
cps = cyclesThisSecond;
cyclesThisSecond = 0;
}
else
cyclesThisSecond++;
lastCycleTime = System.currentTimeMillis();
// sleep if we've finished our work early
timeSinceStart = System.currentTimeMillis() - cycleStartTime;
if (timeSinceStart < MS_PER_FRAME)// && MS_PER_FRAME - timeSinceStart > 5)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -