Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* See LICENSE file for copyright and license details. */
- #include <math.h>
- #include <stdbool.h>
- #include <stdlib.h>
- #include <time.h>
- #include <assert.h>
- #include <stdarg.h>
- #include "SDL/SDL.h"
- #include "SDL/SDL_opengl.h"
- #include "SDL/SDL_mixer.h"
- #include "SDL/SDL_ttf.h"
- #include "ubiqx/ubi_dLinkList.h"
- //#include "mcheck.h"
- /*
- (!)gprof asteroids -b | vim -
- (!)astyle asteroids.c -SUT8b
- (!)ctags asteroids.c
- (!)make && gdb -q asteroids.c -ex r -ex q
- gcc
- -Wall -Wextra --pedantic //all warnings, etc
- asteroids.c -o asteroids
- -lGL -lSDL -lSDL_mixer -lSDL_ttf -lGLU
- -lm -lc //link math and c libs
- -lubiqx //abstract primitives lib(for OBJ_LIST)
- -std=c99
- -g //for gdb
- -pg //for gprof
- ---TODO---
- *HIGH priority:
- -rules for getting EXP from destroyed targets (calculate target hit score)
- -split events() func
- -levels
- -rewrite kill_old_objects() func
- -mcheck
- -create player in safe pos
- -rewrite ext rendering
- -time + pause + missiles + particles
- *MEDIUM priority:
- -reloading progressbar
- -suckless.org-like makefile
- -replace astyle with gnu indent
- -licence
- -limit player speed, not just slowdown
- *LOW priority:
- -gettext lib support
- *later:
- -split OBJ_LIST to few lists for optimization of nested loops
- *already done:
- -for(OBJ_LIST) -> while(i)
- -'define TYPE_### #' -> 'enum(TYPE_###, ...)'
- -int x, int y -> vec2i pos
- -add targets & Dlazer
- -vsnprintf() for buttons text
- */
- #define uint unsigned int
- #define lint long int
- #define ulint unsigned long int
- #define M_PI 3.14159265358979323846
- enum
- {
- TYPE_PLAYER,
- TYPE_ROCK,
- TYPE_MISSILE,
- TYPE_PARTICLE,
- TYPE_STAR,
- TYPE_TARGET,
- TYPE_EXPLOSION,
- TYPE_CIRCLE,
- };
- //2d float vector(point)
- typedef struct vec2f vec2f;
- struct vec2f
- {
- float x, y;
- };
- //2d integer vector(point)
- typedef struct vec2i vec2i;
- struct vec2i
- {
- int x, y;
- };
- typedef struct obj obj;
- struct obj
- {
- ubi_dlNode node; //see 'ubi_dlList OBJ_LIST'
- vec2f pos; //position
- vec2f vel; //velocity
- float a; //angle
- float va; //rotation speed
- float size; //
- Uint32 creation_time; //
- int type; //see #define TYPE_######
- bool del; //see delete_marked_objects()
- };
- typedef struct gui_button gui_button;
- struct gui_button
- {
- ubi_dlNode node;
- char* name; //button's idintifier
- char* text; //displayed info
- vec2i pos; //position
- vec2i size; //size
- vec2i tex_size; //texture's size
- uint tex_id; //texture's ID.
- };
- /* forward declarations */
- int rnd(int min, int max);
- float rndf(float min, float max);
- float deg2rad(float degrees);
- //float rad2deg(float radians);
- float get_dist(vec2f p1, vec2f p2);
- bool intersect_circle_line(vec2f c, float rad, vec2f p1, vec2f p2);
- void init_sdl();
- void init_opengl();
- void init_sound();
- void init_interface();
- void init_all();
- void cleanup();
- obj* add_player();
- obj* add_target();
- obj* add_rock();
- obj* add_star();
- obj* add_circle(vec2f pos);
- obj* add_explosion(vec2f pos, float power);
- obj* add_particle(vec2f pos);
- obj* add_missile();
- void kill_player(obj *o);
- void kill_target(obj *o);
- void kill_rock(obj *o);
- void kill_star(obj *o);
- void kill_circle(obj *o);
- void kill_explosion(obj *o);
- void kill_particle(obj *o);
- void kill_missle(obj *o);
- void draw_player(obj *o);
- void draw_target(obj *o);
- void draw_rock(obj *o);
- void draw_star(obj *o);
- void draw_circle(obj *o);
- void draw_explosion(obj *o);
- void draw_particle(obj *o);
- void draw_missle(obj *o);
- void draw_gui();
- void draw_obj(obj *o);
- void draw_playe2targets_lines();
- void draw_death_rays();
- void events();
- void logic();
- void draw();
- bool can_player_shoot();
- void accelerate_player();
- void player_rocks_collisions();
- void move_objects();
- void teleport_objects();
- void missles_rocks_collisions();
- void kill_old_objects();
- void change_targets_speed_and_direction();
- void do_objects_tails();
- void stretch_circles();
- void delete_marked_objects();
- void particle_explosion(vec2f pos, vec2f vel, int power);
- int str2tex(char* text, vec2i *tex_size);
- void change_button_text(char* name, char* format, ...);
- bool add_button(int x, int y, int w, int h, char* name, char *text);
- /* global variables */
- ubi_dlList OBJ_LIST[1] = {{ NULL, NULL, 0 }};
- ubi_dlList GUI_LIST[1] = {{ NULL, NULL, 0 }};
- obj* PLAYER = NULL;
- float PLAYER_ACCELERATION = 0;
- float PLAYER_SIZE = 6;
- int PARTICLE_COUNT = 0;
- int MAX_PARTICLE_COUNT = 1000;
- Uint32 PARTICLE_LIVETIME = 800;
- int ROCKS_COUNT = 0;
- int MAX_ROCK_COUNT = 9;
- int MIN_ROCK_SPLIT_SIZE = 6;
- float MIN_ROCK_SPEED = 1;
- float MAX_ROCK_SPEED = 3;
- float MIN_ROCK_SIZE = 20;
- float MAX_ROCK_SIZE = 30;
- int MAX_TARGET_COUNT = 5;
- int TARGETS_COUNT = 0;
- float MIN_TARGET_SIZE = 6;
- float MAX_TARGET_SIZE = 9;
- float DLAZER_DIST = 350; //death lazer distance
- Uint32 RELOAD_TIME = 1500;
- Uint32 LAST_SHOOT_TIME = 0;
- bool IS_PLAYER_SHOOTING = false;
- Uint32 MISSILE_LIVETIME = 1500;
- float MISSILE_SPEED = 8;
- float MISSLE_SIZE = 2;
- float MAX_MISSLE_SPREAD = 3;
- Uint32 CIRCLE_LIVETIME = 400;
- Uint32 EXPLOSION_LIVETIME = 400;
- Mix_Chunk* SND_BAM = NULL;
- Mix_Chunk* SND_MISSLE = NULL;
- Mix_Chunk* SND_MOVING = NULL;
- int motor_channel = -1;
- bool IS_PROG_RUNNING = true;
- bool PAUSE = false;
- int FUEL = 0;
- int AMMO = 0;
- int EXP = 0;
- int LIVES = 3;
- int LEVEL = 1;
- float FPS = 60;
- vec2i SCR = {500, 500};
- vec2i WORLD = {1000, 1000};
- TTF_Font* FONT = NULL;
- float LINE_WIDTH = 1.5;
- int
- rnd(int min, int max)
- {
- assert(min <= max);
- return (rand()%(max-min+1)+min);
- }
- float
- rndf(float min, float max)
- {
- assert(min <= max);
- return ((max-min)*((float)rand()/RAND_MAX))+min;
- }
- float
- deg2rad(float degrees)
- {
- return(degrees*(M_PI/180.));
- }
- #if(0)
- float
- rad2deg(float radians)
- {
- return(radians*(180./M_PI));
- }
- #endif
- void
- init_sdl()
- {
- SDL_Init(SDL_INIT_EVERYTHING);
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- SDL_SetVideoMode(SCR.x, SCR.y, 32, SDL_OPENGL);
- }
- void
- init_opengl()
- {
- glViewport(0, 0, SCR.x, SCR.y);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- int w = WORLD.x/2, h = WORLD.y/2;
- gluOrtho2D(-w, w, -h, h);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glClearColor(0, 0, 0, 1);
- glLineWidth(LINE_WIDTH);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
- glHint(GL_POINT_SMOOTH_HINT, GL_DONT_CARE);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_POINT_SMOOTH);
- glEnable(GL_BLEND);
- }
- obj*
- add_explosion(vec2f p, float power)
- {
- obj *t = calloc(sizeof(obj), 1);
- t->pos.x = p.x;
- t->pos.y = p.y;
- t->size = rndf(power*30, power*35);
- t->type = TYPE_EXPLOSION;
- t->creation_time = SDL_GetTicks();
- ubi_dlAddTail(OBJ_LIST, t);
- return(t);
- }
- obj*
- add_circle(vec2f p)
- {
- obj *t = calloc(sizeof(obj), 1);
- t->pos.x = p.x;
- t->pos.y = p.y;
- t->size = 5;
- t->type = TYPE_CIRCLE;
- t->creation_time = SDL_GetTicks();
- ubi_dlAddTail(OBJ_LIST, t);
- return(t);
- }
- obj*
- add_target()
- {
- obj *t = calloc(sizeof(obj), 1);
- t->pos.x = rnd(-(WORLD.x/2), (WORLD.x/2));
- t->pos.y = rnd(-(WORLD.y/2), (WORLD.y/2));
- t->size = rndf(MIN_TARGET_SIZE, MAX_TARGET_SIZE);
- t->type = TYPE_TARGET;
- ubi_dlAddTail(OBJ_LIST, t);
- TARGETS_COUNT++;
- add_circle(t->pos);
- return(t);
- }
- obj*
- add_rock()
- {
- obj *r = calloc(sizeof(obj), 1);
- r->pos.x = rnd(-(WORLD.x/2), (WORLD.x/2));
- r->pos.y = rnd(-(WORLD.y/2), (WORLD.y/2));
- r->a = rnd(0, 360);
- float speed = rndf(MIN_ROCK_SPEED, MAX_ROCK_SPEED);
- r->vel.x = cosf(deg2rad(r->a))*speed;
- r->vel.y = sinf(deg2rad(r->a))*speed;
- r->va = rnd(-10, 10);
- r->size = rnd(MIN_ROCK_SIZE, MAX_ROCK_SIZE);
- r->type = TYPE_ROCK;
- ROCKS_COUNT++;
- ubi_dlAddTail(OBJ_LIST, r);
- return(r);
- }
- obj*
- add_star()
- {
- obj *s = calloc(sizeof(obj), 1);
- s->pos.x = rnd(-WORLD.x/2, WORLD.x/2);
- s->pos.y = rnd(-WORLD.y/2, WORLD.y/2);
- s->size = rndf(0.5, 3);
- s->type = TYPE_STAR;
- ubi_dlAddTail(OBJ_LIST, s);
- return(s);
- }
- obj*
- add_particle(vec2f pos)
- {
- obj *p = calloc(sizeof(obj), 1);
- p->pos.x = pos.x;
- p->pos.y = pos.y;
- p->a = rnd(0, 360);
- float speed = rndf(1, 5);
- p->vel.x = cosf(deg2rad(p->a))*speed;
- p->vel.y = sinf(deg2rad(p->a))*speed;
- p->size = rndf(0.2, 1.0);
- p->type = TYPE_PARTICLE;
- ubi_dlAddTail(OBJ_LIST, p);
- p->creation_time = SDL_GetTicks();
- PARTICLE_COUNT++;
- return(p);
- }
- obj*
- add_missile()
- {
- obj *b = calloc(sizeof(obj), 1);
- float spread = MAX_MISSLE_SPREAD;
- float a = PLAYER->a + rnd(-spread,spread);
- b->pos = PLAYER->pos;
- b->vel.x = PLAYER->vel.x + (cosf(deg2rad(a)) * MISSILE_SPEED);
- b->vel.y = PLAYER->vel.y + (sinf(deg2rad(a)) * MISSILE_SPEED);
- b->a = a;
- b->type = TYPE_MISSILE;
- b->size = MISSLE_SIZE;
- ubi_dlAddTail(OBJ_LIST, b);
- b->creation_time = SDL_GetTicks();
- return(b);
- }
- obj*
- add_player()
- {
- PLAYER = calloc(sizeof(obj), 1);
- PLAYER->size = PLAYER_SIZE;
- PLAYER->type = TYPE_PLAYER;
- PLAYER->pos.x = rndf(-WORLD.x/2, WORLD.x/2);
- PLAYER->pos.y = rndf(-WORLD.y/2, WORLD.y/2);
- PLAYER->a = rnd(0, 360);
- ubi_dlAddTail(OBJ_LIST, PLAYER);
- LAST_SHOOT_TIME = SDL_GetTicks()-RELOAD_TIME;
- FUEL = 1500;
- AMMO = 20;
- PLAYER_ACCELERATION = 0;
- IS_PLAYER_SHOOTING = false;
- LIVES --;
- change_button_text("fuel", "fuel: %i", FUEL);
- change_button_text("ammo", "ammo: %i", AMMO);
- change_button_text("live", "lives: %i", LIVES);
- add_circle(PLAYER->pos);
- return(PLAYER);
- }
- void
- kill_player(obj *o)
- {
- particle_explosion(PLAYER->pos, PLAYER->vel, 35);
- add_explosion(o->pos, 33);
- PLAYER = NULL;
- change_button_text("live", "lives: %i", LIVES);
- Mix_PlayChannel(-1, SND_BAM, 0);
- }
- void
- kill_target(obj *o)
- {
- #if(1)//TODO
- EXP += 30;
- #else
- float x = (float)(o->creation_time - SDL_GetTicks())/1000;
- EXP += 30;
- #endif
- TARGETS_COUNT--;
- change_button_text("exp", "exp: %i", EXP);
- //50, 200, 450, 800, 1250, 1800, 2450, 3200, 4050
- if ((EXP >= pow(LEVEL, 2)*50))
- {
- LEVEL++;
- change_button_text("level", "level: %i", LEVEL);
- //TODO change some parameters to make game harder
- }
- add_explosion(o->pos, 15);
- particle_explosion(o->pos, o->vel, 60);
- Mix_PlayChannel(-1, SND_BAM, 0);
- }
- void
- kill_rock(obj *o)
- {
- ROCKS_COUNT--;
- if (o->size > MIN_ROCK_SPLIT_SIZE)
- {
- int x = rnd(1, 3);
- while (x--)
- {
- obj *r = add_rock();
- r->pos.x = o->pos.x;
- r->pos.y = o->pos.y;
- r->size = o->size/rndf(1.3, 2);
- }
- }
- particle_explosion(o->pos, o->vel, o->size*3);
- add_explosion(o->pos, o->size/2);
- Mix_PlayChannel(-1, SND_BAM, 0);
- }
- void
- kill_star(obj *o)
- {
- assert(o != NULL);
- }
- void
- kill_circle(obj *o)
- {
- assert(o != NULL);
- }
- void
- kill_explosion(obj *o)
- {
- assert(o != NULL);
- }
- void
- kill_particle(obj *o)
- {
- assert(o != NULL);
- PARTICLE_COUNT--;
- }
- void
- kill_missle(obj *o)
- {
- assert(o != NULL);
- }
- void
- draw_player(obj *o)
- {
- assert(o != NULL);
- glColor3f(1, 1, 1);
- glBegin(GL_LINES);
- {
- glVertex2d(-1, -1);
- glVertex2d(+1, 0);
- glVertex2d(-1, +1);
- glVertex2d(+1, 0);
- }
- glEnd();
- }
- void
- draw_target(obj *o)
- {
- assert(o != NULL);
- glColor3f(1, 0, 0);
- //glColor3f(1, 1, 1);
- glBegin(GL_LINE_STRIP);
- float a;
- for (a=0; a<=360; a+=120)
- {
- float x,y;
- x = sinf(deg2rad(a));
- y = cosf(deg2rad(a));
- glVertex2d(x, y);
- }
- glVertex2d(0, 0);
- glEnd();
- }
- void
- draw_rock(obj *o)
- {
- assert(o != NULL);
- glColor3f(1, 1, 1);
- glBegin(GL_LINE_STRIP);
- float i;
- for (i=0; i<=360; i+=60)
- {
- float x,y;
- x = sinf(deg2rad(i));
- y = cosf(deg2rad(i));
- glVertex2d(x, y);
- }
- //glVertex2d(0, 0);
- glEnd();
- }
- void
- draw_star(obj *o)
- {
- assert(o != NULL);
- glColor4f(1, 1, 1, rndf(0, 0.5));
- //glColor4f(rndf(0,1), rndf(0,1), rndf(0,1), rndf(0,1));
- glBegin(GL_LINES);
- glVertex2d(0, 0);
- glVertex2d(+0.5, 0);
- glEnd();
- }
- void
- draw_circle(obj *o)
- {
- assert(o != NULL);
- glBegin(GL_LINE_STRIP);
- float time = SDL_GetTicks() - o->creation_time;
- float t = 1. - time/CIRCLE_LIVETIME;
- glColor4f(1, 1, 1, t);
- //glColor4f(1, 1, 1, 0.3);
- float i;
- for (i=0; i<=360; i+=10)
- {
- float x,y;
- x = sinf(deg2rad(i));
- y = cosf(deg2rad(i));
- glVertex2d(x, y);
- }
- glEnd();
- }
- void
- draw_explosion(obj *o)
- {
- assert(o != NULL);
- glBegin(GL_POLYGON);
- float time = SDL_GetTicks() - o->creation_time+150;
- float t = 1. - time/EXPLOSION_LIVETIME;
- glColor4f(1, 1, 1, t);
- glVertex2d(0, 0);
- glColor4f(1, 1, 1, 0.02);
- float i;
- for (i=0; i<=360; i+=30)
- {
- float x,y;
- x = sinf(deg2rad(i));
- y = cosf(deg2rad(i));
- glVertex2d(x, y);
- }
- glEnd();
- }
- void
- draw_particle(obj *o)
- {
- assert(o != NULL);
- float time = SDL_GetTicks() - o->creation_time;
- float t = 1. - time/PARTICLE_LIVETIME;
- glColor4f(1, 1, 1, t);
- //glColor4f(rndf(0,1), rndf(0,1), rndf(0,1), rndf(0.5,1)*t);
- glBegin(GL_LINES);
- glVertex2d(-1, 0);
- glVertex2d(+1, 0);
- glEnd();
- }
- void
- draw_missle(obj *o)
- {
- assert(o != NULL);
- glColor3f(1, 1, 1);
- glBegin(GL_LINES);
- glVertex2d(-1, 0);
- glVertex2d(+1, 0);
- glEnd();
- }
- void
- draw_button(gui_button *b)
- {
- glPushMatrix();
- glTranslatef(-WORLD.x/2+10, WORLD.y/2-30-10, 0);
- glTranslatef(b->pos.x, b->pos.y, 0);
- glBindTexture(GL_TEXTURE_2D, b->tex_id);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glBegin(GL_QUADS);
- {
- glTexCoord2d(0, 0);
- glVertex2d(0, b->tex_size.y);
- glTexCoord2d(1, 0);
- glVertex2d(b->tex_size.x, b->tex_size.y);
- glTexCoord2d(1, 1);
- glVertex2d(b->tex_size.x, 0);
- glTexCoord2d(0, 1);
- glVertex2d(0, 0);
- }
- glEnd();
- glPopMatrix();
- }
- void
- draw_gui()
- {
- glLoadIdentity();
- glColor4f(1, 1, 1, 0.4);
- glEnable(GL_TEXTURE_2D);
- gui_button *i = (gui_button*)ubi_dlFirst(GUI_LIST);
- while (i)
- {
- draw_button(i);
- i = (gui_button*)ubi_dlNext(i);
- }
- glDisable(GL_TEXTURE_2D);
- }
- void
- draw_obj(obj *o)
- {
- glPushMatrix();
- glTranslatef(o->pos.x, o->pos.y, 0);
- glColor3f(1, 1, 1);
- #if(0) //draw velocity vectors
- if (PAUSE && o->type != TYPE_PARTICLE)
- {
- glColor4f(1, 0, 0, 0.7);
- glBegin(GL_LINES);
- glVertex2d(0, 0);
- glVertex2d(o->vel.x*15, o->vel.y*15);
- glEnd();
- }
- #endif
- glRotatef(o->a, 0, 0, 1);
- glScalef(o->size, o->size, 0);
- if (o->type == TYPE_PLAYER) draw_player(o);
- if (o->type == TYPE_TARGET) draw_target(o);
- if (o->type == TYPE_EXPLOSION) draw_explosion(o);
- if (o->type == TYPE_CIRCLE) draw_circle(o);
- if (o->type == TYPE_ROCK) draw_rock(o);
- if (o->type == TYPE_MISSILE) draw_missle(o);
- if (o->type == TYPE_STAR) draw_star(o);
- if (o->type == TYPE_PARTICLE) draw_particle(o);
- glPopMatrix();
- }
- void
- draw_playe2targets_lines()
- {
- glLineWidth(0.3);
- glColor4f(1, 1, 1, 0.4);
- obj *i = (obj*)ubi_dlFirst(OBJ_LIST);
- while (i)
- {
- if (PLAYER && i->type == TYPE_TARGET)
- {
- glBegin(GL_LINES);
- glVertex2d(PLAYER->pos.x, PLAYER->pos.y);
- glVertex2d(i->pos.x, i->pos.y);
- glEnd();
- }
- i = (obj*)ubi_dlNext(i);
- }
- glLineWidth(LINE_WIDTH);
- }
- void
- draw_death_rays()
- {
- obj *i = (obj*)ubi_dlFirst(OBJ_LIST);
- while (i)
- {
- if (i->type == TYPE_TARGET)
- {
- obj *j = (obj*)ubi_dlFirst(OBJ_LIST);
- while (j)
- {
- if (j->type == TYPE_TARGET &&
- get_dist(i->pos, j->pos) < DLAZER_DIST)
- {
- glColor4f(1, 0, 0, rndf(0, 1));
- glLineWidth(rndf(0, 3));
- glBegin(GL_LINES);
- glVertex2f(i->pos.x, i->pos.y);
- glVertex2f(j->pos.x, j->pos.y);
- glEnd();
- glLineWidth(LINE_WIDTH);
- }
- j = (obj*)ubi_dlNext(j);
- }
- }
- i = (obj*)ubi_dlNext(i);
- }
- }
- void
- draw()
- {
- glClear(GL_COLOR_BUFFER_BIT);
- glLoadIdentity();
- draw_gui();
- draw_death_rays();
- draw_playe2targets_lines();
- obj *i = (obj*)ubi_dlFirst(OBJ_LIST);
- while (i)
- {
- draw_obj(i);
- i = (obj*)ubi_dlNext(i);
- }
- SDL_GL_SwapBuffers();
- }
- bool
- can_player_shoot()
- {
- Uint32 time = LAST_SHOOT_TIME+RELOAD_TIME;
- return(AMMO > 0 && SDL_GetTicks() > time);
- }
- void
- events()
- {
- SDL_Event E;
- while (SDL_PollEvent(&E))
- {
- if (E.type == SDL_QUIT)
- {
- IS_PROG_RUNNING = false;
- }
- //general keys(works if player is dead or alive)
- if (E.type == SDL_KEYUP)
- {
- switch (E.key.keysym.sym)
- {
- case SDLK_ESCAPE:
- case SDLK_q:
- IS_PROG_RUNNING = false;
- break;
- case SDLK_p:
- PAUSE = !PAUSE;
- break;
- case SDLK_o:
- if (MAX_PARTICLE_COUNT)
- {
- MAX_PARTICLE_COUNT = 0;
- }
- else
- {
- MAX_PARTICLE_COUNT = 1200;
- }
- break;
- case SDLK_0:
- FPS += 2;
- change_button_text("fps", "fps: %i", FPS);
- break;
- case SDLK_9:
- FPS -= 2;
- change_button_text("fps", "fps: %i", FPS);
- break;
- default:
- break;
- }
- }
- if (!PLAYER)
- {
- if (E.type == SDL_KEYUP)
- {
- switch (E.key.keysym.sym)
- {
- case SDLK_RETURN:
- add_player();
- if (LIVES == 0)
- {
- FUEL = 0;
- AMMO = 0;
- EXP = 0;
- LIVES = 3;
- LEVEL = 1;
- change_button_text("fuel", "fuel: %i", FUEL);
- change_button_text("ammo", "ammo: %i", AMMO);
- change_button_text("exp", "exp: %i", EXP);
- change_button_text("live", "lives: %i", LIVES);
- change_button_text("level", "level: %i", LEVEL);
- }
- break;
- default:
- break;
- }
- }
- }
- if (PLAYER)
- {
- if (E.type == SDL_KEYDOWN)
- {
- switch (E.key.keysym.sym)
- {
- case SDLK_LEFT:
- PLAYER->va += 3;
- break;
- case SDLK_RIGHT:
- PLAYER->va -= 3;
- break;
- case SDLK_SPACE:
- IS_PLAYER_SHOOTING = true;
- break;
- case SDLK_UP:
- PLAYER_ACCELERATION += 0.08;
- if (motor_channel < 0)
- {
- motor_channel = Mix_PlayChannel(-1, SND_MOVING, -1);
- }
- break;
- default:
- break;
- }
- }
- if (E.type == SDL_KEYUP)
- {
- switch (E.key.keysym.sym)
- {
- case SDLK_RIGHT:
- PLAYER->va += 3;
- break;
- case SDLK_LEFT:
- PLAYER->va -= 3;
- break;
- case SDLK_DOWN:
- break;
- case SDLK_UP:
- PLAYER_ACCELERATION = 0;
- Mix_HaltChannel(motor_channel);
- motor_channel = -1;
- break;
- case SDLK_SPACE:
- IS_PLAYER_SHOOTING = false;
- break;
- case SDLK_RETURN:
- FUEL += 500;
- AMMO += 20;
- default:
- break;
- }
- }
- }
- }
- }
- void
- accelerate_player()
- {
- //float oldx = PLAYER->vx, oldy = PLAYER->vy;
- if (FUEL > 0 && (PLAYER_ACCELERATION || PLAYER->va))
- {
- FUEL--;
- change_button_text("fuel", "fuel: %i", FUEL);
- }
- else
- {
- PLAYER_ACCELERATION = 0;
- PLAYER->va = 0;
- }
- float acc_coeff = abs(PLAYER->va)*0.015 + PLAYER_ACCELERATION;
- PLAYER->vel.x += cosf(deg2rad(PLAYER->a)) * acc_coeff;
- PLAYER->vel.y += sinf(deg2rad(PLAYER->a)) * acc_coeff;
- #if(0) //limit PLAYER speed //TODO
- float limit = 4;
- if (sqrt(pow(PLAYER->vx,2) + pow(PLAYER->vy,2)) > limit)
- {
- PLAYER->vx = oldx;
- PLAYER->vy = oldy;
- }
- #endif
- #if(1) //slowdown
- PLAYER->vel.x *= 0.995;
- PLAYER->vel.y *= 0.995;
- #endif
- }
- void
- move_objects()
- {
- obj *i = (obj*)ubi_dlFirst(OBJ_LIST);
- while (i)
- {
- i->a += i->va;
- i->pos.x += i->vel.x;
- i->pos.y += i->vel.y;
- i = (obj*)ubi_dlNext(i);
- }
- }
- void
- teleport_objects()
- {
- float w2 = WORLD.x / 2.;
- float h2 = WORLD.y / 2.;
- obj *i = (obj*)ubi_dlFirst(OBJ_LIST);
- while (i)
- {
- if (i->pos.x > +w2) i->pos.x = -w2;
- if (i->pos.x < -w2) i->pos.x = +w2;
- if (i->pos.y > +h2) i->pos.y = -h2;
- if (i->pos.y < -h2) i->pos.y = +h2;
- i = (obj*)ubi_dlNext(i);
- }
- }
- float
- get_dist(vec2f p1, vec2f p2)
- {
- float dx = p1.x - p2.x;
- float dy = p1.y - p2.y;
- float dist = sqrt(pow(dx, 2) + pow(dy, 2));
- return(dist);
- }
- void
- player_rocks_collisions()
- {
- obj *i = (obj*)ubi_dlFirst(OBJ_LIST);
- while (i)
- {
- float size = i->size + PLAYER->size;
- if ((i->type == TYPE_ROCK || i->type == TYPE_TARGET)
- && get_dist(i->pos, PLAYER->pos) < size)
- {
- //i->del = true;
- PLAYER->del = true;
- return;
- }
- i = (obj*)ubi_dlNext(i);
- }
- }
- void
- missles_rocks_collisions()
- {
- obj *i = (obj*)ubi_dlFirst(OBJ_LIST);;
- while (i)
- {
- if (i->type == TYPE_MISSILE && !(i->del))
- {
- obj *j = (obj*)ubi_dlFirst(OBJ_LIST);;
- while (j)
- {
- float size = j->size + i->size;
- if ((j->type == TYPE_TARGET || j->type == TYPE_ROCK)
- && !(j->del)
- && get_dist(i->pos, j->pos) < size)
- {
- i->del = true;
- j->del = true;
- }
- j = (obj*)ubi_dlNext(j);
- }
- }
- i = (obj*)ubi_dlNext(i);
- }
- }
- void
- kill_old_objects() //TODO
- {
- Uint32 time = SDL_GetTicks();
- obj *i = (obj*)ubi_dlFirst(OBJ_LIST);
- while (i)
- {
- if (i->type == TYPE_MISSILE && time > (i->creation_time + MISSILE_LIVETIME))
- i->del = true;
- if (i->type == TYPE_PARTICLE && time > (i->creation_time + PARTICLE_LIVETIME))
- i->del = true;
- if (i->type == TYPE_EXPLOSION && time > (i->creation_time + EXPLOSION_LIVETIME))
- i->del = true;
- i = (obj*)ubi_dlNext(i);
- }
- }
- void
- particle_explosion(vec2f pos, vec2f vel, int power)
- {
- while (power--)
- {
- if (PARTICLE_COUNT < MAX_PARTICLE_COUNT)
- {
- obj *p = add_particle(pos);
- p->vel.x += vel.x;
- p->vel.y += vel.y;
- }
- }
- }
- void
- player_shoot()
- {
- if (IS_PLAYER_SHOOTING && can_player_shoot())
- {
- add_missile();
- Mix_PlayChannel(-1, SND_MISSLE, 0);
- LAST_SHOOT_TIME = SDL_GetTicks();
- AMMO--;
- change_button_text("ammo", "ammo:%i", AMMO);
- #if(0)
- {
- obj *i = (obj*)ubi_dlFirst(OBJ_LIST);;
- while (i)
- {
- if (i->type == TYPE_TARGET)
- {
- float a = rnd(0, 360);
- float speed = rndf(1, 3);
- i->vel.x = cosf(deg2rad(a))*speed;
- i->vel.y = sinf(deg2rad(a))*speed;
- i->va = rnd(-9, 9);
- }
- i = (obj*)ubi_dlNext(i);
- }
- }
- #endif
- }
- }
- // if obj->del == true then delete obj from OBJ_LIST and free it
- // called by 'logic()'
- void
- delete_marked_objects()
- {
- obj *i = (obj*)ubi_dlFirst(OBJ_LIST);
- while (i)
- {
- obj *next = (obj*)ubi_dlNext(i);
- if (i->del)
- {
- if (i->type == TYPE_ROCK) kill_rock(i);
- if (i->type == TYPE_PARTICLE) kill_particle(i);
- if (i->type == TYPE_TARGET) kill_target(i);
- if (i->type == TYPE_PLAYER) kill_player(i);
- free(ubi_dlRemove(OBJ_LIST, (ubi_dlNodePtr)i));
- }
- i = next;
- }
- }
- void
- change_targets_speed_and_direction()
- {
- obj *i = (obj*)ubi_dlFirst(OBJ_LIST);;
- while (i)
- {
- if (i->type == TYPE_TARGET && !rnd(0, 250))
- {
- float a = rnd(0, 360);
- float speed = rndf(1, 3); // diffuculty level
- i->vel.x = cosf(deg2rad(a))*speed;
- i->vel.y = sinf(deg2rad(a))*speed;
- i->va = rnd(-9, 9);
- }
- i = (obj*)ubi_dlNext(i);
- }
- }
- void
- do_objects_tails()
- {
- obj *i = (obj*)ubi_dlFirst(OBJ_LIST);;
- while (i)
- {
- if (i->type == TYPE_MISSILE && rnd(0,1))
- {
- if (PARTICLE_COUNT < MAX_PARTICLE_COUNT)
- {
- obj *p = add_particle(i->pos);
- float a = rnd(-5,5) + i->a + 180;
- p->vel.x = cosf(deg2rad(a)) * rndf(2,4);
- p->vel.y = sinf(deg2rad(a)) * rndf(2,4);
- p->a = a;
- }
- }
- i = (obj*)ubi_dlNext(i);
- }
- if (PLAYER && (PLAYER_ACCELERATION > 0.02 || PLAYER->va))
- {
- if (PARTICLE_COUNT < MAX_PARTICLE_COUNT)
- {
- obj *p = add_particle(PLAYER->pos);
- float a = PLAYER->a + 180. + rnd(-15,15);
- float speed = rndf(2,6);
- p->vel.x = cosf(deg2rad(a))*speed;
- p->vel.y = sinf(deg2rad(a))*speed;
- p->a = a;
- }
- }
- }
- bool
- intersect_circle_line(vec2f cpos, float crad, vec2f p1, vec2f p2)
- {
- float x1 = p1.x - cpos.x;
- float y1 = p1.y - cpos.y;
- float x2 = p2.x - cpos.x;
- float y2 = p2.y - cpos.y;
- float dx = x2-x1;
- float dy = y2-y1;
- float a = dx*dx + dy*dy;
- float b = 2. * (x1*dx + y1*dy);
- float c = x1*x1 + y1*y1 - crad*crad;
- if (-b < 0) return (c < 0);
- if (-b < (2.*a)) return (4.*a*c-b*b < 0);
- return (a+b+c < 0);
- }
- void
- stretch_circles()
- {
- obj *i = (obj*)ubi_dlFirst(OBJ_LIST);
- while (i)
- {
- if (i->type == TYPE_CIRCLE)
- {
- i->size *= 1.28;
- i->size += 0.3;
- if (i->size > 800)
- {
- i->del = true;
- }
- }
- i = (obj*)ubi_dlNext(i);
- }
- }
- void
- death_rays_logic()
- {
- obj *i = (obj*)ubi_dlFirst(OBJ_LIST);
- while (i)
- {
- if (i->type == TYPE_TARGET)
- {
- obj *j = (obj*)ubi_dlFirst(OBJ_LIST);
- while (j)
- {
- if (j->type == TYPE_TARGET
- && get_dist(i->pos, j->pos) < DLAZER_DIST
- && intersect_circle_line(PLAYER->pos, PLAYER->size, i->pos, j->pos))
- {
- PLAYER->del = true;
- }
- j = (obj*)ubi_dlNext(j);
- }
- }
- i = (obj*)ubi_dlNext(i);
- }
- }
- void
- logic()
- {
- if (PAUSE) return;
- if (PLAYER)
- {
- accelerate_player();
- player_rocks_collisions();
- death_rays_logic();
- player_shoot();
- }
- change_targets_speed_and_direction();
- move_objects();
- teleport_objects();
- do_objects_tails();
- missles_rocks_collisions();
- kill_old_objects();
- stretch_circles();
- if (ROCKS_COUNT < MAX_ROCK_COUNT && !rnd(0, 200))
- {
- add_rock();
- }
- if (TARGETS_COUNT < MAX_TARGET_COUNT && !rnd(0, 100))
- {
- add_target();
- }
- delete_marked_objects();
- }
- void
- init_sound()
- {
- int rate = 44100;
- Uint16 format = MIX_DEFAULT_FORMAT;
- int channels = 1;
- int buffers = 1024;
- if (Mix_OpenAudio(rate, format, channels, buffers))
- {
- printf("Unable to open audio!\n");
- exit(EXIT_FAILURE);
- }
- SND_MISSLE = Mix_LoadWAV("lounch_rocket.ogg");
- SND_BAM = Mix_LoadWAV("bam.ogg");
- SND_MOVING = Mix_LoadWAV("motor.ogg");
- }
- //generates opengl texture from 'char *text'
- //returns texture ID (see glGenTextures)
- //returns texture width and heigh
- int
- str2tex(char *text, vec2i *tex_size)
- {
- SDL_Color color = {255, 255, 255, 0};
- SDL_Surface *txt = TTF_RenderUTF8_Blended(FONT, text, color);
- uint id = 0;
- glGenTextures(1, &id);
- glBindTexture(GL_TEXTURE_2D, id);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, txt->w, txt->h,
- 0, GL_BGRA, GL_UNSIGNED_BYTE, txt->pixels);
- tex_size->x = txt->w;
- tex_size->y = txt->h;
- SDL_FreeSurface(txt);
- return((int)id);
- }
- void
- change_button_text(char* name, char* format, ...)
- {
- gui_button *i = (gui_button*)ubi_dlFirst(GUI_LIST);
- char str[80];
- va_list ptr;
- va_start(ptr, format);
- while (i)
- {
- if (!strcmp(i->name, name))
- {
- glDeleteTextures(1, &(i->tex_id));
- vsnprintf(str, 80, format, ptr);
- i->tex_id = str2tex(str, &(i->tex_size));
- va_end(ptr);
- return;
- }
- i = (gui_button*)ubi_dlNext(i);
- }
- }
- bool
- add_button(int x, int y, int w, int h, char* name, char *text)
- {
- vec2i tex_size;
- int tex_id = str2tex(text, &(tex_size));
- gui_button *b = calloc(sizeof(gui_button), 1);
- b->name = name;
- //b->pos = pos;
- //b->size = size;
- b->pos.x = x;
- b->pos.y = y;
- b->size.x = w;
- b->size.y = h;
- b->tex_size = tex_size;
- b->tex_id = tex_id;
- b->text = text;
- ubi_dlAddTail(GUI_LIST, b);
- return(true);
- }
- void
- free_lists()
- {
- while (ubi_dlCount(OBJ_LIST))
- {
- free(ubi_dlRemHead(OBJ_LIST));
- }
- while (ubi_dlCount(GUI_LIST))
- {
- free(ubi_dlRemHead(GUI_LIST));
- }
- }
- void
- init_interface()
- {
- if (TTF_Init())
- {
- printf("TTF_Init: %s\n", TTF_GetError());
- exit(EXIT_FAILURE);
- }
- FONT = TTF_OpenFont("font.ttf", 22);
- if (!FONT)
- {
- puts("can not open font!!!");
- exit(EXIT_FAILURE);
- }
- add_button(0, 0, 200, 40, "fuel", "fuel: 0");
- add_button(0, -30, 200, 40, "ammo", "ammo: 0");
- add_button(0, -60, 200, 40, "exp", "exp: 0");
- add_button(0, -90, 200, 40, "live", "lives: 0");
- add_button(0, -120, 200, 40, "fps", "time: -");
- add_button(0, -150, 200, 40, "level","level: 0");
- change_button_text("live", "lives: %i", LIVES);
- change_button_text("fps", "fps: %i", FPS);
- }
- void
- add_stars()
- {
- int x = 80;
- while (x--)
- {
- add_star();
- }
- }
- void
- process_args(int argc, char *argv[])
- {
- if (argc > 1 || !argv[0])
- {
- exit(EXIT_FAILURE);
- }
- }
- void
- init_all(int argc, char *argv[])
- {
- //mtrace();
- process_args(argc, argv);
- srand(time(NULL));
- init_sdl();
- init_opengl();
- init_sound();
- init_interface();
- add_stars();
- }
- void
- cleanup()
- {
- free_lists();
- SDL_Quit();
- Mix_FreeChunk(SND_MOVING);
- Mix_FreeChunk(SND_BAM);
- Mix_FreeChunk(SND_MISSLE);
- Mix_CloseAudio();
- //muntrace();
- }
- int
- main(int argc, char *argv[])
- {
- Uint32 t;
- init_all(argc, argv);
- t = SDL_GetTicks() + 100;
- while (IS_PROG_RUNNING)
- {
- events();
- draw();
- logic();
- if (SDL_GetTicks() < t)
- {
- SDL_Delay(t - SDL_GetTicks());
- }
- t = SDL_GetTicks() + 1000./FPS;
- }
- cleanup();
- return(EXIT_SUCCESS);
- }
Advertisement
Add Comment
Please, Sign In to add comment