diff --git a/Nidrobb_UML.html b/Nidrobb_UML.html new file mode 100644 index 0000000..311ca8b --- /dev/null +++ b/Nidrobb_UML.html @@ -0,0 +1,12 @@ + + + +Draw.io Diagram + + + + +
+ + + diff --git a/Nidrobb_UML.png b/Nidrobb_UML.png new file mode 100644 index 0000000..3da0594 Binary files /dev/null and b/Nidrobb_UML.png differ diff --git a/README.pdf b/README.pdf new file mode 100644 index 0000000..c2dff28 Binary files /dev/null and b/README.pdf differ diff --git a/src/Animation/Animation.cpp b/src/Animation/Animation.cpp new file mode 100644 index 0000000..a939360 --- /dev/null +++ b/src/Animation/Animation.cpp @@ -0,0 +1,100 @@ +#include "Animation.hpp" + +Animation::Animation(const string& name, const vector frames):_name(name)//, _frames(frames) +{ + //VERIFIER BONNE TRANSMISSION DES FRAMES + for(AnimationFrame* frame : frames) + { + //cout<<" anim: "<center().first<<"/"<center().second<& Animation::nextFrame() +{ + unsigned int res; + //cout<<"Progress : "<< _progress << "/"<<_duration <center().first<<"/"<<_frames[res]->center().second<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& 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 "<center().first<<"/"<center().second<center().first<<"/"<center().second< _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 frames); + Animation(const Animation& a){ *this = a;} + ~Animation(); + + bool inProgress() const; //Indique si l'animation est en cours + const pair& 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& 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 \ No newline at end of file diff --git a/src/Animation/AnimationBuilder.cpp b/src/Animation/AnimationBuilder.cpp new file mode 100644 index 0000000..2b057ba --- /dev/null +++ b/src/Animation/AnimationBuilder.cpp @@ -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& Pos, SDL_Rect* SpriteRect, const vector ahitbox, const vector& 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"< 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& StartPos) +{ + //cout<<"AnimationBuilder : Stand"< 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 phitbox; + //Ajout d'une hitbox au vecteur + phitbox.push_back(h); + + vector 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 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& StartPos) +{ + //cout<<"AnimationBuilder : moveRight"< FinalPos = make_pair(StartPos.first+PLAYER_MOVE_DISTANCE, StartPos.second); //Position finale + pair MidPos = make_pair((StartPos.first + FinalPos.first)/2, (StartPos.second + FinalPos.second)/2); //Position Intermédiaire + //cout<<" "< anim; + + vector 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 phitbox; + phitbox.push_back(h); + + vector 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 anim; + anim.push_back(animF1); + anim.push_back(animF2); + anim.push_back(animF3); + */ + //cout<<"Builder Right size: "<< anim.size() <& StartPos) +{ + //cout<<"AnimationBuilder : moveLeft"< FinalPos = make_pair(StartPos.first-PLAYER_MOVE_DISTANCE, StartPos.second); //Position finale + pair MidPos = make_pair((StartPos.first + FinalPos.first)/2, (StartPos.second + FinalPos.second)/2); //Position Intermédiaire + + //cout<<" "< 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& StartPos) +{ + //cout<<"AnimationBuilder : Jump"< anim; + + pair MidPos = make_pair(StartPos.first, StartPos.second - PLAYER_JUMP_HEIGHT/2); //Position Intermédiaire + pair 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& StartPos) +{ + //cout<<"AnimationBuilder : Right Jump"< anim; + + pair MidPos1 = make_pair(StartPos.first+PLAYER_MOVE_DISTANCE, StartPos.second - PLAYER_JUMP_HEIGHT/4); //Position Intermédiaire + pair MidPos2 = make_pair(StartPos.first+PLAYER_MOVE_DISTANCE*2, StartPos.second - PLAYER_JUMP_HEIGHT/2); //Position Intermédiaire + pair TopPos = make_pair(StartPos.first+PLAYER_MOVE_DISTANCE*3, (StartPos.second - PLAYER_JUMP_HEIGHT)); //Position zenith + pair MidPos3 = make_pair(StartPos.first+PLAYER_MOVE_DISTANCE*4, StartPos.second - PLAYER_JUMP_HEIGHT/2); //Position Intermédiaire + pair MidPos4 = make_pair(StartPos.first+PLAYER_MOVE_DISTANCE*5, StartPos.second - PLAYER_JUMP_HEIGHT/4); //Position Intermédiaire + pair 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& StartPos) +{ + //cout<<"AnimationBuilder : Left Jump"< anim; + + pair MidPos1 = make_pair(StartPos.first-PLAYER_MOVE_DISTANCE, StartPos.second - PLAYER_JUMP_HEIGHT/4); //Position Intermédiaire + pair MidPos2 = make_pair(StartPos.first-PLAYER_MOVE_DISTANCE*2, StartPos.second - PLAYER_JUMP_HEIGHT/2); //Position Intermédiaire + pair TopPos = make_pair(StartPos.first-PLAYER_MOVE_DISTANCE*3, (StartPos.second - PLAYER_JUMP_HEIGHT)); //Position zenith + pair MidPos3 = make_pair(StartPos.first-PLAYER_MOVE_DISTANCE*4, StartPos.second - PLAYER_JUMP_HEIGHT/2); //Position Intermédiaire + pair MidPos4 = make_pair(StartPos.first-PLAYER_MOVE_DISTANCE*5, StartPos.second - PLAYER_JUMP_HEIGHT/4); //Position Intermédiaire + pair 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& StartPos) +{ + //cout << "AnimationBuilder : Crouch" << endl; + + vector 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& StartPos)//, const pair& EndPos) +{ + //cout << "AnimationBuilder : Fall" << endl; + + vector anim; + + /* + pair 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 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& StartPos) +{ + vector anim; + + vector 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 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& StartPos) +{ + vector anim; + + vector attackBox1; + attackBox1.push_back(createRect(StartPos.first-PLAYER_WIDTH,StartPos.second,PLAYER_WIDTH,PLAYER_HEIGHT*1/3)); + + vector 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); +} \ No newline at end of file diff --git a/src/Animation/AnimationBuilder.hpp b/src/Animation/AnimationBuilder.hpp new file mode 100644 index 0000000..dd553e7 --- /dev/null +++ b/src/Animation/AnimationBuilder.hpp @@ -0,0 +1,39 @@ +#ifndef ANIMATIONBUILDER_HPP +#define ANIMATIONBUILDER_HPP + +#include +#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 _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& Pos, SDL_Rect* SpriteRect = nullptr, const vector ahitbox =vector(), const vector& phitbox =vector()) const; + + //Pas de const à cause de SDL_Texture... + Animation* stand(const pair& StartPos); //Construit l'animation statique + Animation* moveRight(const pair& StartPos); //Construit un déplacement vers la droite + Animation* moveLeft(const pair& StartPos); //Construit un déplacement vers la gauche + Animation* jump(const pair& StartPos); //Construit un saut + Animation* rightJump(const pair& StartPos); //Construit un saut vers la droite + Animation* leftJump(const pair& StartPos); //Construit un saut vers la gauche + Animation* crouch(const pair& StartPos); //Constuit l'animation pour s'accroupir + Animation* fall(const pair& StartPos); //Construit une chute + Animation* attackRight(const pair& StartPos); //Construit une attaque vers la droite + Animation* attackLeft(const pair& StartPos); //Construit une attaque vers la gauche +}; + +#endif \ No newline at end of file diff --git a/src/Animation/AnimationFrame.cpp b/src/Animation/AnimationFrame.cpp new file mode 100644 index 0000000..e421652 --- /dev/null +++ b/src/Animation/AnimationFrame.cpp @@ -0,0 +1,150 @@ +#include "AnimationFrame.hpp" + +AnimationFrame::AnimationFrame(const Sprite& s, const vector& pHitBox, const vector& aHitBox, const pair& 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"<x<<"/"<y<<" - "<w<<"/"<h<x<<"/"<y<<" - "<w<<"/"<h<& pos) +{ + //Caclul du vecteur de translation + pair 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 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; +} \ No newline at end of file diff --git a/src/Animation/AnimationFrame.hpp b/src/Animation/AnimationFrame.hpp new file mode 100644 index 0000000..ce9c490 --- /dev/null +++ b/src/Animation/AnimationFrame.hpp @@ -0,0 +1,49 @@ +#ifndef ANIMATIONFRAME_HPP +#define ANIMATIONFRAME_HPP + +#include +//#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 _passiveHitbox; //Liste des hitbox passive (Reception de dommages) + vector _activeHitbox; //Liste des hitbox active (Envoie de dommages) + + //Amelioration : rendre relatif au centre les autre attributs + pair _center; //Centre du personnage (repère SDL) + +public: + //AnimationFrame(){}; + AnimationFrame(const Sprite& s, const vector& pHitBox, const vector& aHitBox, const pair& 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& 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& center() { return _center;} + const pair& center() const{ return _center;} + const vector& pHitBox() const { return _passiveHitbox;} + const vector& aHitBox() const {return _activeHitbox;} + + //Opérateurs + AnimationFrame& operator=(const AnimationFrame& a); + bool operator==(const AnimationFrame& a) const; +}; + +#endif \ No newline at end of file diff --git a/src/Collidable.hpp b/src/Collidable.hpp new file mode 100644 index 0000000..7b725e6 --- /dev/null +++ b/src/Collidable.hpp @@ -0,0 +1,21 @@ +#ifndef COLLIDABLE_HPP +#define COLLIDABLE_HPP + +#include + +//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 \ No newline at end of file diff --git a/src/Command/AttackCommand.hpp b/src/Command/AttackCommand.hpp new file mode 100644 index 0000000..7ddf9fb --- /dev/null +++ b/src/Command/AttackCommand.hpp @@ -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 \ No newline at end of file diff --git a/src/Command/Command.hpp b/src/Command/Command.hpp new file mode 100644 index 0000000..a5eb82c --- /dev/null +++ b/src/Command/Command.hpp @@ -0,0 +1,26 @@ +#ifndef COMMAND_HPP +#define COMMAND_HPP + +#include +#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 \ No newline at end of file diff --git a/src/Command/DownCommand.hpp b/src/Command/DownCommand.hpp new file mode 100644 index 0000000..6c4230f --- /dev/null +++ b/src/Command/DownCommand.hpp @@ -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 \ No newline at end of file diff --git a/src/Command/ExitCommand.hpp b/src/Command/ExitCommand.hpp new file mode 100644 index 0000000..713f686 --- /dev/null +++ b/src/Command/ExitCommand.hpp @@ -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 \ No newline at end of file diff --git a/src/Command/FallCommand.hpp b/src/Command/FallCommand.hpp new file mode 100644 index 0000000..e19a96b --- /dev/null +++ b/src/Command/FallCommand.hpp @@ -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 \ No newline at end of file diff --git a/src/Command/InputMap.cpp b/src/Command/InputMap.cpp new file mode 100644 index 0000000..caecc1f --- /dev/null +++ b/src/Command/InputMap.cpp @@ -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::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::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::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::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 map = im.GMap(); + os<< "General" << endl; + for(auto & i : map) //auto = map<>::iterator + { + os<< " " << i.first << " : " << i.second->name() << " " << i.second->target() <::iterator + { + os<< " " << i.first << " : " << i.second->name() << " " << i.second->target() <::iterator + { + os<< " " << i.first << " : " << i.second->name() << " " << i.second->target() < map = im.GMap(); + os<< "General" << endl; + for(auto & i : map) //auto = map<>::iterator + { + os<< " " << i.first << " : " << i.second <::iterator + { + os<< " " << i.first << " : " << i.second <::iterator + { + os<< " " << i.first << " : " << i.second < +#include +#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 _GeneralMap; //Map des commandes système + map _P1Map; //Map des commandes joueur 1 + map _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& GMap() const { return _GeneralMap;}; + const map& P1Map() const { return _P1Map;}; + const map& P2Map() const { return _P2Map;}; +}; + + +//Operateur << std +ostream& operator<<(ostream& os,const InputMap& im); + +#endif \ No newline at end of file diff --git a/src/Command/JumpCommand.hpp b/src/Command/JumpCommand.hpp new file mode 100644 index 0000000..fd4e511 --- /dev/null +++ b/src/Command/JumpCommand.hpp @@ -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 \ No newline at end of file diff --git a/src/Command/LeftCommand.hpp b/src/Command/LeftCommand.hpp new file mode 100644 index 0000000..793f84f --- /dev/null +++ b/src/Command/LeftCommand.hpp @@ -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 \ No newline at end of file diff --git a/src/Command/NullCommand.hpp b/src/Command/NullCommand.hpp new file mode 100644 index 0000000..b4331b0 --- /dev/null +++ b/src/Command/NullCommand.hpp @@ -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 \ No newline at end of file diff --git a/src/Command/RightCommand.hpp b/src/Command/RightCommand.hpp new file mode 100644 index 0000000..2a291bc --- /dev/null +++ b/src/Command/RightCommand.hpp @@ -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 \ No newline at end of file diff --git a/src/Drawable.hpp b/src/Drawable.hpp new file mode 100644 index 0000000..82f7c06 --- /dev/null +++ b/src/Drawable.hpp @@ -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 \ No newline at end of file diff --git a/src/GameEnv/ComputerPlayer.hpp b/src/GameEnv/ComputerPlayer.hpp new file mode 100644 index 0000000..06ce4e9 --- /dev/null +++ b/src/GameEnv/ComputerPlayer.hpp @@ -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& 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 \ No newline at end of file diff --git a/src/GameEnv/Game.cpp b/src/GameEnv/Game.cpp new file mode 100644 index 0000000..46d93e8 --- /dev/null +++ b/src/GameEnv/Game.cpp @@ -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 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 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()<id()<<" ready !"<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"< _currTime) + { + //cout<<"wait : "<< _loopTime-_currTime<obstacles()) + { + _disp.draw(o); + } + //cout<<"draw P"<target()==0) //Commande système + { + //cout<<"Commande système : "<name()<name()=="ExitCommand") + _quit = true; + } + if(cmd->target()>0 && !_menu) //Commande joueur (Hors menu) + { + //cout<<"Commande joueur "<target()<<" : "<name()<target()==p->id()) + cmd->execute(*p); + } + } + } + else + { + cout<<"Game Warning : Invalid Input"<& inputs) +{ + // if(inputs.empty())//Aucune touche appuyée + // { + + // } + //Gestion commande joueurs + for(int i : inputs) + { + //cout<<"Execute : "<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 !"<obstacles()) + { + //cout<<"B :"<<*o->box()<collideP(o->box())) + { + //collided = true; + + // cout<<"Player "<id()<<" : Obstacle Collision"<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 "<id()<<" hit Player "<id()<<" !"<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 pcenter = make_pair(p->pos().first+PLAYER_WIDTH/2, p->pos().second+PLAYER_HEIGHT/2); //Center géométrique de player + // cout<<"Player pos : "<center().first<<" / "<center().second<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 : "<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 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 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 obsList) +{ + //Identification des obstacles sous le joueur eligibles + pair 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 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 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; +} \ No newline at end of file diff --git a/src/GameEnv/Game.hpp b/src/GameEnv/Game.hpp new file mode 100644 index 0000000..5618169 --- /dev/null +++ b/src/GameEnv/Game.hpp @@ -0,0 +1,63 @@ +#ifndef GAME_HPP +#define GAME_HPP + +#include + +#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 _obsList; + World* _world; //Monde + WorldBuilder _builder; //Usine à monde (on pourrait l'externaliser en singleton) + vector _playerList; //Liste des joueurs + set _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& 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 obsList); //Vérifie si un joueur chute + bool isFallingV2(const Player *p, const vector 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 PList() const { return _playerList;} + bool quit() const { return _quit;} + bool& quit(){ return _quit;} + +}; + +#endif \ No newline at end of file diff --git a/src/GameEnv/Obstacle.cpp b/src/GameEnv/Obstacle.cpp new file mode 100644 index 0000000..d951cf6 --- /dev/null +++ b/src/GameEnv/Obstacle.cpp @@ -0,0 +1,40 @@ +#include "Obstacle.hpp" + +Obstacle::Obstacle(Sprite& s, SDL_Rect* collisionBox) +{ + _sprite = s; + _collisionBox = collisionBox; +} + +Obstacle::~Obstacle() +{ + //std::cout<<"Destructeur Obstacle"<x, o.box()->y, o.box()->w, o.box()->h); + + //std::cout<<"Obs = : "<<*this->box()< + +//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 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 \ No newline at end of file diff --git a/src/GameEnv/Player.cpp b/src/GameEnv/Player.cpp new file mode 100644 index 0000000..3e07902 --- /dev/null +++ b/src/GameEnv/Player.cpp @@ -0,0 +1,198 @@ +#include "Player.hpp" + +unsigned int Player::nextPlayerID = 1; + +Player::Player(const pair& 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& 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& pos) +{ + _currAnim->holdPos(pos); +} + +/* +void Player::checkAnim(const vector obstacles) +{ + bool validAnim = true; + vector 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"< _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& StartPos, SDL_Renderer *renderer); + virtual ~Player(); + + void stand(); //Reste en place + void stand(const pair& 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& 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& pos() const { return _pos;} + const vector& aHitBox() const { return _currAnim->getFrame()->aHitBox();} + const vector& 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 obstacles); //On verifie/modifie l'animation pour gerer les collisions +}; + +#endif \ No newline at end of file diff --git a/src/GameEnv/World.cpp b/src/GameEnv/World.cpp new file mode 100644 index 0000000..501c6d3 --- /dev/null +++ b/src/GameEnv/World.cpp @@ -0,0 +1,42 @@ +#include "../GameEnv/World.hpp" + +World::World(const std::string& name, const Sprite& background, const std::vector& 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()< obsList = w.obstacles(); + for(Obstacle* o : obsList) + { + Obstacle* newObs = new Obstacle(*o); + _obsList.push_back(newObs); + } + return *this; +} \ No newline at end of file diff --git a/src/GameEnv/World.hpp b/src/GameEnv/World.hpp new file mode 100644 index 0000000..0266715 --- /dev/null +++ b/src/GameEnv/World.hpp @@ -0,0 +1,39 @@ +#ifndef WORLD_HPP +#define WORLD_HPP + +//#include +#include +#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 _obsList; //Liste des objets solides + Sprite _background; //Fond + +public: + //World(){} + World(const std::string& name, const Sprite& background, const std::vector& 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& obstacles() const { return _obsList;} + Sprite& sprite(){ return _background;} + const Sprite& sprite() const{ return _background;} + + World& operator=(const World& w); +}; + +#endif \ No newline at end of file diff --git a/src/GameEnv/WorldBuilder.cpp b/src/GameEnv/WorldBuilder.cpp new file mode 100644 index 0000000..7c0265f --- /dev/null +++ b/src/GameEnv/WorldBuilder.cpp @@ -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& 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()< 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()<obstacles()) + // { + // cout<<"Builder :"<<*o->box()< 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()<obstacles()) + // { + // cout<<"Builder :"<<*o->box()< +#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 _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& 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 \ No newline at end of file diff --git a/src/GameParam.hpp b/src/GameParam.hpp new file mode 100644 index 0000000..36fe3f7 --- /dev/null +++ b/src/GameParam.hpp @@ -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 \ No newline at end of file diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..155f452 --- /dev/null +++ b/src/Makefile @@ -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 + diff --git a/src/Nidrobb b/src/Nidrobb new file mode 100644 index 0000000..7e6359f Binary files /dev/null and b/src/Nidrobb differ diff --git a/src/Toolbox.cpp b/src/Toolbox.cpp new file mode 100644 index 0000000..50e08a5 --- /dev/null +++ b/src/Toolbox.cpp @@ -0,0 +1,66 @@ +#include "Toolbox.hpp" + +//Retourne le centre géométrique d'un objet à partir +//Pair 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<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; +// } \ No newline at end of file diff --git a/src/Toolbox.hpp b/src/Toolbox.hpp new file mode 100644 index 0000000..d9829fb --- /dev/null +++ b/src/Toolbox.hpp @@ -0,0 +1,11 @@ +#ifndef TOOLBOX_HPP +#define TOOLBOX_HPP + +#include +#include + +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 \ No newline at end of file diff --git a/src/Unitest b/src/Unitest new file mode 100644 index 0000000..5b3c8f1 Binary files /dev/null and b/src/Unitest differ diff --git a/src/Unitests/AnimationFrameTest.cpp b/src/Unitests/AnimationFrameTest.cpp new file mode 100644 index 0000000..b036f6a --- /dev/null +++ b/src/Unitests/AnimationFrameTest.cpp @@ -0,0 +1,187 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE AnimationFrameTest +#include +#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(), vector(), 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(), vector(), 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 hitboxs; + hitboxs.push_back(createRect(x,y,w,h)); + + AnimationFrame frame(s, vector(), 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(), vector(), 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(), vector(), 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(), vector(), 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(), vector(), 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(), vector(), make_pair(x,y)); + + AnimationFrame copy = frame; + + BOOST_CHECK(copy==frame); +} +BOOST_AUTO_TEST_SUITE_END( ) \ No newline at end of file diff --git a/src/Unitests/AnimationFrameTest.o b/src/Unitests/AnimationFrameTest.o new file mode 100644 index 0000000..59a66fd Binary files /dev/null and b/src/Unitests/AnimationFrameTest.o differ diff --git a/src/Unitests/AnimationTest.cpp b/src/Unitests/AnimationTest.cpp new file mode 100644 index 0000000..f55f88a --- /dev/null +++ b/src/Unitests/AnimationTest.cpp @@ -0,0 +1,237 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE AnimationTest +#include +#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 vframe; + vframe.push_back(new AnimationFrame(s1, vector(), vector(), make_pair(x,y))); + vframe.push_back(new AnimationFrame(s2, vector(), vector(), 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; + vframe.push_back(new AnimationFrame(s1, vector(), vector(), make_pair(x,y))); + vframe.push_back(new AnimationFrame(s2, vector(), vector(), 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 vframe; + vframe.push_back(new AnimationFrame(s1, vector(), vector(), make_pair(x,y))); + vframe.push_back(new AnimationFrame(s2, vector(), vector(), make_pair(x+10,y+10))); + vframe.push_back(new AnimationFrame(s2, vector(), vector(), 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 vframe; + vframe.push_back(new AnimationFrame(s1, vector(), vector(), make_pair(x,y))); + vframe.push_back(new AnimationFrame(s2, vector(), vector(), make_pair(x+10,y+10))); + + Animation anim(name, vframe); + + BOOST_CHECK(anim.progress()==1); + pair 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 vframe; + vframe.push_back(new AnimationFrame(s1, vector(), vector(), make_pair(x,y))); + vframe.push_back(new AnimationFrame(s2, vector(), vector(), make_pair(x+10,y+10))); + + Animation anim(name, vframe); + + pair 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 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 hitboxs; + hitboxs.push_back(createRect(x,y,w,h)); + + vector vframe; + vframe.push_back(new AnimationFrame(s1, vector(), 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 hitboxs; + hitboxs.push_back(createRect(x,y,w,h)); + + vector vframe; + vframe.push_back(new AnimationFrame(s1, hitboxs, vector(), 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 vframe; + vframe.push_back(new AnimationFrame(s1, vector(), vector(), make_pair(x,y))); + vframe.push_back(new AnimationFrame(s2, vector(), vector(), 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 +#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 : "< +#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() \ No newline at end of file diff --git a/src/Unitests/ObstacleTest.o b/src/Unitests/ObstacleTest.o new file mode 100644 index 0000000..1c6c828 Binary files /dev/null and b/src/Unitests/ObstacleTest.o differ diff --git a/src/Unitests/SpriteTest.cpp b/src/Unitests/SpriteTest.cpp new file mode 100644 index 0000000..653f82b --- /dev/null +++ b/src/Unitests/SpriteTest.cpp @@ -0,0 +1,123 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE SpriteTest +#include +#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() \ No newline at end of file diff --git a/src/Unitests/ToolboxTest.cpp b/src/Unitests/ToolboxTest.cpp new file mode 100644 index 0000000..01ab1ca --- /dev/null +++ b/src/Unitests/ToolboxTest.cpp @@ -0,0 +1,66 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE ToolboxTest +#include +#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 : "< 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 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 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 wo = w.obstacles(); + std::vector 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 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 wo = w.obstacles(); + std::vector wc = copy.obstacles(); + for(unsigned int i =0; i< obsList.size(); i++) + { + BOOST_REQUIRE(*wc[i]==*wo[i]); + } +} + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/src/Unitests/WorldTest.o b/src/Unitests/WorldTest.o new file mode 100644 index 0000000..3b5c7e5 Binary files /dev/null and b/src/Unitests/WorldTest.o differ diff --git a/src/gui/Menu.hpp b/src/gui/Menu.hpp new file mode 100644 index 0000000..6e36e4c --- /dev/null +++ b/src/gui/Menu.hpp @@ -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 \ No newline at end of file diff --git a/src/gui/display.cpp b/src/gui/display.cpp new file mode 100644 index 0000000..0a4abe6 --- /dev/null +++ b/src/gui/display.cpp @@ -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() ); +} \ No newline at end of file diff --git a/src/gui/display.hpp b/src/gui/display.hpp new file mode 100644 index 0000000..e7b81c2 --- /dev/null +++ b/src/gui/display.hpp @@ -0,0 +1,43 @@ +#ifndef DISPLAY_HPP +#define DISPLAY_HPP + +#include "../GameParam.hpp" +/* +#include +#include + +#include "SDL2/SDL.h" +#include +*/ +#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 \ No newline at end of file diff --git a/src/gui/sprite.cpp b/src/gui/sprite.cpp new file mode 100644 index 0000000..358afea --- /dev/null +++ b/src/gui/sprite.cpp @@ -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"<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; +} \ No newline at end of file diff --git a/src/gui/sprite.hpp b/src/gui/sprite.hpp new file mode 100644 index 0000000..d00689a --- /dev/null +++ b/src/gui/sprite.hpp @@ -0,0 +1,32 @@ +#ifndef SPRITE_HPP +#define SPRITE_HPP + +#include +#include +#include +#include + +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 \ No newline at end of file diff --git a/src/gui/window.cpp b/src/gui/window.cpp new file mode 100644 index 0000000..166dbfd --- /dev/null +++ b/src/gui/window.cpp @@ -0,0 +1,191 @@ +#include "window.hpp" + +#include + + +//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; +} \ No newline at end of file diff --git a/src/gui/window.hpp b/src/gui/window.hpp new file mode 100644 index 0000000..25346b6 --- /dev/null +++ b/src/gui/window.hpp @@ -0,0 +1,10 @@ +#ifndef WINDOW_HPP +#define WINDOW_HPP + +#include +#include +#include + +#include "GameParam.hpp" + +#endif \ No newline at end of file diff --git a/src/images/Mewtwo.png b/src/images/Mewtwo.png new file mode 100644 index 0000000..de1ec66 Binary files /dev/null and b/src/images/Mewtwo.png differ diff --git a/src/images/Nidrobb.png b/src/images/Nidrobb.png new file mode 100644 index 0000000..7c7e65c Binary files /dev/null and b/src/images/Nidrobb.png differ diff --git a/src/images/Robot/robot_attack_left.png b/src/images/Robot/robot_attack_left.png new file mode 100644 index 0000000..efc80aa Binary files /dev/null and b/src/images/Robot/robot_attack_left.png differ diff --git a/src/images/Robot/robot_attack_left2.png b/src/images/Robot/robot_attack_left2.png new file mode 100644 index 0000000..18e7a20 Binary files /dev/null and b/src/images/Robot/robot_attack_left2.png differ diff --git a/src/images/Robot/robot_attack_right.png b/src/images/Robot/robot_attack_right.png new file mode 100644 index 0000000..e9daf63 Binary files /dev/null and b/src/images/Robot/robot_attack_right.png differ diff --git a/src/images/Robot/robot_attack_right2.png b/src/images/Robot/robot_attack_right2.png new file mode 100644 index 0000000..6f3cd5c Binary files /dev/null and b/src/images/Robot/robot_attack_right2.png differ diff --git a/src/images/Robot/robot_crouch.png b/src/images/Robot/robot_crouch.png new file mode 100644 index 0000000..19de020 Binary files /dev/null and b/src/images/Robot/robot_crouch.png differ diff --git a/src/images/Robot/robot_jump.png b/src/images/Robot/robot_jump.png new file mode 100644 index 0000000..b7417cb Binary files /dev/null and b/src/images/Robot/robot_jump.png differ diff --git a/src/images/Robot/robot_jump_left.png b/src/images/Robot/robot_jump_left.png new file mode 100644 index 0000000..540788d Binary files /dev/null and b/src/images/Robot/robot_jump_left.png differ diff --git a/src/images/Robot/robot_jump_left2.png b/src/images/Robot/robot_jump_left2.png new file mode 100644 index 0000000..ba099eb Binary files /dev/null and b/src/images/Robot/robot_jump_left2.png differ diff --git a/src/images/Robot/robot_jump_right.png b/src/images/Robot/robot_jump_right.png new file mode 100644 index 0000000..8f2a76b Binary files /dev/null and b/src/images/Robot/robot_jump_right.png differ diff --git a/src/images/Robot/robot_jump_right2.png b/src/images/Robot/robot_jump_right2.png new file mode 100644 index 0000000..db7dbd3 Binary files /dev/null and b/src/images/Robot/robot_jump_right2.png differ diff --git a/src/images/Robot/robot_left.png b/src/images/Robot/robot_left.png new file mode 100644 index 0000000..2954451 Binary files /dev/null and b/src/images/Robot/robot_left.png differ diff --git a/src/images/Robot/robot_left2.png b/src/images/Robot/robot_left2.png new file mode 100644 index 0000000..e0a74b7 Binary files /dev/null and b/src/images/Robot/robot_left2.png differ diff --git a/src/images/Robot/robot_right.png b/src/images/Robot/robot_right.png new file mode 100644 index 0000000..426b466 Binary files /dev/null and b/src/images/Robot/robot_right.png differ diff --git a/src/images/Robot/robot_right2.png b/src/images/Robot/robot_right2.png new file mode 100644 index 0000000..2f61edc Binary files /dev/null and b/src/images/Robot/robot_right2.png differ diff --git a/src/images/Robot/robot_stand.png b/src/images/Robot/robot_stand.png new file mode 100644 index 0000000..c6fcd71 Binary files /dev/null and b/src/images/Robot/robot_stand.png differ diff --git a/src/images/Robot/robotchuck.png b/src/images/Robot/robotchuck.png new file mode 100644 index 0000000..870f6f9 Binary files /dev/null and b/src/images/Robot/robotchuck.png differ diff --git a/src/images/black.png b/src/images/black.png new file mode 100644 index 0000000..9a8da08 Binary files /dev/null and b/src/images/black.png differ diff --git a/src/images/crouch.jpg b/src/images/crouch.jpg new file mode 100644 index 0000000..b6cf7c9 Binary files /dev/null and b/src/images/crouch.jpg differ diff --git a/src/images/crouch1.jpg b/src/images/crouch1.jpg new file mode 100644 index 0000000..5efb84f Binary files /dev/null and b/src/images/crouch1.jpg differ diff --git a/src/images/crouch2.jpg b/src/images/crouch2.jpg new file mode 100644 index 0000000..5557049 Binary files /dev/null and b/src/images/crouch2.jpg differ diff --git a/src/images/jump.jpg b/src/images/jump.jpg new file mode 100644 index 0000000..7919dee Binary files /dev/null and b/src/images/jump.jpg differ diff --git a/src/images/nuage.png b/src/images/nuage.png new file mode 100644 index 0000000..4749a74 Binary files /dev/null and b/src/images/nuage.png differ diff --git a/src/images/red_square.png b/src/images/red_square.png new file mode 100644 index 0000000..c0d262b Binary files /dev/null and b/src/images/red_square.png differ diff --git a/src/images/sauts.jpg b/src/images/sauts.jpg new file mode 100644 index 0000000..a4acb60 Binary files /dev/null and b/src/images/sauts.jpg differ diff --git a/src/images/skyBackground.jpg b/src/images/skyBackground.jpg new file mode 100644 index 0000000..6ec28b9 Binary files /dev/null and b/src/images/skyBackground.jpg differ diff --git a/src/images/stickman_punch.png b/src/images/stickman_punch.png new file mode 100644 index 0000000..b1f6bbb Binary files /dev/null and b/src/images/stickman_punch.png differ diff --git a/src/images/stickman_right.png b/src/images/stickman_right.png new file mode 100644 index 0000000..05a90b3 Binary files /dev/null and b/src/images/stickman_right.png differ diff --git a/src/images/stickman_stand.png b/src/images/stickman_stand.png new file mode 100644 index 0000000..5ae8b1d Binary files /dev/null and b/src/images/stickman_stand.png differ diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..36e49f4 --- /dev/null +++ b/src/main.cpp @@ -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"<