add some games, make DOOM somewhat playable

This commit is contained in:
MX
2022-09-15 04:42:17 +03:00
parent 51ffdcd3bc
commit 361a239d3e
51 changed files with 3948 additions and 7 deletions

View File

@@ -0,0 +1,68 @@
# Doom Flipper Zero edition
<div style="text-align:center"><img src="assets/intro-screen.png"/></div>
## Will it run Doom?
As tradition goes, Doom is being ported to almost every possible embedded electronic device. Therefore I did an attempt to come up with something close to Doom and still compatible on the Flipper Zero's hardware.<br> This is not the actual Doom game but a port made from yet another Doom port to the Arduino Nano (https://github.com/daveruiz/doom-nano/). This port is basically a raycasting engine, using Doom sprites.<br>
This version is very basic and might be improved over time.
## How to install on Flipper Zero
During the porting process, minor changes were made to the workings (and build options) of the current firmware. These changes are documented here and are necessary in order to get a working firmware build that contains this Doom port.
### Modifying the firmware & build options
* In the `sites/cc.scons` add the following values to the `CCFLAGS` section:
```
...
"-Wno-unused-parameter",
"-Wno-type-limits",
"-Wno-unused-variable",
...
```
* In `applications/gui/canvas_i.h` comment out the following line:<br>
`uint8_t* canvas_get_buffer(Canvas* canvas);` --> `//uint8_t* canvas_get_buffer(Canvas* canvas);`
* In `applications/gui/canvas.h` add the following lines:
```
uint8_t* canvas_get_buffer(Canvas* canvas);
void canvas_draw_icon_bitmap(Canvas* canvas, uint8_t x, uint8_t y, int16_t w, int16_t h, const Icon* icon);
```
* In `applications/gui/canvas.c` add the following function:
```
void canvas_draw_icon_bitmap(Canvas* canvas, uint8_t x, uint8_t y, int16_t w, int16_t h, const Icon* icon){
furi_assert(canvas);
furi_assert(icon);
x += canvas->offset_x;
y += canvas->offset_y;
uint8_t* icon_data = NULL;
furi_hal_compress_icon_decode(icon_get_data(icon), &icon_data);
u8g2_DrawXBM(&canvas->fb, x, y, w, h, icon_data);
}
```
### Installing the plugin in the firmware
* Make a folder called Doom in the applications folder. Add all the source files (also the compiled folder and it's files) in the Doom folder.
* Make the `applications/meta/application.fam` look like the following:
```
App(
appid="basic_plugins",
name="Basic applications for plug-in menu",
apptype=FlipperAppType.METAPACKAGE,
provides=[
...
"doom_game",
...
],
)
```
If all went well the only thing left to do is building the firmware and installing it to the Flipper.
## Screenshots
![Intro screen](assets/screenshot-intro2.jpg)
![Start screen](assets/screenshot-start2.jpg)
![Imp](assets/screenshot-imp2.jpg)
![Medkit](assets/screenshot-medkit2.jpg)

View File

@@ -0,0 +1,15 @@
App(
appid="game_doom",
name="DOOM",
apptype=FlipperAppType.PLUGIN,
entry_point="doom_app",
cdefines=["APP_DOOM_GAME"],
requires=[
"gui",
"music_player",
],
stack_size=4 * 1024,
order=75,
fap_icon="doom_10px.png",
fap_category="Games",
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 847 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,403 @@
#include "assets_icons.h"
#include <gui/icon_i.h>
// Inverted icons
const uint8_t _I_fire_inv_0[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x40, 0xee, 0x00, 0x80, 0xe6, 0x00,
0x80, 0xa7, 0x01, 0x80, 0xc7, 0x03, 0x40, 0x45, 0x03, 0xe0, 0x41, 0x07, 0xf8, 0x82, 0x9f, 0xb9,
0x01, 0x3e, 0x7c, 0x00, 0x7a, 0x6e, 0x00, 0x56, 0x1c, 0x00, 0x6c, 0xf4, 0x01, 0x3a, 0x6c, 0x00,
0x7e, 0xfc, 0x00, 0x1a, 0x08, 0x00, 0x3c, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00,
};
const uint8_t* const _I_fire_inv[] = {_I_fire_inv_0};
const uint8_t _I_gun_inv_0[] = {
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x80, 0x23, 0x00, 0x00, 0x40,
0x20, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x57, 0x00, 0x00, 0x20, 0x8b, 0x00, 0x00,
0x90, 0x11, 0x01, 0x00, 0x98, 0x00, 0x00, 0x00, 0xb0, 0x43, 0x01, 0x00, 0x94, 0x81, 0x03,
0x00, 0xd0, 0x45, 0x04, 0x00, 0x8c, 0x02, 0x02, 0x00, 0xc4, 0x00, 0x03, 0x00, 0xc8, 0x00,
0x02, 0x00, 0x4e, 0x40, 0x00, 0x00, 0x92, 0x00, 0x02, 0x80, 0x07, 0x15, 0x04, 0xe0, 0x8f,
0x00, 0x0c, 0xd0, 0x9d, 0x07, 0x17, 0xe0, 0x3a, 0xc0, 0x3f, 0xe0, 0xf7, 0xff, 0x77, 0xe0,
0xae, 0xfe, 0x4b, 0xd8, 0xdd, 0xff, 0x4d, 0x88, 0xea, 0xbe, 0x26, 0x4c, 0xf5, 0xff, 0x17,
0xc8, 0xfa, 0xae, 0x0b, 0xcc, 0xff, 0xdf, 0x19, 0xe8, 0xeb, 0xa7, 0x00, 0xd8, 0xf1, 0x4d,
0x0c, 0xc0, 0xbe, 0x1a, 0x08, 0xf6, 0xfd, 0x37, 0x04,
};
const uint8_t* const _I_gun_inv[] = {_I_gun_inv_0};
const uint8_t _I_gun_mask_inv_0[] = {
0x01, 0x00, 0x53, 0x00, 0x00, 0x0c, 0x38, 0x04, 0x38, 0x09, 0xf8, 0x0c, 0x78, 0x17, 0xf0,
0x18, 0xf8, 0x00, 0x67, 0xff, 0x01, 0xaf, 0xc3, 0xff, 0x01, 0x80, 0x7e, 0x3f, 0xf0, 0x38,
0x07, 0xf0, 0x0e, 0x40, 0x31, 0x03, 0x8f, 0xfb, 0xff, 0x07, 0x01, 0x94, 0x3c, 0x0e, 0xc0,
0x35, 0xff, 0x85, 0xc8, 0x06, 0x30, 0x7e, 0x00, 0x0c, 0x61, 0xe2, 0xe1, 0xff, 0xc7, 0xc5,
0xc3, 0xff, 0x9f, 0x80, 0xca, 0xfe, 0x03, 0x2f, 0xf8, 0x0c, 0xc6, 0xc2, 0x03, 0x4b, 0xf8,
0xa8, 0x42, 0xe2, 0x03, 0x28, 0xf8, 0x1e, 0x80, 0x68, 0x1e, 0x28, 0x78,
};
const uint8_t* const _I_gun_mask_inv[] = {_I_gun_mask_inv_0};
const uint8_t _I_logo_inv_0[] = {
0x01, 0x00, 0x71, 0x01, 0x00, 0x44, 0x0a, 0x21, 0x00, 0xc0, 0x48, 0x20, 0x91, 0x0c, 0x05, 0x20,
0x14, 0x30, 0x80, 0x71, 0x80, 0x8e, 0x03, 0x00, 0x85, 0x40, 0x22, 0x98, 0x8a, 0x00, 0x20, 0x60,
0xa0, 0x83, 0xa8, 0x50, 0x20, 0xd8, 0x00, 0x41, 0xcd, 0x01, 0x03, 0x82, 0xc3, 0xc3, 0x61, 0xf0,
0xa8, 0xf0, 0x44, 0x6c, 0x14, 0x68, 0x26, 0x16, 0x3b, 0x0a, 0x89, 0xcd, 0x24, 0x14, 0x0a, 0x96,
0x32, 0x1b, 0x11, 0x85, 0xc4, 0x62, 0x92, 0x00, 0x88, 0xe1, 0x30, 0xb1, 0x18, 0x54, 0x46, 0x6d,
0x28, 0xa0, 0x70, 0x82, 0x23, 0x51, 0xa5, 0x54, 0x62, 0x90, 0x1b, 0x05, 0x0b, 0x19, 0x15, 0x89,
0x86, 0x86, 0x69, 0x42, 0xb0, 0xf5, 0xb2, 0x9a, 0x58, 0xac, 0xae, 0xaf, 0x35, 0x85, 0x50, 0xb8,
0xda, 0x69, 0x6d, 0x6e, 0x95, 0x9b, 0x9b, 0x50, 0xac, 0x9c, 0xac, 0x6e, 0x36, 0x37, 0x2b, 0xad,
0xed, 0xa2, 0x41, 0xa1, 0xd7, 0x6b, 0x42, 0x23, 0x3f, 0xdb, 0x75, 0xad, 0x5d, 0x6c, 0x2c, 0x37,
0xbf, 0x5b, 0x0d, 0x0e, 0x5a, 0xc5, 0xca, 0xdb, 0xef, 0x6b, 0xf6, 0xea, 0xff, 0xde, 0x6d, 0x4d,
0xfb, 0x75, 0xe5, 0xfb, 0xfd, 0xde, 0xfe, 0x6d, 0xe7, 0xb9, 0x7b, 0xba, 0xff, 0xdb, 0xfd, 0xaf,
0xbf, 0x77, 0xc7, 0xd9, 0xf3, 0x5f, 0x79, 0xed, 0x3c, 0x10, 0x3f, 0x79, 0x7d, 0xbf, 0x9f, 0xed,
0xff, 0xf7, 0xe7, 0x5f, 0xff, 0xbd, 0xae, 0xbd, 0xd6, 0xfe, 0xdf, 0x62, 0x34, 0xbf, 0xdf, 0xde,
0x77, 0x6b, 0xe9, 0x7f, 0xbf, 0xf5, 0x38, 0x77, 0xe7, 0xef, 0x7b, 0xb9, 0xf4, 0xbf, 0x7f, 0xde,
0xbd, 0xb8, 0x34, 0x3f, 0xbb, 0x5f, 0xbb, 0xff, 0xff, 0xbf, 0xda, 0x80, 0x63, 0xfb, 0xa1, 0xfe,
0xc1, 0x05, 0xdf, 0x11, 0x8f, 0xce, 0xdd, 0xf2, 0xff, 0xff, 0x40, 0xe3, 0xff, 0xf3, 0xfd, 0xe9,
0x42, 0xb1, 0xfc, 0x84, 0xc4, 0x32, 0x3f, 0xbb, 0xf0, 0x10, 0x7e, 0x60, 0x82, 0xfe, 0xdc, 0xe8,
0xc1, 0x11, 0x07, 0x97, 0xff, 0xfd, 0x7f, 0xbf, 0x82, 0x07, 0x8f, 0xff, 0xf8, 0x82, 0x06, 0xef,
0x7e, 0x04, 0x0e, 0x0f, 0xff, 0xe0, 0x9f, 0xfe, 0x04, 0x67, 0x01, 0x9f, 0x60, 0x21, 0xff, 0x0d,
0xf8, 0x68, 0xa0, 0x11, 0xcc, 0x04, 0x1f, 0xc1, 0xbf, 0x0d, 0x0c, 0xfe, 0x01, 0x08, 0x80, 0x40,
0xb8, 0x1f, 0xc0, 0x88, 0xc7, 0xe0, 0x00, 0x03, 0xe4, 0x5f, 0xff, 0xf0, 0xf0, 0x42, 0x70, 0x03,
0x43, 0x03, 0x04, 0x28, 0x68, 0x60, 0x20, 0x87, 0x03, 0xa4, 0x03, 0xc1, 0x7f, 0x1a, 0x08, 0x45,
0x86, 0x8b, 0x00, 0xc0, 0x5f, 0xe1, 0xc0, 0x85, 0x80, 0x5f, 0xe0, 0x80, 0x86, 0xfe, 0x01, 0xda,
0x01, 0x78, 0x04, 0x3c, 0xc0,
};
const uint8_t* const _I_logo_inv[] = {_I_logo_inv_0};
const Icon I_fire_inv =
{.width = 24, .height = 20, .frame_count = 1, .frame_rate = 0, .frames = _I_fire_inv};
const Icon I_gun_inv =
{.width = 32, .height = 32, .frame_count = 1, .frame_rate = 0, .frames = _I_gun_inv};
const Icon I_gun_mask_inv =
{.width = 32, .height = 32, .frame_count = 1, .frame_rate = 0, .frames = _I_gun_mask_inv};
const Icon I_logo_inv =
{.width = 72, .height = 47, .frame_count = 1, .frame_rate = 0, .frames = _I_logo_inv};
const uint8_t space[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const uint8_t zero[] = {0x00, 0x60, 0x90, 0x90, 0x90, 0x60};
const uint8_t one[] = {0x00, 0x20, 0x20, 0x20, 0x20, 0x70};
const uint8_t two[] = {0x00, 0x60, 0x90, 0x20, 0x40, 0xf0};
const uint8_t three[] = {0x00, 0x60, 0x90, 0x20, 0x90, 0x60};
const uint8_t four[] = {0x00, 0x90, 0x90, 0xf0, 0x10, 0x10};
const uint8_t five[] = {0x00, 0xf0, 0x80, 0xe0, 0x10, 0xe0};
const uint8_t six[] = {0x00, 0x60, 0x80, 0xe0, 0x90, 0x60};
const uint8_t seven[] = {0x00, 0xf0, 0x10, 0x10, 0x10, 0x10};
const uint8_t eight[] = {0x00, 0x60, 0x90, 0x60, 0x90, 0x60};
const uint8_t nine[] = {0x00, 0x60, 0x90, 0x70, 0x10, 0x60};
const uint8_t A[] = {0x00, 0x60, 0x90, 0xf0, 0x90, 0x90};
const uint8_t B[] = {0x00, 0xe0, 0x90, 0xe0, 0x90, 0xe0};
const uint8_t C[] = {0x00, 0x60, 0x90, 0x80, 0x90, 0x60};
const uint8_t D[] = {0x00, 0xe0, 0x90, 0x90, 0x90, 0xe0};
const uint8_t E[] = {0x00, 0xf0, 0x80, 0xe0, 0x80, 0xf0};
const uint8_t F[] = {0x00, 0xf0, 0x80, 0xe0, 0x80, 0x80};
const uint8_t G[] = {0x00, 0x60, 0x80, 0x80, 0x90, 0x60};
const uint8_t H[] = {0x00, 0x90, 0x90, 0xf0, 0x90, 0x90};
const uint8_t I[] = {0x00, 0x20, 0x20, 0x20, 0x20, 0x20};
const uint8_t J[] = {0x00, 0x10, 0x10, 0x10, 0x90, 0x60};
const uint8_t K[] = {0x00, 0x90, 0xa0, 0xc0, 0xa0, 0x90};
const uint8_t L[] = {0x00, 0x80, 0x80, 0x80, 0x80, 0xf0};
const uint8_t M[] = {0x00, 0x90, 0xf0, 0x90, 0x90, 0x90};
const uint8_t N[] = {0x00, 0x90, 0xd0, 0xb0, 0x90, 0x90};
const uint8_t O[] = {0x00, 0x60, 0x90, 0x90, 0x90, 0x60};
const uint8_t P[] = {0x00, 0xe0, 0x90, 0xe0, 0x80, 0x80};
const uint8_t Q[] = {0x00, 0x60, 0x90, 0x90, 0xb0, 0x70};
const uint8_t R[] = {0x00, 0xe0, 0x90, 0xe0, 0x90, 0x90};
const uint8_t S[] = {0x00, 0x60, 0x80, 0x60, 0x10, 0xe0};
const uint8_t T[] = {0x00, 0xe0, 0x40, 0x40, 0x40, 0x40};
const uint8_t U[] = {0x00, 0x90, 0x90, 0x90, 0x90, 0x60};
const uint8_t V[] = {0x00, 0x90, 0x90, 0x90, 0x60, 0x60};
const uint8_t W[] = {0x00, 0x90, 0x90, 0x90, 0xf0, 0x90};
const uint8_t X[] = {0x00, 0x90, 0x90, 0x60, 0x90, 0x90};
const uint8_t Y[] = {0x00, 0x90, 0x90, 0x60, 0x60, 0x60};
const uint8_t Z[] = {0x00, 0xf0, 0x10, 0x60, 0x80, 0xf0};
const uint8_t dot[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x40};
const uint8_t comma[] = {0x00, 0x00, 0x00, 0x00, 0x20, 0x40};
const uint8_t dash[] = {0x00, 0x00, 0x00, 0x60, 0x00, 0x00};
const uint8_t underscore[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0xf0};
const uint8_t bracket_open[] = {0x00, 0x20, 0x40, 0x40, 0x40, 0x20};
const uint8_t bracket_close[] = {0x00, 0x40, 0x20, 0x20, 0x20, 0x40};
const uint8_t cross_left[] = {0x10, 0x10, 0x70, 0x70, 0x10, 0x10};
const uint8_t cross_right[] = {0x80, 0x80, 0xe0, 0xe0, 0x80, 0x80};
const uint8_t pacman_left[] = {0x00, 0x30, 0x50, 0x70, 0x70, 0x00};
const uint8_t pacman_right[] = {0x00, 0xc0, 0x60, 0xe0, 0xe0, 0xe0};
const uint8_t box[] = {0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00};
const uint8_t* char_arr[48] = {
space,
zero,
one,
two,
three,
four,
five,
six,
seven,
eight,
nine,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
dot,
comma,
dash,
underscore,
bracket_open,
bracket_close,
cross_left,
cross_right,
pacman_left,
pacman_right,
box};
const uint8_t gradient[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x22, 0x22,
0x00, 0x00, 0x8a, 0x8a, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0xaa, 0xaa,
0x10, 0x10, 0xaa, 0xaa, 0x00, 0x00, 0xaa, 0xaa, 0x01, 0x01, 0xaa, 0xaa,
0x44, 0x44, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x44, 0x44, 0xaa, 0xaa,
0x15, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xbb, 0xbb,
0x55, 0x55, 0xaa, 0xea, 0x55, 0x55, 0xbb, 0xbb, 0x55, 0x55, 0xff, 0xff,
0x55, 0x55, 0xfb, 0xfb, 0x55, 0x55, 0xff, 0xff, 0x55, 0x55, 0xbb, 0xbf,
0x57, 0x57, 0xff, 0xff, 0xdd, 0xdd, 0xff, 0xff, 0x77, 0x75, 0xff, 0xff,
0xdd, 0xdd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
//const uint8_t gun[] = {0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x27, 0xff, 0xff, 0xfe, 0x3b, 0xff, 0xff, 0xfd, 0xfb, 0xff, 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xfd, 0x15, 0xff, 0xff, 0xfb, 0x2e, 0xff, 0xff, 0xf6, 0x77, 0x7f, 0xff, 0xe6, 0xff, 0xff, 0xff, 0xf2, 0x3d, 0x7f, 0xff, 0xd6, 0x7e, 0x3f, 0xff, 0xf4, 0x5d, 0xdf, 0xff, 0xce, 0xbf, 0xbf, 0xff, 0xdc, 0xff, 0x3f, 0xff, 0xec, 0xff, 0xbf, 0xff, 0x8d, 0xfd, 0xff, 0xff, 0xb6, 0xff, 0xbf, 0xfe, 0x1f, 0x57, 0xdf, 0xf8, 0x0e, 0xff, 0xcf, 0xf4, 0x46, 0x1f, 0x17, 0xf8, 0xa3, 0xfc, 0x03, 0xf8, 0x10, 0x00, 0x11, 0xf8, 0x8a, 0x80, 0x2d, 0xe4, 0x44, 0x00, 0x4d, 0xee, 0xa8, 0x82, 0x9b, 0xcd, 0x50, 0x00, 0x17, 0xec, 0xa0, 0x8a, 0x2f, 0xcc, 0x00, 0x04, 0x67, 0xe8, 0x28, 0x1a, 0xff, 0xe4, 0x70, 0x4d, 0xcf, 0xfc, 0x82, 0xa7, 0xef, 0x90, 0x40, 0x13, 0xdf};
// const uint8_t gun_mask[] = {0xff, 0xff, 0x8f, 0xff, 0xff, 0xfe, 0x03, 0xff, 0xff, 0xfc, 0x01, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xf8, 0x00, 0xff, 0xff, 0xf8, 0x00, 0xff, 0xff, 0xf0, 0x00, 0x7f, 0xff, 0xe0, 0x00, 0x3f, 0xff, 0xc0, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x3f, 0xff, 0x80, 0x00, 0x1f, 0xff, 0x80, 0x00, 0x0f, 0xff, 0x80, 0x00, 0x1f, 0xff, 0x80, 0x00, 0x1f, 0xff, 0x80, 0x00, 0x1f, 0xff, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0f};
const uint8_t gun[] = {0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x01, 0xc4, 0x00,
0x00, 0x02, 0x04, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0xea, 0x00,
0x00, 0x04, 0xd1, 0x00, 0x00, 0x09, 0x88, 0x80, 0x00, 0x19, 0x00, 0x00,
0x00, 0x0d, 0xc2, 0x80, 0x00, 0x29, 0x81, 0xc0, 0x00, 0x0b, 0xa2, 0x20,
0x00, 0x31, 0x40, 0x40, 0x00, 0x23, 0x00, 0xc0, 0x00, 0x13, 0x00, 0x40,
0x00, 0x72, 0x02, 0x00, 0x00, 0x49, 0x00, 0x40, 0x01, 0xe0, 0xa8, 0x20,
0x07, 0xf1, 0x00, 0x30, 0x0b, 0xb9, 0xe0, 0xe8, 0x07, 0x5c, 0x03, 0xfc,
0x07, 0xef, 0xff, 0xee, 0x07, 0x75, 0x7f, 0xd2, 0x1b, 0xbb, 0xff, 0xb2,
0x11, 0x57, 0x7d, 0x64, 0x32, 0xaf, 0xff, 0xe8, 0x13, 0x5f, 0x75, 0xd0,
0x33, 0xff, 0xfb, 0x98, 0x17, 0xd7, 0xe5, 0x00, 0x1b, 0x8f, 0xb2, 0x30,
0x03, 0x7d, 0x58, 0x10, 0x6f, 0xbf, 0xec, 0x20};
const uint8_t gun_mask[] = {0x00, 0x00, 0x70, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x03, 0xfe, 0x00,
0x00, 0x07, 0xfe, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x07, 0xff, 0x00,
0x00, 0x0f, 0xff, 0x80, 0x00, 0x1f, 0xff, 0xc0, 0x00, 0x3f, 0xff, 0x80,
0x00, 0x3f, 0xff, 0xc0, 0x00, 0x7f, 0xff, 0xe0, 0x00, 0x7f, 0xff, 0xf0,
0x00, 0x7f, 0xff, 0xe0, 0x00, 0x7f, 0xff, 0xe0, 0x00, 0x7f, 0xff, 0xe0,
0x00, 0xff, 0xff, 0xc0, 0x00, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xf0,
0x0f, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xfe,
0x1f, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff,
0x3f, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xf8,
0x7f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xf8,
0x7f, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xf0};
const uint8_t
imp_inv[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
0x02, 0x80, 0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x01,
0x00, 0x00, 0x01, 0x0f, 0xb3, 0x00, 0x00, 0xd0, 0x4e, 0x00, 0x00, 0x79, 0x8c,
0x00, 0x00, 0x1c, 0x19, 0x00, 0x01, 0x8a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x40, 0x02, 0x08, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x8e,
0x30, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x0c, 0x20, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x06, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x02, 0x20, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x03, 0xe0,
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0xa1, 0x80, 0x01, 0x80, 0x13, 0x00,
0x00, 0xf3, 0x8a, 0x00, 0x00, 0x09, 0x94, 0x00, 0x00, 0x88, 0x38, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x23, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x80,
0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0xe2, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x20, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x02, 0x20, 0x00,
0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x02, 0x20, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0,
0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
0x00, 0x1f, 0x00, 0x00, 0x02, 0x2a, 0x80, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01,
0xae, 0x20, 0x00, 0x01, 0x24, 0x40, 0x00, 0x02, 0xac, 0x80, 0x00, 0x02, 0x86,
0x00, 0x00, 0x03, 0x20, 0x20, 0x00, 0x04, 0x30, 0x40, 0x00, 0x0c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x00,
0x1c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x98,
0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00,
0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0xd6, 0x80, 0x00,
0x02, 0xbf, 0x80, 0x00, 0x06, 0x61, 0xa0, 0x00, 0x0c, 0xe8, 0x80, 0x00, 0x0c,
0x10, 0x00, 0x00, 0x1a, 0x22, 0x00, 0x00, 0x12, 0x40, 0x00, 0x00, 0x06, 0x0c,
0x00, 0x00, 0x04, 0x0d, 0x00, 0x00, 0x3a, 0x03, 0x00, 0x00, 0x10, 0x02, 0x00,
0x00, 0x60, 0x0a, 0x00, 0x00, 0x50, 0x04, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00,
0x00, 0x04, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01,
0x18, 0x00, 0x00, 0x01, 0x41, 0x40, 0x02, 0x33, 0xb6, 0x80, 0x01, 0x9c, 0x04,
0x00, 0x08, 0xfa, 0x02, 0x08, 0x05, 0x00, 0x01, 0x0c, 0x27, 0x83, 0xa2, 0x2a,
0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00}; //{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x0f, 0xb3, 0x00, 0x00, 0xd0, 0x4e, 0x00, 0x00, 0x79, 0x8c, 0x00, 0x00, 0x1c, 0x19, 0x00, 0x01, 0x8a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x08, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x8e, 0x30, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x0c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const uint8_t imp_mask_inv[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0xc0, 0x00,
0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x01, 0x07, 0xf1, 0x80,
0x00, 0xdf, 0xfe, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x01, 0xff, 0xff, 0x80,
0x00, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0x80, 0x03, 0xcf, 0xf1, 0xc0, 0x01, 0xc7, 0xf1, 0xc0,
0x01, 0x87, 0xf1, 0xc0, 0x03, 0x0f, 0xf9, 0x80, 0x03, 0x0f, 0xfb, 0x80, 0x01, 0x8f, 0xff, 0x80,
0x03, 0x9f, 0x79, 0x00, 0x00, 0x1f, 0x7c, 0x00, 0x00, 0x0f, 0x78, 0x00, 0x00, 0x0f, 0x78, 0x00,
0x00, 0x07, 0x30, 0x00, 0x00, 0x07, 0x38, 0x00, 0x00, 0x07, 0x30, 0x00, 0x00, 0x07, 0x30, 0x00,
0x00, 0x03, 0x78, 0x00, 0x00, 0x07, 0x30, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x07, 0xe0, 0x00,
0x00, 0x07, 0xc0, 0x00, 0x01, 0x07, 0xe1, 0x00, 0x00, 0x8f, 0xfa, 0x00, 0x00, 0xff, 0xfe, 0x00,
0x00, 0x3f, 0xfe, 0x00, 0x01, 0x7f, 0xff, 0x80, 0x00, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0x80,
0x03, 0xcf, 0xfb, 0xc0, 0x03, 0x87, 0xf1, 0xc0, 0x03, 0xcf, 0xf3, 0xc0, 0x01, 0xcf, 0xf1, 0x80,
0x00, 0xcf, 0xf1, 0x00, 0x00, 0x0f, 0xfb, 0x80, 0x00, 0x1e, 0x78, 0x00, 0x00, 0x0e, 0x78, 0x00,
0x00, 0x1e, 0x78, 0x00, 0x00, 0x0f, 0x70, 0x00, 0x00, 0x0f, 0x78, 0x00, 0x00, 0x07, 0x70, 0x00,
0x00, 0x07, 0x70, 0x00, 0x00, 0x07, 0x38, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x03, 0x20, 0x00,
0x00, 0x07, 0x30, 0x00, 0x00, 0x05, 0x70, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1f, 0x00,
0x00, 0x00, 0x1f, 0x00, 0x00, 0x03, 0x3f, 0x80, 0x00, 0x01, 0x3f, 0x00, 0x00, 0x01, 0xff, 0x30,
0x00, 0x03, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xc0, 0x00, 0x03, 0xff, 0x80, 0x00, 0x07, 0xff, 0xe0,
0x00, 0x07, 0xff, 0xc0, 0x00, 0x05, 0xff, 0xe0, 0x00, 0x00, 0xfc, 0xe0, 0x00, 0x01, 0xfc, 0xe0,
0x00, 0x01, 0xfc, 0x70, 0x00, 0x03, 0xfc, 0x38, 0x00, 0x03, 0xfe, 0x70, 0x00, 0x07, 0xfc, 0x00,
0x00, 0x07, 0x9e, 0x00, 0x00, 0x0f, 0xbc, 0x00, 0x00, 0x0f, 0x3e, 0x00, 0x00, 0x07, 0x9c, 0x00,
0x00, 0x03, 0x9c, 0x00, 0x00, 0x03, 0xb8, 0x00, 0x00, 0x03, 0x98, 0x00, 0x00, 0x01, 0x98, 0x00,
0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x1f, 0x00,
0x00, 0x00, 0x1f, 0x40, 0x00, 0x00, 0x3e, 0x80, 0x00, 0x01, 0xff, 0x80, 0x00, 0x03, 0xff, 0x80,
0x00, 0x07, 0xff, 0xe0, 0x00, 0x0e, 0xff, 0xc0, 0x00, 0x0c, 0xff, 0x80, 0x00, 0x1f, 0xfe, 0x00,
0x00, 0x13, 0xfc, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x1f, 0xff, 0x00, 0x00, 0x3f, 0x9f, 0x00,
0x00, 0x3e, 0x0f, 0x00, 0x00, 0x7c, 0x0f, 0x00, 0x00, 0x78, 0x0f, 0x00, 0x00, 0x78, 0x07, 0x80,
0x00, 0x78, 0x07, 0x40, 0x00, 0x38, 0x07, 0x80, 0x00, 0x30, 0x07, 0x00, 0x00, 0x30, 0x01, 0x00,
0x01, 0xf0, 0x00, 0x00, 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x00,
0x00, 0x01, 0x3e, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x01, 0x3f, 0xff, 0xc0,
0x01, 0xff, 0xff, 0xc0, 0x19, 0xff, 0xff, 0xe8, 0x7f, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xfe,
0x1f, 0xc2, 0x07, 0xe0, 0x1f, 0x00, 0x01, 0xe0, 0x0e, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
}; //{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x01, 0x07, 0xf1, 0x80, 0x00, 0xdf, 0xfe, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x01, 0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0x80, 0x03, 0xcf, 0xf1, 0xc0, 0x01, 0xc7, 0xf1, 0xc0, 0x01, 0x87, 0xf1, 0xc0, 0x03, 0x0f, 0xf9, 0x80, 0x03, 0x0f, 0xfb, 0x80, 0x01, 0x8f, 0xff, 0x80, 0x03, 0x9f, 0x79, 0x00, 0x00, 0x1f, 0x7c, 0x00, 0x00, 0x0f, 0x78, 0x00, 0x00, 0x0f, 0x78, 0x00, 0x00, 0x07, 0x30, 0x00, 0x00, 0x07, 0x38, 0x00, 0x00, 0x07, 0x30, 0x00, 0x00, 0x07, 0x30, 0x00, 0x00, 0x03, 0x78, 0x00, 0x00, 0x07, 0x30, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00};
const uint8_t fireball[] = {0x00, 0x00, 0x01, 0x40, 0x0a, 0xb0, 0x0e, 0xd0, 0x00, 0x68, 0x53,
0xb4, 0x0f, 0x48, 0x27, 0x78, 0x17, 0xa8, 0x27, 0xf0, 0x21, 0xd6,
0x02, 0xf8, 0x20, 0x48, 0x06, 0x20, 0x01, 0x00, 0x00, 0x00};
const uint8_t fireball_mask[] = {0x1f, 0x40, 0x0f, 0xf0, 0x3f, 0xf8, 0x1f, 0xfc, 0x7f, 0xfd, 0x7f,
0xfc, 0x7f, 0xfd, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xff, 0xfe, 0x3f, 0xfe, 0x17, 0xf8, 0x07, 0xf4, 0x01, 0xe0};
const uint8_t item[] = {0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfe, 0x77, 0xee, 0x3f,
0xfc, 0x5f, 0xfa, 0x2f, 0xf6, 0x53, 0xcc, 0x3e, 0x7e, 0x5e, 0x7c,
0x38, 0x1e, 0x58, 0x1c, 0x3e, 0x7e, 0x5e, 0x7e, 0x2e, 0xfc, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfc,
0x17, 0xfc, 0x22, 0x6c, 0x36, 0x44, 0x3f, 0xfc, 0x1f, 0xfc, 0x2b,
0xfc, 0x05, 0x54, 0x02, 0xa8, 0x00, 0x00, 0x00, 0x00};
const uint8_t item_mask[] = {0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f,
0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe,
0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x3f, 0xfc, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfc,
0x1f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f,
0xfc, 0x07, 0xfc, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00};
//const uint8_t door[] = {0xff, 0xff, 0xff, 0xff,0xb2, 0xbd, 0xcd, 0x5b,0x9a, 0xf4, 0x6d, 0x71,0xff, 0xff, 0xff, 0xff,0x00, 0x00, 0x00, 0x00,0xbf, 0xff, 0xff, 0xfd,0x3f, 0x00, 0xfe, 0xfc,0x3e, 0x00, 0xc6, 0xfc,0xbc, 0xaa, 0xfe, 0xbd,0x39, 0x54, 0xc6, 0xbc,0x32, 0x8e, 0xfe, 0xac,0xb5, 0xfe, 0xc6, 0xad,0x3f, 0xe0, 0xfe, 0xac,0x31, 0xe0, 0xc6, 0xac,0xb3, 0xf4, 0xfe, 0xad,0x3f, 0xe8, 0xc6, 0xac,0x3c, 0xf4, 0xd6, 0xac,0xb8, 0xff, 0xfe, 0xad,0x34, 0xc7, 0xfe, 0xfc,0x38, 0xd6, 0x0e, 0x0c,0xb0, 0xd6, 0x4e, 0x0d,0x3f, 0xd6, 0xaf, 0x5c,0x30, 0x47, 0xff, 0xac,0xb7, 0x57, 0xff, 0xfd,0x3f, 0xc6, 0x0e, 0x0c,0x35, 0x56, 0x40, 0x4c,0xb5, 0x46, 0xaa, 0xad,0x35, 0x56, 0x55, 0x4c,0xff, 0xff, 0xff, 0xff,0xb0, 0x1f, 0xf8, 0x0d,0xd9, 0x30, 0x0c, 0x9b,0xff, 0xe0, 0x07, 0xff};
const uint8_t door[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x07, 0xe1, 0x8c, 0x00, 0x04,
0x00, 0x7c, 0x03, 0x18, 0x60, 0x08, 0x00, 0x3e, 0x0f, 0xf7, 0xdf, 0x00, 0x1f, 0x00, 0xfe, 0x0f,
0xbe, 0xf8, 0x3e, 0x00, 0x3f, 0x1f, 0xff, 0xdf, 0x00, 0x1f, 0x81, 0xff, 0x0f, 0xff, 0xf8, 0x7e,
0x00, 0x3f, 0x8f, 0xff, 0xdf, 0x00, 0xff, 0xf9, 0xff, 0x1f, 0xff, 0xf8, 0xff, 0x80, 0x3f, 0xc7,
0xff, 0xcc, 0x07, 0xff, 0xfc, 0xff, 0x1f, 0xff, 0xe3, 0xff, 0x80, 0x3f, 0xc7, 0xff, 0xc0, 0x07,
0xff, 0xfc, 0x7f, 0x0f, 0xfe, 0x03, 0xff, 0xc0, 0x3f, 0xc3, 0xf7, 0xc0, 0x07, 0xdf, 0xf8, 0x3e,
0x0f, 0xbe, 0x01, 0xff, 0x80, 0x1f, 0x80, 0xe3, 0x80, 0x07, 0x8f, 0xf8, 0x1e, 0x07, 0x1c, 0x01,
0xff, 0x80, 0x3f, 0xc1, 0xff, 0xc0, 0x0f, 0xff, 0xfc, 0x3f, 0x0f, 0xbe, 0x03, 0xff, 0xc0, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0x80, 0x00,
0x7f, 0xff, 0xff, 0xc0, 0x00, 0x00, 0xe0, 0x00, 0x1f, 0xf0, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xff,
0xc0, 0x00, 0x00, 0xe0, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x01,
0xe0, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x01, 0xf0, 0x00, 0x0f,
0xf0, 0xff, 0x00, 0x03, 0xff, 0xff, 0xff, 0xe0, 0x7f, 0x81, 0xf0, 0x00, 0x0f, 0xf0, 0xff, 0x00,
0x07, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xc1, 0xf0, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x0f, 0xff, 0xff,
0xff, 0xe1, 0xff, 0xe1, 0xf0, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0xff,
0xc1, 0xf3, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xe0, 0xff, 0x81, 0xff, 0xc0,
0x0f, 0xf0, 0xff, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xe0, 0x3f, 0x01, 0xff, 0xc0, 0x0f, 0xf0, 0xff,
0x00, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xe0, 0x0f, 0xf0, 0xff, 0x01, 0xff, 0xff,
0xff, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xe0, 0x0f, 0xf0, 0xff, 0x03, 0xff, 0xff, 0xff, 0xff, 0xe1,
0xff, 0xe1, 0xff, 0xe0, 0x0f, 0xf0, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xc1, 0xff,
0xf0, 0x0f, 0xf0, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x8f, 0xe0, 0xff, 0x81, 0xff, 0xff, 0x0f, 0xf0,
0xff, 0x1f, 0xff, 0xff, 0xfe, 0x07, 0xe0, 0x7f, 0x81, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff,
0xff, 0xfc, 0x07, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff, 0x8f, 0xfc, 0x03,
0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff, 0x07, 0xfc, 0x07, 0xe0, 0xff, 0xc1,
0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xfe, 0x00, 0x7f, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f,
0xf0, 0xff, 0x0f, 0x9c, 0x00, 0x3f, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x07,
0xfc, 0x00, 0x7f, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x07, 0xfc, 0x00, 0x7f,
0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x0f, 0xfc, 0x00, 0x7f, 0xff, 0xe0, 0xff,
0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x0f, 0xfc, 0x00, 0x7f, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff,
0x8f, 0xf0, 0xff, 0x1f, 0xfe, 0x00, 0x7f, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff,
0x1f, 0xfc, 0x00, 0x3f, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xfc, 0x00,
0x3f, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xf0, 0x00, 0x1f, 0xff, 0xe0,
0x7f, 0x81, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x0f, 0xf0, 0x00, 0x1f, 0xff, 0xe0, 0xff, 0x81, 0xff,
0xff, 0x8f, 0xf0, 0xff, 0x07, 0xe0, 0x00, 0x3f, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0x8f, 0xf0,
0xff, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x00, 0x1f,
0x80, 0x3f, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x00, 0x3f, 0xc0, 0x1f, 0xff,
0xe1, 0xff, 0xe1, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x00, 0x7f, 0xc0, 0x0f, 0xff, 0xe1, 0xff, 0xe1,
0xff, 0xff, 0x8f, 0xf0, 0xff, 0x00, 0xff, 0xc0, 0x07, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, 0x8f,
0xf0, 0xff, 0x01, 0xff, 0xc0, 0x03, 0x8f, 0xc0, 0xc1, 0x81, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x03,
0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x07, 0xff, 0xc0, 0xff,
0x80, 0x00, 0x00, 0x01, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0x0f, 0xff, 0xc1, 0xff, 0x80, 0x00, 0x00,
0x01, 0xf3, 0x8e, 0x0f, 0xf0, 0xff, 0x0f, 0xff, 0xc3, 0xff, 0xc0, 0x00, 0x00, 0x01, 0xff, 0x9c,
0x0f, 0xf0, 0xff, 0x0f, 0xff, 0xc3, 0xff, 0xc0, 0xff, 0xfc, 0x01, 0xff, 0xfe, 0x0f, 0xf0, 0xff,
0x0f, 0xff, 0xc3, 0xff, 0xc1, 0xff, 0xfe, 0x01, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0x07, 0xff, 0xc3,
0xff, 0xc3, 0xff, 0xff, 0x01, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x0f, 0xff, 0xc3, 0xff, 0xc3, 0xff,
0xff, 0x01, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x0f, 0xff, 0xc3, 0xff, 0xc3, 0xff, 0xff, 0x01, 0xff,
0xff, 0x8f, 0xf0, 0xff, 0x0f, 0xff, 0xc3, 0xff, 0xc3, 0xff, 0xff, 0x01, 0xff, 0xff, 0x8f, 0xf0,
0xff, 0x0f, 0xff, 0xc3, 0xff, 0xc3, 0xff, 0xff, 0x01, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0x0f, 0xff,
0xc3, 0xff, 0xc3, 0xff, 0xff, 0x00, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0x0f, 0xff, 0xc3, 0xff, 0xc3,
0xff, 0xff, 0x00, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0x07, 0xff, 0xe3, 0xff, 0xc3, 0xff, 0xff, 0x00,
0x3f, 0xfe, 0x0f, 0xf0, 0xff, 0x07, 0xff, 0xf3, 0xff, 0xc1, 0xef, 0xfe, 0x00, 0x3f, 0xfe, 0x0f,
0xf0, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xc0, 0x82, 0x00, 0x00, 0x1f, 0xff, 0x0f, 0xf0, 0xff, 0x1f,
0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x07, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff, 0xff, 0xff,
0xc0, 0x00, 0x00, 0x00, 0x07, 0xff, 0x0f, 0xf0, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00,
0x00, 0x03, 0x8e, 0x0f, 0xf0, 0xff, 0x1f, 0xc1, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x03, 0x88,
0x0f, 0xf0, 0xff, 0x0f, 0x80, 0xff, 0xff, 0xc1, 0xff, 0xfc, 0x00, 0xff, 0xfe, 0x0f, 0xf0, 0xff,
0x06, 0x00, 0x73, 0xff, 0xc3, 0xff, 0xfe, 0x01, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0x00, 0x00, 0x03,
0xff, 0xc3, 0xff, 0xff, 0x83, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x07, 0x0c, 0x73, 0xff, 0xc3, 0xff,
0xff, 0xff, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x0f, 0xfe, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff,
0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xf0,
0xff, 0x1f, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff,
0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xc3,
0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff,
0xff, 0xff, 0x8f, 0xf0, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f,
0xf0, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0xf0, 0xfe, 0x1f,
0xfe, 0xfb, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfc, 0x0f, 0x9e, 0x73, 0xff,
0x81, 0xf9, 0xf7, 0xe7, 0x9c, 0xff, 0x03, 0xf0, 0xfc, 0x07, 0xfe, 0xfb, 0xc0, 0x00, 0xf0, 0x00,
0x6f, 0xbe, 0xfe, 0x03, 0xf0, 0x3c, 0x07, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe,
0x03, 0xc0, 0x1c, 0x0f, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0x03, 0x80, 0x1e,
0x0f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0x07, 0x80, 0x3f, 0x0f, 0xff, 0xff,
0xe0, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0x0f, 0xc0, 0x1f, 0x8f, 0xff, 0xff, 0xe7, 0xff, 0xff,
0xfe, 0x7f, 0xff, 0xff, 0x1f, 0x80, 0x1f, 0xc7, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfe, 0x3f, 0x80, 0x07, 0xc3, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xfc, 0x3e, 0x00,
0x07, 0xc1, 0xfe, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xcf, 0xf7, 0xf8, 0x3e, 0x00, 0x01, 0x00, 0xfc,
0x7e, 0x7f, 0xff, 0xff, 0xff, 0xe7, 0xe3, 0xf0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff,
0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xe0,
0x00, 0x00, 0x00, 0x00};

View File

@@ -0,0 +1,114 @@
#pragma once
#include <gui/icon.h>
#ifndef _sprites_h
#define _sprites_h
#define bmp_font_width 24 // in bytes
#define bmp_font_height 6
#define bmp_font_width_pxs 192
#define bmp_font_height_pxs 48
#define CHAR_MAP " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.,-_(){}[]#"
#define CHAR_WIDTH 4
#define CHAR_HEIGHT 6
#define BMP_GUN_WIDTH 32
#define BMP_GUN_HEIGHT 32
#define BMP_FIRE_WIDTH 24
#define BMP_FIRE_HEIGHT 20
#define BMP_IMP_WIDTH 32
#define BMP_IMP_HEIGHT 32
#define BMP_IMP_COUNT 5
#define BMP_FIREBALL_WIDTH 16
#define BMP_FIREBALL_HEIGHT 16
#define BMP_DOOR_WIDTH 100
#define BMP_DOOR_HEIGHT 100
#define BMP_ITEMS_WIDTH 16
#define BMP_ITEMS_HEIGHT 16
#define BMP_ITEMS_COUNT 2
#define BMP_LOGO_WIDTH 72
#define BMP_LOGO_HEIGHT 47
#define GRADIENT_WIDTH 2
#define GRADIENT_HEIGHT 8
#define GRADIENT_COUNT 8
#define GRADIENT_WHITE 7
#define GRADIENT_BLACK 0
// Inverted icons
extern const Icon I_fire_inv;
extern const Icon I_gun_inv;
extern const Icon I_gun_mask_inv;
extern const Icon I_logo_inv;
// Fonts
extern const uint8_t zero[];
extern const uint8_t one[];
extern const uint8_t two[];
extern const uint8_t three[];
extern const uint8_t four[];
extern const uint8_t five[];
extern const uint8_t six[];
extern const uint8_t seven[];
extern const uint8_t eight[];
extern const uint8_t nine[];
extern const uint8_t A[];
extern const uint8_t B[];
extern const uint8_t C[];
extern const uint8_t D[];
extern const uint8_t E[];
extern const uint8_t F[];
extern const uint8_t G[];
extern const uint8_t H[];
extern const uint8_t I[];
extern const uint8_t J[];
extern const uint8_t K[];
extern const uint8_t L[];
extern const uint8_t M[];
extern const uint8_t N[];
extern const uint8_t O[];
extern const uint8_t P[];
extern const uint8_t Q[];
extern const uint8_t R[];
extern const uint8_t S[];
extern const uint8_t T[];
extern const uint8_t U[];
extern const uint8_t V[];
extern const uint8_t W[];
extern const uint8_t X[];
extern const uint8_t Y[];
extern const uint8_t Z[];
extern const uint8_t dot[];
extern const uint8_t comma[];
extern const uint8_t dash[];
extern const uint8_t underscore[];
extern const uint8_t bracket_open[];
extern const uint8_t bracket_close[];
extern const uint8_t cross_left[];
extern const uint8_t cross_right[];
extern const uint8_t pacman_left[];
extern const uint8_t pacman_right[];
extern const uint8_t box[];
extern const uint8_t* char_arr[48];
extern const uint8_t gradient[];
//extern const uint8_t gun[]
//extern const uint8_t gun_mask[]
extern const uint8_t gun[];
extern const uint8_t gun_mask[];
extern const uint8_t imp_inv[];
extern const uint8_t imp_mask_inv[];
extern const uint8_t fireball[];
extern const uint8_t fireball_mask[];
extern const uint8_t item[];
extern const uint8_t item_mask[];
extern const uint8_t door[];
#endif

View File

@@ -0,0 +1,91 @@
#ifndef _constants_h
#define _constants_h
#define PB_CONSTEXPR constexpr
#define PI 3.14159265358979323846
// Key pinout
#define USE_INPUT_PULLUP
#define K_LEFT 6
#define K_RIGHT 7
#define K_UP 8
#define K_DOWN 3
#define K_FIRE 10
// SNES Controller
// uncomment following line to enable snes controller support
// #define SNES_CONTROLLER
const uint8_t DATA_CLOCK = 11;
const uint8_t DATA_LATCH = 12;
const uint8_t DATA_SERIAL = 13;
// Sound
const uint8_t SOUND_PIN = 9; // do not change, belongs to used timer
// GFX settings
#define OPTIMIZE_SSD1306 // Optimizations for SSD1366 displays
#define FRAME_TIME 66.666666 // Desired time per frame in ms (66.666666 is ~15 fps)
#define RES_DIVIDER 2
/* Higher values will result in lower horizontal resolution when rasterize and lower process and memory usage
Lower will require more process and memory, but looks nicer
*/
#define Z_RES_DIVIDER 2 // Zbuffer resolution divider. We sacrifice resolution to save memory
#define DISTANCE_MULTIPLIER 20
/* Distances are stored as uint8_t, multiplying the distance we can obtain more precision taking care
of keep numbers inside the type range. Max is 256 / MAX_RENDER_DEPTH
*/
#define MAX_RENDER_DEPTH 12
#define MAX_SPRITE_DEPTH 8
#define ZBUFFER_SIZE SCREEN_WIDTH / Z_RES_DIVIDER
// Level
#define LEVEL_WIDTH_BASE 6
#define LEVEL_WIDTH (1 << LEVEL_WIDTH_BASE)
#define LEVEL_HEIGHT 57
#define LEVEL_SIZE LEVEL_WIDTH / 2 * LEVEL_HEIGHT
// scenes
#define INTRO 0
#define GAME_PLAY 1
// Game
#define GUN_TARGET_POS 18
#define GUN_SHOT_POS GUN_TARGET_POS + 4
#define ROT_SPEED .12
#define MOV_SPEED .2
#define MOV_SPEED_INV 5 // 1 / MOV_SPEED
#define JOGGING_SPEED .005
#define ENEMY_SPEED .02
#define FIREBALL_SPEED .2
#define FIREBALL_ANGLES 45 // Num of angles per PI
#define MAX_ENTITIES 10 // Max num of active entities
#define MAX_STATIC_ENTITIES 28 // Max num of entities in sleep mode
#define MAX_ENTITY_DISTANCE 200 // * DISTANCE_MULTIPLIER
#define MAX_ENEMY_VIEW 80 // * DISTANCE_MULTIPLIER
#define ITEM_COLLIDER_DIST 6 // * DISTANCE_MULTIPLIER
#define ENEMY_COLLIDER_DIST 4 // * DISTANCE_MULTIPLIER
#define FIREBALL_COLLIDER_DIST 2 // * DISTANCE_MULTIPLIER
#define ENEMY_MELEE_DIST 6 // * DISTANCE_MULTIPLIER
#define WALL_COLLIDER_DIST .2
#define ENEMY_MELEE_DAMAGE 8
#define ENEMY_FIREBALL_DAMAGE 20
#define GUN_MAX_DAMAGE 20
// display
const uint8_t SCREEN_WIDTH = 128;
const uint8_t SCREEN_HEIGHT = 64;
const uint8_t HALF_WIDTH = SCREEN_WIDTH / 2;
const uint8_t RENDER_HEIGHT = 56; // raycaster working height (the rest is for the hud)
const uint8_t HALF_HEIGHT = SCREEN_HEIGHT / 2;
#endif

View File

@@ -0,0 +1,282 @@
#include <gui/gui.h>
#include <gui/canvas_i.h>
#include <furi_hal.h>
#include <u8g2_glue.h>
#include "constants.h"
#include "compiled/assets_icons.h"
#define CHECK_BIT(var, pos) ((var) & (1 << (pos)))
static const uint8_t bit_mask[8] = {128, 64, 32, 16, 8, 4, 2, 1};
#define pgm_read_byte(addr) (*(const unsigned char*)(addr))
#define read_bit(b, n) b& pgm_read_byte(bit_mask + n) ? 1 : 0
//#define read_bit(byte, index) (((unsigned)(byte) >> (index)) & 1)
void drawVLine(uint8_t x, int8_t start_y, int8_t end_y, uint8_t intensity, Canvas* const canvas);
void drawPixel(int8_t x, int8_t y, bool color, bool raycasterViewport, Canvas* const canvas);
void drawSprite(
int8_t x,
int8_t y,
const uint8_t* bitmap,
const uint8_t* bitmap_mask,
int16_t w,
int16_t h,
uint8_t sprite,
double distance,
Canvas* const canvas);
void drawBitmap(
int16_t x,
int16_t y,
const Icon* i,
int16_t w,
int16_t h,
uint16_t color,
Canvas* const canvas);
void drawTextSpace(int8_t x, int8_t y, char* txt, uint8_t space, Canvas* const canvas);
void drawChar(int8_t x, int8_t y, char ch, Canvas* const canvas);
void clearRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, Canvas* const canvas);
void drawGun(
int16_t x,
int16_t y,
const uint8_t* bitmap,
int16_t w,
int16_t h,
uint16_t color,
Canvas* const canvas);
void drawRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, Canvas* const canvas);
void drawText(uint8_t x, uint8_t y, uint8_t num, Canvas* const canvas);
void fadeScreen(uint8_t intensity, bool color, Canvas* const canvas);
bool getGradientPixel(uint8_t x, uint8_t y, uint8_t i);
double getActualFps();
void fps();
void setupDisplay(Canvas* canvas);
uint8_t reverse_bits(uint8_t num);
// FPS control
double delta = 1;
uint32_t lastFrameTime = 0;
uint8_t zbuffer[128]; /// 128 = screen width & REMOVE WHEN DISPLAY.H IMPLEMENTED
uint8_t* display_buf = NULL;
void drawGun(
int16_t x,
int16_t y,
const uint8_t* bitmap,
int16_t w,
int16_t h,
uint16_t color,
Canvas* const canvas) {
int16_t byteWidth = (w + 7) / 8;
uint8_t byte = 0;
for(int16_t j = 0; j < h; j++, y++) {
for(int16_t i = 0; i < w; i++) {
if(i & 7)
byte <<= 1;
else
byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
if(byte & 0x80) drawPixel(x + i, y, color, false, canvas);
}
}
}
void drawVLine(uint8_t x, int8_t start_y, int8_t end_y, uint8_t intensity, Canvas* const canvas) {
UNUSED(intensity);
uint8_t dots = end_y - start_y;
for(int i = 0; i < dots; i++) {
canvas_draw_dot(canvas, x, start_y + i);
}
}
void setupDisplay(Canvas* canvas) {
memset(zbuffer, 0xff, 128);
display_buf = (uint8_t*)canvas_get_buffer(canvas);
//display_buf = u8g2_GetBufferPtr(&canvas->fb);
}
void drawBitmap(
int16_t x,
int16_t y,
const Icon* i,
int16_t w,
int16_t h,
uint16_t color,
Canvas* const canvas) {
UNUSED(color);
canvas_draw_icon_bitmap(canvas, x, y, w, h, i);
}
void drawText(uint8_t x, uint8_t y, uint8_t num, Canvas* const canvas) {
char buf[4];
itoa(num, buf, 10);
drawTextSpace(x, y, buf, 1, canvas);
}
void drawTextSpace(int8_t x, int8_t y, char* txt, uint8_t space, Canvas* const canvas) {
uint8_t pos = x;
uint8_t i = 0;
char ch;
while((ch = txt[i]) != '\0') {
drawChar(pos, y, ch, canvas);
i++;
pos += CHAR_WIDTH + space;
// shortcut on end of screen
if(pos > SCREEN_WIDTH) return;
}
}
// Custom drawBitmap method with scale support, mask, zindex and pattern filling
void drawSprite(
int8_t x,
int8_t y,
const uint8_t* bitmap,
const uint8_t* bitmap_mask,
int16_t w,
int16_t h,
uint8_t sprite,
double distance,
Canvas* const canvas) {
uint8_t tw = (double)w / distance;
uint8_t th = (double)h / distance;
uint8_t byte_width = w / 8;
uint8_t pixel_size = fmax(1, (double)1.0 / (double)distance);
uint16_t sprite_offset = byte_width * h * sprite;
bool pixel;
bool maskPixel;
// Don't draw the whole sprite if the anchor is hidden by z buffer
// Not checked per pixel for performance reasons
if(zbuffer[(int)(fmin(fmax(x, 0), ZBUFFER_SIZE - 1) / Z_RES_DIVIDER)] <
distance * DISTANCE_MULTIPLIER) {
return;
}
for(uint8_t ty = 0; ty < th; ty += pixel_size) {
// Don't draw out of screen
if(y + ty < 0 || y + ty >= RENDER_HEIGHT) {
continue;
}
uint8_t sy = ty * distance; // The y from the sprite
for(uint8_t tx = 0; tx < tw; tx += pixel_size) {
uint8_t sx = tx * distance; // The x from the sprite
uint16_t byte_offset = sprite_offset + sy * byte_width + sx / 8;
// Don't draw out of screen
if(x + tx < 0 || x + tx >= SCREEN_WIDTH) {
continue;
}
maskPixel = read_bit(pgm_read_byte(bitmap_mask + byte_offset), sx % 8);
if(maskPixel) {
pixel = read_bit(pgm_read_byte(bitmap + byte_offset), sx % 8);
for(uint8_t ox = 0; ox < pixel_size; ox++) {
for(uint8_t oy = 0; oy < pixel_size; oy++) {
if(bitmap == imp_inv)
drawPixel(x + tx + ox, y + ty + oy, 1, true, canvas);
else
drawPixel(x + tx + ox, y + ty + oy, pixel, true, canvas);
}
}
}
}
}
}
void drawPixel(int8_t x, int8_t y, bool color, bool raycasterViewport, Canvas* const canvas) {
if(x < 0 || x >= SCREEN_WIDTH || y < 0 ||
y >= (raycasterViewport ? RENDER_HEIGHT : SCREEN_HEIGHT)) {
return;
}
if(color)
canvas_draw_dot(canvas, x, y);
else {
canvas_invert_color(canvas);
canvas_draw_dot(canvas, x, y);
canvas_invert_color(canvas);
}
}
void drawChar(int8_t x, int8_t y, char ch, Canvas* const canvas) {
uint8_t lsb;
uint8_t c = 0;
while(CHAR_MAP[c] != ch && CHAR_MAP[c] != '\0') c++;
for(uint8_t i = 0; i < 6; i++) {
//lsb = (char_arr[c][i] >> 4);
lsb = reverse_bits(char_arr[c][i]);
for(uint8_t n = 0; n < 4; n++) {
if(CHECK_BIT(lsb, n)) {
drawPixel(x + n, y + i, true, false, canvas);
}
}
}
}
void clearRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, Canvas* const canvas) {
canvas_invert_color(canvas);
for(int i = 0; i < w; i++) {
for(int j = 0; j < h; j++) {
canvas_draw_dot(canvas, x + i, y + j);
}
}
canvas_invert_color(canvas);
}
void drawRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, Canvas* const canvas) {
for(int i = 0; i < w; i++) {
for(int j = 0; j < h; j++) {
canvas_draw_dot(canvas, x + i, y + j);
}
}
}
bool getGradientPixel(uint8_t x, uint8_t y, uint8_t i) {
if(i == 0) return 0;
if(i >= GRADIENT_COUNT - 1) return 1;
uint8_t index =
fmax(0, fmin(GRADIENT_COUNT - 1, i)) * GRADIENT_WIDTH * GRADIENT_HEIGHT // gradient index
+ y * GRADIENT_WIDTH % (GRADIENT_WIDTH * GRADIENT_HEIGHT) // y byte offset
+ x / GRADIENT_HEIGHT % GRADIENT_WIDTH; // x byte offset
//uint8_t *gradient_data = NULL;
//furi_hal_compress_icon_decode(icon_get_data(&I_gradient_inv), &gradient_data);
// return the bit based on x
return read_bit(pgm_read_byte(gradient + index), x % 8);
}
void fadeScreen(uint8_t intensity, bool color, Canvas* const canvas) {
for(uint8_t x = 0; x < SCREEN_WIDTH; x++) {
for(uint8_t y = 0; y < SCREEN_HEIGHT; y++) {
if(getGradientPixel(x, y, intensity)) drawPixel(x, y, color, false, canvas);
}
}
}
// Adds a delay to limit play to specified fps
// Calculates also delta to keep movement consistent in lower framerates
void fps() {
while(furi_get_tick() - lastFrameTime < FRAME_TIME)
;
delta = (double)(furi_get_tick() - lastFrameTime) / (double)FRAME_TIME;
lastFrameTime = furi_get_tick();
}
double getActualFps() {
return 1000 / ((double)FRAME_TIME * (double)delta);
}
uint8_t reverse_bits(uint8_t num) {
unsigned int NO_OF_BITS = sizeof(num) * 8;
uint8_t reverse_num = 0;
uint8_t i;
for(i = 0; i < NO_OF_BITS; i++) {
if((num & (1 << i))) reverse_num |= 1 << ((NO_OF_BITS - 1) - i);
}
return reverse_num;
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -0,0 +1,499 @@
#include "doom_music_player_worker.h"
#include <furi_hal.h>
#include <furi.h>
#include <storage/storage.h>
#include <lib/flipper_format/flipper_format.h>
#include <m-array.h>
#define TAG "MusicPlayerWorker"
#define MUSIC_PLAYER_FILETYPE "Flipper Music Format"
#define MUSIC_PLAYER_VERSION 0
#define SEMITONE_PAUSE 0xFF
#define NOTE_C4 261.63f
#define NOTE_C4_SEMITONE (4.0f * 12.0f)
#define TWO_POW_TWELTH_ROOT 1.059463094359f
typedef struct {
uint8_t semitone;
uint8_t duration;
uint8_t dots;
} NoteBlock;
ARRAY_DEF(NoteBlockArray, NoteBlock, M_POD_OPLIST);
struct MusicPlayerWorker {
FuriThread* thread;
bool should_work;
MusicPlayerWorkerCallback callback;
void* callback_context;
float volume;
uint32_t bpm;
uint32_t duration;
uint32_t octave;
NoteBlockArray_t notes;
};
static int32_t music_player_worker_thread_callback(void* context) {
furi_assert(context);
MusicPlayerWorker* instance = context;
NoteBlockArray_it_t it;
NoteBlockArray_it(it, instance->notes);
while(instance->should_work) {
if(NoteBlockArray_end_p(it)) {
NoteBlockArray_it(it, instance->notes);
furi_delay_ms(10);
} else {
NoteBlock* note_block = NoteBlockArray_ref(it);
float note_from_a4 = (float)note_block->semitone - NOTE_C4_SEMITONE;
float frequency = NOTE_C4 * powf(TWO_POW_TWELTH_ROOT, note_from_a4);
float duration =
60.0 * furi_kernel_get_tick_frequency() * 4 / instance->bpm / note_block->duration;
uint32_t dots = note_block->dots;
while(dots > 0) {
duration += duration / 2;
dots--;
}
uint32_t next_tick = furi_get_tick() + duration;
float volume = instance->volume;
if(instance->callback) {
instance->callback(
note_block->semitone,
note_block->dots,
note_block->duration,
0.0,
instance->callback_context);
}
furi_hal_speaker_stop();
furi_hal_speaker_start(frequency, volume);
while(instance->should_work && furi_get_tick() < next_tick) {
volume *= 0.9945679;
furi_hal_speaker_set_volume(volume);
furi_delay_ms(2);
}
NoteBlockArray_next(it);
}
}
furi_hal_speaker_stop();
return 0;
}
MusicPlayerWorker* music_player_worker_alloc() {
MusicPlayerWorker* instance = malloc(sizeof(MusicPlayerWorker));
NoteBlockArray_init(instance->notes);
instance->thread = furi_thread_alloc();
furi_thread_set_name(instance->thread, "MusicPlayerWorker");
furi_thread_set_stack_size(instance->thread, 1024);
furi_thread_set_context(instance->thread, instance);
furi_thread_set_callback(instance->thread, music_player_worker_thread_callback);
instance->volume = 1.0f;
return instance;
}
void music_player_worker_free(MusicPlayerWorker* instance) {
furi_assert(instance);
furi_thread_free(instance->thread);
NoteBlockArray_clear(instance->notes);
free(instance);
}
static bool is_digit(const char c) {
return isdigit(c) != 0;
}
static bool is_letter(const char c) {
return islower(c) != 0 || isupper(c) != 0;
}
static bool is_space(const char c) {
return c == ' ' || c == '\t';
}
static size_t extract_number(const char* string, uint32_t* number) {
size_t ret = 0;
while(is_digit(*string)) {
*number *= 10;
*number += (*string - '0');
string++;
ret++;
}
return ret;
}
static size_t extract_dots(const char* string, uint32_t* number) {
size_t ret = 0;
while(*string == '.') {
*number += 1;
string++;
ret++;
}
return ret;
}
static size_t extract_char(const char* string, char* symbol) {
if(is_letter(*string)) {
*symbol = *string;
return 1;
} else {
return 0;
}
}
static size_t extract_sharp(const char* string, char* symbol) {
if(*string == '#' || *string == '_') {
*symbol = '#';
return 1;
} else {
return 0;
}
}
static size_t skip_till(const char* string, const char symbol) {
size_t ret = 0;
while(*string != '\0' && *string != symbol) {
string++;
ret++;
}
if(*string != symbol) {
ret = 0;
}
return ret;
}
static bool music_player_worker_add_note(
MusicPlayerWorker* instance,
uint8_t semitone,
uint8_t duration,
uint8_t dots) {
NoteBlock note_block;
note_block.semitone = semitone;
note_block.duration = duration;
note_block.dots = dots;
NoteBlockArray_push_back(instance->notes, note_block);
return true;
}
static int8_t note_to_semitone(const char note) {
switch(note) {
case 'C':
return 0;
// C#
case 'D':
return 2;
// D#
case 'E':
return 4;
case 'F':
return 5;
// F#
case 'G':
return 7;
// G#
case 'A':
return 9;
// A#
case 'B':
return 11;
default:
return 0;
}
}
static bool music_player_worker_parse_notes(MusicPlayerWorker* instance, const char* string) {
const char* cursor = string;
bool result = true;
while(*cursor != '\0') {
if(!is_space(*cursor)) {
uint32_t duration = 0;
char note_char = '\0';
char sharp_char = '\0';
uint32_t octave = 0;
uint32_t dots = 0;
// Parsing
cursor += extract_number(cursor, &duration);
cursor += extract_char(cursor, &note_char);
cursor += extract_sharp(cursor, &sharp_char);
cursor += extract_number(cursor, &octave);
cursor += extract_dots(cursor, &dots);
// Post processing
note_char = toupper(note_char);
if(!duration) {
duration = instance->duration;
}
if(!octave) {
octave = instance->octave;
}
// Validation
bool is_valid = true;
is_valid &= (duration >= 1 && duration <= 128);
is_valid &= ((note_char >= 'A' && note_char <= 'G') || note_char == 'P');
is_valid &= (sharp_char == '#' || sharp_char == '\0');
is_valid &= (octave <= 16);
is_valid &= (dots <= 16);
if(!is_valid) {
FURI_LOG_E(
TAG,
"Invalid note: %u%c%c%u.%u",
duration,
note_char == '\0' ? '_' : note_char,
sharp_char == '\0' ? '_' : sharp_char,
octave,
dots);
result = false;
break;
}
// Note to semitones
uint8_t semitone = 0;
if(note_char == 'P') {
semitone = SEMITONE_PAUSE;
} else {
semitone += octave * 12;
semitone += note_to_semitone(note_char);
semitone += sharp_char == '#' ? 1 : 0;
}
if(music_player_worker_add_note(instance, semitone, duration, dots)) {
FURI_LOG_D(
TAG,
"Added note: %c%c%u.%u = %u %u",
note_char == '\0' ? '_' : note_char,
sharp_char == '\0' ? '_' : sharp_char,
octave,
dots,
semitone,
duration);
} else {
FURI_LOG_E(
TAG,
"Invalid note: %c%c%u.%u = %u %u",
note_char == '\0' ? '_' : note_char,
sharp_char == '\0' ? '_' : sharp_char,
octave,
dots,
semitone,
duration);
}
cursor += skip_till(cursor, ',');
}
if(*cursor != '\0') cursor++;
}
return result;
}
bool music_player_worker_load(MusicPlayerWorker* instance, const char* file_path) {
furi_assert(instance);
furi_assert(file_path);
bool ret = false;
if(strcasestr(file_path, ".fmf")) {
ret = music_player_worker_load_fmf_from_file(instance, file_path);
} else {
ret = music_player_worker_load_rtttl_from_file(instance, file_path);
}
return ret;
}
bool music_player_worker_load_fmf_from_file(MusicPlayerWorker* instance, const char* file_path) {
furi_assert(instance);
furi_assert(file_path);
bool result = false;
string_t temp_str;
string_init(temp_str);
Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* file = flipper_format_file_alloc(storage);
do {
if(!flipper_format_file_open_existing(file, file_path)) break;
uint32_t version = 0;
if(!flipper_format_read_header(file, temp_str, &version)) break;
if(string_cmp_str(temp_str, MUSIC_PLAYER_FILETYPE) || (version != MUSIC_PLAYER_VERSION)) {
FURI_LOG_E(TAG, "Incorrect file format or version");
break;
}
if(!flipper_format_read_uint32(file, "BPM", &instance->bpm, 1)) {
FURI_LOG_E(TAG, "BPM is missing");
break;
}
if(!flipper_format_read_uint32(file, "Duration", &instance->duration, 1)) {
FURI_LOG_E(TAG, "Duration is missing");
break;
}
if(!flipper_format_read_uint32(file, "Octave", &instance->octave, 1)) {
FURI_LOG_E(TAG, "Octave is missing");
break;
}
if(!flipper_format_read_string(file, "Notes", temp_str)) {
FURI_LOG_E(TAG, "Notes is missing");
break;
}
if(!music_player_worker_parse_notes(instance, string_get_cstr(temp_str))) {
break;
}
result = true;
} while(false);
furi_record_close(RECORD_STORAGE);
flipper_format_free(file);
string_clear(temp_str);
return result;
}
bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const char* file_path) {
furi_assert(instance);
furi_assert(file_path);
bool result = false;
string_t content;
string_init(content);
Storage* storage = furi_record_open(RECORD_STORAGE);
File* file = storage_file_alloc(storage);
do {
if(!storage_file_open(file, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) {
FURI_LOG_E(TAG, "Unable to open file");
break;
};
uint16_t ret = 0;
do {
uint8_t buffer[65] = {0};
ret = storage_file_read(file, buffer, sizeof(buffer) - 1);
for(size_t i = 0; i < ret; i++) {
string_push_back(content, buffer[i]);
}
} while(ret > 0);
string_strim(content);
if(!string_size(content)) {
FURI_LOG_E(TAG, "Empty file");
break;
}
if(!music_player_worker_load_rtttl_from_string(instance, string_get_cstr(content))) {
FURI_LOG_E(TAG, "Invalid file content");
break;
}
result = true;
} while(0);
storage_file_free(file);
furi_record_close(RECORD_STORAGE);
string_clear(content);
return result;
}
bool music_player_worker_load_rtttl_from_string(MusicPlayerWorker* instance, const char* string) {
furi_assert(instance);
const char* cursor = string;
// Skip name
cursor += skip_till(cursor, ':');
if(*cursor != ':') {
return false;
}
// Duration
cursor += skip_till(cursor, '=');
if(*cursor != '=') {
return false;
}
cursor++;
cursor += extract_number(cursor, &instance->duration);
// Octave
cursor += skip_till(cursor, '=');
if(*cursor != '=') {
return false;
}
cursor++;
cursor += extract_number(cursor, &instance->octave);
// BPM
cursor += skip_till(cursor, '=');
if(*cursor != '=') {
return false;
}
cursor++;
cursor += extract_number(cursor, &instance->bpm);
// Notes
cursor += skip_till(cursor, ':');
if(*cursor != ':') {
return false;
}
cursor++;
if(!music_player_worker_parse_notes(instance, cursor)) {
return false;
}
return true;
}
void music_player_worker_set_callback(
MusicPlayerWorker* instance,
MusicPlayerWorkerCallback callback,
void* context) {
furi_assert(instance);
instance->callback = callback;
instance->callback_context = context;
}
void music_player_worker_set_volume(MusicPlayerWorker* instance, float volume) {
furi_assert(instance);
instance->volume = volume;
}
void music_player_worker_start(MusicPlayerWorker* instance) {
furi_assert(instance);
furi_assert(instance->should_work == false);
instance->should_work = true;
furi_thread_start(instance->thread);
}
void music_player_worker_stop(MusicPlayerWorker* instance) {
furi_assert(instance);
furi_assert(instance->should_work == true);
instance->should_work = false;
furi_thread_join(instance->thread);
}

View File

@@ -0,0 +1,44 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*MusicPlayerWorkerCallback)(
uint8_t semitone,
uint8_t dots,
uint8_t duration,
float position,
void* context);
typedef struct MusicPlayerWorker MusicPlayerWorker;
MusicPlayerWorker* music_player_worker_alloc();
void music_player_worker_free(MusicPlayerWorker* instance);
bool music_player_worker_load(MusicPlayerWorker* instance, const char* file_path);
bool music_player_worker_load_fmf_from_file(MusicPlayerWorker* instance, const char* file_path);
bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const char* file_path);
bool music_player_worker_load_rtttl_from_string(MusicPlayerWorker* instance, const char* string);
void music_player_worker_set_callback(
MusicPlayerWorker* instance,
MusicPlayerWorkerCallback callback,
void* context);
void music_player_worker_set_volume(MusicPlayerWorker* instance, float volume);
void music_player_worker_start(MusicPlayerWorker* instance);
void music_player_worker_stop(MusicPlayerWorker* instance);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,42 @@
#include "entities.h"
//extern "C"
/*Player create_player(double x, double y){
return {create_coords((double) x + (double)0.5, (double) y + (double)0.5), create_coords(1, 0), create_coords(0, -0.66), 0, 100, 0};
}*/
Player create_player(double x, double y) {
Player p;
p.pos = create_coords((double)x + (double)0.5, (double)y + (double)0.5);
p.dir = create_coords(1, 0);
p.plane = create_coords(0, -0.66);
p.velocity = 0;
p.health = 100;
p.keys = 0;
return p; //{create_coords((double) x + (double)0.5, (double) y + (double)0.5), create_coords(1, 0), create_coords(0, -0.66), 0, 100, 0};
}
//extern "C"
Entity
create_entity(uint8_t type, uint8_t x, uint8_t y, uint8_t initialState, uint8_t initialHealth) {
UID uid = create_uid(type, x, y);
Coords pos = create_coords((double)x + (double).5, (double)y + (double).5);
Entity new_entity; // = { uid, pos, initialState, initialHealth, 0, 0 };
new_entity.uid = uid;
new_entity.pos = pos;
new_entity.state = initialState;
new_entity.health = initialHealth;
new_entity.distance = 0;
new_entity.timer = 0;
return new_entity;
}
//extern "C"
StaticEntity crate_static_entity(UID uid, uint8_t x, uint8_t y, bool active) {
StaticEntity ent;
ent.uid = uid;
ent.x = x;
ent.y = y;
ent.active = active;
return ent;
}

View File

@@ -0,0 +1,56 @@
#ifndef _entities_h
#define _entities_h
#include <stdint.h>
#include <stdbool.h>
#include "types.h"
// Shortcuts
//#define create_player(x, y) {create_coords((double) x + (double)0.5, (double) y + (double)0.5), create_coords(1, 0), create_coords(0, -0.66), 0, 100}
#define create_enemy(x, y) create_entity(E_ENEMY, x, y, S_STAND, 50)
#define create_medikit(x, y) create_entity(E_MEDIKIT, x, y, S_STAND, 0)
#define create_key(x, y) create_entity(E_KEY, x, y, S_STAND, 0)
#define create_fireball(x, y, dir) create_entity(E_FIREBALL, x, y, S_STAND, dir)
#define create_door(x, y) create_entity(E_DOOR, x, y, S_STAND, 0)
// entity statuses
#define S_STAND 0
#define S_ALERT 1
#define S_FIRING 2
#define S_MELEE 3
#define S_HIT 4
#define S_DEAD 5
#define S_HIDDEN 6
#define S_OPEN 7
#define S_CLOSE 8
typedef struct Player {
Coords pos;
Coords dir;
Coords plane;
double velocity;
uint8_t health;
uint8_t keys;
} Player;
typedef struct Entity {
UID uid;
Coords pos;
uint8_t state;
uint8_t health; // angle for fireballs
uint8_t distance;
uint8_t timer;
} Entity;
typedef struct StaticEntity {
UID uid;
uint8_t x;
uint8_t y;
bool active;
} StaticEntity;
Entity
create_entity(uint8_t type, uint8_t x, uint8_t y, uint8_t initialState, uint8_t initialHealth);
StaticEntity create_static_entity(UID uid, uint8_t x, uint8_t y, bool active);
Player create_player(double x, double y);
#endif

View File

@@ -0,0 +1,188 @@
#ifndef _level_h
#define _level_h
#include "constants.h"
/*
Based on E1M1 from Wolfenstein 3D
################################################################
#############################...........########################
######....###################........E..########################
######....########..........#...........#...####################
######.....#######..........L.....E.......M.####################
######.....#######..........#...........#...####################
##################...########...........########################
######.........###...########...........########################
######.........###...#############D#############################
######.........#......E##########...############################
######....E....D...E...##########...############################
######.........#.......##########...############################
######....E....##################...############################
#...##.........##################...############################
#.K.######D######################...############################
#...#####...###############...#E.....K##########################
##D######...###############..####...############################
#...#####...###############..####...############################
#...#...#...###############..####...############################
#...D...#...#####################...############################
#...#...#...#####################...############################
#...######D#######################L#############################
#.E.##.........#################.....#################........##
#...##.........############...............############........##
#...##...E.....############...............############........##
#....#.........############...E.......E....#.........#........##
#....L....K....############................D....E....D....E...##
#....#.........############................#.........#........##
#...##.....E...############...............####....####........##
#...##.........############...............#####..#####.....M..##
#...##.........#################.....##########..#####........##
#...######L#######################D############..###############
#...#####...#####################...###########..###############
#E.E#####...#####################...###########..###############
#...#...#...#####################.E.###########..###############
#...D.M.#...#####################...###########..###############
#...#...#...#####################...###########..###.#.#.#.#####
#...#####...#####################...###########...#.........####
#...#####...#####################...###########...D....E..K.####
#................##......########...###########...#.........####
#....E........E...L...E...X######...################.#.#.#.#####
#................##......########...############################
#################################...############################
#############..#..#..#############L#############################
###########....#..#.########....#...#....#######################
#############.....##########.P..D...D....#######################
############################....#...#....#######################
##############..#################...############################
##############..############....#...#....#######################
############################....D...D....#######################
############################....#...#....#######################
#################################...############################
############################.............#######################
############################..........EK.#######################
############################.............#######################
################################################################
*/
/*
Same map above built from some regexp replacements using the legend above.
Using this way lets me use only 4 bit to store each block
*/
const uint8_t sto_level_1[LEVEL_SIZE] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00,
0x00, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00,
0x00, 0x20, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x2F, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x02, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x90, 0xFF, 0xFF, 0xFF, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xF2,
0x00, 0x00, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x4F, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0x40, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x20, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xF0, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xF0, 0x00, 0xFF, 0x00, 0x02, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xF0, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x20,
0x00, 0x00, 0x00, 0x20, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xF0, 0x00, 0x05, 0x00, 0x00, 0x90, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, 0x20, 0x00, 0xFF,
0xF0, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xF0, 0x00, 0xFF, 0x00, 0x00, 0x02, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xF0, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0x00, 0x00, 0x08, 0x00, 0xFF,
0xF0, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF2, 0x02, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0x40, 0x80, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x40, 0x00, 0x02, 0x00, 0x90, 0xFF, 0xFF,
0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xF0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x50, 0x00, 0x20, 0x00, 0x7F, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF,
0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x0F, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0xF0, 0x00, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00,
0x40, 0x00, 0x40, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0xF0, 0x00, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0xF0, 0x00, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x40, 0x00, 0x40, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0xF0, 0x00, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x29, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
#endif

View File

@@ -0,0 +1,35 @@
#ifndef sound_h
#define sound_h
#include <m-string.h>
#include <furi.h>
#include <furi_hal.h>
#include <stdint.h>
#include "doom_music_player_worker.h"
//static const char dspistol[] = "AnyConv:d=,o=,b=120:408,40p,40p,40p,40p,405,40p,40p,40p,405,30p.,30p.,30p.,13p";
static const char dsintro[] =
"Doom:d=32,o=4,b=56:f,f,f5,f,f,d#5,f,f,c#5,f,f,b,f,f,c5,c#5,f,f,f5,f,f,d#5,f,f,c#5,f,f,8b.,f,f,f5,f,f,d#5,f,f,c#5,f,f,b,f,f,c5,c#5,f,f,f5,f,f,d#5,f,f,c#5,f,f,8b.,a#,a#,a#5,a#,a#,g#5,a#,a#,f#5,a#,a#,e5,a#,a#,f5,f#5,a#,a#,a#5,a#,a#,g#5,a#,a#,f#5,a#,a#,8e5";
//static const char dsgetpow[] = "dsgetpow:d=,o=,b=120:407,40p,30.6,407,40p,406,40p,407,40p,40p,407,30p.,407";
//static const char dsnoway[] = "dsnoway:d=,o=,b=120:407,30.4";
#define MUSIC_PLAYER_SEMITONE_HISTORY_SIZE 4
static const float MUSIC_PLAYER_VOLUMES[] = {0, .25, .5, .75, 1};
typedef struct {
uint8_t semitone_history[MUSIC_PLAYER_SEMITONE_HISTORY_SIZE];
uint8_t duration_history[MUSIC_PLAYER_SEMITONE_HISTORY_SIZE];
uint8_t volume;
uint8_t semitone;
uint8_t dots;
uint8_t duration;
float position;
} MusicPlayerModel;
typedef struct {
MusicPlayerModel* model;
MusicPlayerWorker* worker;
FuriMutex** model_mutex;
} MusicPlayer;
#endif

View File

@@ -0,0 +1,33 @@
#include "types.h"
/*template <class T>
inline T sq(T value) {
return value * value;
}*/
double sq(double val) {
return val * val;
}
//extern "C"
Coords create_coords(double x, double y) {
Coords cord;
cord.x = x;
cord.y = y;
return cord;
}
//extern "C"
uint8_t coords_distance(Coords* a, Coords* b) {
return sqrt(sq(a->x - b->x) + sq(a->y - b->y)) * 20;
}
//extern "C"
UID create_uid(uint8_t type, uint8_t x, uint8_t y) {
return ((y << 6) | x) << 4 | type;
}
//extern "C"
uint8_t uid_get_type(UID uid) {
return uid & 0x0F;
}

View File

@@ -0,0 +1,36 @@
#ifndef _types_h
#define _types_h
#include <stdint.h>
#include <math.h>
//#include "constants.h"
#define UID_null 0
// Entity types (legend applies to level.h)
#define E_FLOOR 0x0 // . (also null)
#define E_WALL 0xF // #
#define E_PLAYER 0x1 // P
#define E_ENEMY 0x2 // E
#define E_DOOR 0x4 // D
#define E_LOCKEDDOOR 0x5 // L
#define E_EXIT 0x7 // X
// collectable entities >= 0x8
#define E_MEDIKIT 0x8 // M
#define E_KEY 0x9 // K
#define E_FIREBALL 0xA // not in map
typedef uint16_t UID;
typedef uint8_t EType;
typedef struct Coords {
double x;
double y;
} Coords;
UID create_uid(EType type, uint8_t x, uint8_t y);
EType uid_get_type(UID uid);
Coords create_coords(double x, double y);
uint8_t coords_distance(Coords* a, Coords* b);
#endif

View File

@@ -0,0 +1,12 @@
App(
appid="game_flappybird",
name="Flappy Bird",
apptype=FlipperAppType.PLUGIN,
entry_point="flappy_game_app",
cdefines=["APP_FLAPPY_GAME"],
requires=["gui"],
stack_size=4 * 1024,
order=100,
fap_icon="flappy_10px.png",
fap_category="Games",
)

View File

@@ -0,0 +1,54 @@
#include <furi.h>
uint8_t bird_array[3][15][11] = {
{
{0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0},
{0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0},
{0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0},
{0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1},
{1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1},
{1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1},
{1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0},
{1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0},
{0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0},
{0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0},
{0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0},
},
{
{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0},
{0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0},
{0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0},
{0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1},
{1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1},
{1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0},
{1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0},
{0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0},
{0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0},
{0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0},
},
{
{0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0},
{0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0},
{0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0},
{0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1},
{1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1},
{1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0},
{1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0},
{0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0},
{0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0},
{0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0},
}};

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -0,0 +1,357 @@
#include <furi.h>
#include <gui/gui.h>
#include <input/input.h>
#include <stdlib.h>
#include "bird.h"
#define TAG "Flappy"
#define DEBUG false
#define FLAPPY_BIRD_HEIGHT 15
#define FLAPPY_BIRD_WIDTH 10
#define FLAPPY_PILAR_MAX 6
#define FLAPPY_PILAR_DIST 40
#define FLAPPY_GAB_HEIGHT 25
#define FLAPPY_GAB_WIDTH 5
#define FLAPPY_GRAVITY_JUMP -1.1
#define FLAPPY_GRAVITY_TICK 0.15
#define FLIPPER_LCD_WIDTH 128
#define FLIPPER_LCD_HEIGHT 64
typedef enum {
EventTypeTick,
EventTypeKey,
} EventType;
typedef struct {
int x;
int y;
} POINT;
typedef struct {
float gravity;
POINT point;
} BIRD;
typedef struct {
POINT point;
int height;
int visible;
bool passed;
} PILAR;
typedef enum {
GameStateLife,
GameStateGameOver,
} State;
typedef struct {
BIRD bird;
int points;
int pilars_count;
PILAR pilars[FLAPPY_PILAR_MAX];
bool debug;
State state;
} GameState;
typedef struct {
EventType type;
InputEvent input;
} GameEvent;
typedef enum {
DirectionUp,
DirectionRight,
DirectionDown,
DirectionLeft,
} Direction;
static void flappy_game_random_pilar(GameState* const game_state) {
PILAR pilar;
pilar.passed = false;
pilar.visible = 1;
pilar.height = random() % (FLIPPER_LCD_HEIGHT - FLAPPY_GAB_HEIGHT) + 1;
pilar.point.y = 0;
pilar.point.x = FLIPPER_LCD_WIDTH + FLAPPY_GAB_WIDTH + 1;
game_state->pilars_count++;
game_state->pilars[game_state->pilars_count % FLAPPY_PILAR_MAX] = pilar;
}
static void flappy_game_state_init(GameState* const game_state) {
BIRD bird;
bird.gravity = 0.0f;
bird.point.x = 15;
bird.point.y = 32;
game_state->debug = DEBUG;
game_state->bird = bird;
game_state->pilars_count = 0;
game_state->points = 0;
game_state->state = GameStateLife;
memset(game_state->pilars, 0, sizeof(game_state->pilars));
flappy_game_random_pilar(game_state);
}
// static void flappy_game_reset(GameState* const game_state) {
// FURI_LOG_I(TAG, "Reset Game State\r\n"); // Resetting State
// }
static void flappy_game_tick(GameState* const game_state) {
if(game_state->state == GameStateLife) {
if(!game_state->debug) {
game_state->bird.gravity += FLAPPY_GRAVITY_TICK;
game_state->bird.point.y += game_state->bird.gravity;
}
// Checking the location of the last respawned pilar.
PILAR* pilar = &game_state->pilars[game_state->pilars_count % FLAPPY_PILAR_MAX];
if(pilar->point.x == (FLIPPER_LCD_WIDTH - FLAPPY_PILAR_DIST))
flappy_game_random_pilar(game_state);
// Updating the position/status of the pilars (visiblity, posotion, game points)
// | | | | |
// | | | | |
// |__| | |__|
// _____X | X_____
// | | | | | // [Pos + Width of pilar] >= [Bird Pos]
// |_____| | |_____|
// X <----> | X <->
// Bird Pos + Lenght of the bird] >= [Pilar]
for(int i = 0; i < FLAPPY_PILAR_MAX; i++) {
PILAR* pilar = &game_state->pilars[i];
if(pilar != NULL && pilar->visible && game_state->state == GameStateLife) {
pilar->point.x--;
if(game_state->bird.point.x >= pilar->point.x + FLAPPY_GAB_WIDTH &&
pilar->passed == false) {
pilar->passed = true;
game_state->points++;
}
if(pilar->point.x < -FLAPPY_GAB_WIDTH) pilar->visible = 0;
// Checking out of bounds
if(game_state->bird.point.y < 0 - FLAPPY_BIRD_WIDTH ||
game_state->bird.point.y > FLIPPER_LCD_HEIGHT) {
game_state->state = GameStateGameOver;
break;
}
// Bird inbetween pipes
if((game_state->bird.point.x + FLAPPY_BIRD_HEIGHT >= pilar->point.x) &&
(game_state->bird.point.x <= pilar->point.x + FLAPPY_GAB_WIDTH)) {
// Bird below Bottom Pipe
if(game_state->bird.point.y + FLAPPY_BIRD_WIDTH - 2 >=
pilar->height + FLAPPY_GAB_HEIGHT) {
game_state->state = GameStateGameOver;
break;
}
// Bird above Upper Pipe
if(game_state->bird.point.y < pilar->height) {
game_state->state = GameStateGameOver;
break;
}
}
}
}
}
}
static void flappy_game_flap(GameState* const game_state) {
game_state->bird.gravity = FLAPPY_GRAVITY_JUMP;
}
static void flappy_game_render_callback(Canvas* const canvas, void* ctx) {
const GameState* game_state = acquire_mutex((ValueMutex*)ctx, 25);
if(game_state == NULL) {
return;
}
canvas_draw_frame(canvas, 0, 0, 128, 64);
if(game_state->state == GameStateLife) {
// Pilars
for(int i = 0; i < FLAPPY_PILAR_MAX; i++) {
const PILAR* pilar = &game_state->pilars[i];
if(pilar != NULL && pilar->visible == 1) {
canvas_draw_frame(
canvas, pilar->point.x, pilar->point.y, FLAPPY_GAB_WIDTH, pilar->height);
canvas_draw_frame(
canvas,
pilar->point.x,
pilar->point.y + pilar->height + FLAPPY_GAB_HEIGHT,
FLAPPY_GAB_WIDTH,
FLIPPER_LCD_HEIGHT - pilar->height - FLAPPY_GAB_HEIGHT);
}
}
// Flappy
for(int h = 0; h < FLAPPY_BIRD_HEIGHT; h++) {
for(int w = 0; w < FLAPPY_BIRD_WIDTH; w++) {
// Switch animation
int bird = 0;
if(game_state->bird.gravity < -0.5)
bird = 1;
else
bird = 2;
// Draw bird pixels
if(bird_array[bird][h][w] == 1) {
int x = game_state->bird.point.x + h;
int y = game_state->bird.point.y + w;
canvas_draw_dot(canvas, x, y);
}
}
}
// Stats
canvas_set_font(canvas, FontSecondary);
char buffer[12];
snprintf(buffer, sizeof(buffer), "Score: %u", game_state->points);
canvas_draw_str_aligned(canvas, 100, 12, AlignCenter, AlignBottom, buffer);
if(game_state->debug) {
char coordinates[20];
snprintf(coordinates, sizeof(coordinates), "Y: %u", game_state->bird.point.y);
canvas_draw_str_aligned(canvas, 1, 12, AlignCenter, AlignBottom, coordinates);
}
}
if(game_state->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");
/*if(game_state->points != 0 && game_state->points % 5 == 0) {
DOLPHIN_DEED(getRandomDeed());
}*/
canvas_set_font(canvas, FontSecondary);
char buffer[12];
snprintf(buffer, sizeof(buffer), "Score: %u", game_state->points);
canvas_draw_str_aligned(canvas, 64, 41, AlignCenter, AlignBottom, buffer);
}
release_mutex((ValueMutex*)ctx, game_state);
}
static void flappy_game_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
furi_assert(event_queue);
GameEvent event = {.type = EventTypeKey, .input = *input_event};
furi_message_queue_put(event_queue, &event, FuriWaitForever);
}
static void flappy_game_update_timer_callback(FuriMessageQueue* event_queue) {
furi_assert(event_queue);
GameEvent event = {.type = EventTypeTick};
furi_message_queue_put(event_queue, &event, 0);
}
int32_t flappy_game_app(void* p) {
UNUSED(p);
int32_t return_code = 0;
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(GameEvent));
GameState* game_state = malloc(sizeof(GameState));
flappy_game_state_init(game_state);
ValueMutex state_mutex;
if(!init_mutex(&state_mutex, game_state, sizeof(GameState))) {
FURI_LOG_E(TAG, "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, flappy_game_render_callback, &state_mutex);
view_port_input_callback_set(view_port, flappy_game_input_callback, event_queue);
FuriTimer* timer =
furi_timer_alloc(flappy_game_update_timer_callback, FuriTimerTypePeriodic, event_queue);
furi_timer_start(timer, furi_kernel_get_tick_frequency() / 25);
// Open GUI and register view_port
Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
GameEvent event;
for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
GameState* game_state = (GameState*)acquire_mutex_block(&state_mutex);
if(event_status == FuriStatusOk) {
// press events
if(event.type == EventTypeKey) {
if(event.input.type == InputTypePress) {
switch(event.input.key) {
case InputKeyUp:
game_state->bird.point.y--;
break;
case InputKeyDown:
game_state->bird.point.y++;
break;
case InputKeyRight:
game_state->bird.point.x++;
break;
case InputKeyLeft:
game_state->bird.point.x--;
break;
case InputKeyOk:
if(game_state->state == GameStateGameOver) {
flappy_game_state_init(game_state);
}
if(game_state->state == GameStateLife) {
flappy_game_flap(game_state);
}
break;
case InputKeyBack:
processing = false;
break;
}
}
} else if(event.type == EventTypeTick) {
flappy_game_tick(game_state);
}
} else {
//FURI_LOG_D(TAG, "osMessageQueue: event timeout");
// event timeout
}
view_port_update(view_port);
release_mutex(&state_mutex, game_state);
}
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);
delete_mutex(&state_mutex);
free_and_exit:
free(game_state);
furi_message_queue_free(event_queue);
return return_code;
}

