diff --git a/img/fly-dead.png b/img/fly-dead.png
new file mode 100644
index 0000000..526ba3e
Binary files /dev/null and b/img/fly-dead.png differ
diff --git a/img/fly-noto.png b/img/fly-noto.png
new file mode 100644
index 0000000..d14f9c6
Binary files /dev/null and b/img/fly-noto.png differ
diff --git a/libc3/array.c b/libc3/array.c
index 1079a2d..bf15b5b 100644
--- a/libc3/array.c
+++ b/libc3/array.c
@@ -91,7 +91,8 @@ void * array_data (const s_array *a, const uw *address)
assert(a->data);
while (i < a->dimension) {
if (address[i] >= a->dimensions[i].count) {
- warnx("array_data: address overflow: %lu", i);
+ warnx("array_data: address overflow: %lu: [%lu >= %lu]",
+ i, address[i], a->dimensions[i].count);
return NULL;
}
offset += address[i] * a->dimensions[i].item_size;
diff --git a/libc3/window/cairo/cairo_png.c b/libc3/window/cairo/cairo_png.c
index 295f983..a82c914 100644
--- a/libc3/window/cairo/cairo_png.c
+++ b/libc3/window/cairo/cairo_png.c
@@ -10,6 +10,8 @@
* AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
* THIS SOFTWARE.
*/
+#include <assert.h>
+#include <err.h>
#include <unistd.h>
#include <cairo.h>
#include <libc3/c3.h>
@@ -20,10 +22,16 @@ cairo_surface_t * cairo_png_1 (const s8 *path)
s_str found_str;
s_str path_str;
cairo_surface_t *surface = NULL;
+ assert(path);
str_init_1(&path_str, NULL, path);
if (file_search(&path_str, sym_1("r"), &found_str)) {
surface = cairo_image_surface_create_from_png(found_str.ptr.ps8);
+ if (! surface)
+ warnx("cairo_png_1: cairo_image_surface_create_from_png: %s",
+ found_str.ptr.ps8);
str_clean(&found_str);
}
+ else
+ warnx("cairo_png_1: file not found: %s", path);
return surface;
}
diff --git a/libc3/window/cairo/cairo_sprite.c b/libc3/window/cairo/cairo_sprite.c
index 4b200e7..02feaad 100644
--- a/libc3/window/cairo/cairo_sprite.c
+++ b/libc3/window/cairo/cairo_sprite.c
@@ -11,6 +11,7 @@
* THIS SOFTWARE.
*/
#include <assert.h>
+#include <err.h>
#include "cairo_sprite.h"
void cairo_sprite_blit (const s_cairo_sprite *sprite, uw frame,
@@ -51,8 +52,10 @@ s_cairo_sprite * cairo_sprite_init (s_cairo_sprite *sprite,
assert(sprite);
assert(dim_x);
assert(dim_y);
- if (! (sprite->surface = surface))
+ if (! (sprite->surface = surface)) {
+ warnx("cairo_sprite_init: NULL surface");
return NULL;
+ }
sprite->surface_w = cairo_image_surface_get_width(surface);
sprite->surface_h = cairo_image_surface_get_height(surface);
sprite->dim_x = dim_x;
diff --git a/libc3/window/cairo/demo/flies.c b/libc3/window/cairo/demo/flies.c
index 1c8411b..070778a 100644
--- a/libc3/window/cairo/demo/flies.c
+++ b/libc3/window/cairo/demo/flies.c
@@ -17,9 +17,35 @@
#define BOARD_SIZE 25
-static const character g_block = 0x2588;
-static const character g_fly = 0x1FAB0;
-static const character g_space = ' ';
+typedef enum {
+ BOARD_ITEM_SPACE = 0,
+ BOARD_ITEM_BLOCK = 1,
+ BOARD_ITEM_FLY = 2,
+ BOARD_ITEM_DEAD_FLY = 3
+} e_board_item_type;
+
+static const u8 g_board_item_space = BOARD_ITEM_SPACE;
+static const u8 g_board_item_block = BOARD_ITEM_BLOCK;
+static const u8 g_board_item_fly = BOARD_ITEM_FLY;
+static const u8 g_board_item_dead_fly = BOARD_ITEM_DEAD_FLY;
+s_cairo_sprite g_dead_fly_sprite = {0};
+s_cairo_sprite g_fly_sprite = {0};
+static const f64 g_xy_ratio = 0.6;
+
+static void fly_init (s_map *map)
+{
+ uw address[2] = { BOARD_SIZE / 2,
+ 0 };
+ s_array *board;
+ uw *in;
+ f64 *t;
+ board = &map->values[0].data.array;
+ in = &map->values[1].data.uw;
+ t = &map->values[3].data.f64;
+ array_data_set(board, address, &g_board_item_fly);
+ *t = 0.0;
+ (*in)++;
+}
bool flies_load (s_sequence *seq,
s_window_cairo *window)
@@ -30,19 +56,26 @@ bool flies_load (s_sequence *seq,
uw j;
s_map *map;
(void) window;
- tag_map(&seq->tag, 1);
+ tag_map(&seq->tag, 4);
map = &seq->tag.data.map;
tag_init_sym_1( map->keys + 0, "board");
- tag_init_array(map->values + 0, sym_1("Character"),
+ tag_init_array(map->values + 0, sym_1("U8"),
2, (uw[]) {BOARD_SIZE, BOARD_SIZE});
+ tag_init_sym_1( map->keys + 1, "in");
+ tag_init_uw(map->values + 1, 0);
+ tag_init_sym_1( map->keys + 2, "out");
+ tag_init_uw(map->values + 2, 0);
+ tag_init_sym_1( map->keys + 3, "t");
+ tag_init_f64(map->values + 3, 0.0);
board = &map->values[0].data.array;
+ board->data = malloc(board->size);
i = 0;
while (i < BOARD_SIZE) {
address[0] = i;
j = 0;
while (j < BOARD_SIZE) {
address[1] = j;
- array_data_set(board, address, &g_space);
+ array_data_set(board, address, &g_board_item_space);
j++;
}
i++;
@@ -51,90 +84,194 @@ bool flies_load (s_sequence *seq,
while (i < BOARD_SIZE) {
address[0] = i;
address[1] = 0;
- array_data_set(board, address, &g_block);
+ array_data_set(board, address, &g_board_item_block);
address[1] = BOARD_SIZE - 1;
- array_data_set(board, address, &g_block);
+ array_data_set(board, address, &g_board_item_block);
address[0] = 0;
address[1] = i;
- array_data_set(board, address, &g_block);
+ array_data_set(board, address, &g_board_item_block);
address[0] = BOARD_SIZE - 1;
- array_data_set(board, address, &g_block);
+ array_data_set(board, address, &g_board_item_block);
i++;
}
address[0] = BOARD_SIZE / 2;
address[1] = 0;
- array_data_set(board, address, &g_space);
+ array_data_set(board, address, &g_board_item_space);
address[1] = BOARD_SIZE - 1;
- array_data_set(board, address, &g_space);
+ array_data_set(board, address, &g_board_item_space);
address[1] = BOARD_SIZE / 2;
i = 1;
- while (i < BOARD_SIZE * 3 / 4) {
+ while (i <= BOARD_SIZE / 2) {
address[0] = i;
- array_data_set(board, address, &g_block);
+ array_data_set(board, address, &g_board_item_block);
i++;
}
- address[0] = BOARD_SIZE * 3 / 4 - 1;
+ address[0] = BOARD_SIZE / 2;
j = BOARD_SIZE / 4;
- while (j < BOARD_SIZE / 2 - 1) {
+ while (j < BOARD_SIZE / 2) {
address[1] = j;
- array_data_set(board, address, &g_block);
+ array_data_set(board, address, &g_board_item_block);
j++;
}
address[1] = BOARD_SIZE * 3 / 4;
i = BOARD_SIZE / 4;
while (i < BOARD_SIZE - 1) {
address[0] = i;
- array_data_set(board, address, &g_block);
+ array_data_set(board, address, &g_board_item_block);
i++;
}
+ fly_init(map);
return true;
}
bool flies_render (s_sequence *seq, s_window_cairo *window,
cairo_t *cr)
{
+ s8 a[BOARD_SIZE];
uw address[2];
s_array *board;
+ f64 board_w;
+ f64 board_h;
+ f64 board_x;
+ u8 *board_item;
+ f64 board_item_w;
+ f64 board_item_h;
s_buf buf;
- character *c;
+ u8 direction;
+ bool directions[9];
+ uw fly_address[2];
+ uw *fly_in;
+ uw *fly_out;
+ f64 *fly_time;
uw i;
- s8 line[BOARD_SIZE * 4 + 1];
s_map *map;
+ uw r;
cairo_text_extents_t te;
+ f64 x;
+ f64 y;
cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
cairo_rectangle(cr, 0, 0, window->w, window->h);
cairo_fill(cr);
- cairo_set_font_size(cr, window->h / BOARD_SIZE);
- cairo_select_font_face(cr, "Courier New",
- CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
- i = 0;
- while (i < BOARD_SIZE) {
- line[i] = ' ';
- i++;
- }
- line[i] = 0;
- cairo_text_extents(cr, line, &te);
/* io_inspect(&seq->tag); */
if (seq->tag.type == TAG_MAP) {
map = &seq->tag.data.map;
- if (map->count > 0 && map->values[0].type == TAG_ARRAY) {
- board = &map->values[0].data.array;
+ if (map->count == 4 &&
+ map->values[0].type == TAG_ARRAY &&
+ map->values[3].type == TAG_F64) {
+ board = &map->values[0].data.array;
+ fly_in = &map->values[1].data.uw;
+ fly_out = &map->values[2].data.uw;
+ fly_time = &map->values[3].data.f64;
+ board_item_h = (f64) (window->h - 60) / BOARD_SIZE;
+ board_item_w = board_item_h * g_xy_ratio;
+ board_w = board_item_w * BOARD_SIZE;
+ board_h = board_item_h * BOARD_SIZE;
+ board_x = (window->w - board_w) / 2.0;
+ cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+ cairo_set_font_size(cr, board_item_h);
+ cairo_select_font_face(cr, "Courier New",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+ buf_init(&buf, false, sizeof(a), a);
+ buf_write_1(&buf, "In ");
+ buf_inspect_uw(&buf, fly_in);
+ buf_write_u8(&buf, 0);
+ cairo_text_extents(cr, buf.ptr.ps8, &te);
+ y = board_h + board_item_h + te.height + te.y_bearing;
+ x = board_x;
+ cairo_move_to(cr, x, y);
+ cairo_show_text(cr, buf.ptr.ps8);
address[1] = 0;
while (address[1] < BOARD_SIZE) {
+ y = board_item_h * address[1];
address[0] = 0;
- buf_init(&buf, false, sizeof(line), line);
while (address[0] < BOARD_SIZE) {
- c = (character *) array_data(board, address);
- buf_write_character_utf8(&buf, *c);
+ x = board_x + board_item_w * address[0];
+ cairo_translate(cr, x, y);
+ board_item = (u8 *) array_data(board, address);
+ assert(board_item);
+ switch (*board_item) {
+ case BOARD_ITEM_SPACE:
+ cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+ cairo_rectangle(cr, 0, 0, board_item_w + 0.5,
+ board_item_h + 0.5);
+ cairo_fill(cr);
+ break;
+ case BOARD_ITEM_BLOCK:
+ cairo_set_source_rgb(cr, 0.0, 0.0, 1.0);
+ cairo_rectangle(cr, 0, 0, board_item_w + 0.5,
+ board_item_h + 0.5);
+ cairo_fill(cr);
+ break;
+ case BOARD_ITEM_FLY:
+ cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
+ cairo_rectangle(cr, 0, 0, board_item_w + 0.5,
+ board_item_h + 0.5);
+ cairo_fill(cr);
+ if (address[0] == BOARD_SIZE / 2 &&
+ address[1] == BOARD_SIZE - 1) {
+ (*fly_out)++;
+ fly_init(map);
+ break;
+ }
+ i = 0;
+ while (i < 9) {
+ directions[i] = true;
+ i++;
+ }
+ fly_address[0] = address[0];
+ fly_address[1] = address[1];
+ while (directions[0] || directions[1] || directions[2] ||
+ directions[3] || directions[4] || directions[5] ||
+ directions[6] || directions[7] || directions[8]) {
+ fly_address[0] = address[0];
+ fly_address[1] = address[1];
+ r = random() % 12;
+ direction = r;
+ if (direction >= 9)
+ direction = (direction - 6) % 3 + 6;
+ switch (direction) {
+ case 0: fly_address[0]--; fly_address[1]--; break;
+ case 1: fly_address[1]--; break;
+ case 2: fly_address[0]++; fly_address[1]--; break;
+ case 3: fly_address[0]--; ; break;
+ case 4: ; break;
+ case 5: fly_address[0]++; ; break;
+ case 6: fly_address[0]--; fly_address[1]++; break;
+ case 7: fly_address[1]++; break;
+ case 8: fly_address[0]++; fly_address[1]++; break;
+ }
+ if (fly_address[0] < BOARD_SIZE &&
+ fly_address[1] < BOARD_SIZE &&
+ (board_item = (u8 *) array_data(board,
+ fly_address)) &&
+ *board_item == g_board_item_space) {
+ array_data_set(board, address, &g_board_item_space);
+ array_data_set(board, fly_address, &g_board_item_fly);
+ break;
+ }
+ directions[direction] = false;
+ fly_address[0] = address[0];
+ fly_address[1] = address[1];
+ }
+ *fly_time += seq->dt;
+ if (*fly_time > 1) {
+ array_data_set(board, fly_address, &g_board_item_dead_fly);
+ fly_init(map);
+ }
+ break;
+ case BOARD_ITEM_DEAD_FLY:
+ cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
+ cairo_rectangle(cr, 0, 0, board_item_w + 0.5,
+ board_item_h + 0.5);
+ cairo_fill(cr);
+ break;
+ }
+ cairo_identity_matrix(cr);
address[0]++;
}
- buf_write_u8(&buf, 0);
-
address[1]++;
}
- address[0] = BOARD_SIZE / 2;
- address[1] = 0;
- array_data_set(board, address, &g_fly);
}
}
return true;
diff --git a/libc3/window/cairo/demo/flies.h b/libc3/window/cairo/demo/flies.h
index abff47b..9eff323 100644
--- a/libc3/window/cairo/demo/flies.h
+++ b/libc3/window/cairo/demo/flies.h
@@ -15,6 +15,9 @@
#include "../types.h"
+extern s_cairo_sprite g_dead_fly_sprite;
+extern s_cairo_sprite g_fly_sprite;
+
bool flies_load (s_sequence *seq, s_window_cairo *window);
bool flies_render (s_sequence *seq, s_window_cairo *window,
cairo_t *cr);
diff --git a/libc3/window/cairo/demo/window_cairo_demo.c b/libc3/window/cairo/demo/window_cairo_demo.c
index 999670b..2f7acfc 100644
--- a/libc3/window/cairo/demo/window_cairo_demo.c
+++ b/libc3/window/cairo/demo/window_cairo_demo.c
@@ -24,6 +24,7 @@
#include "bg_rect.h"
#include "lightspeed.h"
#include "toasters.h"
+#include "flies.h"
bool window_cairo_demo_button (s_window_cairo *window, u8 button,
sw x, sw y)
@@ -90,6 +91,17 @@ bool window_cairo_demo_load (s_window_cairo *window)
window_cairo_sequence_init(window->sequence + 2, 60.0,
"03. Toasters",
toasters_load, toasters_render);
+ if (! cairo_sprite_init(&g_fly_sprite,
+ cairo_png_1("img/fly-noto.png"),
+ 1, 1, 1))
+ return false;
+ if (! cairo_sprite_init(&g_dead_fly_sprite,
+ cairo_png_1("img/fly-dead.png"),
+ 1, 1, 1))
+ return false;
+ window_cairo_sequence_init(window->sequence + 3, 60.0,
+ "04. Flies",
+ flies_load, flies_render);
window_set_sequence_pos((s_window *) window, 0);
return true;
}
diff --git a/libc3/window/cairo/demo/window_cairo_demo.h b/libc3/window/cairo/demo/window_cairo_demo.h
index 81ef80b..16930b7 100644
--- a/libc3/window/cairo/demo/window_cairo_demo.h
+++ b/libc3/window/cairo/demo/window_cairo_demo.h
@@ -15,7 +15,7 @@
#include "../types.h"
-#define WINDOW_CAIRO_DEMO_SEQUENCE_COUNT 3
+#define WINDOW_CAIRO_DEMO_SEQUENCE_COUNT 4
bool window_cairo_demo_button (s_window_cairo *window, u8 button,
sw x, sw y);
diff --git a/libc3/window/cairo/quartz/demo/Makefile b/libc3/window/cairo/quartz/demo/Makefile
index a64098e..b46f877 100644
--- a/libc3/window/cairo/quartz/demo/Makefile
+++ b/libc3/window/cairo/quartz/demo/Makefile
@@ -21,6 +21,8 @@ DISTCLEANFILES = ${CLEANFILES} config.mk
IMG_SOURCES = \
../../../../../img/flaps.png \
+ ../../../../../img/fly-dead.png \
+ ../../../../../img/fly-noto.png \
../../../../../img/toast.png \
build: