24. Restarting the game
Now we have three lives, but we run out of them, the game ends immediately. It would be more reasonable if we were taken back to the intro screen and we were able to start a new game easily.
To achieve this, we would need not only a "Init" function, but also another to be called each time we are going to start a new game. We might just repeat "Init", but there is no need to enter the graphic mode again, nor to load the images once more, so we will create a new function, which we might call "PrepareGameStart", and which will restart the score, the lives, the coordinates and speed for each element.
Our program would become:
/* First mini-graphics-game skeleton Version N: restarting a game */ using System; public class SdlMuncher { static bool sessionFinished = false; static int startX = 32 * 8; static int startY = 32 * 11; static int lives; static int x, y; static int pacSpeed; static int amountOfEnemies; static float[] xEnemy; static float[] yEnemy; static float[] incrXEnemy; static int[] xDot; static int[] yDot; static bool[] visible; static int amountOfDots; static Image dotImage; static Image enemyImage; static Image pacImage; static Image wallImage; static string[] map = { "-----------------", "-.......-.......-", "-.--.--.-.--.--.-", "-...............-", "-.--.-.---.-.--.-", "-....-..-..-....-", "----.--...--.----", ".................", "----.-.-.-.-.----", "-....-.-.-.-....-", "-.--.-.---.-.--.-", "-...............-", "-.--.-.---.-.--.-", "-....-.....-....-", "-----------------" }; static int score; static Font sans18; public static void Init() { bool fullScreen = false; SdlHardware.Init(800, 600, 24, fullScreen); dotImage = new Image("data/dot.png"); enemyImage = new Image("data/ghostGreen.png"); pacImage = new Image("data/pac01r.png"); wallImage = new Image("data/wall.png"); sans18 = new Font("data/Joystix.ttf", 18); } public static void PrepareGameStart() { x = startX; y = startY; pacSpeed = 4; amountOfEnemies = 4; xEnemy = new float[] { 150, 400, 500, 600 }; yEnemy = new float[] { 100, 200, 300, 400 }; incrXEnemy = new float[] { 5f, 3f, 6f, 4.5f }; // Data for the dots // First: count how many dots are there amountOfDots = 0; for (int row = 0; row < 15; row++) { for (int column = 0; column < 17; column++) { if (map[row][column] == '.') amountOfDots++; } } xDot = new int[amountOfDots]; yDot = new int[amountOfDots]; visible = new bool[amountOfDots]; // Now, assign their coordinates int currentDot = 0; for (int row = 0; row < 15; row++) { for (int column = 0; column < 17; column++) { if (map[row][column] == '.') { xDot[currentDot] = column * 32; yDot[currentDot] = row * 32; visible[currentDot] = true; currentDot++; } } } score = 0; lives = 3; } public static void Intro() { Image pac = new Image("data/pac01r.png"); Image ghost = new Image("data/ghostGreen.png"); int x = -40; bool exitIntro = false; do { SdlHardware.ClearScreen(); SdlHardware.WriteHiddenText("Hit SPACE to start", 300, 500, 0xCC, 0xCC, 0xCC, sans18); SdlHardware.WriteHiddenText("or Q to Quit", 340, 540, 0x99, 0x99, 0x99, sans18); SdlHardware.DrawHiddenImage(ghost, x - 50, 300); SdlHardware.DrawHiddenImage(pac, x, 300); SdlHardware.ShowHiddenScreen(); x += 8; if (x > 850) x = -40; SdlHardware.Pause(20); if (SdlHardware.KeyPressed(SdlHardware.KEY_SPC)) exitIntro = true; if (SdlHardware.KeyPressed(SdlHardware.KEY_Q)) { exitIntro = true; sessionFinished = true; } } while (!exitIntro); } public static bool CanMoveTo(int x, int y, string[] map) { bool canMove = true; for (int row = 0; row < 15; row++) { for (int column = 0; column < 17; column++) { if (map[row][column] == '-') if ((x > column * 32 - 32) && (x < column * 32 + 32) && (y > row * 32 - 32) && (y < row * 32 + 32) ) { canMove = false; } } } return canMove; } public static void Main() { Init(); Intro(); while (!sessionFinished) { PrepareGameStart(); // Game Loop bool gameFinished = false; while (!gameFinished) { // Draw SdlHardware.ClearScreen(); //Console.Write("Score: {0}",score); // Background map for (int row = 0; row < 15; row++) { for (int column = 0; column < 17; column++) { if (map[row][column] == '-') SdlHardware.DrawHiddenImage(wallImage, column * 32, row * 32); } } for (int i = 0; i < amountOfDots; i++) { if (visible[i]) SdlHardware.DrawHiddenImage(dotImage, xDot[i], yDot[i]); } SdlHardware.DrawHiddenImage(pacImage, x, y); for (int i = 0; i < amountOfEnemies; i++) SdlHardware.DrawHiddenImage(enemyImage, (int)xEnemy[i], (int)yEnemy[i]); SdlHardware.WriteHiddenText("Score: " + score, 610, 100, 0x80, 0x80, 0xFF, sans18); SdlHardware.WriteHiddenText("Lives: " + lives, 610, 140, 0x80, 0x80, 0xFF, sans18); SdlHardware.ShowHiddenScreen(); // Read keys and calculate new position if (SdlHardware.KeyPressed(SdlHardware.KEY_RIGHT) && CanMoveTo(x + pacSpeed, y, map)) x += pacSpeed; if (SdlHardware.KeyPressed(SdlHardware.KEY_LEFT) && CanMoveTo(x - pacSpeed, y, map)) x -= pacSpeed; if (SdlHardware.KeyPressed(SdlHardware.KEY_DOWN) && CanMoveTo(x, y + pacSpeed, map)) y += pacSpeed; if (SdlHardware.KeyPressed(SdlHardware.KEY_UP) && CanMoveTo(x, y - pacSpeed, map)) y -= pacSpeed; if (SdlHardware.KeyPressed(SdlHardware.KEY_ESC)) gameFinished = true; // Move enemies and environment for (int i = 0; i < amountOfEnemies; i++) { xEnemy[i] += incrXEnemy[i]; if ((xEnemy[i] < 1) || (xEnemy[i] > 760)) incrXEnemy[i] = -incrXEnemy[i]; } // Collisions, lose energy or lives, etc for (int i = 0; i < amountOfDots; i++) if (visible[i] && (x > xDot[i] - 32) && (x < xDot[i] + 32) && (y > yDot[i] - 32) && (y < yDot[i] + 32) ) { score += 10; visible[i] = false; } for (int i = 0; i < amountOfEnemies; i++) if ( (x > xEnemy[i] - 32) && (x < xEnemy[i] + 32) && (y > yEnemy[i] - 32) && (y < yEnemy[i] + 32) ) { x = startX; y = startY; lives--; if (lives == 0) gameFinished = true; } // Pause till next fotogram SdlHardware.Pause(40); } // end of game loop Intro(); } // end of session } // end of Main } // end of class