From 9949c1c89e54e71bc3de9fc22bb2163791876cce Mon Sep 17 00:00:00 2001 From: Michael Hayes Date: Tue, 1 Oct 2013 15:10:31 +1300 Subject: [PATCH 1/4] Split out things module --- apps/gobble6/Makefile | 9 +- apps/gobble6/Makefile.test | 11 +- apps/gobble6/gobble6.c | 246 ++++++------------------------------- apps/gobble6/things.c | 186 ++++++++++++++++++++++++++++ apps/gobble6/things.h | 18 +++ 5 files changed, 256 insertions(+), 214 deletions(-) create mode 100644 apps/gobble6/things.c create mode 100644 apps/gobble6/things.h diff --git a/apps/gobble6/Makefile b/apps/gobble6/Makefile index 59b3866..da06c66 100644 --- a/apps/gobble6/Makefile +++ b/apps/gobble6/Makefile @@ -5,7 +5,7 @@ # Definitions. CC = avr-gcc -CFLAGS = -mmcu=atmega32u2 -Os -Wall -Wstrict-prototypes -Wextra -g -I../../drivers/avr -I../../drivers -I../../utils +CFLAGS = -mmcu=atmega32u2 -Os -Wall -Wstrict-prototypes -Wextra -g -I. -I../../drivers/avr -I../../fonts -I../../drivers -I../../utils OBJCOPY = avr-objcopy SIZE = avr-size DEL = rm @@ -16,7 +16,10 @@ all: gobble6.out # Compile: create object files from C source files. -gobble6.o: gobble6.c ../../drivers/avr/system.h ../../drivers/avr/timer.h ../../drivers/display.h ../../drivers/led.h ../../drivers/navswitch.h ../../utils/font.h ../../utils/pacer.h ../../utils/tinygl.h +gobble6.o: gobble6.c ../../drivers/avr/system.h ../../drivers/avr/timer.h ../../drivers/display.h ../../drivers/led.h ../../drivers/navswitch.h ../../fonts/font3x5_1.h ../../utils/font.h ../../utils/pacer.h ../../utils/tinygl.h things.h + $(CC) -c $(CFLAGS) $< -o $@ + +things.o: things.c ../../drivers/avr/system.h ../../drivers/display.h ../../utils/font.h ../../utils/tinygl.h things.h $(CC) -c $(CFLAGS) $< -o $@ pio.o: ../../drivers/avr/pio.c ../../drivers/avr/pio.h ../../drivers/avr/system.h @@ -53,7 +56,7 @@ tinygl.o: ../../utils/tinygl.c ../../drivers/avr/system.h ../../drivers/display. # Link: create output file (executable) from object files. -gobble6.out: gobble6.o pio.o system.o timer.o display.o led.o ledmat.o navswitch.o font.o pacer.o tinygl.o +gobble6.out: gobble6.o things.o pio.o system.o timer.o display.o led.o ledmat.o navswitch.o font.o pacer.o tinygl.o $(CC) $(CFLAGS) $^ -o $@ -lm $(SIZE) $@ diff --git a/apps/gobble6/Makefile.test b/apps/gobble6/Makefile.test index 52087ef..ef70368 100644 --- a/apps/gobble6/Makefile.test +++ b/apps/gobble6/Makefile.test @@ -4,7 +4,7 @@ # Descr: Makefile for gobble6 CC = gcc -CFLAGS = -Wall -Wstrict-prototypes -Wextra -g -I../../drivers/test -I../../drivers -I../../utils +CFLAGS = -Wall -Wstrict-prototypes -Wextra -g -I. -I../../drivers/test -I../../drivers -I../../fonts -I../../utils DEL = rm @@ -14,7 +14,10 @@ all: gobble6 # Compile: create object files from C source files. -gobble6-test.o: gobble6.c ../../drivers/display.h ../../drivers/led.h ../../drivers/navswitch.h ../../drivers/test/system.h ../../drivers/test/timer.h ../../utils/font.h ../../utils/pacer.h ../../utils/tinygl.h +gobble6-test.o: gobble6.c ../../drivers/display.h ../../drivers/led.h ../../drivers/navswitch.h ../../drivers/test/system.h ../../drivers/test/timer.h ../../fonts/font3x5_1.h ../../utils/font.h ../../utils/pacer.h ../../utils/tinygl.h things.h + $(CC) -c $(CFLAGS) $< -o $@ + +things-test.o: things.c ../../drivers/display.h ../../drivers/test/system.h ../../utils/font.h ../../utils/tinygl.h things.h $(CC) -c $(CFLAGS) $< -o $@ display-test.o: ../../drivers/display.c ../../drivers/display.h ../../drivers/ledmat.h ../../drivers/test/system.h @@ -54,14 +57,14 @@ tinygl-test.o: ../../utils/tinygl.c ../../drivers/display.h ../../drivers/test/s # Link: create executable file from object files. -gobble6: gobble6-test.o display-test.o led-test.o ledmat-test.o navswitch-test.o mgetkey-test.o pio-test.o system-test.o timer-test.o font-test.o pacer-test.o tinygl-test.o +gobble6: gobble6-test.o things-test.o display-test.o led-test.o ledmat-test.o navswitch-test.o mgetkey-test.o pio-test.o system-test.o timer-test.o font-test.o pacer-test.o tinygl-test.o $(CC) $(CFLAGS) $^ -o $@ -lrt # Clean: delete derived files. .PHONY: clean clean: - -$(DEL) gobble6 gobble6-test.o display-test.o led-test.o ledmat-test.o navswitch-test.o mgetkey-test.o pio-test.o system-test.o timer-test.o font-test.o pacer-test.o tinygl-test.o + -$(DEL) gobble6 gobble6-test.o things-test.o display-test.o led-test.o ledmat-test.o navswitch-test.o mgetkey-test.o pio-test.o system-test.o timer-test.o font-test.o pacer-test.o tinygl-test.o diff --git a/apps/gobble6/gobble6.c b/apps/gobble6/gobble6.c index 93360cd..74d7087 100644 --- a/apps/gobble6/gobble6.c +++ b/apps/gobble6/gobble6.c @@ -4,8 +4,8 @@ @brief */ -#include #include +#include #include "system.h" #include "pacer.h" #include "navswitch.h" @@ -13,9 +13,8 @@ #include "timer.h" #include "tinygl.h" #include "../fonts/font3x5_1.h" +#include "things.h" -/* Number of initial objects. */ -#define NUM_THINGS 6 #define LOOP_RATE 200 @@ -23,183 +22,15 @@ #define NAVSWITCH_RATE 50 -#define SAFE_DISTANCE 3 - -#define ANXIETY_LEVEL 2 - -#define PANIC_LEVEL 50 - -typedef struct thing_struct -{ - tinygl_point_t pos; - uint8_t anxiety; - bool alive; -} thing_t; - - -static int8_t things_killed_p (thing_t *things, uint8_t num) -{ - uint8_t i; - - for (i = 1; i < num; i++) - { - if (things[i].alive) - return 0; - } - return 1; -} - - -static int8_t thing_find (thing_t *things, uint8_t num, tinygl_point_t pos) -{ - uint8_t i; - - for (i = 0; i < num; i++) - { - if (things[i].pos.x == pos.x - && things[i].pos.y == pos.y - && things[i].alive) - return i; - } - return -1; -} - - -static uint8_t thing_distance_squared (thing_t *things, uint8_t this) -{ - int8_t dx; - int8_t dy; - - dx = things[this].pos.x - things[0].pos.x; - dy = things[this].pos.y - things[0].pos.y; - - return dx * dx + dy * dy; -} - - -static uint8_t bounds_p (tinygl_point_t pos) -{ - return pos.x >= 0 && pos.x < TINYGL_WIDTH - && pos.y >= 0 && pos.y < TINYGL_HEIGHT; -} - - -static void monster_move (thing_t *things, uint8_t num, int8_t dx, int8_t dy) -{ - int8_t other; - tinygl_point_t newpos; - - newpos = tinygl_point (things[0].pos.x + dx, things[0].pos.y + dy); - if (!bounds_p (newpos)) - return; - - other = thing_find (things, num, newpos); - if (other != -1) - things[other].alive = 0; - - tinygl_draw_point (things[0].pos, 0); - things[0].pos = newpos; - tinygl_draw_point (newpos, 1); -} - - -static void thing_move (thing_t *things, uint8_t num, uint8_t this) -{ - uint8_t i; - uint8_t distsq; - uint8_t panic; - tinygl_point_t pos; - - tinygl_draw_point (things[this].pos, 0); - - distsq = thing_distance_squared (things, this); - pos = things[this].pos; - - if (thing_distance_squared (things, this) <= SAFE_DISTANCE * SAFE_DISTANCE) - things[this].anxiety++; - else - things[this].anxiety = 0; - - panic = things[this].anxiety > ANXIETY_LEVEL - && (rand () % 100 > (100 - PANIC_LEVEL)); - - for (i = 0; i < 12; i++) - { - int8_t dx; - int8_t dy; - tinygl_point_t newpos; - - dx = (rand () % 3) - 1; - dy = (rand () % 3) - 1; - - newpos = tinygl_point (pos.x + dx, pos.y + dy); - - /* Check for a valid position. */ - if ((dx || dy) - && (! bounds_p (newpos) || thing_find (things, num, newpos) != -1)) - continue; - - /* Try new position. */ - things[this].pos = newpos; - - if (panic || thing_distance_squared (things, this) > distsq) - break; - } - - /* Stay put if cannot find better position. */ - if (i == 12) - things[this].pos = pos; - - tinygl_draw_point (things[this].pos, 1); -} - - -static void things_move (thing_t *things, uint8_t num) -{ - uint8_t i; - - for (i = 1; i < num; i++) - if (things[i].alive) - thing_move (things, num, i); -} - - -static void things_create (thing_t *things, uint8_t num) -{ - uint8_t i; - - things[0].pos.x = 0; - things[0].pos.y = 0; - things[0].alive = 1; - tinygl_draw_point (things[0].pos, 1); - - for (i = 1; i < num; i++) - { - uint8_t x; - uint8_t y; - - do - { - x = rand () % TINYGL_WIDTH; - y = rand () % TINYGL_HEIGHT; - } while (thing_find (things, i, tinygl_point (x, y)) != -1); - - things[i].pos.x = x; - things[i].pos.y = y; - things[i].alive = 1; - - tinygl_draw_point (things[i].pos, 1); - } -} - int main (void) { uint16_t tick = 0; uint16_t navswitch_tick = 0; - uint8_t running = 0; + bool running = 0; + bool game_over = 1; int duration = 0; - thing_t things[NUM_THINGS]; + system_init (); navswitch_init (); @@ -234,43 +65,41 @@ int main (void) navswitch_update (); - if (running) - { - duration++; - if (navswitch_push_event_p (NAVSWITCH_NORTH)) - monster_move (things, NUM_THINGS, 0, -1); - if (navswitch_push_event_p (NAVSWITCH_SOUTH)) - monster_move (things, NUM_THINGS, 0, 1); - if (navswitch_push_event_p (NAVSWITCH_EAST)) - monster_move (things, NUM_THINGS, 1, 0); - if (navswitch_push_event_p (NAVSWITCH_WEST)) - monster_move (things, NUM_THINGS, -1, 0); - if (navswitch_push_event_p (NAVSWITCH_PUSH)) - { - running = 0; - led_set (LED1, running); - } - if (things_killed_p (things, NUM_THINGS)) - { - char buffer[6]; - - running = 0; - led_set (LED1, running); - sprintf (buffer, "%d", duration); - tinygl_text (buffer); - } - } - else + if (navswitch_push_event_p (NAVSWITCH_NORTH)) + monster_move (0, -1); + if (navswitch_push_event_p (NAVSWITCH_SOUTH)) + monster_move (0, 1); + if (navswitch_push_event_p (NAVSWITCH_EAST)) + monster_move (1, 0); + if (navswitch_push_event_p (NAVSWITCH_WEST)) + monster_move (-1, 0); + + /* Pause/resume things running around. */ + if (navswitch_push_event_p (NAVSWITCH_PUSH)) { - if (navswitch_push_event_p (NAVSWITCH_PUSH)) + if (! running && game_over) { srand (timer_get ()); tinygl_clear (); - things_create (things, NUM_THINGS); - running = 1; + things_create (); + duration = 0; - led_set (LED1, running); + game_over = 0; } + + running = !running; + led_set (LED1, running); + } + + if (running && things_killed_p ()) + { + char buffer[6]; + + running = 0; + game_over = 1; + led_set (LED1, 0); + sprintf (buffer, "%d", duration); + tinygl_text (buffer); } } @@ -278,9 +107,12 @@ int main (void) if (tick >= LOOP_RATE / MOVE_RATE) { tick = 0; - + if (running) - things_move (things, NUM_THINGS); + { + duration++; + things_move (); + } } } return 0; diff --git a/apps/gobble6/things.c b/apps/gobble6/things.c new file mode 100644 index 0000000..44b0798 --- /dev/null +++ b/apps/gobble6/things.c @@ -0,0 +1,186 @@ +#include +#include "things.h" +#include "tinygl.h" + + +/* Number of initial objects. */ +#define THINGS_NUM 6 + +#define SAFE_DISTANCE 3 + +#define ANXIETY_LEVEL 2 + +#define PANIC_LEVEL 50 + +#define MOVE_ATTEMPTS 12 + + +typedef struct thing_struct +{ + tinygl_point_t pos; + uint8_t anxiety; + bool alive; +} thing_t; + + +static thing_t things[THINGS_NUM]; + + +bool things_killed_p (void) +{ + uint8_t i; + + for (i = 1; i < THINGS_NUM; i++) + { + if (things[i].alive) + return 0; + } + return 1; +} + + +static int8_t thing_find (tinygl_point_t pos) +{ + uint8_t i; + + for (i = 0; i < THINGS_NUM; i++) + { + if (things[i].pos.x == pos.x + && things[i].pos.y == pos.y + && things[i].alive) + return i; + } + return -1; +} + + +static uint8_t thing_distance_squared (thing_t *things, uint8_t this) +{ + int8_t dx; + int8_t dy; + + dx = things[this].pos.x - things[0].pos.x; + dy = things[this].pos.y - things[0].pos.y; + + return dx * dx + dy * dy; +} + + +static bool thing_inbounds_p (tinygl_point_t pos) +{ + return pos.x >= 0 && pos.x < TINYGL_WIDTH + && pos.y >= 0 && pos.y < TINYGL_HEIGHT; +} + + +static bool thing_position_valid_p (tinygl_point_t pos) +{ + return thing_inbounds_p (pos) && thing_find (pos) == -1; +} + + +void monster_move (int8_t dx, int8_t dy) +{ + int8_t other; + tinygl_point_t newpos; + + newpos = tinygl_point (things[0].pos.x + dx, things[0].pos.y + dy); + if (!thing_inbounds_p (newpos)) + return; + + other = thing_find (newpos); + if (other != -1) + things[other].alive = 0; + + tinygl_draw_point (things[0].pos, 0); + things[0].pos = newpos; + tinygl_draw_point (newpos, 1); +} + + +static void thing_move (uint8_t this) +{ + uint8_t i; + uint8_t distsq; + uint8_t panic; + tinygl_point_t pos; + + tinygl_draw_point (things[this].pos, 0); + + distsq = thing_distance_squared (things, this); + pos = things[this].pos; + + if (thing_distance_squared (things, this) <= SAFE_DISTANCE * SAFE_DISTANCE) + things[this].anxiety++; + else + things[this].anxiety = 0; + + panic = things[this].anxiety > ANXIETY_LEVEL + && (rand () % 100 > (100 - PANIC_LEVEL)); + + for (i = 0; i < MOVE_ATTEMPTS; i++) + { + int8_t dx; + int8_t dy; + tinygl_point_t newpos; + + dx = (rand () % 3) - 1; + dy = (rand () % 3) - 1; + + newpos = tinygl_point (pos.x + dx, pos.y + dy); + + if ((dx || dy) && ! thing_position_valid_p (newpos)) + continue; + + things[this].pos = newpos; + + if (panic || thing_distance_squared (things, this) > distsq) + break; + } + + /* Stay put if cannot find better position. */ + if (i == MOVE_ATTEMPTS) + things[this].pos = pos; + + tinygl_draw_point (things[this].pos, 1); +} + + +void things_move (void) +{ + uint8_t i; + + for (i = 1; i < THINGS_NUM; i++) + if (things[i].alive) + thing_move (i); +} + + +void things_create (void) +{ + uint8_t i; + + things[0].pos.x = 0; + things[0].pos.y = 0; + things[0].alive = 1; + tinygl_draw_point (things[0].pos, 1); + + for (i = 1; i < THINGS_NUM; i++) + { + uint8_t x; + uint8_t y; + + do + { + x = rand () % TINYGL_WIDTH; + y = rand () % TINYGL_HEIGHT; + } while (thing_find (tinygl_point (x, y)) != -1); + + things[i].pos.x = x; + things[i].pos.y = y; + things[i].alive = 1; + + tinygl_draw_point (things[i].pos, 1); + } +} + diff --git a/apps/gobble6/things.h b/apps/gobble6/things.h new file mode 100644 index 0000000..d644780 --- /dev/null +++ b/apps/gobble6/things.h @@ -0,0 +1,18 @@ +#ifndef THINGS_H +#define THINGS_H + +#include "system.h" + +void things_create (void); + +void things_twinkle (void); + +void things_display (uint8_t tick); + +bool things_killed_p (void); + +void monster_move (int8_t dx, int8_t dy); + +void things_move (void); + +#endif From 1332ef8ad56b00ac314bc40961f23c9bc905dcf7 Mon Sep 17 00:00:00 2001 From: Michael Hayes Date: Tue, 1 Oct 2013 15:16:39 +1300 Subject: [PATCH 2/4] Make monster flash --- apps/gobble6/gobble6.c | 6 ++++++ apps/gobble6/things.c | 7 +++++++ apps/gobble6/things.h | 10 ++++------ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/apps/gobble6/gobble6.c b/apps/gobble6/gobble6.c index 74d7087..e298b90 100644 --- a/apps/gobble6/gobble6.c +++ b/apps/gobble6/gobble6.c @@ -61,6 +61,12 @@ int main (void) navswitch_tick++; if (navswitch_tick >= LOOP_RATE / NAVSWITCH_RATE) { + static int count = 0; + + count++; + if (running && count % 4 == 0) + monster_toggle (); + navswitch_tick = 0; navswitch_update (); diff --git a/apps/gobble6/things.c b/apps/gobble6/things.c index 44b0798..68edfed 100644 --- a/apps/gobble6/things.c +++ b/apps/gobble6/things.c @@ -98,6 +98,13 @@ void monster_move (int8_t dx, int8_t dy) } +void monster_toggle (void) +{ + tinygl_pixel_set (things[0].pos, ! tinygl_pixel_get (things[0].pos)); +} + + + static void thing_move (uint8_t this) { uint8_t i; diff --git a/apps/gobble6/things.h b/apps/gobble6/things.h index d644780..8b83a46 100644 --- a/apps/gobble6/things.h +++ b/apps/gobble6/things.h @@ -3,16 +3,14 @@ #include "system.h" -void things_create (void); - -void things_twinkle (void); +bool things_killed_p (void); -void things_display (uint8_t tick); +void things_create (void); -bool things_killed_p (void); +void things_move (void); void monster_move (int8_t dx, int8_t dy); -void things_move (void); +void monster_toggle (void); #endif From 86266ce624a38012552afbd5601f7edab60a30d3 Mon Sep 17 00:00:00 2001 From: Michael Hayes Date: Tue, 1 Oct 2013 15:55:23 +1300 Subject: [PATCH 3/4] Add comment about unsigned arithmetic --- drivers/avr/timer.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/avr/timer.c b/drivers/avr/timer.c index e8bf725..b5c0a4b 100644 --- a/drivers/avr/timer.c +++ b/drivers/avr/timer.c @@ -57,8 +57,15 @@ timer_tick_t timer_wait_until (timer_tick_t when) now = timer_get (); + /* Note, both when and now are unsigned so they wrap around to + zero when they overflow. The difference is also unsigned + so when now < when then the result wraps around to a large + positive value and fails the following test. */ diff = now - when; + /* There is a possibility that we are called when when < now. + So we allow a possible overrun defined by + TIMER_OVERRUN_MAX. */ if (diff < TIMER_OVERRUN_MAX) return now; } From 1381bf5ee3bcc9ec8328825c18c78bcfb8bb3eb0 Mon Sep 17 00:00:00 2001 From: Michael Hayes Date: Tue, 1 Oct 2013 16:01:19 +1300 Subject: [PATCH 4/4] Make monster flash --- apps/gobble6/gobble6.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/apps/gobble6/gobble6.c b/apps/gobble6/gobble6.c index e298b90..1d8266f 100644 --- a/apps/gobble6/gobble6.c +++ b/apps/gobble6/gobble6.c @@ -22,11 +22,14 @@ #define NAVSWITCH_RATE 50 +#define MONSTER_FLASH_RATE 5 + int main (void) { uint16_t tick = 0; uint16_t navswitch_tick = 0; + uint16_t monster_flash_tick = 0; bool running = 0; bool game_over = 1; int duration = 0; @@ -58,15 +61,10 @@ int main (void) tinygl_update (); } + /* Poll the navswitch and update monster position. */ navswitch_tick++; if (navswitch_tick >= LOOP_RATE / NAVSWITCH_RATE) { - static int count = 0; - - count++; - if (running && count % 4 == 0) - monster_toggle (); - navswitch_tick = 0; navswitch_update (); @@ -109,6 +107,7 @@ int main (void) } } + /* Move the things. */ tick++; if (tick >= LOOP_RATE / MOVE_RATE) { @@ -120,6 +119,15 @@ int main (void) things_move (); } } + + /* Flash the monster. */ + monster_flash_tick++; + if (monster_flash_tick >= LOOP_RATE / MONSTER_FLASH_RATE / 2) + { + monster_flash_tick = 0; + if (running) + monster_toggle (); + } } return 0; }