basic world text
[fishladder.git] / fishladder_resources.h
1 // FONTS
2
3 struct sdf_char
4 {
5 u16 uvx, uvy, originX, originY, w, h, advance;
6 };
7
8 struct sdf_font
9 {
10 const char *name;
11 int size, width, height;
12 struct sdf_char *characters;
13 };
14
15 static struct sdf_char characters_Ubuntu[] = {
16 {655, 167, 9, 9, 18, 18, 11},
17 {561, 64, 6, 42, 25, 52, 13},
18 {435, 167, 6, 45, 32, 30, 20},
19 {797, 64, 7, 42, 46, 51, 32},
20 {362, 0, 6, 46, 39, 60, 27},
21 {918, 0, 7, 43, 55, 52, 41},
22 {973, 0, 7, 43, 47, 52, 32},
23 {467, 167, 6, 45, 23, 30, 11},
24 {142, 0, 5, 46, 30, 64, 15},
25 {172, 0, 9, 46, 30, 64, 15},
26 {291, 167, 7, 42, 38, 37, 23},
27 {171, 167, 6, 35, 40, 42, 27},
28 {410, 167, 7, 14, 25, 31, 12},
29 {625, 167, 8, 26, 30, 22, 14},
30 {558, 167, 6, 15, 25, 24, 12},
31 {0, 0, 10, 46, 39, 64, 18},
32 {88, 64, 7, 43, 41, 52, 27},
33 {532, 116, 5, 42, 32, 51, 27},
34 {370, 64, 6, 43, 39, 52, 27},
35 {409, 64, 6, 43, 39, 52, 27},
36 {176, 116, 7, 42, 42, 51, 27},
37 {448, 64, 6, 42, 39, 52, 27},
38 {170, 64, 6, 42, 40, 52, 27},
39 {343, 116, 6, 42, 40, 51, 27},
40 {854, 0, 6, 43, 40, 53, 27},
41 {210, 64, 7, 43, 40, 52, 27},
42 {146, 167, 6, 34, 25, 43, 12},
43 {564, 116, 7, 34, 26, 51, 12},
44 {211, 167, 6, 34, 40, 39, 27},
45 {370, 167, 6, 30, 40, 32, 27},
46 {251, 167, 6, 34, 40, 39, 27},
47 {525, 64, 8, 43, 36, 52, 19},
48 {401, 0, 6, 43, 57, 59, 45},
49 {700, 64, 9, 42, 49, 51, 32},
50 {218, 116, 5, 42, 42, 51, 31},
51 {769, 0, 6, 43, 44, 53, 30},
52 {935, 64, 5, 42, 45, 51, 34},
53 {383, 116, 5, 42, 40, 51, 27},
54 {423, 116, 5, 42, 38, 51, 26},
55 {724, 0, 6, 43, 45, 53, 32},
56 {45, 116, 5, 42, 44, 51, 34},
57 {590, 116, 5, 42, 23, 51, 13},
58 {487, 64, 9, 42, 38, 52, 24},
59 {89, 116, 5, 42, 44, 51, 30},
60 {461, 116, 5, 42, 38, 51, 25},
61 {646, 64, 6, 42, 54, 51, 42},
62 {0, 116, 5, 42, 45, 51, 35},
63 {674, 0, 6, 43, 50, 53, 37},
64 {302, 116, 5, 42, 41, 51, 29},
65 {312, 0, 6, 43, 50, 61, 37},
66 {133, 116, 5, 42, 43, 51, 30},
67 {813, 0, 7, 43, 41, 53, 25},
68 {0, 64, 8, 42, 44, 52, 27},
69 {44, 64, 5, 42, 44, 52, 33},
70 {749, 64, 8, 42, 48, 51, 31},
71 {586, 64, 8, 42, 60, 51, 44},
72 {843, 64, 8, 42, 46, 51, 30},
73 {889, 64, 9, 42, 46, 51, 28},
74 {260, 116, 7, 42, 42, 51, 27},
75 {202, 0, 4, 46, 29, 64, 16},
76 {39, 0, 10, 46, 39, 64, 18},
77 {231, 0, 9, 46, 29, 64, 16},
78 {329, 167, 7, 42, 41, 36, 27},
79 {583, 167, 9, 4, 42, 22, 23},
80 {490, 167, 6, 46, 27, 28, 18},
81 {695, 116, 7, 34, 38, 44, 25},
82 {458, 0, 5, 46, 40, 56, 28},
83 {733, 116, 7, 34, 37, 44, 22},
84 {498, 0, 7, 46, 40, 56, 28},
85 {655, 116, 7, 34, 40, 44, 27},
86 {641, 0, 5, 46, 33, 55, 18},
87 {250, 64, 7, 34, 40, 52, 27},
88 {603, 0, 5, 46, 38, 55, 27},
89 {894, 0, 6, 44, 24, 53, 12},
90 {282, 0, 12, 44, 30, 62, 12},
91 {564, 0, 5, 46, 39, 55, 25},
92 {538, 0, 5, 46, 26, 56, 13},
93 {860, 116, 5, 34, 52, 43, 41},
94 {0, 167, 5, 34, 38, 43, 27},
95 {613, 116, 7, 34, 42, 44, 28},
96 {290, 64, 5, 34, 40, 52, 28},
97 {330, 64, 7, 34, 40, 52, 28},
98 {113, 167, 5, 34, 33, 43, 18},
99 {770, 116, 7, 34, 36, 44, 21},
100 {499, 116, 5, 42, 33, 51, 19},
101 {38, 167, 5, 34, 38, 43, 27},
102 {912, 116, 8, 34, 41, 43, 24},
103 {806, 116, 8, 34, 54, 43, 37},
104 {953, 116, 8, 34, 41, 43, 24},
105 {129, 64, 9, 34, 41, 52, 24},
106 {76, 167, 7, 34, 37, 43, 22},
107 {78, 0, 7, 46, 32, 64, 16},
108 {260, 0, 4, 46, 22, 64, 13},
109 {110, 0, 9, 46, 32, 64, 16},
110 {517, 167, 7, 27, 41, 26, 27},
111 };
112
113 static struct sdf_font font_Ubuntu = {"Ubuntu", 48, 1024, 256, characters_Ubuntu};
114
115 vg_tex2d tex_ubuntu = { .path = "textures/ubuntu.qoi" };
116
117 // TEXTURES
118 // ===========================================================================================================
119
120 vg_tex2d tex_tile_data = { .path = "textures/tileset.qoi" };
121 vg_tex2d tex_tile_detail = { .path = "textures/tile_overlays.qoi" };
122 vg_tex2d tex_wood = { .path = "textures/wood.qoi" };
123 vg_tex2d tex_ball_noise = { .path = "textures/bnoise.qoi" };
124 vg_tex2d tex_monofur = { .path = "textures/ascii.qoi", .flags = VG_TEXTURE_NO_MIP };
125 vg_tex2d tex_unkown = { .path = "textures/unkown.qoi" };
126 vg_tex2d tex_buttons = { .path = "textures/buttons.qoi" };
127
128 vg_tex2d *texture_list[] = { &tex_tile_detail, &tex_tile_data, &tex_wood, &tex_ball_noise, &tex_monofur, &tex_unkown, &tex_buttons, &tex_ubuntu };
129
130 // AUDIO
131 // ===========================================================================================================
132
133 sfx_vol_control audio_volume_sfx = { .val = 1.0f, .name = "Sound effects" };
134 sfx_vol_control audio_volume_music = { .val = 1.0f, .name = "Music" };
135
136 sfx_system audio_system_sfx =
137 {
138 .vol = 1.f,
139 .ch = 1,
140 .vol_src = &audio_volume_sfx,
141 .name = "sfx"
142 };
143
144 sfx_set audio_tile_mod =
145 {
146 .sources = "\
147 sound/mod_01.ogg\0\
148 sound/mod_02.ogg\0\
149 sound/mod_03.ogg\0\
150 sound/mod_04.ogg\0\
151 sound/mod_05.ogg\0\
152 sound/mod_06.ogg\0",
153 .flags = 0
154 };
155
156 sfx_set audio_splitter =
157 {
158 .sources = "\
159 sound/splitter_01.ogg\0"
160 };
161
162 sfx_set audio_rolls =
163 {
164 .sources = "\
165 sound/rolling_01.ogg\0\
166 sound/rolling_02.ogg\0"
167 };
168
169 sfx_set audio_random =
170 {
171 .sources = "\
172 sound/random_01.ogg\0\
173 sound/random_02.ogg\0\
174 sound/random_03.ogg\0\
175 sound/random_04.ogg\0\
176 sound/random_05.ogg\0\
177 sound/random_06.ogg\0\
178 sound/random_07.ogg\0\
179 sound/random_08.ogg\0"
180 };
181
182 sfx_set audio_clicks =
183 {
184 .sources = "\
185 sound/click_a.ogg\0\
186 sound/click_b.ogg\0\
187 sound/click_c.ogg\0"
188 };
189
190 sfx_set audio_tones =
191 {
192 .sources = "\
193 sound/y0.ogg\0\
194 sound/y1.ogg\0\
195 sound/y2.ogg\0\
196 sound/y3.ogg\0\
197 sound/y4.ogg\0\
198 sound/y5.ogg\0\
199 sound/y6.ogg\0\
200 sound/y7.ogg\0\
201 sound/y8.ogg\0\
202 sound/win.ogg\0"
203 };
204
205 // One two or three layers of rolling noise
206 sfx_system audio_system_balls_rolling =
207 {
208 .vol = 0.7f, .ch = 1, .vol_src = &audio_volume_sfx,
209 .name = "Balls Rolling", .flags = SFX_FLAG_REPEAT | SFX_FLAG_PERSISTENT
210 };
211
212 // Various oneshots
213 sfx_system audio_system_balls_switching =
214 {
215 .vol = 0.2f, .ch = 1, .vol_src = &audio_volume_sfx,
216 .name = "Balls Switching"
217 };
218
219 // Gameplay critical sounds eg. splitter sound rocking
220 sfx_system audio_system_balls_important =
221 {
222 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
223 .name = "Balls Gameplay"
224 };
225
226 // Suplemental sounds
227 sfx_system audio_system_balls_extra =
228 {
229 .vol = 0.27f, .ch = 1, .vol_src = &audio_volume_sfx,
230 .name = "Balls Extra"
231 };
232
233 sfx_system audio_system_ui =
234 {
235 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
236 .name = "UI"
237 };
238
239 ui_colourset ui_fl_colours = {
240 .main = 0xff807373,
241 .hover = 0xff918484,
242 .active = 0xffad9f9e
243 };
244
245 ui_colourset ui_fl_colours_inactive = {
246 .main = 0xff655958,
247 .hover = 0xff655958,
248 .active = 0xff655958
249 };
250
251 static void resource_load_main(void)
252 {
253 // Textures // UI
254 vg_tex2d_init( texture_list, vg_list_size( texture_list ) );
255 ui_global_ctx.colours_main = &ui_fl_colours;
256 gui_reset_colours();
257
258 // Audio
259 sfx_set_init( &audio_tile_mod, NULL );
260 sfx_set_init( &audio_splitter, NULL );
261 sfx_set_init( &audio_rolls, NULL );
262 sfx_set_init( &audio_random, NULL );
263 sfx_set_init( &audio_clicks, NULL );
264 sfx_set_init( &audio_tones, NULL );
265 }
266
267 static void resource_free_main(void)
268 {
269 vg_tex2d_free( texture_list, vg_list_size( texture_list ) );
270
271 sfx_set_free( &audio_tile_mod );
272 sfx_set_free( &audio_splitter );
273 sfx_set_free( &audio_rolls );
274 sfx_set_free( &audio_random );
275 sfx_set_free( &audio_clicks );
276 sfx_set_free( &audio_tones );
277 }
278
279 // SHADERS
280 // ===========================================================================================================
281
282 SHADER_DEFINE( shader_tile_colour,
283
284 // VERTEX
285 "layout (location=0) in vec2 a_co;"
286 "uniform mat3 uPv;"
287 "uniform vec3 uOffset;"
288 ""
289 "void main()"
290 "{"
291 "gl_Position = vec4( uPv * vec3( a_co * uOffset.z + uOffset.xy, 1.0 ), 1.0 );"
292 "}",
293
294 // FRAGMENT
295 "out vec4 FragColor;"
296 "uniform vec4 uColour;"
297 ""
298 "void main()"
299 "{"
300 "FragColor = uColour;"
301 "}"
302 ,
303 UNIFORMS({ "uPv", "uOffset", "uColour" })
304 )
305
306 SHADER_DEFINE( shader_ball,
307 // VERTEX
308 "layout (location=0) in vec2 a_co;"
309 "uniform vec3 uOffset;"
310 "uniform mat3 uPv;"
311 ""
312 "out vec4 aTexCoords;"
313 ""
314 "void main()"
315 "{"
316 // Vertex transform
317 "vec3 worldpos = vec3( (a_co * 0.5 - 0.25) * uOffset.z + uOffset.xy, 1.0 );"
318 "gl_Position = vec4( uPv * worldpos, 1.0 );"
319
320 // Create texture coords
321 "aTexCoords = vec4( a_co, worldpos.xy );"
322 "}",
323
324 // FRAGMENT
325 "out vec4 FragColor;"
326 ""
327 "uniform sampler2D uTexMain;"
328 "uniform vec3 uColour;"
329 "uniform vec2 uTexOffset;"
330 ""
331 "in vec4 aTexCoords;"
332 ""
333 "void main()"
334 "{"
335 "vec2 center_coords = aTexCoords.xy - 0.5;"
336 "vec2 center_coords_sqr = center_coords*center_coords;"
337 "float circle_factor = smoothstep( 0.07, 0.0625, center_coords_sqr.x+center_coords_sqr.y );"
338
339 "float bulge_amt = center_coords_sqr.x+center_coords_sqr.y;"
340 "vec2 warped_coords = aTexCoords.zw+uTexOffset - center_coords;"
341 "vec4 noise_sample = texture( uTexMain, warped_coords );"
342
343 "float rim_light = (center_coords_sqr.x+center_coords_sqr.y)*15.0;"
344
345 "vec2 shadow_coords = center_coords + vec2(0.02,0.07);"
346 "vec2 shadow_coords_sqr = shadow_coords*shadow_coords;"
347 "float shadow = exp(-((shadow_coords_sqr.x+shadow_coords_sqr.y)-0.0125)*15.0);"
348
349 "vec3 marble_comp = uColour*0.9 + (noise_sample.x*0.7+pow(rim_light,3.0)*2.0) * 0.1;"
350 "vec4 colour_comp = mix( vec4(0.74,0.53,0.34,shadow), vec4(marble_comp,1.0), circle_factor );"
351
352 "FragColor = colour_comp;"
353 "}"
354 ,
355 UNIFORMS({ "uTexMain", "uColour", "uOffset", "uPv", "uTexOffset" })
356 )
357
358 SHADER_DEFINE( shader_tile_main,
359 // VERTEX
360 "layout (location=0) in vec2 a_co;"
361 "uniform vec4 uOffset;" // Tile x/y, uv x/y
362 "uniform mat3 uPv;"
363 "uniform mat2 uSubTransform;"
364 ""
365 "out vec4 aTexCoords;"
366 "out vec2 aWorldCoords;"
367 ""
368 "vec2 hash22(vec2 p)"
369 "{"
370 "vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));"
371 "p3 += dot(p3, p3.yzx+33.33);"
372 "return fract((p3.xx+p3.yz)*p3.zy);"
373 "}"
374 ""
375 "void main()"
376 "{"
377 // Vertex transform
378 "vec2 subtransform = uSubTransform * (a_co-0.5) + 0.5;"
379 "vec3 worldpos = vec3( subtransform + uOffset.xy, 1.0 );"
380 "gl_Position = vec4( uPv * worldpos, 1.0 );"
381
382 // Create texture coords
383 "vec2 random_offset = floor(hash22(uOffset.xy) * 4.0) * 0.25;"
384 "vec2 edge_safe_coords = a_co * 0.98 + 0.01;"
385 "aTexCoords = vec4((edge_safe_coords + uOffset.zw) * 0.25, edge_safe_coords * 0.25 + random_offset );"
386 "aWorldCoords = worldpos.xy;"
387 "}",
388
389 // FRAGMENT
390 "out vec4 FragColor;"
391 ""
392 "uniform sampler2D uTexGlyphs;"
393 "uniform sampler2D uTexWood;"
394 "uniform float uGhost;"
395 "uniform float uForeground;"
396 "uniform vec2 uMousePos;"
397 "uniform vec4 uColour;"
398 ""
399 "in vec4 aTexCoords;"
400 "in vec2 aWorldCoords;"
401 ""
402 "void main()"
403 "{"
404 "vec3 shadowing_colour = vec3( 0.93, 0.88536, 0.8184 ) * 0.97;"
405 "vec4 glyph = texture( uTexGlyphs, aTexCoords.xy );"
406 "vec4 wood = texture( uTexWood, aTexCoords.zw );"
407 "vec4 wood_secondary = texture( uTexWood, aTexCoords.zw + 0.25 );"
408 "vec3 wood_comp = mix( wood_secondary.rgb * shadowing_colour, wood.rgb, clamp( glyph.b * 2.0 - 1.0, 0.0, 1.0 ) );"
409
410 "vec3 shadows = mix( vec3( 0.85, 0.7344, 0.561 ), vec3(1.0,1.0,1.0), glyph.r );"
411
412 "vec4 output_regular = vec4( wood_comp * shadows, mix( glyph.a, glyph.b, uForeground ) );"
413
414 "float ghost_dist = clamp( 1.5 - distance(uMousePos, aWorldCoords), 0.0, 1.0 );"
415 "vec4 output_ghost = vec4( 1.0, 1.0, 1.0, glyph.g * ghost_dist );"
416
417 "FragColor = mix( output_regular, output_ghost, uGhost ) * uColour;"
418 "}"
419 ,
420 UNIFORMS({ "uPv", "uOffset", "uTexGlyphs", "uTexWood", "uSubTransform", "uGhost", "uMousePos", "uColour", "uForeground" })
421 )
422
423 SHADER_DEFINE( shader_background,
424 // VERTEX
425 "layout (location=0) in vec2 a_co;"
426 "uniform mat3 uPv;"
427 "uniform vec3 uOffset;"
428 ""
429 "out vec2 aTexCoords;"
430 ""
431 "void main()"
432 "{"
433 "vec2 world_pos = a_co * uOffset.z + uOffset.xy;"
434 "gl_Position = vec4( uPv * vec3( world_pos, 1.0 ), 1.0 );"
435 "aTexCoords = a_co;"
436 "}",
437
438 // FRAGMENT
439 "out vec4 FragColor;"
440 ""
441 "uniform sampler2D uTexMain;"
442 "uniform sampler2D uSamplerNoise;"
443 "uniform float uVariance;"
444 ""
445 "in vec2 aTexCoords;"
446 ""
447 "void main()"
448 "{"
449 "float ao_accum = 0.0;"
450 "for( int i=0; i<10; ++i )"
451 "{"
452 "vec2 random_noise = (texture( uSamplerNoise, aTexCoords * 20.0 + float(i) * 0.2 ).xy - vec2( 0.5, 0.5 )) * uVariance;"
453 "vec4 background = texture( uTexMain, aTexCoords + random_noise );"
454 "ao_accum += background.r * clamp((1.0 - length( random_noise )), 0.0, 1.0);"
455 "}"
456 "ao_accum *= 0.15;"
457
458 "vec4 data_this_tile = texture( uTexMain, aTexCoords );"
459
460 "ao_accum -= data_this_tile.r;"
461
462 "vec3 colour_main = mix( vec3( 0.369768, 0.3654, 0.42 ),vec3( 0.275, 0.388, 0.553 ), data_this_tile.g );"
463
464 "vec2 square_coords = fract( aTexCoords * 64.0 );"
465 "vec2 grid_coords = abs( square_coords - 0.5 );"
466 "float edge_contrast = (1.0-ao_accum*0.2);"
467
468 "float gridline = step( 0.49, max(grid_coords.x,grid_coords.y) );"
469 "float gridline_fadeout = min(max(edge_contrast-1.0, 0.0)*40.0 + data_this_tile.g,10.0);"
470
471 "FragColor = vec4( colour_main * edge_contrast + gridline * 0.02 * gridline_fadeout, 1.0 );"
472 "}"
473 ,
474 UNIFORMS({ "uPv", "uOffset", "uTexMain", "uVariance", "uSamplerNoise" })
475 )
476
477 SHADER_DEFINE( shader_wire,
478 // VERTEX
479 "layout (location=0) in vec2 a_co;"
480 "uniform vec3 uStart;"
481 "uniform vec3 uEnd;"
482 "uniform mat3 uPv;"
483 "uniform float uCurve;"
484 ""
485 "out vec2 aTexCoords;"
486 ""
487 "vec3 sample_curve_time( float t )"
488 "{"
489 "vec3 line_coord = mix( uStart, uEnd, t );"
490
491 "float curve_amt = 1.0-(pow((t*2.0-1.0),2.0));"
492 "return vec3( line_coord.x, line_coord.y - curve_amt*uCurve, line_coord.z );"
493 "}"
494 ""
495 "void main()"
496 "{"
497 // Vertex transform
498 "vec3 p0 = sample_curve_time( a_co.x );"
499 "vec3 p1 = sample_curve_time( a_co.x + 0.025 );"
500
501 "vec2 line_tangent = normalize(p1.xy-p0.xy);"
502 "vec2 line_normal = vec2( -line_tangent.y, line_tangent.x );"
503
504 "vec2 worldfinal = p0.xy + line_normal*a_co.y*p0.z;"
505
506 "gl_Position = vec4( uPv * vec3(worldfinal, 1.0), 1.0 );"
507
508 // Create texture coords (todo: include stretch adjusted coords?)
509 "aTexCoords = vec2( a_co.x, a_co.y + 0.5 );"
510 "}",
511
512 // FRAGMENT
513 "out vec4 FragColor;"
514 ""
515 "uniform sampler2D uTexMain;"
516 "uniform vec4 uColour;"
517 "uniform float uTime;"
518 "uniform float uGlow;"
519 ""
520 "in vec2 aTexCoords;"
521 ""
522 "void main()"
523 "{"
524 // Compute shadowing
525 "float shadow = 1.0 - abs(aTexCoords.y - 0.5) * 2.0;"
526 "float masking = smoothstep( 0.5, 0.8, shadow );"
527
528 "vec3 colour_comp = mix( vec3(0.0,0.0,0.0), uColour.rgb, masking );"
529
530 "float flow_thing = fract( aTexCoords.x + uTime );"
531 "vec3 final_comp = colour_comp + flow_thing * uGlow;"
532
533 "FragColor = vec4( final_comp, max( shadow* 0.2, masking ) * uColour.a );"
534 "}"
535 ,
536 UNIFORMS({ "uPv", "uColour", "uTexMain", "uStart", "uEnd", "uCurve", "uTime", "uGlow" })
537 )
538
539 SHADER_DEFINE( shader_buttons,
540 // VERTEX
541 "layout (location=0) in vec2 a_co;"
542 "uniform vec4 uOffset;" // Tile x/y, uv x/y
543 "uniform mat3 uPv;"
544 ""
545 "out vec2 aTexCoords;"
546 ""
547 "void main()"
548 "{"
549 // Vertex transform
550 "vec3 worldpos = vec3( a_co + uOffset.xy, 1.0 );"
551 "gl_Position = vec4( uPv * worldpos, 1.0 );"
552
553 // Create texture coords
554 "vec2 edge_safe_coords = a_co * 0.98 + 0.01;"
555 "aTexCoords = (edge_safe_coords + uOffset.zw) * 0.25;"
556 "}",
557
558 // FRAGMENT
559 "out vec4 FragColor;"
560 ""
561 "uniform sampler2D uTexMain;"
562 "uniform vec4 uColour;" // rgb, light amount
563 ""
564 "in vec2 aTexCoords;"
565 ""
566 "void main()"
567 "{"
568 "vec4 glyph = texture( uTexMain, aTexCoords.xy );"
569
570 "FragColor = vec4( uColour.rgb * (mix(glyph.r, glyph.g, uColour.a)+0.02)*2.6 + glyph.b * 0.4, glyph.a );"
571 "}"
572 ,
573 UNIFORMS({ "uPv", "uOffset", "uTexMain", "uColour" })
574 )
575
576 SHADER_DEFINE( shader_sdf,
577
578 // VERTEX
579 "layout (location=0) in vec2 a_co;"
580 "layout (location=1) in vec2 a_uv;"
581 "layout (location=2) in vec4 a_colour;"
582 "uniform mat3 uPv;"
583 ""
584 "out vec2 aTexCoords;"
585 "out vec4 aColour;"
586 ""
587 "void main()"
588 "{"
589 "gl_Position = vec4( uPv * vec3( a_co, 1.0 ), 1.0 );"
590 "aTexCoords = a_uv;"
591 "aColour = a_colour;"
592 "}",
593
594 // FRAGMENT
595 "uniform sampler2D uTexGlyphs;"
596 "out vec4 FragColor;"
597 ""
598 "in vec2 aTexCoords;"
599 "in vec4 aColour;"
600 ""
601 "void main()"
602 "{"
603 "vec4 glyph = texture( uTexGlyphs, aTexCoords );"
604 "FragColor = vec4( aColour.rgb, smoothstep( 0.48, 0.52, glyph.r ) * aColour.a );"
605 //"FragColor = glyph;"
606 "}"
607 ,
608 UNIFORMS({ "uPv", "uTexGlyphs" })
609 )
610
611 void vg_register(void)
612 {
613 SHADER_INIT( shader_tile_colour );
614 SHADER_INIT( shader_tile_main );
615 SHADER_INIT( shader_ball );
616 SHADER_INIT( shader_background );
617 SHADER_INIT( shader_wire );
618 SHADER_INIT( shader_buttons );
619 SHADER_INIT( shader_sdf );
620 }
621
622 /*
623 0000 0 | 0001 1 | 0010 2 | 0011 3
624 | | | | |
625 X | X= | X | X=
626 | | |
627 0100 4 | 0101 5 | 0110 6 | 0111 7
628 | | | | |
629 =X | =X= | =X | =X=
630 | | |
631 1000 8 | 1001 9 | 1010 10 | 1011 11
632 | | | | |
633 X | X= | X | X=
634 | | | | | | |
635 1100 12 | 1101 13 | 1110 14 | 1111 15
636 | | | | |
637 =X | =X= | =X | =X=
638 | | | | | | |
639 */
640
641 struct cmp_level
642 {
643 const char *map_name;
644 const char *title;
645 const char *description;
646
647 int unlocked;
648 int completed_score;
649
650 int _unlock, _linked; // When completed, unlock this level
651 struct cmp_level *unlock, *linked;
652
653 int serial_id;
654 int is_tutorial;
655
656 SteamLeaderboard_t steam_leaderboard;
657 };
658
659 static struct cmp_level cmp_levels_tutorials[] =
660 {
661 // r1
662 {
663 .serial_id = 0,
664 .title = "PRINCIPLE 1",
665 .map_name = "cmp_t01",
666 .description =
667 "Utilize basic transport methods",
668
669 ._unlock = 1,
670 .is_tutorial = 1
671 },
672 // r1
673 {
674 .serial_id = 1,
675 .title = "PRINCIPLE 2",
676 .map_name = "cmp_t02",
677 .description =
678 "Utilize the twisty turny(TM) piece to split the marble\n"
679 "stream into two",
680
681 ._unlock = 2,
682 .is_tutorial = 1,
683 },
684 // r1
685 {
686 .serial_id = 2,
687 .title = "PRINCIPLE 3",
688 .map_name = "cmp_t03",
689 .description =
690 "Merge transport into one path",
691
692 ._unlock = 12,
693 .is_tutorial = 1
694 },
695 // r1
696 {
697 .serial_id = 12,
698 .title = "PRINCIPLE 4",
699 .map_name = "cmp_t04",
700 .description =
701 "Some stages require multiple runs to succeed in order to\n"
702 "pass",
703
704 ._unlock = 6,
705 .is_tutorial = 1
706 }
707 };
708
709 static struct cmp_level cmp_levels_basic[] =
710 {
711 // r2 GM
712 {
713 .serial_id = 6,
714 .title = "PATCH",
715 .map_name = "cmp_b04",
716 .description =
717 "For some reason, the division module our intern built\n"
718 "for us is sending twice as many yellows as needed. Send\n"
719 "the excess to be recycled!",
720
721 ._unlock = 7,
722 ._linked = 3
723 },
724 // r1 GM
725 {
726 .serial_id = 3,
727 .title = "SUBDIVISION 1",
728 .map_name = "cmp_b01",
729 .description =
730 "Sometimes getting the desired amount takes dividing up\n"
731 "the input and recombining it.",
732
733 ._linked = 4,
734 ._unlock = 5
735 },
736 // r1 GM
737 {
738 .serial_id = 4,
739 .title = "SUBDIVISION 2",
740 .map_name = "cmp_b02",
741 .description =
742 "",
743
744 ._unlock = 7
745 },
746 // r1 GM
747 {
748 .serial_id = 5,
749 .title = "RESTRUCTURE",
750 .map_name = "cmp_b03",
751 .description =
752 "It is possible to swap these values using simple\n"
753 "division and addition.",
754
755 ._unlock = 8
756 },
757 // r2 GM
758 {
759 .serial_id = 7,
760 .title = "PATTERNS 1",
761 .map_name = "cmp_b05",
762 .description =
763 "Replicate the pattern",
764
765 ._linked = 8
766 },
767 // r2 GM
768 {
769 .serial_id = 8,
770 .title = "PATTERNS 2",
771 .map_name = "cmp_b06",
772 .description =
773 "Replicate MORE",
774
775 ._unlock = 15
776 },
777 // r2 GM
778 {
779 .serial_id = 15,
780 .title = "PRINCIPLE 5",
781 .map_name = "cmp_b10",
782 .description =
783 "The sharp engineers among you may have already spotted\n"
784 "and utilized this part of the system\n"
785 "\n"
786 "We forgot to include the relevant principle tasks as\n"
787 "of your training package, you will now be tasked to\n"
788 "complete them",
789
790 ._unlock = 16,
791 .is_tutorial = 1
792 },
793 // r2 GM
794 {
795 .serial_id = 16,
796 .title = "ROUTING PROBLEM",
797 .map_name = "cmp_routing",
798 .description =
799 "Things can get a little chaotic on tight boards, do your\n"
800 "best to utilize principle 5 to get the job done\n",
801
802 ._linked = 9
803 },
804 // r2 GM
805 {
806 .serial_id = 9,
807 .title = "MIGHTY CONSUMER",
808 .map_name = "cmp_b07",
809 .description =
810 "Build a greedy system",
811
812 ._linked = 10,
813 ._unlock = 11
814 },
815 {
816 .serial_id = 10,
817 .title = "SHIFT",
818 .map_name = "cmp_b08",
819 .description =
820 "",
821
822 ._unlock = 17
823 },
824 // r2 GM
825 {
826 .serial_id = 11,
827 .title = "REVERSE",
828 .map_name = "cmp_b09",
829 .description =
830 "Reverse the incoming order. Always length 4",
831
832 ._unlock = 17
833 },
834 // r2 GM
835 {
836 .serial_id = 17,
837 .title = "PRINCIPLE 6",
838 .map_name = "cmp_b11",
839 .description =
840 "Usually the splitter piece will flip flop between left\n"
841 "and right, however it can be forced to only rotate in\n"
842 "one direction if trigger wires are attached.\n"
843 "\n"
844 "Right click and drag from a regular block, and attach it\n"
845 "to a splitter. This creates a trigger.\n"
846 "The default state is left, and once a marble hits the\n"
847 "trigger it will switch to rotating that direction.",
848
849 ._unlock = 18,
850 .is_tutorial = 1
851 },
852 // r2 GM
853 {
854 .serial_id = 18,
855 .title = "NOT GATE",
856 .map_name = "cmp_not",
857 .description =
858 "Test your knowledge of triggers, build an 'NOT GATE'\n"
859 "emulated by marble logic.",
860
861 ._linked = 19,
862 ._unlock = 20
863 },
864 // r2 GM
865 {
866 .serial_id = 19,
867 .title = "AND GATE",
868 .map_name = "cmp_and",
869 .description =
870 "A slightly more complicated gate, but shouldn't be\n"
871 "too difficult for your skillset.",
872
873 ._unlock = 20
874 },
875 // r2 GM
876 {
877 .serial_id = 20,
878 .title = "QUALIFICATION PROJECT",
879 .map_name = "cmp_xor",
880 .description =
881 "Significantly more complicated than an AND or NOT gate,\n"
882 "but possible.",
883
884 ._unlock = 13
885 }
886 };
887
888 static struct cmp_level cmp_levels_grad[] =
889 {
890 // r2
891 {
892 .serial_id = 13,
893 .title = "SORT",
894 .map_name = "cmp_i01",
895 .description =
896 "Devise a scheme to filter and sort the inputs. If you\n"
897 "believe you lack the tools required to solve this one,\n"
898 "take a harder look at the inputs.",
899 ._linked = 14
900
901 },
902 // r2
903 {
904 .serial_id = 14,
905 .title = "THIRDS",
906 .map_name = "cmp_i02",
907 .description =
908 "Split the inputs up into a third of their values\n"
909 "\n"
910 "Is this possible? -HG",
911 ._linked = 21
912
913 },
914 // r2 GM
915 {
916 .serial_id = 21,
917 .title = "SIMPLE ADDITION",
918 .map_name = "cmp_grad",
919 .description =
920 "Take the amount of yellows coming in, and add them\n"
921 "together. Send your result using the stream of blues.",
922
923 ._linked = 22
924 },
925 // r2 GM
926 {
927 .serial_id = 22,
928 .title = "SECRET CODE",
929 .map_name = "cmp_secret",
930 .description =
931 ""
932 }
933 };
934
935 #define NUM_CAMPAIGN_LEVELS (vg_list_size( cmp_levels_tutorials ) + vg_list_size( cmp_levels_basic ) + vg_list_size( cmp_levels_grad ))
936
937 static struct serializable_set
938 {
939 struct cmp_level *pack;
940 int count;
941 }
942 career_serializable[] =
943 {
944 {
945 .pack = cmp_levels_tutorials,
946 .count = vg_list_size( cmp_levels_tutorials )
947 },
948 {
949 .pack = cmp_levels_basic,
950 .count = vg_list_size( cmp_levels_basic )
951 },
952 {
953 .pack = cmp_levels_grad,
954 .count = vg_list_size( cmp_levels_grad )
955 }
956 };
957
958 // Setup pointers and that
959 static void career_local_data_init(void)
960 {
961 struct cmp_level *level_ptrs[ NUM_CAMPAIGN_LEVELS ];
962
963 // COllect pointers
964 for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
965 {
966 struct serializable_set *set = &career_serializable[i];
967
968 for( int j = 0; j < set->count; j ++ )
969 level_ptrs[ set->pack[j].serial_id ] = &set->pack[j];
970 }
971
972 // Apply
973 for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
974 {
975 struct serializable_set *set = &career_serializable[i];
976
977 for( int j = 0; j < set->count; j ++ )
978 {
979 struct cmp_level *lvl = &set->pack[j];
980 lvl->unlock = lvl->_unlock? level_ptrs[ lvl->_unlock ]: NULL;
981 lvl->linked = lvl->_linked? level_ptrs[ lvl->_linked ]: NULL;
982 }
983 }
984 }