📄 gameengine.java
字号:
*/
private int m_nRegion2Points;
/**
* The data structure of the region that is selected. Contains the vertices
* of that region.
*/
private short m_arrSelectedRegion[][];
/**
* Indicates the number of vertices in the selected Region.
*/
private int m_nSelectedRegionPoints;
/**
* The data structure of the region that is remaining to be selected.
* Contains the vertices of that region.
*/
public short m_arrUnSelectedRegion[][];
/**
* Indicates the number of points in unselected Region.
*/
public int m_nUnSelectedRegionPoints;
/**
* Maximum number of vertices that can be handled in the unsecured region.
* If this limit is crossed then the data structure is reallocated.
*/
private final int MAX_UNSELECTED_REGION_VERTICES = 200;
/**
* The amount of additional space to be allocated to the region arrays.
*/
private final int ARRAY_REALLOCATION_GRANULARITY = 50;
/**
* The table of all the vertical edges in a region.
* This data structure is used for filling the secured region.
*/
private short m_arrEdgeTable[][];
/**
* The number of Edges in the edges table.
*/
private int m_nNumberOfEdges;
/**
* Max number of intersections of a region with a particular horizontal
* line that can be handled. This quantity may be increased
* if it is found insufficient.
*/
private final int MAX_COLUMN_BOUNDS = 100;
/**
* A array which is used to store a list of column expanses at which a
* horizontal line intersects a particular region.
* This is used to calculate the sizes of the regions
* created after a move of Erix, and also to
* fill-in the region selected for securing.
*/
private short m_arrColumnBounds[] = new short[MAX_COLUMN_BOUNDS];
/**
* The number of elements of the column bounds array, that are in use.
*/
private int m_nColumnBoundsCount = 0;
/**
* Indicates the state when the game gets over.
*/
private boolean m_bGameOver;
/**
* Indicates the time (in milliseconds) in which one iteration
* of the game logic and painting loop is desired to be finished.
* 120 is a value adjusted to Tova/Midori performance. if you modify this
* you should also modify characters delay time
*/
private final int GAME_LOOP_TIME = 120;
/**
* The flag that indicates whether Erix has to continue moving in case it
* reaches the boundary at a vertex.
*/
private boolean m_bContinueErixMovement;
/**
* The indices of all the entities visible on the game screen.
* It is mainitained in the sorted order of the entities' Y-coordinate.
* The enemies are painted in this order, thus giving the illusion
* of a character with a smaller Y-coordinate being "behind"
* a character having a larger Y-coordinate.
*/
public byte m_arrGameEntities[];
/**
* The sound requested during the current game loop iteration,
* that is of the highest priority from amongst all the requests
* received in this iteration. Near the end of each iteration,
* the highest-priority sound received in that iteration is played.
* The value GameEffects.NO_SOUND indicates that no sound has so far
* been requested in the current iteration.
*/
private int m_nHighestPrioritySoundRequested = GameEffects.NO_SOUND;
/**
* The number of cycles to be skipped during PRE_LEVEL_COMPLETE_MODE.
*/
private final int PRE_LEVEL_COMPLETE_COUNTER = 15;
/**
* The number of cycles to be skipped during LEVEL_INITIALIZE_MODE.
*/
private final int LEVEL_INITIALIZE_COUNTER = 8;
/**
* The number of cycles to be skipped during LIFE_LOSE_MODE.
*/
private final int LIFE_LOSE_MODE_COUNTER = 12;
/**
* The number of cycles to be skipped during PRE_GAME_WIN_MODE.
*/
private final int PRE_GAME_WIN_COUNTER = 25;
/**
* The number of cycles to be skipped during GAME_OVER_MODE or
* GAME_WIN_MODE.
*/
private final int GAME_WIN_OVER_MODE_COUNTER = 12;
/**
* The number of cycles to be skipped during LEVEL_START_MODE.
*/
private final int LEVEL_START_MODE_COUNTER = 15;
/**
* The counter used to skip cycles in a particular mode.
*/
public int m_nDelayCounter;
/**
* Flag to indicate whether the game display needs to be updated.
* This does not indicate that a region has been secured, but that
* there is even otherwise a need to update the display.
*/
//public boolean m_bUpdateGameScreen = false;
public boolean m_bUpdateGameScreen;
/**
* Flag to indicate whether a region has just been secured. Used to
* implement conditional selective updation of the secured region layout.
*/
public boolean m_bRegionSecured;
/**
* This array is used for storing random enemy positions.
*/
public short[] m_arrRandomPositions;
/**
* Indicates the number of random enemy positions in the
* array m_arrRandomPositions.
*/
public int m_nNumberOfRandomPositions;
/**
* The counter used to cycle through the array of random positions so that
* a new position can be assigned to the enemy whenever a level is started.
*/
private int m_nRandomPositionCounter;
/**
* Indicates whether Erix crosses his own path or Enemy crossed Erix's path.
* This is used to show Erix's path using a different color on the screen
* when the player loses a life due to any of the above mentioned reasons.
*/
public boolean m_bIsPathCrossed;
/**
* GameEngine constructor
*/
public GameEngine(GameCanvas objCanvas, ErixMIDlet objMidlet) {
m_objMidlet = objMidlet;
m_objCanvas = objCanvas;
m_objEffects = new GameEffects(objMidlet);
m_bContinueErixMovement = false;
m_nColMax = GameEngine.X_MAX >> 3;
m_bUpdateGameScreen = false;
m_bytLevelNumber = 1;
m_nTotalArea = (GameEngine.X_MAX-2)*GameEngine.Y_MAX;
m_nUnSelectedArea = m_nTotalArea;
m_objErix = new Erix(this);
m_objEnemy = new Enemy[MAX_NUMBER_OF_ENEMIES];
for(int i = 0; i < MAX_NUMBER_OF_ENEMIES; i++){
m_objEnemy[i] = new Enemy(this);
}
m_arrSecuredRegionBmp = new byte[GameEngine.Y_MAX][m_nColMax];
m_arrEdgeTable = new short[MAX_UNSELECTED_REGION_VERTICES][3];
m_arrRegion1 = new short[MAX_UNSELECTED_REGION_VERTICES][2];
m_arrRegion2 = new short[MAX_UNSELECTED_REGION_VERTICES][2];
m_arrUnSelectedRegion = new short[MAX_UNSELECTED_REGION_VERTICES][2];
m_arrEnemyRegion1 = new byte[MAX_NUMBER_OF_ENEMIES];
m_nEnemyRegion1Count = 0;
m_arrEnemyRegion2 = new byte[MAX_NUMBER_OF_ENEMIES];
m_nEnemyRegion2Count = 0;
m_nEnemiesToRelocate = 0;
m_arrGameEntities = new byte[MAX_NUMBER_OF_ENEMIES + 1];
m_nDelayCounter = 0;
m_nEngineMode = -1;
//Assign a random number between 0 - 15.
m_nRandomPositionCounter = (int)(System.currentTimeMillis() % 16);
m_nPrevEngineMode = -1;
} // end of the GameEngine constructor
/**
* Informs the GameEngine whether the user has chosen to resume the
* previously saved game, or in case the user has chosen to start a new
* game, the difficulty level of the game (Easy, Medium or Hard).
* The difficulty level setting affects the speed of movement of enemies
* and Erix in the game, and also the "Difficulty Bonus" awarded to the
* player at each level.
* @param nGameType Initialise the Engine according to the type of game to
* be started.
*/
public void initialiseGameType(int nGameType) {
if (nGameType != ErixMIDlet.RESUME_GAME_STR) {
m_bytGameType = (byte)nGameType;
m_lTotalScore = 0;
//m_lScoreAtLevelStart = 0;
m_bytLifeCount = 3;
//m_bytLifeCountAtLevelStart = 3;
m_lLifeBonus = LIFE_BONUS_SCORE;
} else {
m_lLifeBonus = ((m_lTotalScore/10000)+1) * 10000;
//m_lScoreAtLevelStart = m_lTotalScore;
//m_bytLifeCountAtLevelStart = m_bytLifeCount;
}
//This flag is set to true whenever a game is completed.
//So this flag has to be set to false to start another game.
m_bGameOver = false;
// This flag indicates whether the current game has been saved into
// the RMS in the current session. If the game ends and this flag is
// in the set state, (i.e., game was saved), it means that the game
// in the RMS is the one just completed, and so it is to be deleted.
// On the other hand, if at the end of the game, this flag is not in
// the set state (i.e., the game was not saved), it means the current
// game has ended without any progress in level from the one in which
// it started. In that case, the existing saved game is not deleted.
// Since the new game being started, or the existing game being
// resumed right now has not yet been saved in the RMS in *this*
// session, we set reset the flag here.
m_objMidlet.m_bCurrentGameSaved = false;
initialiseLevel(m_bytLevelNumber);
// Ask for the game start sound to be played immediately.
m_objEffects.playSound(GameEffects.GAME_START_SOUND);
Thread t = new Thread(this);
t.start();
}
/**
* Initialises a new level.
* This method is called after the player has completed a level and it is
* needed to continue the game from the next level. This method performs
* the neccessary initializations of the data structures, and sets the
* initial positions of Erix and the enemies.
* Some of the tasks performed by this method are:
* <ul>
* <li> Increasing the percentage area to be secured in each successive
* level.
* <li> Calculating the percentage area to be secured for the level.
* <li> Calculating the number of enemies for the level.
* <li> Resetting the initial positions and directions of Erix and the
* enemies, at the start of a level.
* <li> Resetting the counters and data structures used for a level.
* <li> Requesting the 'Level start' sound to be played by calling
* queueSound() method of this class.
* </ul>
* @param nLevelNumber The level to be started.
*/
private void initialiseLevel(int nLevelNumber) {
m_nNumberOfMoves = 0;
resetPlayField();
//Reset Area Counter
m_nPercentAreaSecured = 0;
m_nPercentAreaToSecure = 0;
m_nUnSelectedArea = m_nTotalArea;
//Every level, the amount of area to be covered changes.
int nSubLevel = (m_bytLevelNumber - 1)%4;
switch(nSubLevel){
case 0:
m_nPercentAreaToSecure = 70;
break;
case 1:
m_nPercentAreaToSecure = 75;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -