Before I continue, I'd like to state that this request will only work if you have Visual C++ installed in your computer, otherwise you will not be able to compile this code. If you do have a C++ editor different from Visual C++, you will have to install additional libraries and such if you don't have them.
Visual C++ Express Edition can be found here (FREE)
PROCEDURE
To run this game, load the following files to a new project in their respective folders:
+ Show Spoiler [Source Files] +
+ Show Spoiler [character.cpp] +
#include "character.h"
Character::Character(Level *lvl, DrawEngine *de, int s_index, float x, float y, int lives,
char up_key, char down_key, char left_key, char right_key)
: Sprite(lvl, de, s_index, x, y, lives)
{
upKey = up_key;
downKey = down_key;
leftKey = left_key;
rightKey = right_key;
classID = CHARACTER_CLASSID;
}
bool Character::keyPress(char c)
{
if (c == upKey)
{
return move(0, -1);
}
else if (c == downKey)
{
return move(0, 1);
}
else if (c == leftKey)
{
return move(-1, 0);
}
else if (c == rightKey)
{
return move(1, 0);
}
return false;
}
void Character::addLives(int num)
{
Sprite::addLives(num);
if (Sprite::isAlive())
{
pos.x = 1;
pos.y = 1;
move(0, 0);
}
}
+ Show Spoiler [drawEngine.cpp] +
#include "drawEngine.h"
#include <windows.h>
#include <iostream>
using namespace std;
DrawEngine::DrawEngine(int xSize, int ySize)
{
screenWidth=xSize;
screenHeight=ySize;
cursorVisibility(false);
map=0;
}
DrawEngine::~DrawEngine()
{
cursorVisibility(true);
gotoxy(0, screenHeight);
cout << "Game Over" << endl;
}
int DrawEngine::createSprite(int index, char c)
{
if (index >=0 && index < 16)
{
spriteImage[index]=c;
return index;
}
return -1;
}
void DrawEngine::deleteSprite(int index)
{
}
void DrawEngine::drawSprite(int index, int posx, int posy)
{
gotoxy(posx, posy);
cout << spriteImage[index];
}
void DrawEngine::eraseSprite(int posx, int posy)
{
gotoxy(posx, posy);
cout << ' ';
}
void DrawEngine::setMap(char **data)
{
map=data;
}
void DrawEngine::createBackgroundTile(int index, char c)
{
if (index >= 0 && index < 16)
{
tileImage[index]=c;
}
}
void DrawEngine::drawBackground(int lvl_width, int lvl_height)
{
if (map)
{
for (int y=0; y < lvl_height; y++)
{
gotoxy(0, y);
for (int x=0; x < lvl_width; x++)
cout << tileImage[map[x][y]];
}
}
screenWidth=lvl_width;
screenHeight=lvl_height;
}
void DrawEngine::gotoxy(int x, int y)
{
HANDLE output_handle;
COORD pos;
pos.X=x;
pos.Y=y;
output_handle=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(output_handle, pos);
}
void DrawEngine::cursorVisibility(bool visibility)
{
HANDLE output_handle;
CONSOLE_CURSOR_INFO cciInfo;
cciInfo.dwSize=1;
cciInfo.bVisible=visibility;
output_handle=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorInfo(output_handle, &cciInfo);
}
+ Show Spoiler [enemy.cpp] +
#include "enemy.h"
#include "level.h"
#include "character.h"
#include <math.h>
#include <stdlib.h>
Enemy::Enemy(Level *l, DrawEngine *de, int s_index, float x, float y, int i_lives)
: Sprite(l, de, s_index, x, y, i_lives)
{
goal=0;
classID=ENEMY_CLASSID;
}
bool Enemy::move(float x, float y)
{
int xpos=(int)(pos.x + x);
int ypos=(int)(pos.y + y);
if (isValidLevelMove(xpos, ypos))
{
list <Sprite *>::iterator Iter;
for (Iter=level->npc.begin(); Iter != level->npc.end(); Iter++)
{
if ((*Iter) != this && (int)(*Iter)->getX() == xpos && (int)(*Iter)->getY() == ypos)
{
return false;
}
}
erase(pos.x, pos.y);
pos.x += x;
pos.y += y;
facingDirection.x=x;
facingDirection.y=y;
draw(pos.x, pos.y);
if ((int)goal->getX() == xpos && (int)goal->getY() == ypos)
goal->addLives(-1);
return true;
}
return false;
}
void Enemy::idleUpdate(void)
{
if (goal)
simulateAI();
}
void Enemy::addGoal(Character *g)
{
goal=g;
}
void Enemy::simulateAI(void)
{
vector goal_pos=goal->getPosition();
vector direction;
direction.x=goal_pos.x - pos.x;
direction.y=goal_pos.y - pos.y;
float mag=sqrt(direction.x * direction.x + direction.y * direction.y);
direction.x=direction.x / (mag * 5);
direction.y=direction.y / (mag * 5);
if (!move(direction.x, direction.y))
{
while(!move(float(rand() % 3 - 1), float(rand() % 3 - 1)))
{
}
}
}
+ Show Spoiler [fireball.cpp] +
#include "fireball.h"
Fireball::Fireball(Level *lev, DrawEngine *de, int s_index, float x, float y,
float xbir, float ybir, int i_lives) : Sprite(lev, de, s_index, x, y, i_lives)
{
facingDirection.x=xbir;
facingDirection.y=ybir;
classID=FIREBALL_CLASSID;
}
void Fireball::idleUpdate(void)
{
if (isValidLevelMove((int)pos.x, (int)pos.y) && (facingDirection.x + facingDirection.y) != 0)
{
if (Sprite::move(facingDirection.x, facingDirection.y))
{
list <Sprite *>::iterator Iter;
for (Iter=level->npc.begin(); Iter != level->npc.end(); Iter++)
{
if ((*Iter)->classID != classID &&
(int)(*Iter)->getX() == (int)pos.x &&
(int)(*Iter)->getY() == (int)pos.y)
{
(*Iter)->addLives(-1);
addLives(-1);
level->addEnemies(-1);
}
}
}
else
addLives(-1);
}
}
+ Show Spoiler [game.cpp] +
#include "game.h"
#include <windows.h>
#include <conio.h>
#include <iostream>
using namespace std;
/* STANDARD VALUES
#define GAME_SPEED 33.333
#define WIDTH_OF_LEVEL 30
#define HEIGHT_OF_LEVEL 20
#define NUMBER_OF_ENEMIES 3//*/
//*
int GAME_SPEED;
int WIDTH_OF_LEVEL;
int HEIGHT_OF_LEVEL;
int NUMBER_OF_ENEMIES;//*/
bool Game:: run(void)
{
int nivel=3;
char key=' ';
char still=' ';
while (nivel > 0 && key != 'q' )
{
switch (nivel)
{
case 3: // LEVEL 1
GAME_SPEED=33;
WIDTH_OF_LEVEL=30;
HEIGHT_OF_LEVEL=20;
NUMBER_OF_ENEMIES=3;
break;
case 2: // LEVEL 2
GAME_SPEED=25;
WIDTH_OF_LEVEL=55;
HEIGHT_OF_LEVEL=22;
NUMBER_OF_ENEMIES=6;
break;
case 1: // LEVEL 3
GAME_SPEED=18;
WIDTH_OF_LEVEL=80;
HEIGHT_OF_LEVEL=24;
NUMBER_OF_ENEMIES=12;
};
level=new Level(&drawArea, WIDTH_OF_LEVEL, HEIGHT_OF_LEVEL);
drawArea.createBackgroundTile(TILE_EMPTY, ' ' );
drawArea.createBackgroundTile(TILE_WALL, 219);
drawArea.createSprite(SPRITE_PLAYER, 1);
drawArea.createSprite(SPRITE_ENEMY, '$' );
drawArea.createSprite(SPRITE_FIREBALL, '*' );
player=new Mage(level, &drawArea, 0);
level->draw(WIDTH_OF_LEVEL, HEIGHT_OF_LEVEL);
level->addPlayer(player);
level->addEnemies(NUMBER_OF_ENEMIES);
startTime=timeGetTime();
frameCount=0;
posx=0;
player->move(0, 0);
while (key !='q' )
{
while (!getInput(&key))
{
timerUpdate();
if (player->isAlive() == false)
{
return 0;
}
else if (level->numberOfEnemies() == 0)
{
break;
}
}
if (level->numberOfEnemies() == 0)
break;
level->keyPress(key);
//cout << "Here's what you pressed: " << key << endl;
}
delete player;
nivel--;
// cout << frameCount / ((timeGetTime() - startTime) / 1000) << " fps" << endl;
// cout << "End of the game" << endl;
}
return true;
}
bool Game::getInput(char *c)
{
if (_kbhit())
{
*c=_getch();
return true;
}
return false;
}
void Game::timerUpdate(void)
{
double currentTime=timeGetTime() - lastTime;
if (currentTime < GAME_SPEED)
return;
level->update();
frameCount++;
lastTime=timeGetTime();
}
+ Show Spoiler [level.cpp] +
#include "level.h"
#include "character.h"
#include "enemy.h"
#include <stdlib.h>
#include <iostream>
using namespace std;
Level::Level(DrawEngine *de, int w, int h)
{
drawArea=de;
numEnemy=0;
width=w;
height=h;
player=0;
// create memory for our level
level=new char *[width];
for (int x=0; x < width; x++)
{
level[x]=new char[height];
}
// create the level
createLevel();
drawArea->setMap(level);
}
Level::~Level()
{
for (int x=0; x < width; x++)
delete [] level[x];
delete [] level;
for (Iter=npc.begin(); Iter != npc.end(); Iter++)
delete (*Iter);
}
void Level::createLevel(void)
{
for (int x=0 ; x < width ; x++)
{
for (int y=0; y < height ; y++)
{
if (y == 0 || y == height - 1 || x == 0 || x == width - 1)
{
level[x][y]=TILE_WALL;
}
else
{
int random=rand() % 100;
if (random < 90)
level[x][y]=TILE_EMPTY;
else
level[x][y]=TILE_WALL;
}
}
}
}
void Level::draw(int lvl_width, int lvl_height)
{
// we need to draw the level
drawArea->drawBackground(lvl_width, lvl_height);
}
void Level::addPlayer(Character *p)
{
player=p;
}
bool Level::keyPress(char c)
{
if (player)
if (player->keyPress(c))
return true;
return false;
}
void Level::update()
{
//deal with fireballs, enemies, AI, etc
for(Iter=npc.begin(); Iter != npc.end(); )
{
(*Iter)->idleUpdate();
if((*Iter)->isAlive() == false)
{
Sprite *temp=*Iter;
Iter=npc.erase(Iter);
delete temp;
}
else
Iter++;
}
}
void Level::addEnemies(int num)
{
int i=num;
numEnemy += num;
while (i > 0)
{
int xpos=int((float(rand() % 100) / 100) * (width - 2) + 1);
int ypos=int((float(rand() % 100) / 100) * (height - 2) + 1);
if (level[xpos][ypos] != TILE_WALL)
{
Enemy *temp=new Enemy(this, drawArea, SPRITE_ENEMY, float(xpos), (float)ypos);
temp->addGoal(player);
addNPC((Sprite *)temp);
i--;
}
}
}
int Level::numberOfEnemies()
{
return numEnemy;
}
void Level::addNPC(Sprite *spr)
{
npc.push_back(spr);
}
+ Show Spoiler [mage.cpp] +
#include "mage.h"
#include "fireball.h"
#include "level.h"
Mage::Mage(Level *l, DrawEngine *de, int s_index, float x, float y, int lives,
char spell_key, char up_key, char down_key, char left_key, char right_key)
: Character(l, de, s_index, x, y, lives, up_key, down_key, left_key, right_key)
{
spellKey=spell_key;
classID=MAGE_CLASSID;
}
bool Mage::keyPress(char c)
{
bool val=Character::keyPress(c);
if (val == false)
{
if (c == spellKey)
{
castSpell();
return true;
}
}
return val;
}
void Mage::castSpell(void)
{
Fireball *temp=new Fireball(level, drawArea, SPRITE_FIREBALL,
(int)pos.x+facingDirection.x, (int)pos.y+facingDirection.y,
facingDirection.x, facingDirection.y);
level->addNPC((Sprite *)temp);
}
+ Show Spoiler [main.cpp] +
#include "game.h"
#include <iostream>
using namespace std;
int main()
{
Game gameHeart;
gameHeart.run();
return 0;
}
+ Show Spoiler [sprite.cpp] +
#include "sprite.h"
Sprite::Sprite(Level *l, DrawEngine *de, int s_index, float x, float y, int i_lives)
{
drawArea=de;
pos.x=x;
pos.y=y;
spriteIndex=s_index;
numLives=i_lives;
facingDirection.x=1;
facingDirection.y=0;
classID=SPRITE_CLASSID;
level=l;
}
Sprite::~Sprite()
{
// erase the dying sprite
erase(pos.x, pos.y);
}
vector Sprite::getPosition(void)
{
return pos;
}
float Sprite::getX(void)
{
return pos.x;
}
float Sprite::getY(void)
{
return pos.y;
}
void Sprite::addLives(int num)
{
numLives += num;
}
int Sprite::getLives(void)
{
return numLives;
}
bool Sprite::isAlive(void)
{
return (numLives > 0);
}
bool Sprite::move(float x, float y)
{
int xpos=(int)(pos.x + x);
int ypos=(int)(pos.y + y);
if (isValidLevelMove(xpos, ypos))
{
// erase sprite
erase(pos.x, pos.y);
pos.x += x;
pos.y += y;
facingDirection.x=x;
facingDirection.y=y;
// draw sprite
draw(pos.x, pos.y);
return true;
}
return false;
}
void Sprite::draw(float x, float y)
{
drawArea->drawSprite(spriteIndex, (int)x, (int)y);
}
void Sprite::erase(float x, float y)
{
drawArea->eraseSprite((int)x, (int)y);
}
bool Sprite::isValidLevelMove(int xpos, int ypos)
{
if (level->level[xpos][ypos] != TILE_WALL)
return true;
return false;
}
void Sprite::idleUpdate(void)
{
// this is for the inherited classes
}
+ Show Spoiler [Header Files] +
+ Show Spoiler [character.h] +
#ifndef CHARACTER_H
#define CHARACTER_H
#include "sprite.h"
class Character : public Sprite
{
public:
Character(Level *l, DrawEngine *de, int s_index, float x=1, float y=1, int lives=3,
char up_key='w', char down_key='s', char left_key='a', char right_key='d' );
virtual bool keyPress(char c);
virtual void addLives(int num=1);
protected:
char upKey;
char downKey;
char leftKey;
char rightKey;
};
#endif
+ Show Spoiler [drawEngine.h] +
#ifndef DRAWENGINE_H
#define DRAWENGINE_H
class DrawEngine
{
public:
DrawEngine(int xSize=80, int ySize=24);
~DrawEngine();
int createSprite(int index, char c);
void deleteSprite(int index);
void eraseSprite(int posx, int posy);
void drawSprite(int index, int posx, int posy);
void createBackgroundTile(int index, char c);
void setMap(char **);
void drawBackground(int lvl_width, int lvl_height);
protected:
char **map;
int screenWidth, screenHeight;
char spriteImage[16];
char tileImage[16];
private:
void gotoxy(int x, int y);
void cursorVisibility(bool visibility);
};
#endif
+ Show Spoiler [enemy.h] +
#ifndef ENEMY_H
#define ENEMY_H
#include "sprite.h"
class Level;
class Character;
class Enemy : public Sprite
{
public:
Enemy(Level *l, DrawEngine *de, int s_index, float x=1, float y=1,
int i_lives=1);
void addGoal(Character *g);
bool move(float x, float y);
void idleUpdate(void);
protected:
void simulateAI(void);
Character *goal;
private:
};
#endif
+ Show Spoiler [fireball.h] +
#ifndef FIREBALL_H
#define FIREBALL_H
#include "sprite.h"
class Fireball : public Sprite
{
public:
Fireball(Level *lev, DrawEngine *de, int s_index, float x=1, float y=1,
float xbir=0, float ybir=0, int i_lives=1);
void idleUpdate(void);
protected:
};
#endif
+ Show Spoiler [game.h] +
#ifndef GAME_H
#define GAME_H
#include "drawEngine.h"
#include "level.h"
#include "character.h"
#include "mage.h"
class Game
{
public:
bool run(void);
protected:
bool getInput(char *c);
void timerUpdate(void);
private:
Level *level;
Mage *player;
double frameCount;
double startTime;
double lastTime;
int posx;
DrawEngine drawArea;
};
#endif
+ Show Spoiler [level.h] +
#ifndef LEVEL_H
#define LEVEL_H
#include <list>
using std::list;
enum
{
SPRITE_PLAYER,
SPRITE_ENEMY,
SPRITE_FIREBALL,
};
enum
{
TILE_EMPTY,
TILE_WALL,
};
#include "drawEngine.h"
//#include "character.h"
class Sprite;
class Character;
class Level
{
public:
Level(DrawEngine *de, int width=80, int height=24);
~Level();
void addPlayer(Character *p);
void update(void);
void draw(int lvl_width, int lvl_height);
bool keyPress(char c);
void addEnemies(int num);
int numberOfEnemies();
void addNPC(Sprite *spr);
friend class Sprite;
protected:
void createLevel(void);
private:
int width;
int height;
int numEnemy;
char **level;
Character *player;
DrawEngine *drawArea;
public:
list <Sprite *> npc;
list <Sprite *>::iterator Iter;
};
#endif
+ Show Spoiler [mage.h] +
#ifndef MAGE_H
#define MAGE_H
#include "drawEngine.h"
#include "character.h"
class Mage : public Character
{
public:
Mage(Level *l, DrawEngine *de, int s_index, float x=1, float y=1,
int lives=3, char spell_key=' ', char up_key='w', char down_key='s', char left_key='a', char right_key='d' );
bool keyPress(char c);
protected:
void castSpell(void);
private:
char spellKey;
};
#endif
+ Show Spoiler [sprite.h] +
#ifndef SPRITE_H
#define SPRITE_H
#include "drawEngine.h"
#include "level.h"
enum classID
{
SPRITE_CLASSID,
CHARACTER_CLASSID,
ENEMY_CLASSID,
FIREBALL_CLASSID,
MAGE_CLASSID,
};
struct vector
{
float x;
float y;
};
class Sprite
{
public:
Sprite(Level *l, DrawEngine *de, int s_index, float x=1, float y=1, int i_lives=1);
~Sprite();
vector getPosition(void);
float getX(void);
float getY(void);
virtual void addLives(int num=1);
int getLives(void);
bool isAlive(void);
virtual void idleUpdate(void);
virtual bool move(float x, float y);
int classID;
protected:
Level *level;
DrawEngine *drawArea;
vector pos;
int spriteIndex;
int numLives;
vector facingDirection;
void draw(float x, float y);
void erase(float x, float y);
bool isValidLevelMove(int xpos, int ypos);
};
#endif
INTRODUCTION
I coded a little game that is played in the command prompt. This game is about a little mage (☺) that shoots fireballs (*) towards evil enemies ($) in a series of 3 consecutive levels, which increase in difficulty as you beat them.
You won't get past level 2.
Here's are a couple screen shots of the game:
you guys so easy to kill, lol
fuck...
CONTROLS
W - Move Up
S - Move Down
A - Move Left
D - Move Right
SPACE - Shoot
Q - Quit Game
LAST COMMENTS
Yes I'm a newbie programmer and felt hyped up because I successfully coded this program ^^ bear with me xD
Freel free to fuck with the code as much as you want, however, I have one rule: If you happen to make something really cool such as a new implementation, a new character class, multiplayer support (easy, but im too lazy), shooting enemies and what-not, post it here! We'd love to see it
Alright, peace.
- Rap