added project code to repo
This commit is contained in:
parent
3c3923ab81
commit
4897e4b8c6
|
@ -0,0 +1,10 @@
|
||||||
|
flappy: main.o game.o bird.o pipe.o
|
||||||
|
gcc -o flappy main.o game.o bird.o pipe.o -lcurses
|
||||||
|
main.o: main.c game.h config.h
|
||||||
|
gcc -c main.c
|
||||||
|
game.o: game.c game.h bird.h pipe.h config.h
|
||||||
|
gcc -c game.c
|
||||||
|
bird.o: bird.c bird.h config.h
|
||||||
|
gcc -c bird.c
|
||||||
|
pipe.o: pipe.c pipe.h config.h
|
||||||
|
gcc -c pipe.c
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include "bird.h"
|
||||||
|
|
||||||
|
bird* bird_create(){
|
||||||
|
/* Allocate memory */
|
||||||
|
bird* b = malloc(sizeof(bird));
|
||||||
|
|
||||||
|
/* Set values */
|
||||||
|
b->pos_x = CAM_OFFSET_X;
|
||||||
|
b->pos_y = HEIGHT/2;
|
||||||
|
b->vel_x = BIRD_VEL_X;
|
||||||
|
b->vel_y = 0;
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bird_destroy(bird* b){
|
||||||
|
free(b);
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef _H_BIRD
|
||||||
|
#define _H_BIRD
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
float pos_x;
|
||||||
|
float pos_y;
|
||||||
|
float vel_x;
|
||||||
|
float vel_y;
|
||||||
|
} bird;
|
||||||
|
|
||||||
|
bird* bird_create();
|
||||||
|
void bird_destroy(bird* b);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef _H_CONFIG
|
||||||
|
#define _H_CONFIG
|
||||||
|
|
||||||
|
#define KEY_QUIT 'q'
|
||||||
|
#define KEY_JUMP ' '
|
||||||
|
|
||||||
|
#define FPS 10
|
||||||
|
#define WIDTH 60
|
||||||
|
#define HEIGHT 20
|
||||||
|
#define CAM_OFFSET_X 10
|
||||||
|
|
||||||
|
#define BIRD_VEL_X 10.0F
|
||||||
|
#define BIRD_VEL_Y_JUMP 13.5F
|
||||||
|
#define BIRD_ACC_Y -30.0F
|
||||||
|
|
||||||
|
#define PIPE_DISTANCE 16
|
||||||
|
#define PIPE_HEIGHT 3
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,126 @@
|
||||||
|
#include "game.h"
|
||||||
|
|
||||||
|
game* game_create(){
|
||||||
|
/* Allocate memory */
|
||||||
|
game* g = malloc(sizeof(game));
|
||||||
|
|
||||||
|
/* Set vars */
|
||||||
|
g->bird = bird_create();
|
||||||
|
g->num_pipes = WIDTH/PIPE_DISTANCE + 1;
|
||||||
|
g->pipes = malloc(sizeof(pipe*)*g->num_pipes);
|
||||||
|
for(int i=0; i<g->num_pipes; i++){
|
||||||
|
g->pipes[i] = pipe_create();
|
||||||
|
}
|
||||||
|
g->score = 0;
|
||||||
|
g->highscore = 0;
|
||||||
|
|
||||||
|
/* Reset level */
|
||||||
|
game_reset_level(g);
|
||||||
|
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_reset_level(game* g){
|
||||||
|
/* Reset bird */
|
||||||
|
bird_destroy(g->bird);
|
||||||
|
g->bird = bird_create();
|
||||||
|
|
||||||
|
/* Reset pipes */
|
||||||
|
for(int i=0; i<g->num_pipes; i++){
|
||||||
|
g->pipes[i]->pos_x = WIDTH + PIPE_DISTANCE*i;
|
||||||
|
g->pipes[i]->pos_y = rand()%(HEIGHT-PIPE_HEIGHT-2)+1;
|
||||||
|
g->pipes[i]->height = PIPE_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset other vars */
|
||||||
|
g->score = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_destroy(game* g){
|
||||||
|
/* Free memory */
|
||||||
|
bird_destroy(g->bird);
|
||||||
|
for(int i=0; i<g->num_pipes; i++){
|
||||||
|
pipe_destroy(g->pipes[i]);
|
||||||
|
}
|
||||||
|
free(g->pipes);
|
||||||
|
free(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_key_pressed(game* g, char key){
|
||||||
|
if(key == KEY_JUMP){
|
||||||
|
g->bird->vel_y = BIRD_VEL_Y_JUMP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int game_update(game* g, float dt){
|
||||||
|
/* Update bird position */
|
||||||
|
g->bird->vel_y += BIRD_ACC_Y * dt;
|
||||||
|
g->bird->pos_x += g->bird->vel_x * dt;
|
||||||
|
g->bird->pos_y += g->bird->vel_y * dt;
|
||||||
|
|
||||||
|
/* Check for collisions */
|
||||||
|
int bird_x = g->bird->pos_x;
|
||||||
|
for(int i=0; i<g->num_pipes; i++){
|
||||||
|
if(bird_x == g->pipes[i]->pos_x){
|
||||||
|
int bird_y = g->bird->pos_y;
|
||||||
|
if(bird_y < g->pipes[i]->pos_y || bird_y >= g->pipes[i]->pos_y + g->pipes[i]->height){
|
||||||
|
/* Collision */
|
||||||
|
return STATE_COLLISION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(g->bird->pos_y < 0){
|
||||||
|
return STATE_COLLISION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move pipes */
|
||||||
|
for(int i=0; i<g->num_pipes; i++){
|
||||||
|
/* Check if off screen */
|
||||||
|
if(g->pipes[i]->pos_x < g->bird->pos_x-CAM_OFFSET_X){
|
||||||
|
/* Move */
|
||||||
|
g->pipes[i]->pos_x += g->num_pipes*PIPE_DISTANCE;
|
||||||
|
g->pipes[i]->pos_y = rand()%(HEIGHT-PIPE_HEIGHT-2)+1;
|
||||||
|
|
||||||
|
/* Adjust score */
|
||||||
|
g->score++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATE_OKAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_render(game* g){
|
||||||
|
/* Clear screen */
|
||||||
|
clear();
|
||||||
|
|
||||||
|
/* Init vars */
|
||||||
|
int delta_x = g->bird->pos_x - CAM_OFFSET_X;
|
||||||
|
|
||||||
|
/* Draw ground */
|
||||||
|
move(HEIGHT, 0);
|
||||||
|
for(int x=0; x<WIDTH; x++){
|
||||||
|
addch('=');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw pipes */
|
||||||
|
for(int i=0; i<g->num_pipes; i++){
|
||||||
|
/* Only draw if in screen */
|
||||||
|
if(g->pipes[i]->pos_x >= delta_x && g->pipes[i]->pos_x < delta_x + WIDTH){
|
||||||
|
int x = g->pipes[i]->pos_x - delta_x;
|
||||||
|
for(int y=0; y<g->pipes[i]->pos_y; y++){
|
||||||
|
mvaddch(HEIGHT-1-y, x, '#');
|
||||||
|
}
|
||||||
|
for(int y=g->pipes[i]->pos_y+g->pipes[i]->height+1; y<HEIGHT; y++){
|
||||||
|
mvaddch(HEIGHT-1-y, x, '#');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw bird */
|
||||||
|
mvaddch(HEIGHT-1-g->bird->pos_y, CAM_OFFSET_X, 'v');
|
||||||
|
|
||||||
|
/* Draw score */
|
||||||
|
char text[50];
|
||||||
|
sprintf(text, "Score: %d\tBest: %d", g->score, g->highscore);
|
||||||
|
mvaddstr(HEIGHT+1, 1, text);
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef _H_GAME
|
||||||
|
#define _H_GAME
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <curses.h>
|
||||||
|
#include "bird.h"
|
||||||
|
#include "pipe.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#define STATE_OKAY 0
|
||||||
|
#define STATE_COLLISION 1
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
bird* bird;
|
||||||
|
pipe** pipes;
|
||||||
|
int num_pipes;
|
||||||
|
int score;
|
||||||
|
int highscore;
|
||||||
|
} game;
|
||||||
|
|
||||||
|
game* game_create();
|
||||||
|
void game_reset_level(game* g);
|
||||||
|
void game_destroy(game* g);
|
||||||
|
|
||||||
|
void game_key_pressed(game* g, char key);
|
||||||
|
int game_update(game* g, float dt);
|
||||||
|
void game_render(game* g);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,77 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <curses.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include "game.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
void msleep(int msec){
|
||||||
|
struct timespec ts;
|
||||||
|
ts.tv_sec = msec/1000;
|
||||||
|
ts.tv_nsec = (msec%1000) * 1000000;
|
||||||
|
nanosleep(&ts, &ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv){
|
||||||
|
|
||||||
|
/* Init curses */
|
||||||
|
WINDOW* win;
|
||||||
|
win = initscr();
|
||||||
|
noecho();
|
||||||
|
keypad(win, TRUE);
|
||||||
|
nodelay(win, TRUE);
|
||||||
|
curs_set(FALSE);
|
||||||
|
|
||||||
|
/* Init game */
|
||||||
|
srand(time(NULL));
|
||||||
|
game* g = game_create();
|
||||||
|
|
||||||
|
/* Game Loop */
|
||||||
|
char c;
|
||||||
|
while(1){
|
||||||
|
/* Get input */
|
||||||
|
do{
|
||||||
|
c = getch();
|
||||||
|
if(c == KEY_QUIT) break;
|
||||||
|
if(c != ERR) game_key_pressed(g, c);
|
||||||
|
}while(c != ERR);
|
||||||
|
if(c == KEY_QUIT) break;
|
||||||
|
|
||||||
|
/* Update */
|
||||||
|
int state = game_update(g, 1.0F/(float)FPS);
|
||||||
|
|
||||||
|
/* Render */
|
||||||
|
game_render(g);
|
||||||
|
refresh();
|
||||||
|
|
||||||
|
/* Exit if collision */
|
||||||
|
if(state == STATE_COLLISION){
|
||||||
|
/* Update score */
|
||||||
|
char is_best_score = 0;
|
||||||
|
if(g->score > g->highscore){
|
||||||
|
g->highscore = g->score;
|
||||||
|
is_best_score = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw message */
|
||||||
|
move(HEIGHT+2, 1);
|
||||||
|
addstr((is_best_score ? "New Highscore!" : "Game Over!"));
|
||||||
|
refresh();
|
||||||
|
|
||||||
|
/* Delay and restart */
|
||||||
|
msleep(1000);
|
||||||
|
game_reset_level(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delay */
|
||||||
|
msleep(1000/FPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cleanup */
|
||||||
|
game_destroy(g);
|
||||||
|
delwin(win);
|
||||||
|
endwin();
|
||||||
|
refresh();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#include "pipe.h"
|
||||||
|
|
||||||
|
pipe* pipe_create(){
|
||||||
|
/* Allocate memory */
|
||||||
|
pipe* p = malloc(sizeof(pipe));
|
||||||
|
|
||||||
|
/* Set values */
|
||||||
|
p->pos_x = 0;
|
||||||
|
p->pos_y = 0;
|
||||||
|
p->height = PIPE_HEIGHT;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pipe_destroy(pipe* p){
|
||||||
|
free(p);
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef _H_PIPE
|
||||||
|
#define _H_PIPE
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int pos_x;
|
||||||
|
int pos_y;
|
||||||
|
int height;
|
||||||
|
} pipe;
|
||||||
|
|
||||||
|
pipe* pipe_create();
|
||||||
|
void pipe_destroy(pipe* p);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue