Project import

This commit is contained in:
Antoine Harle 2020-09-27 11:48:46 +02:00
parent 165d05fd2c
commit 92b1da8f35
89 changed files with 3769 additions and 0 deletions

12
Nidrobb_UML.html Normal file

File diff suppressed because one or more lines are too long

BIN
Nidrobb_UML.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 KiB

BIN
README.pdf Normal file

Binary file not shown.

100
src/Animation/Animation.cpp Normal file
View file

@ -0,0 +1,100 @@
#include "Animation.hpp"
Animation::Animation(const string& name, const vector<AnimationFrame*> frames):_name(name)//, _frames(frames)
{
//VERIFIER BONNE TRANSMISSION DES FRAMES
for(AnimationFrame* frame : frames)
{
//cout<<" anim: "<<frame->center().first<<"/"<<frame->center().second<<endl;
_frames.push_back(frame);
}
_duration = _frames.size(); //-1 ?
_progress = 0;
}
Animation::~Animation()
{
for(AnimationFrame* a : _frames)
delete a;
}
//Indique si l'animation est en cours
bool Animation::inProgress() const
{
if (_progress<_duration-1) //Animation en cours
return true;
else //Animation terminée
return false;
}
//Défile l'animation et retourne la position de la frame active
const pair<int,int>& Animation::nextFrame()
{
unsigned int res;
//cout<<"Progress : "<< _progress << "/"<<_duration <<endl;
res=_progress; //indice de la frame renvoyée
if(_progress<_duration-1)
{
_progress++; //Prochain indice
}
else
{
//cout<<"Warning : using finished animation (using Frame "<< res+1 <<" / "<<_frames.size()<<")"<<endl;
}
//cout<<"Frame Pos : "<<_frames[res]->center().first<<"/"<<_frames[res]->center().second<<endl;
return _frames[res]->center();
}
//Vérifie si une hitbox rentre en collision active avec la frame active
bool Animation::collideA(const SDL_Rect* box) const
{
if(_frames[_progress]->collideA(box))
return true;
else
return false;
}
//Vérifie si une hitbox rentre en collision passive avec la frame active
bool Animation::collideP(const SDL_Rect* box) const
{
if(_frames[_progress]->collideP(box))
return true;
else
return false;
}
//Bloque toute les frames à une position donnée (repère SDL)
void Animation::holdPos(const pair<int,int>& pos)
{
for(AnimationFrame* a : _frames)
{
a->translate(pos);
}
}
Animation& Animation::operator=(const Animation& a)
{
_name = a.name();
_duration=a.duration();
_progress=a.progress()-1; //On recupère l'indice
_frames.clear(); //Si pas supprimé, garde le précédent vecteur et rajoute a la fin ...
AnimationFrame* animFrame;
for(unsigned int i=0; i<_duration; i++)
{
//std::cout<<"Framecopy "<<i<<"/"<<a.duration()<<std::endl;
//cout<<"operator = : "<<i<<" - "<<a.getFrame(i)->center().first<<"/"<<a.getFrame(i)->center().second<<endl;
animFrame = new AnimationFrame(*a.getFrame(i));
_frames.push_back(animFrame);
}
// for(AnimationFrame* f : _frames)
// cout<<"operator = fin : "<<" - "<<f->center().first<<"/"<<f->center().second<<endl;
//std::cout<<"Framecopyf"<<std::endl;
return *this;
}

View file

@ -0,0 +1,45 @@
#ifndef ANIMATION_HPP
#define ANIMATION_HPP
#include "../Animation/AnimationFrame.hpp"
//#include "../Drawable.hpp" //Inclus dans AnimationFrame
//#include "../Collidable.hpp" //Inclus dans AnimationFrame
using namespace std;
//Repéresente une animation
class Animation : public Drawable, public Collidable
{
protected:
string _name; //Nome de l'animation
vector<AnimationFrame*> _frames; //Frames de l'animation
unsigned int _duration, _progress; //Durée/Progrès de l'animation (en Frame)
public:
//Animation():_name("Null"), _duration(0), _progress(0){};
Animation(const string& name, const vector<AnimationFrame*> frames);
Animation(const Animation& a){ *this = a;}
~Animation();
bool inProgress() const; //Indique si l'animation est en cours
const pair<int,int>& nextFrame(); //Défile l'animation et retourne la position de la frame active
bool collideA(const SDL_Rect* box) const; //Vérifie si une hitbox rentre en collision active avec la frame active
bool collideP(const SDL_Rect* box) const; //Vérifie si une hitbox rentre en collision passive avec la frame active
void holdPos(const pair<int,int>& pos); //Bloque toute les frames à une position donnée (repère SDL)
//Accesseurs
const string& name() const{ return _name;}
AnimationFrame* getFrame() const{ return _frames[_progress];}
AnimationFrame* getFrame(unsigned int i) const{ if(i<_duration) return _frames[i]; else return nullptr;}
Sprite& sprite() { return _frames[_progress]->sprite();};
const Sprite& sprite() const{ return _frames[_progress]->sprite();}
unsigned int duration() const{ return _duration;}
unsigned int progress() const{ return _progress+1;} //Numéro de la frame (indice+1)
/*
SDL_Texture *getTexture() const {return _frames[_progress]->getTexture();}//On recupere la texture de l'objet dessinable
SDL_Rect *getRect() const { return _frames[_progress]->getRect();}//On recupere la zone ou dessiner l'objet dessinable
*/
Animation& operator=(const Animation& a);
};
#endif

View file

@ -0,0 +1,425 @@
#include "AnimationBuilder.hpp"
//Chargement de toute les textures joueurs.
//Amélioration : ne charger les texture que une à une quand elles sont demandés
AnimationBuilder::AnimationBuilder(SDL_Renderer *renderer):_renderer(renderer)
{
//ATTENTION BUILDER CREER UNE FOIS PAR JOUEUR (soit singleton soit texture persos)
//addTexture("red_square","images/red_square.png");
// addTexture("stand","images/stickman_stand.png");
// addTexture("right_move","images/stickman_right.png");
// addTexture("jump","images/jump.jpg");
// addTexture("crouch1","images/crouch1.jpg");
// addTexture("crouch2","images/crouch2.jpg");
// addTexture("punch","images/stickman_punch.png");
addTexture("stand","images/Robot/robot_stand.png");
addTexture("right_move","images/Robot/robot_right.png");
addTexture("right_move2","images/Robot/robot_right2.png");
addTexture("left_move","images/Robot/robot_left.png");
addTexture("left_move2","images/Robot/robot_left2.png");
addTexture("jump","images/Robot/robot_jump.png");
addTexture("jump_right","images/Robot/robot_jump_right.png");
addTexture("jump_right2","images/Robot/robot_jump_right2.png");
addTexture("jump_left","images/Robot/robot_jump_left.png");
addTexture("jump_left2","images/Robot/robot_jump_left2.png");
addTexture("crouch","images/Robot/robot_crouch.png");
addTexture("attack_left","images/Robot/robot_attack_left.png");
addTexture("attack_left2","images/Robot/robot_attack_left2.png");
addTexture("attack_right","images/Robot/robot_attack_right.png");
addTexture("attack_right2","images/Robot/robot_attack_right2.png");
}
AnimationBuilder::~AnimationBuilder()
{
for(auto & i : _texture) // map<>::iterator
{
SDL_DestroyTexture(i.second); //Destruction des textures
}
}
//Ajout d'une texture au dictionnaire
void AnimationBuilder::addTexture(const string name, const string imgPath)
{
//Chargement d'une texture par defaut (objet noir)
SDL_Surface *tmpSurface = IMG_Load(imgPath.c_str());
//Verification de la non presence d'erreur lors du chargement
if(!tmpSurface)
std::cout << "AnimationBuilder : Surface "<< name <<" non chargee. Erreur :" << SDL_GetError() << std::endl;
//Creation/Ajout de la texture a partir de la surface chargee
_texture [name]= SDL_CreateTextureFromSurface(_renderer, tmpSurface);
//Liberation de la memoire allouee pour la surface
SDL_FreeSurface(tmpSurface);
}
//Construit une frame de joueur. Par défaut, sans active hitbox et avec le rectangle de texture en passive hitbox.
AnimationFrame* AnimationBuilder::PlayerFrame(SDL_Texture * texture, const pair<int,int>& Pos, SDL_Rect* SpriteRect, const vector<SDL_Rect*> ahitbox, const vector<SDL_Rect*>& phitbox) const
{
AnimationFrame* res;
if(SpriteRect == nullptr)
{
SpriteRect = createRect(Pos.first,Pos.second,PLAYER_WIDTH,PLAYER_HEIGHT);
}
Sprite s(SpriteRect,texture);
if(phitbox.size()==0)//Passive hitbox par défault (Rectangle du sprite)
{
//cout<<"default"<<endl;
vector<SDL_Rect*> defPhitbox;
defPhitbox.push_back(SpriteRect);
res = new AnimationFrame(s,defPhitbox,ahitbox, Pos);
}
else
res = new AnimationFrame(s,phitbox,ahitbox, Pos);
return res;
}
//ON prefere des constructeur avec pos initial ou intial/final ?
//Construit l'animation statique
Animation* AnimationBuilder::stand(const pair<int,int>& StartPos)
{
//cout<<"AnimationBuilder : Stand"<<endl;
vector<AnimationFrame*> anim;
anim.push_back(PlayerFrame(_texture["stand"], StartPos));
/*
//Creation d'une hitbox
SDL_Rect *h = createRect(StartPos.first,StartPos.second,PLAYER_WIDTH,PLAYER_HEIGHT);
//ATTENTION A LA POSITION ? POSITION DU CDG OU DES PIEDS ?
//Declaration du vecteur des hitboxes d'un personnage
vector<SDL_Rect*> phitbox;
//Ajout d'une hitbox au vecteur
phitbox.push_back(h);
vector<SDL_Rect*> ahitbox; //Vide
//Ajout d'une hitbox au vecteur
//ahitbox.push_back(h2);
//Sprite s(_renderer, h, "images/stickman_stand.png");
Sprite s(h,_texture["stand"]);
//Creation d'une frame d'une animation composee de cette hitbox
AnimationFrame* animF = new AnimationFrame(s,phitbox,ahitbox, StartPos);
//Creation de l'animation en ajoutant la frame
vector<AnimationFrame*> anim;
anim.push_back(animF);
*/
//Animation res(anim);
return new Animation("Stand",anim);//Attention on souhaite plus tard creer des ensemble de frame
}
//Construit un déplacement vers la droite
//Vitesse en fonction des positions/nombre de frames ...
Animation* AnimationBuilder::moveRight(const pair<int,int>& StartPos)
{
//cout<<"AnimationBuilder : moveRight"<<endl;
pair<int,int> FinalPos = make_pair(StartPos.first+PLAYER_MOVE_DISTANCE, StartPos.second); //Position finale
pair<int,int> MidPos = make_pair((StartPos.first + FinalPos.first)/2, (StartPos.second + FinalPos.second)/2); //Position Intermédiaire
//cout<<" "<<StartPos.first<<"/"<<StartPos.second<<"-"<<FinalPos.first<<"/"<<FinalPos.second<<endl;
vector<AnimationFrame*> anim;
vector<SDL_Rect*> aHitbox; aHitbox.push_back(createRect(StartPos.first, StartPos.second,PLAYER_WIDTH,PLAYER_HEIGHT));
//1ere frame
//anim.push_back(PlayerFrame(_texture["right_move"], StartPos, nullptr, aHitbox));
anim.push_back(PlayerFrame(_texture["right_move"], StartPos));
anim.push_back(PlayerFrame(_texture["right_move"], StartPos));
/*
SDL_Rect *h = createRect(StartPos.first,StartPos.second,PLAYER_WIDTH,PLAYER_HEIGHT);
vector<SDL_Rect*> phitbox;
phitbox.push_back(h);
vector<SDL_Rect*> ahitbox; //Vide
Sprite s1(h,_texture["stand"]);
//AnimationFrame animF1(phitbox,ahitbox, StartPos);
AnimationFrame* animF1 = new AnimationFrame(s1,phitbox,ahitbox, StartPos);
*/
//2e Frame
anim.push_back(PlayerFrame(_texture["right_move"], MidPos));
anim.push_back(PlayerFrame(_texture["right_move2"], MidPos));
/*
h = createRect(MidPos.first,MidPos.second,PLAYER_WIDTH,PLAYER_HEIGHT);
phitbox.clear();
phitbox.push_back(h);
ahitbox.clear(); //Vide
//ahitbox.push_back(h2);
Sprite s2(h,_texture["right_move"]);
//AnimationFrame animF2(phitbox,ahitbox, MidPos);
AnimationFrame* animF2 = new AnimationFrame(s2,phitbox,ahitbox, MidPos);
*/
//3e Frame
anim.push_back(PlayerFrame(_texture["right_move2"], FinalPos));
anim.push_back(PlayerFrame(_texture["stand"], FinalPos));
/*
h = createRect(FinalPos.first,FinalPos.second,PLAYER_WIDTH,PLAYER_HEIGHT);
phitbox.clear();
phitbox.push_back(h);
ahitbox.clear(); //Vide
Sprite s3(h,_texture["stand"]);
//AnimationFrame animF3(phitbox,ahitbox, FinalPos);
AnimationFrame* animF3 = new AnimationFrame(s3,phitbox,ahitbox, FinalPos);
*/
//Creation de l'animation en ajoutant les frame
/*
vector<AnimationFrame*> anim;
anim.push_back(animF1);
anim.push_back(animF2);
anim.push_back(animF3);
*/
//cout<<"Builder Right size: "<< anim.size() <<endl;
//Animation res(anim);
return new Animation("Right Move",anim);//Attention on souhaite plus tard creer des ensemble de frame
}
//Construit un déplacement vers la gauche
//Vitesse en fonction des positions/nombre de frames ...
//Besoin de sprite approprié
Animation* AnimationBuilder::moveLeft(const pair<int,int>& StartPos)
{
//cout<<"AnimationBuilder : moveLeft"<<endl;
pair<int,int> FinalPos = make_pair(StartPos.first-PLAYER_MOVE_DISTANCE, StartPos.second); //Position finale
pair<int,int> MidPos = make_pair((StartPos.first + FinalPos.first)/2, (StartPos.second + FinalPos.second)/2); //Position Intermédiaire
//cout<<" "<<StartPos.first<<"/"<<StartPos.second<<"-"<<FinalPos.first<<"/"<<FinalPos.second<<endl;
vector<AnimationFrame*> anim;
//1ere frame
anim.push_back(PlayerFrame(_texture["left_move"], StartPos));
anim.push_back(PlayerFrame(_texture["left_move"], StartPos));
//2e Frame
anim.push_back(PlayerFrame(_texture["left_move"], MidPos));
anim.push_back(PlayerFrame(_texture["left_move2"], MidPos));
//3e Frame
anim.push_back(PlayerFrame(_texture["left_move2"], FinalPos));
anim.push_back(PlayerFrame(_texture["stand"], FinalPos));
//Animation res(anim);
return new Animation("Left Move",anim);
}
//Construit un saut
//PB DERNIERE FRAME PAS JOUER -> CHECK player in progress
Animation* AnimationBuilder::jump(const pair<int,int>& StartPos)
{
//cout<<"AnimationBuilder : Jump"<<endl;
vector<AnimationFrame*> anim;
pair<int,int> MidPos = make_pair(StartPos.first, StartPos.second - PLAYER_JUMP_HEIGHT/2); //Position Intermédiaire
pair<int,int> TopPos = make_pair(StartPos.first, (StartPos.second - PLAYER_JUMP_HEIGHT)); //Position zenith
//1ere frame
anim.push_back(PlayerFrame(_texture["jump"], StartPos));
anim.push_back(PlayerFrame(_texture["jump"], StartPos));
anim.push_back(PlayerFrame(_texture["jump"], StartPos));
//2e frame
anim.push_back(PlayerFrame(_texture["jump"], MidPos));
anim.push_back(PlayerFrame(_texture["jump"], MidPos));
anim.push_back(PlayerFrame(_texture["jump"], MidPos));
//3e frame
anim.push_back(PlayerFrame(_texture["jump"], TopPos));
anim.push_back(PlayerFrame(_texture["jump"], TopPos));
anim.push_back(PlayerFrame(_texture["jump"], TopPos));
//4e frame
anim.push_back(PlayerFrame(_texture["stand"], MidPos));
anim.push_back(PlayerFrame(_texture["stand"], MidPos));
anim.push_back(PlayerFrame(_texture["stand"], MidPos));
//5e frame
anim.push_back(PlayerFrame(_texture["stand"], StartPos));
anim.push_back(PlayerFrame(_texture["stand"], StartPos));
//Frame de debbug : PB de dernière frame pas tjrs jouer
//anim.push_back(PlayerFrame(_texture["stand"], StartPos));
//Animation res(anim);
return new Animation("Jump",anim);//Attention on souhaite plus tard creer des ensemble de frame
}
//Construit un saut vers la droite
//Besoin de sprite approprié
Animation* AnimationBuilder::rightJump(const pair<int,int>& StartPos)
{
//cout<<"AnimationBuilder : Right Jump"<<endl;
vector<AnimationFrame*> anim;
pair<int,int> MidPos1 = make_pair(StartPos.first+PLAYER_MOVE_DISTANCE, StartPos.second - PLAYER_JUMP_HEIGHT/4); //Position Intermédiaire
pair<int,int> MidPos2 = make_pair(StartPos.first+PLAYER_MOVE_DISTANCE*2, StartPos.second - PLAYER_JUMP_HEIGHT/2); //Position Intermédiaire
pair<int,int> TopPos = make_pair(StartPos.first+PLAYER_MOVE_DISTANCE*3, (StartPos.second - PLAYER_JUMP_HEIGHT)); //Position zenith
pair<int,int> MidPos3 = make_pair(StartPos.first+PLAYER_MOVE_DISTANCE*4, StartPos.second - PLAYER_JUMP_HEIGHT/2); //Position Intermédiaire
pair<int,int> MidPos4 = make_pair(StartPos.first+PLAYER_MOVE_DISTANCE*5, StartPos.second - PLAYER_JUMP_HEIGHT/4); //Position Intermédiaire
pair<int,int> EndPos = make_pair(StartPos.first+PLAYER_MOVE_DISTANCE*6, StartPos.second); //Position Intermédiaire
anim.push_back(PlayerFrame(_texture["jump_right"], StartPos));
anim.push_back(PlayerFrame(_texture["jump_right"], MidPos1));
anim.push_back(PlayerFrame(_texture["jump_right"], MidPos1));
anim.push_back(PlayerFrame(_texture["jump_right"], MidPos2));
anim.push_back(PlayerFrame(_texture["jump_right"], MidPos2));
anim.push_back(PlayerFrame(_texture["jump"], TopPos));
anim.push_back(PlayerFrame(_texture["jump"], TopPos));
anim.push_back(PlayerFrame(_texture["jump_right2"], MidPos3));
anim.push_back(PlayerFrame(_texture["jump_right2"], MidPos3));
anim.push_back(PlayerFrame(_texture["jump_right2"], MidPos4));
anim.push_back(PlayerFrame(_texture["jump_right2"], MidPos4));
anim.push_back(PlayerFrame(_texture["jump_right2"], EndPos));
anim.push_back(PlayerFrame(_texture["stand"], EndPos));
return new Animation("Right Jump",anim);
}
//Construit un saut vers la gauche
//Besoin de sprite approprié
Animation* AnimationBuilder::leftJump(const pair<int,int>& StartPos)
{
//cout<<"AnimationBuilder : Left Jump"<<endl;
vector<AnimationFrame*> anim;
pair<int,int> MidPos1 = make_pair(StartPos.first-PLAYER_MOVE_DISTANCE, StartPos.second - PLAYER_JUMP_HEIGHT/4); //Position Intermédiaire
pair<int,int> MidPos2 = make_pair(StartPos.first-PLAYER_MOVE_DISTANCE*2, StartPos.second - PLAYER_JUMP_HEIGHT/2); //Position Intermédiaire
pair<int,int> TopPos = make_pair(StartPos.first-PLAYER_MOVE_DISTANCE*3, (StartPos.second - PLAYER_JUMP_HEIGHT)); //Position zenith
pair<int,int> MidPos3 = make_pair(StartPos.first-PLAYER_MOVE_DISTANCE*4, StartPos.second - PLAYER_JUMP_HEIGHT/2); //Position Intermédiaire
pair<int,int> MidPos4 = make_pair(StartPos.first-PLAYER_MOVE_DISTANCE*5, StartPos.second - PLAYER_JUMP_HEIGHT/4); //Position Intermédiaire
pair<int,int> EndPos = make_pair(StartPos.first-PLAYER_MOVE_DISTANCE*6, StartPos.second); //Position Intermédiaire
anim.push_back(PlayerFrame(_texture["jump_left"], StartPos));
anim.push_back(PlayerFrame(_texture["jump_left"], MidPos1));
anim.push_back(PlayerFrame(_texture["jump_left"], MidPos1));
anim.push_back(PlayerFrame(_texture["jump_left"], MidPos2));
anim.push_back(PlayerFrame(_texture["jump_left"], MidPos2));
anim.push_back(PlayerFrame(_texture["jump"], TopPos));
anim.push_back(PlayerFrame(_texture["jump"], TopPos));
anim.push_back(PlayerFrame(_texture["jump_left2"], MidPos3));
anim.push_back(PlayerFrame(_texture["jump_left2"], MidPos3));
anim.push_back(PlayerFrame(_texture["jump_left2"], MidPos4));
anim.push_back(PlayerFrame(_texture["jump_left2"], MidPos4));
anim.push_back(PlayerFrame(_texture["jump_left2"], EndPos));
anim.push_back(PlayerFrame(_texture["stand"], EndPos));
return new Animation("Left Jump",anim);
}
//Constuit l'animation pour s'accroupir
Animation* AnimationBuilder::crouch(const pair<int,int>& StartPos)
{
//cout << "AnimationBuilder : Crouch" << endl;
vector<AnimationFrame*> anim;
SDL_Rect* crouchRect1 = createRect(StartPos.first,StartPos.second+PLAYER_HEIGHT*1/3,PLAYER_WIDTH,PLAYER_HEIGHT*2/3); //Acrroupi = plus petite hitbox/sprite
SDL_Rect* crouchRect2 = createRect(StartPos.first,StartPos.second+PLAYER_HEIGHT*1/3,PLAYER_WIDTH,PLAYER_HEIGHT*2/3);
anim.push_back(PlayerFrame(_texture["crouch"], StartPos, crouchRect1));
anim.push_back(PlayerFrame(_texture["crouch"], StartPos, crouchRect2));
return new Animation("Crouch", anim);
}
//Construit une chute
Animation* AnimationBuilder::fall(const pair<int, int>& StartPos)//, const pair<int, int>& EndPos)
{
//cout << "AnimationBuilder : Fall" << endl;
vector<AnimationFrame*> anim;
/*
pair<int, int> pos;
//Chute a vitesse consdtante... on peut l'ameliorer on verra
int y = StartPos.second;
while( y < EndPos.second )
{
pos = make_pair(StartPos.first, y);
anim.push_back(PlayerFrame(_texture["stand"], pos));
y += 1;
}
*/
pair<int, int> newPos(StartPos.first, StartPos.second + PLAYER_FALL_SPEED);
// anim.push_back(PlayerFrame(_texture["stand"], StartPos));
anim.push_back(PlayerFrame(_texture["stand"], newPos));
//COmment faire ? On aimerait detecter le bord le plus pres sur lequel le perso atterit ?
return new Animation("Fall", anim);
}
//Construit une attaque vers la droite
//Hitbox active à retravailler ! (parade impossible)
Animation* AnimationBuilder::attackRight(const pair<int,int>& StartPos)
{
vector<AnimationFrame*> anim;
vector<SDL_Rect*> attackBox1;
//attackBox.push_back(createRect(StartPos.first,StartPos.second+PLAYER_HEIGHT*1/4,PLAYER_WIDTH,PLAYER_HEIGHT*1/10));
attackBox1.push_back(createRect(StartPos.first,StartPos.second,PLAYER_WIDTH,PLAYER_HEIGHT*1/3));
vector<SDL_Rect*> attackBox2;
//attackBox.push_back(createRect(StartPos.first,StartPos.second+PLAYER_HEIGHT*1/4,PLAYER_WIDTH,PLAYER_HEIGHT*1/10));
attackBox2.push_back(createRect(StartPos.first,StartPos.second,PLAYER_WIDTH*3/2,PLAYER_HEIGHT*1/3));
anim.push_back(PlayerFrame(_texture["attack_right"], StartPos, nullptr, attackBox1));
anim.push_back(PlayerFrame(_texture["attack_right"], StartPos, nullptr, attackBox1));
anim.push_back(PlayerFrame(_texture["attack_right"], StartPos, nullptr, attackBox1));
anim.push_back(PlayerFrame(_texture["attack_right2"], StartPos, nullptr, attackBox2));
anim.push_back(PlayerFrame(_texture["attack_right2"], StartPos, nullptr, attackBox2));
anim.push_back(PlayerFrame(_texture["attack_right2"], StartPos, nullptr, attackBox2));
anim.push_back(PlayerFrame(_texture["stand"], StartPos));
return new Animation("Attack Right", anim);
}
//Construit une attaque vers la gauche
//Besoin de sprite approprié
//Hitbox active à retravailler ! (parade impossible)
Animation* AnimationBuilder::attackLeft(const pair<int,int>& StartPos)
{
vector<AnimationFrame*> anim;
vector<SDL_Rect*> attackBox1;
attackBox1.push_back(createRect(StartPos.first-PLAYER_WIDTH,StartPos.second,PLAYER_WIDTH,PLAYER_HEIGHT*1/3));
vector<SDL_Rect*> attackBox2;
//attackBox.push_back(createRect(StartPos.first,StartPos.second+PLAYER_HEIGHT*1/4,PLAYER_WIDTH,PLAYER_HEIGHT*1/10));
attackBox2.push_back(createRect(StartPos.first-PLAYER_WIDTH/2,StartPos.second,PLAYER_WIDTH*3/2,PLAYER_HEIGHT*1/3));
anim.push_back(PlayerFrame(_texture["attack_left"], StartPos, nullptr, attackBox1));
anim.push_back(PlayerFrame(_texture["attack_left"], StartPos, nullptr, attackBox1));
anim.push_back(PlayerFrame(_texture["attack_left"], StartPos, nullptr, attackBox1));
anim.push_back(PlayerFrame(_texture["attack_left2"], StartPos, nullptr, attackBox2));
anim.push_back(PlayerFrame(_texture["attack_left2"], StartPos, nullptr, attackBox2));
anim.push_back(PlayerFrame(_texture["attack_left2"], StartPos, nullptr, attackBox2));
anim.push_back(PlayerFrame(_texture["stand"], StartPos));
return new Animation("Attack Left", anim);
}

