262 lines
5.5 KiB
C
262 lines
5.5 KiB
C
#include "cat_api.h"
|
|
#include <time.h>
|
|
|
|
void bye(void)
|
|
{
|
|
printf("bye!\n");
|
|
exit(0);
|
|
}
|
|
|
|
struct keydowns
|
|
{
|
|
char k;
|
|
struct keydowns* next;
|
|
};
|
|
|
|
struct keydowns* first_keydown = NULL;
|
|
|
|
void add_keydown(char k)
|
|
{
|
|
struct keydowns* new = malloc(sizeof(struct keydowns));
|
|
new->k = k;
|
|
new->next = NULL;
|
|
if (first_keydown == NULL) first_keydown = new;
|
|
else
|
|
{
|
|
struct keydowns* head;
|
|
for (head = first_keydown; head->next != NULL; head = head->next)
|
|
if (head->k == k) return;
|
|
head->next = new;
|
|
}
|
|
}
|
|
|
|
void lit_remove_keydown(struct keydowns* entry)
|
|
{
|
|
if (first_keydown == entry) first_keydown = entry->next;
|
|
else
|
|
{
|
|
struct keydowns* head;
|
|
for (head = first_keydown; head->next != entry; head = head->next) ;
|
|
head->next = entry->next;
|
|
}
|
|
}
|
|
|
|
void remove_keydown(char k)
|
|
{
|
|
struct keydowns* head;
|
|
for (head = first_keydown; head != NULL; head = head->next)
|
|
if (head->k == k) lit_remove_keydown(head);
|
|
}
|
|
|
|
int is_held(char k)
|
|
{
|
|
struct keydowns* head;
|
|
for (head = first_keydown; head != NULL; head = head->next)
|
|
if (head->k == k) return 1;
|
|
return 0;
|
|
}
|
|
|
|
struct entity
|
|
{
|
|
int is_player;
|
|
int is_static;
|
|
int x;
|
|
int y;
|
|
int width;
|
|
int height;
|
|
unsigned char r; /* replace this with sprite TODO */
|
|
unsigned char g;
|
|
unsigned char b;
|
|
float vx;
|
|
float vy;
|
|
float ax;
|
|
float ay;
|
|
struct entity* next;
|
|
};
|
|
|
|
struct entity* first_entity = NULL;
|
|
|
|
void add_entity(int is_player, int is_static, int x, int y, int width, int height, unsigned char r,
|
|
unsigned char g, unsigned char b, float vx, float vy, float ax, float ay)
|
|
{
|
|
struct entity* new = malloc(sizeof(struct entity));
|
|
new->is_player = is_player;
|
|
new->is_static = is_static;
|
|
new->x = x;
|
|
new->y = y;
|
|
new->width = width;
|
|
new->height = height;
|
|
new->r = r;
|
|
new->g = g;
|
|
new->b = b;
|
|
new->vx = vx;
|
|
new->vy = vy;
|
|
new->ax = ax;
|
|
new->ay = ay;
|
|
new->next = NULL;
|
|
if (first_entity == NULL) first_entity = new;
|
|
else
|
|
{
|
|
struct entity* head;
|
|
for (head = first_entity; head->next != NULL; head = head->next) ;
|
|
head->next = new;
|
|
}
|
|
}
|
|
|
|
struct entity* get_player(void)
|
|
{
|
|
struct entity* head;
|
|
for (head = first_entity; head != NULL; head = head->next)
|
|
if (head->is_player) return head;
|
|
return NULL;
|
|
}
|
|
|
|
void key_down(char k)
|
|
{
|
|
add_keydown(k);
|
|
printf("%c pressed!\n", k);
|
|
switch (k)
|
|
{
|
|
case 'a': get_player()->ax = -2; break;
|
|
case 'd': get_player()->ax = 2; break;
|
|
}
|
|
}
|
|
|
|
void key_up(char k)
|
|
{
|
|
remove_keydown(k);
|
|
printf("%c un-pressed\n", k);
|
|
switch (k)
|
|
{
|
|
case 'a': get_player()->ax = 0; break;
|
|
case 'd': get_player()->ax = 0; break;
|
|
}
|
|
}
|
|
|
|
static int mousex = 0;
|
|
static int mousey = 0;
|
|
|
|
void mouse_move(int x, int y)
|
|
{
|
|
/* clear old mouse icn */
|
|
mousex = x;
|
|
mousey = y;
|
|
printf("mouse moved! (%d, %d)\n", x, y);
|
|
}
|
|
|
|
void mouse_down(unsigned char button)
|
|
{
|
|
printf("mouse button %02x clicked!\n", button);
|
|
/* TODO struct for this too?? that seems like a lot. what if we *don't* use mouse for anything... */
|
|
}
|
|
|
|
void mouse_up(unsigned char button)
|
|
{
|
|
printf("mouse button %02x un-clicked!\n", button);
|
|
}
|
|
|
|
void process_input(void)
|
|
{
|
|
struct cat_event* e = cat_get_event();
|
|
if (e == NULL) return;
|
|
if (e->type == QUIT) bye();
|
|
else if (e->type == KEYDOWN) key_down(e->key);
|
|
else if (e->type == KEYUP) key_up(e->key);
|
|
else if (e->type == MOUSEMOVE) mouse_move(e->mousex, e->mousey);
|
|
else if (e->type == MOUSEDOWN) mouse_down(e->mouse_button);
|
|
else if (e->type == MOUSEUP) mouse_up(e->mouse_button);
|
|
}
|
|
|
|
void erase_entity(struct entity* e)
|
|
{
|
|
/* get sprite info, etc */
|
|
/* FIXME */
|
|
if (e->x < 0 || e->y < 0 || e->x >= screen_width || e->y >= screen_height) return;
|
|
cat_fill(1, 0, e->x, e->y, e->width, e->height, 0, 0, 0);
|
|
}
|
|
|
|
void draw_entity(struct entity* e)
|
|
{
|
|
/* get sprite info, etc */
|
|
/* FIXME */
|
|
if (e->x < 0 || e->y < 0 || e->x >= screen_width || e->y >= screen_height) return;
|
|
cat_fill(1, 1, e->x, e->y, e->width, e->height, e->r, e->g, e->b);
|
|
/* if out of bounds do not draw */
|
|
}
|
|
|
|
void erase_entities(void)
|
|
{
|
|
struct entity* head;
|
|
for (head = first_entity; head != NULL; head = head->next)
|
|
erase_entity(head);
|
|
}
|
|
|
|
void draw_entities(void)
|
|
{
|
|
struct entity* head;
|
|
for (head = first_entity; head != NULL; head = head->next)
|
|
draw_entity(head);
|
|
}
|
|
|
|
static long last_sec = 0;
|
|
static long last_nsec = 0;
|
|
|
|
#define NS_PER_TICK 30000000
|
|
|
|
void apply_friction(void) /* FIXME */
|
|
{
|
|
struct entity* p = get_player();
|
|
if (p->vx > 0) p->vx -= 1;
|
|
else if (p->vx < 0) p->vx += 1;
|
|
if (p->vy > 0) p->vy -= 1;
|
|
else if (p->vy < 0) p->vy += 1;
|
|
}
|
|
|
|
void tick(void)
|
|
{
|
|
/* run every N milliseconds... nanoseconds? idk */
|
|
struct timespec t;
|
|
clock_gettime(CLOCK_REALTIME, &t);
|
|
if (last_sec == 0) goto yes;
|
|
else if ((t.tv_sec - last_sec) > 0) goto yes;
|
|
else if ((t.tv_nsec - last_nsec) > NS_PER_TICK) goto yes;
|
|
else return;
|
|
/* do a tick */
|
|
yes: last_sec = t.tv_sec;
|
|
last_nsec = t.tv_nsec;
|
|
|
|
/* code to run every tick goes here */
|
|
erase_entities();
|
|
struct entity* p = get_player();
|
|
if (is_held(' ')) p->ay = -5;
|
|
else p->ay = 9.81;
|
|
p->vx += p->ax;
|
|
p->vy += p->ay;
|
|
apply_friction(); /* FIXME */
|
|
p->x += (int)p->vx;
|
|
p->y += (int)p->vy;
|
|
draw_entities();
|
|
}
|
|
|
|
void game_loop(void)
|
|
{
|
|
cat_render();
|
|
process_input();
|
|
tick();
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
cat_init();
|
|
cat_create_window(1920, 1080);
|
|
//cat_play_wav("etc/example.wav");
|
|
//cat_play_wav("etc/cat_quick.wav");
|
|
cat_play_wav("etc/cat_beep_box.wav");
|
|
/* layer, visibility, x, y, width, height, r, g, b */
|
|
cat_fill(0, 1, 0, 0, screen_width - 1, screen_height - 1, 132, 155, 132);
|
|
/* create the player */ add_entity(1, 0, 0, 0, 50, 50, 100, 50, 0, 0, 0, 0, 0);
|
|
/* create a random entity */ add_entity(0, 0, 20, 20, 50, 50, 100, 100, 50, 0, 0, 0, 0);
|
|
while (1) game_loop();
|
|
return 0;
|
|
}
|