View File

@@ -10,7 +10,7 @@ App(
],
provides=["music_player_start"],
stack_size=2 * 1024,
order=20,
order=45,
fap_icon="../../../assets/icons/Archive/music_10px.png",
fap_category="Games",
)

View File

@@ -3,6 +3,10 @@
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*MusicPlayerWorkerCallback)(
uint8_t semitone,
uint8_t dots,
@@ -34,3 +38,7 @@ void music_player_worker_set_volume(MusicPlayerWorker* instance, float volume);
void music_player_worker_start(MusicPlayerWorker* instance);
void music_player_worker_stop(MusicPlayerWorker* instance);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,12 @@
App(
appid="game_zombiez",
name="Zombiez",
apptype=FlipperAppType.PLUGIN,
entry_point="zombiez_game_app",
cdefines=["APP_ZOMBIEZ_GAME"],
requires=["gui"],
stack_size=2 * 1024,
order=280,
fap_icon="zombie_10px.png",
fap_category="Games",
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -0,0 +1,400 @@
#include <furi.h>
#include <gui/gui.h>
#include <input/input.h>
#include <stdlib.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 {
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) {
const PluginState* plugin_state = acquire_mutex((ValueMutex*)ctx, 25);
if(plugin_state == NULL) {
return;
}
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_circle(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);
release_mutex((ValueMutex*)ctx, plugin_state);
}
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);
ValueMutex state_mutex;
if(!init_mutex(&state_mutex, plugin_state, sizeof(PluginState))) {
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, &state_mutex);
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);
PluginEvent event;
bool isRunning = true;
while(isRunning) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
PluginState* plugin_state = (PluginState*)acquire_mutex_block(&state_mutex);
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 -= 2;
}
break;
case InputKeyDown:
if(plugin_state->player.position.y < (MAX_Y - 1)) {
plugin_state->player.position.y += 2;
}
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);
}
} else {
// event timeout
}
view_port_update(view_port);
release_mutex(&state_mutex, plugin_state);
}
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);
delete_mutex(&state_mutex);
free_and_exit:
free(plugin_state);
furi_message_queue_free(event_queue);
return return_code;
}

