15. Collisions in graphic mode
In our previous versions, collisions weren't working: we cannot pick up dots, because the previous collision detection is too strict for graphics mode. It is not very likely that the X and Y coordinates of two images will be exactly the same.
A simple collision detection method which works better in this case is checking if the rectangles which contain both images are overlapping:

For example, if x2 is between x1 and x+width1, and y2 is between y1 and y+height1, there is a collision. Also, the same would happen if the rectangle "1" is on the left: x1 should be between x2 and x+width2.
In our case, the width and height for all the images is 32, so we might check collisions this way:
// 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; }
(As seen in this example, we should check collisions only with visible dot, and after "eating" a dot, we should mark it as "not visible").
The whole game would be:
/* First mini-graphics-game skeleton Version C: Collisions between player and dots */ using System; public class Game02c { public static void Main() { bool fullScreen = false; SdlHardware.Init(800, 600, 24, fullScreen); Image dotImage = new Image("dot.bmp"); Image enemyImage = new Image("ghostGreen.bmp"); Image pacImage = new Image("pac01r.bmp"); int x=40, y=12; int pacSpeed = 6; int amountOfDots = 100; int[] xDot = new int[amountOfDots]; int[] yDot = new int[amountOfDots]; bool[] visible = new bool[amountOfDots]; Random randomNumberGenerator = new Random(); for(int i=0; i<amountOfDots; i++) { xDot[i] = randomNumberGenerator.Next(0,760); yDot[i] = randomNumberGenerator.Next(40,560); visible[i] = true; } int amountOfEnemies = 4; float[] xEnemy = { 150, 400, 500, 600 }; float[] yEnemy = { 100, 200, 300, 400 }; float[] incrXEnemy = { 5f, 3f, 6f, 4.5f }; int score = 0; bool gameFinished = false; // Game Loop while( ! gameFinished ) { // Draw SdlHardware.ClearScreen(); //Console.Write("Score: {0}",score); 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.ShowHiddenScreen(); // Read keys and calculate new position if (SdlHardware.KeyPressed(SdlHardware.KEY_RIGHT)) x+=pacSpeed; if (SdlHardware.KeyPressed(SdlHardware.KEY_LEFT)) x-=pacSpeed; if (SdlHardware.KeyPressed(SdlHardware.KEY_DOWN)) y+=pacSpeed; if (SdlHardware.KeyPressed(SdlHardware.KEY_UP)) 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; } // Pause till next fotogram SdlHardware.Pause(40); } } }
And as we "eat" dots, they will disappear on screen:
