Project import
12
Nidrobb_UML.html
Normal file
BIN
Nidrobb_UML.png
Normal file
After Width: | Height: | Size: 534 KiB |
BIN
README.pdf
Normal file
100
src/Animation/Animation.cpp
Normal 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;
|
||||
}
|
45
src/Animation/Animation.hpp
Normal 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
|
425
src/Animation/AnimationBuilder.cpp
Normal 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);
|
||||
}
|
39
src/Animation/AnimationBuilder.hpp
Normal 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
|
150
src/Animation/AnimationFrame.cpp
Normal 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;
|
||||
}
|
49
src/Animation/AnimationFrame.hpp
Normal 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
|
@ -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
|
14
src/Command/AttackCommand.hpp
Normal 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
|
@ -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
|
14
src/Command/DownCommand.hpp
Normal 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
|
14
src/Command/ExitCommand.hpp
Normal 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
|
13
src/Command/FallCommand.hpp
Normal 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
|
@ -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
|
@ -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
|
13
src/Command/JumpCommand.hpp
Normal 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
|
13
src/Command/LeftCommand.hpp
Normal 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
|
15
src/Command/NullCommand.hpp
Normal 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
|
13
src/Command/RightCommand.hpp
Normal 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
|
@ -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
|
18
src/GameEnv/ComputerPlayer.hpp
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
108
src/GameEnv/WorldBuilder.cpp
Normal 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;
|
||||
}
|
29
src/GameEnv/WorldBuilder.hpp
Normal 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
|
@ -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
|
@ -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
66
src/Toolbox.cpp
Normal 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
|
@ -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
187
src/Unitests/AnimationFrameTest.cpp
Normal 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( )
|
BIN
src/Unitests/AnimationFrameTest.o
Normal file
237
src/Unitests/AnimationTest.cpp
Normal 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( )
|
BIN
src/Unitests/AnimationTest.o
Normal file
46
src/Unitests/InputMapTest.cpp
Normal 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
125
src/Unitests/ObstacleTest.cpp
Normal 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
123
src/Unitests/SpriteTest.cpp
Normal 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()
|
66
src/Unitests/ToolboxTest.cpp
Normal 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
|
@ -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
19
src/gui/Menu.hpp
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
After Width: | Height: | Size: 231 KiB |
BIN
src/images/Nidrobb.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
src/images/Robot/robot_attack_left.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
src/images/Robot/robot_attack_left2.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
src/images/Robot/robot_attack_right.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
src/images/Robot/robot_attack_right2.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
src/images/Robot/robot_crouch.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
src/images/Robot/robot_jump.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/images/Robot/robot_jump_left.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
src/images/Robot/robot_jump_left2.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
src/images/Robot/robot_jump_right.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
src/images/Robot/robot_jump_right2.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
src/images/Robot/robot_left.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src/images/Robot/robot_left2.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
src/images/Robot/robot_right.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src/images/Robot/robot_right2.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
src/images/Robot/robot_stand.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
src/images/Robot/robotchuck.png
Normal file
After Width: | Height: | Size: 215 KiB |
BIN
src/images/black.png
Normal file
After Width: | Height: | Size: 151 B |
BIN
src/images/crouch.jpg
Normal file
After Width: | Height: | Size: 660 KiB |
BIN
src/images/crouch1.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
src/images/crouch2.jpg
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
src/images/jump.jpg
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
src/images/nuage.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
src/images/red_square.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
src/images/sauts.jpg
Normal file
After Width: | Height: | Size: 572 KiB |
BIN
src/images/skyBackground.jpg
Normal file
After Width: | Height: | Size: 277 KiB |
BIN
src/images/stickman_punch.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
src/images/stickman_right.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
src/images/stickman_stand.png
Normal file
After Width: | Height: | Size: 14 KiB |
17
src/main.cpp
Normal 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
|
||||
}
|
||||
}
|