Skip to content

Commit d56472e

Browse files
committed
add air labyrinth game
1 parent 455f94b commit d56472e

40 files changed

+4700
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
assets/sprites/*

non_catalog_apps/air_labyrinth/LICENSE

+674
Large diffs are not rendered by default.
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Air Labyrinth
2+
3+
![Air Labyrinth](./.catalog/screenshots/1.png)
4+
5+
This is a simple game where you have to navigate a ball through a maze. The game is controlled by tilting the Flipper Zero with a Video Game Module attached. You can also play the game using the Flipper Zero's d-pad.
6+
7+
## How to play
8+
9+
1. Attach the video game module to the Flipper Zero.
10+
2. Open the Air Labyrinth game (`Apps`/`Games`/`Air Labyrinth`).
11+
3. Tilt the Flipper Zero to move the ball through the maze.
12+
13+
## Version history
14+
- 0.1.0 - Initial release by @CodeAllNight (https://youtube.com/@MrDerekJamison/about)
15+
16+
17+
## Other
18+
19+
This game was made based on the [air_arkanoid](https://github.com/flipperdevices/flipperzero-good-faps/tree/dev/air_arkanoid) and [flipperzero-game-engine-example](https://github.com/flipperdevices/flipperzero-game-engine-example) projects. Thanks to the authors of these projects for the inspiration and the code.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
App(
2+
appid="air_labyrinth",
3+
name="Air Labyrinth",
4+
apptype=FlipperAppType.EXTERNAL,
5+
entry_point="game_app",
6+
stack_size=4 * 1024, # Game stack, change accordingly
7+
fap_icon="icon.png",
8+
fap_category="Games",
9+
fap_description="Labyrinth game v0.1 that supports the Video Game Module motion sensor. Written by @CodeAllNight (https://youtube.com/MrDerekJamison/about)",
10+
fap_weburl="https://github.com/jamisonderek/flipper-zero-tutorials/tree/main/vgm/apps/air_labyrinth",
11+
fap_author="@CodeAllNight (MrDerekJamison)",
12+
fap_version="0.1",
13+
fap_file_assets="assets", # Do not touch this and the next line, it is needed to generate sprites
14+
# fap_extbuild=(
15+
# ExtFile(
16+
# path="${FAP_SRC_DIR}/assets",
17+
# command=("python" if __import__("sys").platform == "win32" else "python3")
18+
# + " ${FAP_SRC_DIR}/engine/scripts/sprite_builder.py ${FAP_SRC_DIR.abspath}/sprites ${TARGET.abspath}/sprites",
19+
# ),
20+
# ),
21+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
https://github.com/flipperdevices/flipperzero-game-engine dev /

non_catalog_apps/air_labyrinth/engine/LICENSE

+674
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Flipper Zero Game Engine
2+
3+
Welcome to the Flipper Zero game engine! This engine is designed to help you create games for the Flipper Zero device.
4+
5+
## Example App
6+
7+
To see the game engine in action, check out our [example app](https://github.com/flipperdevices/flipperzero-game-engine-example). This app demonstrates how to use the game engine to create a simple game.
8+
9+
## Contributing
10+
11+
We welcome contributions to the Flipper Zero game engine! If you have any bug reports, feature requests, or pull requests, please submit them to the [official repository](https://github.com/flipperdevices/flipperzero-game-engine).
12+
13+
Happy game development with Flipper Zero!
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#include <furi.h>
2+
#include "canvas.h"
3+
4+
void canvas_printf(Canvas* canvas, uint8_t x, uint8_t y, const char* format, ...) {
5+
FuriString* string = furi_string_alloc();
6+
va_list args;
7+
va_start(args, format);
8+
furi_string_vprintf(string, format, args);
9+
va_end(args);
10+
11+
canvas_draw_str(canvas, x, y, furi_string_get_cstr(string));
12+
13+
furi_string_free(string);
14+
}
15+
16+
size_t canvas_printf_width(Canvas* canvas, const char* format, ...) {
17+
FuriString* string = furi_string_alloc();
18+
va_list args;
19+
va_start(args, format);
20+
furi_string_vprintf(string, format, args);
21+
va_end(args);
22+
23+
size_t size = canvas_string_width(canvas, furi_string_get_cstr(string));
24+
25+
furi_string_free(string);
26+
27+
return size;
28+
}
29+
30+
void canvas_printf_aligned(
31+
Canvas* canvas,
32+
uint8_t x,
33+
uint8_t y,
34+
Align h,
35+
Align v,
36+
const char* format,
37+
...) {
38+
FuriString* string = furi_string_alloc();
39+
va_list args;
40+
va_start(args, format);
41+
furi_string_vprintf(string, format, args);
42+
va_end(args);
43+
44+
canvas_draw_str_aligned(canvas, x, y, h, v, furi_string_get_cstr(string));
45+
46+
furi_string_free(string);
47+
}
48+
49+
void canvas_draw_str_aligned_outline(
50+
Canvas* canvas,
51+
uint8_t x,
52+
uint8_t y,
53+
Align h,
54+
Align v,
55+
const char* cstr) {
56+
canvas_invert_color(canvas);
57+
canvas_draw_str_aligned(canvas, x + 1, y + 0, h, v, cstr);
58+
canvas_draw_str_aligned(canvas, x - 1, y - 0, h, v, cstr);
59+
canvas_draw_str_aligned(canvas, x + 0, y + 1, h, v, cstr);
60+
canvas_draw_str_aligned(canvas, x - 0, y - 1, h, v, cstr);
61+
canvas_invert_color(canvas);
62+
canvas_draw_str_aligned(canvas, x, y, h, v, cstr);
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#pragma once
2+
#include <stddef.h>
3+
#include <gui/canvas.h>
4+
5+
#ifdef __cplusplus
6+
extern "C" {
7+
#endif
8+
9+
/**
10+
* @brief Print formatted string to canvas
11+
*
12+
* @param canvas canvas instance
13+
* @param x x position
14+
* @param y y position
15+
* @param format format string
16+
* @param ... arguments
17+
*/
18+
void canvas_printf(Canvas* canvas, uint8_t x, uint8_t y, const char* format, ...)
19+
__attribute__((__format__(__printf__, 4, 5)));
20+
21+
/**
22+
* @brief Get width of formatted string
23+
*
24+
* @param canvas canvas instance
25+
* @param format format string
26+
* @param ... arguments
27+
* @return size_t width of formatted string
28+
*/
29+
size_t canvas_printf_width(Canvas* canvas, const char* format, ...)
30+
__attribute__((__format__(__printf__, 2, 3)));
31+
32+
/**
33+
* @brief Print formatted string to canvas with alignment
34+
*
35+
* @param canvas canvas instance
36+
* @param x x position
37+
* @param y y position
38+
* @param h horizontal alignment
39+
* @param v vertical alignment
40+
* @param format format string
41+
* @param ... arguments
42+
*/
43+
void canvas_printf_aligned(
44+
Canvas* canvas,
45+
uint8_t x,
46+
uint8_t y,
47+
Align h,
48+
Align v,
49+
const char* format,
50+
...) __attribute__((__format__(__printf__, 6, 7)));
51+
52+
/**
53+
* @brief Draw aligned string with outline
54+
*
55+
* @param canvas
56+
* @param x
57+
* @param y
58+
* @param h
59+
* @param v
60+
* @param cstr
61+
*/
62+
void canvas_draw_str_aligned_outline(
63+
Canvas* canvas,
64+
uint8_t x,
65+
uint8_t y,
66+
Align h,
67+
Align v,
68+
const char* cstr);
69+
70+
#ifdef __cplusplus
71+
}
72+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#include "clock_timer.h"
2+
#include <stdlib.h>
3+
4+
#include <furi_hal_interrupt.h>
5+
#include <furi_hal_bus.h>
6+
#include <stm32wbxx_ll_tim.h>
7+
8+
#define FURI_HAL_CLOCK_TIMER TIM2
9+
#define FURI_HAL_CLOCK_TIMER_BUS FuriHalBusTIM2
10+
#define FURI_HAL_CLOCK_TIMER_IRQ FuriHalInterruptIdTIM2
11+
12+
typedef struct {
13+
ClockTimerCallback callback;
14+
void* context;
15+
} ClockTimer;
16+
17+
static ClockTimer clock_timer = {
18+
.callback = NULL,
19+
.context = NULL,
20+
};
21+
22+
static void clock_timer_isr(void* context) {
23+
if(clock_timer.callback) {
24+
clock_timer.callback(context);
25+
}
26+
27+
LL_TIM_ClearFlag_UPDATE(FURI_HAL_CLOCK_TIMER);
28+
}
29+
30+
void clock_timer_start(ClockTimerCallback callback, void* context, float period) {
31+
clock_timer.callback = callback;
32+
clock_timer.context = context;
33+
34+
furi_hal_bus_enable(FURI_HAL_CLOCK_TIMER_BUS);
35+
36+
// init timer to produce interrupts
37+
LL_TIM_InitTypeDef TIM_InitStruct = {0};
38+
TIM_InitStruct.Autoreload = (SystemCoreClock / period) - 1;
39+
LL_TIM_Init(FURI_HAL_CLOCK_TIMER, &TIM_InitStruct);
40+
41+
furi_hal_interrupt_set_isr(FURI_HAL_CLOCK_TIMER_IRQ, clock_timer_isr, clock_timer.context);
42+
43+
LL_TIM_EnableIT_UPDATE(FURI_HAL_CLOCK_TIMER);
44+
LL_TIM_EnableCounter(FURI_HAL_CLOCK_TIMER);
45+
}
46+
47+
void clock_timer_stop(void) {
48+
LL_TIM_DisableIT_UPDATE(FURI_HAL_CLOCK_TIMER);
49+
LL_TIM_DisableCounter(FURI_HAL_CLOCK_TIMER);
50+
51+
furi_hal_bus_disable(FURI_HAL_CLOCK_TIMER_BUS);
52+
furi_hal_interrupt_set_isr(FURI_HAL_CLOCK_TIMER_IRQ, NULL, NULL);
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#pragma once
2+
3+
#ifdef __cplusplus
4+
extern "C" {
5+
#endif
6+
7+
typedef void (*ClockTimerCallback)(void* context);
8+
9+
void clock_timer_start(ClockTimerCallback callback, void* context, float period);
10+
11+
void clock_timer_stop(void);
12+
13+
#ifdef __cplusplus
14+
}
15+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#pragma once
2+
#include <furi.h>
3+
#include "game_engine.h"
4+
#include "level.h"
5+
#include "entity.h"
6+
#include "game_manager.h"
7+
8+
#ifdef __cplusplus
9+
extern "C" {
10+
#endif
11+
12+
typedef struct {
13+
float target_fps;
14+
bool show_fps;
15+
bool always_backlight;
16+
void (*start)(GameManager* game_manager, void* context);
17+
void (*stop)(void* context);
18+
size_t context_size;
19+
} Game;
20+
21+
extern const Game game;
22+
23+
#ifdef __cplusplus
24+
}
25+
#endif

0 commit comments

Comments
 (0)