Skip to content

Commit

Permalink
add game of life
Browse files Browse the repository at this point in the history
  • Loading branch information
v1nc committed Jul 27, 2022
1 parent 69ad105 commit 0b0a44b
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 0 deletions.
1 change: 1 addition & 0 deletions ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ If you need another layout, create an issue or look [here](https:/v1
* [Flappy Bird](https:/RogueMaster/flipperzero-firmware-wPlugins/tree/unleashed/applications/flappy_bird)
* [Video Poker](https:/RogueMaster/flipperzero-firmware-wPlugins/tree/unleashed/applications/VideoPoker)
* [2048](https:/RogueMaster/flipperzero-firmware-wPlugins/tree/unleashed/applications/game2048)
* [Game of Life](https:/RogueMaster/flipperzero-firmware-wPlugins/tree/unleashed/applications/game_of_life)

### This software is for experimental purposes only and is not meant for any illegal activity/purposes. <br> We do not condone illegal activity and strongly encourage keeping transmissions to legal/valid uses allowed by law. <br> Also this software is made without any support from Flipper Devices and in no way related to official devs.
### Please use for experimental purposes only!
Expand Down
10 changes: 10 additions & 0 deletions applications/game_of_life/application.fam
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
App(
appid="GAME_GameOfLife",
name="Game of Life",
apptype=FlipperAppType.GAME,
entry_point="game_of_life_app",
cdefines=["APP_GAMEOFLIFE_GAME"],
requires=["gui"],
stack_size=1 * 1024,
order=110,
)
159 changes: 159 additions & 0 deletions applications/game_of_life/game_of_life.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#include <furi.h>
#include <gui/gui.h>

#include <input/input.h>
#include <stdlib.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define TOTAL_PIXELS SCREEN_WIDTH* SCREEN_HEIGHT

typedef enum {
EventTypeTick,
EventTypeKey,
} EventType;

typedef struct {
EventType type;
InputEvent input;
} AppEvent;

typedef struct {
bool revive;
int evo;
} State;

unsigned char new[TOTAL_PIXELS] = {};
unsigned char old[TOTAL_PIXELS] = {};
unsigned char* fields[] = {new, old};

int current = 0;
int next = 1;

unsigned char get_cell(int x, int y) {
if(x <= 0 || x >= SCREEN_WIDTH) return 0;
if(y <= 0 || y >= SCREEN_HEIGHT) return 0;

int pix = (y * SCREEN_WIDTH) + x;
return fields[current][pix];
}

int count_neightbors(int x, int y) {
return get_cell(x + 1, y - 1) + get_cell(x - 1, y - 1) + get_cell(x - 1, y + 1) +
get_cell(x + 1, y + 1) + get_cell(x + 1, y) + get_cell(x - 1, y) + get_cell(x, y - 1) +
get_cell(x, y + 1);
}

static void update_field(State* state) {
if(state->revive) {
for(int i = 0; i < TOTAL_PIXELS; ++i) {
if((random() % 100) == 1) {
fields[current][i] = 1;
}
state->revive = false;
}
}

for(int i = 0; i < TOTAL_PIXELS; ++i) {
int x = i % SCREEN_WIDTH;
int y = (int)(i / SCREEN_WIDTH);

int v = get_cell(x, y);
int n = count_neightbors(x, y);

if(v && n == 3) {
++state->evo;
} else if(v && (n < 2 || n > 3)) {
++state->evo;
v = 0;
} else if(!v && n == 3) {
++state->evo;
v = 1;
}

fields[next][i] = v;
}

next ^= current;
current ^= next;
next ^= current;

if(state->evo < TOTAL_PIXELS) {
state->revive = true;
state->evo = 0;
}
}

static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
furi_assert(event_queue);

AppEvent event = {.type = EventTypeKey, .input = *input_event};
furi_message_queue_put(event_queue, &event, 0);
}

static void render_callback(Canvas* canvas, void* ctx) {
State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25);
canvas_clear(canvas);

for(int i = 0; i < TOTAL_PIXELS; ++i) {
int x = i % SCREEN_WIDTH;
int y = (int)(i / SCREEN_WIDTH);
if(fields[current][i] == 1) canvas_draw_dot(canvas, x, y);
}
release_mutex((ValueMutex*)ctx, state);
}

int32_t game_of_life_app(void* p) {
UNUSED(p);
srand(DWT->CYCCNT);

FuriMessageQueue* event_queue = furi_message_queue_alloc(1, sizeof(AppEvent));
furi_check(event_queue);

State* _state = malloc(sizeof(State));

ValueMutex state_mutex;
if(!init_mutex(&state_mutex, _state, sizeof(State))) {
printf("cannot create mutex\r\n");
free(_state);
return 255;
}

ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, render_callback, &state_mutex);
view_port_input_callback_set(view_port, input_callback, event_queue);

Gui* gui = furi_record_open("gui");
gui_add_view_port(gui, view_port, GuiLayerFullscreen);

AppEvent event;
for(bool processing = true; processing;) {
State* state = (State*)acquire_mutex_block(&state_mutex);
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 25);

if(event_status == FuriStatusOk && event.type == EventTypeKey &&
event.input.type == InputTypePress) {
if(event.input.key == InputKeyBack) {
// furiac_exit(NULL);
processing = false;
release_mutex(&state_mutex, state);
break;
}
}

update_field(state);

view_port_update(view_port);
release_mutex(&state_mutex, state);
}

view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port);
furi_record_close("gui");
view_port_free(view_port);
furi_message_queue_free(event_queue);
delete_mutex(&state_mutex);
free(_state);

return 0;
}
1 change: 1 addition & 0 deletions applications/meta/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ App(
"GAME_FlappyBird",
"GAME_VideoPoker",
"GAME_2048",
"GAME_GameOfLife",
],
)

Expand Down

0 comments on commit 0b0a44b

Please sign in to comment.