Practicando el primer juego guiado II

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.

Etiquetas: ,. Guarda el enlace permanente.

Deja un comentario ^^