summaryrefslogtreecommitdiff
path: root/src/game.c
blob: d35d7a9feb883e7ef475e8ccac53e4370443402c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "game.h"
#include "exit.h"
#include "map.h"
#include "player.h"
#include "cfg.h"
#include "rotrect.h"
#include "spike.h"
#include <string.h>

void
game_init(Game *this)
{
	memset(this, 0, sizeof(*this));
	this->player_dir = 1;
	game_restart_scene(this);
}

void
game_deinit([[maybe_unused]] Game *this)
{
}

void
game_update(Game *this)
{
	extern double tick;
	this->spike_rect = rotrect_create(10, 10, tick / 16);
	this->spike_irect = rotrect_create(10, 10, -tick / 16);
	if (this->queue_restart_scene > 0) {
		if (--this->queue_restart_scene == 0)
			game_restart_scene(this);
	}
	if (this->queue_next_scene) {
		this->queue_next_scene = false;
		this->player_dir = game_get_entity(this,
		                                   entity_type("exit"))->exit.dir;
		map_next();
		game_restart_scene(this);
		return;
	}
	for (int i = 0; i < MAX_ENTITIES; i++) {
		Entity *const e = &this->entities[i];
		if (e->type != ET_NONE && e->update != NULL)
			e->update(e, this);
	}
	this->show_ui -= (this->show_ui > 0);
}

void
game_draw(Game *this)
{
	map_draw();
	for (int i = 0; i < MAX_ENTITIES; i++) {
		Entity *const e = &this->entities[i];
		if (e->type != ET_NONE && e->draw != NULL)
			e->draw(e, this);
	}
	if (this->show_ui)
		map_draw_ui();
}

void
game_restart_scene(Game *this)
{
	memset(this->entities, 0, sizeof(this->entities));
	this->show_ui = 30;
	for (int y = 0; y < map_height(); y++)
		for (int x = 0; x < map_width(); x++) {
			const int dx = x * TSIZE + TSIZE / 2;
			const int dy = y * TSIZE + TSIZE / 2;
			Entity *e;
			switch (map_get(x, y)) {
			case 2:
				e = player_init(game_create_entity(this), dx, dy);
				e->player.dirx = this->player_dir;
				break;
			case 3:
			case 4:
				e = exit_init(game_create_entity(this), dx, dy);
				e->exit.dir = (map_get(x, y) == 3) ? -1 : 1;
				break;
			case 5:
				spike_init(game_create_entity(this), dx, dy);
				break;
			default:
				break;
			}
		}
}

Entity *
game_create_entity(Game *this)
{
	Entity *e = &this->entities[MAX_ENTITIES - 1];
	for (int i = 0; i < MAX_ENTITIES; i++)
		if (this->entities[i].type == ET_NONE) {
			e = &this->entities[i];
			break;
		}
	e->type = ET_NONE;
	e->uuid = this->uuid;
	this->uuid += 1;
	return e;
}

int
game_entity_count(Game *this, unsigned int type)
{
	int count = 0;
	for (int i = 0; i < MAX_ENTITIES; i++)
		count += (this->entities[i].type == type);
	return count;
}

Entity *
game_get_entity(Game *this, unsigned int type)
{
	for (int i = 0; i < MAX_ENTITIES; i++)
		if (this->entities[i].type == type)
			return &this->entities[i];
	return NULL;
}