Explorar el Código

Add zombiez from https://github.com/xMasterX/all-the-plugins

git-subtree-dir: zombiez
git-subtree-mainline: b0a940f8fd666abab7fe15d13d71fa2e08189932
git-subtree-split: 961de08d3b3b4c9c95bba83d3c5cdcff0af6afed
Willy-JL hace 2 años
padre
commit
591f2d013e
Se han modificado 7 ficheros con 479 adiciones y 0 borrados
  1. 1 0
      zombiez/.gitsubtree
  2. 14 0
      zombiez/application.fam
  3. BIN
      zombiez/img/1.png
  4. BIN
      zombiez/img/2.png
  5. BIN
      zombiez/zombie_10px.png
  6. 402 0
      zombiez/zombiez.c
  7. 62 0
      zombiez/zombiez.h

+ 1 - 0
zombiez/.gitsubtree

@@ -0,0 +1 @@
+https://github.com/xMasterX/all-the-plugins dev base_pack/zombiez

+ 14 - 0
zombiez/application.fam

@@ -0,0 +1,14 @@
+App(
+    appid="zombiez",
+    name="Zombiez",
+    apptype=FlipperAppType.EXTERNAL,
+    entry_point="zombiez_game_app",
+    requires=["gui"],
+    stack_size=2 * 1024,
+    order=280,
+    fap_icon="zombie_10px.png",
+    fap_category="Games",
+    fap_author="@DevMilanIan & @xMasterX, (original By @Dooskington)",
+    fap_version="1.1",
+    fap_description="Defend your walls from the zombies",
+)

BIN
zombiez/img/1.png


BIN
zombiez/img/2.png


BIN
zombiez/zombie_10px.png


+ 402 - 0
zombiez/zombiez.c

@@ -0,0 +1,402 @@
+#include <furi.h>
+#include <gui/gui.h>
+#include <input/input.h>
+#include <stdlib.h>
+#include <dolphin/dolphin.h>
+
+//ORIGINAL REPO: https://github.com/Dooskington/flipperzero-zombiez
+//AUTHORS: https://github.com/Dooskington | https://github.com/DevMilanIan
+
+#include "zombiez.h"
+
+#define ZOMBIES_MAX 3
+#define ZOMBIES_WIDTH 5
+#define ZOMBIES_HEIGHT 8
+#define PROJECTILES_MAX 10
+
+#define MIN_Y 5
+#define MAX_Y 58
+#define WALL_X 16
+#define PLAYER_START_X 8
+#define PLAYER_START_Y (MAX_Y - MIN_Y) / 2
+
+typedef enum {
+    EventTypeTick,
+    EventTypeKey,
+} EventType;
+
+typedef struct {
+    EventType type;
+    InputEvent input;
+} PluginEvent;
+
+typedef enum { GameStatePlaying, GameStateGameOver } GameState;
+
+typedef struct {
+    int x;
+    int y;
+} Point;
+
+typedef struct {
+    Point position;
+    int hp;
+} Player;
+
+typedef struct {
+    Point position;
+    int hp;
+} Zombie;
+
+typedef struct {
+    Point position;
+} Projectile;
+
+typedef struct {
+    FuriMutex* mutex;
+    GameState game_state;
+    Player player;
+
+    size_t zombies_count;
+    Zombie* zombies[ZOMBIES_MAX];
+
+    size_t projectiles_count;
+    Projectile* projectiles[PROJECTILES_MAX];
+
+    uint16_t score;
+    bool input_shoot;
+} PluginState;
+
+static void render_callback(Canvas* const canvas, void* ctx) {
+    furi_assert(ctx);
+    const PluginState* plugin_state = ctx;
+    furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
+
+    canvas_draw_frame(canvas, 0, 0, 128, 64);
+
+    canvas_set_font(canvas, FontPrimary);
+    canvas_draw_str_aligned(
+        canvas,
+        plugin_state->player.position.x,
+        plugin_state->player.position.y,
+        AlignCenter,
+        AlignCenter,
+        "@");
+
+    canvas_draw_line(canvas, WALL_X, 0, WALL_X, 64);
+    canvas_draw_line(canvas, WALL_X + 2, 4, WALL_X + 2, 59);
+
+    for(int i = 0; i < PROJECTILES_MAX; ++i) {
+        Projectile* p = plugin_state->projectiles[i];
+        if(p != NULL) {
+            canvas_draw_disc(canvas, p->position.x, p->position.y, 3);
+        }
+    }
+
+    for(int i = 0; i < ZOMBIES_MAX; ++i) {
+        Zombie* z = plugin_state->zombies[i];
+        if(z != NULL) {
+            for(int h = 0; h < ZOMBIES_HEIGHT; h++) {
+                for(int w = 0; w < ZOMBIES_WIDTH; w++) {
+                    // Switch animation
+                    int zIdx = 0;
+                    if(z->position.x % 2 == 0) {
+                        zIdx = 1;
+                    }
+
+                    // Draw zombie pixels
+                    if(zombie_array[zIdx][h][w] == 1) {
+                        int x = z->position.x + w;
+                        int y = z->position.y + h;
+
+                        canvas_draw_dot(canvas, x, y);
+                    }
+                }
+            }
+        }
+    }
+
+    int heart;
+    if((plugin_state->player.hp - 10) > 5) { // 16, 17, 18, 19, 20
+        heart = 0;
+    } else if((plugin_state->player.hp - 5) > 5) { // 11, 12, 13, 14, 15
+        heart = 1;
+    } else if((plugin_state->player.hp - 3) > 2) { // 6, 7, 8, 9, 10
+        heart = 2;
+    } else if(plugin_state->player.hp > 0) { // 1, 2, 3, 4, 5
+        heart = 3;
+    } else { // 0
+        heart = 4;
+    }
+    // visual representation of health
+    for(int h = 0; h < 5; h++) {
+        for(int w = 0; w < 5; w++) {
+            if(heart_array[heart][h][w] == 1) {
+                int x = 124 - w;
+                int y = 56 + h;
+
+                canvas_draw_dot(canvas, x, y);
+            }
+        }
+    }
+
+    // buffer hp + score
+    char hpBuffer[8];
+    char scoreBuffer[14];
+
+    if(plugin_state->game_state == GameStatePlaying) {
+        // display ammo / reload
+        if(plugin_state->projectiles_count >= PROJECTILES_MAX) {
+            canvas_draw_str_aligned(canvas, 24, 10, AlignLeft, AlignCenter, "RELOAD");
+        } else {
+            for(uint8_t i = 0; i < (PROJECTILES_MAX - plugin_state->projectiles_count); i++) {
+                canvas_draw_box(canvas, 24 + (4 * i), 6, 2, 4);
+            }
+        }
+        // display hp + score
+        snprintf(hpBuffer, sizeof(hpBuffer), "%u", plugin_state->player.hp);
+        canvas_draw_str_aligned(canvas, 118, 62, AlignRight, AlignBottom, hpBuffer);
+
+        snprintf(scoreBuffer, sizeof(scoreBuffer), "%u", plugin_state->score);
+        canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, scoreBuffer);
+    }
+    // Game Over banner
+    if(plugin_state->game_state == GameStateGameOver) {
+        // Screen is 128x64 px
+        canvas_set_color(canvas, ColorWhite);
+        canvas_draw_box(canvas, 34, 20, 62, 24);
+
+        canvas_set_color(canvas, ColorBlack);
+        canvas_draw_frame(canvas, 34, 20, 62, 24);
+
+        canvas_set_font(canvas, FontPrimary);
+        canvas_draw_str(canvas, 37, 31, "Game Over");
+
+        canvas_set_font(canvas, FontSecondary);
+        snprintf(scoreBuffer, sizeof(scoreBuffer), "Score: %u", plugin_state->score);
+        canvas_draw_str_aligned(canvas, 64, 41, AlignCenter, AlignBottom, scoreBuffer);
+    }
+
+    //char* info = (char*)malloc(16 * sizeof(char));
+    //asprintf(&info, "%d, %d", plugin_state->x, plugin_state->y);
+    //canvas_draw_str_aligned(canvas, 32, 16, AlignLeft, AlignBottom, info);
+    //free(info);
+
+    furi_mutex_release(plugin_state->mutex);
+}
+
+static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
+    furi_assert(event_queue);
+    PluginEvent event = {.type = EventTypeKey, .input = *input_event};
+    furi_message_queue_put(event_queue, &event, FuriWaitForever);
+}
+
+static void tick(PluginState* const plugin_state) {
+    if(plugin_state->input_shoot && (plugin_state->projectiles_count < PROJECTILES_MAX)) {
+        Projectile* p = (Projectile*)malloc(sizeof(Projectile));
+        p->position.x = plugin_state->player.position.x;
+        p->position.y = plugin_state->player.position.y;
+
+        size_t idx = plugin_state->projectiles_count;
+        plugin_state->projectiles[idx] = p;
+        plugin_state->projectiles_count += 1;
+    }
+
+    for(int i = 0; i < ZOMBIES_MAX; ++i) {
+        if(!plugin_state->zombies[i]) {
+            Zombie* z = (Zombie*)malloc(sizeof(Zombie));
+            //z->hp = 20;
+            z->position.x = 126;
+            z->position.y = MIN_Y + (rand() % (MAX_Y - MIN_Y));
+
+            plugin_state->zombies[i] = z;
+            plugin_state->zombies_count += 1;
+        }
+    }
+
+    for(int i = 0; i < PROJECTILES_MAX; ++i) {
+        Projectile* p = plugin_state->projectiles[i];
+        if(p != NULL) {
+            p->position.x += 2;
+
+            for(int i = 0; i < ZOMBIES_MAX; ++i) {
+                Zombie* z = plugin_state->zombies[i];
+                if(z != NULL) {
+                    if( // projectile close enough to zombie
+                        (((z->position.x - p->position.x) <= 2) &&
+                         ((z->position.y - p->position.y) <= 4)) &&
+                        (((p->position.x - z->position.x) <= 2) &&
+                         ((p->position.y - z->position.y) <= 6))) {
+                        //z->hp -= 5;
+                        //if(z->hp <= 0) {
+                        plugin_state->zombies_count -= 1;
+                        free(z);
+                        plugin_state->zombies[i] = NULL;
+                        plugin_state->score++;
+                        //if(plugin_state->score % 15 == 0) dolphin_deed(getRandomDeed());
+                        //}
+                    } else if(z->position.x <= WALL_X && z->position.x > 0) { // zombie got to the wall
+                        plugin_state->zombies_count -= 1;
+                        free(z);
+                        plugin_state->zombies[i] = NULL;
+                        if(plugin_state->player.hp > 0) {
+                            plugin_state->player.hp--;
+                        } else {
+                            plugin_state->game_state = GameStateGameOver;
+                        }
+                    } else {
+                        if(furi_get_tick() % 2 == 0) z->position.x--;
+                    }
+                }
+            }
+
+            if(p->position.x >= 128) {
+                free(p);
+                plugin_state->projectiles[i] = NULL;
+            }
+        }
+    }
+
+    plugin_state->input_shoot = false;
+}
+
+static void timer_callback(void* ctx) {
+    furi_assert(ctx);
+    FuriMessageQueue* event_queue = ctx;
+    PluginEvent event = {.type = EventTypeTick};
+    furi_message_queue_put(event_queue, &event, 0);
+}
+
+static void zombiez_state_init(PluginState* const plugin_state) {
+    plugin_state->player.position.x = PLAYER_START_X;
+    plugin_state->player.position.y = PLAYER_START_Y;
+    plugin_state->player.hp = 20;
+
+    plugin_state->projectiles_count = 0;
+    plugin_state->zombies_count = 0;
+    plugin_state->score = 0;
+
+    for(int i = 0; i < PROJECTILES_MAX; i++) {
+        plugin_state->projectiles[i] = NULL;
+    }
+
+    for(int i = 0; i < ZOMBIES_MAX; i++) {
+        plugin_state->zombies[i] = NULL;
+    }
+
+    plugin_state->game_state = GameStatePlaying;
+    plugin_state->input_shoot = false;
+}
+
+int32_t zombiez_game_app(void* p) {
+    UNUSED(p);
+    uint32_t return_code = 0;
+    FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
+
+    PluginState* plugin_state = malloc(sizeof(PluginState));
+    zombiez_state_init(plugin_state);
+
+    plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
+    if(!plugin_state->mutex) {
+        FURI_LOG_E("Zombiez", "cannot create mutex\r\n");
+        return_code = 255;
+        goto free_and_exit;
+    }
+
+    // Set system callbacks
+    ViewPort* view_port = view_port_alloc();
+    view_port_draw_callback_set(view_port, render_callback, plugin_state);
+    view_port_input_callback_set(view_port, input_callback, event_queue);
+
+    FuriTimer* timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, event_queue);
+    furi_timer_start(timer, furi_kernel_get_tick_frequency() / 22);
+
+    // Open GUI and register view_port
+    Gui* gui = furi_record_open(RECORD_GUI);
+    gui_add_view_port(gui, view_port, GuiLayerFullscreen);
+
+    // Call dolphin deed on game start
+    dolphin_deed(DolphinDeedPluginGameStart);
+
+    PluginEvent event;
+    bool isRunning = true;
+    while(isRunning) {
+        FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
+        furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
+        if(event_status == FuriStatusOk) {
+            if(event.type == EventTypeKey) {
+                if(event.input.type == InputTypePress) {
+                    switch(event.input.key) {
+                    case InputKeyUp:
+                        if(plugin_state->player.position.y > MIN_Y &&
+                           plugin_state->game_state == GameStatePlaying) {
+                            plugin_state->player.position.y--;
+                        }
+                        break;
+                    case InputKeyDown:
+                        if(plugin_state->player.position.y < MAX_Y &&
+                           plugin_state->game_state == GameStatePlaying) {
+                            plugin_state->player.position.y++;
+                        }
+                        break;
+                    case InputKeyOk:
+                        if(plugin_state->projectiles_count < PROJECTILES_MAX &&
+                           plugin_state->game_state == GameStatePlaying) {
+                            plugin_state->input_shoot = true;
+                        }
+                        break;
+                    case InputKeyBack:
+                        break;
+                    default:
+                        break;
+                    }
+                } else if(
+                    event.input.type == InputTypeRepeat &&
+                    plugin_state->game_state == GameStatePlaying) {
+                    switch(event.input.key) {
+                    case InputKeyUp:
+                        if(plugin_state->player.position.y > (MIN_Y + 1)) {
+                            plugin_state->player.position.y -= 4;
+                        }
+                        break;
+                    case InputKeyDown:
+                        if(plugin_state->player.position.y < (MAX_Y - 1)) {
+                            plugin_state->player.position.y += 4;
+                        }
+                        break;
+                    default:
+                        break;
+                    }
+                } else if(event.input.type == InputTypeLong) {
+                    if(event.input.key == InputKeyOk) {
+                        if(plugin_state->game_state == GameStateGameOver) {
+                            zombiez_state_init(plugin_state);
+                        } else if(plugin_state->projectiles_count >= PROJECTILES_MAX) {
+                            plugin_state->projectiles_count = 0;
+                            plugin_state->player.hp++;
+                        }
+                    } else if(event.input.key == InputKeyBack) {
+                        isRunning = false;
+                    }
+                }
+            } else if(event.type == EventTypeTick) {
+                tick(plugin_state);
+            }
+        }
+        
+        furi_mutex_release(plugin_state->mutex);
+        view_port_update(view_port);
+    }
+
+    furi_timer_free(timer);
+    view_port_enabled_set(view_port, false);
+    gui_remove_view_port(gui, view_port);
+    furi_record_close(RECORD_GUI);
+    view_port_free(view_port);
+    furi_mutex_free(plugin_state->mutex);
+
+free_and_exit:
+    free(plugin_state);
+    furi_message_queue_free(event_queue);
+
+    return return_code;
+}

+ 62 - 0
zombiez/zombiez.h

@@ -0,0 +1,62 @@
+#include <furi.h>
+
+uint8_t zombie_array[2][8][5] = {
+    {
+        {0, 0, 1, 1, 1},
+        {0, 0, 1, 1, 1},
+        {1, 1, 1, 1, 1},
+        {0, 0, 1, 1, 1},
+        {0, 0, 1, 1, 1},
+        {0, 0, 1, 1, 1},
+        {0, 0, 1, 0, 0},
+        {0, 0, 1, 0, 0},
+    },
+    {
+        {0, 0, 1, 1, 1},
+        {0, 0, 1, 1, 1},
+        {1, 1, 1, 1, 1},
+        {0, 0, 1, 1, 1},
+        {0, 0, 1, 1, 1},
+        {0, 0, 1, 1, 1},
+        {0, 0, 0, 0, 1},
+        {0, 0, 0, 0, 1},
+    },
+};
+
+uint8_t heart_array[5][5][5] = {
+    {
+        {0, 1, 0, 1, 0},
+        {1, 1, 1, 1, 1},
+        {1, 1, 1, 1, 1},
+        {0, 1, 1, 1, 0},
+        {0, 0, 1, 0, 0},
+    },
+    {
+        {0, 0, 0, 0, 0},
+        {1, 1, 1, 1, 1},
+        {1, 1, 1, 1, 1},
+        {0, 1, 1, 1, 0},
+        {0, 0, 1, 0, 0},
+    },
+    {
+        {0, 0, 0, 0, 0},
+        {0, 0, 0, 0, 0},
+        {1, 1, 1, 1, 1},
+        {0, 1, 1, 1, 0},
+        {0, 0, 1, 0, 0},
+    },
+    {
+        {0, 0, 0, 0, 0},
+        {0, 0, 0, 0, 0},
+        {0, 0, 0, 0, 0},
+        {0, 1, 1, 1, 0},
+        {0, 0, 1, 0, 0},
+    },
+    {
+        {1, 0, 0, 0, 1},
+        {0, 1, 0, 1, 0},
+        {0, 0, 1, 0, 0},
+        {0, 1, 0, 1, 0},
+        {1, 0, 0, 0, 1},
+    },
+};