#include <ncurses.h>
#include <time.h>
#include <stdlib.h>
#include "galaga.h"
#include "ship.h"
#include "alien.h"
#define MAX_BULLETS 100
// The possible game states
typedef enum {
PLAYING,
FINISHED
} state_t;
// Global variables
typedef struct {
int width, height;
state_t state;
ship_t *ship;
bullet_t *bullets[MAX_BULLETS];
int nbullets;
agroup_t *ag;
} galaga_t;
// The game variable struct
galaga_t g;
void setup(int width, int height);
void draw();
void update();
void process_input();
double time_in_milli();
// Begin the game, contain the game loop
void start_game(int width, int height)
{
setup(width, height);
// The game loop, with code to control fps
double start = time_in_milli();
double dt;
while(g.state != FINISHED) {
dt = time_in_milli() - start;
if(dt > 33) {
draw();
update();
process_input();
start = time_in_milli();
}
}
}
// Closes curses
void end_game()
{
endwin();
}
void setup(int width, int height)
{
// ----- NCURSES INIT ----- //
initscr(); // Initialize ncurses library and clear the screen
cbreak(); // Disable terminal buffering
keypad(stdscr, true); // Enables special keyboard characters
noecho(); // Disable the echoing of characters
curs_set(false); // Disable the cursor
timeout(false); // Enable nonblocking input
// ------------------------ //
// ----- INIT GAME VARIABLES ----- //
g.width = width;
g.height = height;
g.state = PLAYING;
g.ship = new_ship(g.width / 2, g.height - 1);
g.nbullets = 0;
g.ag = new_agroup();
// ------------------------------- //
}
void draw()
{
clear(); // Clear the previous frame
// Draw the ship
draw_ship(g.ship);
// Draw the bullets
for(int i = 0; i < g.nbullets; ++i) {
draw_bullet(g.bullets[i]);
}
// Draw aliens
draw_agroup(g.ag);
// Draw the game border
mvhline(0, 1, '-', g.width);
mvvline(0, 0, '|', g.height + 1);
mvhline(g.height, 1, '-', g.width);
mvvline(0, g.width, '|', g.height + 1);
// Write the changes to the screen
refresh();
}
void update()
{
if(g.ship->x >= g.width) g.ship->x = g.width - 1;
else if(g.ship->x <= 0) g.ship->x = 1;
// Update the bullets
for(int i = 0; i < g.nbullets; ++i) {
update_bullet(g.bullets[i]);
if(g.bullets[i]->y <= 0) {
free(g.bullets[i]);
g.bullets[i] = g.bullets[--g.nbullets];
}
}
}
void process_input()
{
int c = getch();
switch(c) {
case KEY_LEFT:
g.ship->x--;
break;
case KEY_RIGHT:
g.ship->x++;
break;
case ' ':
if(g.nbullets < MAX_BULLETS) {
bullet_t *b = shoot(g.ship);
g.bullets[g.nbullets++] = b;
}
break;
}
}
double time_in_milli()
{
return (clock() / (double)CLOCKS_PER_SEC) * 1000.0;
}