View file

@ -0,0 +1,39 @@
#ifndef ANIMATIONBUILDER_HPP
#define ANIMATIONBUILDER_HPP
#include <map>
#include "../Animation/Animation.hpp"
#include "../GameParam.hpp"
SDL_Rect *createRect(int x, int y, int w, int h); //Forward Declaration (Game.cpp)
//Usine à animation
//Possiblement transformer en singleton
class AnimationBuilder
{
protected:
SDL_Renderer *_renderer; //Outils de rendu lié à display (Détruit dans display)
map<string,SDL_Texture *> _texture; //Dictionnaire des textures
public:
AnimationBuilder(SDL_Renderer *renderer);
~AnimationBuilder();
void addTexture(const string name, const string imgPath); //Ajout d'une texture au dictionnaire
//Construit une frame de joueur. Par défaut, sans active hitbox et avec le rectangle de texture en passive hitbox.
AnimationFrame* PlayerFrame(SDL_Texture * texture, const pair<int,int>& Pos, SDL_Rect* SpriteRect = nullptr, const vector<SDL_Rect*> ahitbox =vector<SDL_Rect*>(), const vector<SDL_Rect*>& phitbox =vector<SDL_Rect*>()) const;
//Pas de const à cause de SDL_Texture...
Animation* stand(const pair<int,int>& StartPos); //Construit l'animation statique
Animation* moveRight(const pair<int,int>& StartPos); //Construit un déplacement vers la droite
Animation* moveLeft(const pair<int,int>& StartPos); //Construit un déplacement vers la gauche
Animation* jump(const pair<int,int>& StartPos); //Construit un saut
Animation* rightJump(const pair<int,int>& StartPos); //Construit un saut vers la droite
Animation* leftJump(const pair<int,int>& StartPos); //Construit un saut vers la gauche
Animation* crouch(const pair<int,int>& StartPos); //Constuit l'animation pour s'accroupir
Animation* fall(const pair<int, int>& StartPos); //Construit une chute
Animation* attackRight(const pair<int,int>& StartPos); //Construit une attaque vers la droite
Animation* attackLeft(const pair<int,int>& StartPos); //Construit une attaque vers la gauche
};
#endif

View file

@ -0,0 +1,150 @@
#include "AnimationFrame.hpp"
AnimationFrame::AnimationFrame(const Sprite& s, const vector<SDL_Rect*>& pHitBox, const vector<SDL_Rect*>& aHitBox, const pair<int,int>& center)
{
_sprite=s; //Attention opérateur par copie !
_center = center;
//Copie des hitbox
SDL_Rect* nr = nullptr;
for(SDL_Rect* r : pHitBox)
{
nr = createRect(r->x, r->y, r->w, r->h);
_passiveHitbox.push_back(nr);
}
for(SDL_Rect* r : aHitBox)
{
nr = createRect(r->x, r->y, r->w, r->h);
_activeHitbox.push_back(nr);
}
}
AnimationFrame::~AnimationFrame()
{
//cout<<"Delete AnimF"<<endl;
for(SDL_Rect* p : _passiveHitbox)
delete p;
for(SDL_Rect* a : _activeHitbox)
delete a;
// _passiveHitbox.clear();
// _activeHitbox.clear();
}
///Vérifie si une hitbox rentre en collision active
bool AnimationFrame::collideA(const SDL_Rect* box) const
{
for(SDL_Rect* b : _activeHitbox)
{
if(SDL_HasIntersection(box,b) == SDL_TRUE) //Collision avec une hitbox
{
//cout<<"Collision !"<<endl;
return true;
}
}
return false;
}
//Vérifie si une hitbox rentre en collision passive
bool AnimationFrame::collideP(const SDL_Rect* box) const
{
//cout<<"AnimationFrame : Collision test"<<endl;
for(SDL_Rect* b : _passiveHitbox)
{
// if(SDL_IntersectRect(box,b,nullptr) == SDL_TRUE) //Collision avec une hitbox
// {
// cout<<"Collision !"<<endl;
// return true;
// }
if(SDL_HasIntersection(box,b) == SDL_TRUE) //Collision avec une hitbox
{
//cout<<"Collision !"<<endl;
return true;
}
// if(checkCollision(box,b))
// {
// // cout<<"Collision !"<<endl;
// // cout<<"B1 : "<<box->x<<"/"<<box->y<<" - "<<box->w<<"/"<<box->h<<endl;
// // cout<<"B2 : "<<b->x<<"/"<<b->y<<" - "<<b->w<<"/"<<b->h<<endl;
// return true;
// }
}
return false;
}
//Deplace la frame à un centre donner (repère SDL)
void AnimationFrame::translate(const pair<int,int>& pos)
{
//Caclul du vecteur de translation
pair<int,int> transform;
transform.first = pos.first - _center.first;
transform.second = pos.second - _center.second;
//Application de la translation
_center = pos;
for(SDL_Rect* r : _passiveHitbox)
{
r->x+=transform.first;
r->y+=transform.second;
}
for(SDL_Rect* r : _activeHitbox)
{
r->x+=transform.first;
r->y+=transform.second;
}
}
AnimationFrame& AnimationFrame::operator=(const AnimationFrame& a)
{
_sprite = a.sprite(); //Attention opérateur =
_center = a.center();
//Copie des hitbox (ATTENTION delete)
SDL_Rect* nr = nullptr;
vector<SDL_Rect*> v = a.pHitBox();
for(SDL_Rect* r : v)
{
nr = createRect(r->x, r->y, r->w, r->h);
_passiveHitbox.push_back(nr);
}
v=a.aHitBox();
for(SDL_Rect* r : v)
{
nr = createRect(r->x, r->y, r->w, r->h);
_activeHitbox.push_back(nr);
}
return *this;
}
bool AnimationFrame::operator==(const AnimationFrame& a) const
{
bool res = true;
if(_center==a.center() && _sprite==a.sprite() && _passiveHitbox.size()==a.pHitBox().size() && _activeHitbox.size()==a.aHitBox().size())
{
for(unsigned int i=0;i<_passiveHitbox.size();i++)
{
if(SDL_RectEquals(_passiveHitbox[i],a.pHitBox()[i])==SDL_FALSE)
{
res = false;
break;
}
}
if(res) //Si c'est toujours bon
{
for(unsigned int i=0;i<_passiveHitbox.size();i++)
{
if(SDL_RectEquals(_activeHitbox[i],a.aHitBox()[i]) == SDL_FALSE)
{
res = false;
break;
}
}
}
}
return res;
}

View file

@ -0,0 +1,49 @@
#ifndef ANIMATIONFRAME_HPP
#define ANIMATIONFRAME_HPP
#include <vector>
//#include "../gui/sprite.hpp"
#include "../Drawable.hpp"//Inclus sprite
#include "../Collidable.hpp"
using namespace std;
//bool checkCollision( const SDL_Rect* a, const SDL_Rect* b ); //Forward declaration (Game)
//Représente une frame d'animation
class AnimationFrame : public Drawable, public Collidable
{
protected:
Sprite _sprite; //Sprite (pourrait être préférable par pointeur)
vector<SDL_Rect*> _passiveHitbox; //Liste des hitbox passive (Reception de dommages)
vector<SDL_Rect*> _activeHitbox; //Liste des hitbox active (Envoie de dommages)
//Amelioration : rendre relatif au centre les autre attributs
pair<int,int> _center; //Centre du personnage (repère SDL)
public:
//AnimationFrame(){};
AnimationFrame(const Sprite& s, const vector<SDL_Rect*>& pHitBox, const vector<SDL_Rect*>& aHitBox, const pair<int,int>& center);
AnimationFrame(const AnimationFrame& a){ *this = a;}
~AnimationFrame();
bool collideA(const SDL_Rect* box) const; //Vérifie si une hitbox rentre en collision active
bool collideP(const SDL_Rect* box) const; //Vérifie si une hitbox rentre en collision passive
void translate(const pair<int,int>& pos); //Deplace la frame à un centre donner (repère SDL)
//Accesseurs
void addPHitbox(SDL_Rect* p){_passiveHitbox.push_back(p);}
void addAHitbox(SDL_Rect* a){_activeHitbox.push_back(a);}
Sprite& sprite() { return _sprite;}
const Sprite& sprite() const{ return _sprite;}
pair<int,int>& center() { return _center;}
const pair<int,int>& center() const{ return _center;}
const vector<SDL_Rect*>& pHitBox() const { return _passiveHitbox;}
const vector<SDL_Rect*>& aHitBox() const {return _activeHitbox;}
//Opérateurs
AnimationFrame& operator=(const AnimationFrame& a);
bool operator==(const AnimationFrame& a) const;
};
#endif

21
src/Collidable.hpp Normal file
View file

@ -0,0 +1,21 @@
#ifndef COLLIDABLE_HPP
#define COLLIDABLE_HPP
#include <SDL2/SDL.h>
//http://lazyfoo.net/tutorials/SDL/27_collision_detection/index.php
//https://loka.developpez.com/tutoriel/sdl/collision/
class Collidable
{
public:
//Collidable(){}
virtual ~Collidable(){}
//Manque des infos de direction de collision (un set de direction ?)
virtual bool collideA(const SDL_Rect* box) const = 0; //Collisions passive
virtual bool collideP(const SDL_Rect* box) const = 0; //Collisions active
//On devrait avoir passiveCollide & *activeCollide* afin de pouvoir "parer"
};
#endif

View file

@ -0,0 +1,14 @@
#ifndef ATTACKCOMMAND_HPP
#define ATTACKCOMMAND_HPP
#include "Command.hpp"
class AttackCommand : public Command
{
public:
AttackCommand(int tgt){this->_name ="AttackCommand"; this->_target=tgt;}
virtual void execute(Player& p) const {p.attack();} //Execute l'action sur un joueur
//virtual void execute(Game& g){ Game.quit()= true;};
};
#endif

26
src/Command/Command.hpp Normal file
View file

@ -0,0 +1,26 @@
#ifndef COMMAND_HPP
#define COMMAND_HPP
#include <iostream>
#include "../GameEnv/Player.hpp"
//Représente une commande
//Command Pattern
class Command
{
protected:
std::string _name;
int _target; //0:système , >0 : Player
public:
virtual ~Command() {}
//Pourrait être préférable de prendre le jeu en argument
virtual void execute(Player& p) const = 0; //Execute l'action sur un joueur
//virtual void execute(Game& g) = 0;
//Accesseurs
const std::string& name() const{return _name;}
int target() const{return _target;}
};
#endif

View file

@ -0,0 +1,14 @@
#ifndef DOWNCOMMAND_HPP
#define DOWNCOMMAND_HPP
#include "Command.hpp"
class DownCommand : public Command
{
public:
DownCommand(int tgt){this->_name ="DownCommand"; this->_target=tgt;}
virtual void execute(Player& p) const {p.crouch();} //Execute l'action sur un joueur
//virtual void execute(Game& g){ Game.quit()= true;};
};
#endif

View file

@ -0,0 +1,14 @@
#ifndef EXITCOMMAND_HPP
#define EXITCOMMAND_HPP
#include "Command.hpp"
class ExitCommand : public Command
{
public:
ExitCommand(){this->_name ="ExitCommand"; this->_target=0;}
virtual void execute(Player& p) const {} //Execute l'action sur un joueur
//virtual void execute(Game& g){ Game.quit()= true;};
};
#endif

View file

@ -0,0 +1,13 @@
#ifndef FALLCOMMAND_HPP
#define FALLCOMMAND_HPP
#include "Command.hpp"
class FallCommand : public Command
{
public:
FallCommand(int tgt){this->_name ="FallCommand"; this->_target=tgt;};
virtual void execute(Player& p) const {p.fall();} //Execute l'action sur un joueur
};
#endif

186
src/Command/InputMap.cpp Normal file
View file

@ -0,0 +1,186 @@
#include "InputMap.hpp"
InputMap::InputMap()
{
//Default General map
_GeneralMap[SDLK_ESCAPE]= new ExitCommand();
//Default Player 1 map
_P1Map[SDLK_q]= new LeftCommand(1); //Q
_P1Map[SDLK_d]= new RightCommand(1); //D
_P1Map[SDLK_s]= new DownCommand(1); //S
_P1Map[SDLK_SPACE]= new JumpCommand(1); //SpaceBar
_P1Map[SDLK_g]= new AttackCommand(1); //G
_P1Map[SDLK_F1] = new FallCommand(1);
//Default Player 2 map
_P2Map[SDLK_LEFT]=new LeftCommand(2); //Fleche gauche
_P2Map[SDLK_RIGHT]= new RightCommand(2); //Fleche droite
_P2Map[SDLK_DOWN]= new DownCommand(2); //Fleche bas
_P2Map[SDLK_KP_ENTER] = new JumpCommand(2); //Enter Pav Num
_P2Map[SDLK_KP_0]= new AttackCommand(2); //0 Pav Num
_P2Map[SDLK_F2] = new FallCommand(2);
}
InputMap::~InputMap()
{
for(auto & i : _GeneralMap) //auto = map<>::iterator
{
delete i.second;
}
for(auto & i : _P1Map) //auto = map<>::iterator
{
delete i.second;
}
for(auto & i : _P2Map) //auto = map<>::iterator
{
delete i.second;
}
}
//Renvoie la commande associé à l'argument (nullptr si la commande n'existe pas)
Command* InputMap::operator()(int input)
{
//Recherche GeneralMap
map<int,Command*>::iterator it = _GeneralMap.find(input);
if(it != _GeneralMap.end()) //element trouvé
return _GeneralMap[input];
//Recherche Player 1 map
it = _P1Map.find(input);
if(it != _P1Map.end()) //element trouvé
return _P1Map[input];
//Recherche Player 2 map
it = _P2Map.find(input);
if(it != _P2Map.end()) //element trouvé
return _P2Map[input];
else //Aucune valeur trouvé
return nullptr;
}
//Relie une commande à une entrée et indique si un ancien mapping a été écrasée
bool InputMap::remap(Command* cmd, int new_input)
{
bool res = false; //Indique si une ancienne commande a ete ecrasée
//Suppresion de l'ancien mapping
int oldKey=0;
for(auto & i : _GeneralMap) //auto = map<>::iterator
{
if(i.second == cmd) //Action déja mappé dans General Map
{
//_GeneralMap.erase((map<int,string>::iterator)i);
oldKey = i.first; //On recupère la clé correspondante
res = true;
break;
}
}
_GeneralMap.erase(oldKey); //Suppresion de la clé associé à l'action
_GeneralMap.erase(new_input); //Suppresion de l'action lié à la nouvelle clé
for(auto & i : _P1Map) //auto = map<>::iterator
{
if(i.second == cmd) //Action déja mappé dans General Map
{
//_GeneralMap.erase((map<int,string>::iterator)i);
oldKey = i.first; //On recupère la clé correspondante
res = true;
break;
}
}
_P1Map.erase(oldKey); //Suppresion de la clé associé à l'action
_P1Map.erase(new_input); //Suppresion de l'action lié à la nouvelle clé
for(auto & i : _P2Map) //auto = map<>::iterator
{
if(i.second == cmd) //Action déja mappé dans General Map
{
//_GeneralMap.erase((map<int,string>::iterator)i);
oldKey = i.first; //On recupère la clé correspondante
res = true;
break;
}
}
_P2Map.erase(oldKey); //Suppresion de la clé associé à l'action
_P2Map.erase(new_input); //Suppresion de l'action lié à la nouvelle clé
//Ajout de la nouvelle entrée
switch(cmd->target())
{
case(0): //Action système
_GeneralMap[new_input]=cmd;
break;
case(1): //Action Joueur 1
_P1Map[new_input]=cmd;
break;
case(2): //Action Joueur 2
_P2Map[new_input]=cmd;
break;
}
return res;
}
ostream& operator<<(ostream& os,const InputMap& im)
{
//Verification
//Operation
map<int,Command*> map = im.GMap();
os<< "General" << endl;
for(auto & i : map) //auto = map<>::iterator
{
os<< " " << i.first << " : " << i.second->name() << " " << i.second->target() <<endl;
}
map = im.P1Map();
os<< endl << " P1 Map" << endl;
for(auto & i : map) //auto = map<>::iterator
{
os<< " " << i.first << " : " << i.second->name() << " " << i.second->target() <<endl;
}
map = im.P2Map();
os<< endl << " P2 Map" << endl;
for(auto & i : map) //auto = map<>::iterator
{
os<< " " << i.first << " : " << i.second->name() << " " << i.second->target() <<endl;
}
return os;
}
/*
ostream& operator<<(ostream& os,const InputMap& im)
{
//Verification
//Operation
map<int,string> map = im.GMap();
os<< "General" << endl;
for(auto & i : map) //auto = map<>::iterator
{
os<< " " << i.first << " : " << i.second <<endl;
}
map = im.P1Map();
os<< endl << " P1 Map" << endl;
for(auto & i : map) //auto = map<>::iterator
{
os<< " " << i.first << " : " << i.second <<endl;
}
map = im.P2Map();
os<< endl << " P2 Map" << endl;
for(auto & i : map) //auto = map<>::iterator
{
os<< " " << i.first << " : " << i.second <<endl;
}
return os;
}
*/

44
src/Command/InputMap.hpp Normal file
View file

@ -0,0 +1,44 @@
#ifndef INPUTMAP_HPP
#define INPUTMAP_HPP
#include <map>
#include <iostream>
#include "Command.hpp"
#include "NullCommand.hpp"
#include "ExitCommand.hpp"
#include "RightCommand.hpp"
#include "LeftCommand.hpp"
#include "JumpCommand.hpp"
#include "DownCommand.hpp"
#include "FallCommand.hpp"
#include "AttackCommand.hpp"
using namespace std;
//Représente une map des entrée utilisateurs
class InputMap
{
protected:
//https://wiki.libsdl.org/SDL_Keycode
map<int,Command*> _GeneralMap; //Map des commandes système
map<int,Command*> _P1Map; //Map des commandes joueur 1
map<int,Command*> _P2Map; //Map des commandes joueur 2
public:
InputMap();
~InputMap();
Command* operator()(int input); //Renvoie la commande associé à l'argument
//Command* operator()(SDL_Keycode input);
bool remap(Command* action, int new_input); //Relie une commande à une entrée et indique si un ancien mapping a été écrasée
//Accesseurs
const map<int,Command*>& GMap() const { return _GeneralMap;};
const map<int,Command*>& P1Map() const { return _P1Map;};
const map<int,Command*>& P2Map() const { return _P2Map;};
};
//Operateur << std
ostream& operator<<(ostream& os,const InputMap& im);
#endif

View file

@ -0,0 +1,13 @@
#ifndef JUMPCOMMAND_HPP
#define JUMPCOMMAND_HPP
#include "Command.hpp"
class JumpCommand : public Command
{
public:
JumpCommand(int tgt){this->_name ="JumpCommand"; this->_target=tgt;};
virtual void execute(Player& p) const {p.jump();} //Execute l'action sur un joueur
};
#endif

View file

@ -0,0 +1,13 @@
#ifndef LEFTCOMMAND_HPP
#define LEFTCOMMAND_HPP
#include "Command.hpp"
class LeftCommand : public Command
{
public:
LeftCommand(int tgt){this->_name ="LeftCommand"; this->_target=tgt;};
virtual void execute(Player& p) const {p.moveLeft();} //Execute l'action sur un joueur
};
#endif

View file

@ -0,0 +1,15 @@
#ifndef NULLCOMMAND_HPP
#define NULLCOMMAND_HPP
#include "Command.hpp"
class NullCommand : public Command
{
public:
NullCommand(){this->_name ="NullCommand"; this->_target=-1;}
NullCommand(string name){this->_name =name; this->_target=0;} //Commande système en attendant de mieux
virtual void execute(Player& p) const {} //Execute l'action sur un joueur
//virtual void execute(Game& g){};
};
#endif

View file

@ -0,0 +1,13 @@
#ifndef RIGHTCOMMAND_HPP
#define RIGHTCOMMAND_HPP
#include "Command.hpp"
class RightCommand : public Command
{
public:
RightCommand(int tgt){this->_name ="RightCommand"; this->_target=tgt;}
virtual void execute(Player& p) const {p.moveRight();} //Execute l'action sur un joueur
};
#endif

18
src/Drawable.hpp Normal file
View file

@ -0,0 +1,18 @@
#ifndef DRAWABLE_HPP
#define DRAWABLE_HPP
#include "SDL2/SDL.h"
#include "./gui/sprite.hpp"
class Drawable
{
public:
//Drawable(){};
virtual ~Drawable(){};
//virtual SDL_Texture *getTexture() const = 0;//On recupere la texture de l'objet dessinable
//virtual SDL_Rect *getRect() const = 0;//On recupere la zone ou dessiner l'objet dessinable
virtual Sprite& sprite() = 0; //On recupère l'objet dessinable (peut pas etre const à cause de texture ?)
virtual const Sprite& sprite() const = 0;
};
#endif

View file

@ -0,0 +1,18 @@
#ifndef COMPUTERPLAYER_HPP
#define COMPUTERPLAYER_HPP
#include "../GameEnv/Player.hpp"
class Game; //Forward trop limité pour le traitement de l'IA
//Classe parente de toute les IA
class ComputerPlayer : public Player
{
public:
ComputerPlayer(const pair<int,int>& StartPos, SDL_Renderer *renderer): Player(StartPos, renderer){_ia = true;}
//virtual ~ComputerPlayer(){}
virtual void nextAction(const Game* g){ this->jump();} //A surcharger pour le traitement
};
#endif

403
src/GameEnv/Game.cpp Normal file
View file

@ -0,0 +1,403 @@
#include "Game.hpp"
//Single Instance
Game Game::_instance=Game();
//Constructeur singleton
Game::Game() : _builder(_disp.getRenderer())
{
//Environement
_world = _builder.sky();
//_world = _builder.collisionTest();
//Joueur
pair<int,int> start_pos_P1 = make_pair (P1_START_POSX,P1_START_POSY);
Player* p1 = new Player(start_pos_P1,_disp.getRenderer());
_playerList.push_back(p1);
pair<int,int> start_pos_P2 = make_pair (P2_START_POSX,P2_START_POSY);
Player* p2 = new Player(start_pos_P2,_disp.getRenderer()); //Joueurs
//Player* p2 = new ComputerPlayer(start_pos_P2,_disp.getRenderer()); //IA
_playerList.push_back(p2);
//Print infos
cout << "World : "<<_world->name()<<endl;
for(Player* p : _playerList)
{
cout<<"Player "<<p->id()<<" ready !"<<endl;
}
}
//Destructeur singleton
Game::~Game()
{
for(Player* p : _playerList)
delete p;
delete _world;
}
//Effectue un tour de jeu
void Game::run()
{
//_quit = true;
//cout<<"-------------------"<<endl;
_loopTime = SDL_GetTicks() + MIN_LOOP_TIME; //Temps fin de boucle prévu
//Handle events on queue
while( SDL_PollEvent( &_event ) != 0 )
{
switch( _event.type )
{
case SDL_QUIT: //User requests quit
_quit = true;
break;
case SDL_KEYDOWN:
//cout<<"Key down : "<< _event.key.keysym.sym<<endl;
_currInputs.insert(_event.key.keysym.sym);
break;
case SDL_KEYUP:
//cout<<"Key up : "<< _event.key.keysym.sym<<endl;
_currInputs.erase(_event.key.keysym.sym);
break;
default :
break;
}
}
if(_menu)
{
}
else //Next Game turn
{
//cout<<"Execute input"<<endl;
//Execute action
executeInput(_currInputs);
//executeInput(100); //P1 Droite
//executeInput(27); //Echap
for(Player* p : _playerList)
{
p->nextAnim(); //ATTENTION : on saute la pemière frame de chaque animation !
checkCollisions(p); //On s'assure que les actions des joueurs sont valide
checkHits(p); //Handle hits
}
}
//cout<<"Render"<<endl;
//Clear screen
SDL_RenderClear( _disp.getRenderer() );
//cout<<"draw"<<endl;
//Render texture to screen
draw();
_currTime = SDL_GetTicks(); //Temps fin de boucle
//cout<<"Time : "<<_currTime<<endl;
//cout<<"loopTime : "<< _loopTime<<endl;
if(_loopTime > _currTime)
{
//cout<<"wait : "<< _loopTime-_currTime<<endl;
SDL_Delay(_loopTime - _currTime);
}
}
//Affiche le jeu
void Game::draw()
{
//cout<<"draw W"<<endl;
_disp.draw(_world);
//cout<<"draw O"<<endl;
for(Obstacle* o : _world->obstacles())
{
_disp.draw(o);
}
//cout<<"draw P"<<endl;
for(Player* p : _playerList)
{
_disp.draw(p);
}
//cout<<"draw F"<<endl;
//cout<<"Valgrind err"<<endl;
//Update screen
SDL_RenderPresent( _disp.getRenderer() ); //Source d'erreur valgrind (?)
//cout<<"Valgrind no err"<<endl;
}
//Execute l'action correspondant à l'argument (si contenu dans l'inputMap)
void Game::executeInput(SDL_Keycode input)
{
Command* cmd = _inputMap(input);
if(cmd !=nullptr) //Commande valide
{
if(cmd->target()==0) //Commande système
{
//cout<<"Commande système : "<<cmd->name()<<endl;
if(cmd->name()=="ExitCommand")
_quit = true;
}
if(cmd->target()>0 && !_menu) //Commande joueur (Hors menu)
{
//cout<<"Commande joueur "<<cmd->target()<<" : "<<cmd->name()<<endl;
for(Player* p : _playerList)
{
if(cmd->target()==p->id())
cmd->execute(*p);
}
}
}
else
{
cout<<"Game Warning : Invalid Input"<<endl;
}
}
//Execute un ensemble d'action
void Game::executeInput(const set<int>& inputs)
{
// if(inputs.empty())//Aucune touche appuyée
// {
// }
//Gestion commande joueurs
for(int i : inputs)
{
//cout<<"Execute : "<<i<<endl;
executeInput(i);
}
//Gestion commande ordinateur
for(Player* p : _playerList)
{
if(p->isComputer())
{
p->nextAction(this);
}
}
}
//Verifie la validité de l'action d'un joueur (Hitbox Passive vs Passive & Active vs Active)
void Game::checkCollisions(Player * p)
{
bool falling = isFallingV2(p, _world->obstacles()); //On demande s'il y a chute
//Handle Active Collision
for(Player* op : _playerList)
{
if(p->id()!=op->id() && p->collideA(op)) //Pas de collision avec soit même
{
cout<<"Active collision !"<<endl;
resolveCollision(p,op); //Handle collision
}
}
//Handle Passive Collision
for(Obstacle* o : _world->obstacles())
{
//cout<<"B :"<<*o->box()<<endl;
if(p->collideP(o->box()))
{
//collided = true;
// cout<<"Player "<<p->id()<<" : Obstacle Collision"<<endl;
//Handle Collision
resolveCollision(p,o);
}
// cout << falling << " | " << collided << endl;
// cout << endl;
}
//cout << endl;
//Handle fall
if(falling)
{
//cout << "je tombe" << endl;
if(p->id() == 1)
{
// _currInputs.erase(SDLK_q);
// _currInputs.erase(SDLK_d);
// _currInputs.erase(SDLK_SPACE);
_currInputs.insert(SDLK_F1);
}
if(p->id() == 2)
{
// _currInputs.erase(SDLK_LEFT);
// _currInputs.erase(SDLK_RIGHT);
// _currInputs.erase(SDLK_KP_ENTER);
_currInputs.insert(SDLK_F2);
}
}
else
{
//cout << "je tombe pas" << endl;
if(p->id() == 1)
_currInputs.erase(SDLK_F1);
if(p->id() == 2)
_currInputs.erase(SDLK_F2);
}
}
//Verifie si un attaquant touche un autre joueur (Hitbox Active vs Passive)
void Game::checkHits(Player * attacker)
{
for(Player* receiver : _playerList)
{
if(attacker->id()!=receiver->id() && attacker->hit(receiver)) //On s'assure que le joueur ne tente pas de s'attaquer lui meme
{
cout<<"Player "<<attacker->id()<<" hit Player "<<receiver->id()<<" !"<<endl;
//reset(); //On recommance un round
reset(receiver->id());
}
}
}
//Résoud un cas de collision joueur/obstacle (grossièrement)
//Un peu bugger mais vivable (+ Ne devrait pas permettre d'avoir des animations dans les obstacles)
void Game::resolveCollision(Player * p, Obstacle* o)
{
//Handle Collision
int x_transform = 0, y_transform = 0;
//Provisoire !
pair<int,int> pcenter = make_pair(p->pos().first+PLAYER_WIDTH/2, p->pos().second+PLAYER_HEIGHT/2); //Center géométrique de player
// cout<<"Player pos : "<<pcenter.first<<" / "<<pcenter.second<<endl;
// cout<<"Obstacle pos : "<<o->center().first<<" / "<<o->center().second<<endl;
if(pcenter.first < o->center().first) //Joueur à gauche de l'obstacle
{
x_transform = (o->center().first - pcenter.first) - (PLAYER_WIDTH/2+o->box()->w/2);
}
else if(pcenter.first > o->center().first)
{
x_transform = (pcenter.first - o->center().first) - (PLAYER_WIDTH/2+o->box()->w/2);
}
if(pcenter.second < o->center().second) //Joueur au dessus de l'obstacle
{
y_transform = (o->center().second - pcenter.second) - (PLAYER_HEIGHT/2+o->box()->h/2);
}
else if(pcenter.second > o->center().second) //Joueur au dessous de l'obstacle
{
//y_transform = (pcenter.second - o->center().second) - (PLAYER_HEIGHT/2+o->box()->h/2);
y_transform = (PLAYER_HEIGHT/2+o->box()->h/2) - (pcenter.second - o->center().second);
}
// cout<<"Transform : "<<x_transform<<" / "<<y_transform<<endl;
//Resolution de la collision (application du plus faible changement)
if(x_transform !=0 && abs(x_transform) < abs(y_transform))
{
p->holdPos(make_pair(p->pos().first+x_transform, p->pos().second)); //Translation en x
}
else //if(abs(y_transform)< PLAYER_HEIGHT)
{
p->holdPos(make_pair(p->pos().first, p->pos().second+y_transform)); //Translation en y
}
}
//Résoud un cas de collision joueur/joueur (Knockback des deux joueurs)
void Game::resolveCollision(Player * p1, Player* p2)
{
pair<int,int> pos1 = p1->pos(), pos2 = p2->pos();
if(pos1.first < pos2.first) //P1 à gauche de P2
{
pos1.first -= PLAYER_KNOCKBACK;
pos2.first += PLAYER_KNOCKBACK;
}
else //P2 à gauche de P1
{
pos1.first += PLAYER_KNOCKBACK;
pos2.first -= PLAYER_KNOCKBACK;
}
p1->stand(pos1);
p2->stand(pos2);
}
/*
bool Game::isFalling(Player *p, Obstacle *o)
{
pair<int,int> pcenter = make_pair(p->pos().first+PLAYER_WIDTH/2, p->pos().second+PLAYER_HEIGHT/2); //Center géométrique de player
int oh = o->box()->h;
int ow = o->box()->w;
cout << oh << " | " << o->center().second << endl;
cout << "position pied : " << pcenter.second + PLAYER_HEIGHT/2 << " | position du sol de l'obstacle : " << o->center().second - oh/2 -20 << endl;
if ((pcenter.second + PLAYER_HEIGHT/2 < o->center().second - oh/2 -5) && abs(pcenter.first - o->center().first) < ow/2)
return true;
return false;
}
*/
//Vérifie si un joueur chute
bool Game::isFalling(Player *p, std::vector<Obstacle*> obsList)
{
//Identification des obstacles sous le joueur eligibles
pair<int,int> pcenter = make_pair(p->pos().first+PLAYER_WIDTH/2, p->pos().second+PLAYER_HEIGHT/2); //Centre géométrique de player
int oh, ow;
Obstacle floor(*obsList[0]); //Risqué !
bool firstOcc = true;
for(Obstacle* o : obsList)
{
ow = o->box()->w;
oh = o->box()->h;
if ((abs(pcenter.first - o->center().first) <= ow/2) && (pcenter.second + PLAYER_HEIGHT/2 < o->center().second - oh/2))
{
if(firstOcc)
{
firstOcc = false;
floor = *o;
}
else if(o->center().second - oh/2 < floor.center().second - floor.box()->h/2)
floor = *o;
}
}
return (pcenter.second + PLAYER_HEIGHT/2 < floor.center().second - floor.box()->h/2);
}
//Vérifie si un joueur chute
bool Game::isFallingV2(const Player *p, const vector<Obstacle*> obsList)
{
bool res = true; //On suppose qu'il y a chute
//A simplifier en n'utilisant que les hitbox passive
AnimationFrame testFrame(*p->currFrame()); //Sert à tester si un chute est envisageable
pair<int,int> testPos = testFrame.center();
testPos.second += 1; //On test juste en dessous du personnage
testFrame.translate(testPos);
for(Obstacle* o : obsList)
{
if(testFrame.collideP(o->box())) //Si une frame touche un obstacle
{
res = false;
break;
}
}
return res;
}
//Remet à zéro la partie
//Replace les joueurs aux positions de départ
void Game::reset()
{
_playerList[0]->stand(make_pair(P1_START_POSX,P1_START_POSY));
_playerList[1]->stand(make_pair(P2_START_POSX,P2_START_POSY));
}
//Replace un joueur à son spawn
void Game::reset(unsigned int playerID)
{
if(playerID==1)
_playerList[0]->stand(make_pair(P1_START_POSX,P1_START_POSY));
if(playerID==2)
_playerList[1]->stand(make_pair(P2_START_POSX,P2_START_POSY));
}
Game& Game::operator=(const Game& g)
{
//_playerList = g.PList();
return *this;
}

63
src/GameEnv/Game.hpp Normal file
View file

@ -0,0 +1,63 @@
#ifndef GAME_HPP
#define GAME_HPP
#include <set>
#include "../gui/display.hpp"
#include "../Command/InputMap.hpp"
//#include "../GameEnv/Obstacle.hpp"
//#include "../GameEnv/World.hpp"
#include "../GameEnv/WorldBuilder.hpp"
#include "../GameEnv/ComputerPlayer.hpp" //Pour l'IA
#include "../Toolbox.hpp"
#include "../GameParam.hpp"
class Game
{
private:
Display& _disp = Display::Instance(); //Affichage
//vector<Obstacle*> _obsList;
World* _world; //Monde
WorldBuilder _builder; //Usine à monde (on pourrait l'externaliser en singleton)
vector<Player*> _playerList; //Liste des joueurs
set<int> _currInputs; //Touche appuyés (SDL_Keycode ! bug ?) (On preferait SDL_Keysym pour avoir les modifiers) (https://wiki.libsdl.org/SDL_Keysym)
InputMap _inputMap; //Map des entrée utilisateurs
bool _quit = false, _menu = false;
unsigned int _currTime,_loopTime; //millisecondes
//Event handler
SDL_Event _event;
//Singleton
static Game _instance;
Game();
~Game();
Game& operator=(const Game& g);
public:
void run(); //Effectue un tour de jeu
void draw(); //Affiche le jeu
void executeInput(int input); //Execute l'action correspondant à l'argument (si contenu dans l'inputMap)
void executeInput(const set<int>& inputs); //Execute un ensemble d'action
void checkCollisions(Player * p); //Verifie la validité de l'action d'un joueur (Hitbox Passive vs Passive & Active vs Active)
void checkHits(Player * attacker); //Verifie si un attaquant touche un autre joueur (Hitbox Active vs Passive)
void resolveCollision(Player * p, Obstacle* o); //Résoud un cas de collision joueur/obstacle (grossièrement)
void resolveCollision(Player * p1, Player* p2); //Résoud un cas de collision joueur/joueur (Knockback des deux joueurs)
bool isFalling(Player *p, std::vector<Obstacle*> obsList); //Vérifie si un joueur chute
bool isFallingV2(const Player *p, const vector<Obstacle*> obsList); //Vérifie si un joueur chute
void reset(); //Remet à zéro la partie
void reset(unsigned int playerID); //Replace un joueur à son spawn
//Singleton
static Game& Instance(){ return _instance;} //Accès à l'instance du jeu
//Accesseurs
std::vector<Player*> PList() const { return _playerList;}
bool quit() const { return _quit;}
bool& quit(){ return _quit;}
};
#endif

40
src/GameEnv/Obstacle.cpp Normal file
View file

@ -0,0 +1,40 @@
#include "Obstacle.hpp"
Obstacle::Obstacle(Sprite& s, SDL_Rect* collisionBox)
{
_sprite = s;
_collisionBox = collisionBox;
}
Obstacle::~Obstacle()
{
//std::cout<<"Destructeur Obstacle"<<std::endl;
delete _collisionBox;
}
//Verifie s'il y a collision avec une hitbox
bool Obstacle::collideP(const SDL_Rect* box) const
{
//std::cout<<"Obstacle : Collision test"<<std::endl;
if(SDL_HasIntersection(box,_collisionBox) == SDL_TRUE) //Collision avec une hitbox
return true;
else
return false;
}
Obstacle& Obstacle::operator=(const Obstacle& o)
{
_sprite = o.sprite();
_collisionBox = createRect(o.box()->x, o.box()->y, o.box()->w, o.box()->h);
//std::cout<<"Obs = : "<<*this->box()<<std::endl;
return *this;
}
bool Obstacle::operator==(const Obstacle& o) const
{
if(_sprite==o.sprite() && SDL_RectEquals(_collisionBox, o.box()) == SDL_TRUE)
return true;
else
return false;
}

35
src/GameEnv/Obstacle.hpp Normal file
View file

@ -0,0 +1,35 @@
#ifndef OBSTACLE_HPP
#define OBSTACLE_HPP
//#include "../gui/sprite.hpp" //Dans drawable
#include "../Drawable.hpp"
#include "../Collidable.hpp"
#include <iostream>
//std::ostream& operator<<(std::ostream& os, const SDL_Rect& r); //Forward declaration
//Obstacle passif
class Obstacle : public Drawable, public Collidable
{
protected:
SDL_Rect* _collisionBox;
Sprite _sprite;
public:
Obstacle(Sprite& s, SDL_Rect* collisionBox);
Obstacle(const Obstacle& o){ *this = o;}
~Obstacle();
bool collideA(const SDL_Rect* box) const { return false;} //Obstacles passifs
bool collideP(const SDL_Rect* box) const; //Verifie s'il y a collision avec une hitbox
//Accesseurs
std::pair<int,int> center() { return std::make_pair(_collisionBox->x+_collisionBox->w/2,_collisionBox->y+_collisionBox->h/2);}
Sprite& sprite() { return _sprite;}
const Sprite& sprite() const { return _sprite;}
const SDL_Rect* box() const{ return _collisionBox;}
Obstacle& operator=(const Obstacle& o);
bool operator==(const Obstacle& o) const;
};
#endif

