Question
// INSTRUCTIONS // ------------ // Compile this code. You should see a rectangular play field of periods, with // 3 Entity objects visible on it.
// INSTRUCTIONS // ------------ // Compile this code. You should see a rectangular play field of periods, with // 3 Entity objects visible on it. The happy-face Entity moves with the "wasd" // keys, and the club Entity moves with the "ijkl" keys. If the happy-face // reaches the diamond Entity, the player wins. If the happy-face reaches the // club, the player loses. // // Read through this code! Try to understand it before starting the assignment. // Comment confusing lines with what you think code is doing, and experiment // with existing code to test your understanding. // Once you feel comfortable with this code, accomplish each of the following, // and make sure your code compiles and runs after each step is completed. // // 1) Getting comfortable with the game code // a) Implement initialization lists in Vector2, Entity, and Game (setting // object values after a ':', between the constructor signature and body). // Have initialization lists set initial values for each member variable. // b) Add another Entity to the game that isn't the same location as an // existing Entity. Use a heart icon (ASCII code 3). It should display in // the game. // c) Add logic that makes the club (PLAYER2) win the game if that player // reaches the heart Entity. You may want to make new constants, like // GOAL2, and WIN2, to follow the existing code convention. // d) Make a new private function called "void Game::handleUserInput()", move // the user input handling logic from Game::update() into this new // function, and call Game::handleUserInput from Game::update. // e) Add whitespace to the handleUserInput logic, and comment each line with // what you understand it is doing. If you don't understand what the code // is doing, experiment with it until you do! Do things like printing // variables you are unsure about, and guess what output will look like. // f) Implement the prototyped overloaded operators for Vector2. Once they // are finished you should be able to use the alternate code for setting // up PLAYER2 in Game::Game() in "game.cpp". // 2) A "BlinkEntity" class // a) Create 2 new files in your project: "blinkentity.h", and // "blinkentity.cpp" // b) Make a BlinkEntity class that extends Entity. Declare the class in // "blinkentity.h" and define it's methods in "blinkentity.cpp". Your // "blinkentity.h" file should look something like: // #pragma once // // #include "entity.h" // // class BlinkEntity : public Entity { // }; // c) Instead of using an Entity for the Entity marked GOAL1 in the Game // constructor, use a BlinkEntity. You will need to create a public // BlinkEntity constructor. // d) Give BlinkEntity another member variable called "alternateIcon". When // BlinkEntity calls it's update function, swap the values of "icon" and // "alternateIcon". You won't notice a change during runtime until you add // the virtual modifier to Entity::update(). // 3) A "WanderingEntity" class // a) Create 2 new files in your project: "wanderingentity.h", and // "wanderingentity.cpp" // b) Make a WanderingEntity class that extends Entity. Declare the class in // "wanderingentity.h" and define it's methods in "wanderingentity.cpp". // Your "wanderingentity.h" file should look something like: // #pragma once // // #include "entity.h" // // class WanderingEntity : public Entity { // }; // c) Instead of using an Entity for the Entity marked PLAYER2 in the Game // constructor, use a WanderingEntity. You will need to create a public // WanderingEntity constructor. // d) Create a new update method for WanderingEntity. Declare it in // "wanderingentity.h", and define it in "wanderingentity.cpp". In the // WanderingEntity::update() method, set the "howToMoveNext" variable // to a random number from 0 to 3. You can use "rand() % 4" to do this in // "wanderingentity.cpp" if you #include
CODE (some code has additional instructions commented)
main.cpp
// lab4: simplegame_Inheritance
//
// read main.cpp, and follow the instructions at the bottom of main.cpp
#include
#include
#include "game.h"
void main()
{
Game game;
do
{
game.draw();
game.setInput(_getch());
game.update();
}
while(game.getState() == Game::RUNNING);
printf("press ESCAPE to quit ");
while(_getch() != 27);
}
game.h
#pragma once
#include "entity.h"
#include "vector2.h"
class Game
{
private:
static const int LIST_SIZE = 4;
Entity* list[LIST_SIZE];
/** labels for which Entity in 'list' is what*/
static const int
PLAYER1 = 0,
PLAYER2 = 1,
GOAL1 = 2,
GOAL2 = 3;
/** width/height of the map */
Vector2 size;
int userInput;
int state;
public:
void setInput(int input){ userInput = input; }
int getState() { return state; }
/** game state constants */
static const int
RUNNING = 1,
WIN = 2,
LOST = 3,
DEFEAT = 4,
USER_QUIT = -1;
Game();
void draw();
void update();
~Game();
};
game.cpp
#include "game.h"
#include "consoleutil.h"
#include
// moves for players. each list in order defined by Entity::Move_XXXX variables
char * moveCommands[] = {"wasd", "ijkl"};
const int NUMBER_OF_PLAYERS = sizeof(moveCommands) / sizeof(moveCommands[0]);
Game::Game()
{
state = RUNNING;
size.init(20,15);
// allocate each entity
list[PLAYER1] = new Entity(4,3,1);
list[GOAL1] = new Entity(10,7,4);
list [GOAL2]= new Entity (1,1,3);
Vector2 g1 = list[GOAL1]->getPosition();
Vector2 p1 = list[PLAYER1]->getPosition();
list[PLAYER2] = new Entity(
(g1.x + p1.x)/2,
(g1.y + p1.y)/2, 5);
// TODO overload operators below to replace logic above
//Vector2 p2 = (g1 + p1) / 2;
//list[PLAYER2] = new Entity(p2.x, p2.y, 5);
}
void Game::draw()
{
// draw the game world
moveCursor(0,0);
for(int row = 0; row < size.y; row++) {
for(int col = 0; col < size.x; col++) {
putchar('.');
}
putchar(' ');
}
// draw players in the game
for(int i = 0; i < LIST_SIZE; ++i) {
list[i]->draw();
}
// inform player how to play
for(int i = 0; i < NUMBER_OF_PLAYERS; i++) {
moveCursor(0, size.y+i);
printf("use \"%s\" to move %c ",
moveCommands[i], list[i]->getIcon());
}
}
void Game::update()
{
// if the user pressed the escape key
if(userInput == 27) {
state = USER_QUIT;
return; // quit
}
// move the players, based on what key was pressed
int whatMove = Entity::MOVE_NONE, whosTurnItIs;
for(int player = 0; player < NUMBER_OF_PLAYERS; ++player) {
for(int i = 0; moveCommands[player][i] != '\0'; ++i) {
if(moveCommands[player][i] == userInput) {
whosTurnItIs = player;
whatMove = i;
break;
}
}
if(whatMove != Entity::MOVE_NONE) {
break;
}
}
if(whatMove != Entity::MOVE_NONE) {
list[whosTurnItIs]->move(whatMove);
}
// game logic
for(int i = 0; i < LIST_SIZE; ++i) {
list[i]->update();
}
Entity * player1 = list[PLAYER1];
Entity * player2 = list[PLAYER2];
Entity * goal = list[GOAL1];
if(goal->getPosition().is(player1->getPosition())) {
state = WIN;
}
if(!player1->getPosition().isWithin(0, 0, size.x, size.y)) {
state = LOST;
}
if(player2->getPosition().is(player1->getPosition())) {
state = DEFEAT;
}
// show the end-of-game state message when the game ends
if(state != Game::RUNNING) {
moveCursor(0, size.y+NUMBER_OF_PLAYERS+1);
char * message;
switch(state)
{
case WIN: message = "Goal ACHIEVED!"; break;
case LOST: message = "Player lost..."; break;
case DEFEAT:message = "Player was CLUBBED"; break;
default: message = "unknown state occured"; break;
}
printf("%s ", message);
}
}
Game::~Game()
{
// de-allocate each entity
for(int i = 0; i < LIST_SIZE; ++i)
delete list[i];
}
consoleutil.h
#pragma once
/** * moves the console cursor to the given x/y coordinate * @param x * @param y */ void moveCursor(int x, int y);
consoleutil.cpp
#include
#include "consoleutil.h"
/**
* moves the console cursor to the given x/y coordinate
* @param x
* @param y
*/
void moveCursor(int x, int y)
{
COORD c = {x,y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
vector2.h
#pragma once
/**
* Object Oriented implementation of a 2 dimensional (math) vector, using short precision
*/
struct Vector2
{
/** the x, y coordinates */
short x, y;
/** initializes the Vector2 */
Vector2(short x, short y)
{
this->x = x;
this->y = y;
}
/** default constructor - sets x,y to 0,0 */
Vector2()
{
x = 0;
y = 0;
}
/** @return true if the given x, y coordinate mathes this Vector2's data */
bool is(short x, short y);
/** @return true if the given x, y coordinate mathes this Vector2's data */
bool is(Vector2 xy);
/** @return true if the Vector2 is within the given rectangular boundary */
bool isWithin(short minx, short miny, short maxx, short maxy);
/** re-initialize */
void init(short x, short y);
/** @return a random Vector2 within the specified boundary */
static Vector2 random(Vector2 min, Vector2 max);
Vector2& operator+=(Vector2& v);
Vector2 operator+(Vector2& v);
Vector2& operator*=(short value);
Vector2 operator*(short value);
// TODO implement these...
Vector2& operator-=(Vector2& v);
Vector2 operator-(Vector2& v);
Vector2& operator/=(short value);
Vector2 operator/(short value);
};
vector2.cpp
#include "vector2.h"
/** @return true if the given x, y coordinate matches this Vector2's data */
bool Vector2::is(short x, short y)
{
return this->x == x && this->y == y;
}
/** @return true if the given x, y coordinate matches this Vector2's data */
bool Vector2::is(Vector2 xy)
{
return xy.x == x && xy.y == y;
}
/** @return true if the Vector2 is within the given rectangular boundary */
bool Vector2::isWithin(short minx, short miny, short maxx, short maxy)
{
return x >= minx && y >= miny && x < maxx && y < maxy;
}
/** re-initialize */
void Vector2::init(short a_x, short a_y)
{
x = a_x;
y = a_y;
}
Vector2& Vector2::operator+=(Vector2& v)
{
x += v.x;
y += v.y;
return *this;
}
Vector2 Vector2::operator+(Vector2& v)
{
return Vector2(x+v.x, y+v.y);
}
Vector2& Vector2::operator*=(short value)
{
x *= value;
y *= value;
return *this;
}
Vector2 Vector2::operator*(short value)
{
return Vector2(x*value, y*value);
}
#include "stdlib.h"
/** @return a random Vector2 within the specified boundary */
Vector2 Vector2::random(Vector2 min, Vector2 max)
{
return Vector2(
(rand() % (max.x-min.x)) + min.x,
(rand() % (max.y-min.y)) + min.y);
}
entity.h
#pragma once
#include "vector2.h"
/**
* basic game entity
*/
class Entity
{
protected:
/** where the entity is */
Vector2 pos;
/** what the entity looks like */
char icon;
/** */
int howToMoveNext;
public:
/** used to determine which move to make (based on what key was pressed) */
static const int MOVE_NONE = -1, MOVE_UP = 0, MOVE_LEFT = 1, MOVE_DOWN = 2, MOVE_RIGHT = 3;
/**
* @param x where
* @param y where
* @param icon what it looks like
*/
Entity(int x, int y, char icon)
{
pos.x = x;
pos.y = y;
this->icon = icon;
howToMoveNext = MOVE_NONE;
}
Entity(){}
/** draws the entity at it's known location, dependend on moveCursor(,) and putchar() */
void draw();
short getX() { return pos.x; }
short getY() { return pos.y; }
void setX(int value){ pos.x = value; }
void setY(int value){ pos.y = value; }
void addX(int value){ pos.x += value; }
void addY(int value){ pos.y += value; }
/** returns a the Entity's position */
Vector2 getPosition(){return pos;}
/** re-initialize */
void init(int x, int y, char icon);
/**
* @param MOVE_UP, MOVE_LEFT, MOVE_DOWN, or MOVE_RIGHT
* @return true if the parameter was a valid move
*/
bool move(int direction);
/** implement actual changes to the Entity's state, including movement */
void update();
/** access what the Entity looks like */
char getIcon(){return icon;}
};
entity.cpp
#include "entity.h"
#include
#include "consoleutil.h"
/** draws the entity at it's known location, dependent on moveCursor(,) and putchar() */
void Entity::draw()
{
moveCursor(pos.x, pos.y);
putchar(icon);
}
/** re-initialize */
void Entity::init(int a_x, int a_y, char a_icon)
{
pos.init(a_x, a_y);
icon = a_icon;
}
/**
* @param MOVE_UP, MOVE_LEFT, MOVE_DOWN, or MOVE_RIGHT
* @return true if the parameter was a valid move
*/
bool Entity::move(int direction)
{
bool validMove = false;
switch(direction)
{
case MOVE_UP:
case MOVE_LEFT:
case MOVE_DOWN:
case MOVE_RIGHT:
this->howToMoveNext = direction;
validMove = true;
}
return validMove;
}
/** implement actual changes to the Entity's state, including movement */
void Entity::update()
{
switch(howToMoveNext)
{
case MOVE_UP: pos += Vector2(0,-1); break;
case MOVE_LEFT: pos += Vector2(-1,0); break;
case MOVE_DOWN: pos += Vector2(0,+1); break;
case MOVE_RIGHT:pos += Vector2(+1,0); break;
}
howToMoveNext = MOVE_NONE;
}
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started