forked from University/epr24pr42-ojanssen2
feat: finished implementing ghost, started working on infomodus
This commit is contained in:
parent
11ab3ee46d
commit
c856139997
17 changed files with 361 additions and 156 deletions
|
@ -2,13 +2,13 @@
|
||||||
#include "../Environment/Maze.h"
|
#include "../Environment/Maze.h"
|
||||||
|
|
||||||
namespace game {
|
namespace game {
|
||||||
Entity::Entity(PositionVector starting_position, char display_character): pos(starting_position), display_character(display_character), move_left(true){}
|
Entity::Entity(const Vector2d starting_position, const char display_character): pos(starting_position), display_character(display_character), move_left(true){}
|
||||||
|
|
||||||
bool Entity::is_at_position(const PositionVector& position) const {
|
bool Entity::is_at_position(const Vector2d& position) const {
|
||||||
return this->pos.eq(position);
|
return this->pos.eq(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::tick(Maze& maze, const PositionVector& player_position){
|
void Entity::tick(const Maze& maze, const Vector2d& player_position){
|
||||||
switch (this->display_character) {
|
switch (this->display_character) {
|
||||||
case 'A':
|
case 'A':
|
||||||
// No thoughts, head empty :P
|
// No thoughts, head empty :P
|
||||||
|
@ -20,12 +20,14 @@ namespace game {
|
||||||
this->handle_connelly(maze, player_position);
|
this->handle_connelly(maze, player_position);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
|
cout << "ERR: THIS IS NOT A GHOST!";
|
||||||
|
/// This case will never happen
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::handle_bowie(Maze& maze) {
|
void Entity::handle_bowie(const Maze& maze) {
|
||||||
PositionVector target_position = {this->pos.x, this->pos.y};
|
Vector2d target_position = this->pos;
|
||||||
if (this->move_left)
|
if (this->move_left)
|
||||||
target_position.change_x(-1);
|
target_position.change_x(-1);
|
||||||
else
|
else
|
||||||
|
@ -36,14 +38,67 @@ namespace game {
|
||||||
this->move_left = !this->move_left;
|
this->move_left = !this->move_left;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::handle_connelly(Maze& maze, const PositionVector& player_position) {
|
bool Entity::connelly_move_up(const Maze& maze) {
|
||||||
PositionVector diff = maze.get_distance_pos1_pos2(player_position, this->pos);
|
Vector2d top = this->pos.get_new_updated(0, 1);
|
||||||
PositionVector normalized_diff = {diff.x, diff.y};
|
if (maze.is_pos_free(top, false)) {
|
||||||
normalized_diff.normalize();
|
this->pos = top;
|
||||||
PositionVector target_position = {this->pos.x, this->pos.y};
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char Entity::get_display_character() {
|
bool Entity::connelly_move_down(const Maze& maze) {
|
||||||
|
Vector2d bottom = this->pos.get_new_updated(0, -1);
|
||||||
|
if (maze.is_pos_free(bottom, false)) {
|
||||||
|
this-> pos = bottom;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Entity::connelly_move_left(const Maze& maze) {
|
||||||
|
Vector2d left = this->pos.get_new_updated(-1, 0);
|
||||||
|
if (maze.is_pos_free(left, false)) {
|
||||||
|
this->pos = left;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Entity::connelly_move_right(const Maze& maze) {
|
||||||
|
Vector2d right = this->pos.get_new_updated(1, 0);
|
||||||
|
if (maze.is_pos_free(right, false)) {
|
||||||
|
this->pos = right;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entity::handle_connelly(const Maze& maze, const Vector2d& player_position) {
|
||||||
|
Vector2d diff = maze.get_delta_vector(player_position, this->pos);
|
||||||
|
Vector2d normalized = diff.normalize();
|
||||||
|
|
||||||
|
if ((normalized.y == normalized.x || normalized.y > normalized.x) && normalized.y != 0) {
|
||||||
|
if (diff.y > 0 ) {
|
||||||
|
if (this->connelly_move_up(maze))
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (this->connelly_move_down(maze))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (normalized.x != 0) {
|
||||||
|
if (diff.x > 0){
|
||||||
|
if (this->connelly_move_right(maze))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bool _ = this->connelly_move_left(maze);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char Entity::get_display_character() const {
|
||||||
return this->display_character;
|
return this->display_character;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include "../Util/PositionVector.h"
|
#include "../Util/Vector2d.h"
|
||||||
|
|
||||||
|
|
||||||
#ifndef ENTITY_H
|
#ifndef ENTITY_H
|
||||||
#define ENTITY_H
|
#define ENTITY_H
|
||||||
|
@ -7,19 +6,60 @@
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
class Maze;
|
class Maze;
|
||||||
|
/// Eine Entität, z.B. ein Geist
|
||||||
class Entity {
|
class Entity {
|
||||||
private:
|
private:
|
||||||
PositionVector pos;
|
/// Die aktuelle Position des Geistes
|
||||||
|
Vector2d pos;
|
||||||
|
/// Wie der Geist dargestellt werden sollte
|
||||||
char display_character;
|
char display_character;
|
||||||
|
/// Ist wahr, wenn der Bowie nach Links läuft, falsch, wenn er nach Rechts läuft.
|
||||||
bool move_left;
|
bool move_left;
|
||||||
|
|
||||||
void handle_bowie(Maze& maze);
|
/// Behandle Bowie Bewegungen
|
||||||
void handle_connelly(Maze& maze, const PositionVector& player_position);
|
/// @param maze Das Labyrinth
|
||||||
|
void handle_bowie(const Maze& maze);
|
||||||
|
|
||||||
|
/// Behandle Connelly Bewegungen
|
||||||
|
/// @param maze Das Labyrinth
|
||||||
|
/// @param player_position Die Position des Spielers
|
||||||
|
void handle_connelly(const Maze& maze, const Vector2d& player_position);
|
||||||
|
|
||||||
|
/// Versuche den Connelly nach oben zu bewegen
|
||||||
|
/// @param maze Das Labyrinth
|
||||||
|
/// @returns Ob die Bewegung geglückt hat
|
||||||
|
bool connelly_move_up(const Maze& maze);
|
||||||
|
|
||||||
|
/// Versuche den Connelly nach unten zu bewegen
|
||||||
|
/// @param maze Das Labyrinth
|
||||||
|
/// @returns Ob die Bewegung geglückt hat
|
||||||
|
bool connelly_move_down(const Maze& maze);
|
||||||
|
|
||||||
|
/// Versuche den Connelly nach links zu bewegen
|
||||||
|
/// @param maze Das Labyrinth
|
||||||
|
/// @returns Ob die Bewegung geglückt hat
|
||||||
|
bool connelly_move_left(const Maze& maze);
|
||||||
|
|
||||||
|
/// Versuche den Connelly nach Rechts zu bewegen
|
||||||
|
/// @param maze Das Labyrinth
|
||||||
|
/// @returns Ob die Bewegung geglückt hat
|
||||||
|
bool connelly_move_right(const Maze& maze);
|
||||||
public:
|
public:
|
||||||
Entity(PositionVector starting_position, char display_character);
|
Entity(Vector2d starting_position, char display_character);
|
||||||
void tick(Maze& maze, const PositionVector& player_position);
|
|
||||||
bool is_at_position(const PositionVector& position) const;
|
/// Halte den Entität bzw. den Geist up to date, bewege ihn
|
||||||
char get_display_character();
|
/// @param maze Das Labyrinth
|
||||||
|
/// @param player_position Die Position des Spielers
|
||||||
|
void tick(const Maze& maze, const Vector2d& player_position);
|
||||||
|
|
||||||
|
/// Kontrolliere, ob sich das Entity auf einer Position befindet
|
||||||
|
/// @param position Die Position
|
||||||
|
/// @returns Ob das sich das Entity auf der Position befindet
|
||||||
|
bool is_at_position(const Vector2d& position) const;
|
||||||
|
|
||||||
|
/// Besorge dir das Zeichen, was auf dem Labyrinth angezeigt werden soll
|
||||||
|
/// @returns Das Zeichen
|
||||||
|
char get_display_character() const;
|
||||||
};
|
};
|
||||||
} // game
|
} // game
|
||||||
|
|
||||||
|
|
|
@ -14,23 +14,23 @@ namespace game
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Player::Player(const PositionVector pos) : pos(pos), keys_in_inventory(0)
|
Player::Player(const Vector2d pos) : pos(pos), keys_in_inventory(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PositionVector Player::get_pos() const
|
Vector2d Player::get_pos() const
|
||||||
{
|
{
|
||||||
return this->pos;
|
return this->pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::update_position(const PositionVector& target)
|
void Player::update_position(const Vector2d& target)
|
||||||
{
|
{
|
||||||
this->pos = target;
|
this->pos = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maze Player::handle_move(Maze& maze, const PositionVector& move_vector)
|
Maze Player::handle_move(Maze& maze, const Vector2d& move_vector)
|
||||||
{
|
{
|
||||||
const PositionVector target_position = PositionVector(this->get_pos().x + move_vector.x,
|
const Vector2d target_position = Vector2d(this->get_pos().x + move_vector.x,
|
||||||
this->get_pos().y + move_vector.y);
|
this->get_pos().y + move_vector.y);
|
||||||
|
|
||||||
if (maze.is_pos_free(target_position, this->has_key_available()))
|
if (maze.is_pos_free(target_position, this->has_key_available()))
|
||||||
|
@ -43,21 +43,21 @@ namespace game
|
||||||
}
|
}
|
||||||
|
|
||||||
Maze Player::handle_user_input(Maze& maze, const char& input) {
|
Maze Player::handle_user_input(Maze& maze, const char& input) {
|
||||||
PositionVector move_vector = {0, 0};
|
Vector2d move_vector = {0, 0};
|
||||||
|
|
||||||
switch (input) {
|
switch (input) {
|
||||||
case 'w':
|
case 'w':
|
||||||
move_vector = {-1, 0};
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
move_vector = {1, 0};
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
move_vector = {0, -1};
|
move_vector = {0, -1};
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 's':
|
||||||
move_vector = {0, 1};
|
move_vector = {0, 1};
|
||||||
break;
|
break;
|
||||||
|
case 'a':
|
||||||
|
move_vector = {-1, 0};
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
move_vector = {1, 0};
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->handle_move(maze, move_vector);
|
this->handle_move(maze, move_vector);
|
||||||
|
@ -80,7 +80,7 @@ namespace game
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GameState Player::handle_collisions(const Game& game, const Maze& maze) {
|
GameState Player::handle_collisions(const Game& game, const Maze& maze) const {
|
||||||
char field_at_pos = maze.get_field(this->get_pos());
|
char field_at_pos = maze.get_field(this->get_pos());
|
||||||
// Game state sanity check
|
// Game state sanity check
|
||||||
if (game.get_state() != GameState::RUNNING)
|
if (game.get_state() != GameState::RUNNING)
|
||||||
|
@ -96,9 +96,9 @@ namespace game
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Player::tick(const Game& game, Maze& maze) {
|
GameState Player::tick(const Game& game, Maze& maze) {
|
||||||
this->handle_keys(maze);
|
this->handle_keys(maze);
|
||||||
this->handle_collisions(game, maze);
|
return this->handle_collisions(game, maze);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::has_key_available() const
|
bool Player::has_key_available() const
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "../Util/PositionVector.h"
|
#include "../Util/Vector2d.h"
|
||||||
#include "../Util/GameState.h"
|
#include "../Util/GameState.h"
|
||||||
|
|
||||||
#ifndef PLAYER_H
|
#ifndef PLAYER_H
|
||||||
|
@ -17,14 +17,14 @@ namespace game
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/// Die Position des Spielers
|
/// Die Position des Spielers
|
||||||
PositionVector pos;
|
Vector2d pos;
|
||||||
int keys_in_inventory;
|
int keys_in_inventory;
|
||||||
|
|
||||||
/// Bewege den Splieler um den Bewegungsvektor, insofern die Zielposition begehbar ist
|
/// Bewege den Splieler um den Bewegungsvektor, insofern die Zielposition begehbar ist
|
||||||
/// @param maze Das Maze
|
/// @param maze Das Maze
|
||||||
/// @param move_vector Die gewollte Bewegung
|
/// @param move_vector Die gewollte Bewegung
|
||||||
/// @return Die neue Position des Spielers
|
/// @return Die neue Position des Spielers
|
||||||
Maze handle_move(Maze& maze, const PositionVector& move_vector);
|
Maze handle_move(Maze& maze, const Vector2d& move_vector);
|
||||||
|
|
||||||
/// Gebe oder Nehme dem Spieler Schlüssel
|
/// Gebe oder Nehme dem Spieler Schlüssel
|
||||||
/// Updated auch das Maze (Reference!)
|
/// Updated auch das Maze (Reference!)
|
||||||
|
@ -33,7 +33,7 @@ namespace game
|
||||||
|
|
||||||
/// Kontrolliere, ob der Spieler gerade in einem Geist steht
|
/// Kontrolliere, ob der Spieler gerade in einem Geist steht
|
||||||
/// @param maze Das Maze
|
/// @param maze Das Maze
|
||||||
GameState handle_collisions(const Game& game, const Maze& maze);
|
GameState handle_collisions(const Game& game, const Maze& maze) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Ein Spieler.
|
/// Ein Spieler.
|
||||||
|
@ -44,21 +44,26 @@ namespace game
|
||||||
|
|
||||||
/// Ein Spieler
|
/// Ein Spieler
|
||||||
/// @param pos Die Startposition des Spielers
|
/// @param pos Die Startposition des Spielers
|
||||||
explicit Player(PositionVector pos);
|
explicit Player(Vector2d pos);
|
||||||
|
|
||||||
/// Kriege die Position des Spielers
|
/// Kriege die Position des Spielers
|
||||||
/// @return Die Position des Spielers
|
/// @return Die Position des Spielers
|
||||||
PositionVector get_pos() const;
|
Vector2d get_pos() const;
|
||||||
|
|
||||||
/// Aktuallisiere die Position des Spielers ohne weitere Checks
|
/// Aktuallisiere die Position des Spielers ohne weitere Checks
|
||||||
/// @param target Das ziel
|
/// @param target Das ziel
|
||||||
void update_position(const PositionVector& target);
|
void update_position(const Vector2d& target);
|
||||||
|
|
||||||
///
|
/// Behandle die eingabe des Nutzers für den Spieler
|
||||||
|
/// @param maze Das Labyrinth
|
||||||
|
/// @param input Die Eingabe des Nutzers
|
||||||
Maze handle_user_input(Maze& maze, const char& input);
|
Maze handle_user_input(Maze& maze, const char& input);
|
||||||
|
|
||||||
///
|
/// Halte den Spieler aktuell
|
||||||
void tick(const Game& game, Maze& maze);
|
/// @param game Das Spiel
|
||||||
|
/// @param maze Das Labyrinth
|
||||||
|
/// @returns Der Status des Spiels
|
||||||
|
GameState tick(const Game& game, Maze& maze);
|
||||||
|
|
||||||
/// Check, if a player has at least one key
|
/// Check, if a player has at least one key
|
||||||
/// @return If the player as an available key
|
/// @return If the player as an available key
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "../Entities/Player.h"
|
|
||||||
#include "Maze.h"
|
#include "Maze.h"
|
||||||
#include "../Exceptions/MovementNotPossible.h"
|
#include "../Exceptions/MovementNotPossible.h"
|
||||||
#include "../Exceptions/UnkownAction.h"
|
#include "../Exceptions/UnkownAction.h"
|
||||||
#include "../Util/PositionVector.h"
|
#include "../Util/Vector2d.h"
|
||||||
|
|
||||||
using game::Player;
|
using game::Player;
|
||||||
using game::Maze;
|
using game::Maze;
|
||||||
|
@ -12,11 +11,12 @@ using game_exceptions::MovementNotPossible;
|
||||||
|
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
Game::Game(Maze& maze): maze(maze), player(0, 0), infomode_enabled(false), state(GameState::RUNNING), enemies({})
|
Game::Game(Maze& maze) : maze(maze), player(0, 0), enemies({}), state(GameState::RUNNING), infomode_enabled(false)
|
||||||
{
|
{
|
||||||
PositionVector player_start_position = this->maze.get_player_start_position();
|
Vector2d player_start_position = this->maze.get_player_start_position();
|
||||||
|
|
||||||
this->player = Player(player_start_position);
|
this->player = Player(player_start_position);
|
||||||
|
this->enemies = maze.get_entities();
|
||||||
}
|
}
|
||||||
|
|
||||||
GameState Game::get_state() const {
|
GameState Game::get_state() const {
|
||||||
|
@ -32,8 +32,12 @@ namespace game
|
||||||
case 's':
|
case 's':
|
||||||
case 'd':
|
case 'd':
|
||||||
break;
|
break;
|
||||||
|
case 'i':
|
||||||
|
this->infomode_enabled = !this->infomode_enabled;
|
||||||
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
this->state = GameState::QUITTING;
|
this->state = GameState::QUITTING;
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
cout <<
|
cout <<
|
||||||
"Du wurdest von einem Zauberer in ein Labyrinth gesperrt, nachdem du seine Künste beleidigt hast.\n"
|
"Du wurdest von einem Zauberer in ein Labyrinth gesperrt, nachdem du seine Künste beleidigt hast.\n"
|
||||||
|
@ -46,14 +50,15 @@ namespace game
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Game::is_enemy_at_pos(const PositionVector& position) const{
|
bool Game::is_enemy_at_pos(const Vector2d& position) const {
|
||||||
for (Entity e : this->enemies)
|
for (Entity e : this->enemies)
|
||||||
if (e.is_at_position(position))
|
if (e.is_at_position(position))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Game::should_end_game() {
|
bool Game::should_end_game() const
|
||||||
|
{
|
||||||
return this->state != GameState::RUNNING;
|
return this->state != GameState::RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +69,7 @@ namespace game
|
||||||
// Hauptschleife
|
// Hauptschleife
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
this->maze.render(this->player, this->enemies);
|
this->maze.render(this->player, this->enemies, this->infomode_enabled);
|
||||||
|
|
||||||
if (this->maze.is_player_at_goal(this->player))
|
if (this->maze.is_player_at_goal(this->player))
|
||||||
{
|
{
|
||||||
|
@ -74,6 +79,9 @@ namespace game
|
||||||
|
|
||||||
cin >> game_input;
|
cin >> game_input;
|
||||||
|
|
||||||
|
if (!cin)
|
||||||
|
this->state = GameState::QUITTING;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
this->handle_user_input(game_input);
|
this->handle_user_input(game_input);
|
||||||
|
@ -86,12 +94,12 @@ namespace game
|
||||||
cout << err.what() << "\n";
|
cout << err.what() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
this->player.tick(*this, this->maze);
|
this->state = this->player.tick(*this, this->maze);
|
||||||
|
|
||||||
for (Entity e : this->enemies)
|
for (Entity& e : this->enemies)
|
||||||
e.tick(this->maze, this->player.get_pos());
|
e.tick(this->maze, this->player.get_pos());
|
||||||
|
|
||||||
this->player.tick(*this, this->maze);
|
this->state = this->player.tick(*this, this->maze);
|
||||||
|
|
||||||
if (this->should_end_game())
|
if (this->should_end_game())
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace game
|
||||||
void handle_user_input(const char& input);
|
void handle_user_input(const char& input);
|
||||||
|
|
||||||
/// Kontrolliere, ob das Spiel beendet werden sollte
|
/// Kontrolliere, ob das Spiel beendet werden sollte
|
||||||
bool should_end_game();
|
bool should_end_game() const;
|
||||||
|
|
||||||
/// Starte das Spiel
|
/// Starte das Spiel
|
||||||
void run_game();
|
void run_game();
|
||||||
|
@ -42,7 +42,10 @@ namespace game
|
||||||
/// @returns Den aktuellen Status
|
/// @returns Den aktuellen Status
|
||||||
GameState get_state() const;
|
GameState get_state() const;
|
||||||
|
|
||||||
bool is_enemy_at_pos(const PositionVector& position) const ;
|
/// Krontroliere ob ein Geist sich an einer Position befindet
|
||||||
|
/// @param position Die Position
|
||||||
|
/// @returns Ob sich dort ein Geist aufhält
|
||||||
|
bool is_enemy_at_pos(const Vector2d& position) const ;
|
||||||
};
|
};
|
||||||
} // game
|
} // game
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,18 @@
|
||||||
#include "../Entities/Player.h"
|
#include "../Entities/Player.h"
|
||||||
#include "../Exceptions/MalformedMaze.h"
|
#include "../Exceptions/MalformedMaze.h"
|
||||||
#include "../Entities/Entity.h"
|
#include "../Entities/Entity.h"
|
||||||
|
#include "../Util/MathUtil.h"
|
||||||
|
|
||||||
using game_exceptions::MalformedMaze;
|
using game_exceptions::MalformedMaze;
|
||||||
|
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
Maze::Maze(const vector<vector<char>> play_field, const vector<int> player_start_position, const vector<Entity> enemies):
|
class MathUtil;
|
||||||
|
|
||||||
|
Maze::Maze(const vector<vector<char>>& play_field, const vector<int>& player_start_position, const vector<Entity>& enemies):
|
||||||
field(play_field),
|
field(play_field),
|
||||||
player_start_position(PositionVector{player_start_position[1], player_start_position[0]})
|
player_start_position(Vector2d{player_start_position[1], player_start_position[0]}),
|
||||||
|
enemies(enemies)
|
||||||
{
|
{
|
||||||
if (!this->is_pos_free(this->player_start_position, false))
|
if (!this->is_pos_free(this->player_start_position, false))
|
||||||
throw MalformedMaze("Player oob");
|
throw MalformedMaze("Player oob");
|
||||||
|
@ -25,7 +29,7 @@ namespace game
|
||||||
return this->field[player.get_pos().y][player.get_pos().x] == 'Z';
|
return this->field[player.get_pos().y][player.get_pos().x] == 'Z';
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Maze::is_pos_free(const PositionVector& pos, const bool& player_has_key) const
|
bool Maze::is_pos_free(const Vector2d& pos, const bool& player_has_key) const
|
||||||
{
|
{
|
||||||
if (pos.x < 0 || pos.y < 0 || pos.y > field.size() - 1 || pos.x > field[pos.y].size() - 1)
|
if (pos.x < 0 || pos.y < 0 || pos.y > field.size() - 1 || pos.x > field[pos.y].size() - 1)
|
||||||
return false;
|
return false;
|
||||||
|
@ -36,7 +40,7 @@ namespace game
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maze::render(const Player& player, const vector<Entity> entities) const
|
void Maze::render(const Player& player, const vector<Entity> entities, const bool& infomode_enabled)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < field.size(); ++y)
|
for (int y = 0; y < field.size(); ++y)
|
||||||
{
|
{
|
||||||
|
@ -56,38 +60,56 @@ namespace game
|
||||||
}
|
}
|
||||||
cout << " ";
|
cout << " ";
|
||||||
}
|
}
|
||||||
|
if (y == 0 && infomode_enabled)
|
||||||
|
{
|
||||||
|
int steps = this->calculate_steps_until_win(player.get_pos(), 5);
|
||||||
|
if (steps > 999)
|
||||||
|
cout << steps << "Schritte bis zum Ziel";
|
||||||
|
}
|
||||||
cout << "\n";
|
cout << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char Maze::get_field(const PositionVector& pos) const
|
char Maze::get_field(const Vector2d& pos) const
|
||||||
{
|
{
|
||||||
return this->field[pos.y][pos.x];
|
return this->field[pos.y][pos.x];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maze::update_field(const PositionVector& pos, const char& target)
|
void Maze::update_field(const Vector2d& pos, const char& target)
|
||||||
{
|
{
|
||||||
this->field[pos.y][pos.x] = target;
|
this->field[pos.y][pos.x] = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
PositionVector Maze::get_player_start_position() const
|
Vector2d Maze::get_player_start_position() const
|
||||||
{
|
{
|
||||||
return this->player_start_position;
|
return this->player_start_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
PositionVector Maze::get_distance_pos1_pos2(const PositionVector& pos1, const PositionVector& pos2) {
|
Vector2d Maze::get_delta_vector(const Vector2d& pos1, const Vector2d& pos2) const {
|
||||||
int x_diff = pos1.x - pos2.x;
|
int x_diff = pos1.x - pos2.x;
|
||||||
int y_diff = pos1.y - pos2.y;
|
int y_diff = pos1.y - pos2.y;
|
||||||
|
|
||||||
return {x_diff, y_diff};
|
return {x_diff, y_diff};
|
||||||
}
|
}
|
||||||
|
|
||||||
int Maze::calculate_steps(const PositionVector& target_position, PositionVector position, int steps) {
|
int Maze::calculate_steps_until_win(const Vector2d& position, const int& steps) {
|
||||||
if (this->is_pos_free(position, false))
|
if (!this->is_pos_free(position, false))
|
||||||
return 999;
|
return 999;
|
||||||
if (target_position.eq(position))
|
if (this->get_field(position) == 'Z')
|
||||||
return 0;
|
return 0;
|
||||||
if (steps <= 0)
|
if (steps <= 0)
|
||||||
return 999;
|
return 999;
|
||||||
|
|
||||||
vector<int> i;
|
vector<int> i;
|
||||||
|
i.push_back(this->calculate_steps_until_win(position.get_new_updated(0, -1), steps - 1));
|
||||||
|
i.push_back(this->calculate_steps_until_win(position.get_new_updated(0, 1), steps - 1));
|
||||||
|
i.push_back(this->calculate_steps_until_win(position.get_new_updated(1, 0), steps - 1));
|
||||||
|
i.push_back(this->calculate_steps_until_win(position.get_new_updated(-1, 0), steps - 1));
|
||||||
|
|
||||||
|
return MathUtil::get_min(i) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<Entity> Maze::get_entities() {
|
||||||
|
return this->enemies;
|
||||||
}
|
}
|
||||||
} // game
|
} // game
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "../std_lib_inc.h"
|
#include "../std_lib_inc.h"
|
||||||
#include "../Util/PositionVector.h"
|
#include "../Util/Vector2d.h"
|
||||||
|
|
||||||
#ifndef MAZE_H
|
#ifndef MAZE_H
|
||||||
#define MAZE_H
|
#define MAZE_H
|
||||||
|
@ -18,12 +18,13 @@ namespace game
|
||||||
/// Das Spielfeld
|
/// Das Spielfeld
|
||||||
vector<vector<char>> field;
|
vector<vector<char>> field;
|
||||||
/// Die Startposition des Spielers
|
/// Die Startposition des Spielers
|
||||||
PositionVector player_start_position;
|
Vector2d player_start_position;
|
||||||
|
/// Eine Liste an Gegnern
|
||||||
|
vector<Entity> enemies;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Das Spielfeld
|
/// Das Spielfeld
|
||||||
Maze(const vector<vector<char>> play_field, const vector<int> player_start_position, const vector<Entity> enemies);
|
Maze(const Vector<Vector<char>>& play_field, const Vector<int>& player_start_position, const Vector<Entity>& enemies);
|
||||||
|
|
||||||
/// Kontrolliere, ob der Spieler stirbt
|
/// Kontrolliere, ob der Spieler stirbt
|
||||||
/// @param player Der Spieler
|
/// @param player Der Spieler
|
||||||
/// @return Ob der Spieler tot ist
|
/// @return Ob der Spieler tot ist
|
||||||
|
@ -38,31 +39,40 @@ namespace game
|
||||||
/// @param pos Die Position, die überprüft werden soll
|
/// @param pos Die Position, die überprüft werden soll
|
||||||
/// @param player_has_key If the player has at least one key
|
/// @param player_has_key If the player has at least one key
|
||||||
/// @return Ob die Position begehbar ist
|
/// @return Ob die Position begehbar ist
|
||||||
bool is_pos_free(const PositionVector& pos, const bool& player_has_key) const;
|
bool is_pos_free(const Vector2d& pos, const bool& player_has_key) const;
|
||||||
|
|
||||||
/// Zeige das Spielfeld in der Konsole an
|
/// Zeige das Spielfeld in der Konsole an
|
||||||
/// @param player Der Spieler
|
/// @param player Der Spieler
|
||||||
void render(const Player& player, const vector<Entity> entities) const;
|
/// @param infomode_enabled Ob der Infomode aktiv ist
|
||||||
|
void render(const Player& player, vector<Entity> entities, const bool& infomode_enabled);
|
||||||
|
|
||||||
/// Kriege den Wert einer Position
|
/// Kriege den Wert einer Position
|
||||||
/// @param pos Die gewollte Position
|
/// @param pos Die gewollte Position
|
||||||
/// @return Der Wert der Position
|
/// @return Der Wert der Position
|
||||||
char get_field(const PositionVector& pos) const;
|
char get_field(const Vector2d& pos) const;
|
||||||
|
|
||||||
/// Ersetze den Wert von einer Position
|
/// Ersetze den Wert von einer Position
|
||||||
/// @param pos Die Position die ersetzt werden soll
|
/// @param pos Die Position die ersetzt werden soll
|
||||||
/// @param target Der Wert, auf den die Position gesetzt werden soll
|
/// @param target Der Wert, auf den die Position gesetzt werden soll
|
||||||
void update_field(const PositionVector& pos, const char& target);
|
void update_field(const Vector2d& pos, const char& target);
|
||||||
|
|
||||||
/// Kriege die Startposition des Spielers
|
/// Kriege die Startposition des Spielers
|
||||||
/// @return Die Startposition des Spielers
|
/// @return Die Startposition des Spielers
|
||||||
PositionVector get_player_start_position() const;
|
Vector2d get_player_start_position() const;
|
||||||
|
|
||||||
/// Berrechne den Abstand zwischen zwei Vektoren
|
/// Berrechne den Abstand zwischen zwei Vektoren
|
||||||
/// @return Der Abstand als Differenzvektor
|
/// @return Der Abstand als Differenzvektor
|
||||||
PositionVector get_distance_pos1_pos2(const PositionVector& pos1, const PositionVector& pos2);
|
Vector2d get_delta_vector(const Vector2d& pos1, const Vector2d& pos2) const;
|
||||||
|
|
||||||
int calculate_steps(const PositionVector& target_position, PositionVector position, int steps);
|
/// Berechne wie viele Schritte benötigt werden, um das Labyrinth zu schaffen
|
||||||
|
/// @warning Steps nicht zu groß setzen! Diese Funktion ist 4-fach rekursiv!
|
||||||
|
/// @param position Die Startposition
|
||||||
|
/// @param steps Wie viele Schritte maximal gegangen werden sollten
|
||||||
|
/// @returns Wie viele Schritte benötigt werden
|
||||||
|
int calculate_steps_until_win(const Vector2d& position, const int& steps);
|
||||||
|
|
||||||
|
/// Kriege alle eingelesenen Entities
|
||||||
|
vector<Entity> get_entities();
|
||||||
};
|
};
|
||||||
} // game
|
} // game
|
||||||
|
|
||||||
|
|
11
src/Util/MathUtil.cpp
Normal file
11
src/Util/MathUtil.cpp
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include "MathUtil.h"
|
||||||
|
|
||||||
|
namespace game {
|
||||||
|
int MathUtil::get_min(const vector<int>& numbers) {
|
||||||
|
int i = numbers[0];
|
||||||
|
for (const int j : numbers)
|
||||||
|
if (j < i)
|
||||||
|
i = j;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
} // game
|
16
src/Util/MathUtil.h
Normal file
16
src/Util/MathUtil.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include "../std_lib_inc.h"
|
||||||
|
#ifndef UTIL_H
|
||||||
|
#define UTIL_H
|
||||||
|
|
||||||
|
namespace game
|
||||||
|
{
|
||||||
|
class MathUtil{
|
||||||
|
public:
|
||||||
|
/// Gebe die minimale Nummer aus einer Liste zurück
|
||||||
|
/// @param numbers Eine liste an nummern
|
||||||
|
/// @returns Die kleinste Nummer
|
||||||
|
static int get_min(const vector<int>& numbers);
|
||||||
|
};
|
||||||
|
} // game
|
||||||
|
|
||||||
|
#endif //UTIL_H
|
|
@ -65,12 +65,14 @@ namespace game
|
||||||
|
|
||||||
if (!validate_maze_element(input))
|
if (!validate_maze_element(input))
|
||||||
throw MalformedMaze("The given input is not a valid element of a maze!");
|
throw MalformedMaze("The given input is not a valid element of a maze!");
|
||||||
if (!is_valid_enemy(input))
|
if (is_valid_enemy(input))
|
||||||
row.push_back(input);
|
{
|
||||||
else {
|
|
||||||
enemies.push_back(Entity({x, y}, input));
|
enemies.push_back(Entity({x, y}, input));
|
||||||
row.push_back('.');
|
row.push_back('.');
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
row.push_back(input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
field.push_back(row);
|
field.push_back(row);
|
||||||
|
@ -78,6 +80,6 @@ namespace game
|
||||||
|
|
||||||
vector<int> player_start_pos = request_numbers_from_user(2);
|
vector<int> player_start_pos = request_numbers_from_user(2);
|
||||||
|
|
||||||
return Maze(field, player_start_pos, enemies);
|
return {field, player_start_pos, enemies};
|
||||||
} // Beispieleingabe: `4 3 #.# #.K #T# #Z# 0 1`
|
} // Beispieleingabe: `4 3 #.# #.K #T# #Z# 0 1`
|
||||||
} // game
|
} // game
|
||||||
|
|
|
@ -19,7 +19,9 @@ namespace game
|
||||||
/// Erlaubte Zeichen in einem Labyrinth
|
/// Erlaubte Zeichen in einem Labyrinth
|
||||||
/// Ist eine Konstante, darf also in global scope
|
/// Ist eine Konstante, darf also in global scope
|
||||||
static const vector<char> valid_maze_elements = {'Z', '.', '#', 'A', 'K', 'T', 'B', 'C'};
|
static const vector<char> valid_maze_elements = {'Z', '.', '#', 'A', 'K', 'T', 'B', 'C'};
|
||||||
|
/// Welche Geistertypen es gibt
|
||||||
static const vector<char> valid_enemies = {'A', 'B', 'C'};
|
static const vector<char> valid_enemies = {'A', 'B', 'C'};
|
||||||
|
/// Die Maximale Labyrinthgröße
|
||||||
static constexpr int MAX_MAZE_SIZE = 20;
|
static constexpr int MAX_MAZE_SIZE = 20;
|
||||||
|
|
||||||
class Maze;
|
class Maze;
|
||||||
|
@ -36,6 +38,9 @@ namespace game
|
||||||
/// @return Ob das gegebene Zeichen in einem Labyrinth vorkommen darf
|
/// @return Ob das gegebene Zeichen in einem Labyrinth vorkommen darf
|
||||||
static bool validate_maze_element(const char& target);
|
static bool validate_maze_element(const char& target);
|
||||||
|
|
||||||
|
/// Ob der angegebene char in valider Geist ist
|
||||||
|
/// @param target Der zu kontrollierende Wert
|
||||||
|
/// @returns Ob der Wert ein Valider Geist ist
|
||||||
static bool is_valid_enemy(const char& target);
|
static bool is_valid_enemy(const char& target);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
#include "PositionVector.h"
|
|
||||||
|
|
||||||
namespace game
|
|
||||||
{
|
|
||||||
PositionVector::PositionVector(const int x, const int y)
|
|
||||||
{
|
|
||||||
this->x = x;
|
|
||||||
this->y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PositionVector::update(const int& x, const int& y)
|
|
||||||
{
|
|
||||||
this->x = x;
|
|
||||||
this->y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PositionVector::change_x(const int& amount) {
|
|
||||||
this->x += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PositionVector::change_y(const int& amount) {
|
|
||||||
this->y += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PositionVector::normalize() {
|
|
||||||
if (this->x < 0)
|
|
||||||
this->x *= -1;
|
|
||||||
if (this->y < 0)
|
|
||||||
this->y *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PositionVector::eq(const PositionVector& position) const {
|
|
||||||
return this->x == position.x && this->y == position.y;
|
|
||||||
}
|
|
||||||
} // game
|
|
|
@ -1,35 +0,0 @@
|
||||||
#ifndef POSITION_H
|
|
||||||
#define POSITION_H
|
|
||||||
|
|
||||||
namespace game
|
|
||||||
{
|
|
||||||
/// Ein Vector aus zwei zahlen.
|
|
||||||
/// Kann eine Position oder eine Differenz zwischen zwei Positionen darstellen.
|
|
||||||
struct PositionVector
|
|
||||||
{
|
|
||||||
// struct -> members public by default
|
|
||||||
// Die beiden Variablen des Vectors
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
|
|
||||||
/// Ein Vector aus zwei zahlen.
|
|
||||||
/// Kann eine Position oder eine Differenz zwischen zwei Positionen darstellen.
|
|
||||||
/// @param x Die 'X'-Koordinate
|
|
||||||
/// @param y Die 'Y'-Koordinate
|
|
||||||
PositionVector(int x, int y);
|
|
||||||
|
|
||||||
/// Aktualisiere die Werte des Vectors
|
|
||||||
/// @param x Die neue 'X'-Koordinate
|
|
||||||
/// @param y Die neue 'Y'-Koordinate
|
|
||||||
void update(const int& x, const int& y);
|
|
||||||
|
|
||||||
void change_x(const int& amount);
|
|
||||||
void change_y(const int& amount);
|
|
||||||
|
|
||||||
void normalize();
|
|
||||||
|
|
||||||
bool eq(const PositionVector& position)const ;
|
|
||||||
};
|
|
||||||
} // game
|
|
||||||
|
|
||||||
#endif //POSITION_H
|
|
47
src/Util/Vector2d.cpp
Normal file
47
src/Util/Vector2d.cpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#include "Vector2d.h"
|
||||||
|
|
||||||
|
namespace game
|
||||||
|
{
|
||||||
|
Vector2d::Vector2d(const int x, const int y)
|
||||||
|
{
|
||||||
|
this->x = x;
|
||||||
|
this->y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vector2d::update(const int& x, const int& y)
|
||||||
|
{
|
||||||
|
this->x = x;
|
||||||
|
this->y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vector2d::change_x(const int& amount) {
|
||||||
|
this->x += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vector2d::change_y(const int& amount) {
|
||||||
|
this->y += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2d Vector2d::normalize() {
|
||||||
|
Vector2d v = *this;
|
||||||
|
if (v.x < 0)
|
||||||
|
v.x *= -1;
|
||||||
|
if (v.y < 0)
|
||||||
|
v.y *= -1;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Vector2d::eq(const Vector2d& position) const {
|
||||||
|
return this->x == position.x && this->y == position.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Vector2d Vector2d::get_new_updated(const int& diff_x, const int& diff_y) const {
|
||||||
|
Vector2d new_position = *this;
|
||||||
|
new_position.change_x(diff_x);
|
||||||
|
new_position.change_y(diff_y);
|
||||||
|
|
||||||
|
return new_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // game
|
51
src/Util/Vector2d.h
Normal file
51
src/Util/Vector2d.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef POSITION_H
|
||||||
|
#define POSITION_H
|
||||||
|
|
||||||
|
namespace game
|
||||||
|
{
|
||||||
|
/// Ein Vector aus zwei zahlen.
|
||||||
|
/// Kann eine Position oder eine Differenz zwischen zwei Positionen darstellen.
|
||||||
|
struct Vector2d
|
||||||
|
{
|
||||||
|
// struct -> members public by default
|
||||||
|
// Die beiden Variablen des Vectors
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
/// Ein Vector aus zwei zahlen.
|
||||||
|
/// Kann eine Position oder eine Differenz zwischen zwei Positionen darstellen.
|
||||||
|
/// @param x Die 'X'-Koordinate
|
||||||
|
/// @param y Die 'Y'-Koordinate
|
||||||
|
Vector2d(int x, int y);
|
||||||
|
|
||||||
|
/// Aktualisiere die Werte des Vectors
|
||||||
|
/// @param x Die neue 'X'-Koordinate
|
||||||
|
/// @param y Die neue 'Y'-Koordinate
|
||||||
|
void update(const int& x, const int& y);
|
||||||
|
|
||||||
|
/// Verschiebe den X Wert des Vektors um eine Anzahl
|
||||||
|
/// @param amount Die zu verschiebene Anzahl
|
||||||
|
void change_x(const int& amount);
|
||||||
|
|
||||||
|
/// Verschiebe den Y Wert des Vektors um eine Anzhal
|
||||||
|
/// @param amount Die zu verschiebene Anzahl
|
||||||
|
void change_y(const int& amount);
|
||||||
|
|
||||||
|
/// Kriege einen normalisierten Vektor zurück
|
||||||
|
/// @returns Den aktuellen Vektor als normalisierter Vektor
|
||||||
|
Vector2d normalize();
|
||||||
|
|
||||||
|
/// Kontrolliere, ob ein Vektor einem anderen Enspricht
|
||||||
|
/// @param position Die Position mit der verglichen werden soll
|
||||||
|
/// @returns Ob die Position die gleiche ist
|
||||||
|
bool eq(const Vector2d& position) const;
|
||||||
|
|
||||||
|
/// Kriege einen Vektor, der mit den gegebenen Werten verschoben worden ist
|
||||||
|
/// @param diff_x Die Verschiebung auf der X-Achse
|
||||||
|
/// @param diff_y Die Verschiebung auf der Y-Achse
|
||||||
|
/// @returns Den berrechneten Vektor
|
||||||
|
Vector2d get_new_updated(const int& diff_x, const int& diff_y) const;
|
||||||
|
};
|
||||||
|
} // game
|
||||||
|
|
||||||
|
#endif //POSITION_H
|
|
@ -2,8 +2,6 @@
|
||||||
#include "Util/MazeParser.h"
|
#include "Util/MazeParser.h"
|
||||||
#include "Environment/Game.h"
|
#include "Environment/Game.h"
|
||||||
#include "Exceptions/MalformedMaze.h"
|
#include "Exceptions/MalformedMaze.h"
|
||||||
#include "Exceptions/MovementNotPossible.h"
|
|
||||||
#include "Exceptions/UnkownAction.h"
|
|
||||||
#include "Util/GameState.h"
|
#include "Util/GameState.h"
|
||||||
|
|
||||||
using game::Maze;
|
using game::Maze;
|
||||||
|
@ -42,6 +40,8 @@ int main()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Schriebe eine Nachricht in die Konsole wenn das Programm beendet wird
|
||||||
|
/// @param state Der Spielzustand als das Programm beendet wurde
|
||||||
void print_exit_message_based_on_state(const GameState& state) {
|
void print_exit_message_based_on_state(const GameState& state) {
|
||||||
switch (state){
|
switch (state){
|
||||||
case GameState::QUITTING:
|
case GameState::QUITTING:
|
||||||
|
|
Loading…
Add table
Reference in a new issue