198
src/GameEnv/Player.cpp Normal file
View file

@ -0,0 +1,198 @@
#include "Player.hpp"
unsigned int Player::nextPlayerID = 1;
Player::Player(const pair<int,int>& StartPos, SDL_Renderer *renderer): _builder(renderer)
{
_playerID = nextPlayerID++;
_pos = StartPos;
_currAnim = _builder.stand(_pos);
}
Player::~Player()
{
delete _currAnim;
}
//Reste en place
void Player::stand()
{
delete _currAnim;
_currAnim = _builder.stand(_pos);
}
//Reste en place à une position donnée
void Player::stand(const pair<int,int>& pos)
{
delete _currAnim;
_currAnim = _builder.stand(pos);
_pos = pos;
}
//Déplacement vers la droite (si possible)
void Player::moveRight()
{
if(!_currAnim->inProgress()) //Animation précédente terminée
{
delete _currAnim;
_currAnim = _builder.moveRight(_pos);
_prevDirection = true; //mvt droite
}
else if(_currAnim->name()=="Jump"&&_currAnim->progress()==0)
{
delete _currAnim;
_currAnim = _builder.rightJump(_pos);
_prevDirection = true; //mvt droite
}
}
//Déplacement vers la gauche (si possible)
void Player::moveLeft()
{
if(!_currAnim->inProgress()) //Animation précédente terminée
{
delete _currAnim;
_currAnim = _builder.moveLeft(_pos);
_prevDirection = false; //mvt gauche
}
else if(_currAnim->name()=="Jump"&&_currAnim->progress()==0)
{
delete _currAnim;
_currAnim = _builder.leftJump(_pos);
_prevDirection = false; //mvt gauche
}
}
//Saut (si possible)
void Player::jump()
{
if(!_currAnim->inProgress()) //Animation précédente terminée
{
delete _currAnim;
_currAnim = _builder.jump(_pos);
}
else if(_currAnim->name()=="Right Move")
{
delete _currAnim;
_currAnim = _builder.rightJump(_pos);
}
else if(_currAnim->name()=="Left Move")
{
delete _currAnim;
_currAnim = _builder.leftJump(_pos);
}
}
//Accroupis (si possible)
void Player::crouch()
{
if(!_currAnim->inProgress()) //Animation précédente terminée
{
delete _currAnim;
_currAnim = _builder.crouch(_pos);
}
}
//Chute
//Ne devrait pas pouvoir etre évité : Gestion de la chute à affiner
void Player::fall()
{
//N'agit pas si une animation de saut est en cours (Amelioration: ajouter attribut interompable dans animation)
//if( !(_currAnim->inProgress() && ( _currAnim->name()=="Jump" || _currAnim->name()=="Right Jump" || _currAnim->name()=="Left Jump")))
if(!_currAnim->inProgress()) //Animation précédente terminée
{
delete _currAnim;
_currAnim = _builder.fall(_pos);//, EndPos);
}
}
//Attaque (si possible)
void Player::attack()
{
if(!_currAnim->inProgress())
{
delete _currAnim;
if(_prevDirection)//Précédente action vers la droite
{
_currAnim = _builder.attackRight(_pos);
}
else//Précédente action vers la gauche
{
_currAnim = _builder.attackLeft(_pos);
}
}
}
//Vérifie si un joueur entre en collision (Hitbox Active vs Active)
bool Player::collideA(const Player* p) const
{
for(SDL_Rect* box : p->aHitBox())
{
if(collideA(box)) //Les deux joueurs entre en collisions (active)
return true;
}
return false;
}
//Vérifie si une hitbox rentre en collision active
bool Player::collideA(const SDL_Rect* box) const
{
if(_currAnim->collideA(box))
return true;
else
return false;
}
//Vérifie si une hitbox rentre en collision passive
bool Player::collideP(const SDL_Rect* box) const
{
if(_currAnim->collideP(box))
return true;
else
return false;
}
//Verifie si le joueur touche un autre joueur (Hitbox Active vs Passive)
bool Player::hit(const Player* receiver) const
{
for(SDL_Rect* attack : aHitBox()) //On parcours toute les hitbox actives de l'attaquant
{
if(receiver->collideP(attack)) //Si l'attaquant est touché (ie Attaquant touche les hitbox passive du receveur)
{
return true;
}
}
return false;
}
//Fini une animation à un point donnée (Ref SDL)
void Player::holdPos(const pair<int,int>& pos)
{
_currAnim->holdPos(pos);
}
/*
void Player::checkAnim(const vector<SDL_Rect*> obstacles)
{
bool validAnim = true;
vector<SDL_Rect*> collisions;
for (int i = 0; i < 100; i++) //Limite à 100 essais
{
//Recherche de tout les obstacles en collision (si aucune collision, on sort)
for(SDL_Rect* o : obstacles)
{
if(_currAnim)
}
if(validAnim)
break;
//Création d'une animation valide (à priori)
}
if(!validAnim)//Aucune solution trouvée
{
cout<<"CheckAnim : Pas de solution trouvée"<<endl;
}
}
*/

64
src/GameEnv/Player.hpp Normal file
View file

@ -0,0 +1,64 @@
#ifndef PLAYER_HPP
#define PLAYER_HPP
//#include "../Drawable.hpp" //Inclus dans Animation
//#include "../Collidable.hpp" //Inclus dans Animation
//#include "../Animation/Animation.hpp" //Inclus dans animationbuilder
#include "../Animation/AnimationBuilder.hpp"
//Forward declaration IA
class Game;
//Repéresente un joueur
class Player: public Drawable, public Collidable
{
protected:
unsigned int _playerID; //Identifiant du joueur
static unsigned int nextPlayerID;
pair<int,int> _pos; //Position du personnage
Animation* _currAnim;//Animation courante
AnimationBuilder _builder;//Builder pour les animations
bool _prevDirection = true; //Indique la dernière direction prise (true = droite, false = gauche) (Peut manquer d'info, à améliorer au besoin)
bool _ia = false; //Indique si le joueur est controlée par l'ordinateur
public:
Player(const pair<int,int>& StartPos, SDL_Renderer *renderer);
virtual ~Player();
void stand(); //Reste en place
void stand(const pair<int,int>& pos); //Reste en place à une position donnée
void moveRight(); //Déplacement vers la droite (si possible)
void moveLeft(); //Déplacement vers la gauche (si possible)
void jump(); //Saut (si possible)
void crouch(); //Accroupis (si possible)
void fall(); //Chute
void attack(); //Attaque (si possible)
void nextAnim() { _pos=_currAnim->nextFrame();} //Defile la frame & récupère la position
bool collideA(const Player* p) const; //Vérifie si un joueur entre en collision (Hitbox Active vs Active)
bool collideA(const SDL_Rect* box) const; //Vérifie si une hitbox rentre en collision active
bool collideP(const SDL_Rect* box) const; //Vérifie si une hitbox rentre en collision passive
bool hit(const Player* receiver) const; //Verifie si le joueur touche un autre joueur (Hitbox Active vs Passive)
void holdPos(const pair<int,int>& pos); //Fini une animation à un point donnée (Ref SDL)
virtual void nextAction(const Game* g){} //IA : Demande au joueur d'effectuer une action
//Accesseurs
int id() const { return _playerID;}
const AnimationFrame* currFrame() const{ return _currAnim->getFrame();}
Sprite& sprite() { return _currAnim->sprite();}
const Sprite& sprite() const{ return _currAnim->sprite();}
const pair<int,int>& pos() const { return _pos;}
const vector<SDL_Rect*>& aHitBox() const { return _currAnim->getFrame()->aHitBox();}
const vector<SDL_Rect*>& pHitBox() const { return _currAnim->getFrame()->pHitBox();}
const bool isComputer() const { return _ia;}
/*
SDL_Texture *getTexture() const { return _currAnim.getTexture();}//On recupere la texture de l'objet dessinable
SDL_Rect *getRect() const { return _currAnim.getTexture();}//On recupere la zone ou dessiner l'objet dessinable
*/
//void checkAnim(const vector<SDL_Rect*> obstacles); //On verifie/modifie l'animation pour gerer les collisions
};
#endif

42
src/GameEnv/World.cpp Normal file
View file

@ -0,0 +1,42 @@
#include "../GameEnv/World.hpp"
World::World(const std::string& name, const Sprite& background, const std::vector<Obstacle*>& obsList) : _worldName(name)
{
_background = background;
for(Obstacle* o : obsList)
{
Obstacle* newObs = new Obstacle(*o);
_obsList.push_back(newObs);
}
// for(Obstacle* o : _obsList)
// {
// std::cout<<"World :"<<*o->box()<<std::endl;
// }
}
World::~World()
{
for(Obstacle* o : _obsList)
{
delete o;
}
}
// void World::setSprite(SDL_Renderer *renderer,std::string imgPath)
// {
// SDL_Rect* BackBox = createRect(0,0, SCREEN_WIDTH, SCREEN_HEIGHT);
// _background = Sprite(renderer,BackBox,imgPath);
// }
World& World::operator=(const World& w)
{
_worldName = w.name();
_background = w.sprite();
std::vector<Obstacle*> obsList = w.obstacles();
for(Obstacle* o : obsList)
{
Obstacle* newObs = new Obstacle(*o);
_obsList.push_back(newObs);
}
return *this;
}

39
src/GameEnv/World.hpp Normal file
View file

@ -0,0 +1,39 @@
#ifndef WORLD_HPP
#define WORLD_HPP
//#include <iostream>
#include <vector>
#include "../GameEnv/Obstacle.hpp"
//#include "../gui/Sprite.hpp"
#include "../GameParam.hpp"
//std::ostream& operator<<(std::ostream& os, const SDL_Rect& r); //Forward (Game)
//Représente un monde de jeu
class World : public Drawable
{
protected:
std::string _worldName; //Nom du monde
std::vector<Obstacle*> _obsList; //Liste des objets solides
Sprite _background; //Fond
public:
//World(){}
World(const std::string& name, const Sprite& background, const std::vector<Obstacle*>& obsList);
World(const World& w){ *this = w;}
~World();
//BOF BOF
//void addObs(const Obstacle& newObstacle) { return _obsList.push_back(new Obstacle(newObstacle));}
//void setSprite(SDL_Renderer *renderer,std::string imgPath); //Fuites memoires
//Accesseurs
const std::string& name() const { return _worldName;}
const std::vector<Obstacle*>& obstacles() const { return _obsList;}
Sprite& sprite(){ return _background;}
const Sprite& sprite() const{ return _background;}
World& operator=(const World& w);
};
#endif

View file

@ -0,0 +1,108 @@
#include "WorldBuilder.hpp"
//Chargement de toute les textures environement.
//Amélioration : ne charger les texture que une à une quand elles sont demandés
WorldBuilder::WorldBuilder(SDL_Renderer *renderer) : _renderer(renderer)
{
addTexture("red_square","images/red_square.png");
addTexture("skyBack","images/skyBackground.jpg");
addTexture("logo","images/Nidrobb.png");
addTexture("nuage","images/nuage.png");
}
WorldBuilder::~WorldBuilder()
{
for(auto & i : _texture) // map<>::iterator
{
SDL_DestroyTexture(i.second); //Destruction des textures
}
}
//Ajout d'une texture au dictionnaire
void WorldBuilder::addTexture(const string name, const string imgPath)
{
//Chargement d'une texture par defaut (objet noir)
SDL_Surface *tmpSurface = IMG_Load(imgPath.c_str());
//Verification de la non presence d'erreur lors du chargement
if(!tmpSurface)
std::cout << "WorldBuilder : Surface "<< name <<" non chargee. Erreur :" << SDL_GetError() << std::endl;
//Creation/Ajout de la texture a partir de la surface chargee
_texture [name]= SDL_CreateTextureFromSurface(_renderer, tmpSurface);
//Liberation de la memoire allouee pour la surface
SDL_FreeSurface(tmpSurface);
}
//Construit un obstacle
Obstacle* WorldBuilder::createObstacle(SDL_Texture * texture, const pair<int,int>& Pos, int width, int height) const
{
SDL_Rect *h = createRect(Pos.first,Pos.second,width,height); //ATTENTION : sprite supprime les rect
Sprite s(h,texture);
SDL_Rect *h2 = createRect(Pos.first,Pos.second,width,height);
Obstacle* res = new Obstacle(s,h2);
//cout <<"Create Obs: "<<*res->box()<<endl;
return res;
}
//Construit la map aérienne
World* WorldBuilder::sky()
{
//Background
SDL_Rect* worldArea = createRect(0,0, SCREEN_WIDTH, SCREEN_HEIGHT);
Sprite worldSprite(worldArea,_texture["skyBack"]);
//Environement
vector<Obstacle*> obsList;
obsList.push_back(createObstacle(_texture["nuage"], make_pair(-WALL_THICKNESS+10,-10), WALL_THICKNESS,SCREEN_HEIGHT+10)); //Mur gauche
obsList.push_back(createObstacle(_texture["nuage"], make_pair(SCREEN_WIDTH,-90), WALL_THICKNESS,SCREEN_HEIGHT)); //Mur droit
obsList.push_back(createObstacle(_texture["nuage"], make_pair(-90,-90),SCREEN_WIDTH, WALL_THICKNESS)); //Plafond
obsList.push_back(createObstacle(_texture["nuage"], make_pair(-50,SCREEN_HEIGHT-WALL_THICKNESS/2),SCREEN_WIDTH+100, WALL_THICKNESS)); //Sol
obsList.push_back(createObstacle(_texture["logo"], make_pair(SCREEN_WIDTH/2-200, 0), 400, 100)); //Logo
//Plateformes
obsList.push_back(createObstacle(_texture["nuage"], make_pair(200,250),300,60));
obsList.push_back(createObstacle(_texture["nuage"], make_pair(SCREEN_WIDTH-500,250),300,60));
obsList.push_back(createObstacle(_texture["nuage"], make_pair(50,SCREEN_HEIGHT-200),200,60));
obsList.push_back(createObstacle(_texture["nuage"], make_pair(SCREEN_WIDTH-400,SCREEN_HEIGHT-200),200,60));
obsList.push_back(createObstacle(_texture["nuage"], make_pair(SCREEN_WIDTH/2-200,SCREEN_HEIGHT-300),400,100));
// for(Obstacle* o : obsList)
// {
// cout<<"Builder :"<<*o->box()<<endl;
// }
World* res = new World("Sky World",worldSprite, obsList);
// for(Obstacle* o : res->obstacles())
// {
// cout<<"Builder :"<<*o->box()<<endl;
// }
return res;
}
//Construit la map de test de collision
World* WorldBuilder::collisionTest()
{
//Background
SDL_Rect* worldArea = createRect(0,0, SCREEN_WIDTH, SCREEN_HEIGHT);
Sprite worldSprite(worldArea,_texture["skyBack"]);
//Environement
vector<Obstacle*> obsList;
obsList.push_back(createObstacle(_texture["nuage"], make_pair(0,450),700,40)); //Sol
obsList.push_back(createObstacle(_texture["logo"], make_pair(SCREEN_WIDTH/2-100, 0), 200, 100)); //Logo
obsList.push_back(createObstacle(_texture["red_square"], make_pair(300,350),100,101)); //Obstacle 1
obsList.push_back(createObstacle(_texture["red_square"], make_pair(200,400),100,101)); //Obstacle 2
obsList.push_back(createObstacle(_texture["red_square"], make_pair(350,250),100,101)); //Obstacle 3
// for(Obstacle* o : obsList)
// {
// cout<<"Builder :"<<*o->box()<<endl;
// }
World* res = new World("Sky World",worldSprite, obsList);
// for(Obstacle* o : res->obstacles())
// {
// cout<<"Builder :"<<*o->box()<<endl;
// }
return res;
}

View file

@ -0,0 +1,29 @@
#ifndef WORLDBUILDER_HPP
#define WORLDBUILDER_HPP
#include <map>
#include "../GameEnv/World.hpp"
using namespace std;
//Usine à monde
//Possiblement transformer en singleton
class WorldBuilder
{
protected :
SDL_Renderer *_renderer; //Outils de rendu lié à display (Détruit dans display)
map<string,SDL_Texture *> _texture; //Dictionnaire des textures
public:
WorldBuilder(SDL_Renderer *renderer);
~WorldBuilder();
void addTexture(const string name, const string imgPath); //Ajout d'une texture au dictionnaire
Obstacle* createObstacle(SDL_Texture * texture, const pair<int,int>& Pos, int width, int height) const; //Construit un obstacle
//Pas de const à cause de SDL_Texture...
World* sky(); //Construit la map aérienne
World* collisionTest(); //Construit la map de test de collision
};
#endif

