├── LICENSE ├── Makefile ├── README.md ├── asteroid ├── build.sh ├── data ├── fonts │ └── FreeMonoBold.ttf ├── pics │ ├── asteroid.png │ ├── debris.png │ ├── exp.png │ ├── fire1.png │ ├── indicators.png │ ├── ship.png │ ├── ship_dmg0.png │ ├── ship_dmg1.png │ ├── ship_plume.png │ ├── ship_plume2.png │ ├── ship_plume3.png │ ├── ship_plume4.png │ ├── ship_plume5.png │ ├── ship_plume6.png │ ├── spexpb.bmp │ └── title.bmp └── snd │ ├── crash.wav │ ├── explosion.wav │ ├── intro.wav │ ├── rockets.wav │ ├── shield.wav │ ├── shot.wav │ └── theme.ogg ├── list.c ├── list.h ├── main.c └── screenshot.png /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Velorek1 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .POSIX: 2 | CC = gcc 3 | CFLAGS = -Wall -Wextra -Os 4 | LDFLAGS = 5 | LDLIBS = -lm -lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_ttf 6 | 7 | obj = list.o main.o 8 | 9 | asteroid: $(obj) 10 | $(CC) $(LDFLAGS) -o $@ $(obj) $(LDLIBS) 11 | 12 | clean: 13 | rm -f asteroid $(obj) 14 | list.o: list.c list.h 15 | main.o: main.c list.h 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ast3r0id 2 | Classic Asteroid Game coded with SDL2 in C 3 | * Remember to install GCC and SDL2 libraries to compile. 4 | * MIT LICENSE added 5 | * [NEW] Windows 32-bit binary release -> https://github.com/velorek1/asteroid/releases/download/2/asteroid32bit.zip 6 | * [NEW] Windows 64-bit binary release -> https://github.com/velorek1/asteroid/files/7026151/asteroid_64bit.zip 7 | 8 | TO COMPILE and RUN: 9 | 10 | * GNU/LINUX: 11 | - Download or clone repository. 12 | - Type "bash build.sh" or "make" and "./asteroid" to run. 13 | 14 | * WINDOWS: 15 | - It can be compiled with Codeblocks + TDM-GCC + SDL2 Headers 16 | 17 | ![Alt text](screenshot.png?raw=true "Demo") 18 | -------------------------------------------------------------------------------- /asteroid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/asteroid -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # file: build.sh 3 | echo -e "\e[93mAst3r0id Game - Coded By v3l0r3k\e[0m" 4 | echo 5 | read -p "[+] Install SDL2 libraries? (sudo required) [Y/N]: " -n 1 -r 6 | echo # (optional) move to a new line 7 | if [[ $REPLY =~ ^[Yy]$ ]] 8 | then 9 | sudo apt-get install libsdl2-2.0-0 && sudo apt-get install libsdl2-dev 10 | sudo apt-get install libsdl2-mixer-2.0-0 && sudo apt-get install libsdl2-mixer-dev 11 | sudo apt-get install libsdl2-ttf-2.0-0 && sudo apt-get install libsdl2-ttf-dev 12 | sudo apt-get install libsdl2-image-2.0-0 && sudo apt-get install libsdl2-image-dev 13 | fi 14 | echo 15 | echo [+] Attempting to compile game... 16 | gcc -c list.c 17 | gcc -c -Wall main.c 18 | gcc list.o main.o -lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_ttf -lm -Wall -o asteroid 19 | echo gcc main.c -lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_ttf -lm -Wall -o asteroid 20 | echo 21 | echo -e "Run as \e[93m./asteroid\e[0m" 22 | echo Enjoy it! 23 | 24 | -------------------------------------------------------------------------------- /data/fonts/FreeMonoBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/fonts/FreeMonoBold.ttf -------------------------------------------------------------------------------- /data/pics/asteroid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/pics/asteroid.png -------------------------------------------------------------------------------- /data/pics/debris.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/pics/debris.png -------------------------------------------------------------------------------- /data/pics/exp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/pics/exp.png -------------------------------------------------------------------------------- /data/pics/fire1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/pics/fire1.png -------------------------------------------------------------------------------- /data/pics/indicators.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/pics/indicators.png -------------------------------------------------------------------------------- /data/pics/ship.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/pics/ship.png -------------------------------------------------------------------------------- /data/pics/ship_dmg0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/pics/ship_dmg0.png -------------------------------------------------------------------------------- /data/pics/ship_dmg1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/pics/ship_dmg1.png -------------------------------------------------------------------------------- /data/pics/ship_plume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/pics/ship_plume.png -------------------------------------------------------------------------------- /data/pics/ship_plume2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/pics/ship_plume2.png -------------------------------------------------------------------------------- /data/pics/ship_plume3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/pics/ship_plume3.png -------------------------------------------------------------------------------- /data/pics/ship_plume4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/pics/ship_plume4.png -------------------------------------------------------------------------------- /data/pics/ship_plume5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/pics/ship_plume5.png -------------------------------------------------------------------------------- /data/pics/ship_plume6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/pics/ship_plume6.png -------------------------------------------------------------------------------- /data/pics/spexpb.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/pics/spexpb.bmp -------------------------------------------------------------------------------- /data/pics/title.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/pics/title.bmp -------------------------------------------------------------------------------- /data/snd/crash.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/snd/crash.wav -------------------------------------------------------------------------------- /data/snd/explosion.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/snd/explosion.wav -------------------------------------------------------------------------------- /data/snd/intro.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/snd/intro.wav -------------------------------------------------------------------------------- /data/snd/rockets.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/snd/rockets.wav -------------------------------------------------------------------------------- /data/snd/shield.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/snd/shield.wav -------------------------------------------------------------------------------- /data/snd/shot.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/snd/shot.wav -------------------------------------------------------------------------------- /data/snd/theme.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/data/snd/theme.ogg -------------------------------------------------------------------------------- /list.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "list.h" 5 | 6 | // create new list element of type OBJECT from the supplied text string 7 | OBJECT *newelement(OBJECT temp) 8 | { 9 | OBJECT *newp; 10 | newp = (OBJECT *) malloc (sizeof(OBJECT)); 11 | newp->index = temp.index; 12 | newp->Img = temp.Img; 13 | newp->X = temp.X; 14 | newp->Y = temp.Y; 15 | newp->W = temp.W; 16 | newp->H = temp.H; 17 | newp->DIRX = temp.DIRX; 18 | newp->DIRY = temp.DIRY; 19 | newp->Life = temp.Life; 20 | newp->DX = temp.DX; 21 | newp->DY = temp.DY; 22 | newp->FX = temp.FX; 23 | newp->FY = temp.FY; 24 | newp->Angle = temp.Angle; 25 | newp -> next = NULL; 26 | return newp; 27 | } 28 | 29 | // Delete first element on list whose item field matches the given text 30 | // NOTE!! delete requests for elements not in the list are silently ignored :-) 31 | void RemoveThing(OBJECT **head, int index) 32 | { 33 | BOOL present = FALSE; 34 | OBJECT *old; 35 | OBJECT **tracer = head; 36 | if ((*tracer)->index==index) present=TRUE; 37 | while((*tracer) && !(present)){ 38 | if ((*tracer)->index==index) present=TRUE; 39 | tracer = &(*tracer)->next; 40 | } 41 | 42 | if(present) 43 | { 44 | old = *tracer; 45 | *tracer = (*tracer)->next; 46 | free(old); // free up remainder of list element 47 | } 48 | } 49 | void deleteList(OBJECT **head) 50 | { 51 | /* deref head_ref to get the real head */ 52 | OBJECT *current = *head; 53 | OBJECT *next = NULL; 54 | OBJECT **tracer=head; 55 | while (current != NULL) 56 | { 57 | next = current->next; 58 | free(current); 59 | current = next; 60 | } 61 | 62 | /* deref head_ref to affect the real head back 63 | in the caller. */ 64 | 65 | *tracer = NULL; 66 | } 67 | 68 | 69 | // updatelement: remove from list the first instance of an element 70 | OBJECT *update(OBJECT *head, int index, OBJECT temp) 71 | { 72 | OBJECT *p; 73 | for (p = head; p != NULL; p = p -> next) { 74 | if (p -> index == index) { 75 | break; 76 | } 77 | } 78 | p-> index = temp.index; 79 | return head; 80 | 81 | } 82 | 83 | // getObject 84 | OBJECT *getObject(OBJECT *head, int index) 85 | { 86 | OBJECT *p; 87 | for (p = head; p != NULL; p = p -> next) { 88 | if (p -> index == index) { 89 | break; 90 | } 91 | } 92 | //p-> index = temp.index; 93 | return p; 94 | 95 | } 96 | // delelement: remove from list the first instance of an element 97 | // containing a given text string 98 | // NOTE!! delete requests for elements not in the list are silently ignored 99 | OBJECT *delelement(OBJECT *head, int index) 100 | { 101 | OBJECT *p, *prev; 102 | prev = NULL; 103 | for (p = head; p != NULL; p = p -> next) { 104 | if (p -> index == index) { 105 | if(prev == NULL) 106 | head = p-> next; 107 | else 108 | prev -> next = p -> next; 109 | free(p); // remove rest of OBJECT 110 | return head; 111 | } 112 | prev = p; 113 | } 114 | return NULL; 115 | } 116 | /* addfront: add new OBJECT to front of list */ 117 | /* example usage: start = (addfront(start, newelement("burgers")); */ 118 | 119 | OBJECT *addfront(OBJECT *head, OBJECT *newp) 120 | { 121 | newp -> next = head; 122 | return newp; 123 | } 124 | 125 | /* addend: add new OBJECT to the end of a list */ 126 | /* usage example: start = (addend(start, newelement("wine")); */ 127 | 128 | OBJECT *addend (OBJECT *head, OBJECT *newp) 129 | { 130 | OBJECT *p2; 131 | if (head == NULL) 132 | return newp; 133 | // now find the end of list 134 | for (p2 = head; p2 -> next != NULL; p2 = p2 -> next) 135 | ; 136 | p2 -> next = newp; 137 | return head; 138 | } 139 | 140 | void printlist(OBJECT **head) 141 | // this routine uses pointer-to-pointer techniques :-) 142 | { 143 | OBJECT **tracer = head; 144 | while ((*tracer) != NULL) { 145 | printf("%d \n",(*tracer)->index); 146 | tracer = &(*tracer)->next; 147 | } 148 | } 149 | 150 | int length(OBJECT **head) 151 | // this routine uses pointer-to-pointer techniques :-) 152 | { 153 | 154 | int count=0; 155 | OBJECT **tracer = head; 156 | while ((*tracer) != NULL) { 157 | count = count +1; 158 | tracer = &(*tracer)->next; 159 | } 160 | return count; 161 | } 162 | void reindex(OBJECT **head) 163 | { 164 | int count=0; 165 | OBJECT *p=NULL; 166 | OBJECT **tracer = head; 167 | while ((*tracer) != NULL) { 168 | p = *tracer; 169 | p->index=count; 170 | count = count +1; 171 | tracer = &(*tracer)->next; 172 | } 173 | } 174 | 175 | void deleteObject(OBJECT **head,int index, BOOL sort){ 176 | OBJECT *p=*head; 177 | if (index == 0 || length(head) <=1 || p->index == index ) 178 | RemoveThing(head,index); 179 | else 180 | delelement(*head,index); 181 | if (sort == TRUE) reindex(head); 182 | } 183 | 184 | 185 | -------------------------------------------------------------------------------- /list.h: -------------------------------------------------------------------------------- 1 | #ifndef _LIST_H_ 2 | #define _LIST_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define TRUE 1 9 | #define FALSE 0 10 | typedef int BOOL; 11 | typedef struct _object 12 | { 13 | int index; 14 | SDL_Surface *Img; 15 | int X,Y,W,H,DIRX,DIRY,Life; 16 | float FX,FY,DX,DY; 17 | int Angle; 18 | struct _object *next; 19 | } OBJECT; 20 | 21 | 22 | /* Adapted from Kernighan and Pike's "The Practice of Programming" pp.46 et 23 | seq. (Addison-Wesley 1999) */ 24 | 25 | // create new list element of type OBJECT from the supplied text string 26 | OBJECT *newelement(OBJECT temp); 27 | OBJECT *addfront(OBJECT *head, OBJECT *newp); 28 | OBJECT *addend (OBJECT *head, OBJECT *newp); 29 | OBJECT *addmiddle (OBJECT *head, OBJECT *newp); 30 | OBJECT *update(OBJECT *head, int index, OBJECT temp); 31 | OBJECT *getObject(OBJECT *head, int index); 32 | void RemoveThing(OBJECT **head, int index); 33 | void deleteList(OBJECT **head); 34 | OBJECT *delelement(OBJECT *head, int index); 35 | void deleteObject(OBJECT **head,int index, BOOL sort); 36 | int length(OBJECT **head); 37 | void printlist(OBJECT **head); 38 | void reindex(OBJECT **head); 39 | #endif 40 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* *************************** Ast3r0id *************************** */ 2 | /* Author: V3lorek */ 3 | /* Date : 2020 */ 4 | /* [+] STRUCTURE: |-------------------v */ 5 | /* [MAIN] -> [NEWGAME] -> [MAIN_LOOP] ->[UPDATEGAME && HANDLE_EVENTS] */ 6 | /* ^ | */ 7 | /* [DRAWTOSCREEN] <- [MOVEOBJECTS] */ 8 | /* ***************************************************************** */ 9 | /* [Authors of Assets] */ 10 | /* - Ship: [Seki]from cleanpng.com */ 11 | /* - Asteroid: pngwave.com */ 12 | /* - Theme: [Jan125] opengameart.org */ 13 | /* - Crash : [freesound] */ 14 | /* - Intro : https://mixkit.co/free-sound-effects/intro/ */ 15 | /* ***************************************************************** */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #define SDL_MAIN_HANDLED 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "list.h" 26 | 27 | #define PI 3.14159265 28 | //GAME CONSTANTS 29 | #define SCREEN_W 640 30 | #define SCREEN_H 480 31 | #define ASTW0 80 32 | #define ASTH0 80 33 | #define ASTW1 60 34 | #define ASTH1 60 35 | #define ASTW2 32 36 | #define ASTH2 32 37 | #define MAX_LIFE 100 38 | #define MAX_KEY 1000 39 | #define UP 1 40 | #define DOWN 0 41 | #define SPEED 12 42 | #define ROTATION 5.5 43 | //MESSAGES 44 | #define STS_MSG0 "SDL Graphics loaded successfully.\n" 45 | #define ERR_MSG0 "SDL Graphics could not be loaded. \n" 46 | #define ERR_MSG1 "Failed to load asset. \n" 47 | 48 | 49 | typedef struct _sprite{ 50 | SDL_Surface *Img; 51 | } SPRITE; 52 | 53 | enum SHIPSTATE{HALTED, UTHRUST, DTHRUST, LTHRUST, RTHRUST, DAMAGED}; 54 | 55 | /* GLOBALS */ 56 | OBJECT ship; 57 | OBJECT *asteroids; 58 | OBJECT *projectiles; 59 | SPRITE shipSprite[9]; 60 | SDL_Surface *background,*asteroid,*projectile,*explosionIMG,*debris,*indicators; 61 | SDL_Event ev; 62 | SDL_Renderer *ren1; 63 | SDL_Window *win1; 64 | long KeyState[MAX_KEY]; 65 | BOOL Running=TRUE; 66 | BOOL keypressed=FALSE; 67 | BOOL mouseclicked=FALSE; 68 | time_t t; 69 | Mix_Music *Theme; 70 | Mix_Chunk *sound, *intro, *shot, *expsnd, *shield, *crash=NULL; 71 | enum SHIPSTATE ShipState; 72 | int level=0; int lives=MAX_LIFE; 73 | int oldX, oldY, oldAngle; 74 | int points = 0; 75 | int currentLevel = 1; 76 | double PlayerShootTime, timetemp=0; 77 | int expticks=0; 78 | BOOL explosion=FALSE; 79 | BOOL momentum=FALSE; 80 | BOOL reversed=FALSE; 81 | BOOL shipstill=FALSE; 82 | double velocity = SPEED; 83 | int bestScore = 0; 84 | /* ---------------------------------------------- */ 85 | /* FUNCTION PROTOTYPES */ 86 | /* ---------------------------------------------- */ 87 | /* Mathematics & Physics */ 88 | BOOL Collision(int AX1, int AY1, int AX2, int AY2, int BX1, int BY1, int BX2, int BY2); 89 | double sinD(int degree); 90 | double cosD(int degree); 91 | int randnum(int number); 92 | /*SDL Related */ 93 | BOOL InitVideo(); 94 | BOOL InitAudio(); 95 | void ToggleFullscreen(SDL_Window* Window); 96 | void CleanMemory(); 97 | /* EVENTS */ 98 | BOOL Key(long K); 99 | void HandleKey(long Sym, BOOL Down); 100 | void HandleEvents(); 101 | BOOL timer1(int *ticks, double *time, int ms); 102 | BOOL lerp(double *value, double *time, int ms); 103 | 104 | /* Game engine */ 105 | 106 | void LaunchProjectile(double X, double Y, double DX, double DY, SDL_Surface *Img, int Life); 107 | void LoadAssets(); 108 | void Intro(); 109 | void NewGame(int currentLevel); 110 | void UpdateGame(); 111 | void Main_Loop(); 112 | void LaunchPoof(int X, int Y, SDL_Surface * Img, int life); 113 | void movePlayerXY(int speed); 114 | void rotateBy(OBJECT *Object, float D); 115 | void Ship_Behaviour(); 116 | void moveAsteroids(); 117 | void moveProjectiles(); 118 | void ShootPlayerBullet(); 119 | /* Drawing */ 120 | void Draw(int X, int Y, SDL_Surface *Img); 121 | void DrawObject(OBJECT Object); 122 | void DrawAnimation(int X, int Y, int H, int W, int frame, SDL_Surface *Img); 123 | void DrawDynamicObject(OBJECT *Object); 124 | void DrawScreen(); 125 | void DrawText(char* string,int size, int x, int y,int fR, int fG, int fB,int bR, int bG, int bB, BOOL transparent); 126 | void LoadAsteroids(); 127 | void addAsteroid(int X,int Y,int DIRX, int DIRY, int size); 128 | 129 | /* ---------------------------------------------- */ 130 | /* MAIN - ENTRY POINT */ 131 | /* ---------------------------------------------- */ 132 | int main(){ 133 | InitVideo(); 134 | InitAudio(); 135 | TTF_Init(); 136 | LoadAssets(); 137 | Intro(); 138 | NewGame(currentLevel); 139 | Main_Loop(); //UPDATE EVENTS AND DRAW TO SCREEN 140 | CleanMemory(); 141 | return 0; 142 | } 143 | 144 | /* FUNCTIONS */ 145 | 146 | /* ==========================================================*/ 147 | //Mathematics and Physics 148 | /* ==========================================================*/ 149 | 150 | BOOL Collision(int AX1, int AY1, int AX2, int AY2, int BX1, int BY1, int BX2, int BY2){ 151 | return (AX1 < BX1 + (BX2-BX1)) && (AX1 + (AX2-AX1) > BX1) && (AY1 < BY1 + (BY2-BY1)) && (AY1 + (AY2-AY1) > BY1); 152 | } 153 | 154 | double sinD(int degree){ 155 | double ret,val; 156 | val = PI / 180; 157 | ret = sin(degree*val); 158 | return ret; 159 | } 160 | 161 | double cosD(int degree){ 162 | double ret,val; 163 | val = PI / 180; 164 | ret = cos(degree*val); 165 | return ret; 166 | } 167 | int randnum(int number){ 168 | //srand((unsigned) time(&t)); 169 | return rand() % number; 170 | } 171 | 172 | /* ==========================================================*/ 173 | //SDL Initialization 174 | /* ==========================================================*/ 175 | 176 | BOOL InitVideo(){ 177 | SDL_Init(SDL_INIT_VIDEO); 178 | IMG_Init(IMG_INIT_PNG); 179 | #ifdef __linux__ 180 | win1 = SDL_CreateWindow(" > Ast3r0id <", 50,50,SCREEN_W,SCREEN_H,SDL_WINDOW_SHOWN); 181 | #elif _WIN32 182 | win1 = SDL_CreateWindow(" > Ast3r0id <", 50,50,SCREEN_W,SCREEN_H,SDL_WINDOW_SHOWN); 183 | #else 184 | #endif 185 | ren1 = SDL_CreateRenderer(win1, -1, 0); 186 | SDL_SetWindowBordered(win1,SDL_TRUE); 187 | return (ren1 != NULL) && (win1 != NULL); 188 | } 189 | 190 | BOOL InitAudio(){ 191 | if (SDL_Init(SDL_INIT_AUDIO) < 0){ 192 | return FALSE; 193 | } 194 | Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 195 | MIX_DEFAULT_CHANNELS, 4096); 196 | return TRUE; 197 | } 198 | void ToggleFullscreen(SDL_Window* Window) { 199 | Uint32 FullscreenFlag = SDL_WINDOW_FULLSCREEN; 200 | BOOL IsFullscreen = SDL_GetWindowFlags(Window) & FullscreenFlag; 201 | SDL_SetWindowFullscreen(Window, IsFullscreen ? 0 : FullscreenFlag); 202 | SDL_ShowCursor(IsFullscreen); 203 | } 204 | 205 | /* ==========================================================*/ 206 | //Events Functions 207 | /* ==========================================================*/ 208 | 209 | BOOL Key(long K){ 210 | if ((K>= 0) && (K <= MAX_KEY)) 211 | return KeyState[K]; 212 | else 213 | return FALSE; 214 | } 215 | 216 | void HandleKey(long Sym, BOOL Down){ 217 | if (Sym == SDLK_UP) Sym = SDL_SCANCODE_UP; 218 | if (Sym == SDLK_DOWN) Sym = SDL_SCANCODE_DOWN; 219 | if (Sym == SDLK_LEFT) Sym = SDL_SCANCODE_LEFT; 220 | if (Sym == SDLK_RIGHT) Sym = SDL_SCANCODE_RIGHT; 221 | if (Sym == SDLK_SPACE) Sym = SDL_SCANCODE_SPACE; 222 | if ((Sym >= 0) && (Sym <= MAX_KEY)) { 223 | KeyState[Sym] = Down; 224 | if (Sym == SDLK_ESCAPE) Running = FALSE; 225 | } 226 | } 227 | 228 | void HandleEvents(){ 229 | SDL_Event e; 230 | if (SDL_PollEvent(&e)) { 231 | if (e.type == SDL_QUIT) { 232 | Running = FALSE; 233 | } 234 | 235 | if (e.type == SDL_KEYDOWN){ 236 | keypressed = TRUE; 237 | HandleKey(e.key.keysym.sym, TRUE); 238 | } 239 | 240 | if (e.type == SDL_MOUSEBUTTONDOWN){ 241 | mouseclicked = TRUE; 242 | } 243 | if (e.type == SDL_MOUSEBUTTONUP){ 244 | mouseclicked = FALSE; 245 | } 246 | if (e.type == SDL_KEYUP){ 247 | keypressed = FALSE; 248 | HandleKey(e.key.keysym.sym, FALSE); 249 | } 250 | } 251 | } 252 | 253 | /* ==========================================================*/ 254 | // Game Engine 255 | /* ==========================================================*/ 256 | 257 | void LoadAssets(){ 258 | /* Images */ 259 | background = SDL_LoadBMP("data/pics/spexpb.bmp"); 260 | if (background == NULL) {fprintf(stderr, ERR_MSG1); exit(0);} 261 | asteroid = IMG_Load("data/pics/asteroid.png"); 262 | if (asteroid == NULL) {fprintf(stderr, ERR_MSG1); exit(0);} 263 | projectile = IMG_Load("data/pics/fire1.png"); 264 | if (projectile == NULL) {fprintf(stderr, ERR_MSG1); exit(0);} 265 | debris = IMG_Load("data/pics/debris.png"); 266 | if (debris == NULL) {fprintf(stderr, ERR_MSG1); exit(0);} 267 | indicators = IMG_Load("data/pics/indicators.png"); 268 | if (indicators == NULL) {fprintf(stderr, ERR_MSG1); exit(0);} 269 | 270 | 271 | shipSprite[0].Img = IMG_Load("data/pics/ship.png"); 272 | if (shipSprite[0].Img == NULL) {fprintf(stderr, ERR_MSG1);exit(0);} 273 | shipSprite[1].Img = IMG_Load("data/pics/ship_plume.png"); 274 | if (shipSprite[1].Img == NULL) {fprintf(stderr, ERR_MSG1);exit(0);} 275 | shipSprite[2].Img = IMG_Load("data/pics/ship_plume2.png"); 276 | if (shipSprite[2].Img == NULL) {fprintf(stderr, ERR_MSG1);exit(0);} 277 | shipSprite[3].Img = IMG_Load("data/pics/ship_plume3.png"); 278 | if (shipSprite[3].Img == NULL) {fprintf(stderr, ERR_MSG1);exit(0);} 279 | shipSprite[4].Img = IMG_Load("data/pics/ship_plume4.png"); 280 | if (shipSprite[4].Img == NULL) {fprintf(stderr, ERR_MSG1);exit(0);} 281 | shipSprite[5].Img = IMG_Load("data/pics/ship_plume5.png"); 282 | if (shipSprite[5].Img == NULL) {fprintf(stderr, ERR_MSG1);exit(0);} 283 | shipSprite[6].Img = IMG_Load("data/pics/ship_plume6.png"); 284 | if (shipSprite[6].Img == NULL) {fprintf(stderr, ERR_MSG1);exit(0);} 285 | shipSprite[7].Img = IMG_Load("data/pics/ship_dmg0.png"); 286 | if (shipSprite[7].Img == NULL) {fprintf(stderr, ERR_MSG1);exit(0);} 287 | shipSprite[8].Img = IMG_Load("data/pics/ship_dmg1.png"); 288 | if (shipSprite[8].Img == NULL) {fprintf(stderr, ERR_MSG1);exit(0);} 289 | 290 | ship.Img = shipSprite[0].Img; 291 | explosionIMG = IMG_Load("data/pics/exp.png"); 292 | if (explosionIMG == NULL) {fprintf(stderr, ERR_MSG1); exit(0);} 293 | 294 | /* Music and Sounds */ 295 | Theme = Mix_LoadMUS("data/snd/theme.ogg"); 296 | if (Theme == NULL) {fprintf(stderr, ERR_MSG1); exit(0);} 297 | 298 | intro = Mix_LoadWAV("data/snd/intro.wav"); 299 | if (intro == NULL) {fprintf(stderr, ERR_MSG1); exit(0);} 300 | Mix_VolumeChunk(intro, MIX_MAX_VOLUME ); 301 | 302 | sound = Mix_LoadWAV("data/snd/rockets.wav"); 303 | if (sound == NULL) {fprintf(stderr, ERR_MSG1); exit(0);} 304 | Mix_VolumeChunk( sound, MIX_MAX_VOLUME ); 305 | 306 | shot = Mix_LoadWAV("data/snd/shot.wav"); 307 | if (shot == NULL) {fprintf(stderr, ERR_MSG1); exit(0);} 308 | Mix_VolumeChunk(shot, MIX_MAX_VOLUME ); 309 | 310 | expsnd = Mix_LoadWAV("data/snd/explosion.wav"); 311 | if (expsnd == NULL) {fprintf(stderr, ERR_MSG1); exit(0);} 312 | Mix_VolumeChunk(expsnd, MIX_MAX_VOLUME ); 313 | 314 | shield = Mix_LoadWAV("data/snd/shield.wav"); 315 | if (shield == NULL) {fprintf(stderr, ERR_MSG1); exit(0);} 316 | Mix_VolumeChunk(shield, MIX_MAX_VOLUME ); 317 | 318 | crash = Mix_LoadWAV("data/snd/crash.wav"); 319 | if (crash == NULL) {fprintf(stderr, ERR_MSG1); exit(0);} 320 | Mix_VolumeChunk(crash, MIX_MAX_VOLUME ); 321 | 322 | 323 | } 324 | 325 | void LaunchProjectile(double X, double Y, double DX, double DY, SDL_Surface *Img, int Life){ 326 | OBJECT p; 327 | if (projectiles == NULL) 328 | p.index = 0; 329 | else{ 330 | p.index = length(&projectiles); 331 | } 332 | p.Img = Img; 333 | p.Angle = ship.Angle; 334 | p.W = 16; 335 | p.H = 16; 336 | if (Life == -1) { 337 | //ship projectile 338 | p.FX = (ship.X+(ship.W-10)/2) + ((cosD(p.Angle) *-1) - (sinD(p.Angle) * 40)*-1); 339 | p.FY = (ship.Y+(ship.H-30)/2) + (sinD(p.Angle) * -1) + ((cosD(p.Angle) * 40*-1)); 340 | p.DX = DX; 341 | p.DY = DY; 342 | p.X = round(p.FX); 343 | p.Y = round(p.FY); 344 | } else{ 345 | //poof explosion animation 346 | p.X = X; 347 | p.Y = Y; 348 | p.FX = X; 349 | p.FY = Y; 350 | p.DX = DX; 351 | p.DY = DY; 352 | } 353 | p.Life = Life; 354 | projectiles=addend(projectiles, newelement(p)); 355 | } 356 | 357 | void addAsteroid(int X,int Y,int DIRX, int DIRY, int size) 358 | { 359 | OBJECT temp; 360 | temp.index = length(&asteroids); 361 | temp.DIRX = DIRX; 362 | temp.DIRY = DIRY; 363 | temp.X = X; 364 | temp.Y = Y; 365 | temp.DX = temp.X; 366 | temp.DY = temp.Y; 367 | if (size==0){ 368 | temp.W = ASTH0; 369 | temp.H = ASTW0; 370 | temp.Life = 3; 371 | } 372 | if(size==1) { 373 | temp.W = ASTH1; 374 | temp.H = ASTW1; 375 | temp.Life = 2; 376 | } 377 | if(size==2){ 378 | temp.W = ASTH2; 379 | temp.H = ASTW2; 380 | temp.Life = 1; 381 | } 382 | temp.Angle=0; 383 | temp.Img = asteroid; 384 | asteroids = addend(asteroids, newelement(temp)); 385 | } 386 | 387 | void Intro(){ 388 | char introStr[10]; 389 | char helpStr0[100]; 390 | char helpStr1[100]; 391 | char helpStr2[100]; 392 | char helpStr3[100]; 393 | char helpStr4[100]; 394 | int wherey=0; 395 | BOOL keyFlag = FALSE; 396 | SDL_Event e; 397 | 398 | SDL_RenderClear(ren1); 399 | Draw(0,0,background); 400 | sprintf(introStr, "AST3R0ID"); 401 | if (Mix_Playing(1) == 0) Mix_PlayChannel(1, intro, 0); 402 | do{ 403 | SDL_RenderClear(ren1); 404 | Draw(0,0,background); 405 | DrawText(introStr, 100, 80,wherey, 255,0, 0, 0, 0, 0,TRUE); 406 | DrawText(introStr, 100, 85,wherey+5,255,255, 0, 0, 0, 0,TRUE); 407 | SDL_RenderPresent(ren1); 408 | SDL_Delay(10); 409 | wherey = wherey + 3; 410 | } while (wherey < 100); 411 | sprintf(helpStr0, "Coded by v3l0r3k - 2021 "); 412 | sprintf(helpStr1, "CONTROLS: "); 413 | sprintf(helpStr2, "^: UP v: DOWN <- : LEFT -> : RIGHT | SPACE : SHOOT "); 414 | sprintf(helpStr3, "F: FULLSCREEN | ESC: EXIT"); 415 | sprintf(helpStr4, "PRESS ANY KEY TO START"); 416 | 417 | DrawText(helpStr0, 12, 230,200,105,105, 105, 0, 0, 0,TRUE); 418 | DrawText(helpStr1, 12, 10,370,255,255, 255, 0, 0, 0,TRUE); 419 | DrawText(helpStr2, 12, 10,390,255,255, 255, 0, 0, 0,TRUE); 420 | DrawText(helpStr3, 12, 10,410,255,255, 255, 0, 0, 0,TRUE); 421 | DrawText(helpStr4, 16, 200,250,255,255, 255, 0, 0, 0,TRUE); 422 | 423 | SDL_RenderPresent(ren1); 424 | 425 | do { 426 | if (SDL_PollEvent(&e)) { 427 | if (e.type == SDL_QUIT) { 428 | Running = FALSE; 429 | break; 430 | } 431 | if (e.type == SDL_KEYDOWN){ 432 | keyFlag = TRUE; 433 | } 434 | } 435 | 436 | } while (keyFlag ==FALSE); 437 | SDL_Delay(100); 438 | } 439 | 440 | void NewGame(int currentLevel){ 441 | int i,a,tDIRX,tDIRY,tSIZE,tX,tY; 442 | 443 | if (asteroids != NULL) deleteList(&asteroids); 444 | 445 | lives = MAX_LIFE; 446 | /* SHIP */ 447 | ship.X = 100; 448 | ship.Y = 100; 449 | oldX = ship.X; 450 | oldY = ship.Y; 451 | ship.DX = ship.X; 452 | ship.DY = ship.Y; 453 | ship.W = 50; 454 | ship.H = 70; 455 | ship.Angle = 0; 456 | oldAngle = ship.Angle; 457 | shipstill = TRUE; 458 | /* Asteroids */ 459 | 460 | srand((unsigned) time(&t)); 461 | 462 | for (i=0; i<3*currentLevel; i++){ 463 | a = rand() % 2; 464 | if (a==0) tDIRX = 1; 465 | else 466 | tDIRX = -1; 467 | a = rand() % 2; 468 | if (a==0) tDIRY = 1; 469 | else 470 | tDIRY = -1; 471 | tX = rand() % 640; 472 | tY = rand() % 480; 473 | tSIZE = rand() % 3; 474 | addAsteroid(tX,tY,tDIRX, tDIRY, tSIZE); 475 | } 476 | /* Music */ 477 | Mix_PlayMusic(Theme, -1); 478 | } 479 | 480 | void CleanMemory(){ 481 | if (asteroids != NULL) deleteList(&asteroids); 482 | SDL_DestroyRenderer(ren1); 483 | SDL_DestroyWindow(win1); 484 | Mix_Quit(); 485 | IMG_Quit(); 486 | TTF_Quit(); 487 | SDL_Quit(); 488 | } 489 | 490 | 491 | /* ==========================================================*/ 492 | // Drawing Functions 493 | /* ==========================================================*/ 494 | 495 | void Draw(int X, int Y, SDL_Surface *Img) { 496 | SDL_Rect R; 497 | SDL_Texture *text; 498 | 499 | R.x = X; 500 | R.y = Y; 501 | R.w = Img->w; 502 | R.h = Img->h; 503 | text = SDL_CreateTextureFromSurface(ren1,Img); 504 | SDL_RenderCopy(ren1, text, NULL, &R); 505 | SDL_DestroyTexture(text); 506 | } 507 | 508 | void DrawAnimation(int X, int Y, int H, int W, int frame, SDL_Surface *Img) { 509 | SDL_Rect R, D; 510 | SDL_Texture *text; 511 | 512 | R.x = X; 513 | R.y = Y; 514 | R.w = H; 515 | R.h = W; 516 | D.x = H*frame; 517 | D.y = 0; 518 | D.w = W; 519 | D.h = W; 520 | text = SDL_CreateTextureFromSurface(ren1,Img); 521 | SDL_RenderCopy(ren1, text, &D, &R); 522 | SDL_DestroyTexture(text); 523 | } 524 | 525 | 526 | void DrawDynamicObject(OBJECT *Object){ 527 | SDL_Rect R; 528 | SDL_Texture *text; 529 | 530 | R.x = Object->X; 531 | R.y = Object->Y; 532 | R.w = Object->W; 533 | R.h = Object->H; 534 | text = SDL_CreateTextureFromSurface(ren1,Object->Img); 535 | SDL_RenderCopyEx(ren1, text, NULL, &R, Object->Angle,NULL, SDL_FLIP_NONE); 536 | SDL_DestroyTexture(text); 537 | } 538 | 539 | 540 | void DrawObject(OBJECT Object){ 541 | SDL_Rect R; 542 | SDL_Texture *text; 543 | 544 | R.x = Object.X; 545 | R.y = Object.Y; 546 | R.w = Object.W; 547 | R.h = Object.H; 548 | text = SDL_CreateTextureFromSurface(ren1,Object.Img); 549 | SDL_RenderCopyEx(ren1, text, NULL, &R, Object.Angle,NULL, SDL_FLIP_NONE); 550 | SDL_DestroyTexture(text); 551 | } 552 | void DrawLife(){ 553 | SDL_Rect rect; 554 | rect.x = 45; 555 | rect.y = 3; 556 | rect.w = lives; 557 | rect.h = 10; 558 | if(lives>0) { 559 | SDL_SetRenderDrawColor(ren1, 255,69,0,0); 560 | SDL_RenderDrawRect(ren1, &rect); 561 | SDL_RenderFillRect(ren1, &rect); 562 | } 563 | Draw(1,1, indicators); 564 | } 565 | void DrawText(char* string,int size, int x, int y,int fR, int fG, int fB,int bR, int bG, int bB, BOOL transparent) 566 | { 567 | 568 | //if (TTF_Init == NULL) exit(0); 569 | 570 | TTF_Font* font = TTF_OpenFont("data/fonts/FreeMonoBold.ttf", size); 571 | 572 | SDL_Color foregroundColor = { fR, fG, fB, 0 }; 573 | SDL_Color backgroundColor = { bR, bG, bB, 0 }; 574 | SDL_Surface* textSurface; 575 | 576 | if (transparent == TRUE) 577 | textSurface = TTF_RenderText_Blended(font, string, foregroundColor); 578 | else 579 | textSurface = TTF_RenderText_Shaded(font, string, foregroundColor,backgroundColor); 580 | 581 | SDL_Texture* texture1 = SDL_CreateTextureFromSurface(ren1, textSurface); 582 | 583 | SDL_Rect textLocation = { x, y, textSurface->w, textSurface->h }; 584 | 585 | SDL_RenderCopy(ren1, texture1, NULL, &textLocation); 586 | 587 | SDL_FreeSurface(textSurface); 588 | SDL_DestroyTexture(texture1); 589 | 590 | TTF_CloseFont(font); 591 | 592 | } 593 | 594 | /* ==========================================================*/ 595 | // FINAL SCREEN COMPOSITION = DRAW SCREEN 596 | /* ==========================================================*/ 597 | 598 | void DrawScreen() { 599 | int i, a; 600 | char pointstext[12]; 601 | char levelstr[12]; 602 | char beststr[30]; 603 | 604 | SDL_RenderClear(ren1); 605 | Draw(0,0,background); 606 | switch (ShipState){ 607 | case HALTED: ship.Img = shipSprite[0].Img; break; 608 | case UTHRUST: a=rand() & 1; ship.Img = shipSprite[a+1].Img; break; 609 | case DTHRUST: a=rand() & 1; ship.Img = shipSprite[a+3].Img; break; 610 | case LTHRUST: ship.Img = shipSprite[6].Img; break; 611 | case RTHRUST: ship.Img = shipSprite[5].Img; break; 612 | case DAMAGED: a=rand() & 1; ship.Img = shipSprite[a+7].Img; break; 613 | } 614 | if (!explosion) DrawObject(ship); 615 | 616 | if (asteroids != NULL) { 617 | for (i=0;i 0) { 623 | for (i=0;iLife == -1){ 675 | p->FX = p->FX + (p->DX*sinD(p->Angle)); 676 | p->FY = p->FY + (p->DY*cosD(p->Angle))*-1; 677 | p->X = round(p->FX); 678 | p->Y = round(p->FY); 679 | } else 680 | {//poof projectiles 681 | p->FX = p->FX + p->DX; 682 | p->FY = p->FY + p->DY; 683 | p->X = round(p->FX); 684 | p->Y = round(p->FY); 685 | } 686 | //Delete projectiles which get off the screen 687 | if (p->Life != -1) p->Life = p->Life -1; 688 | if (p->Y < -10 || p->Y > SCREEN_H + 10 || p-> X < -10 || p-> X > SCREEN_W + 10 || p->Life == 0) { 689 | deleteObject(&projectiles,i,TRUE); 690 | continue; 691 | } 692 | //Collision with Asteroids. 693 | for (j=0; jX,p->Y,p->X+p->W,p->Y+p->H,a->X,a->Y, 697 | a->X+a->W,a->Y+a->H) && p->Life == -1) { 698 | Mix_PlayChannel( 5, crash, 0); 699 | if(a->Life == 1 ) { 700 | deleteObject(&asteroids,j,TRUE); 701 | LaunchPoof(a->X, a->Y,debris,10); 702 | if (p->Img != debris) points = points + 1; 703 | continue; 704 | } 705 | if(a->Life == 2){ 706 | addAsteroid(a->X, a->Y, 1,1,2); 707 | addAsteroid(a->X, a->Y, -1,-1,2); 708 | deleteObject(&asteroids,j,TRUE); 709 | if (p->Img != debris) points = points + 2; 710 | } 711 | if(a->Life == 3){ 712 | addAsteroid(a->X, a->Y, 1,1,1); 713 | addAsteroid(a->X, a->Y, -1,-1,1); 714 | addAsteroid(a->X, a->Y, 1,-1,1); 715 | if (p->Img != debris) points = points + 3; 716 | deleteObject(&asteroids,j,TRUE); 717 | } 718 | deleteObject(&projectiles,i,TRUE); 719 | bcollision = TRUE; 720 | break; 721 | } 722 | } 723 | if (bcollision == TRUE) break; 724 | } 725 | } 726 | void rotateBy(OBJECT *Object, float D){ 727 | float temp; 728 | if (Mix_Playing(1) == 0) Mix_PlayChannel( 1, sound, 0); 729 | if(fabs(Object->Angle + D) < 181) { 730 | temp = Object->Angle + D; 731 | Object->Angle = round(temp); 732 | } else{ 733 | Object->Angle = Object->Angle * -1; 734 | } 735 | } 736 | 737 | 738 | void Ship_Behaviour(){ 739 | if (momentum == TRUE) { 740 | momentum=lerp(&velocity,&timetemp,100); 741 | if (reversed == FALSE) movePlayerXY(-velocity); 742 | else movePlayerXY(velocity); 743 | } else 744 | { 745 | velocity = SPEED; 746 | } 747 | if (ship.Y < -10) {ship.Y = SCREEN_H; ship.DY = SCREEN_H;} 748 | if (ship.Y > SCREEN_H+10) {ship.Y = 0; ship.DY = 0;} 749 | if (ship.X > SCREEN_W + 10) {ship.X = 0; ship.DX = 0;} 750 | if (ship.X < -10) {ship.X = SCREEN_W; ship.DX = SCREEN_W;} 751 | } 752 | 753 | void moveAsteroids(){ 754 | 755 | int i,j; 756 | OBJECT *p,*q; 757 | 758 | for (i=0; iX,p->Y, 762 | p->X+p->W,p->Y+p->H)) { 763 | p->DIRX = p->DIRX * -1; 764 | p->DIRY = p->DIRY * -1; 765 | ShipState = DAMAGED; 766 | lives = lives -1; 767 | if (Mix_Playing(4) == 0) Mix_PlayChannel(4, shield, 0); 768 | if(lives == 0) { 769 | //Game Over 770 | Mix_HaltChannel(-1); 771 | explosion = TRUE; 772 | if (bestScore < points) bestScore = points; 773 | points = 0; 774 | } 775 | 776 | } 777 | //Collision with Asteroids 778 | for (j=0; jX,p->Y+5,p->X+p->W-5,p->Y+p->H-5, 782 | q->X,q->Y,q->X+q->W,q->Y+q->H)) { 783 | p->DIRX = p->DIRX * -1; 784 | p->DIRY = p->DIRY * -1; 785 | p->DIRX = p->DIRX * -1; 786 | p->DIRY = p->DIRY * -1; 787 | } 788 | } 789 | } 790 | p->DX = p->DX + (1.5 * p->DIRX); 791 | p->DY = p->DY + (1.5 * p->DIRY); 792 | p->X = round(p->DX); 793 | p->Y = round(p->DY); 794 | p->Angle += 3.5; 795 | if (p->Y < -10) {p->Y = SCREEN_H; p->DY = SCREEN_H;} 796 | if (p->Y > SCREEN_H + 10) {p->Y = 0; p->DY = 0;} 797 | if (p->X > SCREEN_W + 10) {p->X = 0; p->DX = 0;} 798 | if (p->X < -10) {p->X = SCREEN_W; p->DX = SCREEN_W;} 799 | } 800 | //LEVEL ACCOMPLISH - NEW GAME 801 | if(length(&asteroids) == 0) { 802 | //Game Over 803 | Mix_HaltChannel(-1); 804 | //delete remaining projectiles 805 | deleteList(&projectiles); 806 | SDL_Delay(1000); 807 | currentLevel++; 808 | NewGame(currentLevel); 809 | } 810 | } 811 | 812 | void ShootPlayerBullet(){ 813 | if (SDL_GetTicks() - PlayerShootTime < 100) { 814 | //Do nothing 815 | } else{ 816 | PlayerShootTime = SDL_GetTicks(); 817 | Mix_PlayChannel(2, shot, 0); 818 | LaunchProjectile(ship.X+16, ship.Y-2, 20,20, projectile,-1); 819 | } 820 | 821 | } 822 | 823 | /* ==========================================================*/ 824 | // TIMERS 825 | /* ==========================================================*/ 826 | 827 | BOOL timer1(int *ticks, double *time, int ms){ 828 | BOOL value; 829 | if (SDL_GetTicks() - *time < ms) { 830 | value = TRUE; 831 | if (Mix_Playing(3) == 0) Mix_PlayChannel(3, expsnd, 0); 832 | } else{ 833 | *time = SDL_GetTicks(); 834 | if (*ticks < 6) { 835 | *ticks = *ticks +1; 836 | value = TRUE; 837 | }else { 838 | *ticks = 0; 839 | value = FALSE; 840 | currentLevel = 1; 841 | NewGame(currentLevel); 842 | } 843 | } 844 | return value; 845 | } 846 | 847 | BOOL lerp(double *value, double *time, int ms){ 848 | BOOL res; 849 | if (SDL_GetTicks() - *time < ms) { 850 | res = TRUE; 851 | } else{ 852 | *time = SDL_GetTicks(); 853 | if (*value > 0) { 854 | *value = *value -1; 855 | res = TRUE; 856 | }else { 857 | *value = 0; 858 | res = FALSE; 859 | } 860 | } 861 | return res; 862 | } 863 | 864 | 865 | /* ==========================================================*/ 866 | // FINAL UPDATE COMPOSITION 867 | /* ==========================================================*/ 868 | 869 | void UpdateGame(){ 870 | //if (Key(SDLK_q)) printf("Q\n"); 871 | oldX = ship.X; 872 | oldY = ship.Y; 873 | oldAngle = ship.Angle; 874 | if (Key(SDLK_f)) ToggleFullscreen(win1); 875 | if (Key(SDL_SCANCODE_SPACE)) {ShootPlayerBullet();} 876 | if (Key(SDL_SCANCODE_UP) || Key(SDLK_w)) {ShipState = UTHRUST; movePlayerXY(-SPEED);} 877 | if (Key(SDL_SCANCODE_DOWN) || Key(SDLK_s)) {ShipState = DTHRUST; movePlayerXY(SPEED);} 878 | if (Key(SDL_SCANCODE_RIGHT) || Key(SDLK_d)) {ShipState = RTHRUST; rotateBy(&ship, ROTATION);} 879 | if (Key(SDL_SCANCODE_LEFT) || Key(SDLK_a)) {ShipState = LTHRUST; rotateBy(&ship, -ROTATION);} 880 | if (keypressed) momentum = FALSE; 881 | if (shipstill) { 882 | //inertia/momentum 883 | if (ShipState == UTHRUST) {momentum = TRUE; reversed = FALSE;} 884 | if (ShipState == DTHRUST) {momentum = TRUE; reversed = TRUE;} 885 | ShipState = HALTED; 886 | if (Mix_Playing(1) != 0) Mix_FadeOutChannel(1,500); 887 | } 888 | if (mouseclicked == TRUE) {ShootPlayerBullet();} 889 | Ship_Behaviour(); 890 | moveAsteroids(); 891 | moveProjectiles(); 892 | if (ship.X != oldX || ship.Y != oldY || ship.Angle != oldAngle) shipstill = FALSE; 893 | else shipstill = TRUE; 894 | } 895 | 896 | /* ==========================================================*/ 897 | // MAIN LOOP HERE 898 | /* ==========================================================*/ 899 | void Main_Loop(){ 900 | /* Update + HandleEvents - Draw */ 901 | unsigned int LastTime, CurrentTime; 902 | 903 | LastTime = SDL_GetTicks(); 904 | while (Running==TRUE) { 905 | CurrentTime = SDL_GetTicks(); 906 | if (CurrentTime - LastTime > 1000) LastTime = CurrentTime - 60; 907 | while (CurrentTime - LastTime > 1000/30) { 908 | UpdateGame(); 909 | LastTime = LastTime + 30; 910 | } 911 | HandleEvents(); 912 | DrawScreen(); 913 | } 914 | } 915 | /* ---------------------------------------------- */ 916 | /* END */ 917 | /* ---------------------------------------------- */ 918 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velorek1/asteroid/4498cc92c4c4c2aebe7e6b45e24852e713e00235/screenshot.png --------------------------------------------------------------------------------