forked from University/epr24pr42-ojanssen2
feat: continued work on ghosts, started work on required recursive function
This commit is contained in:
parent
14c43b4e13
commit
11ab3ee46d
12 changed files with 150 additions and 32 deletions
|
@ -1,12 +1,49 @@
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
|
#include "../Environment/Maze.h"
|
||||||
|
|
||||||
namespace game {
|
namespace game {
|
||||||
Entity::Entity(PositionVector starting_position, char display_character): pos(starting_position), display_character(display_character){}
|
Entity::Entity(PositionVector starting_position, 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 PositionVector& position) const {
|
||||||
return this->pos.eq(position);
|
return this->pos.eq(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Entity::tick(Maze& maze, const PositionVector& player_position){
|
||||||
void move(const Maze& maze, const PositionVector& player_position);
|
switch (this->display_character) {
|
||||||
|
case 'A':
|
||||||
|
// No thoughts, head empty :P
|
||||||
|
return;
|
||||||
|
case 'B':
|
||||||
|
this->handle_bowie(maze);
|
||||||
|
return;
|
||||||
|
case 'C':
|
||||||
|
this->handle_connelly(maze, player_position);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entity::handle_bowie(Maze& maze) {
|
||||||
|
PositionVector target_position = {this->pos.x, this->pos.y};
|
||||||
|
if (this->move_left)
|
||||||
|
target_position.change_x(-1);
|
||||||
|
else
|
||||||
|
target_position.change_x(1);
|
||||||
|
if (maze.is_pos_free(target_position, false))
|
||||||
|
this->pos = target_position;
|
||||||
|
else
|
||||||
|
this->move_left = !this->move_left;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entity::handle_connelly(Maze& maze, const PositionVector& player_position) {
|
||||||
|
PositionVector diff = maze.get_distance_pos1_pos2(player_position, this->pos);
|
||||||
|
PositionVector normalized_diff = {diff.x, diff.y};
|
||||||
|
normalized_diff.normalize();
|
||||||
|
PositionVector target_position = {this->pos.x, this->pos.y};
|
||||||
|
}
|
||||||
|
|
||||||
|
char Entity::get_display_character() {
|
||||||
|
return this->display_character;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "../Util/PositionVector.h"
|
#include "../Util/PositionVector.h"
|
||||||
|
|
||||||
|
|
||||||
#ifndef ENTITY_H
|
#ifndef ENTITY_H
|
||||||
#define ENTITY_H
|
#define ENTITY_H
|
||||||
|
|
||||||
|
@ -10,10 +11,15 @@ namespace game
|
||||||
private:
|
private:
|
||||||
PositionVector pos;
|
PositionVector pos;
|
||||||
char display_character;
|
char display_character;
|
||||||
|
bool move_left;
|
||||||
|
|
||||||
|
void handle_bowie(Maze& maze);
|
||||||
|
void handle_connelly(Maze& maze, const PositionVector& player_position);
|
||||||
public:
|
public:
|
||||||
Entity(PositionVector starting_position, char display_character);
|
Entity(PositionVector starting_position, char display_character);
|
||||||
void move(const Maze& maze, const PositionVector& player_position);
|
void tick(Maze& maze, const PositionVector& player_position);
|
||||||
bool is_at_position(const PositionVector& position) const;
|
bool is_at_position(const PositionVector& position) const;
|
||||||
|
char get_display_character();
|
||||||
};
|
};
|
||||||
} // game
|
} // game
|
||||||
|
|
||||||
|
|
|
@ -80,30 +80,25 @@ namespace game
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GameState Player::handle_collisions(const GameState& prev_game_state, const Maze& maze) {
|
GameState Player::handle_collisions(const Game& game, const Maze& maze) {
|
||||||
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 (prev_game_state != GameState::RUNNING)
|
if (game.get_state() != GameState::RUNNING)
|
||||||
return prev_game_state;
|
return game.get_state();
|
||||||
|
|
||||||
if (field_at_pos == '.')
|
if (field_at_pos == '.'){
|
||||||
return GameState::RUNNING;
|
if (game.is_enemy_at_pos(this->get_pos()))
|
||||||
switch (field_at_pos) {
|
|
||||||
case 'A':
|
|
||||||
case 'B':
|
|
||||||
case 'C':
|
|
||||||
return GameState::HIT_BY_GHOST;
|
return GameState::HIT_BY_GHOST;
|
||||||
break;
|
return GameState::RUNNING;
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return prev_game_state;
|
// You are not supposed to be here!
|
||||||
|
return game.get_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Player::tick(const GameState& prev_game_state, Maze& maze) {
|
void Player::tick(const Game& game, Maze& maze) {
|
||||||
this->handle_keys(maze);
|
this->handle_keys(maze);
|
||||||
this->handle_collisions(prev_game_state, maze);
|
this->handle_collisions(game, maze);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::has_key_available() const
|
bool Player::has_key_available() const
|
||||||
|
|
|
@ -9,6 +9,7 @@ using game::GameState;
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
class Maze;
|
class Maze;
|
||||||
|
class Game;
|
||||||
|
|
||||||
/// Ein Spieler.
|
/// Ein Spieler.
|
||||||
/// Besitzt einen veränderbaren Positionsvektor
|
/// Besitzt einen veränderbaren Positionsvektor
|
||||||
|
@ -32,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 GameState& prev_game_state, const Maze& maze);
|
GameState handle_collisions(const Game& game, const Maze& maze);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Ein Spieler.
|
/// Ein Spieler.
|
||||||
|
@ -57,7 +58,7 @@ namespace game
|
||||||
Maze handle_user_input(Maze& maze, const char& input);
|
Maze handle_user_input(Maze& maze, const char& input);
|
||||||
|
|
||||||
///
|
///
|
||||||
void tick(const GameState& prev_game_state, Maze& maze);
|
void 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
|
||||||
|
|
|
@ -12,14 +12,14 @@ using game_exceptions::MovementNotPossible;
|
||||||
|
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
Game::Game(Maze& maze): maze(maze), player(0, 0), infomode_enabled(false), state(GameState::RUNNING)
|
Game::Game(Maze& maze): maze(maze), player(0, 0), infomode_enabled(false), state(GameState::RUNNING), enemies({})
|
||||||
{
|
{
|
||||||
PositionVector player_start_position = this->maze.get_player_start_position();
|
PositionVector player_start_position = this->maze.get_player_start_position();
|
||||||
|
|
||||||
this->player = Player(player_start_position);
|
this->player = Player(player_start_position);
|
||||||
}
|
}
|
||||||
|
|
||||||
GameState Game::get_state() {
|
GameState Game::get_state() const {
|
||||||
return this->state;
|
return this->state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,13 @@ namespace game
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Game::is_enemy_at_pos(const PositionVector& position) const{
|
||||||
|
for (Entity e : this->enemies)
|
||||||
|
if (e.is_at_position(position))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Game::should_end_game() {
|
bool Game::should_end_game() {
|
||||||
return this->state != GameState::RUNNING;
|
return this->state != GameState::RUNNING;
|
||||||
}
|
}
|
||||||
|
@ -79,7 +86,12 @@ namespace game
|
||||||
cout << err.what() << "\n";
|
cout << err.what() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
this->player.tick(this->state, this->maze);
|
this->player.tick(*this, this->maze);
|
||||||
|
|
||||||
|
for (Entity e : this->enemies)
|
||||||
|
e.tick(this->maze, this->player.get_pos());
|
||||||
|
|
||||||
|
this->player.tick(*this, this->maze);
|
||||||
|
|
||||||
if (this->should_end_game())
|
if (this->should_end_game())
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "Maze.h"
|
#include "Maze.h"
|
||||||
#include "../Entities/Player.h"
|
#include "../Entities/Player.h"
|
||||||
#include "../Util/GameState.h"
|
#include "../Util/GameState.h"
|
||||||
|
#include "../Entities/Entity.h"
|
||||||
|
|
||||||
#ifndef GAME_H
|
#ifndef GAME_H
|
||||||
#define GAME_H
|
#define GAME_H
|
||||||
|
@ -39,7 +40,9 @@ namespace game
|
||||||
|
|
||||||
/// Kriege den aktuellen Status des Spiels
|
/// Kriege den aktuellen Status des Spiels
|
||||||
/// @returns Den aktuellen Status
|
/// @returns Den aktuellen Status
|
||||||
GameState get_state();
|
GameState get_state() const;
|
||||||
|
|
||||||
|
bool is_enemy_at_pos(const PositionVector& position) const ;
|
||||||
};
|
};
|
||||||
} // game
|
} // game
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,13 @@ namespace game
|
||||||
if (y == player.get_pos().y && x == player.get_pos().x)
|
if (y == player.get_pos().y && x == player.get_pos().x)
|
||||||
cout << "S";
|
cout << "S";
|
||||||
else {
|
else {
|
||||||
for(Entity e : entities) {
|
bool an_enemy_is_at_this_position = false;
|
||||||
|
for (Entity e : entities)
|
||||||
|
if (e.is_at_position({x, y})) {
|
||||||
|
an_enemy_is_at_this_position = true;
|
||||||
|
cout << e.get_display_character();
|
||||||
}
|
}
|
||||||
|
if (!an_enemy_is_at_this_position)
|
||||||
cout << field[y][x];
|
cout << field[y][x];
|
||||||
}
|
}
|
||||||
cout << " ";
|
cout << " ";
|
||||||
|
@ -69,4 +74,20 @@ namespace game
|
||||||
{
|
{
|
||||||
return this->player_start_position;
|
return this->player_start_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PositionVector Maze::get_distance_pos1_pos2(const PositionVector& pos1, const PositionVector& pos2) {
|
||||||
|
int x_diff = pos1.x - pos2.x;
|
||||||
|
int y_diff = pos1.y - pos2.y;
|
||||||
|
return {x_diff, y_diff};
|
||||||
|
}
|
||||||
|
|
||||||
|
int Maze::calculate_steps(const PositionVector& target_position, PositionVector position, int steps) {
|
||||||
|
if (this->is_pos_free(position, false))
|
||||||
|
return 999;
|
||||||
|
if (target_position.eq(position))
|
||||||
|
return 0;
|
||||||
|
if (steps <= 0)
|
||||||
|
return 999;
|
||||||
|
vector<int> i;
|
||||||
|
}
|
||||||
} // game
|
} // game
|
||||||
|
|
|
@ -57,6 +57,12 @@ namespace game
|
||||||
/// 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;
|
PositionVector get_player_start_position() const;
|
||||||
|
|
||||||
|
/// Berrechne den Abstand zwischen zwei Vektoren
|
||||||
|
/// @return Der Abstand als Differenzvektor
|
||||||
|
PositionVector get_distance_pos1_pos2(const PositionVector& pos1, const PositionVector& pos2);
|
||||||
|
|
||||||
|
int calculate_steps(const PositionVector& target_position, PositionVector position, int steps);
|
||||||
};
|
};
|
||||||
} // game
|
} // game
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
#include "MazeParser.h"
|
#include "MazeParser.h"
|
||||||
#include "../Environment/Maze.h"
|
#include "../Environment/Maze.h"
|
||||||
#include "../Exceptions/MalformedMaze.h"
|
#include "../Exceptions/MalformedMaze.h"
|
||||||
|
#include "../Entities/Entity.h"
|
||||||
|
|
||||||
using game_exceptions::MalformedMaze;
|
using game_exceptions::MalformedMaze;
|
||||||
|
using game::Entity;
|
||||||
|
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
|
@ -33,12 +35,20 @@ namespace game
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MazeParser::is_valid_enemy(const char& target) {
|
||||||
|
for (const char c : valid_enemies)
|
||||||
|
if (c == target)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Maze MazeParser::request_maze_from_user()
|
Maze MazeParser::request_maze_from_user()
|
||||||
{
|
{
|
||||||
vector<int> maze_size = request_numbers_from_user(2);
|
vector<int> maze_size = request_numbers_from_user(2);
|
||||||
|
|
||||||
char input;
|
char input;
|
||||||
vector<vector<char>> field;
|
vector<vector<char>> field;
|
||||||
|
vector<Entity> enemies;
|
||||||
|
|
||||||
for (int y = 0; y < maze_size[0]; ++y)
|
for (int y = 0; y < maze_size[0]; ++y)
|
||||||
{
|
{
|
||||||
|
@ -49,14 +59,18 @@ namespace game
|
||||||
if (!cin)
|
if (!cin)
|
||||||
throw MalformedMaze("Cin failed while reading chars!");
|
throw MalformedMaze("Cin failed while reading chars!");
|
||||||
|
|
||||||
// I don't think that this is needed. I doubt that the test check for this one ~Eric
|
// I don't think that this is needed. I doubt that they test the check for this one ~Eric
|
||||||
// if (input == 'q')
|
// if (input == 'q')
|
||||||
// throw ExitGame("Schoenen Tag noch!");
|
// throw ExitGame("Schoenen Tag noch!");
|
||||||
|
|
||||||
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))
|
||||||
row.push_back(input);
|
row.push_back(input);
|
||||||
|
else {
|
||||||
|
enemies.push_back(Entity({x, y}, input));
|
||||||
|
row.push_back('.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
field.push_back(row);
|
field.push_back(row);
|
||||||
|
@ -64,6 +78,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);
|
return Maze(field, player_start_pos, enemies);
|
||||||
} // Beispieleingabe: `4 3 #.# #.K #T# #Z# 0 1`
|
} // Beispieleingabe: `4 3 #.# #.K #T# #Z# 0 1`
|
||||||
} // game
|
} // game
|
||||||
|
|
|
@ -19,6 +19,7 @@ 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'};
|
||||||
|
static const vector<char> valid_enemies = {'A', 'B', 'C'};
|
||||||
static constexpr int MAX_MAZE_SIZE = 20;
|
static constexpr int MAX_MAZE_SIZE = 20;
|
||||||
|
|
||||||
class Maze;
|
class Maze;
|
||||||
|
@ -35,6 +36,8 @@ 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);
|
||||||
|
|
||||||
|
static bool is_valid_enemy(const char& target);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Lese ein Labyrinth aus der Konsole
|
/// Lese ein Labyrinth aus der Konsole
|
||||||
/// @return Das Labyrinth
|
/// @return Das Labyrinth
|
||||||
|
|
|
@ -14,6 +14,21 @@ namespace game
|
||||||
this->y = y;
|
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 {
|
bool PositionVector::eq(const PositionVector& position) const {
|
||||||
return this->x == position.x && this->y == position.y;
|
return this->x == position.x && this->y == position.y;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,11 @@ namespace game
|
||||||
/// @param y Die neue 'Y'-Koordinate
|
/// @param y Die neue 'Y'-Koordinate
|
||||||
void update(const int& x, const int& y);
|
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 ;
|
bool eq(const PositionVector& position)const ;
|
||||||
};
|
};
|
||||||
} // game
|
} // game
|
||||||
|
|
Loading…
Add table
Reference in a new issue