30
src/GameParam.hpp Normal file
View file

@ -0,0 +1,30 @@
#ifndef GAMEPARAM_HPP
#define GAMEPARAM_HPP
//Toujours tout recompiler à la modification des paramètres
//Paramètre Affichage
#define MIN_LOOP_TIME 17 //60 FPS
//#define MIN_LOOP_TIME 33 //30 FPS
#define SCREEN_WIDTH 1280
#define SCREEN_HEIGHT 720
#define SCREEN_BPP 32
//Paramètre environement
#define WALL_THICKNESS 40
#define P1_START_POSX 50
#define P1_START_POSY 250
#define P2_START_POSX SCREEN_WIDTH-100
#define P2_START_POSY 250
//Paramètre joueur
#define PLAYER_HEIGHT 100
#define PLAYER_WIDTH 50
#define PLAYER_JUMP_HEIGHT 150
#define PLAYER_MOVE_DISTANCE 40
#define PLAYER_FALL_SPEED 20
#define PLAYER_KNOCKBACK 50
#endif

38
src/Makefile Normal file
View file

@ -0,0 +1,38 @@
# options de compilation
CC =g++ -std=c++11
CCFLAGS = -Wall -g #-msse3 #-msse2
LDFLAGS = -lboost_unit_test_framework -lSDL2 -lSDL2_image #-lSDL_mixer
# fichiers du projet
MAIN = main.cpp
SRC = Toolbox.cpp Command/InputMap.cpp gui/display.cpp gui/sprite.cpp Animation/Animation.cpp Animation/AnimationFrame.cpp Animation/AnimationBuilder.cpp GameEnv/Game.cpp GameEnv/WorldBuilder.cpp GameEnv/World.cpp GameEnv/Obstacle.cpp GameEnv/Player.cpp
OBJ = $(SRC:.cpp=.o)
EXEC = Nidrobb
TESTSRC = Unitests/AnimationTest.cpp #Unitests/WorldTest.cpp #Unitests/ObstacleTest.cpp #Unitests/InputMapTest.cpp #Unitests/AnimationTest.cpp #Unitests/AnimationFrameTest.cpp #Unitests/ToolboxTest.cpp #Unitests/SpriteTest.cpp
TESTOBJ = $(TESTSRC:.cpp=.o)
# règle initiale
all: $(EXEC) #clean
# dépendance des .hpp
%.o: %.hpp
# règles de compilation
%.o: %.cpp
$(CC) $(CCFLAGS) -o $@ -c $<
# règles d'édition de liens
$(EXEC): $(MAIN:.cpp=.o) $(OBJ)
$(CC) -o $@ $^ $(LDFLAGS)
# règles supplémentaires
clean:
rm -rf $(MAIN:.cpp=.o) $(OBJ) $(TESTOBJ)
rmproper:
rm -rf $(EXEC) Unitest
Unitest: $(OBJ) $(TESTOBJ)
$(CC) -o $@ $^ $(LDFLAGS) && ./$@ --log_level=test_suite

BIN
src/Nidrobb Normal file

Binary file not shown.

66
src/Toolbox.cpp Normal file
View file

@ -0,0 +1,66 @@
#include "Toolbox.hpp"
//Retourne le centre géométrique d'un objet à partir
//Pair<int,int> centerSDLtoObject()
SDL_Rect *createRect(int x, int y, int w, int h)
{
//Attention il faut desallouer le SDL_Rect en dehors de la fonction
SDL_Rect *r = new SDL_Rect;
r->x = x;
r->y = y;
r->w = w;
r->h = h;
return r;
}
std::ostream& operator<<(std::ostream& os, const SDL_Rect& r)
{
os<<r.x<<"/"<<r.y<<" - "<<r.w<<"/"<<r.h;
return os;
}
// bool checkCollision(const SDL_Rect* a, const SDL_Rect* b )
// {
// //The sides of the rectangles
// int leftA, leftB;
// int rightA, rightB;
// int topA, topB;
// int bottomA, bottomB;
// //Calculate the sides of rect A
// leftA = a->x;
// rightA = a->x + a->w;
// topA = a->y;
// bottomA = a->y + a->h;
// //Calculate the sides of rect B
// leftB = b->x;
// rightB = b->x + b->w;
// topB = b->y;
// bottomB = b->y + b->h;
// //If any of the sides from A are outside of B
// if( bottomA <= topB )
// {
// return false;
// }
// if( topA >= bottomB )
// {
// return false;
// }
// if( rightA <= leftB )
// {
// return false;
// }
// if( leftA >= rightB )
// {
// return false;
// }
// //If none of the sides from A are outside B
// return true;
// }

11
src/Toolbox.hpp Normal file
View file

@ -0,0 +1,11 @@
#ifndef TOOLBOX_HPP
#define TOOLBOX_HPP
#include <iostream>
#include <SDL2/SDL.h>
SDL_Rect *createRect(int x, int y, int w, int h);
std::ostream& operator<<(std::ostream& os, const SDL_Rect& r);
//bool checkCollision(const SDL_Rect* a, const SDL_Rect* b );
#endif

BIN
src/Unitest Normal file

Binary file not shown.

View file

@ -0,0 +1,187 @@
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE AnimationFrameTest
#include <boost/test/unit_test.hpp>
#include "../Animation/AnimationFrame.hpp"
//Fixture
struct F
{
F()
{
BOOST_TEST_MESSAGE( "setup fixture" );
window = SDL_CreateWindow("Test",SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 10, 10, SDL_WINDOW_SHOWN);
BOOST_CHECK(window != nullptr);
renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );
BOOST_CHECK(renderer != nullptr);
//Chargement d'une texture par defaut (objet noir)
tmpSurface = IMG_Load("images/black.png");
//Verification de la non presence d'erreur lors du chargement
BOOST_CHECK(tmpSurface != nullptr);
//Creation de la texture du sprite a partir de la surface chargee
texture = SDL_CreateTextureFromSurface(renderer, tmpSurface);
//Liberation de la memoire allouee pour la surface
SDL_FreeSurface(tmpSurface);
}
~F()
{
BOOST_TEST_MESSAGE( "teardown fixture" );
SDL_DestroyTexture(texture);
SDL_DestroyRenderer( renderer );
SDL_DestroyWindow( window );
}
SDL_Window* window = nullptr;
SDL_Renderer* renderer = nullptr;
SDL_Surface *tmpSurface = nullptr;
SDL_Texture* texture = nullptr;
};
BOOST_AUTO_TEST_SUITE (Constructeurs)
BOOST_FIXTURE_TEST_CASE (Constructeur_Full, F)
{
int x = 10, y=20, w = 30, h=40;
Sprite s(createRect(x,y,w,h), texture);
AnimationFrame frame(s, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x,y));
BOOST_REQUIRE(frame.sprite()==s);
BOOST_REQUIRE(frame.pHitBox().size()==0);
BOOST_REQUIRE(frame.aHitBox().size()==0);
BOOST_REQUIRE(frame.center().first==10);
BOOST_REQUIRE(frame.center().second==20);
}
BOOST_FIXTURE_TEST_CASE (Constructeur_Copie, F)
{
int x = 10, y=20, w = 30, h=40;
Sprite s(createRect(x,y,w,h), texture);
AnimationFrame frame(s, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x,y));
AnimationFrame copy = frame;
BOOST_REQUIRE(copy.sprite()==frame.sprite());
BOOST_REQUIRE(copy.pHitBox().size()==frame.pHitBox().size());
BOOST_REQUIRE(copy.aHitBox().size()==frame.aHitBox().size());
BOOST_REQUIRE(copy.center().first==frame.center().first);
BOOST_REQUIRE(copy.center().second==frame.center().second);
}
BOOST_AUTO_TEST_SUITE_END( )
BOOST_AUTO_TEST_SUITE (Collisions)
BOOST_FIXTURE_TEST_CASE (CollideA,F)
{
int x = 10, y=20, w = 30, h=40;
int xt=0,yt=0,wt=2,ht=2;
SDL_Rect* test1 = createRect(x,y,w,h);
SDL_Rect* test2 = createRect(xt,yt,wt,ht);
Sprite s(createRect(x,y,w,h), texture);
vector<SDL_Rect*> hitboxs;
hitboxs.push_back(createRect(x,y,w,h));
AnimationFrame frame(s, vector<SDL_Rect*>(), hitboxs, make_pair(x,y));
BOOST_REQUIRE(frame.collideA(test1));
BOOST_REQUIRE(!frame.collideA(test2));
delete test1;
delete test2;
}
BOOST_AUTO_TEST_SUITE_END( )
BOOST_FIXTURE_TEST_CASE(Translate,F)
{
int x = 10, y=20, w = 30, h=40;
Sprite s(createRect(x,y,w,h), texture);
AnimationFrame frame(s, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x,y));
frame.addPHitbox(createRect(x,y,w,h));
frame.addAHitbox(createRect(x,y,w,h));
frame.translate(make_pair(0,0));
BOOST_REQUIRE(frame.pHitBox()[0]->x == 0);
BOOST_REQUIRE(frame.pHitBox()[0]->y == 0);
BOOST_REQUIRE(frame.aHitBox()[0]->x == 0);
BOOST_REQUIRE(frame.aHitBox()[0]->y == 0);
}
BOOST_AUTO_TEST_SUITE (Accesseurs)
BOOST_FIXTURE_TEST_CASE(AddPHitbox, F)
{
int x = 10, y=20, w = 30, h=40;
Sprite s(createRect(x,y,w,h), texture);
AnimationFrame frame(s, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x,y));
frame.addPHitbox(createRect(x,y,w,h));
SDL_Rect* test = createRect(x,y,w,h);
BOOST_CHECK(frame.pHitBox().size()==1);
BOOST_CHECK(SDL_RectEquals(frame.pHitBox()[0],test)== SDL_TRUE);
delete test;
}
BOOST_FIXTURE_TEST_CASE(AddAHitbox, F)
{
int x = 10, y=20, w = 30, h=40;
Sprite s(createRect(x,y,w,h), texture);
AnimationFrame frame(s, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x,y));
frame.addAHitbox(createRect(x,y,w,h));
SDL_Rect* test = createRect(x,y,w,h);
BOOST_CHECK(frame.aHitBox().size()==1);
BOOST_CHECK(SDL_RectEquals(frame.aHitBox()[0],test)== SDL_TRUE);
delete test;
}
BOOST_AUTO_TEST_SUITE_END( )
BOOST_AUTO_TEST_SUITE (Operateurs)
BOOST_FIXTURE_TEST_CASE(assign,F)
{
int x = 10, y=20, w = 30, h=40;
Sprite s(createRect(x,y,w,h), texture);
AnimationFrame frame(s, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x,y));
AnimationFrame copy = frame;
BOOST_REQUIRE(frame.center()==copy.center());
BOOST_REQUIRE(frame.sprite()==copy.sprite());
BOOST_REQUIRE(frame.pHitBox().size()==copy.pHitBox().size());
BOOST_REQUIRE(frame.aHitBox().size()==copy.aHitBox().size());
for(unsigned int i=0;i<copy.pHitBox().size();i++)
BOOST_REQUIRE(SDL_RectEquals(frame.pHitBox()[i],copy.pHitBox()[i])==SDL_FALSE);
for(unsigned int i=0;i<copy.aHitBox().size();i++)
BOOST_REQUIRE(SDL_RectEquals(frame.aHitBox()[i],copy.aHitBox()[i]) == SDL_FALSE);
}
BOOST_FIXTURE_TEST_CASE(equal,F)
{
int x = 10, y=20, w = 30, h=40;
Sprite s(createRect(x,y,w,h), texture);
AnimationFrame frame(s, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x,y));
AnimationFrame copy = frame;
BOOST_CHECK(copy==frame);
}
BOOST_AUTO_TEST_SUITE_END( )

Binary file not shown.

View file