View File

@@ -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},
},
};

View File

@@ -367,6 +367,23 @@ void canvas_draw_glyph(Canvas* canvas, uint8_t x, uint8_t y, uint16_t ch) {
u8g2_DrawGlyph(&canvas->fb, x, y, ch);
}
void canvas_draw_icon_bitmap(
Canvas* canvas,
uint8_t x,
uint8_t y,
int16_t w,
int16_t h,
const Icon* icon) {
furi_assert(canvas);
furi_assert(icon);
x += canvas->offset_x;
y += canvas->offset_y;
uint8_t* icon_data = NULL;
furi_hal_compress_icon_decode(icon_get_data(icon), &icon_data);
u8g2_DrawXBM(&canvas->fb, x, y, w, h, icon_data);
}
void canvas_set_bitmap_mode(Canvas* canvas, bool alpha) {
u8g2_SetBitmapMode(&canvas->fb, alpha ? 1 : 0);
}

View File

@@ -358,6 +358,14 @@ void canvas_draw_rbox(
uint8_t height,
uint8_t radius);
void canvas_draw_icon_bitmap(
Canvas* canvas,
uint8_t x,
uint8_t y,
int16_t w,
int16_t h,
const Icon* icon);
#ifdef __cplusplus
}
#endif

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,2.3,,
Version,+,3.0,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@@ -540,6 +540,7 @@ Function,+,canvas_draw_frame,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t"
Function,+,canvas_draw_glyph,void,"Canvas*, uint8_t, uint8_t, uint16_t"
Function,+,canvas_draw_icon,void,"Canvas*, uint8_t, uint8_t, const Icon*"
Function,+,canvas_draw_icon_animation,void,"Canvas*, uint8_t, uint8_t, IconAnimation*"
Function,+,canvas_draw_icon_bitmap,void,"Canvas*, uint8_t, uint8_t, int16_t, int16_t, const Icon*"
Function,+,canvas_draw_line,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t"
Function,+,canvas_draw_rbox,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t"
Function,+,canvas_draw_rframe,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t"
@@ -1479,7 +1480,7 @@ Function,-,isupper,int,int
Function,-,isupper_l,int,"int, locale_t"
Function,-,isxdigit,int,int
Function,-,isxdigit_l,int,"int, locale_t"
Function,-,itoa,char*,"int, char*, int"
Function,+,itoa,char*,"int, char*, int"
Function,-,j0,double,double
Function,-,j0f,float,float
Function,-,j1,double,double
1 entry status name type params
2 Version + 2.3 3.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
540 Function + canvas_draw_glyph void Canvas*, uint8_t, uint8_t, uint16_t
541 Function + canvas_draw_icon void Canvas*, uint8_t, uint8_t, const Icon*
542 Function + canvas_draw_icon_animation void Canvas*, uint8_t, uint8_t, IconAnimation*
543 Function + canvas_draw_icon_bitmap void Canvas*, uint8_t, uint8_t, int16_t, int16_t, const Icon*
544 Function + canvas_draw_line void Canvas*, uint8_t, uint8_t, uint8_t, uint8_t
545 Function + canvas_draw_rbox void Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t
546 Function + canvas_draw_rframe void Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t
1480 Function - isupper_l int int, locale_t
1481 Function - isxdigit int int
1482 Function - isxdigit_l int int, locale_t
1483 Function - + itoa char* int, char*, int
1484 Function - j0 double double
1485 Function - j0f float float
1486 Function - j1 double double

View File

@@ -19,7 +19,6 @@ class FlipperAppType(Enum):
STARTUP = "StartupHook"
EXTERNAL = "External"
METAPACKAGE = "Package"
GAME = "Game"
@dataclass