-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnon_renderer_code.odin
258 lines (235 loc) · 6.16 KB
/
non_renderer_code.odin
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
package sprite_renderer
import "base:runtime"
import "core:time"
import sapp "third_party/sokol/app"
// A timer for idle animations to showcase it sprite animations
TICK_ANIMATION :: 1 / 60.0 * 6
TICK_MAX :: 0.25
// [Enumarated array] to neatly store our sprite atlas lookup data.
// https://odin-lang.org/docs/overview/#enumerated-array
SPRITES :: #partial [Sprite_Name]Sprite {
.PINK_MONSTER = {
frames = {{0, 0}, {19, 0}, {38, 0}, {0, 28}, {19, 28}, {38, 28}},
size = {19, 28},
},
}
Key :: enum {
UP,
DOWN,
LEFT,
RIGHT,
}
Input :: struct {
// Store our currently held down buttons in a [Bit set]. Fits neatly!
// https://odin-lang.org/docs/overview/#bit-sets
keys: bit_set[Key],
}
Timer :: struct {
animation: u64,
current: time.Time,
}
// Some helpers to easily store our sprite atlas locations for rendering
Sprite_To_Render :: struct {
position: [2]int,
color: [4]f32,
scale: [2]i32,
sprite: Sprite,
}
Sprite :: struct {
frames: [][2]u16,
size: [2]u16,
}
Sprite_Name :: enum {
NONE,
PINK_MONSTER,
}
// Some sprites to render
// `[?]` to infer the fixed array length.
// https://odin-lang.org/docs/overview/#fixed-arrays
sprites_to_render := [?]Sprite_To_Render {
{
// Player
position = {29 * 0 + 8, 120},
sprite = SPRITES[.PINK_MONSTER],
color = {255, 255, 255, 1},
scale = {1, 1},
},
{
// Red
position = {29 * 0 + 8, 8},
sprite = SPRITES[.PINK_MONSTER],
color = {200, 20, 0, 1},
scale = {1, 1},
},
{
// Orange
position = {29 * 1 + 8, 8},
sprite = SPRITES[.PINK_MONSTER],
color = {220, 150, 0, 1},
scale = {1, 1},
},
{
// Yellow
position = {29 * 2 + 8, 8},
sprite = SPRITES[.PINK_MONSTER],
color = {200, 220, 0, 1},
scale = {1, 1},
},
{
// Green
position = {29 * 3 + 8, 8},
sprite = SPRITES[.PINK_MONSTER],
color = {0, 200, 0, 1},
scale = {1, 1},
},
{
// "Blue"
position = {29 * 4 + 8, 8},
sprite = SPRITES[.PINK_MONSTER],
color = {20, 60, 200, 1},
scale = {1, 1},
},
{
// Original
position = {29 * 5 + 8, 8},
sprite = SPRITES[.PINK_MONSTER],
color = {255, 255, 255, 1},
scale = {1, 1},
},
{
// Overlap 1
position = {29 * 6 + 8, 8},
sprite = SPRITES[.PINK_MONSTER],
color = {90, 90, 90, 1},
scale = {1, 1},
},
{
// Overlap 2
position = {29 * 6 + 16, 8},
sprite = SPRITES[.PINK_MONSTER],
color = {145, 145, 145, 1},
scale = {1, 1},
},
{
// Overlap 3
position = {29 * 6 + 24, 8},
sprite = SPRITES[.PINK_MONSTER],
color = {200, 200, 200, 1},
scale = {1, 1},
},
{
// Wide boii
position = {29 * 0 + 8, 40},
sprite = SPRITES[.PINK_MONSTER],
color = {255, 255, 255, 1},
scale = {2, 1},
},
{
// Upsidedown!?
// This "turns around the axis", not optimal (notice the Y-coordinate is 69, not 40)
position = {29 * 2 + 8, 69},
sprite = SPRITES[.PINK_MONSTER],
color = {255, 255, 255, 1},
scale = {-1, -1},
},
{
// Skewed af
position = {29 * 2 + 8, 98},
sprite = SPRITES[.PINK_MONSTER],
color = {255, 255, 255, 0.5},
scale = {-3, -1},
},
{
// Tall boii
position = {29 * 2 + 8, 40},
sprite = SPRITES[.PINK_MONSTER],
color = {255, 255, 255, 1},
scale = {1, 2},
},
{
// Original - ghost
position = {29 * 5 + 8, 8},
sprite = SPRITES[.PINK_MONSTER],
color = {255, 255, 255, 0.5},
scale = {1, 1},
},
}
// Convert sokol_app event keycodes to our own keycodes
sapp_keycode_to_key :: proc(keycode: sapp.Keycode) -> Maybe(Key) {
#partial switch keycode {
case .W, .UP:
return .UP
case .S, .DOWN:
return .DOWN
case .A, .LEFT:
return .LEFT
case .D, .RIGHT:
return .RIGHT
case:
return nil
}
}
tick :: proc() {
new_time := time.now()
frame_time := time.duration_seconds(time.diff(timer.current, new_time))
if frame_time > TICK_MAX do frame_time = TICK_MAX
timer.current = new_time
@(static) timer_tick_animation := TICK_ANIMATION
timer_tick_animation -= frame_time
if timer_tick_animation <= 0 {
timer.animation += 1
timer_tick_animation += TICK_ANIMATION
}
}
handle_input :: proc() {
// Let the player controll the first sprite.
// Yes this is not a superb input system but that's not the focus here.
// Bit sets are neat though!
if .UP in input.keys {
sprites_to_render[0].position.y += 1
}
if .DOWN in input.keys {
sprites_to_render[0].position.y -= 1
}
if .LEFT in input.keys {
sprites_to_render[0].position.x -= 1
}
if .RIGHT in input.keys {
sprites_to_render[0].position.x += 1
}
}
event :: proc "c" (ev: ^sapp.Event) {
context = runtime.default_context()
if ev.type == .KEY_DOWN {
#partial switch ev.key_code {
case .W, .UP:
input.keys += {.UP}
case .S, .DOWN:
input.keys += {.DOWN}
case .A, .LEFT:
input.keys += {.LEFT}
case .D, .RIGHT:
input.keys += {.RIGHT}
case .Q:
sapp.request_quit()
case .F:
sapp.toggle_fullscreen()
}
}
if ev.type == .KEY_UP {
#partial switch ev.key_code {
case .W, .UP:
input.keys -= {.UP}
case .S, .DOWN:
input.keys -= {.DOWN}
case .A, .LEFT:
input.keys -= {.LEFT}
case .D, .RIGHT:
input.keys -= {.RIGHT}
}
}
if ev.type == .RESIZED {
renderer.offscreen.pixel_to_viewport_multiplier =
gfx_get_pixel_to_viewport_multiplier(GAME_WIDTH, GAME_HEIGHT)
}
}