@ -0,0 +1,237 @@
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE AnimationTest
#include <boost/test/unit_test.hpp>
#include "../Animation/Animation.hpp"
//Fixture
struct F
{
F()
{
BOOST_TEST_MESSAGE( "setup fixture" );
window = SDL_CreateWindow("Test",SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 10, 10, SDL_WINDOW_SHOWN);
BOOST_CHECK(window != nullptr);
renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );
BOOST_CHECK(renderer != nullptr);
//Chargement d'une texture par defaut (objet noir)
tmpSurface = IMG_Load("images/black.png");
//Verification de la non presence d'erreur lors du chargement
BOOST_CHECK(tmpSurface != nullptr);
//Creation de la texture du sprite a partir de la surface chargee
texture = SDL_CreateTextureFromSurface(renderer, tmpSurface);
//Liberation de la memoire allouee pour la surface
SDL_FreeSurface(tmpSurface);
x = 10; y=20; w = 30; h=40;
}
~F()
{
// for(AnimationFrame* a : vframe)
// delete a;
BOOST_TEST_MESSAGE( "teardown fixture" );
SDL_DestroyTexture(texture);
SDL_DestroyRenderer( renderer );
SDL_DestroyWindow( window );
}
SDL_Window* window = nullptr;
SDL_Renderer* renderer = nullptr;
SDL_Surface *tmpSurface = nullptr;
SDL_Texture* texture = nullptr;
int x, y, w , h;
};
BOOST_AUTO_TEST_SUITE (Constructeurs)
BOOST_FIXTURE_TEST_CASE (Constructeur_Full, F)
{
string name = "test";
Sprite s1(createRect(x,y,w,h), texture);
Sprite s2(createRect(x+10,y+10,w,h), texture);
vector<AnimationFrame*> vframe;
vframe.push_back(new AnimationFrame(s1, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x,y)));
vframe.push_back(new AnimationFrame(s2, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x+10,y+10)));
Animation anim(name, vframe);
BOOST_REQUIRE(anim.name()==name);
BOOST_REQUIRE(anim.progress()==1);
BOOST_REQUIRE(anim.duration()==vframe.size());
for(unsigned int i=0; i<vframe.size(); i++)
{
//std::cout<<"Frame : "<<i<<"/"<<vframe.size()<<std::endl;
BOOST_REQUIRE(anim.getFrame(i)==vframe[i]);
}
}
BOOST_FIXTURE_TEST_CASE (Constructeur_Copie, F)
{
string name = "test";
Sprite s1(createRect(x,y,w,h), texture);
Sprite s2(createRect(x+10,y+10,w,h), texture);
vector<AnimationFrame*> vframe;
vframe.push_back(new AnimationFrame(s1, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x,y)));
vframe.push_back(new AnimationFrame(s2, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x+10,y+10)));
Animation anim(name, vframe);
Animation copy(anim);
BOOST_REQUIRE(copy.name()==anim.name());
BOOST_REQUIRE(copy.progress()==anim.progress());
BOOST_REQUIRE(copy.duration()==anim.duration());
for(unsigned int i=0; i<anim.duration(); i++)
{
BOOST_REQUIRE(*copy.getFrame(i)==*anim.getFrame(i));
}
}
BOOST_AUTO_TEST_SUITE_END( )
BOOST_AUTO_TEST_SUITE (Frame_Access)
BOOST_FIXTURE_TEST_CASE (InProgress,F)
{
string name = "test";
Sprite s1(createRect(x,y,w,h), texture);
Sprite s2(createRect(x+10,y+10,w,h), texture);
vector<AnimationFrame*> vframe;
vframe.push_back(new AnimationFrame(s1, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x,y)));
vframe.push_back(new AnimationFrame(s2, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x+10,y+10)));
vframe.push_back(new AnimationFrame(s2, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x+10,y+10)));
Animation anim(name, vframe);
BOOST_REQUIRE(anim.inProgress()==true);
anim.nextFrame();
BOOST_REQUIRE(anim.inProgress()==true);
anim.nextFrame();
BOOST_REQUIRE(anim.inProgress()==false); //On a atteint la dernière frame
anim.nextFrame();
BOOST_REQUIRE(anim.inProgress()==false);
}
BOOST_FIXTURE_TEST_CASE (NextFrame,F)
{
string name = "test";
Sprite s1(createRect(x,y,w,h), texture);
Sprite s2(createRect(x+10,y+10,w,h), texture);
vector<AnimationFrame*> vframe;
vframe.push_back(new AnimationFrame(s1, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x,y)));
vframe.push_back(new AnimationFrame(s2, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x+10,y+10)));
Animation anim(name, vframe);
BOOST_CHECK(anim.progress()==1);
pair<int,int> pos = anim.nextFrame();
BOOST_REQUIRE(anim.progress()==2);
BOOST_REQUIRE(pos == make_pair(x,y));
//Empeche dépassement
pos = anim.nextFrame();
BOOST_REQUIRE(pos == make_pair(x+10,y+10));
BOOST_REQUIRE(anim.progress()==2);
}
BOOST_FIXTURE_TEST_CASE (HoldPos,F)
{
string name = "test";
Sprite s1(createRect(x,y,w,h), texture);
Sprite s2(createRect(x+10,y+10,w,h), texture);
vector<AnimationFrame*> vframe;
vframe.push_back(new AnimationFrame(s1, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x,y)));
vframe.push_back(new AnimationFrame(s2, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x+10,y+10)));
Animation anim(name, vframe);
pair<int,int> hold = make_pair(100, 200);
anim.holdPos(hold);
BOOST_CHECK(anim.progress()==1); //On verfie qu'on est tjrs au début de l'animation
pair<int,int> pos = anim.nextFrame(); //On récupère la position ( & passe à la prochaine frame)
BOOST_REQUIRE(pos == hold);
BOOST_CHECK(anim.progress()==2);
pos = anim.nextFrame(); //On récupère la position ( & passe à la prochaine frame)
BOOST_REQUIRE(pos == hold);
}
BOOST_AUTO_TEST_SUITE_END( )
BOOST_AUTO_TEST_SUITE (Collisions)
BOOST_FIXTURE_TEST_CASE (CollideA,F)
{
string name = "test";
Sprite s1(createRect(x,y,w,h), texture);
vector<SDL_Rect*> hitboxs;
hitboxs.push_back(createRect(x,y,w,h));
vector<AnimationFrame*> vframe;
vframe.push_back(new AnimationFrame(s1, vector<SDL_Rect*>(), hitboxs, make_pair(x,y)));
Animation anim(name, vframe);
int xt=x,yt=y,wt=w-10,ht=h-10;
int xt2=x+w,yt2=y,wt2=w,ht2=h;
SDL_Rect* test = createRect(xt,yt,wt,ht); //Box incluse
SDL_Rect* test2 = createRect(xt2,yt2,wt2,ht2); //Box externe
BOOST_REQUIRE(anim.collideA(test)==true);
BOOST_REQUIRE(anim.collideA(test2)==false);
}
BOOST_FIXTURE_TEST_CASE (CollideP,F)
{
string name = "test";
Sprite s1(createRect(x,y,w,h), texture);
vector<SDL_Rect*> hitboxs;
hitboxs.push_back(createRect(x,y,w,h));
vector<AnimationFrame*> vframe;
vframe.push_back(new AnimationFrame(s1, hitboxs, vector<SDL_Rect*>(), make_pair(x,y)));
Animation anim(name, vframe);
int xt=x,yt=y,wt=w-10,ht=h-10;
int xt2=x+w,yt2=y,wt2=w,ht2=h;
SDL_Rect* test = createRect(xt,yt,wt,ht); //Box incluse
SDL_Rect* test2 = createRect(xt2,yt2,wt2,ht2); //Box externe
BOOST_REQUIRE(anim.collideP(test)==true);
BOOST_REQUIRE(anim.collideP(test2)==false);
}
BOOST_AUTO_TEST_SUITE_END( )
BOOST_AUTO_TEST_SUITE (Operateurs)
BOOST_FIXTURE_TEST_CASE(assign,F)
{
string name = "test";
Sprite s1(createRect(x,y,w,h), texture);
Sprite s2(createRect(x+10,y+10,w,h), texture);
vector<AnimationFrame*> vframe;
vframe.push_back(new AnimationFrame(s1, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x,y)));
vframe.push_back(new AnimationFrame(s2, vector<SDL_Rect*>(), vector<SDL_Rect*>(), make_pair(x+10,y+10)));
Animation anim(name, vframe);
Animation copy = anim;
BOOST_REQUIRE(copy.name()==anim.name());
BOOST_REQUIRE(copy.progress()==anim.progress());
BOOST_REQUIRE(copy.duration()==anim.duration());
for(unsigned int i=0; i<anim.duration(); i++)
{
BOOST_REQUIRE(*copy.getFrame(i)==*anim.getFrame(i));
}
}
BOOST_AUTO_TEST_SUITE_END( )

Binary file not shown.

View file

@ -0,0 +1,46 @@
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE InputMapTest
#include <boost/test/unit_test.hpp>
#include "../Command/InputMap.hpp"
BOOST_AUTO_TEST_SUITE (Constructeurs)
//A voir quel commande sont ajouté au final au constructeur
BOOST_AUTO_TEST_CASE (Default)
{
InputMap map;
BOOST_CHECK(map.GMap().size()>0);
BOOST_CHECK(map.P1Map().size()>0);
BOOST_CHECK(map.P2Map().size()>0);
}
BOOST_AUTO_TEST_SUITE_END( )
BOOST_AUTO_TEST_SUITE(Operators)
BOOST_AUTO_TEST_CASE(access)
{
InputMap map;
Command* test = map(SDLK_ESCAPE);
BOOST_CHECK(test->target()==0);
BOOST_CHECK(test->name()=="ExitCommand");
test = map(SDLK_q);
BOOST_CHECK(test->target()==1);
BOOST_CHECK(test->name()=="LeftCommand");
test = map(SDLK_KP_0);
BOOST_CHECK(test->target()==2);
BOOST_CHECK(test->name()=="AttackCommand");
}
BOOST_AUTO_TEST_CASE(print)
{
InputMap map;
BOOST_CHECK(map.GMap().size()>0);
BOOST_CHECK(map.P1Map().size()>0);
BOOST_CHECK(map.P2Map().size()>0);
std::cout<<"InputMap : "<<std::endl<<map<<std::endl;
}
BOOST_AUTO_TEST_SUITE_END()

BIN
src/Unitests/InputMapTest.o Normal file

Binary file not shown.

View file

@ -0,0 +1,125 @@
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE ObstacleTest
#include <boost/test/unit_test.hpp>
#include "../GameEnv/Obstacle.hpp"
//http://www.linuxembedded.fr/2015/02/introduction-a-boost-test-library-unit-test-framework/
//Fixture
struct F
{
F()
{
BOOST_TEST_MESSAGE( "setup fixture" );
window = SDL_CreateWindow("Test",SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 10, 10, SDL_WINDOW_SHOWN);
BOOST_CHECK(window != nullptr);
renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );
BOOST_CHECK(renderer != nullptr);
//Chargement d'une texture par defaut (objet noir)
tmpSurface = IMG_Load("images/black.png");
//Verification de la non presence d'erreur lors du chargement
BOOST_CHECK(tmpSurface != nullptr);
//Creation de la texture du sprite a partir de la surface chargee
texture = SDL_CreateTextureFromSurface(renderer, tmpSurface);
//Liberation de la memoire allouee pour la surface
SDL_FreeSurface(tmpSurface);
}
~F()
{
BOOST_TEST_MESSAGE( "teardown fixture" );
SDL_DestroyTexture(texture);
SDL_DestroyRenderer( renderer );
SDL_DestroyWindow( window );
}
SDL_Window* window = nullptr;
SDL_Renderer* renderer = nullptr;
SDL_Surface *tmpSurface = nullptr;
SDL_Texture* texture = nullptr;
int x = 10, y=20, w = 30, h=40;
};
BOOST_AUTO_TEST_SUITE (Constructeurs)
BOOST_FIXTURE_TEST_CASE (Default, F)
{
Sprite s(createRect(x,y,w,h), texture);
Obstacle o(s, createRect(x,y,w,h));
SDL_Rect* test = createRect(x,y,w,h);
BOOST_REQUIRE(o.center()==std::make_pair(x+w/2,y+h/2));
BOOST_REQUIRE(o.sprite()==s);
BOOST_REQUIRE(SDL_RectEquals(o.box(),test)==SDL_TRUE);
}
BOOST_FIXTURE_TEST_CASE (Constructeur_copie, F)
{
Sprite s(createRect(x,y,w,h), texture);
Obstacle o(s, createRect(x,y,w,h));
Obstacle copy(o);
BOOST_REQUIRE(o.center()==copy.center());
BOOST_REQUIRE(o.sprite()==copy.sprite());
BOOST_REQUIRE(SDL_RectEquals(o.box(),copy.box())==SDL_TRUE);
}
BOOST_AUTO_TEST_SUITE_END( )
BOOST_AUTO_TEST_SUITE(Collisions)
BOOST_FIXTURE_TEST_CASE(CollideA, F)
{
Sprite s(createRect(x,y,w,h), texture);
Obstacle o(s, createRect(x,y,w,h));
SDL_Rect* test = createRect(x,y,w,h);
BOOST_REQUIRE(o.collideA(test)==false); //Obstacle passif
delete test;
}
BOOST_FIXTURE_TEST_CASE(CollideP, F)
{
Sprite s(createRect(x,y,w,h), texture);
Obstacle o(s, createRect(x,y,w,h));
SDL_Rect* test = createRect(x,y,w,h);
SDL_Rect* test2 = createRect(x+w,y,w,h);
BOOST_REQUIRE(o.collideP(test)==true);
BOOST_REQUIRE(o.collideP(test2)==false);
delete test;
delete test2;
}
BOOST_AUTO_TEST_SUITE_END( )
BOOST_AUTO_TEST_SUITE(Operators)
BOOST_FIXTURE_TEST_CASE(assign, F)
{
Sprite s(createRect(x,y,w,h), texture);
Obstacle o(s, createRect(x,y,w,h));
Obstacle copy = o;
BOOST_REQUIRE(o.center()==copy.center());
BOOST_REQUIRE(o.sprite()==copy.sprite());
BOOST_REQUIRE(SDL_RectEquals(o.box(),copy.box())==SDL_TRUE);
}
BOOST_FIXTURE_TEST_CASE(equal, F)
{
Sprite s(createRect(x,y,w,h), texture);
Obstacle o(s, createRect(x,y,w,h));
Obstacle copy = o;
BOOST_REQUIRE(o==copy);
}
BOOST_AUTO_TEST_SUITE_END()

BIN
src/Unitests/ObstacleTest.o Normal file

Binary file not shown.

123
src/Unitests/SpriteTest.cpp Normal file
View file

@ -0,0 +1,123 @@
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE SpriteTest
#include <boost/test/unit_test.hpp>
#include "../gui/sprite.hpp"
//http://www.linuxembedded.fr/2015/02/introduction-a-boost-test-library-unit-test-framework/
//Fixture
struct F
{
F()
{
BOOST_TEST_MESSAGE( "setup fixture" );
window = SDL_CreateWindow("Test",SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 10, 10, SDL_WINDOW_SHOWN);
BOOST_CHECK(window != nullptr);
renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );
BOOST_CHECK(renderer != nullptr);
//Chargement d'une texture par defaut (objet noir)
tmpSurface = IMG_Load("images/black.png");
//Verification de la non presence d'erreur lors du chargement
BOOST_CHECK(tmpSurface != nullptr);
//Creation de la texture du sprite a partir de la surface chargee
texture = SDL_CreateTextureFromSurface(renderer, tmpSurface);
//Liberation de la memoire allouee pour la surface
SDL_FreeSurface(tmpSurface);
}
~F()
{
BOOST_TEST_MESSAGE( "teardown fixture" );
SDL_DestroyTexture(texture);
SDL_DestroyRenderer( renderer );
SDL_DestroyWindow( window );
}
SDL_Window* window = nullptr;
SDL_Renderer* renderer = nullptr;
SDL_Surface *tmpSurface = nullptr;
SDL_Texture* texture = nullptr;
};
BOOST_AUTO_TEST_SUITE (Constructeurs)
BOOST_AUTO_TEST_CASE (Default)
{
Sprite s;
BOOST_CHECK(s.getTexture() == nullptr); // test basique
BOOST_CHECK(s.getRect() == nullptr);
}
BOOST_FIXTURE_TEST_CASE (Constructeur_rect_texture, F)
{
int x = 10, y=20, w = 30, h=40;
Sprite s(createRect(x,y,w,h), texture);
BOOST_REQUIRE(s.getTexture() != nullptr);
SDL_Rect* r = s.getRect();
BOOST_REQUIRE(r != nullptr);
BOOST_REQUIRE(r->x==x);
BOOST_REQUIRE(r->y==y);
BOOST_REQUIRE(r->w==w);
BOOST_REQUIRE(r->h==h);
}
BOOST_FIXTURE_TEST_CASE (Constructeur_copie, F)
{
int x = 10, y=20, w = 30, h=40;
Sprite s(createRect(x,y,w,h), texture);
Sprite copy(s);
BOOST_REQUIRE(copy.getTexture() == s.getTexture()); //Pas de création de nouvelles textures
SDL_Rect* r1 = s.getRect();
SDL_Rect* r2 = copy.getRect();
BOOST_REQUIRE(r2 != nullptr);
BOOST_REQUIRE(r1->x==r2->x);
BOOST_REQUIRE(r1->y==r2->y);
BOOST_REQUIRE(r1->w==r2->w);
BOOST_REQUIRE(r1->h==r2->h);
}
BOOST_AUTO_TEST_SUITE_END( )
BOOST_AUTO_TEST_SUITE(Operators)
BOOST_FIXTURE_TEST_CASE(assign, F)
{
int x = 10, y=20, w = 30, h=40;
Sprite s(createRect(x,y,w,h), texture);
Sprite copy;
copy=s;
BOOST_REQUIRE(copy.getTexture() == s.getTexture()); //Pas de création de nouvelles textures
SDL_Rect* r1 = s.getRect();
SDL_Rect* r2 = copy.getRect();
BOOST_REQUIRE(r2 != nullptr);
BOOST_REQUIRE(r1->x==r2->x);
BOOST_REQUIRE(r1->y==r2->y);
BOOST_REQUIRE(r1->w==r2->w);
BOOST_REQUIRE(r1->h==r2->h);
}
BOOST_FIXTURE_TEST_CASE(equal, F)
{
int x = 10, y=20, w = 30, h=40;
Sprite s(createRect(x,y,w,h), texture);
Sprite copy = s;
BOOST_CHECK(s==copy);
}
BOOST_AUTO_TEST_SUITE_END()

View file

@ -0,0 +1,66 @@
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE ToolboxTest
#include <boost/test/unit_test.hpp>
#include "../Toolbox.hpp"
BOOST_AUTO_TEST_SUITE (CreateRect)
BOOST_AUTO_TEST_CASE (Positive)
{
int x = 10, y=20, w = 30, h=40;
SDL_Rect* r = createRect(x,y,w,h);
BOOST_REQUIRE(r != nullptr); //Bloquant
BOOST_REQUIRE(r->x==x);
BOOST_REQUIRE(r->y==y);
BOOST_REQUIRE(r->w==w);
BOOST_REQUIRE(r->h==h);
delete r;
}
BOOST_AUTO_TEST_CASE (Nul)
{
int x = 0, y=0, w = 0, h=0;
SDL_Rect* r = createRect(x,y,w,h);
BOOST_REQUIRE(r != nullptr);
BOOST_REQUIRE(r->x==x);
BOOST_REQUIRE(r->y==y);
BOOST_REQUIRE(r->w==w);
BOOST_REQUIRE(r->h==h);
delete r;
}
BOOST_AUTO_TEST_CASE (Negative)
{
int x = -10, y=-20, w = -30, h=-40;
SDL_Rect* r = createRect(x,y,w,h);
BOOST_REQUIRE(r != nullptr);
BOOST_REQUIRE(r->x==x);
BOOST_REQUIRE(r->y==y);
BOOST_CHECK(r->w>=0); //Devrait pas autoriser w, h <0
BOOST_CHECK(r->h>=0); //Non bloquant
delete r;
}
BOOST_AUTO_TEST_SUITE_END( )
BOOST_AUTO_TEST_SUITE (OperatorPrint)
BOOST_AUTO_TEST_CASE (SDLRect)
{
int x = 10, y=20, w = 30, h=40;
SDL_Rect* r = createRect(x,y,w,h);
BOOST_REQUIRE(r != nullptr);
std::cout<<"Rect : "<<x<<"/"<<y<<" - "<<w<<"/"<<h<<" = "<<*r<<std::endl;
delete r;
}
BOOST_AUTO_TEST_SUITE_END( )

