├── README.md ├── assets ├── BOSS │ ├── boss_AI.cpp │ ├── boss_AI.h │ ├── boss_Controller.cpp │ ├── boss_Controller.h │ ├── boss_Head.cpp │ ├── boss_Head.h │ ├── boss_TailSegment.cpp │ ├── boss_TailSegment.h │ ├── boss_TailSegmentConnector.cpp │ └── boss_TailSegmentConnector.h ├── NAV │ ├── nav_graph.cpp │ ├── nav_graph.h │ ├── nav_path.cpp │ ├── nav_path.h │ ├── nav_point.cpp │ └── nav_point.h ├── animation.cpp ├── animation.h ├── background.cpp ├── background.h ├── missile.cpp ├── missile.h ├── physicsObj.cpp ├── physicsObj.h ├── player.cpp ├── player.h ├── projectile.cpp ├── projectile.h ├── terrain.cpp └── terrain.h ├── base.cpp ├── base.h ├── build.sh ├── defs.h ├── gamemaster.cpp ├── gamemaster.h ├── main.cpp ├── random.h └── resource ├── bg_volcano.png ├── boss_head.png ├── boss_head_alt.png ├── boss_tailsegment.png ├── boss_tailsegment_end.png ├── boss_tailsegmentconnector.png ├── exp.png ├── exp_large.png ├── fire.png ├── flare_01_0.png ├── hitmarker.png ├── laser_sprite.png ├── missile.png ├── missile_drop.png ├── player.png ├── point.png ├── projectile.png ├── terrain1.png └── terrain1_msk.png /README.md: -------------------------------------------------------------------------------- 1 | # SDL2-Game 2 | A small 2D, SDL2 Game written in C++ featuring destructive terrain, raycasts, tailphysics and more! 3 | 4 | ![bsp_img](https://i.imgur.com/bT7p3lS.jpg) 5 | 6 | This is what it looks like: https://www.youtube.com/watch?v=upb3DJJbQIM 7 | 8 | Only dependencies are the SDL2 and SDL2-image libraries. See [here](https://krother.gitbooks.io/objektorientierte-programmierung-mit-c/content/gitbook/SDL_unter_eclipse.html). 9 | 10 | All code was written by me and is public domain. 11 | 12 | # Controls 13 | - WASD to move the player 14 | - LMB to fire a projectile that destroys terrain 15 | - RMB to create terrain 16 | 17 | Healthbars and AI are missing, so you will have to control the boss/enemy yourself: 18 | - 1 for the Boss to shoot his laser 19 | - 2 for the Boss to shoot his rockets 20 | - 3 to toggle a continous rain of rockets 21 | 22 | # Sources for Artwork: 23 | - Projectiles: http://millionthvector.blogspot.de/p/free-sprites.html 24 | - Fire animation: https://opengameart.org/content/wgstudio-fire-animation-loop 25 | - Explosion animation: https://opengameart.org/content/explosion 26 | - Metal Structure: https://opengameart.org/content/metal-grate-texture 27 | - Metal Supports: https://opengameart.org/content/brown-metal-trim (And similar from the same author) 28 | - Laser Flare: http://www.photos-public-domain.com/2011/11/19/bright-sun/ 29 | - Destructible Rock texture: textures.com 30 | - Everything Else: Myself 31 | 32 | # Documentation: 33 | 34 | ### Root directory 35 | 36 | The root directory contains what you might consider to be the 'game engine': 37 | - *defs.h*: All constant values used across other files, including file directories, window size etc. 38 | - *random.h*: Inline header file to generate random numbers. 39 | - *main.cpp*: Runs the start-method in gamemaster.cpp. That's all. 40 | - *gamemaster.cpp/.h*: Contains the base 'game-loop'. Continously clears, draws and updates all relevant objects. 41 | - *base.cpp/.h*: Fundamental classes/functions used and inherited throughout the project. This includes: Timer, Vector2, Camera, GameWindow, Object, Image, AdvImage. Object being the base class for all Objects drawn on screen. 42 | 43 | 44 | ### Assets directory 45 | 46 | Includes more specialized files. All of these inherit from either the Object or Image class. 47 | - *animation*: Class for a spritesheet-animation. Used by explosion or fire aniamtions, aswells as the player sprite. 48 | - *background*: Parallax background image that scrolls relative to player position and level size. 49 | - *terrain*: Actual level. Pixel collision and destructible terrain are handled here. 50 | - *missile*: The missiles that the boss spawns on his second attack. 51 | - *physicsObj*: Base class for all physics-based Objects. 52 | - *player*: The player. 53 | - *projectile*: Base class for physics-based projectiles. 54 | 55 | 56 | ### assets/NAV directory 57 | 58 | Point- and Path-classes used for the Navigation of the Boss. 59 | Paths can have ease-in/-out aswell as linear, bezier or sine-curve interpolations. 60 | nav_graph creates and includes preset paths for the boss to navigate along. 61 | 62 | 63 | ### assets/BOSS directory 64 | 65 | All classes concerning the boss. 66 | - *boss_AI*: Main wrapper for the entire thing. Looks at what attack the boss is doing and executes it by calling boss_Controller methods. 67 | - *boss_Controller*: Handles boss idle animations, laser animations etc. Second layer of complexity wrapping. 68 | - *boss_Head*: The main bulk of the boss' head. 69 | - *boss_TailSegment*: The small segments that constitute the boss' tail. Each segment has an angular and positional velocity aswell as an angular and positional acceleration. At a certain self-positonal-velocity the segments will accelerate towards the vector of said velocity. If this velocity is smaller than the given threshhold, the segments will accelerate towards their default position. 70 | - *boss_TailSegmentConnector*: The red connectors between segments. 71 | 72 | 73 | Certain elements are heavily inspired by the Supreme Jeh'Oul bossfight from Wings of Vi ([this one](https://www.youtube.com/watch?v=VD-y3-hH1do)). 74 | -------------------------------------------------------------------------------- /assets/BOSS/boss_AI.cpp: -------------------------------------------------------------------------------- 1 | #include "boss_AI.h" 2 | 3 | boss_AI::boss_AI(GameWindow* gw, terrain* ter) : Object(gw) { 4 | boss = new boss_Controller(gw, ter); 5 | busy = false; 6 | currentAttack = NONE; 7 | innerStage = 0; 8 | this->ter = ter; 9 | for(int i=0; i<30; i++) { 10 | missiles.push_back(new missile(this->gw, 0, 0, ROCKET_SPEED, 0, false)); 11 | missiles.at(i)->dead = true; 12 | } 13 | rocketDropTimer.start(); 14 | spawnRockets = false; 15 | } 16 | 17 | boss_AI::~boss_AI() { 18 | } 19 | 20 | void boss_AI::update() { 21 | boss->update(); 22 | for(int i = missiles.size()-1; i>=0; i--) { 23 | missiles.at(i)->update(ter); 24 | } 25 | for(int i = rockets_drop.size()-1; i>=0; i--) { 26 | rockets_drop.at(i)->update(ter); 27 | if(rockets_drop.at(i)->explosion->dead) { 28 | missile* m = rockets_drop.at(i); 29 | rockets_drop.erase(rockets_drop.begin() + i); 30 | delete m; 31 | i--; 32 | } 33 | } 34 | 35 | if(rocketDropTimer.elapsedTime() > 500 && spawnRockets) { 36 | missile* m = new missile(this->gw, getRandInteger(300,LEVELWIDTH), 100, 0, ROCKET_SPEED*3, true); 37 | rockets_drop.push_back(m); 38 | rocketDropTimer.start(); 39 | } 40 | 41 | switch(currentAttack) { 42 | case LASER : { 43 | if(innerStage<=0) { //Move boss to position 44 | boss->bossNavigator->moveTo(TL); 45 | innerStage = 1; 46 | } 47 | else if(innerStage==1 && !boss->bossNavigator->isBusy()) { //Boss at position, go to next stage 48 | innerTimer.start(); 49 | innerStage = 2; 50 | } 51 | else if(innerStage==2) { //Move head to -20deg 52 | boss->head->setTilt(Lerp(0, -20, innerTimer.elapsedTime()/200.0f)); 53 | if(innerTimer.elapsedTime()>=200.0) { 54 | boss->laserOn = true; 55 | boss->head->laser = true; 56 | boss->setTailWiggle(1.5f, 1.2f); 57 | innerTimer.start(); 58 | innerStage = 3; 59 | } 60 | } 61 | else if(innerStage==3) { //Move laser up to down 62 | boss->head->setTilt(Lerp(-20, 60, innerTimer.elapsedTime()/BOSS_LASER_DURATION)); 63 | if(innerTimer.elapsedTime()>=BOSS_LASER_DURATION) { 64 | innerTimer.start(); 65 | innerStage = 4; 66 | } 67 | } 68 | else if(innerStage==4) { //Move laser back up 69 | boss->head->setTilt(Lerp(60, -20, innerTimer.elapsedTime()/BOSS_LASER_DURATION)); 70 | if(innerTimer.elapsedTime()>=BOSS_LASER_DURATION) { 71 | boss->laserOn = false; 72 | boss->head->laser = false; 73 | innerTimer.start(); 74 | boss->setTailWiggle(1.0f, 1.0f); 75 | boss->bossNavigator->moveTo(OUT); 76 | innerStage = 5; 77 | } 78 | } 79 | else if(innerStage==5) { //Move head to default position and bugger off 80 | boss->head->setTilt(Lerp(-20, 0, innerTimer.elapsedTime()/500.0f)); 81 | if(!boss->bossNavigator->isBusy()) innerStage = 6; 82 | } 83 | else if(innerStage==6) { //Boss arrived outside, end attack 84 | launchAttack(NONE); 85 | } 86 | break; 87 | } 88 | 89 | case ROCKETS : { 90 | if(innerStage<=0) { //Move boss to position 91 | boss->bossNavigator->moveTo(TL2); 92 | innerStage = 1; 93 | } 94 | else if(innerStage==1 && !boss->bossNavigator->isBusy()) { //Increase Tail movement 95 | boss->setTailWiggle(2.0f, 1.0f); 96 | boss->head->setIdleOffsetMul(5.0, 2.0); 97 | innerTimer.start(); 98 | //spawn rockets 99 | Vector2 spawnPos; 100 | spawnPos.set(-530, 700); 101 | for(int i=0; isetPos(spawnPos); spawnPos.y += 80; missiles.at(i)->reset();} 102 | spawnPos.set(-930, 200); 103 | for(int i=missiles.size()/3; i<2*missiles.size()/3; i++) {missiles.at(i)->setPos(spawnPos); spawnPos.y += 80; missiles.at(i)->reset();} 104 | spawnPos.set(-1330, 700); 105 | for(int i=2*missiles.size()/3; isetPos(spawnPos); spawnPos.y += 80; missiles.at(i)->reset();} 106 | innerStage = 2; 107 | } 108 | else if(innerStage==2 && innerTimer.elapsedTime()>5000.0f) { //bugger off 109 | boss->setTailWiggle(1.0f, 1.0f); 110 | boss->head->setIdleOffsetMul(1.0, 1.0); 111 | boss->bossNavigator->moveTo(OUT); 112 | innerStage = 5; 113 | innerTimer.start(); 114 | } 115 | else if(innerStage==5) { //Move head to default position and bugger off 116 | boss->head->setTilt(Lerp(0, -120, innerTimer.elapsedTime()/500.0f)); 117 | if(!boss->bossNavigator->isBusy()) innerStage = 6; 118 | } 119 | else if(innerStage==6 && !boss->bossNavigator->isBusy()) { //Boss arrived outside, end attack 120 | boss->head->setTilt(0); 121 | launchAttack(NONE); 122 | } 123 | break; 124 | } 125 | 126 | default : { 127 | break; 128 | } 129 | 130 | } 131 | 132 | } 133 | 134 | void boss_AI::launchAttack(ATTACKS a) { 135 | currentAttack = a; 136 | innerStage = 0; 137 | } 138 | 139 | void boss_AI::draw() { 140 | for(int i = missiles.size()-1; i>=0; i--) { 141 | missiles.at(i)->draw(); 142 | } 143 | for(int i = rockets_drop.size()-1; i>=0; i--) { 144 | rockets_drop.at(i)->draw(); 145 | } 146 | boss->draw(); 147 | } 148 | -------------------------------------------------------------------------------- /assets/BOSS/boss_AI.h: -------------------------------------------------------------------------------- 1 | #ifndef BOSS_AI_H 2 | #define BOSS_AI_H 3 | 4 | #include "boss_Controller.h" 5 | #include "../../random.h" 6 | #include "../missile.h" 7 | #include 8 | 9 | enum ATTACKS {LASER, ROCKETS, NONE}; 10 | 11 | class boss_AI : Object { 12 | private: 13 | vector missiles; 14 | vector rockets_drop; 15 | Timer innerTimer; 16 | Timer rocketDropTimer; 17 | bool busy; 18 | ATTACKS currentAttack; 19 | int innerStage; 20 | boss_Controller* boss; 21 | terrain* ter; 22 | 23 | void laser(); 24 | 25 | public: 26 | bool spawnRockets; 27 | bool isBusy(); 28 | void update(); 29 | void draw(); 30 | void launchAttack(ATTACKS a); 31 | boss_AI(GameWindow* gw, terrain* ter); 32 | ~boss_AI(); 33 | }; 34 | 35 | 36 | 37 | #endif // BOSS_AI_H 38 | -------------------------------------------------------------------------------- /assets/BOSS/boss_Controller.cpp: -------------------------------------------------------------------------------- 1 | #include "boss_Controller.h" 2 | 3 | boss_Controller::boss_Controller(GameWindow* gw, terrain* ter) : Object(gw) { 4 | bossNavigator = new nav_graph(this); 5 | this->ter = ter; 6 | tailOffset.set(-100, 30); 7 | laserOffset.set(120, 160); 8 | this->head = new boss_Head(gw); 9 | this->tail = new boss_TailSegment(gw); 10 | this->tail->buildTail(6, NULL); 11 | tailWiggleTimer.start(); 12 | laser = new AdvImage(gw); 13 | laser->loadTexture(LASER_SPRITE); 14 | laser->center = new SDL_Point(); 15 | laser_impact = new animation(gw); 16 | laser_impact2 = new animation(gw); 17 | laser_impact->setAnim(LASER_IMPACT_SPRITE, 1, 4, 100.0f, 1); 18 | laser_impact->loop = true; 19 | laser_impact2->setAnim(LASER_IMPACT_SPRITE, 1, 4, 90.0f, 1); 20 | laser_impact2->loop = true; 21 | laser_flare = new AdvImage(gw); 22 | laser_flare->loadTexture(LASER_IMPACT_SPRITE); 23 | idleAngle = 0; 24 | laserOn = false; 25 | tailWiggleAmplitude = 1; //These values aremultiplied with base values from defs.h 26 | tailWiggleSpeed = 1; 27 | } 28 | 29 | boss_Controller::~boss_Controller() { 30 | } 31 | 32 | void boss_Controller::update() { 33 | this->head->setPos(pos); 34 | this->head->update(); 35 | 36 | updateTail(); //update head before this 37 | 38 | if(laserOn) updateLaser(); 39 | 40 | bossNavigator->update(); 41 | } 42 | 43 | void boss_Controller::draw() { 44 | this->tail->draw(); 45 | this->head->draw(); 46 | if(laserOn) { 47 | this->laser->draw(); 48 | laser_flare->draw(); 49 | } 50 | } 51 | 52 | void boss_Controller::updateLaser() { 53 | this->laser->setPos(pos.x+laserOffset.x, pos.y+laserOffset.y); 54 | this->laser->angle = this->head->angle + 90; 55 | Vector2 lookat; 56 | lookat.fromAngle(laser->angle); 57 | Vector2 hit = ter->raycast(laser->getPos(), lookat, 0.1f); 58 | laser_flare->setPosCenter(hit); 59 | laser_flare->update(); 60 | laser_impact->setPos(hit.x-laser_impact->getRect().w/2, hit.y-laser_impact->getRect().h+20); 61 | laser_impact2->setPos(hit.x-laser_impact->getRect().w/2, hit.y-laser_impact->getRect().h+20); 62 | this->laser->setFromTo(laser->getPos(), hit, true); 63 | this->laser->update(); 64 | this->laser_impact->update(); 65 | this->laser_impact2->update(); 66 | this->laser_flare->angle += 50; 67 | } 68 | 69 | void boss_Controller::updateTail() { 70 | this->tail->angle = BOSS_DEFAULT_TAIL_ROTATION + tailWiggleAmplitude*BOSS_TAILWIGGLE_AMPLITUDE * sin(tailWiggleTimer.elapsedTime()*BOSS_TAILWIGGLE_SPEED*tailWiggleSpeed); 71 | Vector2 headCenter; 72 | headCenter.x = head->getPos().x + head->getRect().w/2; 73 | headCenter.y = head->getPos().y + head->getRect().h/2; 74 | Vector2 tmp_tailPos = tailOffset; 75 | tmp_tailPos.rotate(head->angle); 76 | tmp_tailPos.add(headCenter); 77 | this->tail->setPos(tmp_tailPos); 78 | this->tail->update(); 79 | } 80 | 81 | void boss_Controller::setTailWiggle(float Amp, float Speed) { 82 | tailWiggleAmplitude = Amp; 83 | tailWiggleSpeed = Speed; 84 | } 85 | -------------------------------------------------------------------------------- /assets/BOSS/boss_Controller.h: -------------------------------------------------------------------------------- 1 | #ifndef BOSS_CONTROLLER_H 2 | #define BOSS_CONTROLLER_H 3 | 4 | #include "boss_Head.h" 5 | #include "boss_TailSegment.h" 6 | #include "../terrain.h" 7 | #include "../animation.h" 8 | #include "../NAV/nav_graph.h" 9 | 10 | class boss_Controller : public Object { 11 | private: 12 | terrain* ter; 13 | float tailWiggleAmplitude; 14 | float tailWiggleSpeed; 15 | Timer tailWiggleTimer; 16 | Vector2 tailOffset; 17 | Vector2 laserOffset; 18 | double idleAngle; 19 | boss_TailSegment* tail; 20 | AdvImage* laser; 21 | animation* laser_impact; 22 | animation* laser_impact2; 23 | AdvImage* laser_flare; 24 | void updateLaser(); 25 | void updateTail(); 26 | public: 27 | bool laserOn; 28 | nav_graph* bossNavigator; 29 | boss_Head* head; 30 | void draw(); 31 | void update(); 32 | boss_Controller(GameWindow* gw, terrain* ter); 33 | ~boss_Controller(); 34 | void setTailWiggle(float Amp, float Speed); 35 | }; 36 | 37 | 38 | 39 | #endif // BOSS_CONTROLLER_H 40 | -------------------------------------------------------------------------------- /assets/BOSS/boss_Head.cpp: -------------------------------------------------------------------------------- 1 | #include "boss_Head.h" 2 | 3 | boss_Head::boss_Head(GameWindow* gw) : AdvImage(gw) { 4 | this->loadTexture(BOSS_HEAD_SPRITE); 5 | idleAngle = 0; 6 | idleOffsetMul.set(1,1); 7 | alt = new AdvImage(gw); 8 | alt->loadTexture(BOSS_HEAD_SPRITE_ALTERNATIVE); 9 | laser = false; 10 | } 11 | 12 | boss_Head::~boss_Head() { 13 | } 14 | 15 | void boss_Head::update() { 16 | Vector2 headPos = pos; 17 | idleAngle += BOSS_IDLEANIMATION_SPEED; 18 | idleOffset.fromAngle(idleAngle); 19 | idleOffset.mul(BOSS_IDLEANIMATION_RADIUS); 20 | idleOffset.x *= idleOffsetMul.x; 21 | idleOffset.y *= idleOffsetMul.y; 22 | headPos.add(idleOffset); 23 | this->setPos(headPos); 24 | 25 | alt->angle = this->angle; 26 | alt->setPos(pos); 27 | alt->update(); 28 | 29 | AdvImage::update(); 30 | } 31 | 32 | void boss_Head::tilt(double angle) { 33 | this->angle += angle; 34 | } 35 | 36 | void boss_Head::setTilt(double angle) { 37 | this->angle = angle; 38 | } 39 | 40 | void boss_Head::setIdleOffsetMul(float x, float y) { 41 | idleOffsetMul.set(x,y); 42 | } 43 | 44 | void boss_Head::draw() { 45 | if(laser) alt->draw(); 46 | else AdvImage::draw(); 47 | } 48 | -------------------------------------------------------------------------------- /assets/BOSS/boss_Head.h: -------------------------------------------------------------------------------- 1 | #ifndef BOSS_HEAD_H 2 | #define BOSS_HEAD_H 3 | 4 | #include "../../base.h" 5 | 6 | class boss_Head : public AdvImage { 7 | private: 8 | AdvImage* alt; 9 | double idleAngle; 10 | Vector2 idleOffset; 11 | Vector2 idleOffsetMul; 12 | public: 13 | bool laser; 14 | boss_Head(GameWindow* gw); 15 | ~boss_Head(); 16 | void update(); 17 | void tilt(double angle); 18 | void setTilt(double angle); 19 | void setIdleOffsetMul(float x, float y); 20 | void draw(); 21 | }; 22 | 23 | 24 | 25 | #endif // BOSS_HEAD_H 26 | -------------------------------------------------------------------------------- /assets/BOSS/boss_TailSegment.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/assets/BOSS/boss_TailSegment.cpp -------------------------------------------------------------------------------- /assets/BOSS/boss_TailSegment.h: -------------------------------------------------------------------------------- 1 | #ifndef BOSS_TAILSEGMENT_H 2 | #define BOSS_TAILSEGMENT_H 3 | 4 | #include "../../base.h" 5 | #include "boss_TailSegmentConnector.h" 6 | 7 | class boss_TailSegment : public AdvImage { 8 | private: 9 | Vector2 intenPos(); 10 | double intenAngle(); 11 | Vector2 vel, acel; 12 | double Avel, Aacel; 13 | public: 14 | boss_TailSegmentConnector* connector; 15 | Vector2 getMidUpperPoint(); 16 | Vector2 getMidLowerPoint(); 17 | boss_TailSegment* previous; 18 | boss_TailSegment* next; 19 | void update(); 20 | void draw(); 21 | boss_TailSegment(GameWindow* gw); 22 | ~boss_TailSegment(); 23 | void buildTail(int num, boss_TailSegment* prev); 24 | }; 25 | 26 | 27 | 28 | #endif // BOSS_TAILSEGMENT_H 29 | -------------------------------------------------------------------------------- /assets/BOSS/boss_TailSegmentConnector.cpp: -------------------------------------------------------------------------------- 1 | #include "boss_TailSegmentConnector.h" 2 | 3 | boss_TailSegmentConnector::boss_TailSegmentConnector(GameWindow* gw) : AdvImage(gw) { 4 | this->center = new SDL_Point(); 5 | center->x = 0; 6 | center->y = 0; 7 | } 8 | 9 | boss_TailSegmentConnector::~boss_TailSegmentConnector() { 10 | } 11 | 12 | void boss_TailSegmentConnector::update(Vector2 from, Vector2 to) { 13 | this->setFromTo(from, to, true); 14 | AdvImage::update(); 15 | } 16 | -------------------------------------------------------------------------------- /assets/BOSS/boss_TailSegmentConnector.h: -------------------------------------------------------------------------------- 1 | #ifndef BOSS_TAILSEGMENTCONNECTOR_H 2 | #define BOSS_TAILSEGMENTCOONECTOR_H 3 | 4 | #include "../../base.h" 5 | 6 | class boss_TailSegmentConnector : public AdvImage { 7 | private: 8 | public: 9 | void update(Vector2 from, Vector2 to); 10 | boss_TailSegmentConnector(GameWindow* gw); 11 | ~boss_TailSegmentConnector(); 12 | }; 13 | 14 | 15 | 16 | #endif // BOSS_TAILSEGMENTCONNECTOR_H 17 | -------------------------------------------------------------------------------- /assets/NAV/nav_graph.cpp: -------------------------------------------------------------------------------- 1 | #include "nav_graph.h" 2 | 3 | nav_graph::nav_graph(Object* agent) { 4 | tl_in.set(-500, 1500); 5 | tl.set(130, 700); 6 | tl_out.set(130, -500); 7 | tl_in_control.set(500, 1200); 8 | 9 | tl_enter.init_bezier(tl_in, tl, tl_in_control, 0.01f, agent, false, true); 10 | tl_exit.init_sine(tl, tl_out, 170, 5, 0.005f, agent, true, false); 11 | 12 | tl2_out.set(-500, 800); 13 | tl2_out_control.set(0, 500); 14 | 15 | tl2_exit.init_bezier(tl, tl2_out, tl2_out_control, 0.02f, agent, true, false); 16 | 17 | //Example for linear: bl_t_tl.init_linear(bl, tl, 0.01f, agent, false, true); 18 | 19 | active = &tl_enter; 20 | location = OUT; 21 | } 22 | 23 | nav_graph::~nav_graph() { 24 | } 25 | 26 | void nav_graph::update() { 27 | active->update(); 28 | } 29 | 30 | void nav_graph::moveTo(locations loc) { 31 | switch(loc) { 32 | case TL : { 33 | traverse(&tl_enter); 34 | break; 35 | } 36 | case TL2 : { 37 | traverse(&tl_enter); 38 | break; 39 | } 40 | case OUT : { 41 | if(location==TL) traverse(&tl_exit); 42 | if(location==TL2) traverse(&tl2_exit); 43 | } 44 | } 45 | location = loc; 46 | } 47 | 48 | bool nav_graph::isBusy() { 49 | return active->isBusy(); 50 | } 51 | 52 | void nav_graph::traverse(nav_path* p) { 53 | p->traverse(); 54 | active = p; 55 | } 56 | -------------------------------------------------------------------------------- /assets/NAV/nav_graph.h: -------------------------------------------------------------------------------- 1 | #ifndef NAV_GRAPH_H 2 | #define NAV_GRAPH_H 3 | 4 | #include "nav_path.h" 5 | 6 | enum locations {TL, OUT, TL2}; 7 | 8 | class nav_graph { 9 | private: 10 | nav_path tl_enter; //bottom left to top left 11 | nav_path tl_exit; 12 | 13 | nav_path tl2_exit; //tl2 has same entry as tl 14 | 15 | Vector2 tl, tl_in, tl_out; 16 | Vector2 tl2_out, tl2_out_control; 17 | Vector2 tl_in_control; 18 | 19 | nav_path* active; 20 | locations location; 21 | 22 | void traverse(nav_path* p); 23 | public: 24 | nav_graph(Object* agent); 25 | ~nav_graph(); 26 | void moveTo(locations loc); 27 | void update(); 28 | bool isBusy(); 29 | }; 30 | 31 | 32 | 33 | #endif // NAV_POINT_H 34 | -------------------------------------------------------------------------------- /assets/NAV/nav_path.cpp: -------------------------------------------------------------------------------- 1 | #include "nav_path.h" 2 | 3 | nav_path::nav_path() { 4 | speed = 1; 5 | sine_amplitude = 1; 6 | sine_curveamount = 1; 7 | active = false; 8 | agent = NULL; 9 | mode = LINEAR; 10 | relPos = 0; 11 | easeIn = false; 12 | easeOut = false; 13 | } 14 | 15 | nav_path::~nav_path() { 16 | } 17 | 18 | void nav_path::init_linear(Vector2 start, Vector2 end, float speed, Object* agent, bool easeIn, bool easeOut) { 19 | this->agent = agent; 20 | this->speed = speed; 21 | this->start = start; 22 | this->end = end; 23 | this->mode = LINEAR; 24 | this->easeIn = easeIn; 25 | this->easeOut = easeOut; 26 | } 27 | 28 | void nav_path::init_bezier(Vector2 start, Vector2 end, Vector2 control, float speed, Object* agent, bool easeIn, bool easeOut) { 29 | init_linear(start, end, speed, agent, easeIn, easeOut); 30 | this->bezier_control = control; 31 | this->mode = BEZIER; 32 | } 33 | 34 | void nav_path::init_sine(Vector2 start, Vector2 end, float amp, float curveamount, float speed, Object* agent, bool easeIn, bool easeOut) { 35 | init_linear(start, end, speed, agent, easeIn, easeOut); 36 | this->sine_amplitude = amp; 37 | this->sine_curveamount = curveamount; 38 | this->mode = SINE; 39 | } 40 | 41 | void nav_path::traverse() { 42 | relPos = 0; 43 | active = true; 44 | } 45 | 46 | void nav_path::update() { 47 | if(!active) return; 48 | if(relPos>=1) active=false; 49 | 50 | switch(mode) { 51 | case LINEAR : { 52 | agent->setPos(Lerp(start, end, relPos)); 53 | break; 54 | } 55 | case SINE : { 56 | Vector2 target = end; 57 | target.sub(start); 58 | target.rotate(90); 59 | target.normalize(); 60 | target.mul(sine_amplitude*sin(relPos*sine_curveamount*2*PI)); 61 | target.add(Lerp(start, end, relPos)); 62 | agent->setPos(target); 63 | break; 64 | } 65 | case BEZIER : { 66 | agent->setPos(Bezier(start, bezier_control, end, relPos)); 67 | break; 68 | } 69 | } 70 | 71 | float speedMul = 1; 72 | if(easeIn && relPos1-EASE_OUT_PERC) speedMul = Lerp(1, 0.01, (relPos-(1-EASE_OUT_PERC))/(EASE_OUT_PERC)); 74 | relPos += speed*speedMul; 75 | } 76 | 77 | bool nav_path::isBusy() { 78 | return active; 79 | } 80 | -------------------------------------------------------------------------------- /assets/NAV/nav_path.h: -------------------------------------------------------------------------------- 1 | #ifndef NAV_PATH_H 2 | #define NAV_PATH_H 3 | 4 | #include "../../base.h" 5 | 6 | enum interpolation_mode {LINEAR, SINE, BEZIER}; 7 | 8 | class nav_path { 9 | private: 10 | float relPos; //Percentage positioning along the path 11 | float speed; 12 | float sine_amplitude; 13 | float sine_curveamount; 14 | Vector2 bezier_control; 15 | bool easeIn; 16 | bool easeOut; 17 | public: 18 | bool active; 19 | Object* agent; 20 | interpolation_mode mode; 21 | Vector2 start; 22 | Vector2 end; 23 | nav_path(); 24 | ~nav_path(); 25 | void init_linear(Vector2 start, Vector2 end, float speed, Object* agent, bool easeIn, bool easeOut); 26 | void init_sine(Vector2 start, Vector2 end, float amp, float mul, float speed, Object* agent, bool easeIn, bool easeOut); 27 | void init_bezier(Vector2 start, Vector2 end, Vector2 control, float speed, Object* agent, bool easeIn, bool easeOut); 28 | void traverse(); 29 | void update(); 30 | bool isBusy(); 31 | }; 32 | 33 | 34 | 35 | #endif // NAV_POINT_H 36 | -------------------------------------------------------------------------------- /assets/NAV/nav_point.cpp: -------------------------------------------------------------------------------- 1 | #include "nav_point.h" 2 | 3 | nav_point::nav_point() { 4 | } 5 | 6 | nav_point::~nav_point() { 7 | } 8 | -------------------------------------------------------------------------------- /assets/NAV/nav_point.h: -------------------------------------------------------------------------------- 1 | #ifndef NAV_POINT_H 2 | #define NAV_POINT_H 3 | 4 | #include "../../base.h" 5 | 6 | class nav_point { 7 | private: 8 | public: 9 | Vector2 point; 10 | nav_point(); 11 | ~nav_point(); 12 | }; 13 | 14 | 15 | 16 | #endif // NAV_POINT_H 17 | -------------------------------------------------------------------------------- /assets/animation.cpp: -------------------------------------------------------------------------------- 1 | #include "animation.h" 2 | 3 | void animation::setAnim(const char* path ,int rows, int columns, float deltaT, int direction) { 4 | this->loadTexture(path); 5 | this->dir = direction; 6 | this->rows = rows; 7 | this->cols = columns; 8 | this->deltaT = deltaT; 9 | this->maxFrame = rows*columns; 10 | if(deltaT<=0) this->manualOverride = true; 11 | 12 | this->texr.w = this->texr.w/cols; 13 | this->texr.h = this->texr.h/rows; 14 | this->srcRect.w = this->texr.w; 15 | this->srcRect.h = this->texr.h; 16 | setFrame(0); 17 | innerTimer->start(); 18 | } 19 | 20 | animation::animation(GameWindow* gw) : Image(gw) { 21 | manualOverride = dead = loop = false; 22 | dieOnEnd = true; 23 | innerTimer = new Timer(); 24 | cols = rows = dir = maxFrame = currFrame = 0; 25 | deltaT = 0; 26 | } 27 | 28 | animation::~animation() { 29 | delete innerTimer; 30 | } 31 | 32 | //Set the animation to a certain frame 33 | void animation::setFrame(int frameNum) { 34 | if(this->dir==0) { //from bottom right to top left (right to left) 35 | this->setFrame(maxFrame - (frameNum % maxFrame)); //this wont work... 36 | } 37 | if(this->dir==1) { //from top left to bottom right (left to right) 38 | this->srcRect.y = ((frameNum / cols) % rows) * this->texr.h; 39 | this->srcRect.x = (frameNum % cols) * this->texr.w; 40 | } 41 | } 42 | 43 | void animation::update() { 44 | if(dead) return; 45 | Image::update(); 46 | if(manualOverride) return; 47 | if(innerTimer->elapsedTime()>deltaT) { 48 | if(currFrame == maxFrame-1 && dieOnEnd && !dead) { 49 | dead = true; 50 | return; 51 | } 52 | currFrame = (currFrame + 1) % maxFrame; 53 | innerTimer->start(); 54 | } 55 | setFrame(currFrame); 56 | } 57 | 58 | void animation::setPos(float x, float y) { 59 | pos.set(x,y); 60 | } 61 | 62 | void animation::draw() { 63 | if(dead) return; 64 | gw->draw(this->tex, &srcRect, &texr); 65 | } 66 | 67 | void animation::reset() { 68 | dead = false; 69 | innerTimer->start(); 70 | currFrame = 0; 71 | setFrame(0); 72 | } 73 | -------------------------------------------------------------------------------- /assets/animation.h: -------------------------------------------------------------------------------- 1 | #ifndef ANIMATION_H 2 | #define ANIMATION_H 3 | 4 | #include "../base.h" 5 | 6 | class animation : public Image { 7 | private: 8 | Timer* innerTimer; 9 | int rows, cols, dir; 10 | float deltaT; 11 | int currFrame, maxFrame; 12 | SDL_Rect srcRect; 13 | public: 14 | bool loop; 15 | bool dieOnEnd; 16 | bool dead; 17 | bool manualOverride; 18 | void setFrame(int framenum); 19 | void setAnim(const char* path, int rows, int columns, float deltaT, int direction); 20 | void update(); 21 | animation(GameWindow* gw); 22 | ~animation(); 23 | void setPos(float x, float y); 24 | void draw(); 25 | void reset(); 26 | }; 27 | 28 | 29 | 30 | #endif // PLAYER_H 31 | -------------------------------------------------------------------------------- /assets/background.cpp: -------------------------------------------------------------------------------- 1 | #include "background.h" 2 | 3 | background::background(GameWindow* gw) : Image(gw) { 4 | moveDistance.x = -BGWIDTH + SWIDTH; //These should be negative numbers, as the background scrolls to the left 5 | moveDistance.y = -BGHEIGHT + SHEIGHT; 6 | } 7 | 8 | background::~background() {} 9 | 10 | void background::update(Vector2 ViewPortPos) { 11 | this->pos.x = Lerp(0, moveDistance.x, ViewPortPos.x/(LEVELWIDTH-SWIDTH)); 12 | this->pos.y = Lerp(0, moveDistance.y, ViewPortPos.y/(LEVELHEIGHT-SHEIGHT)); 13 | Image::update(); 14 | } 15 | 16 | void background::draw() { 17 | gw->drawOverride(this->tex, NULL, &texr); //Use drawOverride, because we consider the ViewPortOffset manually in update() 18 | } 19 | -------------------------------------------------------------------------------- /assets/background.h: -------------------------------------------------------------------------------- 1 | #ifndef BACKGROUND_H 2 | #define BACKGROUND_H 3 | 4 | #include "../base.h" 5 | 6 | class background : public Image { 7 | private: 8 | Vector2 moveDistance; 9 | public: 10 | background(GameWindow* gw); 11 | ~background(); 12 | void update(Vector2 CameraPos); 13 | void draw(); 14 | }; 15 | 16 | 17 | 18 | #endif // BACKGROUND_H 19 | -------------------------------------------------------------------------------- /assets/missile.cpp: -------------------------------------------------------------------------------- 1 | #include "missile.h" 2 | 3 | missile::missile(GameWindow* gw) : AdvImage(gw) { 4 | loadTexture(MISSILESPRITE); 5 | dead = false; 6 | terrainCollision = false; 7 | lifetime = 15000; //15 seconds 8 | lifeTimer.start(); 9 | trail = new animation(gw); 10 | trail->setAnim(FIRESPRITE, 5, 5, 0.3f, 1); 11 | trail->dieOnEnd = false; 12 | trail->loop = true; 13 | randomDrift.set(0.3*getRandDecimal(), 0.3*getRandDecimal()); 14 | randomDriftOffset = getRandInteger(0, 50000); 15 | randomDriftSpeed = getRandInteger(300, 800); 16 | flameTrail = true; 17 | straight = false; 18 | explosion = new animation(gw); 19 | explosion->setAnim(LARGEEXPLOSIONSPRITE, 4, 4, 25, 1); 20 | explosion->loop = false; 21 | explosion->dieOnEnd = true; 22 | hitMarker = new Image(gw); 23 | markHit = true; 24 | hitMarker->loadTexture(HITMARKER); 25 | } 26 | 27 | missile::missile(GameWindow* gw, int spawnX, int spawnY, float velX, float velY, bool drop) : AdvImage(gw) { 28 | if(drop) { 29 | terrainCollision = true; 30 | flameTrail = false; 31 | straight = true; 32 | loadTexture(MISSILEDROPSPRITE); 33 | hitMarker = new Image(gw); 34 | markHit = true; 35 | hitMarker->loadTexture(HITMARKER); 36 | } 37 | else { 38 | markHit = false; 39 | terrainCollision = false; 40 | flameTrail = true; 41 | straight = false; 42 | trail = new animation(gw); 43 | trail->setAnim(FIRESPRITE, 5, 5, 0.2f, 1); 44 | trail->dieOnEnd = false; 45 | trail->loop = true; 46 | randomDrift.set(0.3*getRandDecimal(), 0.3*getRandDecimal()); 47 | randomDriftOffset = getRandInteger(0, 50000); 48 | randomDriftSpeed = getRandInteger(100, 1000); 49 | loadTexture(MISSILESPRITE); 50 | } 51 | vel.x = velX; 52 | vel.y = velY; 53 | pos.x = spawnX; 54 | pos.y = spawnY; 55 | dead = false; 56 | lifetime = 15000; //15 seconds 57 | lifeTimer.start(); 58 | explosion = new animation(gw); 59 | explosion->setAnim(LARGEEXPLOSIONSPRITE, 4, 4, 25, 1); 60 | explosion->loop = false; 61 | explosion->dieOnEnd = true; 62 | } 63 | 64 | missile::~missile() { 65 | } 66 | 67 | void missile::update(terrain* ter) { 68 | if(lifeTimer.elapsedTime()>lifetime) dead=true; 69 | if(!dead && terrainCollision && ter->getSolid(pos.x, pos.y)) { 70 | explosion->setPos(pos.x, pos.y-75); 71 | explosion->reset(); 72 | dead = true; 73 | } 74 | if(dead && terrainCollision) { 75 | explosion->update(); 76 | return; 77 | } 78 | 79 | if(!straight) vel.y = randomDrift.y * sin(randomDriftOffset + lifeTimer.elapsedTime()/randomDriftSpeed); 80 | Vector2 def; 81 | def.set(1,0); 82 | this->angle = vel.angle(def); 83 | 84 | if(flameTrail) { 85 | trail->setPos(pos.x-60, pos.y-60); 86 | trail->update(); 87 | } 88 | 89 | if(markHit) { 90 | setHitMarker(ter); 91 | hitMarker->update(); 92 | } 93 | 94 | this->pos.add(vel); 95 | AdvImage::update(); 96 | } 97 | 98 | void missile::setPos(Vector2 pos) { 99 | this->pos = pos; 100 | } 101 | 102 | Vector2 missile::getPos() { 103 | return this->pos; 104 | } 105 | 106 | void missile::launch(Vector2 vel) { 107 | this->vel = vel; 108 | } 109 | 110 | void missile::draw() { 111 | if(dead && terrainCollision) { 112 | explosion->draw(); 113 | return; 114 | } 115 | if(flameTrail) trail->draw(); 116 | if(markHit) hitMarker->draw(); 117 | AdvImage::draw(); 118 | } 119 | 120 | void missile::reset() { 121 | lifeTimer.start(); 122 | dead = false; 123 | } 124 | 125 | void missile::setHitMarker(terrain* ter) { 126 | Vector2 markerPos = ter->raycast(pos, vel, 3.0f); 127 | markerPos.y -= hitMarker->getRect().h; 128 | hitMarker->setPos(markerPos); 129 | } 130 | -------------------------------------------------------------------------------- /assets/missile.h: -------------------------------------------------------------------------------- 1 | #ifndef MISSILE_H 2 | #define MISSILE_H 3 | 4 | #include "physicsObj.h" 5 | #include "animation.h" 6 | #include "../random.h" 7 | 8 | class missile : public AdvImage { 9 | private: 10 | Vector2 vel; 11 | Timer lifeTimer; 12 | animation* trail; 13 | Vector2 randomDrift; 14 | int randomDriftOffset; 15 | int randomDriftSpeed; 16 | Image* hitMarker; 17 | void setHitMarker(terrain* ter); 18 | public: 19 | animation* explosion; 20 | void update(terrain* ter); 21 | void draw(); 22 | missile(GameWindow* gw); 23 | missile(GameWindow* gw, int spawnX, int spawnY, float velX, float velY, bool drop); 24 | ~missile(); 25 | void reset(); 26 | void launch(Vector2 vel); 27 | bool dead; 28 | void setPos(Vector2 pos); 29 | Vector2 getPos(); 30 | bool terrainCollision; 31 | bool flameTrail; 32 | bool straight; 33 | bool markHit; 34 | float lifetime; 35 | }; 36 | 37 | 38 | 39 | #endif // MISSILE_H 40 | -------------------------------------------------------------------------------- /assets/physicsObj.cpp: -------------------------------------------------------------------------------- 1 | #include "physicsObj.h" 2 | 3 | physicsObj::physicsObj(GameWindow* gw) : Object(gw) { 4 | this->gravity = true; 5 | this->friction = true; 6 | col.set(42,42); 7 | } 8 | 9 | void physicsObj::update(terrain* ter) { 10 | if(grounded(ter) && vel.y>0) vel.y=0; //Ground collision 11 | if(leftCol(ter) && vel.x<0) vel.x=0; //Left collision 12 | if(rightCol(ter) && vel.y>0) vel.x=0; //Right collision 13 | 14 | 15 | this->pos.add(vel); 16 | if(this->friction) vel.mul(FRICTION); 17 | if(gravity) vel.y += GRAVITY; 18 | } 19 | 20 | void physicsObj::accelerate(float x, float y){ 21 | vel.x += x; 22 | vel.y += y; 23 | } 24 | 25 | void physicsObj::setCol(float x, float y) { 26 | col.set(x,y); 27 | } 28 | 29 | bool physicsObj::grounded(terrain* ter) { 30 | if(ter->getSolid((int)(pos.x+col.x-1), (int)(pos.y+col.y))) return true; //bottom right 31 | else if(ter->getSolid((int)(pos.x+1), (int)(pos.y+col.y))) return true; //bottom left 32 | return false; 33 | } 34 | 35 | bool physicsObj::leftCol(terrain* ter) { 36 | if(ter->getSolid((int)(pos.x), (int)(pos.y+col.y-1))) return true; //bottom left 37 | else if(ter->getSolid((int)(pos.x), (int)(pos.y))) return true; //top left 38 | return false; 39 | } 40 | 41 | bool physicsObj::rightCol(terrain* ter) { 42 | if(ter->getSolid((int)(pos.x+col.x), (int)(pos.y+col.y-1))) return true; //bottom right 43 | else if(ter->getSolid((int)(pos.x+col.x), (int)(pos.y))) return true; //top right 44 | return false; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /assets/physicsObj.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICSOBJ_H 2 | #define PHYSICSOBJ_H 3 | 4 | #include "../base.h" 5 | #include "terrain.h" 6 | 7 | class physicsObj : public Object { 8 | protected: 9 | Vector2 col; 10 | Vector2 vel; 11 | public: 12 | void setCol(float x, float y); 13 | physicsObj(GameWindow* gw); 14 | //~physicsObj(); 15 | void update(terrain* ter); 16 | void accelerate(float x, float y); 17 | bool gravity; 18 | bool friction; 19 | bool grounded(terrain* ter); 20 | bool leftCol(terrain* ter); 21 | bool rightCol(terrain* ter); 22 | }; 23 | 24 | 25 | 26 | #endif // PHYSICSOBJ_H 27 | -------------------------------------------------------------------------------- /assets/player.cpp: -------------------------------------------------------------------------------- 1 | #include "player.h" 2 | 3 | player::player(GameWindow* gw) : physicsObj(gw) { 4 | playerSprite = new animation(gw); 5 | playerSprite->setAnim(PLAYERSPRITE, 3, 3, -1, 1); 6 | this->setCol(playerSprite->getRect().w, playerSprite->getRect().h); 7 | this->pos.set(200,500); 8 | } 9 | 10 | player::~player() { 11 | delete(playerSprite); 12 | } 13 | 14 | void player::update(terrain* ter) { 15 | physicsObj::update(ter); 16 | 17 | if(this->vel.x>MOVE_ANIM_VEL && this->vel.y>MOVE_ANIM_VEL) playerSprite->setFrame(2); 18 | else if(this->vel.x<-MOVE_ANIM_VEL && this->vel.y>MOVE_ANIM_VEL) playerSprite->setFrame(0); 19 | else if(this->vel.x>MOVE_ANIM_VEL) playerSprite->setFrame(5); 20 | else if(this->vel.x<-MOVE_ANIM_VEL) playerSprite->setFrame(3); 21 | else if(this->vel.y>MOVE_ANIM_VEL) playerSprite->setFrame(1); 22 | else playerSprite->setFrame(4); 23 | 24 | 25 | playerSprite->setPos(this->pos.x, this->pos.y); 26 | playerSprite->update(); 27 | } 28 | 29 | void player::draw() { 30 | playerSprite->draw(); 31 | } 32 | 33 | Vector2 player::getPos() { 34 | return this->pos; 35 | } 36 | -------------------------------------------------------------------------------- /assets/player.h: -------------------------------------------------------------------------------- 1 | #ifndef PLAYER_H 2 | #define PLAYER_H 3 | 4 | #include "physicsObj.h" 5 | #include "animation.h" 6 | 7 | class player : public physicsObj { 8 | private: 9 | animation* playerSprite; 10 | public: 11 | void update(terrain* ter); 12 | player(GameWindow* gw); 13 | ~player(); 14 | void draw(); 15 | Vector2 getPos(); 16 | }; 17 | 18 | 19 | 20 | #endif // PLAYER_H 21 | -------------------------------------------------------------------------------- /assets/projectile.cpp: -------------------------------------------------------------------------------- 1 | #include "projectile.h" 2 | 3 | projectile::projectile(GameWindow* gw) : physicsObj(gw) { 4 | projectileSprite = new Image(gw); 5 | projectileSprite->loadTexture(PROJECTILESPRITE); 6 | this->setCol(projectileSprite->getRect().w, projectileSprite->getRect().h); 7 | this->friction = false; 8 | this->gravity = false; 9 | dead = false; 10 | } 11 | 12 | projectile::~projectile() { 13 | delete(projectileSprite); 14 | } 15 | 16 | void projectile::update(terrain* ter) { 17 | if(dead) return; 18 | if(grounded(ter) || leftCol(ter) || rightCol(ter)) { 19 | ter->explode(pos.x+this->col.x/2, pos.y+this->col.y/2, 50); 20 | dead = true; 21 | } 22 | physicsObj::update(ter); 23 | projectileSprite->setPos(this->pos); 24 | projectileSprite->update(); 25 | } 26 | 27 | void projectile::draw() { 28 | projectileSprite->draw(); 29 | } 30 | 31 | void projectile::setPos(Vector2 pos) { 32 | this->pos = pos; 33 | } 34 | 35 | Vector2 projectile::getPos() { 36 | return this->pos; 37 | } 38 | 39 | void projectile::launch(Vector2 dir) { 40 | dir.add(-pos.x, -pos.y); 41 | dir.normalize(); 42 | dir.mul(8); //speed 43 | this->accelerate(dir.x, dir.y); 44 | } 45 | -------------------------------------------------------------------------------- /assets/projectile.h: -------------------------------------------------------------------------------- 1 | #ifndef PROJECTILE_H 2 | #define PROJECTILE_H 3 | 4 | #include "physicsObj.h" 5 | 6 | class projectile : public physicsObj { 7 | private: 8 | Image* projectileSprite; 9 | public: 10 | void update(terrain* ter); 11 | projectile(GameWindow* gw); 12 | ~projectile(); 13 | void draw(); 14 | void die(); 15 | void launch(Vector2 dir); 16 | bool dead; 17 | void setPos(Vector2 pos); 18 | Vector2 getPos(); 19 | }; 20 | 21 | 22 | 23 | #endif // PPRoJECTILE_H 24 | -------------------------------------------------------------------------------- /assets/terrain.cpp: -------------------------------------------------------------------------------- 1 | #include "terrain.h" 2 | 3 | terrain::terrain(GameWindow* gw) : Image(gw) { 4 | terMask = IMG_Load(TERRAIN1_MASK); 5 | sur = IMG_Load(TERRAIN1); 6 | updateTexture(); 7 | } 8 | 9 | terrain::~terrain() {} 10 | 11 | bool terrain::getSolid(int x, int y) { 12 | if(x>=LEVELWIDTH || y>=LEVELHEIGHT || x<=0 || y<=0) return true; 13 | SDL_LockSurface(sur); 14 | Uint32 color = get_pixel32(this->sur, x, y); 15 | SDL_UnlockSurface(sur); 16 | colorRGBA col; 17 | col.fromPixel32(color, sur->format); 18 | if(col.a>1) return true; 19 | return false; 20 | } 21 | 22 | bool terrain::getDestructible(int x, int y) { 23 | if(x>=LEVELWIDTH || y>=LEVELHEIGHT) return false; 24 | SDL_LockSurface(terMask); 25 | Uint32 color = get_pixel32(this->terMask, x, y); 26 | SDL_UnlockSurface(sur); 27 | colorRGBA col; 28 | col.fromPixel32(color, terMask->format); 29 | if(col.r>=255 && col.g==0 && col.b>=255) return false; 30 | return true; 31 | } 32 | 33 | void terrain::updateTexture() { 34 | this->tex = this->gw->textureFromSurface(sur); 35 | int w, h; 36 | SDL_QueryTexture(tex, NULL, NULL, &w, &h); 37 | this->texr.x = this->pos.x; texr.y = this->pos.y; texr.w = w; texr.h = h; 38 | } 39 | 40 | void terrain::explode(int x, int y, int r) { 41 | for(int i=x-r; i0 && 48 | j0 && getDestructible(i, j)) put_pixel32(sur, i, j, TRANSPARENT); 49 | } 50 | } 51 | updateTexture(); 52 | } 53 | 54 | void terrain::create_square(Vector2 location, int r) { 55 | int x = location.x; 56 | int y = location.y; 57 | for(int i=x-r; i0 && 60 | j0 && getDestructible(i, j)) put_pixel32(sur, i, j, EARTH); 61 | } 62 | } 63 | updateTexture(); 64 | } 65 | 66 | Vector2 terrain::raycast(Vector2 from, Vector2 dir, float skip) { 67 | dir.normalize(); 68 | dir.mul(skip); 69 | while(!getSolid(from.x, from.y)) { 70 | from.add(dir); 71 | } 72 | return from; 73 | } 74 | -------------------------------------------------------------------------------- /assets/terrain.h: -------------------------------------------------------------------------------- 1 | #ifndef TERRAIN_H 2 | #define TERRAIN_H 3 | 4 | #include "../base.h" 5 | 6 | class terrain : public Image { 7 | private: 8 | 9 | public: 10 | SDL_Surface *terMask; 11 | SDL_Surface *sur; 12 | terrain(GameWindow* gw); 13 | ~terrain(); 14 | bool getSolid(int x, int y); 15 | bool getDestructible(int x, int y); 16 | void updateTexture(); 17 | void explode(int x, int y, int r); 18 | void create_square(Vector2 location, int r); 19 | Vector2 raycast(Vector2 from, Vector2 dir, float accuracy); 20 | }; 21 | 22 | 23 | 24 | #endif // TERRAIN_H 25 | -------------------------------------------------------------------------------- /base.cpp: -------------------------------------------------------------------------------- 1 | #include "base.h" 2 | 3 | using namespace std; 4 | 5 | 6 | //=================GENERAL FUNCTIONS========================= 7 | 8 | //Round a number to three decimals 9 | double round_3dec(double val) { 10 | return round(val * 100.0 ) / 100.0; 11 | } 12 | 13 | //Get the color of a pixel on a surface 14 | Uint32 get_pixel32( SDL_Surface *surface, int x, int y ) 15 | { 16 | //Convert the pixels to 32 bit 17 | Uint32 *pixels = (Uint32 *)surface->pixels; 18 | 19 | //Get the requested pixel 20 | return pixels[ ( y * surface->w ) + x ]; 21 | } 22 | 23 | //Set a pixel of a surface to a certain color 24 | void put_pixel32( SDL_Surface *surface, int x, int y, Uint32 pixel ) 25 | { 26 | //Convert the pixels to 32 bit 27 | Uint32 *pixels = (Uint32 *)surface->pixels; 28 | 29 | //Set the pixel 30 | pixels[ ( y * surface->w ) + x ] = pixel; 31 | } 32 | 33 | //Convert pixel color from number to actual color 34 | void colorRGBA::fromPixel32(Uint32 pixel, const SDL_PixelFormat* format) { 35 | SDL_GetRGBA(pixel, format, &r, &g, &b, &a); 36 | } 37 | 38 | //Return smaller of two numbers 39 | int min(int a, int b) { 40 | if(ab) return a; 47 | return b; 48 | } 49 | 50 | //Clamp a number to a minimum and maximum 51 | float clamp(float value, float min, float max) { 52 | if(valuemax) return max; 54 | return value; 55 | } 56 | 57 | 58 | //=================TIMER METHODS========================= 59 | 60 | void Timer::start() { 61 | stime = (int)SDL_GetTicks(); 62 | } 63 | 64 | int Timer::elapsedTime() { 65 | return ((int)SDL_GetTicks()) - stime; 66 | } 67 | 68 | 69 | //=================CAMERA AND GAMEWINDOW METHODS========================= 70 | 71 | void Camera::setViewPortOffset(Vector2 vpo) { 72 | this->ViewPortOffset = vpo; 73 | } 74 | 75 | void Camera::follow(Vector2 pos) { 76 | centerOn(Lerp(getCenter(), pos, CAMERASMOOTHING)); 77 | } 78 | 79 | void Camera::centerOn(Vector2 pos) { 80 | this->ViewPortOffset.x = clamp(pos.x - SWIDTH/2, 0, LEVELWIDTH-SWIDTH); 81 | this->ViewPortOffset.y = clamp(pos.y - SHEIGHT/2, 0, LEVELHEIGHT-SHEIGHT); 82 | } 83 | 84 | Vector2 Camera::getCenter() { 85 | Vector2 ret; 86 | ret.set(ViewPortOffset.x + SWIDTH/2, ViewPortOffset.y + SHEIGHT/2); 87 | return ret; 88 | } 89 | 90 | GameWindow::GameWindow(void) { 91 | renderer = NULL; 92 | win = NULL; 93 | camera = NULL; 94 | drawrect = NULL; 95 | } 96 | 97 | int GameWindow::init() { 98 | if (SDL_Init(SDL_INIT_VIDEO) < 0) return 0; 99 | win = SDL_CreateWindow(WINDOWNAME, 100, 100, SWIDTH, SHEIGHT, 0); 100 | renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED); 101 | camera = new Camera(); 102 | camera->ViewPortOffset.x = camera->ViewPortOffset.y = 0; 103 | camera->ViewPortOffset.y = 300; 104 | drawrect = new SDL_Rect(); 105 | return 1; 106 | } 107 | 108 | void GameWindow::draw(SDL_Texture* tex, const SDL_Rect* srcrect, const SDL_Rect* dstrect) 109 | { 110 | drawrect->w = dstrect->w; 111 | drawrect->h = dstrect->h; 112 | drawrect->x = dstrect->x - camera->ViewPortOffset.x; 113 | drawrect->y = dstrect->y - camera->ViewPortOffset.y; 114 | SDL_RenderCopy(this->renderer, tex, srcrect, drawrect); 115 | } 116 | 117 | void GameWindow::draw(SDL_Texture* tex, const SDL_Rect* srcrect, const SDL_Rect* dstrect, const double angle, const SDL_Point* center, const SDL_RendererFlip flip) { 118 | drawrect->w = dstrect->w; 119 | drawrect->h = dstrect->h; 120 | drawrect->x = dstrect->x - camera->ViewPortOffset.x; 121 | drawrect->y = dstrect->y - camera->ViewPortOffset.y; 122 | SDL_RenderCopyEx(this->renderer, tex, srcrect, drawrect, angle, center, flip); 123 | } 124 | 125 | //The camera viewPortOffset will not be considered with the override functions 126 | void GameWindow::drawOverride(SDL_Texture* tex, const SDL_Rect* srcrect, const SDL_Rect* dstrect) 127 | { 128 | SDL_RenderCopy(this->renderer, tex, srcrect, dstrect); 129 | } 130 | 131 | void GameWindow::drawOverride(SDL_Texture* tex, const SDL_Rect* srcrect, const SDL_Rect* dstrect, const double angle, const SDL_Point* center, const SDL_RendererFlip flip) { 132 | SDL_RenderCopyEx(this->renderer, tex, srcrect, dstrect, angle, center, flip); 133 | } 134 | 135 | //Convert a Surface to a Texture 136 | SDL_Texture* GameWindow::textureFromSurface(SDL_Surface* sur) { 137 | return SDL_CreateTextureFromSurface(this->renderer, sur); 138 | } 139 | 140 | Vector2 GameWindow::getMousePosition() { 141 | Vector2 ret; 142 | int mx, my; 143 | SDL_GetMouseState(&mx, &my); 144 | ret.x = mx + camera->ViewPortOffset.x; 145 | ret.y = my + camera->ViewPortOffset.y; 146 | return ret; 147 | } 148 | 149 | void GameWindow::clear() { 150 | SDL_RenderClear(renderer); 151 | } 152 | 153 | void GameWindow::present() { 154 | SDL_RenderPresent(renderer); 155 | } 156 | 157 | 158 | //=================VECTOR2 METHODS========================= 159 | 160 | Vector2::Vector2() { 161 | this->x = this->y = 0; 162 | } 163 | 164 | Vector2::Vector2(float x, float y) { 165 | this->x = x; 166 | this->y = y; 167 | } 168 | 169 | void Vector2::add(Vector2 v) { 170 | this->x += v.x; 171 | this->y += v.y; 172 | } 173 | 174 | void Vector2::add(float x, float y) { 175 | this->x += x; 176 | this->y += y; 177 | } 178 | 179 | void Vector2::sub(Vector2 v) { 180 | this->x -= v.x; 181 | this->y -= v.y; 182 | } 183 | 184 | void Vector2::sub(float x, float y) { 185 | this->x -= x; 186 | this->y -= y; 187 | } 188 | 189 | void Vector2::mul(float f) { 190 | this->x *= f; 191 | this->y *= f; 192 | } 193 | 194 | Vector2 Vector2::mul_N(float f) { 195 | Vector2 ret; 196 | ret.x = this->x*f; 197 | ret.y = this->y*f; 198 | return ret; 199 | } 200 | 201 | float Vector2::length() { 202 | return sqrt(x*x+y*y); 203 | } 204 | 205 | void Vector2::normalize() { 206 | float l = length(); 207 | x = x/l; 208 | y = y/l; 209 | } 210 | 211 | double Vector2::angle(Vector2 v) { //Note that this function returns DEG 212 | double dot = this->x*v.x + this->y*v.y; 213 | double det = this->x*v.y - this->y*v.x; 214 | double ret = atan2(det, dot); 215 | ret *= (180.0/PI); 216 | while(ret<0) ret+=360; 217 | while(ret>360) ret-=360; 218 | return ret; 219 | } 220 | 221 | void Vector2::set(float x, float y) { 222 | this->x = x; 223 | this->y = y; 224 | } 225 | 226 | void Vector2::fromAngle(double angle) { //Note that this function takes DEG arguments 227 | this->x = round_3dec(sin(angle*(PI/180.0))); 228 | this->y = round_3dec(cos((180-angle)*(PI/180.0))); //I honestly have no clue why I have to do 180-angle here, but it only works that way :D 229 | this->normalize(); 230 | } 231 | 232 | void Vector2::rotate(double angle) { //takes deg argument 233 | angle = angle*(PI/180.0); 234 | float newX, newY; 235 | newX = x * cos(angle) - y * sin(angle); 236 | newY = x * sin(angle) + y * cos(angle); 237 | x = newX; 238 | y = newY; 239 | } 240 | 241 | //This is just a basic bezier function: http://answers.unity3d.com/questions/12689/moving-an-object-along-a-bezier-curve.html 242 | Vector2 Bezier(Vector2 start, Vector2 control, Vector2 end, float t) { 243 | start.mul(((1-t)*(1-t))); 244 | control.mul(2 * t * (1 - t)); 245 | end.mul((t * t)); 246 | start.add(control); 247 | start.add(end); 248 | return start; 249 | } 250 | 251 | //Interpolates a Vector by value t 252 | Vector2 Lerp(Vector2 start, Vector2 end, float t) { 253 | if(t<=0) return start; 254 | if(t>=1) return end; 255 | end.sub(start); //Vector from start to end 256 | end.mul(t); 257 | end.add(start); 258 | return end; 259 | } 260 | 261 | //Interpolates a float by value t 262 | float Lerp(float start, float end, float t) { 263 | if(t<=0) return start; 264 | if(t>=1) return end; 265 | return (end-start)*t + start; 266 | } 267 | 268 | 269 | //=================OBJECT METHODS========================= 270 | 271 | Object::Object(GameWindow* gw) { 272 | this->tag = DEFAULTTAG; 273 | this->gw = gw; 274 | } 275 | 276 | Object::~Object() {} 277 | 278 | void Object::draw() { 279 | } 280 | 281 | void Object::init() { 282 | cout<<"Object Initialized"<pos.x = pos.x; 287 | this->pos.y = pos.y; 288 | } 289 | 290 | void Object::setPos(int x, int y) { 291 | this->pos.x = x; 292 | this->pos.y = y; 293 | } 294 | 295 | Vector2 Object::getPos() { 296 | return pos; 297 | } 298 | 299 | 300 | //=================IMAGE METHODS========================= 301 | 302 | Image::Image(GameWindow* gw) : Object(gw) { 303 | tex = NULL; 304 | scale = 1; 305 | } 306 | 307 | Image::~Image() { 308 | } 309 | 310 | void Image::loadTexture(const char* path) { 311 | this->tex = IMG_LoadTexture(this->gw->renderer, path); 312 | int w, h; 313 | SDL_QueryTexture(tex, NULL, NULL, &w, &h); 314 | this->texr.x = this->pos.x; texr.y = this->pos.y; texr.w = w; texr.h = h; 315 | } 316 | 317 | void Image::draw() { 318 | gw->draw(this->tex, NULL, &texr); 319 | } 320 | 321 | void Image::update() { 322 | texr.x = pos.x; 323 | texr.y = pos.y; 324 | } 325 | 326 | SDL_Rect Image::getRect() { 327 | return this->texr; 328 | } 329 | 330 | void Image::setHeight(int h) { 331 | texr.h = h; 332 | } 333 | 334 | void Image::setPosCenter(Vector2 pos) { 335 | this->pos.x = pos.x - texr.w/2; 336 | this->pos.y = pos.y - texr.h/2; 337 | } 338 | 339 | void Image::setPosCenter(int x, int y){ 340 | this->pos.x = x - texr.w/2; 341 | this->pos.y = y - texr.h/2; 342 | } 343 | 344 | 345 | //=================ADVIMAGE METHODS========================= 346 | 347 | AdvImage::AdvImage(GameWindow* gw) : Image(gw) { 348 | flip = SDL_FLIP_NONE; 349 | center = NULL; 350 | angle = 0; 351 | } 352 | 353 | AdvImage::~AdvImage() { 354 | } 355 | 356 | void AdvImage::draw() { 357 | gw->draw(this->tex, NULL, &texr, angle, center, flip); 358 | } 359 | 360 | void AdvImage::setFromTo(Vector2 from, Vector2 to, bool height) { 361 | if(height) { 362 | Vector2 ft; 363 | Vector2 down; 364 | down.y=1; 365 | down.x=0; 366 | ft.x = to.x - from.x; 367 | ft.y = to.y - from.y; 368 | ft.x = -ft.x; 369 | this->texr.h = ft.length(); 370 | this->angle = ft.angle(down); 371 | this->center->x = this->texr.w * 0.5f; 372 | this->pos = from; 373 | this->pos.x -= this->texr.w * 0.5f; 374 | } 375 | else { 376 | cout<<"setToFrom width not implemeted"< 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "defs.h" 12 | 13 | using namespace std; 14 | 15 | Uint32 get_pixel32( SDL_Surface *surface, int x, int y ); 16 | void put_pixel32( SDL_Surface *surface, int x, int y, Uint32 pixel ); 17 | double round_3dec(double val); 18 | float clamp(float value, float min, float max); 19 | 20 | class colorRGBA { 21 | public: 22 | Uint8 r; 23 | Uint8 g; 24 | Uint8 b; 25 | Uint8 a; 26 | void fromPixel32(Uint32 pixel, const SDL_PixelFormat* format); 27 | }; 28 | 29 | //==================================================================== 30 | 31 | class Timer { 32 | private: 33 | int stime; 34 | public: 35 | void start(); 36 | int elapsedTime(); 37 | }; 38 | 39 | //==================================================================== 40 | 41 | class Vector2 { 42 | public: 43 | float x, y; 44 | Vector2(); 45 | Vector2(float x, float y); 46 | void sub(Vector2 v); 47 | void sub(float x, float y); 48 | void add(Vector2 v); 49 | void add(float x, float y); 50 | void mul(float f); 51 | Vector2 mul_N(float f); 52 | void normalize(); 53 | float length(); 54 | double angle(Vector2 v); 55 | void set(float x, float y); 56 | void fromAngle(double angle); 57 | void rotate(double angle); 58 | }; 59 | 60 | Vector2 Bezier(Vector2 start, Vector2 control, Vector2 end, float t); 61 | 62 | Vector2 Lerp(Vector2 start, Vector2 end, float t); 63 | 64 | float Lerp(float start, float end, float t); 65 | 66 | //==================================================================== 67 | 68 | class Camera { 69 | public: 70 | Vector2 ViewPortOffset; 71 | void setViewPortOffset(Vector2 vpo); 72 | void centerOn(Vector2 pos); 73 | void follow(Vector2 pos); 74 | Vector2 getCenter(); 75 | }; 76 | 77 | class GameWindow { 78 | private: 79 | SDL_Rect* drawrect; 80 | public: 81 | Camera* camera; 82 | SDL_Window *win = NULL; 83 | SDL_Renderer *renderer = NULL; 84 | SDL_Texture* textureFromSurface(SDL_Surface* sur); 85 | void draw(SDL_Texture* tex, const SDL_Rect* srcrect, const SDL_Rect* dstrect); 86 | void draw(SDL_Texture* tex, const SDL_Rect* srcrect, const SDL_Rect* dstrect, const double angle, const SDL_Point* center, const SDL_RendererFlip flip); 87 | void drawOverride(SDL_Texture* tex, const SDL_Rect* srcrect, const SDL_Rect* dstrect); 88 | void drawOverride(SDL_Texture* tex, const SDL_Rect* srcrect, const SDL_Rect* dstrect, const double angle, const SDL_Point* center, const SDL_RendererFlip flip); 89 | Vector2 getMousePosition(); 90 | void clear(); 91 | void present(); 92 | GameWindow(); 93 | int init(); 94 | }; 95 | 96 | //==================================================================== 97 | 98 | class Object { 99 | protected: 100 | GameWindow* gw; 101 | char tag; 102 | Vector2 pos; 103 | public: 104 | void setPos(Vector2 pos); 105 | void setPos(int x, int y); 106 | Vector2 getPos(); 107 | void draw(); 108 | void init(); 109 | Object(GameWindow* gw); 110 | ~Object(); 111 | }; 112 | 113 | //==================================================================== 114 | 115 | class Image : public Object { 116 | protected: 117 | SDL_Texture* tex; 118 | SDL_Rect texr; 119 | public: 120 | float scale; 121 | SDL_Rect getRect(); 122 | void setPosCenter(Vector2 pos); 123 | void setPosCenter(int x, int y); 124 | void setHeight(int h); 125 | void draw(); 126 | void loadTexture(const char* path); 127 | void update(); 128 | Image(GameWindow* gw); 129 | ~Image(); 130 | }; 131 | 132 | //==================================================================== 133 | //AdvImage is an Image but with a rotation angle and point 134 | 135 | class AdvImage : public Image { 136 | protected: 137 | public: 138 | double angle; 139 | SDL_Point* center; 140 | SDL_RendererFlip flip; 141 | void draw(); 142 | void setFromTo(Vector2 from, Vector2 to, bool height); 143 | AdvImage(GameWindow* gw); 144 | ~AdvImage(); 145 | }; 146 | 147 | #endif // BASE_H 148 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | # compile under Ubuntu with SDL2 installed 2 | g++ main.cpp base.cpp gamemaster.cpp assets/*.cpp assets/BOSS/*.cpp assets/NAV/*.cpp -std=c++11 -I/usr/include/SDL2/ -I. -Iassets/ -Iassets/BOSS/ -Iassets/NAV/ -lSDL2main -lSDL2 -lSDL2_image -o helliaca 3 | -------------------------------------------------------------------------------- /defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * defs.h 3 | * 4 | * Created on: 19.05.2017 5 | * Author: sahel08_bk7 6 | */ 7 | 8 | /* 9 | * ART SOURCES: 10 | * Projectiles: http://millionthvector.blogspot.de/p/free-sprites.html 11 | * Fire: https://opengameart.org/content/wgstudio-fire-animation-loop 12 | * Explosion: https://opengameart.org/content/explosion 13 | * Metal Structure: https://opengameart.org/content/metal-grate-texture 14 | * Metal Supports: https://opengameart.org/content/brown-metal-trim (And similar from the same author) 15 | * Laser Flare: http://www.photos-public-domain.com/2011/11/19/bright-sun/ 16 | * Destructible Rock: textures.com 17 | * Everything Else: Myself 18 | */ 19 | 20 | #ifndef DEFS_H_ 21 | #define DEFS_H_ 22 | 23 | #define LEVELWIDTH 2000 24 | #define LEVELHEIGHT 1500 25 | #define SWIDTH 1280 26 | #define SHEIGHT 800 27 | #define BGWIDTH 1600 28 | #define BGHEIGHT 1155 29 | #define WINDOWNAME "Game" 30 | #define DEFAULTTAG '&' 31 | #define MIN_FRAMETIME 10 32 | 33 | //CONSTANTS 34 | #define GRAVITY 0.4 35 | #define FRICTION 0.95 36 | #define PLAYER_ACCEL_X 0.6 37 | #define PLAYER_ACCEL_Y 0.8 38 | #define BOSS_TAILSEGMENT_ACEL_MULTIPLIER 0.7f 39 | #define BOSS_TAILSEGMENT_AACEL_MULTIPLIER 0.06f 40 | #define BOSS_TAILSEGMENT_VEL_MULTIPLIER 0.1f 41 | #define BOSS_TAILSEGMENT_AVEL_MULTIPLIER 0.4f 42 | #define BOSS_TAILSEGMENT_BLEND_VELOCITY 4.0f 43 | #define BOSS_TAILSEGMENT_DISTANCE 50 44 | #define BOSS_TAILSEGMENT_CONNECTOR_HIDE_DISTANCE_UP 10 45 | #define BOSS_TAILSEGMENT_CONNECTOR_HIDE_DISTANCE_DOWN 15 46 | #define BOSS_IDLEANIMATION_SPEED 3 47 | #define BOSS_IDLEANIMATION_RADIUS 10 48 | #define BOSS_DEFAULT_TAIL_ROTATION 200 49 | #define BOSS_TAILWIGGLE_AMPLITUDE 30 50 | #define BOSS_TAILWIGGLE_SPEED 0.005f 51 | #define CAMERASMOOTHING 0.03f 52 | #define EASE_OUT_PERC 0.2f 53 | #define EASE_IN_PERC 0.1f 54 | #define MOVE_ANIM_VEL 3 55 | #define ROCKET_SPEED 3.0f 56 | #define BOSS_LASER_DURATION 1500.0f 57 | 58 | //PATHS 59 | #define HITMARKER "resource/hitmarker.png" 60 | #define FIRESPRITE "resource/fire.png" 61 | #define POINT "resource/point.png" 62 | #define PLAYERSPRITE "resource/player.png" 63 | #define PROJECTILESPRITE "resource/projectile.png" 64 | #define MISSILESPRITE "resource/missile.png" 65 | #define MISSILEDROPSPRITE "resource/missile_drop.png" 66 | #define EXPLOSIONSPRITE "resource/exp.png" 67 | #define LARGEEXPLOSIONSPRITE "resource/exp_large.png" 68 | #define TERRAIN1 "resource/terrain1.png" 69 | #define TERRAIN1_MASK "resource/terrain1_msk.png" 70 | #define BACKGROUND1 "resource/bg_volcano.png" 71 | #define BOSS_TAILSEGMENT_SPRITE "resource/boss_tailsegment.png" 72 | #define BOSS_TAILSEGMENT_SPRITE_END "resource/boss_tailsegment_end.png" 73 | #define BOSS_TAILSEGMENTCONNECTOR_SPRITE "resource/boss_tailsegmentconnector.png" 74 | #define BOSS_HEAD_SPRITE "resource/boss_head.png" 75 | #define BOSS_HEAD_SPRITE_ALTERNATIVE "resource/boss_head_alt.png" 76 | #define LASER_SPRITE "resource/laser_sprite.png" 77 | #define LASER_IMPACT_SPRITE "resource/flare_01_0.png" 78 | 79 | //COLORS 80 | #define TRANSPARENT 16777215 81 | #define EARTH -12816337 82 | 83 | //MATH 84 | #define PI 3.14159265 85 | 86 | 87 | #endif /* DEFS_H_ */ 88 | -------------------------------------------------------------------------------- /gamemaster.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "gamemaster.h" 3 | #include "assets/terrain.h" 4 | #include "assets/player.h" 5 | #include "assets/projectile.h" 6 | #include "assets/animation.h" 7 | #include "assets/background.h" 8 | #include "assets/BOSS/boss_AI.h" 9 | 10 | GameWindow* win = new GameWindow(); 11 | 12 | Timer frametimer; //Timer to cap framerate 13 | Timer projtimer; //Cooldown timer for shooting projectiles 14 | 15 | Vector2 mousePos; 16 | 17 | vector projs; 18 | vector anims; 19 | 20 | bool InputOutputManager(boss_AI* b, player* p, terrain* o); 21 | void drawAllProjs(); 22 | void drawAllAnims(); 23 | void updateAllProjs(terrain*); 24 | void updateAllAnims(); 25 | 26 | 27 | void start() { 28 | win->init(); 29 | SDL_Init(SDL_INIT_EVERYTHING); 30 | SDL_Init(SDL_INIT_VIDEO); 31 | SDL_Init(IMG_INIT_PNG); 32 | 33 | background* bg = new background(win); 34 | bg->loadTexture(BACKGROUND1); 35 | 36 | terrain* o = new terrain(win); 37 | 38 | player* p = new player(win); 39 | 40 | boss_AI* b = new boss_AI(win, o); 41 | 42 | frametimer.start(); 43 | projtimer.start(); 44 | while(1) { 45 | if(!InputOutputManager(b, p, o)) break; 46 | 47 | win->clear(); //Clear GameWindow 48 | 49 | //Draw everything 50 | bg->draw(); 51 | p->draw(); 52 | o->draw(); 53 | drawAllProjs(); 54 | drawAllAnims(); 55 | b->draw(); 56 | 57 | win->present(); //Show everything we've drawn in the last step 58 | 59 | //Update everything 60 | updateAllAnims(); 61 | b->update(); 62 | p->update(o); 63 | bg->update(win->camera->ViewPortOffset); 64 | updateAllProjs(o); 65 | 66 | while(frametimer.elapsedTime()draw(); 73 | } 74 | 75 | void drawAllProjs() { 76 | for(int i=0; idraw(); 77 | } 78 | 79 | void updateAllProjs(terrain* ter) { 80 | for(int i=0; idead) { 82 | //spawn animation 83 | animation* onDeath = new animation(win); 84 | onDeath->setPos(projs[i]->getPos().x, projs[i]->getPos().y); 85 | onDeath->setAnim(EXPLOSIONSPRITE, 4, 4, 50, 1); 86 | anims.push_back(onDeath); 87 | //remove projectile 88 | delete projs[i]; 89 | projs.erase(projs.begin()+i-1); 90 | i--; 91 | } 92 | projs[i]->update(ter); 93 | } 94 | } 95 | 96 | void updateAllAnims() { 97 | for(int i=0; idead) { 99 | delete anims[i]; 100 | anims.erase(anims.begin()+i-1); 101 | i--; 102 | } 103 | anims[i]->update(); 104 | } 105 | } 106 | 107 | bool InputOutputManager(boss_AI* b, player* p, terrain* o) { 108 | mousePos = win->getMousePosition(); 109 | const Uint8 *keys = SDL_GetKeyboardState(NULL); 110 | SDL_Event e; 111 | if ( SDL_PollEvent(&e) ) { 112 | if (e.type == SDL_QUIT) return false; 113 | else if (e.type == SDL_KEYUP && e.key.keysym.sym == SDLK_ESCAPE) return false; 114 | else if(e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_1) { 115 | b->launchAttack(LASER); 116 | } 117 | else if(e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_2) { 118 | b->launchAttack(ROCKETS); 119 | } 120 | else if(e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_3) { 121 | b->spawnRockets = !b->spawnRockets; 122 | } 123 | } 124 | 125 | win->camera->follow(p->getPos()); 126 | 127 | if(SDL_MOUSEBUTTONDOWN && SDL_BUTTON(SDL_GetMouseState(NULL, NULL)) == 8) o->create_square(mousePos, 25); // looks like right mouse button is 8. SDL_BUTTON_RIGHT seems to be broken 128 | if(SDL_MOUSEBUTTONDOWN && SDL_BUTTON(SDL_GetMouseState(NULL, NULL)) == SDL_BUTTON_LEFT && projtimer.elapsedTime()>300) { 129 | projectile* np = new projectile(win); 130 | np->setPos(p->getPos()); 131 | np->launch(mousePos); 132 | projs.push_back(np); 133 | projtimer.start(); 134 | } 135 | if (keys[SDL_SCANCODE_W]) p->accelerate(0,-PLAYER_ACCEL_Y); 136 | if (keys[SDL_SCANCODE_S]) p->accelerate(0,PLAYER_ACCEL_Y); 137 | if (keys[SDL_SCANCODE_D]) p->accelerate(PLAYER_ACCEL_X,0); 138 | if (keys[SDL_SCANCODE_A]) p->accelerate(-PLAYER_ACCEL_X,0); 139 | return true; 140 | } 141 | 142 | -------------------------------------------------------------------------------- /gamemaster.h: -------------------------------------------------------------------------------- 1 | /* 2 | * gamemaster.h 3 | * 4 | * Created on: 19.05.2017 5 | * Author: sahel08_bk7 6 | */ 7 | 8 | #ifndef GAMEMASTER_H_ 9 | #define GAMEMASTER_H_ 10 | 11 | #include "base.h" 12 | #include 13 | 14 | void start(); 15 | 16 | 17 | #endif /* GAMEMASTER_H_ */ 18 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "gamemaster.h" 8 | 9 | using namespace std; 10 | 11 | int main(int argc, char **argv) { 12 | start(); 13 | return 1; 14 | } 15 | -------------------------------------------------------------------------------- /random.h: -------------------------------------------------------------------------------- 1 | #ifndef RANDOM_H 2 | #define RANDOM_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | inline void init() { 9 | srand(time(NULL)); 10 | } 11 | 12 | //Return random float 13 | inline float getRandDecimal() { 14 | return (float)rand()/RAND_MAX; 15 | } 16 | 17 | //Return random integer in given range 18 | inline int getRandInteger(int min, int max) { 19 | return min + rand() % (max - min); 20 | } 21 | 22 | 23 | #endif // RANDOM_H 24 | -------------------------------------------------------------------------------- /resource/bg_volcano.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/bg_volcano.png -------------------------------------------------------------------------------- /resource/boss_head.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/boss_head.png -------------------------------------------------------------------------------- /resource/boss_head_alt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/boss_head_alt.png -------------------------------------------------------------------------------- /resource/boss_tailsegment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/boss_tailsegment.png -------------------------------------------------------------------------------- /resource/boss_tailsegment_end.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/boss_tailsegment_end.png -------------------------------------------------------------------------------- /resource/boss_tailsegmentconnector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/boss_tailsegmentconnector.png -------------------------------------------------------------------------------- /resource/exp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/exp.png -------------------------------------------------------------------------------- /resource/exp_large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/exp_large.png -------------------------------------------------------------------------------- /resource/fire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/fire.png -------------------------------------------------------------------------------- /resource/flare_01_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/flare_01_0.png -------------------------------------------------------------------------------- /resource/hitmarker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/hitmarker.png -------------------------------------------------------------------------------- /resource/laser_sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/laser_sprite.png -------------------------------------------------------------------------------- /resource/missile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/missile.png -------------------------------------------------------------------------------- /resource/missile_drop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/missile_drop.png -------------------------------------------------------------------------------- /resource/player.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/player.png -------------------------------------------------------------------------------- /resource/point.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/point.png -------------------------------------------------------------------------------- /resource/projectile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/projectile.png -------------------------------------------------------------------------------- /resource/terrain1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/terrain1.png -------------------------------------------------------------------------------- /resource/terrain1_msk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Helliaca/SDL2-Game/9fc1c6c0aa8a25961d9170da34c246db1a010b58/resource/terrain1_msk.png --------------------------------------------------------------------------------