Siguiendo el tutorial de Nacho Cabanes, he terminado con la parte del juego en modo texto. Aquí os dejo el código en varias clases que se compila con gmcs y los nombres de los ficheros.
Main.cs: Pulsa para ver/ocultar el código
/* * File: Game.cs * Author: Dorian Hawkmoon * */ using System; using System.Threading; // Para Thread.Sleep using System.Diagnostics; //para el cronómetro public class main{ public static void Main(){ //mejor puntuación int bestScore=0; //tiempo para un fps de 40 fotogramas por segundo int fps=20; //cronómetro Stopwatch timeElapsed; bool endGame=false; //si el menú devuelve true, comienza el juego endGame=!menu(); while(!endGame){ //comenzamos un nuevo juego Game game; game=new Game(); //generamos obstáculos enemigos y demás game.generateObstacles(20); game.generateEnemies(2); game.generateAwards(20); //creamos un nuevo reloj timeElapsed = Stopwatch.StartNew(); ConsoleKeyInfo key; bool lostLife=false; bool end=false; while(!end && game.hasLife()){ //reseteamos el cronómetro timeElapsed.Reset(); //limpiar pantalla Console.Clear(); //mostrar datos game.paintHUD(); //dibujar game.paintAll(); if (Console.KeyAvailable){ //leer tecla key = Console.ReadKey(false); //mover personaje Moves direction=Moves.NONE; switch(key.Key){ case ConsoleKey.RightArrow: direction=Moves.RIGHT; break; case ConsoleKey.LeftArrow: direction=Moves.LEFT; break; case ConsoleKey.UpArrow: direction=Moves.UP; break; case ConsoleKey.DownArrow: direction=Moves.DOWN; break; case ConsoleKey.Escape: end=true; break; } //si choca contra la pared, deshacemos el movimiento if(!game.moveCharacter(direction)){ game.unMove(); } } lostLife=false; //comprobamos si ha chocado lostLife=game.colisionProtagonistEnemies() || game.colisionProtagonistObstacles(); //mover enemigos game.moveEnemies(); //comprobar colisión personaje lostLife=lostLife || game.colisionProtagonistEnemies(); //si ha chocado, pierde vida if(lostLife){ game.touched(); } //comprobar premios game.colisionAward(); //ajustar fps timeElapsed.Stop(); if(timeElapsed.ElapsedMillisecondsbestScore){ bestScore=game.getScore(); } //mostramos puntuaciones showScore(game.getScore(), bestScore); Console.ReadKey(false); //mostramos menú endGame=!menu(); } Console.Clear(); } //menú public static bool menu(){ Console.Clear(); ConsoleKeyInfo key; do{ Console.WriteLine("Choose an option"); Console.WriteLine("1. Play Game"); Console.WriteLine("2. Help"); Console.WriteLine("3. Exit"); key = Console.ReadKey(false); if(key.Key==ConsoleKey.D2){ help(); } }while(key.Key!=ConsoleKey.D1 && key.Key!=ConsoleKey.D3); if(key.Key==ConsoleKey.D1){ return true; }else{ return false; } } //mostramos el score private static void showScore(int score, int bestScore){ Console.Clear(); Console.WriteLine("Your final score: "+ score); Console.WriteLine("Best score: "+ bestScore); } //mostramos la ayuda private static void help(){ Console.WriteLine("El juego es tratar de sobrevivir el máximo tiempo posible recogiendo premios."+ "\n Tu personaje es verde con el símbolo @ y los enemigos azules y con el símbolo €."+ "\nSi chocas con ellos o con las paredes (rojas y de símbolo =) perderás una vida."+ "\nConsigue la mayor puntuación recogiendo los premios amarillos y de símbolo O."+ "\nEn cualquier momento te puedes rendir si pulsas ESC\n"); } }
Game.cs: Pulsa para ver/ocultar el código
/* * File: Game.cs * Author: Dorian Hawkmoon * */ using System; using System.Collections.Generic; //para las listas public class Game{ //altura y anchura de la pantalla private int height; private int width; //protagonista private Character protagonist; //lista de obstáculos private Listobstacles; //llista de enemigos private List enemies; //lista de premios private List awards; //generador de números aleatorios private Random generator; //vidas private int lifes; //puntuación private int score; //puntos por premio private int amountOfScore=10; public Game(){ generator = new Random(); //obtengo el tamaño de la ventana height=Console.WindowHeight; width=Console.WindowWidth; //punto inicial del protagonista Point point=new Point(10,10); protagonist=new Character('@', ConsoleColor.Green, point); //inicializo listas obstacles=new List (); enemies=new List (); awards=new List (); //inicializo vida y puntuación lifes=3; score=0; } public int getHeight(){ return height; } public int getWidth(){ return width; } //true si le queda vida, false al contrario public bool hasLife(){ return lifes>0; } //puntuación public int getScore(){ return score; } //pintamos los datos public void paintHUD(){ Console.SetCursorPosition(0,0); Console.Write("Lifes: {0}", lifes); Console.Write("\t"); Console.Write("Score: {0}", score); } //si es tocado... public void touched(){ lifes--; protagonist.setActualPoint(protagonist.getInitialPoint()); } //generar obstáculos public void generateObstacles(int number){ generateCharacters('=', ConsoleColor.DarkRed, number, obstacles); } //generar enemigos public void generateEnemies(int number){ generateCharacters('€', ConsoleColor.Blue, number, enemies, (float)0.25); } //generar premios public void generateAwards(int number){ generateCharacters('O', ConsoleColor.Yellow, number, awards); } //mover personaje public bool moveCharacter(Moves move){ protagonist.move(move); return !colisionWall(protagonist.getActualPoint()); } //mover enemigos public void moveEnemies(){ Moves move; int intentos; foreach (Character oneEnemy in enemies){ intentos=15; move=(generator.Next(1,5)<=2)? aleatoryMove():oneEnemy.getLastMove(); oneEnemy.move(move); while((colisionObstacles(oneEnemy) || colisionEnemies(oneEnemy) || colisionWall(oneEnemy.getActualPoint())) && intentos>0){ intentos--; oneEnemy.unMove(); move=aleatoryMove(); oneEnemy.move(move); } if(intentos==0){ oneEnemy.unMove(); } } } //pintar todo public void paintAll(){ paintProtagonist(); paintObstacles(); paintEnemies(); paintAwards(); } //deshacer movimiento del protagonista public void unMove(){ protagonist.unMove(); } //true si ha chocado con las paredes (de la pantalla) public bool colisionWall(Point point){ int x=(int)point.getPointX(); int y=(int)point.getPointY(); if(x>0 & x 0 & y list){ generateCharacters(symbol, color, numbers, list, 1); } //crea una lista de caracteres, incluyendo la velocidad private void generateCharacters(char symbol, ConsoleColor color, int numbers, List list, float velocity){ Character oneCharacter; Point position; for (int i = 0; i < numbers; i++) { int x=generator.Next(1, width); int y=generator.Next(1, height); position=new Point(x,y); oneCharacter=new Character(symbol, color, position, velocity); while(colision(oneCharacter)==true){ x=generator.Next(1, width); y=generator.Next(1, height); position=new Point(x,y); oneCharacter.setActualPoint(position); } list.Add(oneCharacter); } } }
Character.cs: Pulsa para ver/ocultar el código
/* * File: Character.cs * Author: Dorian Hawkmoon * */ using System; public class Character{ //simbolo que le representa private char symbol; //punto inicial donde aparecerá private Point initialPoint; //punto donde está private Point actualPoint; //velocidad de movimiento private float velocity; //color private ConsoleColor color; //último movimiento realizado private Moves lastMove; //constructor public Character(char symbol, ConsoleColor color, Point initialPoint) : this(symbol, color, initialPoint, 1){ } //constructor public Character(char symbol, ConsoleColor color, Point initialPoint, float velocity){ this.symbol=symbol; //creo nuevos puntos, ya que son punteros y si modifico uno, el otro también se modifica this.initialPoint=new Point(initialPoint); this.actualPoint=new Point(initialPoint); this.color=color; this.velocity=velocity; } //último movimiento public Moves getLastMove(){ return lastMove; } //mover el personaje public void move(Moves move){ lastMove=move; switch(move){ case Moves.RIGHT: actualPoint.sumX(velocity); break; case Moves.LEFT: actualPoint.sumX(-velocity); break; case Moves.UP: actualPoint.sumY(-velocity); break; case Moves.DOWN: actualPoint.sumY(velocity); break; } } //deshacer el movimiento public void unMove(){ switch(lastMove){ case Moves.RIGHT: actualPoint.sumX(-velocity); break; case Moves.LEFT: actualPoint.sumX(velocity); break; case Moves.UP: actualPoint.sumY(velocity); break; case Moves.DOWN: actualPoint.sumY(-velocity); break; } } //color del personaje public ConsoleColor getColor(){ return color; } //punto actual del personaje public Point getActualPoint(){ return actualPoint; } //modificar punto actual del personaje public void setActualPoint(Point point){ actualPoint=new Point(point); } //punto inicial del personaje public Point getInitialPoint(){ return initialPoint; } //simbolo del personaje public char getSymbol(){ return symbol; } }
Point.cs: Pulsa para ver/ocultar el código
/* * File: Game.cs * Author: Dorian Hawkmoon * */ public class Point{ private float x; private float y; public Point(float x, float y){ this.x=x; this.y=y; } public Point(Point another){ this.x=another.getPointX(); this.y=another.getPointY(); } public float getPointX() { return x; } public float getPointY() { return y; } public void setPointY(float value) { y=value; } public void setPointX(float value) { x=value; } public void sumX(float value){ x=x+value; } public void sumY(float value){ y=y+value; } public override string ToString(){ return x + " " + y; } }
Moves.cs: Pulsa para ver/ocultar el código
/* * File: Game.cs * Author: Dorian Hawkmoon * */ public enum Moves { UP, DOWN, LEFT, RIGHT, NONE};
Dichos códigos son mejorables (y por mejorables entiendo que hasta yo veo cómo mejorarlos) y es posible que termine mejorándolos y modificando las reglas del juego.