Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
ex_fluid.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
28#define ALLEGRO_UNSTABLE 1
29
30#include <locale.h>
31
32#include "nilorea/n_common.h"
33#include "nilorea/n_log.h"
34#include "nilorea/n_list.h"
35#include "nilorea/n_str.h"
36#include "nilorea/n_time.h"
37#include "nilorea/n_fluids.h"
38
39#include <allegro5/allegro.h>
40#include <allegro5/allegro_ttf.h>
41#include "allegro5/allegro_audio.h"
42#include "allegro5/allegro_acodec.h"
43#include <allegro5/allegro_font.h>
44#include <allegro5/allegro_image.h>
45#include <allegro5/allegro_primitives.h>
46
47#include "ex_fluid_config.h"
48
50#define RESERVED_SAMPLES 16
52#define MAX_SAMPLE_DATA 10
53
54ALLEGRO_DISPLAY* display = NULL;
55
56/* VARIOUS DECLARATIONS * */
57
58int DONE = 0, /* Flag to check if we are always running */
59 getoptret = 0, /* launch parameter check */
60 log_level = LOG_ERR; /* default LOG_LEVEL */
61
62double drawFPS = 60.0;
63double logicFPS = 120.0;
64
65ALLEGRO_TIMER* fps_timer = NULL;
66ALLEGRO_TIMER* logic_timer = NULL;
69
71int WIDTH = 800,
72 HEIGHT = 600;
73bool fullscreen = 0;
74char* bgmusic = NULL;
75
77
78int main(int argc, char* argv[]) {
79 /* Set the locale to the POSIX C environment */
80 setlocale(LC_ALL, "POSIX");
81
83
84 N_STR* log_file = NULL;
85 nstrprintf(log_file, "%s.log", argv[0]);
86 /*set_log_file( _nstr( log_file ) );*/
88
89 char ver_str[128] = "";
90
91 while ((getoptret = getopt(argc, argv, "hvV:L:")) != EOF) {
92 switch (getoptret) {
93 case 'h':
94 n_log(LOG_NOTICE, "\n %s -h help -v version -V DEBUGLEVEL (NOLOG,VERBOSE,NOTICE,ERROR,DEBUG)\n", argv[0]);
95 exit(TRUE);
96 case 'v':
97 sprintf(ver_str, "%s %s", __DATE__, __TIME__);
98 exit(TRUE);
99 break;
100 case 'V':
101 if (!strncmp("INFO", optarg, 6)) {
103 } else {
104 if (!strncmp("NOTICE", optarg, 6)) {
106 } else {
107 if (!strncmp("VERBOSE", optarg, 7)) {
109 } else {
110 if (!strncmp("ERROR", optarg, 5)) {
112 } else {
113 if (!strncmp("DEBUG", optarg, 5)) {
115 } else {
116 n_log(LOG_ERR, "%s is not a valid log level", optarg);
117 exit(FALSE);
118 }
119 }
120 }
121 }
122 }
123 n_log(LOG_NOTICE, "LOG LEVEL UP TO: %d", log_level);
125 break;
126 case 'L':
127 n_log(LOG_NOTICE, "LOG FILE: %s", optarg);
128 set_log_file(optarg);
129 break;
130 case '?': {
131 switch (optopt) {
132 case 'V':
133 n_log(LOG_ERR, "\nPlease specify a log level after -V. \nAvailable values: NOLOG,VERBOSE,NOTICE,ERROR,DEBUG");
134 break;
135 case 'L':
136 n_log(LOG_ERR, "\nPlease specify a log file after -L");
137 default:
138 break;
139 }
140 }
141 __attribute__((fallthrough));
142 default:
143 n_log(LOG_ERR, "\n %s -h help -v version -V DEBUGLEVEL (NOLOG,VERBOSE,NOTICE,ERROR,DEBUG) -L logfile", argv[0]);
144 exit(FALSE);
145 }
146 }
147 /*
148 * INITIALISATION
149 */
150 int threadedProcessing = 0;
151 N_FLUID* fluid_data = NULL;
152 Malloc(fluid_data, N_FLUID, 1);
153 if (load_app_state("CONFIGS/ex_fluid.cfg", &WIDTH, &HEIGHT, &fullscreen, &bgmusic, &drawFPS, &logicFPS, fluid_data, &threadedProcessing) != TRUE) {
154 n_log(LOG_ERR, "couldn't load CONFIGS/ex_fluid.cfg !");
155 exit(1);
156 }
157 double fluid_factor = fluid_data->cScale;
158 n_log(LOG_DEBUG, "%s starting with params: %dx%d fullscreen(%d), music: %s", argv[0], WIDTH, HEIGHT, fullscreen, _str(bgmusic));
159
160 /* allegro 5 + addons loading */
161 if (!al_init()) {
162 n_abort("Could not init Allegro.\n");
163 }
164 if (!al_init_acodec_addon()) {
165 n_abort("Could not register addons.\n");
166 }
167 if (!al_install_audio()) {
168 n_log(LOG_ERR, "Unable to initialize audio addon, disabling bgmusic\n");
169 Free(bgmusic);
170 }
171 if (!al_init_acodec_addon()) {
172 n_abort("Unable to initialize acoded addon\n");
173 }
174 if (!al_init_image_addon()) {
175 n_abort("Unable to initialize image addon\n");
176 }
177 if (!al_init_primitives_addon()) {
178 n_abort("Unable to initialize primitives addon\n");
179 }
180 if (!al_init_font_addon()) {
181 n_abort("Unable to initialize font addon\n");
182 }
183 if (!al_init_ttf_addon()) {
184 n_abort("Unable to initialize ttf_font addon\n");
185 }
186 if (!al_install_keyboard()) {
187 n_abort("Unable to initialize keyboard handler\n");
188 }
189 if (!al_install_mouse()) {
190 n_abort("Unable to initialize mouse handler\n");
191 }
192
193 if (bgmusic && !al_reserve_samples(RESERVED_SAMPLES)) {
194 n_abort("Could not set up voice and mixer.\n");
195 }
196
197 ALLEGRO_SAMPLE* sample_data[MAX_SAMPLE_DATA] = {NULL};
198 memset(sample_data, 0, sizeof(sample_data));
199
200 ALLEGRO_EVENT_QUEUE* event_queue = NULL;
201
202 event_queue = al_create_event_queue();
203 if (!event_queue) {
204 fprintf(stderr, "failed to create event_queue!\n");
205 return -1;
206 }
207
208 if (fullscreen) {
209 al_set_new_display_flags(ALLEGRO_OPENGL | ALLEGRO_FULLSCREEN_WINDOW);
210 } else {
211 al_set_new_display_flags(ALLEGRO_OPENGL | ALLEGRO_WINDOWED);
212 }
213
214#ifdef __windows__
215 al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP | ALLEGRO_NO_PRESERVE_TEXTURE);
216#endif
217
218 display = al_create_display(WIDTH, HEIGHT);
219 if (!display) {
220 n_abort("Unable to create display\n");
221 }
222
223 al_set_window_title(display, argv[0]);
224
225 ALLEGRO_FONT* font = al_load_font("DATAS/2Dumb.ttf", 18, 0);
226 if (!font) {
227 n_abort("Unable to load font DATAS/2Dumb.ttf\n");
228 }
229
230 DONE = 0;
231 fps_timer = al_create_timer(1.0 / drawFPS);
232 logic_timer = al_create_timer(1.0 / logicFPS);
233
234 al_register_event_source(event_queue, al_get_display_event_source(display));
235 al_start_timer(fps_timer);
236 al_start_timer(logic_timer);
237 al_register_event_source(event_queue, al_get_timer_event_source(fps_timer));
238 al_register_event_source(event_queue, al_get_timer_event_source(logic_timer));
239
240 al_register_event_source(event_queue, al_get_keyboard_event_source());
241 al_register_event_source(event_queue, al_get_mouse_event_source());
242
243 bool backbuffer = 1;
244 ALLEGRO_BITMAP* scrbuf = NULL;
245 ALLEGRO_BITMAP* bitmap = NULL;
246
247 al_hide_mouse_cursor(display);
248
249 enum APP_KEYS {
250 KEY_UP,
251 KEY_DOWN,
252 KEY_LEFT,
253 KEY_RIGHT,
254 KEY_ESC,
255 KEY_SPACE,
256 KEY_CTRL,
257 KEY_SHIFT,
258 KEY_PAD_MINUS,
259 KEY_PAD_PLUS,
260 KEY_PAD_ENTER,
261 KEY_M,
262 KEY_W,
263 KEY_F1,
264 KEY_F2,
265 KEY_F3,
266 KEY_F4,
267 KEY_F5,
268 KEY_F6
269 };
270 int key[19] = {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false};
271
272 if (bgmusic) {
273 if (!(sample_data[0] = al_load_sample(bgmusic))) {
274 n_log(LOG_ERR, "Could not load %s", bgmusic);
275 exit(1);
276 }
277 al_play_sample(sample_data[0], 1, 0, 1, ALLEGRO_PLAYMODE_LOOP, NULL);
278 }
279
280 long int nb_cores = get_nb_cpu_cores();
281 if (nb_cores <= 0) {
282 nb_cores = 1;
283 }
284 thread_pool = new_thread_pool((size_t)nb_cores, 0);
285
286 /* set fluid */
287 fluid_sim = new_n_fluid(fluid_data->density, fluid_data->gravity, fluid_data->numIters, fluid_data->fluid_production_percentage, fluid_data->overRelaxation, (size_t)(WIDTH / fluid_factor), (size_t)(HEIGHT / fluid_factor));
288
289 fluid_sim->density = fluid_data->density;
290 fluid_sim->gravity = fluid_data->gravity;
291 fluid_sim->numIters = fluid_data->numIters;
294 fluid_sim->cScale = fluid_data->cScale;
295 Free(fluid_data);
296
297 fluid_sim->dt = 1.0 / logicFPS;
298
299 size_t n = fluid_sim->numY;
300 double inVel = 2.0;
301 for (size_t i = 0; i < fluid_sim->numX; i++) {
302 for (size_t j = 0; j < fluid_sim->numY; j++) {
303 double s = 1.0; // fluid
304 if (i == 0 || j == 0 || j == fluid_sim->numY - 1)
305 s = 0.0; // solid
306 //
307 fluid_sim->s[i * n + j] = s;
308
309 if (i == 1) {
310 fluid_sim->u[i * n + j] = inVel;
311 }
312 }
313 }
314 double pipeH = fluid_sim->fluid_production_percentage * (double)fluid_sim->numY;
315 size_t minJ = (size_t)floor(0.5 * (double)fluid_sim->numY - 0.5 * pipeH);
316 size_t maxJ = (size_t)floor(0.5 * (double)fluid_sim->numY + 0.5 * pipeH);
317 for (size_t j = 0; j < minJ; j++)
318 fluid_sim->m[j] = 1.0;
319 for (size_t j = minJ; j < maxJ; j++)
320 fluid_sim->m[j] = 0.0;
321 for (size_t j = maxJ; j < fluid_sim->numY; j++)
322 fluid_sim->m[j] = 1.0;
323
324 bool do_draw = 1, do_logic = 1;
325 int mx = WIDTH / 3, my = HEIGHT / 2, mouse_button = 0, mouse_b1 = 0, mouse_b2 = 0;
326
328
329 al_flush_event_queue(event_queue);
330 al_set_mouse_xy(display, WIDTH / 3, HEIGHT / 2);
331
332 int w = al_get_display_width(display);
333 int h = al_get_display_height(display);
334
335 bitmap = al_create_bitmap(WIDTH, HEIGHT);
336
337 size_t logic_duration = 0;
338 size_t drawing_duration = 0;
339 do {
340 do {
341 ALLEGRO_EVENT ev;
342
343 al_wait_for_event(event_queue, &ev);
344
345 if (ev.type == ALLEGRO_EVENT_KEY_DOWN) {
346 switch (ev.keyboard.keycode) {
347 case ALLEGRO_KEY_UP:
348 key[KEY_UP] = 1;
349 break;
350 case ALLEGRO_KEY_DOWN:
351 key[KEY_DOWN] = 1;
352 break;
353 case ALLEGRO_KEY_LEFT:
354 key[KEY_LEFT] = 1;
355 break;
356 case ALLEGRO_KEY_RIGHT:
357 key[KEY_RIGHT] = 1;
358 break;
359 case ALLEGRO_KEY_ESCAPE:
360 key[KEY_ESC] = 1;
361 break;
362 case ALLEGRO_KEY_SPACE:
363 key[KEY_SPACE] = 1;
364 break;
365 case ALLEGRO_KEY_LSHIFT:
366 case ALLEGRO_KEY_RSHIFT:
367 key[KEY_SHIFT] = 1;
368 break;
369 case ALLEGRO_KEY_PAD_MINUS:
370 key[KEY_PAD_MINUS] = 1;
371 break;
372 case ALLEGRO_KEY_PAD_PLUS:
373 key[KEY_PAD_PLUS] = 1;
374 break;
375 case ALLEGRO_KEY_PAD_ENTER:
376 key[KEY_PAD_ENTER] = 1;
377 break;
378 case ALLEGRO_KEY_M:
379 key[KEY_M] = 1;
380 break;
381 case ALLEGRO_KEY_W:
382 key[KEY_W] = 1;
383 break;
384 case ALLEGRO_KEY_LCTRL:
385 case ALLEGRO_KEY_RCTRL:
386 key[KEY_CTRL] = 1;
387 break;
388 case ALLEGRO_KEY_F1:
389 key[KEY_F1] = 1;
390 break;
391 case ALLEGRO_KEY_F2:
392 key[KEY_F2] = 1;
393 break;
394 case ALLEGRO_KEY_F3:
395 key[KEY_F3] = 1;
396 break;
397 case ALLEGRO_KEY_F4:
398 key[KEY_F4] = 1;
399 break;
400 case ALLEGRO_KEY_F5:
401 key[KEY_F5] = 1;
402 break;
403 case ALLEGRO_KEY_F6:
404 key[KEY_F6] = 1;
405 break;
406 default:
407 break;
408 }
409 } else if (ev.type == ALLEGRO_EVENT_KEY_UP) {
410 switch (ev.keyboard.keycode) {
411 case ALLEGRO_KEY_UP:
412 key[KEY_UP] = 0;
413 break;
414 case ALLEGRO_KEY_DOWN:
415 key[KEY_DOWN] = 0;
416 break;
417 case ALLEGRO_KEY_LEFT:
418 key[KEY_LEFT] = 0;
419 break;
420 case ALLEGRO_KEY_RIGHT:
421 key[KEY_RIGHT] = 0;
422 break;
423 case ALLEGRO_KEY_ESCAPE:
424 key[KEY_ESC] = 0;
425 break;
426 case ALLEGRO_KEY_SPACE:
427 key[KEY_SPACE] = 0;
428 break;
429 case ALLEGRO_KEY_LSHIFT:
430 case ALLEGRO_KEY_RSHIFT:
431 key[KEY_SHIFT] = 0;
432 break;
433 case ALLEGRO_KEY_PAD_MINUS:
434 key[KEY_PAD_MINUS] = 0;
435 break;
436 case ALLEGRO_KEY_PAD_PLUS:
437 key[KEY_PAD_PLUS] = 0;
438 break;
439 case ALLEGRO_KEY_PAD_ENTER:
440 key[KEY_PAD_ENTER] = 0;
441 break;
442 case ALLEGRO_KEY_M:
443 key[KEY_M] = 0;
444 break;
445 case ALLEGRO_KEY_W:
446 key[KEY_W] = 0;
447 break;
448 case ALLEGRO_KEY_LCTRL:
449 case ALLEGRO_KEY_RCTRL:
450 key[KEY_CTRL] = 0;
451 break;
452 case ALLEGRO_KEY_F1:
453 key[KEY_F1] = 0;
454 break;
455 case ALLEGRO_KEY_F2:
456 key[KEY_F2] = 0;
457 break;
458 case ALLEGRO_KEY_F3:
459 key[KEY_F3] = 0;
460 break;
461 case ALLEGRO_KEY_F4:
462 key[KEY_F4] = 0;
463 break;
464 case ALLEGRO_KEY_F5:
465 key[KEY_F5] = 0;
466 break;
467 case ALLEGRO_KEY_F6:
468 key[KEY_F6] = 0;
469 break;
470
471 default:
472 break;
473 }
474 } else if (ev.type == ALLEGRO_EVENT_TIMER) {
475 if (al_get_timer_event_source(fps_timer) == ev.any.source) {
476 do_draw = 1;
477 } else if (al_get_timer_event_source(logic_timer) == ev.any.source) {
478 do_logic = 1;
479 }
480 } else if (ev.type == ALLEGRO_EVENT_MOUSE_AXES) {
481 mx = ev.mouse.x;
482 my = ev.mouse.y;
483 } else if (ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) {
484 if (ev.mouse.button == 1)
485 mouse_b1 = 1;
486 if (ev.mouse.button == 2)
487 mouse_b2 = 1;
488 } else if (ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
489 if (ev.mouse.button == 1)
490 mouse_b1 = 0;
491 if (ev.mouse.button == 2)
492 mouse_b2 = 0;
493 }
494
495 /* Processing inputs */
496 mouse_button = -1;
497 if (mouse_b1 == 1)
498 mouse_button = 1;
499 if (mouse_b2 == 1)
500 mouse_button = 2;
501 else if (ev.type == ALLEGRO_EVENT_DISPLAY_SWITCH_IN || ev.type == ALLEGRO_EVENT_DISPLAY_SWITCH_OUT) {
502 al_clear_keyboard_state(display);
503 al_flush_event_queue(event_queue);
504 } else {
505 // Processing inputs
506 // get_keyboard( chat_line , ev );
507 if (key[KEY_F1]) {
508 fluid_sim->showSmoke = 1;
509 }
510 if (key[KEY_F2]) {
511 fluid_sim->showSmoke = 0;
512 }
513 if (key[KEY_F3]) {
515 }
516 if (key[KEY_F4]) {
518 }
519 if (key[KEY_F5]) {
520 fluid_sim->showPaint = 1;
521 }
522 if (key[KEY_F6]) {
523 fluid_sim->showPaint = 0;
524 }
525 if (key[KEY_UP]) {
526 fluid_sim->density += 100.0;
527 }
528 if (key[KEY_DOWN]) {
529 fluid_sim->density -= 100.0;
530 if (fluid_sim->density < 1.0) fluid_sim->density = 1.0;
531 }
532 if (key[KEY_LEFT]) {
534 }
535 if (key[KEY_RIGHT]) {
537 if (fluid_sim->numIters < 1.0) fluid_sim->numIters = 1.0;
538 }
539 if (key[KEY_PAD_PLUS]) {
542 }
543 if (key[KEY_PAD_MINUS]) {
546 }
547 if (mouse_button != -1) {
548 n_log(LOG_DEBUG, "mouse button: %d", mouse_button);
549 }
550 }
551 } while (!al_is_event_queue_empty(event_queue));
552
553 if (do_logic == 1) {
555 static int old_mx = -1, old_my = -1;
556 double vx = 0.0, vy = 0.0;
557 if (old_mx != mx || old_my != my) {
558 if (old_mx != -1 && old_my != -1) {
559 vx = (old_mx - mx) / logicFPS;
560 vy = (old_my - my) / logicFPS;
561 }
562 old_mx = mx;
563 old_my = my;
565 n_fluid_setObstacle(fluid_sim, mx / fluid_factor, (my / fluid_factor) - 20.0, vx, vy, fluid_factor / 2);
566 n_fluid_setObstacle(fluid_sim, (mx / fluid_factor) - 15, my / fluid_factor, vx, vy, fluid_factor / 2 + fluid_factor / 3);
567 n_fluid_setObstacle(fluid_sim, (mx / fluid_factor) + 15, my / fluid_factor - 10.0, vx, vy, fluid_factor / 2 + fluid_factor / 2);
568 n_fluid_setObstacle(fluid_sim, (mx / fluid_factor) + 15, my / fluid_factor + 10.0, vx, vy, fluid_factor / 2 + fluid_factor / 2);
569 n_fluid_setObstacle(fluid_sim, mx / fluid_factor, (my / fluid_factor) + 20.0, vx, vy, fluid_factor / 2);
570 }
571
573 minJ = (size_t)floor(0.5 * (double)fluid_sim->numY - 0.5 * pipeH);
574 maxJ = (size_t)floor(0.5 * (double)fluid_sim->numY + 0.5 * pipeH);
575 for (size_t j = 0; j < minJ; j++)
576 fluid_sim->m[j] = 1.0;
577 for (size_t j = minJ; j < maxJ; j++)
578 fluid_sim->m[j] = 0.0;
579 for (size_t j = maxJ; j < fluid_sim->numY; j++)
580 fluid_sim->m[j] = 1.0;
581 for (size_t j = minJ; j < maxJ; j++)
582 fluid_sim->m[j] = 0.0;
583
584 if (threadedProcessing == 1)
586 else
588
589 logic_duration = (logic_duration + (size_t)get_usec(&logic_chrono)) / 2;
590 do_logic = 0;
591 }
592 if (do_draw == 1) {
594
595 if (backbuffer)
596 scrbuf = al_get_backbuffer(display);
597 else
598 scrbuf = bitmap;
599
600 al_set_target_bitmap(scrbuf);
601
602 if (!backbuffer)
603 al_lock_bitmap(scrbuf, al_get_bitmap_format(scrbuf), ALLEGRO_LOCK_READWRITE);
604
606
607 al_draw_circle((float)mx, (float)(my - 20 * fluid_factor), (float)(fluid_factor * fluid_factor / 2), al_map_rgb(255, 0, 0), 2.0);
608 al_draw_circle((float)(mx - 15 * fluid_factor), (float)my, (float)(fluid_factor * fluid_factor / 2 + (fluid_factor * fluid_factor) / 3), al_map_rgb(255, 0, 0), 2.0);
609 al_draw_circle((float)(mx + 15 * fluid_factor), (float)(my + 10.0 * fluid_factor), (float)(fluid_factor * fluid_factor / 2 + (fluid_factor * fluid_factor) / 2), al_map_rgb(255, 0, 0), 2.0);
610 al_draw_circle((float)(mx + 15 * fluid_factor), (float)(my - 10.0 * fluid_factor), (float)(fluid_factor * fluid_factor / 2 + (fluid_factor * fluid_factor) / 2), al_map_rgb(255, 0, 0), 2.0);
611 al_draw_circle((float)mx, (float)(my + 20 * fluid_factor), (float)(fluid_factor * fluid_factor / 2), al_map_rgb(255, 0, 0), 2.0);
612
613 static N_STR* textout = NULL;
614 nstrprintf(textout, "[F1/F2]:showSmoke:%d [F3/F4]:showPressure:%d [F5/F6]:showPaint:%d", fluid_sim->showSmoke, fluid_sim->showPressure, fluid_sim->showPaint);
615 al_draw_text(font, al_map_rgb(0, 0, 255), (float)WIDTH, 10, ALLEGRO_ALIGN_RIGHT, _nstr(textout));
616
617 nstrprintf(textout, "numIters: %zd production: %3.3g density: %3.3g", fluid_sim->numIters, fluid_sim->fluid_production_percentage, fluid_sim->density);
618 al_draw_text(font, al_map_rgb(0, 0, 255), (float)WIDTH, 25, ALLEGRO_ALIGN_RIGHT, _nstr(textout));
619
620 nstrprintf(textout, "logic(max %zd): %zd usecs", (size_t)(1000000.0 / logicFPS), logic_duration);
621 al_draw_text(font, al_map_rgb(0, 0, 255), 5, 10, ALLEGRO_ALIGN_LEFT, _nstr(textout));
622
623 nstrprintf(textout, "drawing(max %zd): %zd usecs", (size_t)(1000000.0 / drawFPS), drawing_duration);
624 al_draw_text(font, al_map_rgb(0, 0, 255), 5, 30, ALLEGRO_ALIGN_LEFT, _nstr(textout));
625
626 if (!backbuffer) {
627 al_unlock_bitmap(scrbuf);
628 al_set_target_bitmap(al_get_backbuffer(display));
629 al_draw_bitmap(scrbuf, (float)(w / 2 - al_get_bitmap_width(scrbuf) / 2), (float)(h / 2 - al_get_bitmap_height(scrbuf) / 2), 0);
630 }
631
632 drawing_duration = (drawing_duration + (size_t)get_usec(&drawing_chrono)) / 2;
633
634 al_flip_display();
635
636 do_draw = 0;
637 }
638
639 } while (!key[KEY_ESC] && !DONE);
640
641 al_uninstall_system();
642
643 return 0;
644}
int main(void)
ALLEGRO_TIMER * fps_timer
Definition ex_fluid.c:65
THREAD_POOL * thread_pool
Definition ex_fluid.c:76
#define MAX_SAMPLE_DATA
audio MAX_SAMPLE_DATA for bgmusic
Definition ex_fluid.c:52
int getoptret
Definition ex_fluid.c:59
double drawFPS
Definition ex_fluid.c:62
int DONE
Definition ex_fluid.c:58
bool fullscreen
Definition ex_fluid.c:73
N_TIME drawing_chrono
Definition ex_fluid.c:68
N_FLUID * fluid_sim
Definition ex_fluid.c:70
N_TIME logic_chrono
Definition ex_fluid.c:67
int log_level
Definition ex_fluid.c:60
char * bgmusic
Definition ex_fluid.c:74
#define RESERVED_SAMPLES
audio RESERVED_SAMPLES for bgmusic
Definition ex_fluid.c:50
ALLEGRO_TIMER * logic_timer
Definition ex_fluid.c:66
double logicFPS
Definition ex_fluid.c:63
ALLEGRO_DISPLAY * display
Definition ex_fluid.c:54
int load_app_state(char *state_filename, int *WIDTH, int *HEIGHT, bool *fullscreen, char **bgmusic, double *drawFPS, double *logicFPS, N_FLUID *fluid, int *threaded)
Load application state from a config file.
#define WIDTH
Definition ex_gui.c:42
#define HEIGHT
Definition ex_gui.c:43
char * key
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:204
#define _str(__PTR)
define true
Definition n_common.h:193
void n_abort(char const *format,...)
abort program with a text
Definition n_common.c:53
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:263
#define _nstr(__PTR)
N_STR or "NULL" string for logging purposes.
Definition n_common.h:199
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:89
#define LOG_DEBUG
debug-level messages
Definition n_log.h:84
#define LOG_ERR
error conditions
Definition n_log.h:76
int set_log_file(char *file)
Set the logging to a file instead of stderr.
Definition n_log.c:168
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL )
Definition n_log.c:121
#define LOG_NOTICE
normal but significant condition
Definition n_log.h:80
#define LOG_INFO
informational
Definition n_log.h:82
size_t numY
number of cells in Y
Definition n_fluids.h:74
double fluid_production_percentage
size of the produced fluid
Definition n_fluids.h:104
bool showSmoke
display fluid as a colored cloud instead of black and white, can be combined with showPressure
Definition n_fluids.h:92
size_t numX
number of cells in X
Definition n_fluids.h:72
double overRelaxation
over relaxation
Definition n_fluids.h:90
bool showPressure
display fluids pressures as color variations, can be combined with showSmoke
Definition n_fluids.h:96
bool showPaint
activate a fonky palette, override smoke and pressure display
Definition n_fluids.h:94
double * u
holder for u arrays
Definition n_fluids.h:109
double dt
time between frames
Definition n_fluids.h:84
double * s
holder for s arrays
Definition n_fluids.h:121
size_t numIters
number of fluid processing iterations for each frame
Definition n_fluids.h:80
double density
density of the fluid (not working ?)
Definition n_fluids.h:82
double * m
holder for m arrays
Definition n_fluids.h:124
double cScale
scale used to deduce cellX and cellY from screen/window width and height
Definition n_fluids.h:106
double gravity
gravity on Y
Definition n_fluids.h:88
int n_fluid_draw(N_FLUID *fluid)
draw a N_FLUID on screen / targert bitmap
Definition n_fluids.c:843
int n_fluid_simulate_threaded(N_FLUID *fluid, THREAD_POOL *thread_pool)
a threaded version of N_FLUID global processing function
Definition n_fluids.c:641
int n_fluid_simulate(N_FLUID *fluid)
non threaded version of N_FLUID global processing function
Definition n_fluids.c:624
int n_fluid_resetObstacles(N_FLUID *fluid)
reset the obstacles set in a N_FLUID
Definition n_fluids.c:740
int n_fluid_setObstacle(N_FLUID *fluid, double x, double y, double vx, double vy, double r)
set an obstacle in the fluid grid
Definition n_fluids.c:713
N_FLUID * new_n_fluid(double density, double gravity, size_t numIters, double dt, double overRelaxation, size_t sx, size_t sy)
return a newly allocated fluid
Definition n_fluids.c:96
structure of a fluid
Definition n_fluids.h:70
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
Definition n_str.h:203
#define nstrprintf(__nstr_var, __format,...)
Macro to quickly allocate and sprintf to N_STR.
Definition n_str.h:117
A box including a string and his lenght.
Definition n_str.h:61
int start_HiTimer(N_TIME *timer)
Initialize or restart from zero any N_TIME HiTimer.
Definition n_time.c:85
time_t get_usec(N_TIME *timer)
Poll any N_TIME HiTimer, returning usec, and moving currentTime to startTime.
Definition n_time.c:107
Timing Structure.
Definition n_time.h:49
THREAD_POOL * new_thread_pool(size_t nbmaxthr, size_t nb_max_waiting)
Create a new pool of nbmaxthr threads.
long int get_nb_cpu_cores()
get number of core of current system
Structure of a thread pool.
Common headers and low-level functions & define.
Fluid management port from "How to write an Eulerian fluid simulator with 200 lines of code",...
List structures and definitions.
static FILE * log_file
static FILE handling if logging to file is enabled
Definition n_log.c:84
Generic log system.
__attribute__((unused))
Definition n_network.c:1286
N_STR and string function declaration.
Timing utilities.