A complex 2D-dungeon game on LPC1768 in SWJTU-Leeds Joint School XJEL2645 project. Referenced from the framework contributed by https://os.mbed.com/users/Siriagus/code/SimplePlatformGame/

Dependencies:   mbed N5110 ShiftReg PinDetect

Revision:
16:caf613d5b85e
Parent:
15:d5eb13c4c1c6
Child:
17:d6a3b29cab31
--- a/Game.cpp	Sun May 10 09:37:51 2015 +0000
+++ b/Game.cpp	Sun May 10 13:14:33 2015 +0000
@@ -3,7 +3,7 @@
 Serial pc(USBTX, USBRX); // TO DELETE - DEBUGGING ONLY
 
 void Game::init()
-{
+{   
     paused = false;
     
     // Set initial values for the player
@@ -11,15 +11,19 @@
     player.y = 5;  // start y
     player.width = player.height = 5; // important that this is correct, see size of Image::Player in Resources.h
     player.onGround = false;
-    
-    enemy = new Enemy(75, 3, 6, 5);
-    enemy->vx = -2;
+}
+
+void Game::spawnEnemy()
+{
+    Enemy *enemy = new Enemy(75, 3, 5, 5, Enemy::SIMPLE);
+    enemy->vx = -1;
     enemy->facingLeft = true;
+    enemies.push_back(enemy);
 }
 
 // Functions
 void Game::update(float dt)
-{
+{    
     // Pause button input
     if (input->read(Input::ButtonC))
     {
@@ -36,8 +40,9 @@
     if (paused) return;
     
     
-    
-    
+    if ((rand() % 100) > 93)
+        spawnEnemy();
+        
     // Handle input, should be its own function
     switch(input->joystick->getDirection())
     {
@@ -60,23 +65,11 @@
         break;
     }
     
-    // Random movement for enemies
-    if (enemy->onGround && (rand() % 100) > 97) // 3 % chance
-    {
-        // jump
-        enemy->vy = -3;
-        enemy->onGround = false;
-    }
-    else if ((rand() % 100) > 98) // 2% chance
-    {
-        // switch direction
-        enemy->vx *= -1; 
-        enemy->facingLeft = (enemy->vx < 0);
-    }
+    
+    // MOVE: Random enemies
     
     // Gravity
     player.vy += 1;
-    enemy->vy += 1;
     
     // Check if player is trying to jump. Player can only jump if it's on the ground
     if (input->read(Input::ButtonA) && player.onGround)
@@ -89,32 +82,10 @@
     if (player.vy > TERMINAL_VELOCITY) player.vy = TERMINAL_VELOCITY;
     
     moveWithCollisionTest(&player, map);
-    
-    if (!enemy->dead)
-        moveWithCollisionTest(enemy, map);
-    else
-    {
-        enemy->y += enemy->vy;
-        enemy->x += enemy->vx;
-    }
-    // else if (enemy->y >= HEIGHT) ; // TODO : delete enemy
+    moveEnemies();
     
-    // Enemy AI
-    if (!enemy->dead)
-    {
-        int nextRight = enemy->getRight() + 1;   // Next position of right edge if enemy moves to the right
-        for (int i = 0; i < enemy->height; ++i)  // Check for all heighs
-        {
-            // Check if crashing if moving right or left. Bounds should already be limited by moveWithCollisionTest!
-            // will also try to climb a slope if it can find one
-            if ((map[enemy->y + i][nextRight] && map[enemy->y+i-1][nextRight]) || (map[enemy->y + i][enemy->x - 1] && map[enemy->y + i-1][enemy->x - 1]))
-            {
-                enemy->vx *= -1; // move in opposite direction
-                enemy->facingLeft = !enemy->facingLeft; // toggle direction
-                break;          // no further testing required
-            }
-        }
-    }
+
+    // else if (enemy->y >= HEIGHT) ; // TODO : delete enemy
     
     // Check if bullet should be fired
     if (input->read(Input::ButtonB) && releasedBtnB)
@@ -160,16 +131,20 @@
             // loop through all enemies
             //bullet // point
             //enemy // entity
-            
-            if (!enemy->dead && bullet->x >= enemy->x && bullet->x <= enemy->getRight() && bullet->y >= enemy->y && bullet->y <= enemy->getBottom()) 
+            for (std::vector<Enemy*>::iterator it = enemies.begin(); it != enemies.end(); ++it)
             {
-                col = true;
-                // break; // todo: make for loop - iterate through all enemies
-                enemy->vx = bullet->vx / 2; // sends the dead enemy in the same direction as the incoming bullet
-                enemy->vy = -3;             // sends the dead enemy upwards in the air, because of impact
+                Enemy *enemy = *it;
                 
-                enemy->dead = true;
-                // remove enemy - todo: make vector
+                if (!enemy->dead && bullet->x >= enemy->x && bullet->x <= enemy->getRight() && bullet->y >= enemy->y && bullet->y <= enemy->getBottom()) 
+                {
+                    col = true;
+                    // break; // todo: make for loop - iterate through all enemies
+                    enemy->vx = bullet->vx / 2; // sends the dead enemy in the same direction as the incoming bullet
+                    enemy->vy = -3;             // sends the dead enemy upwards in the air, because of impact
+                    
+                    enemy->dead = true;
+                    // remove enemy - todo: make vector
+                }
             }
         }
         
@@ -198,28 +173,12 @@
     drawImage(Image::Player, player.x, player.y, false, !player.facingLeft);
     
     // Draw enemies
-    drawImage(Image::Enemy3, enemy->x, enemy->y, false, !enemy->facingLeft, enemy->dead);
-    
-    /*
-    // Draw player - TODO: Make this a part of sprite class (so they can draw themselves)
-    int x0, x1, y0, y1;
-    x0 = (player.x < 0) ? 0 : player.x;                       // x0 = max(0,x);
-    y0 = (player.y < 0) ? 0 : player.y;                       // y0 = max(0,y);
-    x1 = (player.width + player.x > WIDTH) ? WIDTH : player.width + player.x;       //x1 = min(WIDTH, width);
-    y1 = (player.height + player.y > HEIGHT) ? HEIGHT : player.height + player.y;   //y1 = min(HEIGHT, height);
-    
-    for (int i = y0; i < y1; ++i)
-    {   
-        for (int j = x0; j < x1; ++j)
-        {
-            // If player is going right, obtain data from sprite in reverse order => render in reverse
-            int xIndex = (player.facingLeft) ? (j-x0) : (player.width - 1 - (j-x0));
-            
-            if (Image::Player[i-y0][xIndex])
-                lcd->setPixel(j,i);
-        }
-    }*/
-    
+    for (std::vector<Enemy*>::iterator it = enemies.begin(); it != enemies.end(); ++it)
+    {
+        Enemy *enemy = *it;
+        drawImage(Image::EnemySimple, enemy->x, enemy->y, false, !enemy->facingLeft, enemy->dead);
+    }    
+
     // Render bullets
     for (std::vector<Point*>::iterator it = bullets.begin(); it != bullets.end(); ++it)
     {
@@ -256,6 +215,11 @@
         while(steps--) // While it still have more movement left
         {
             collision = false;
+            
+            // Wrapping
+            if (entityRight+1 >= WIDTH)
+                entityRight = -1;// wants entityRight = -1, so next check is entityRight 0*/
+            
             for (int i = 0; i < entity->height; ++i) // Loop through all vertical points on the right hand side of the entity (y+i)
             {
                 if (map[y+i][entityRight+1]) // If moving to the right leads to collision for given y+i
@@ -280,6 +244,10 @@
                 ++entityRight;  // Move entity one px to the right
         }
         
+        // If wrap didn't work, make sure entity is on the correct side of the map
+        if (entityRight < 0)
+            entityRight = WIDTH-1;
+            
         entity->x = entityRight - (entity->width - 1); // Update entity's position. Need to set upper-left pixel.
     }
     else // moving left
@@ -288,9 +256,14 @@
         {
             collision = false;
             
+            // Wrap around map
+            if (x-1 < 0)
+                x = WIDTH; // causes x-1 in the next check to be WIDTH - 1
             
-            for (int i = 0; i < entity->height; ++i) // Check for all y-positions
+            // Check for all y-positions
+            for (int i = 0; i < entity->height; ++i)
             {
+                
                 if (map[y+i][x-1])                  // If solid block
                 {
                     if (!map[y+i-1][x-1] && entity->onGround) // If slope or close to top of wall (=> can climb by going left).
@@ -311,11 +284,12 @@
                 --x;    // Move to the left if no collision is detected
         }
         
-        entity->x = x;
+        x %= WIDTH; // In case wrapping caused entity to crash with wall on other side, x should be 0 instead of WIDTH (invalid).
+        
+        entity->x = x; // update position
     }
     
     // Check collision with map in y-direction - works the same way as the x-axis, except for other axis
-    
     x = entity->x;
     y = entity->y;
     steps = abs(entity->vy);
@@ -326,9 +300,10 @@
         while(steps--)  // Still movement left
         {
             collision = false;
+
             for (int i = 0; i < entity->width; ++i)  // Loop through all x-position on lower part of entity
-            {
-                if (map[entityBottom+1][x+i])       // If moving the entity one step down for a given (x+i)-position gives a collision
+            {   
+                if (map[(entityBottom+1) % HEIGHT][x+i])       // If moving the entity one step down for a given (x+i)-position gives a collision
                 {
                     collision = true;
                     break;                          // No further testing required
@@ -348,17 +323,24 @@
             }
         }
         
-        entity->y = entityBottom - (entity->height - 1);      // Update position when done moving, remember that entity.y refers to upper part of the entity
+        // Wrapping
+        y = (entityBottom - (entity->height - 1));
+        if (y >= HEIGHT)            // if completely outside map
+            y = -entity->height;    // wrap to top of map
+            
+        entity->y = y; // (entityBottom - (entity->height - 1));      // Update position when done moving, remember that entity.y refers to upper part of the entity
     }
     else // moving up, check collision from top
     {
         while(steps--)  // Still movement left
         {
             collision = false;
-            
+                            
             for (int i = 0; i < entity->width; ++i) // Check for all x-positions
             {
-                if (map[y-1][x+i])                  // If moving upwards gives collision for a given x+i
+                int y1 = ((y-1) + HEIGHT) % HEIGHT; // In case negative, because of wrapping
+                
+                if (map[y1][x+i])                  // If moving upwards gives collision for a given x+i
                 {
                     collision = true;               // Then we have a collision
                     break;                          // No further testing needed, skip for loop
@@ -374,6 +356,10 @@
                 --y;        // Move entity one step up
         }
         
+        // Wrapping
+        if (y + (entity->height - 1) < 0)          // completely outside map (bottom of entity over top of map)
+            y = HEIGHT-1 - entity->height - 1;     // Sets the altitude.
+            
         entity->y = y;       // Update vertical position of entity
     }    
 }
@@ -397,4 +383,53 @@
     }
     
     return false;
+}
+
+void Game::moveEnemies()
+{
+    for (std::vector<Enemy*>::iterator it = enemies.begin(); it != enemies.end(); ++it)
+    {   
+        Enemy *enemy = *it;
+        
+        // Random movement for enemies
+        if (enemy->onGround && (rand() % 100) > 97) // 3 % chance
+        {
+            // jump
+            enemy->vy = -3;
+            enemy->onGround = false;
+        }
+        else if ((rand() % 100) > 98) // 2% chance
+        {
+            // switch direction
+            enemy->vx *= -1;
+            enemy->facingLeft = (enemy->vx < 0);
+        }
+        
+        // Gravity
+        enemy->vy += 1;
+        
+        if (!enemy->dead)
+        {
+            moveWithCollisionTest(enemy, map);
+            
+            // Enemy AI
+            int nextRight = enemy->getRight() + 1;   // Next position of right edge if enemy moves to the right
+            nextRight %= WIDTH; // wrapping
+            for (int i = 0; i < enemy->height; ++i)  // Check for all heighs
+            {
+                // Check if crashing if moving right or left. Bounds should already be limited by moveWithCollisionTest!
+                if (map[enemy->y + i][nextRight] || map[enemy->y + i][enemy->x - 1])
+                {
+                    enemy->vx *= -1; // move in opposite direction
+                    enemy->facingLeft = !enemy->facingLeft; // toggle direction
+                    break;          // no further testing required
+                }
+            }
+        }
+        else
+        {
+            enemy->y += enemy->vy;
+            enemy->x += enemy->vx;
+        }
+    }   
 }
\ No newline at end of file