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 List obstacles;
//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 & x0 & 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.

