9. Not so fast!
Our program does not get blocked until we press a key... but now it moves too fast. If we want it to move at a fixed speed in any computer, we might make it wait several milliseconds after drawing each frame. For example, if we want our game to work at 25 frames per second, we might wait for 40 ms after each frame (1000 milliseconds / 25 fps = 40 ms pause):
// Pause till next fotogram Thread.Sleep(40);
In a more complex game, we should check how long have the previous tasks
taken. For example: if drawing, checking collisions and calculating new
positions have taken 8 ms, we would not wait 40 ms but 32 ms (40 minus 8),
but we will not be so careful yet.
Also, if we want our enemy to move slower than we do, we might use a "real" (instead of "integer") coordinate system for it. In this case, its speed might be less than 1 position per frame. For instance, we might increment it 0.4 positions per frame:
float xEnemy=15, yEnemy=17; float incrXEnemy=0.4f;
This has a first drawback: SetCursorPosition expects integer coordinates, so we must convert before drawing on screen:
Console.SetCursorPosition((int)xEnemy, (int)yEnemy); Console.Write("A");
Also, the limits checking must change: now we must not arrive exactly to the coordinate 79, but to 79.2, or 79.1 or any other "near but not exact" position, so we should use "greater than" and "less than" in the comparisons:
// Move enemies and environment xEnemy += incrXEnemy; if ((xEnemy < 1) || (xEnemy > 78)) incrXEnemy = -incrXEnemy;
So the resulting program might be:
/* First mini-console-game skeleton Version K: enemy moves on its own... but not so fast */ using System; using System.Threading; // For the pause with Thread.Sleep public class Game01k { public static void Main() { int x=40, y=12; int xDot1=10, yDot1=5; bool visibleDot1 = true; int xDot2=20, yDot2=15; bool visibleDot2 = true; int xDot3=60, yDot3=11; bool visibleDot3 = true; float xEnemy=15, yEnemy=17; float incrXEnemy=0.4f; int score = 0; ConsoleKeyInfo userKey; // Game Loop while( 1 == 1 ) { // Draw Console.Clear(); Console.Write("Score: {0}",score); if (visibleDot1) { Console.SetCursorPosition(xDot1, yDot1); Console.Write("."); } if (visibleDot2) { Console.SetCursorPosition(xDot2, yDot2); Console.Write("."); } if (visibleDot3) { Console.SetCursorPosition(xDot3, yDot3); Console.Write("."); } Console.SetCursorPosition(x, y); Console.Write("C"); Console.SetCursorPosition((int)xEnemy, (int)yEnemy); Console.Write("A"); // Read keys and calculate new position if (Console.KeyAvailable) { userKey = Console.ReadKey(false); if(userKey.Key == ConsoleKey.RightArrow) x++; if(userKey.Key == ConsoleKey.LeftArrow) x--; if(userKey.Key == ConsoleKey.DownArrow) y++; if(userKey.Key == ConsoleKey.UpArrow) y--; } // Move enemies and environment xEnemy += incrXEnemy; if ((xEnemy < 1) || (xEnemy > 78)) incrXEnemy = -incrXEnemy; // Collisions, lose energy or lives, etc if ((x == xDot1) && (y == yDot1) && visibleDot1) { score += 10; visibleDot1 = false; } if ((x == xDot2) && (y == yDot2) && visibleDot2) { score += 10; visibleDot2 = false; } if ((x == xDot3) && (y == yDot3) && visibleDot3) { score += 10; visibleDot3 = false; } // Pause till next fotogram Thread.Sleep(40); } } }