📄 gameengine.java
字号:
case 2:
m_nPercentAreaToSecure = 80;
break;
case 3:
m_nPercentAreaToSecure = 85;
break;
default:
break;
}
//The number of enemies changes every 4 levels.
m_nNumberOfEnemies = ((m_bytLevelNumber-1)/4) + 1;
/* New method for Erix and enemies delay */
m_objErix.m_nDelay = MAX_ERIX_DELAY - 2 + m_bytGameType;
m_objErix.m_nDelayCounter = 0;
int nEnemyDelayCounter = MAX_ENEMY_DELAY -
((m_bytLevelNumber-1)/12);
if (nEnemyDelayCounter < 0)
nEnemyDelayCounter = 0;
for(int i = 0; i < MAX_NUMBER_OF_ENEMIES; i++){
m_objEnemy[i].m_nEnemyType = m_arrLevelEnemyType[m_bytLevelNumber-1][i];
m_objEnemy[i].m_nDelay = nEnemyDelayCounter;
m_objEnemy[i].m_nDelayCounter = 0;
}
//Assigning initial positions to all enemies.
for(byte i = 0; i < m_nNumberOfEnemies; i++){
m_objEnemy[i].m_nEnemyXPos = m_arrRandomPositions[4*m_nRandomPositionCounter];
m_objEnemy[i].m_nEnemyYPos = m_arrRandomPositions[4*m_nRandomPositionCounter+1];
m_objEnemy[i].initialise(m_arrRandomPositions[4*m_nRandomPositionCounter+2], m_arrRandomPositions[4*m_nRandomPositionCounter+3]);
m_arrGameEntities[i] = i;
m_nRandomPositionCounter++;
if(m_nRandomPositionCounter >= m_nNumberOfRandomPositions){
m_nRandomPositionCounter = 0;
}
}
if(m_nNumberOfEnemies > 1){
sortEnemies();
}
m_arrGameEntities[m_nNumberOfEnemies] = -1;
//Reset the previous erix path array.
m_objErix.resetPath();
//Initialising a level with top & bottom borders as secured.
for(int i = 0; i < m_nColMax; i++){
m_arrSecuredRegionBmp[0][i] = (byte)0xFF;
m_arrSecuredRegionBmp[GameEngine.Y_MAX-1][i] = (byte)0xFF;
}
//Initialising a level with left & right borders as secured.
for(int i = 0; i < GameEngine.Y_MAX - 1; i++){
m_arrSecuredRegionBmp[i][0] |= 0x01;
m_arrSecuredRegionBmp[i][m_nColMax-1] |= 0x40;
}
//To unset the rightmost top & bottom pixel.
m_arrSecuredRegionBmp[0][m_nColMax-1] = (byte)0x7F;
m_arrSecuredRegionBmp[GameEngine.Y_MAX-1][m_nColMax-1] = (byte)0x7F;
// Since we have marked the edges as "secured", we need to set
// a flag to instruct the canvas to update the secured region layout
m_bRegionSecured = true;
//To set all the flags used in each level to initial values.
m_objErix.m_bIsErixOnBoundary = true;
m_objErix.m_bErixMoving = false;
m_bIsPathCrossed = false;
//Reset the data structure used for Filling up a region.
m_nNumberOfEdges = 0;
//Reset the data structure used for identifying the 2 regions.
m_nRegion1Points = 0;
m_nRegion2Points = 0;
//Initialise the initial unselected region as the entire playfield.
m_arrUnSelectedRegion[0][0] = 0;
m_arrUnSelectedRegion[0][1] = 0;
m_arrUnSelectedRegion[1][0] = 0;
m_arrUnSelectedRegion[1][1] = GameEngine.Y_MAX-1;
m_arrUnSelectedRegion[2][0] = GameEngine.X_MAX-2;
m_arrUnSelectedRegion[2][1] = GameEngine.Y_MAX-1;
m_arrUnSelectedRegion[3][0] = GameEngine.X_MAX-2;
m_arrUnSelectedRegion[3][1] = 0;
m_arrUnSelectedRegion[4][0] = 0;
m_arrUnSelectedRegion[4][1] = 0;
m_nUnSelectedRegionPoints = 5;
//Reset the Selected region.
m_arrSelectedRegion = null;
m_nSelectedRegionPoints = 0;
// If we have just completed a level ...
if (m_nEngineMode == GameEngine.LEVEL_COMPLETE_MODE) {
// Remember the current score and lives, to be saved later.
//m_lScoreAtLevelStart = m_lTotalScore;
//m_bytLifeCountAtLevelStart = m_bytLifeCount;
}
m_objCanvas.configureLevelDisplay((int)m_bytLevelNumber);
//Assigning initial positions to Erix.
m_objErix.m_nErixXPos = GameEngine.X_MAX >> 1; //(division by 2)
m_objErix.m_nErixYPos = GameEngine.Y_MAX - 1;
//Initialise engine mode.
if(m_nEngineMode == GameEngine.LEVEL_COMPLETE_MODE
|| m_nEngineMode == -1){
m_nEngineMode = GameEngine.LEVEL_START_MODE;
}else{
m_nEngineMode = GameEngine.NORMAL_MODE;
}
} // end of method initialiseLevel
/**
* This function is used to sort the enemies according to their z-ordering.
* This is done only at the start of a level. Rest of the times only
* their positions are updated by comparing their positions with
* adjacent enemies.
*/
private void sortEnemies(){
try{
byte nEnemyIndex1;
byte nEnemyIndex2;
for(int i = m_nNumberOfEnemies-1; i >= 0; i--){
for(int j = 0; j < i; j++){
nEnemyIndex1 = m_arrGameEntities[j];
nEnemyIndex2 = m_arrGameEntities[j+1];
if(m_objEnemy[nEnemyIndex1].m_nEnemyYPos > m_objEnemy[nEnemyIndex2].m_nEnemyYPos){
m_arrGameEntities[j] = m_arrGameEntities[j+1];
m_arrGameEntities[j+1] = nEnemyIndex1;
}
}
}
}catch(Exception e){
System.out.println("Exception in sortEnemies - " + e);
}
}
/**
* Contains the main game loop.
* Since the GameEngine implements the java.lang.Runnable interface, the
* run method is called when the GameEngine thread is started. This method
* handles the movement of Erix and all the NPCs (the Enemies, Pillars).
* This method also checks for collisions between Erix , Enemy and Pillars
* and also checks if Erix has crossed his own path.
* After a move is complete it identifies as to which region has to be
* filled and then updates the area counter and score as well.
*/
public void run() {
if (!m_objMidlet.m_bProcessing)
return;
try{
long lStartTime = 0;
long lFinishTime = 0;
long lTimeElapsed = 0;
while (!m_bGameOver) {
lStartTime = System.currentTimeMillis();
if(m_nEngineMode == GameEngine.NORMAL_MODE
|| m_nEngineMode == GameEngine.AREA_CALCULATE_MODE){
// Process enemies if mode is not Area Calculation mode.
if(m_nEngineMode != GameEngine.AREA_CALCULATE_MODE){
try{
int nCollision = 0;
for(int i = 0; i < m_nNumberOfEnemies; i++){
if(m_objEnemy[i].m_nDelayCounter >= m_objEnemy[i].m_nDelay){
m_objEnemy[i].m_nDelayCounter = 0;
m_objEnemy[i].move();
nCollision = checkEnemyCollision(i);
if (nCollision == ENEMY_ERIX_COLLISION) {
processLoseLife();
break;
} else if (nCollision == ENEMY_BOUNDARY_COLLISION) {
m_objEnemy[i].setDirection(Enemy.ENEMY_BOUNCE_DIRECTION);
}
} else {
m_objEnemy[i].m_nDelayCounter++;
}
}
} catch(Exception e) {
System.out.println("Exception in Enemy movement - "+e);
}
}
if (m_nEngineMode == GameEngine.LIFE_LOSE_MODE) {
continue;
}
//Process Erix only if it was moving.
if (m_objErix.m_bErixMoving) {
try {
if (m_objErix.m_nDelayCounter >= m_objErix.m_nDelay) {
m_objErix.m_nDelayCounter = 0;
//Erix always moves by 2 logical points
//This is to avoid some complicated situations
//that may result if an edge of Erix's
//path is just one point long.
for (int i = 0; i < 2; i++) {
m_objErix.move();
//Check if Erix crosses himself or Enemy
//crosses erix.
if (m_objErix.isPathBeingCrossed()) {
processLoseLife();
break;
} else {
//Erix isn't crossing its own path.
//So update Erix path.
m_objErix.updatePathBitmap();
}
}
if (m_nEngineMode == GameEngine.LIFE_LOSE_MODE) {
continue;
}
try {
//Check collision of Erix with all enemies.
if (checkErixCollision()) {
processLoseLife();
}
} catch(Exception e) {
System.out.println("Exception in check ErixCollision");
}
//If Erix was inside the unsecured region ...
if (!m_objErix.m_bIsErixOnBoundary) {
// ... check if Erix
// has reached the boundary.
if (hasReachedBoundary()) {
// Request the playing of the "Region Secured" sound.
queueSound(GameEffects.REGION_SECURED_SOUND);
//Switch Engine mode to Area Calculation
//Mode.
m_nEngineMode = GameEngine.AREA_CALCULATE_MODE;
// Update count of how many moves
// were taken to complete a level.
m_nNumberOfMoves++;
//Add the current Erix position into
//Erix's path as the last position.
m_objErix.addBound();
m_objErix.m_bErixMoving = false;
m_objErix.m_bIsErixOnBoundary = true;
// Create the 2 regions created
// upon Erix's completion of a move,
// and determine that region
// out of these two,
// that is to be filled.
identifyRegions();
//Mark the selected region as secured.
markRegionForMove();
//m_objCanvas.repaint();
m_bRegionSecured = true;
//Once the region has been secured
//relocate the trapped enemies,
// if any, from the
//secured to unsecured region.
if (m_nEnemiesToRelocate == 1) {
relocateEnemies(m_arrEnemyRegion1, m_nEnemyRegion1Count);
} else {
relocateEnemies(m_arrEnemyRegion2, m_nEnemyRegion2Count);
}
//Update Area.
if (m_nAreaSecured == -1) {
if (m_nEnemiesToRelocate == 1) {
m_nAreaSecured = calculateArea(m_arrRegion1, m_nRegion1Points);
} else {
m_nAreaSecured = calculateArea(m_arrRegion2, m_nRegion2Points);
}
}
updateAreaAndScore(m_nAreaSecured);
//Reset Erix's path & bitmap.
m_objErix.resetPath();
//If Erix's path finished exactly on a
//vertex and if Erix's direction was
//same as of the edge then continue
//movement of Erix.
if (m_bContinueErixMovement) {
m_objErix.setDirection(m_objErix.m_nErixDirection);
m_bContinueErixMovement = false;
}
// Restore Engine mode to Normal,
// if it is not supposed to wait
// for the time being.
if ((m_nEngineMode != GameEngine.PRE_LEVEL_COMPLETE_MODE)
&& (m_nEngineMode != GameEngine.PRE_GAME_WIN_MODE)) {
m_nEngineMode = GameEngine.NORMAL_MODE;
}
} else {
//Erix is still inside the unsecured
//region (has not reached the boundary)
}
} else {
//Erix is Moving along boundary
//If his direction was Up/Down then check
//if his y position has reached either
//boundary start or end points.
if (m_objErix.m_nErixDirection == Erix.UP_DIRECTION
|| m_objErix.m_nErixDirection == Erix.DOWN_DIRECTION){
if (m_objErix.m_nErixYPos == m_objErix.m_nErixBoundaryStartPoint
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -