|
|
@@ -1,6 +1,9 @@
|
|
|
#include <furi.h>
|
|
|
+#include <flipper_format/flipper_format.h>
|
|
|
+#include <notification/notification.h>
|
|
|
#include <cstring>
|
|
|
#include "pinball0.h"
|
|
|
+#include "notifications.h"
|
|
|
|
|
|
/* generated by fbt from .png files in images folder */
|
|
|
#include <pinball0_icons.h>
|
|
|
@@ -13,18 +16,98 @@
|
|
|
#define GAME_FPS 30
|
|
|
#define TABLE_BUMP_AMOUNT 0.3l
|
|
|
|
|
|
-#define MANUAL_MODE true
|
|
|
#define MANUAL_ADJUSTMENT 20
|
|
|
|
|
|
-// Sound definitions
|
|
|
-// static const NotificationSequence ns_short_sound = {
|
|
|
-// &message_note_c5,
|
|
|
-// &message_delay_50,
|
|
|
-// &message_sound_off,
|
|
|
-// NULL,
|
|
|
-// };
|
|
|
+#define PINBALL_SETTINGS_FILENAME ".pinball0.conf"
|
|
|
+#define PINBALL_SETTINGS_PATH APP_DATA_PATH(PINBALL_SETTINGS_FILENAME)
|
|
|
+#define PINBALL_SETTINGS_FILE_TYPE "Pinball0 Settings File"
|
|
|
+#define PINBALL_SETTINGS_FILE_VERSION 1
|
|
|
+
|
|
|
+void pinball_load_settings(PinballApp* pb) {
|
|
|
+ FlipperFormat* fff_settings = flipper_format_file_alloc(pb->storage);
|
|
|
+ FuriString* tmp_str = furi_string_alloc();
|
|
|
+ uint32_t tmp_data32 = 0;
|
|
|
+
|
|
|
+ // init the settings to default values, then overwrite them if
|
|
|
+ // they appear in the settings file
|
|
|
+ pb->settings.sound_enabled = true;
|
|
|
+ pb->settings.led_enabled = false;
|
|
|
+ pb->settings.vibrate_enabled = false;
|
|
|
+ pb->settings.manual_mode = true;
|
|
|
+ pb->selected_setting = 0;
|
|
|
+ pb->max_settings = 4;
|
|
|
+
|
|
|
+ do {
|
|
|
+ if(!flipper_format_file_open_existing(fff_settings, PINBALL_SETTINGS_PATH)) {
|
|
|
+ FURI_LOG_I(TAG, "SETTINGS: File not found, using defaults");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if(!flipper_format_read_header(fff_settings, tmp_str, &tmp_data32)) {
|
|
|
+ FURI_LOG_E(TAG, "SETTINGS: Missing or incorrect header");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ // do settings file version here? eh..
|
|
|
+ if(flipper_format_read_uint32(fff_settings, "Sound", &tmp_data32, 1)) {
|
|
|
+ pb->settings.sound_enabled = (tmp_data32 == 0) ? false : true;
|
|
|
+ }
|
|
|
+ if(flipper_format_read_uint32(fff_settings, "LED", &tmp_data32, 1)) {
|
|
|
+ pb->settings.led_enabled = (tmp_data32 == 0) ? false : true;
|
|
|
+ }
|
|
|
+ if(flipper_format_read_uint32(fff_settings, "Vibrate", &tmp_data32, 1)) {
|
|
|
+ pb->settings.vibrate_enabled = (tmp_data32 == 0) ? false : true;
|
|
|
+ }
|
|
|
+ if(flipper_format_read_uint32(fff_settings, "Manual", &tmp_data32, 1)) {
|
|
|
+ pb->settings.manual_mode = (tmp_data32 == 0) ? false : true;
|
|
|
+ }
|
|
|
+
|
|
|
+ } while(false);
|
|
|
+
|
|
|
+ furi_string_free(tmp_str);
|
|
|
+ flipper_format_free(fff_settings);
|
|
|
+}
|
|
|
+
|
|
|
+void pinball_save_settings(PinballApp* pb) {
|
|
|
+ FlipperFormat* fff_settings = flipper_format_file_alloc(pb->storage);
|
|
|
+ uint32_t tmp_data32 = 0;
|
|
|
+ FURI_LOG_I(TAG, "SETTINGS: Saving settings");
|
|
|
+ do {
|
|
|
+ if(!flipper_format_file_open_always(fff_settings, PINBALL_SETTINGS_PATH)) {
|
|
|
+ FURI_LOG_E(TAG, "SETTINGS: Unable to open file for save!");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if(!flipper_format_write_header_cstr(
|
|
|
+ fff_settings, PINBALL_SETTINGS_FILE_TYPE, PINBALL_SETTINGS_FILE_VERSION)) {
|
|
|
+ FURI_LOG_E(TAG, "SETTINGS: Failed writing file type and version");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ // now write out our settings data
|
|
|
+ tmp_data32 = pb->settings.sound_enabled ? 1 : 0;
|
|
|
+ if(!flipper_format_write_uint32(fff_settings, "Sound", &tmp_data32, 1)) {
|
|
|
+ FURI_LOG_E(TAG, "SETTINGS: Failed to write 'Sound'");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ tmp_data32 = pb->settings.led_enabled ? 1 : 0;
|
|
|
+ if(!flipper_format_write_uint32(fff_settings, "LED", &tmp_data32, 1)) {
|
|
|
+ FURI_LOG_E(TAG, "SETTINGS: Failed to write 'LED'");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ tmp_data32 = pb->settings.vibrate_enabled ? 1 : 0;
|
|
|
+ if(!flipper_format_write_uint32(fff_settings, "Vibrate", &tmp_data32, 1)) {
|
|
|
+ FURI_LOG_E(TAG, "SETTINGS: Failed to write 'Vibrate'");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ tmp_data32 = pb->settings.manual_mode ? 1 : 0;
|
|
|
+ if(!flipper_format_write_uint32(fff_settings, "Manual", &tmp_data32, 1)) {
|
|
|
+ FURI_LOG_E(TAG, "SETTINGS: Failed to write 'Manual'");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } while(false);
|
|
|
+
|
|
|
+ flipper_format_file_close(fff_settings);
|
|
|
+ flipper_format_free(fff_settings);
|
|
|
+}
|
|
|
|
|
|
-void solve(PinballState* pb, float dt) {
|
|
|
+void solve(PinballApp* pb, float dt) {
|
|
|
Table* table = pb->table;
|
|
|
|
|
|
float sub_dt = dt / PHYSICS_SUB_STEPS;
|
|
|
@@ -125,7 +208,7 @@ void solve(PinballState* pb, float dt) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void pinball_state_init(PinballState* pb) {
|
|
|
+void pinball_app_init(PinballApp* pb) {
|
|
|
furi_assert(pb);
|
|
|
pb->storage = (Storage*)furi_record_open(RECORD_STORAGE);
|
|
|
pb->notify = (NotificationApp*)furi_record_open(RECORD_NOTIFICATION);
|
|
|
@@ -139,15 +222,17 @@ void pinball_state_init(PinballState* pb) {
|
|
|
pb->keys[InputKeyDown] = false;
|
|
|
pb->keys[InputKeyRight] = false;
|
|
|
pb->keys[InputKeyLeft] = false;
|
|
|
-}
|
|
|
|
|
|
-int modulo(int a, int b) {
|
|
|
- return (a % b + b) % b;
|
|
|
+ pinball_load_settings(pb);
|
|
|
}
|
|
|
|
|
|
+// int modulo(int a, int b) {
|
|
|
+// return (a % b + b) % b;
|
|
|
+// }
|
|
|
+
|
|
|
static void pinball_draw_callback(Canvas* const canvas, void* ctx) {
|
|
|
furi_assert(ctx);
|
|
|
- PinballState* pb = (PinballState*)ctx;
|
|
|
+ PinballApp* pb = (PinballApp*)ctx;
|
|
|
furi_mutex_acquire(pb->mutex, FuriWaitForever);
|
|
|
|
|
|
// What are we drawing? table select / menu or the actual game?
|
|
|
@@ -158,9 +243,9 @@ static void pinball_draw_callback(Canvas* const canvas, void* ctx) {
|
|
|
// and the currently selected item is always in the middle, surrounded by pinballs
|
|
|
const TableList& list = pb->table_list;
|
|
|
int32_t y = 25;
|
|
|
- size_t half_way = list.display_size / 2;
|
|
|
+ auto half_way = list.display_size / 2;
|
|
|
|
|
|
- for(size_t i = 0; i < list.display_size; i++) {
|
|
|
+ for(auto i = 0; i < list.display_size; i++) {
|
|
|
int index =
|
|
|
(list.selected - half_way + i + list.menu_items.size()) % list.menu_items.size();
|
|
|
const auto& menu_item = list.menu_items[index];
|
|
|
@@ -236,6 +321,53 @@ static void pinball_draw_callback(Canvas* const canvas, void* ctx) {
|
|
|
|
|
|
pb->table->draw(canvas);
|
|
|
} break;
|
|
|
+ case GM_Settings: {
|
|
|
+ canvas_draw_str_aligned(canvas, 2, 10, AlignLeft, AlignTop, "SETTINGS");
|
|
|
+
|
|
|
+ int x = 55;
|
|
|
+ int y = 30;
|
|
|
+
|
|
|
+ canvas_draw_str_aligned(canvas, 10, y, AlignLeft, AlignTop, "Sound");
|
|
|
+ canvas_draw_circle(canvas, x, y + 3, 4);
|
|
|
+ if(pb->settings.sound_enabled) {
|
|
|
+ canvas_draw_disc(canvas, x, y + 3, 2);
|
|
|
+ }
|
|
|
+ if(pb->selected_setting == 0) {
|
|
|
+ canvas_draw_triangle(canvas, 2, y + 3, 8, 5, CanvasDirectionLeftToRight);
|
|
|
+ }
|
|
|
+ y += 12;
|
|
|
+
|
|
|
+ canvas_draw_str_aligned(canvas, 10, y, AlignLeft, AlignTop, "LED");
|
|
|
+ canvas_draw_circle(canvas, x, y + 3, 4);
|
|
|
+ if(pb->settings.led_enabled) {
|
|
|
+ canvas_draw_disc(canvas, x, y + 3, 2);
|
|
|
+ }
|
|
|
+ if(pb->selected_setting == 1) {
|
|
|
+ canvas_draw_triangle(canvas, 2, y + 3, 8, 5, CanvasDirectionLeftToRight);
|
|
|
+ }
|
|
|
+ y += 12;
|
|
|
+
|
|
|
+ canvas_draw_str_aligned(canvas, 10, y, AlignLeft, AlignTop, "Vibrate");
|
|
|
+ canvas_draw_circle(canvas, x, y + 3, 4);
|
|
|
+ if(pb->settings.vibrate_enabled) {
|
|
|
+ canvas_draw_disc(canvas, x, y + 3, 2);
|
|
|
+ }
|
|
|
+ if(pb->selected_setting == 2) {
|
|
|
+ canvas_draw_triangle(canvas, 2, y + 3, 8, 5, CanvasDirectionLeftToRight);
|
|
|
+ }
|
|
|
+ y += 12;
|
|
|
+
|
|
|
+ canvas_draw_str_aligned(canvas, 10, y, AlignLeft, AlignTop, "Manual");
|
|
|
+ canvas_draw_circle(canvas, x, y + 3, 4);
|
|
|
+ if(pb->settings.manual_mode) {
|
|
|
+ canvas_draw_disc(canvas, x, y + 3, 2);
|
|
|
+ }
|
|
|
+ if(pb->selected_setting == 3) {
|
|
|
+ canvas_draw_triangle(canvas, 2, y + 3, 8, 5, CanvasDirectionLeftToRight);
|
|
|
+ }
|
|
|
+
|
|
|
+ pb->table->draw(canvas);
|
|
|
+ } break;
|
|
|
default:
|
|
|
FURI_LOG_E(TAG, "Unknown Game Mode");
|
|
|
break;
|
|
|
@@ -254,49 +386,49 @@ static void pinball_input_callback(InputEvent* input_event, void* ctx) {
|
|
|
extern "C" int32_t pinball0_app(void* p) {
|
|
|
UNUSED(p);
|
|
|
|
|
|
- PinballState* pinball_state = (PinballState*)malloc(sizeof(PinballState));
|
|
|
- pinball_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
|
|
- if(!pinball_state->mutex) {
|
|
|
+ PinballApp* app = (PinballApp*)malloc(sizeof(PinballApp));
|
|
|
+ app->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
|
|
+ if(!app->mutex) {
|
|
|
FURI_LOG_E(TAG, "Cannot create mutex!");
|
|
|
- free(pinball_state);
|
|
|
+ free(app);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- pinball_state_init(pinball_state);
|
|
|
+ pinball_app_init(app);
|
|
|
|
|
|
// read the list of tables from storage
|
|
|
- table_table_list_init(pinball_state);
|
|
|
+ table_table_list_init(app);
|
|
|
|
|
|
// load the table select table
|
|
|
- table_load_table(pinball_state, 0);
|
|
|
+ table_load_table(app, 0);
|
|
|
|
|
|
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PinballEvent));
|
|
|
furi_timer_set_thread_priority(FuriTimerThreadPriorityElevated);
|
|
|
|
|
|
ViewPort* view_port = view_port_alloc();
|
|
|
view_port_set_orientation(view_port, ViewPortOrientationVertical);
|
|
|
- view_port_draw_callback_set(view_port, pinball_draw_callback, pinball_state);
|
|
|
+ view_port_draw_callback_set(view_port, pinball_draw_callback, app);
|
|
|
view_port_input_callback_set(view_port, pinball_input_callback, event_queue);
|
|
|
|
|
|
// Open the GUI and register view_port
|
|
|
Gui* gui = (Gui*)furi_record_open(RECORD_GUI);
|
|
|
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
|
|
|
|
|
- notification_message(pinball_state->notify, &sequence_display_backlight_enforce_on);
|
|
|
+ notification_message(app->notify, &sequence_display_backlight_enforce_on);
|
|
|
|
|
|
// dolphin_deed(DolphinDeedPluginGameStart);
|
|
|
|
|
|
- pinball_state->processing = true;
|
|
|
+ app->processing = true;
|
|
|
|
|
|
float dt = 0.0f;
|
|
|
uint32_t last_frame_time = furi_get_tick();
|
|
|
|
|
|
FURI_LOG_I(TAG, "Starting event loop");
|
|
|
PinballEvent event;
|
|
|
- while(pinball_state->processing) {
|
|
|
+ while(app->processing) {
|
|
|
FuriStatus event_status =
|
|
|
furi_message_queue_get(event_queue, &event, 10); // TODO best rate?
|
|
|
- furi_mutex_acquire(pinball_state->mutex, FuriWaitForever);
|
|
|
+ furi_mutex_acquire(app->mutex, FuriWaitForever);
|
|
|
|
|
|
if(event_status == FuriStatusOk) {
|
|
|
if(event.type == EventTypeKey) {
|
|
|
@@ -304,87 +436,135 @@ extern "C" int32_t pinball0_app(void* p) {
|
|
|
event.input.type == InputTypeRepeat) {
|
|
|
switch(event.input.key) {
|
|
|
case InputKeyBack:
|
|
|
- if(pinball_state->game_mode == GM_Playing ||
|
|
|
- pinball_state->game_mode == GM_GameOver ||
|
|
|
- pinball_state->game_mode == GM_Error) {
|
|
|
- pinball_state->game_mode = GM_TableSelect;
|
|
|
- table_load_table(pinball_state, TABLE_SELECT);
|
|
|
- } else if(pinball_state->game_mode == GM_TableSelect) {
|
|
|
- pinball_state->processing = false;
|
|
|
+ if(app->game_mode == GM_Playing || app->game_mode == GM_GameOver ||
|
|
|
+ app->game_mode == GM_Error || app->game_mode == GM_Settings) {
|
|
|
+ if(app->game_mode == GM_Settings) {
|
|
|
+ pinball_save_settings(app);
|
|
|
+ }
|
|
|
+ app->game_mode = GM_TableSelect;
|
|
|
+ table_load_table(app, TABLE_SELECT);
|
|
|
+ } else if(app->game_mode == GM_TableSelect) {
|
|
|
+ app->processing = false;
|
|
|
}
|
|
|
break;
|
|
|
case InputKeyRight:
|
|
|
- pinball_state->keys[InputKeyRight] = true;
|
|
|
- // temp
|
|
|
- if(MANUAL_MODE && pinball_state->table->balls_released == false) {
|
|
|
- pinball_state->table->balls[0].p.x += MANUAL_ADJUSTMENT;
|
|
|
- pinball_state->table->balls[0].prev_p.x += MANUAL_ADJUSTMENT;
|
|
|
+ app->keys[InputKeyRight] = true;
|
|
|
+
|
|
|
+ if(app->settings.manual_mode && app->table->balls_released == false) {
|
|
|
+ app->table->balls[0].p.x += MANUAL_ADJUSTMENT;
|
|
|
+ app->table->balls[0].prev_p.x += MANUAL_ADJUSTMENT;
|
|
|
}
|
|
|
- for(auto& f : pinball_state->table->flippers) {
|
|
|
+ for(auto& f : app->table->flippers) {
|
|
|
if(f.side == Flipper::RIGHT) {
|
|
|
f.powered = true;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case InputKeyLeft:
|
|
|
- // FURI_LOG_I(TAG, "LEFT on");
|
|
|
- pinball_state->keys[InputKeyLeft] = true;
|
|
|
- // temp
|
|
|
- if(MANUAL_MODE && pinball_state->table->balls_released == false) {
|
|
|
- pinball_state->table->balls[0].p.x -= MANUAL_ADJUSTMENT;
|
|
|
- pinball_state->table->balls[0].prev_p.x -= MANUAL_ADJUSTMENT;
|
|
|
+ app->keys[InputKeyLeft] = true;
|
|
|
+
|
|
|
+ if(app->settings.manual_mode && app->table->balls_released == false) {
|
|
|
+ app->table->balls[0].p.x -= MANUAL_ADJUSTMENT;
|
|
|
+ app->table->balls[0].prev_p.x -= MANUAL_ADJUSTMENT;
|
|
|
}
|
|
|
- for(auto& f : pinball_state->table->flippers) {
|
|
|
+ for(auto& f : app->table->flippers) {
|
|
|
if(f.side == Flipper::LEFT) {
|
|
|
f.powered = true;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
- case InputKeyUp: // bump table
|
|
|
- if(pinball_state->game_mode == GM_Playing) {
|
|
|
+ case InputKeyUp:
|
|
|
+ switch(app->game_mode) {
|
|
|
+ case GM_Playing:
|
|
|
if(event.input.type == InputTypePress) {
|
|
|
- pinball_state->keys[InputKeyUp] = true;
|
|
|
+ // we only set the key if it's a 'press' to ensure
|
|
|
+ // a single table "bump"
|
|
|
+ app->keys[InputKeyUp] = true;
|
|
|
+ notify_table_bump(app);
|
|
|
}
|
|
|
- } else if(pinball_state->game_mode == GM_TableSelect) {
|
|
|
- pinball_state->table_list.selected =
|
|
|
- (pinball_state->table_list.selected - 1 +
|
|
|
- pinball_state->table_list.menu_items.size()) %
|
|
|
- pinball_state->table_list.menu_items.size();
|
|
|
- }
|
|
|
- // temp
|
|
|
- if(MANUAL_MODE && pinball_state->table->balls_released == false) {
|
|
|
- pinball_state->table->balls[0].p.y -= MANUAL_ADJUSTMENT;
|
|
|
- pinball_state->table->balls[0].prev_p.y -= MANUAL_ADJUSTMENT;
|
|
|
+ if(app->settings.manual_mode && app->table->balls_released == false) {
|
|
|
+ app->table->balls[0].p.y -= MANUAL_ADJUSTMENT;
|
|
|
+ app->table->balls[0].prev_p.y -= MANUAL_ADJUSTMENT;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case GM_TableSelect:
|
|
|
+ app->table_list.selected = (app->table_list.selected - 1 +
|
|
|
+ app->table_list.menu_items.size()) %
|
|
|
+ app->table_list.menu_items.size();
|
|
|
+ break;
|
|
|
+ case GM_Settings:
|
|
|
+ if(app->selected_setting > 0) {
|
|
|
+ app->selected_setting--;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
}
|
|
|
break;
|
|
|
case InputKeyDown:
|
|
|
- if(pinball_state->game_mode == GM_Playing) {
|
|
|
- pinball_state->keys[InputKeyDown] = true;
|
|
|
- } else if(pinball_state->game_mode == GM_TableSelect) {
|
|
|
- pinball_state->table_list.selected =
|
|
|
- (pinball_state->table_list.selected + 1) %
|
|
|
- pinball_state->table_list.menu_items.size();
|
|
|
- }
|
|
|
- // temp
|
|
|
- if(MANUAL_MODE && pinball_state->table->balls_released == false) {
|
|
|
- pinball_state->table->balls[0].p.y += MANUAL_ADJUSTMENT;
|
|
|
- pinball_state->table->balls[0].prev_p.y += MANUAL_ADJUSTMENT;
|
|
|
+ switch(app->game_mode) {
|
|
|
+ case GM_Playing:
|
|
|
+ app->keys[InputKeyDown] = true;
|
|
|
+ if(app->settings.manual_mode && app->table->balls_released == false) {
|
|
|
+ app->table->balls[0].p.y += MANUAL_ADJUSTMENT;
|
|
|
+ app->table->balls[0].prev_p.y += MANUAL_ADJUSTMENT;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case GM_TableSelect:
|
|
|
+ app->table_list.selected = (app->table_list.selected + 1 +
|
|
|
+ app->table_list.menu_items.size()) %
|
|
|
+ app->table_list.menu_items.size();
|
|
|
+ break;
|
|
|
+ case GM_Settings:
|
|
|
+ if(app->selected_setting < app->max_settings - 1) {
|
|
|
+ app->selected_setting++;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
}
|
|
|
break;
|
|
|
case InputKeyOk:
|
|
|
- if(pinball_state->game_mode == GM_Playing) {
|
|
|
- if(!pinball_state->table->balls_released) {
|
|
|
- pinball_state->gameStarted = true;
|
|
|
- pinball_state->table->balls_released = true;
|
|
|
+ switch(app->game_mode) {
|
|
|
+ case GM_Playing:
|
|
|
+ if(!app->table->balls_released) {
|
|
|
+ app->gameStarted = true;
|
|
|
+ app->table->balls_released = true;
|
|
|
}
|
|
|
- } else if(pinball_state->game_mode == GM_TableSelect) {
|
|
|
- size_t sel = pinball_state->table_list.selected;
|
|
|
- if(!table_load_table(pinball_state, sel + TABLE_INDEX_OFFSET)) {
|
|
|
- pinball_state->game_mode = GM_Error;
|
|
|
- table_load_table(pinball_state, TABLE_ERROR);
|
|
|
+ break;
|
|
|
+ case GM_TableSelect: {
|
|
|
+ size_t sel = app->table_list.selected;
|
|
|
+ if(sel == app->table_list.menu_items.size() - 1) {
|
|
|
+ app->game_mode = GM_Settings;
|
|
|
+ table_load_table(app, TABLE_SETTINGS);
|
|
|
+ } else if(!table_load_table(app, sel + TABLE_INDEX_OFFSET)) {
|
|
|
+ app->game_mode = GM_Error;
|
|
|
+ table_load_table(app, TABLE_ERROR);
|
|
|
+ notify_error_message(app);
|
|
|
} else {
|
|
|
- pinball_state->game_mode = GM_Playing;
|
|
|
+ app->game_mode = GM_Playing;
|
|
|
+ }
|
|
|
+ } break;
|
|
|
+ case GM_Settings:
|
|
|
+ switch(app->selected_setting) {
|
|
|
+ case 0:
|
|
|
+ app->settings.sound_enabled = !app->settings.sound_enabled;
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ app->settings.led_enabled = !app->settings.led_enabled;
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ app->settings.vibrate_enabled = !app->settings.vibrate_enabled;
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ app->settings.manual_mode = !app->settings.manual_mode;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
}
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
|
@@ -393,8 +573,8 @@ extern "C" int32_t pinball0_app(void* p) {
|
|
|
} else if(event.input.type == InputTypeRelease) {
|
|
|
switch(event.input.key) {
|
|
|
case InputKeyLeft: {
|
|
|
- pinball_state->keys[InputKeyLeft] = false;
|
|
|
- for(auto& f : pinball_state->table->flippers) {
|
|
|
+ app->keys[InputKeyLeft] = false;
|
|
|
+ for(auto& f : app->table->flippers) {
|
|
|
if(f.side == Flipper::LEFT) {
|
|
|
f.powered = false;
|
|
|
}
|
|
|
@@ -402,8 +582,8 @@ extern "C" int32_t pinball0_app(void* p) {
|
|
|
break;
|
|
|
}
|
|
|
case InputKeyRight: {
|
|
|
- pinball_state->keys[InputKeyRight] = false;
|
|
|
- for(auto& f : pinball_state->table->flippers) {
|
|
|
+ app->keys[InputKeyRight] = false;
|
|
|
+ for(auto& f : app->table->flippers) {
|
|
|
if(f.side == Flipper::RIGHT) {
|
|
|
f.powered = false;
|
|
|
}
|
|
|
@@ -411,10 +591,10 @@ extern "C" int32_t pinball0_app(void* p) {
|
|
|
break;
|
|
|
}
|
|
|
case InputKeyUp:
|
|
|
- pinball_state->keys[InputKeyUp] = false;
|
|
|
+ app->keys[InputKeyUp] = false;
|
|
|
break;
|
|
|
case InputKeyDown:
|
|
|
- pinball_state->keys[InputKeyDown] = false;
|
|
|
+ app->keys[InputKeyDown] = false;
|
|
|
// TODO: release plunger?
|
|
|
break;
|
|
|
default:
|
|
|
@@ -423,19 +603,19 @@ extern "C" int32_t pinball0_app(void* p) {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- solve(pinball_state, dt);
|
|
|
- for(auto& o : pinball_state->table->objects) {
|
|
|
+ solve(app, dt);
|
|
|
+ for(auto& o : app->table->objects) {
|
|
|
o->step_animation();
|
|
|
}
|
|
|
// check game state
|
|
|
- if(pinball_state->game_mode == GM_Playing && pinball_state->table->num_lives == 0) {
|
|
|
+ if(app->game_mode == GM_Playing && app->table->num_lives == 0) {
|
|
|
FURI_LOG_W(TAG, "GAME OVER!");
|
|
|
- pinball_state->game_mode = GM_GameOver;
|
|
|
+ app->game_mode = GM_GameOver;
|
|
|
}
|
|
|
|
|
|
// no keys pressed - we should clear all input keys?
|
|
|
view_port_update(view_port);
|
|
|
- furi_mutex_release(pinball_state->mutex);
|
|
|
+ furi_mutex_release(app->mutex);
|
|
|
|
|
|
// game timing
|
|
|
uint32_t time_lapsed = furi_get_tick() - last_frame_time;
|
|
|
@@ -444,12 +624,12 @@ extern "C" int32_t pinball0_app(void* p) {
|
|
|
time_lapsed = furi_get_tick() - last_frame_time;
|
|
|
dt = time_lapsed / 1000.0f;
|
|
|
}
|
|
|
- pinball_state->tick++;
|
|
|
+ app->tick++;
|
|
|
last_frame_time = furi_get_tick();
|
|
|
}
|
|
|
|
|
|
// general cleanup
|
|
|
- notification_message(pinball_state->notify, &sequence_display_backlight_enforce_auto);
|
|
|
+ notification_message(app->notify, &sequence_display_backlight_enforce_auto);
|
|
|
|
|
|
view_port_enabled_set(view_port, false);
|
|
|
gui_remove_view_port(gui, view_port);
|
|
|
@@ -459,10 +639,10 @@ extern "C" int32_t pinball0_app(void* p) {
|
|
|
view_port_free(view_port);
|
|
|
furi_message_queue_free(event_queue);
|
|
|
|
|
|
- furi_mutex_free(pinball_state->mutex);
|
|
|
+ furi_mutex_free(app->mutex);
|
|
|
|
|
|
- delete pinball_state->table;
|
|
|
- free(pinball_state);
|
|
|
+ delete app->table;
|
|
|
+ free(app);
|
|
|
|
|
|
furi_timer_set_thread_priority(FuriTimerThreadPriorityNormal);
|
|
|
return 0;
|