ACADEMIC RESEARCH AND PUBLICATIONS
during Graduate and Undergraduate Studies
Doctoral Candidate in Computer Science
Visual Computing Division, Digital Production Arts
Clemson University | School of Computing
THEFT OF THE REWOLF FLOWERS:
A C++/SDL2 VIDEO GAME
#include "Player.h"
#include "gamedata.h"
#include "renderContext.h"
Player::Player(const std::string &name, int lev, int maxBarks) :
Drawable( name,
Vector2f( Gamedata::getInstance().getXmlInt(name+"/startLoc/x"),
Gamedata::getInstance().getXmlInt(name+"/startLoc/y") ),
Vector2f(0, 0), //Initialize velocity to 0.
lev, 1.0
),
frames( RenderContext::getInstance()->getFrames(name) ),
currentFrame(0),
numberOfFrames( Gamedata::getInstance().getXmlInt(name+"/frames") ),
frameInterval( Gamedata::getInstance().getXmlInt(name+"/frameInterval") ),
timeSinceLastFrame(0),
worldWidth( Gamedata::getInstance().getXmlInt("world/width") ),
worldHeight( Gamedata::getInstance().getXmlInt("world/height") ),
frameWidth( frames[0]->getWidth() ),
frameHeight( frames[0]->getHeight() ),
origVelX( Gamedata::getInstance().getXmlInt(getName()+"/speedX") ),
origVelY( Gamedata::getInstance().getXmlInt(getName()+"/speedY") ),
flip(false),
left(false),
right(false),
up(false),
down(false),
bark(false),
barkPool( BarkPool(maxBarks, origVelX) ),
observers()
{ }
//=====================================================================
Player::Player(const Player &other) :
Drawable(other),
frames(other.frames),
currentFrame(other.currentFrame),
numberOfFrames(other.numberOfFrames),
frameInterval(other.frameInterval),
timeSinceLastFrame(other.timeSinceLastFrame),
worldWidth(other.worldWidth),
worldHeight(other.worldHeight),
frameWidth(other.frameWidth),
frameHeight(other.frameHeight),
origVelX(other.origVelX),
origVelY(other.origVelY),
flip(other.flip),
left(other.left),
right(other.right),
up(other.up),
down(other.down),
bark(other.bark),
barkPool(other.barkPool),
observers(other.observers)
{ }
//=====================================================================
void Player::draw() const
{
frames[currentFrame]->draw(getX(), getY(), flip, getScale());
barkPool.drawBarks();
}
//=====================================================================
void Player::idle()
{
if (!left && !right)
{
setVelocityX(0);
}
if (!up && !down)
{
setVelocityY(0);
}
}
//=====================================================================
void Player::update(Uint32 ticks)
{
checkEdges(); //Sets velocity to 0 if touching a boundary. Do this before the next two steps.
changeVelocity();
changeScale(); //Subtly change Player's size based off of vertical distance in world (lower y -> higher up in window -> further back within scene).
Vector2f incr = getVelocity() * static_cast<float>(ticks) * 0.001;
setPosition(getPosition() + incr);
advanceFrame(ticks);
if (bark) barkPool.bark(getFlip(), getX(), getY());
barkPool.update(ticks, getX());
for (auto o : observers)
{ o->determineEvade(getX(), getY()); }
idle();
left = false;
right = false;
up = false;
down = false;
bark = false;
}
//=====================================================================
void Player::changeScale()
{
int maxY = Gamedata::getInstance().getXmlInt(getName()+"/maxY");
int dist = Gamedata::getInstance().getXmlInt(getName()+"/maxY") - getY(); //Vertical distance away from max y. If 0, at that max border,
setScale( 1 - (1.1*dist)/maxY ); // If at maxY, scale=1.1. Use this info as a ratio. maxY:1.1, dist:scale
}
//=====================================================================
void Player::changeVelocity()
{
if (left)
{
setVelocityX(getScale() * origVelX);
flip = false;
}
else if (right)
{
setVelocityX(getScale() * -origVelX);
flip = true;
}
if (up)
{
setVelocityY(getScale() * -origVelY);
}
else if (down)
{
setVelocityY(getScale() * origVelY);
}
}
//=====================================================================
void Player::checkEdges()
{
//Reaching upper bounds (y origin at top) of walkable area.
if ( getY() < Gamedata::getInstance().getXmlInt(getName()+"/minY") )
{
up = false; //Disable going up more.
}
//Reaching lower bounds (y origin at top) of walkable area.
else if ( getY() > Gamedata::getInstance().getXmlInt(getName()+"/maxY") )
{
down = false; //Disable going down more.
}
//Reaching leftmost bound.
if ( getX() < 0)
{
left = false;
}
//Reaching rightmost bound.
else if ( getX() > worldWidth-frameWidth)
{
right = false;
}
}
//=====================================================================
void Player::advanceFrame(Uint32 ticks)
{
if (left || right || up || down)
{
timeSinceLastFrame += ticks;
if (timeSinceLastFrame > frameInterval)
{
currentFrame = (currentFrame+1) % (numberOfFrames);
timeSinceLastFrame = 0;
}
}
}
//=====================================================================
std::list<TwoWayMultiSprite*> Player::getActiveBarks() const
{
return barkPool.getActiveBarks();
}
PROJECT PAGE
Language: C++ (using SDL2)
Date: Spring 2017
Class: Data-Driven Game Development
You are a werewolf, and the Selkies had turned your love into a human! Collect the Rewolf Flowers to restore your love to her werewolf state. Hurry, though, because the Selkies can take them away!
This project is a 2D game built in C++ using Simple DirectMedia Layer 2.0. A brief video of the gameplay is provided. The code architecture is object-oriented and utilizes inheritance, object pools, containers and iterators, basic AI, and other programming techniques and C++ tools. The code sample is the implementation file of the Player (the werewolf) class.
Additionally, I created all of the art assets used. The bark and scream sound effects are also my own. The song used is Dreamless by Jake Bowen.