109
src/Unitests/WorldTest.cpp Normal file
View file

@ -0,0 +1,109 @@
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE WorldTest
#include <boost/test/unit_test.hpp>
#include "../GameEnv/World.hpp"
//http://www.linuxembedded.fr/2015/02/introduction-a-boost-test-library-unit-test-framework/
//Fixture
struct F
{
F()
{
BOOST_TEST_MESSAGE( "setup fixture" );
window = SDL_CreateWindow("Test",SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 10, 10, SDL_WINDOW_SHOWN);
BOOST_CHECK(window != nullptr);
renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );
BOOST_CHECK(renderer != nullptr);
//Chargement d'une texture par defaut (objet noir)
tmpSurface = IMG_Load("images/black.png");
//Verification de la non presence d'erreur lors du chargement
BOOST_CHECK(tmpSurface != nullptr);
//Creation de la texture du sprite a partir de la surface chargee
texture = SDL_CreateTextureFromSurface(renderer, tmpSurface);
//Liberation de la memoire allouee pour la surface
SDL_FreeSurface(tmpSurface);
}
~F()
{
BOOST_TEST_MESSAGE( "teardown fixture" );
SDL_DestroyTexture(texture);
SDL_DestroyRenderer( renderer );
SDL_DestroyWindow( window );
}
SDL_Window* window = nullptr;
SDL_Renderer* renderer = nullptr;
SDL_Surface *tmpSurface = nullptr;
SDL_Texture* texture = nullptr;
int x = 10, y=20, w = 30, h=40;
};
BOOST_AUTO_TEST_SUITE (Constructeurs)
BOOST_FIXTURE_TEST_CASE (Default, F)
{
std::string name = "Test";
Sprite s(createRect(x,y,w,h), texture);
std::vector<Obstacle*> obsList;
obsList.push_back(new Obstacle(s,createRect(x,y,w,h)));
World w(name,s, obsList);
BOOST_REQUIRE(w.name()==name);
BOOST_REQUIRE(w.sprite()==s);
BOOST_REQUIRE(w.obstacles().size()==obsList.size());
std::vector<Obstacle*> wo = w.obstacles();
for(unsigned int i =0; i< obsList.size(); i++)
{
BOOST_REQUIRE(*obsList[i]==*wo[i]);
}
}
BOOST_FIXTURE_TEST_CASE (Constructeur_copie, F)
{
std::string name = "Test";
Sprite s(createRect(x,y,w,h), texture);
std::vector<Obstacle*> obsList;
obsList.push_back(new Obstacle(s,createRect(x,y,w,h)));
World w(name,s, obsList);
World copy(w);
BOOST_REQUIRE(w.name()==copy.name());
BOOST_REQUIRE(w.sprite()==copy.sprite());
BOOST_REQUIRE(w.obstacles().size()==copy.obstacles().size());
std::vector<Obstacle*> wo = w.obstacles();
std::vector<Obstacle*> wc = copy.obstacles();
for(unsigned int i =0; i< obsList.size(); i++)
{
BOOST_REQUIRE(*wc[i]==*wo[i]);
}
}
BOOST_AUTO_TEST_SUITE_END( )
BOOST_AUTO_TEST_SUITE(Operators)
BOOST_FIXTURE_TEST_CASE(assign, F)
{
std::string name = "Test";
Sprite s(createRect(x,y,w,h), texture);
std::vector<Obstacle*> obsList;
obsList.push_back(new Obstacle(s,createRect(x,y,w,h)));
World w(name,s, obsList);
World copy = w;
BOOST_REQUIRE(w.name()==copy.name());
BOOST_REQUIRE(w.sprite()==copy.sprite());
BOOST_REQUIRE(w.obstacles().size()==copy.obstacles().size());
std::vector<Obstacle*> wo = w.obstacles();
std::vector<Obstacle*> wc = copy.obstacles();
for(unsigned int i =0; i< obsList.size(); i++)
{
BOOST_REQUIRE(*wc[i]==*wo[i]);
}
}
BOOST_AUTO_TEST_SUITE_END()

BIN
src/Unitests/WorldTest.o Normal file

Binary file not shown.

19
src/gui/Menu.hpp Normal file
View file

@ -0,0 +1,19 @@
#ifndef MENU_HPP
#define MENU_HPP
//Représente un menu
class Menu
{
protected:
int m_fontSize;
string m_fontPath;
SDL_Color m_colorHover;
SDL_Color m_colorNormal;
public:
Menu();
~Menu();
};
#endif

81
src/gui/display.cpp Normal file
View file

@ -0,0 +1,81 @@
#include "display.hpp"
//Single Instance
Display Display::_instance=Display();
//Constructeur qui initialise SDL, le renderer, SDL_image et la fenetre
Display::Display()
{
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
std::cout << "SDL n'a pas pu etre initialise. Erreur SDL : " << SDL_GetError() << std::endl;
return;
}
else
{
//On set le mode de filtrage des texture en lineaire
if( !SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" ) )
std::cout << "Attention : le filtrage des textures n'est pas lineaire" << std::endl;
//Cree une fenetre
_window = SDL_CreateWindow( "Nidrobb", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( _window == NULL )
{
std::cout << "La fenetre n'a pas pu etre cree. Erreur SDL : " << SDL_GetError() << std::endl;
return;
}
else
{
//Cree un renderer pour la fenetre
_renderer = SDL_CreateRenderer( _window, -1, SDL_RENDERER_ACCELERATED );
if( _renderer == NULL )
{
std::cout << "Le renderer n'a pas pu etre cree. Erreur SDL : " << SDL_GetError() << std::endl;
return;
}
else
{
//Initialise la couleur du renderer en blanc
SDL_SetRenderDrawColor( _renderer, 0xFF, 0xFF, 0xFF, 0xFF );
//Initialise le chargement d'image png
int imgFlags = IMG_INIT_PNG | IMG_INIT_JPG;
if( !( IMG_Init( imgFlags ) & imgFlags ) )
{
std::cout << "SDL_image n'a pas pu etre initialiser. Erreur SDL_image : " << IMG_GetError() << std::endl;
return;
}
}
}
}
}
Display& Display::operator=(const Display& d)
{
_window = d.getWindow();
_renderer = d.getRenderer();
//_playerList = d.getPList();
return *this;
}
Display::~Display()
{
//Destroy window
SDL_DestroyRenderer( _renderer );
SDL_DestroyWindow( _window );
_window = NULL;
_renderer = NULL;
//Quit SDL subsystems
IMG_Quit();
SDL_Quit();
}
//Dessine un objet
void Display::draw(Drawable* d) const
{
SDL_RenderCopy( _renderer, d->sprite().getTexture(), NULL,d->sprite().getRect() );
}

43
src/gui/display.hpp Normal file
View file

@ -0,0 +1,43 @@
#ifndef DISPLAY_HPP
#define DISPLAY_HPP
#include "../GameParam.hpp"
/*
#include <vector>
#include <iostream>
#include "SDL2/SDL.h"
#include <SDL2/SDL_image.h>
*/
#include "../GameEnv/Player.hpp"
//#include "sprite.hpp"
//class Player; //Forward Delcaration (Fonctionne pas avec vector, veut type complet)
SDL_Rect *createRect(int x, int y, int w, int h); //Forward Declaration (Game)
//Représente l'écran d'affichage
class Display
{
private:
SDL_Window *_window; //Fenètre d'affichage
SDL_Renderer *_renderer; //Outil de rendu
//Singleton
static Display _instance;
Display();
~Display();
Display& operator=(const Display& d);
public:
void draw(Drawable* d) const; //Dessine un objet
//void renderSprites();
//Singleton
static Display& Instance() { return _instance;}
//Accesseurs
SDL_Window* getWindow() const { return _window;}
SDL_Renderer* getRenderer() const { return _renderer;}
};
#endif

75
src/gui/sprite.cpp Normal file
View file

@ -0,0 +1,75 @@
#include "sprite.hpp"
Sprite::Sprite(){}
//Fuite memoire avec les textures
// Sprite::Sprite(SDL_Renderer *renderer, SDL_Rect *rect)
// {
// //association du rectangle passe en arg a la zone ou applique la texture du sprite
// _rect = rect;
// //Chargement d'une texture par defaut (objet noir)
// SDL_Surface *tmpSurface = IMG_Load("images/black.png");
// //Verification de la non presence d'erreur lors du chargement
// if(!tmpSurface)
// std::cout << "Surface non chargee a partir de black.png. Erreur :" << SDL_GetError() << std::endl;
// //Creation de la texture du sprite a partir de la surface chargee
// _texture = SDL_CreateTextureFromSurface(renderer, tmpSurface);
// //Liberation de la memoire allouee pour la surface
// SDL_FreeSurface(tmpSurface);
// }
//Fuite memoire avec les textures
// Sprite::Sprite(SDL_Renderer *renderer, SDL_Rect *rect, std::string imgPath)
// {
// //association du rectangle passe en arg a la zone ou applique la texture du sprite
// _rect = rect;
// //Chargement d'une texture a partir du chemin d'une image passe en arg
// SDL_Surface *tmpSurface = IMG_Load(imgPath.c_str());
// //Verification de la non presence d'erreur lors du chargement
// if(!tmpSurface)
// std::cout << "Surface non chargee a partir de " << imgPath << " Erreur :" << SDL_GetError() << std::endl;
// //Creation de la texture du sprite a partir de la surface chargee
// _texture = SDL_CreateTextureFromSurface(renderer, tmpSurface);
// //Liberation de la memoire allouee pour la surface
// SDL_FreeSurface(tmpSurface);
// }
Sprite::Sprite(SDL_Rect *rect, SDL_Texture *texture)
{
//association du rectangle passe en arg a la zone ou applique la texture du sprite
_rect = rect;
//association de la texture passee en arg au sprite
_texture = texture;
}
Sprite::Sprite(Sprite& s)
{
*this = s;
}
Sprite::~Sprite()
{
//std::cout<<"Destructeur sprite"<<std::endl;
//Genere des erreurs de double free(), des problemes d'affichage... je laisse la main a SDL
if(_rect !=nullptr)
delete _rect; //Attention parfois supprimé plusieurs fois
// SDL_DestroyTexture(_texture); //Stocké/Détruite hors de sprite
}
Sprite& Sprite::operator=(const Sprite& s)
{
const SDL_Rect* r = s.getRect();
_rect = createRect(r->x, r->y, r->w, r->h);
//ATTENTION suppose ques les textures sont supprimés en fin de pogramme seulement
_texture = s.getTexture();
return *this;
}
bool Sprite::operator==(const Sprite& s) const
{
if(this->getTexture()==s.getTexture() && SDL_RectEquals(this->getRect(),s.getRect())==SDL_TRUE)
return true;
else
return false;
}

32
src/gui/sprite.hpp Normal file
View file

@ -0,0 +1,32 @@
#ifndef SPRITE_HPP
#define SPRITE_HPP
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <string>
#include <iostream>
SDL_Rect *createRect(int x, int y, int w, int h); //Forward Declaration (Game)
class Sprite
{
private:
SDL_Rect *_rect = nullptr; //Rectangle du sprite
SDL_Texture *_texture = nullptr; //Texture du sprite (Stocké dans les usines)
public:
Sprite();
//Sprite(SDL_Renderer *renderer, SDL_Rect *rect); //Fuite mémoire avec les textures
//Sprite(SDL_Renderer *renderer, SDL_Rect *rect, std::string imgPath); //Fuite mémoire avec les textures
Sprite(SDL_Rect *rect, SDL_Texture *texture);
Sprite(Sprite& s);
~Sprite();
//Accesseurs
SDL_Texture *getTexture() const { return _texture;} //SDL_Texture ne peut pas etre const
SDL_Rect *getRect() const { return _rect;}
Sprite& operator=(const Sprite& s);
bool operator==(const Sprite& s) const;
};
#endif

191
src/gui/window.cpp Normal file
View file

@ -0,0 +1,191 @@
#include "window.hpp"
#include <stdio.h>
//Starts up SDL and creates window
bool init();
//Loads media
bool loadMedia();
//Frees media and shuts down SDL
void close();
//Loads individual image as texture
SDL_Texture* loadTexture( std::string path );
//La fenetre que l'on va cree
SDL_Window* gWindow = NULL;
//The window renderer
SDL_Renderer* gRenderer = NULL;
//Current displayed texture
SDL_Texture* gTexture = NULL;
//Cette fonction lance le module graphique SDL et cree une fenetre
bool init()
{
//Initialization flag
bool success = true;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
std::cout << "SDL n'a pas pu etre initialise. Erreur SDL : " << SDL_GetError() << std::endl;
success = false;
}
else
{
//On set le mode de filtrage des texture en lineaire
if( !SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" ) )
std::cout << "Attention : le filtrage des textures n'est pas lineaire" << std::endl;
//Cree une fenetre
gWindow = SDL_CreateWindow( "A&E Dungeon of Death", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( gWindow == NULL )
{
std::cout << "La fenetre n'a pas pu etre cree. Erreur SDL : " << SDL_GetError() << std::endl;
success = false;
}
else
{
//Create renderer for window
gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED );
if( gRenderer == NULL )
{
std::cout << "Le rendu n'a pas pu etre cree. Erreur SDL : " << SDL_GetError() << std::endl;
success = false;
}
else
{
//Initialize renderer color
SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
//Initialize PNG loading
int imgFlags = IMG_INIT_PNG;
if( !( IMG_Init( imgFlags ) & imgFlags ) )
{
printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
success = false;
}
}
}
}
return success;
}
bool loadMedia()
{
//Loading success flag
bool success = true;
//Load PNG texture
gTexture = loadTexture( "images/texture.png" );
if( gTexture == NULL )
{
printf( "Failed to load texture image!\n" );
success = false;
}
return success;
}
void close()
{
//Free loaded image
SDL_DestroyTexture( gTexture );
gTexture = NULL;
//Destroy window
SDL_DestroyRenderer( gRenderer );
SDL_DestroyWindow( gWindow );
gWindow = NULL;
gRenderer = NULL;
//Quit SDL subsystems
IMG_Quit();
SDL_Quit();
}
SDL_Texture* loadTexture( std::string path )
{
//The final texture
SDL_Texture* newTexture = NULL;
//Load image at specified path
SDL_Surface* loadedSurface = IMG_Load( path.c_str() );
if( loadedSurface == NULL )
{
printf( "Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError() );
}
else
{
//Create texture from surface pixels
newTexture = SDL_CreateTextureFromSurface( gRenderer, loadedSurface );
if( newTexture == NULL )
{
printf( "Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError() );
}
//Get rid of old loaded surface
SDL_FreeSurface( loadedSurface );
}
return newTexture;
}
int main( int argc, char* args[] )
{
//Start up SDL and create window
if( !init() )
{
printf( "Failed to initialize!\n" );
}
else
{
//Load media
if( !loadMedia() )
{
printf( "Failed to load media!\n" );
}
else
{
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//While application is running
while( !quit )
{
//Handle events on queue
while( SDL_PollEvent( &e ) != 0 )
{
//User requests quit
if( e.type == SDL_QUIT )
{
quit = true;
}
}
//Clear screen
SDL_RenderClear( gRenderer );
//Render texture to screen
SDL_RenderCopy( gRenderer, gTexture, NULL, NULL );
//Update screen
SDL_RenderPresent( gRenderer );
}
}
}
//Free resources and close SDL
close();
return 0;
}

10
src/gui/window.hpp Normal file
View file

@ -0,0 +1,10 @@
#ifndef WINDOW_HPP
#define WINDOW_HPP
#include <SDL2/SDL.h>
#include <iostream>
#include <string>
#include "GameParam.hpp"
#endif

BIN
src/images/Mewtwo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

BIN
src/images/Nidrobb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

BIN
src/images/black.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B

BIN
src/images/crouch.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 KiB

BIN
src/images/crouch1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
src/images/crouch2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
src/images/jump.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
src/images/nuage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
src/images/red_square.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
src/images/sauts.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

17
src/main.cpp Normal file
View file

@ -0,0 +1,17 @@
//#include "gui/display.hpp"
#include "GameEnv/Game.hpp"
int main(int argc, char *argv[])
{
Game& game = Game::Instance();
while(!game.quit())
{
if(game.quit()) //Indicateur des bugs qui BRISENT LES COUILLES
cout<<"WTF"<<endl;
game.run();
SDL_Delay(1); //Semble calmer les bug wtf
}
}