summaryrefslogtreecommitdiffhomepage
path: root/samples
diff options
context:
space:
mode:
Diffstat (limited to 'samples')
-rw-r--r--samples/00_learn_ruby_optional/00_intermediate_ruby_primer/app/repl.rb0
-rw-r--r--samples/01_rendering_basics/01_labels/app/main.rb4
-rw-r--r--samples/01_rendering_basics/03_solids_borders/app/main.rb2
-rw-r--r--samples/01_rendering_basics/05_sounds/app/main.rb163
-rw-r--r--samples/01_rendering_basics/06_audio_mixer/app/main.rb160
-rw-r--r--samples/01_rendering_basics/07_sound_synthesis/sprites/square-black.pngbin250 -> 0 bytes
-rw-r--r--samples/02_input_basics/01_keyboard/app/main.rb51
-rw-r--r--samples/02_input_basics/01_moving_a_sprite/app/main.rb30
-rw-r--r--samples/02_input_basics/01_moving_a_sprite/license-for-sample.txt (renamed from samples/01_rendering_basics/06_audio_mixer/license-for-sample.txt)0
-rw-r--r--samples/02_input_basics/01_moving_a_sprite/replay.txt73
-rw-r--r--samples/02_input_basics/01_moving_a_sprite/sprites/square/green.png (renamed from samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-green.png)bin283 -> 283 bytes
-rw-r--r--samples/02_input_basics/02_mouse/app/main.rb14
-rw-r--r--samples/02_input_basics/03_mouse_point_to_rect/app/main.rb14
-rw-r--r--samples/02_input_basics/04_mouse_rect_to_rect/app/main.rb18
-rw-r--r--samples/02_input_basics/05_controller/app/main.rb68
-rw-r--r--samples/02_input_basics/06_touch/app/main.rb11
-rw-r--r--samples/03_rendering_sprites/01_animation_using_separate_pngs/app/main.rb15
-rw-r--r--samples/03_rendering_sprites/02_animation_using_sprite_sheet/replay.txt241
-rw-r--r--samples/03_rendering_sprites/03_animation_states/replay.txt182
-rw-r--r--samples/03_rendering_sprites/04_color_and_rotation/app/main.rb4
-rw-r--r--samples/04_physics_and_collisions/02_moving_objects/app/main.rb2
-rw-r--r--samples/04_physics_and_collisions/06_box_collision_3/app/main.rb20
-rw-r--r--samples/04_physics_and_collisions/06_box_collision_3/replay.txt687
-rw-r--r--samples/04_physics_and_collisions/06_jump_physics/app/main.rb195
-rw-r--r--samples/04_physics_and_collisions/06_jump_physics/replay.txt124
-rw-r--r--samples/04_physics_and_collisions/07_jump_physics/app/main.rb11
-rw-r--r--samples/04_physics_and_collisions/08_bouncing_on_collision/app/block.rb20
-rw-r--r--samples/04_physics_and_collisions/08_bouncing_on_collision/docs/LinearCollider.md26
-rw-r--r--samples/04_physics_and_collisions/09_arbitrary_collision/docs/LinearCollider.md26
-rw-r--r--samples/05_mouse/01_mouse_click/app/main.rb18
-rw-r--r--samples/05_mouse/02_mouse_move/app/main.rb4
-rw-r--r--samples/05_mouse/03_mouse_move_paint_app/app/main.rb1
-rw-r--r--samples/05_mouse/04_coordinate_systems/app/main.rb4
-rw-r--r--samples/06_save_load/01_save_load_game/app/main.rb1
-rw-r--r--samples/07_advanced_audio/01_audio_mixer/app/main.rb377
-rw-r--r--samples/07_advanced_audio/01_audio_mixer/app/server_ip_address.txt1
-rw-r--r--samples/07_advanced_audio/01_audio_mixer/license-for-audio.txt (renamed from samples/01_rendering_basics/06_audio_mixer/license-for-audio.txt)0
-rw-r--r--samples/07_advanced_audio/01_audio_mixer/license-for-sample.txt (renamed from samples/01_rendering_basics/07_sound_synthesis/license-for-sample.txt)0
-rw-r--r--samples/07_advanced_audio/01_audio_mixer/metadata/game_metadata.txt (renamed from samples/01_rendering_basics/07_sound_synthesis/metadata/game_metadata.txt)0
-rw-r--r--samples/07_advanced_audio/01_audio_mixer/metadata/icon.png (renamed from samples/01_rendering_basics/07_sound_synthesis/metadata/icon.png)bin157056 -> 157056 bytes
-rw-r--r--samples/07_advanced_audio/01_audio_mixer/metadata/ios_metadata.txt9
-rw-r--r--samples/07_advanced_audio/01_audio_mixer/replay.txt995
-rw-r--r--samples/07_advanced_audio/01_audio_mixer/sounds/drum.mp3bin0 -> 55090 bytes
-rw-r--r--samples/07_advanced_audio/01_audio_mixer/sounds/drum.wav (renamed from samples/01_rendering_basics/06_audio_mixer/sounds/3.wav)bin420476 -> 420476 bytes
-rw-r--r--samples/07_advanced_audio/01_audio_mixer/sounds/music.ogg (renamed from samples/01_rendering_basics/06_audio_mixer/sounds/6.ogg)bin330572 -> 330572 bytes
-rw-r--r--samples/07_advanced_audio/01_audio_mixer/sounds/splash.wav (renamed from samples/01_rendering_basics/06_audio_mixer/sounds/2.wav)bin22374 -> 22374 bytes
-rw-r--r--samples/07_advanced_audio/01_audio_mixer/sounds/spring.wav (renamed from samples/01_rendering_basics/06_audio_mixer/sounds/5.wav)bin117354 -> 117354 bytes
-rw-r--r--samples/07_advanced_audio/01_audio_mixer/sounds/tada.wav (renamed from samples/01_rendering_basics/06_audio_mixer/sounds/1.wav)bin409170 -> 409170 bytes
-rw-r--r--samples/07_advanced_audio/01_audio_mixer/sounds/tink.wav (renamed from samples/01_rendering_basics/06_audio_mixer/sounds/4.wav)bin91358 -> 91358 bytes
-rw-r--r--samples/07_advanced_audio/02_sound_synthesis/app/main.rb (renamed from samples/01_rendering_basics/07_sound_synthesis/app/main.rb)4
-rw-r--r--samples/07_advanced_audio/02_sound_synthesis/license-for-sample.txt (renamed from samples/07_advanced_rendering/02_render_targets_with_alphas/license-for-sample.txt)0
-rw-r--r--samples/07_advanced_audio/02_sound_synthesis/metadata/game_metadata.txt6
-rw-r--r--samples/07_advanced_audio/02_sound_synthesis/metadata/icon.pngbin0 -> 157056 bytes
-rw-r--r--samples/07_advanced_audio/02_sound_synthesis/replay.txt237
-rw-r--r--samples/07_advanced_audio/02_sound_synthesis/sprites/square-white.png (renamed from samples/01_rendering_basics/07_sound_synthesis/sprites/square-white.png)bin279 -> 279 bytes
-rw-r--r--samples/07_advanced_rendering/00_labels_with_wrapped_text/app/main.rb88
-rw-r--r--samples/07_advanced_rendering/00_labels_with_wrapped_text/replay.txt93
-rw-r--r--samples/07_advanced_rendering/00_rotating_label/app/main.rb32
-rw-r--r--samples/07_advanced_rendering/02_render_targets_with_alphas/app/main.rb95
-rw-r--r--samples/07_advanced_rendering/03_render_target_viewports/app/main.rb7
-rw-r--r--samples/07_advanced_rendering/04_render_primitive_hierarchies/app/main.rb2
-rw-r--r--samples/07_advanced_rendering/05_render_primitives_as_hash/app/main.rb15
-rw-r--r--samples/07_advanced_rendering/07_simple_camera/app/main.rb93
-rw-r--r--samples/07_advanced_rendering/07_simple_camera/replay.txt232
-rw-r--r--samples/07_advanced_rendering/07_splitscreen_camera/run.bat6
-rw-r--r--samples/07_advanced_rendering/08_splitscreen_camera/app/main.rb (renamed from samples/07_advanced_rendering/07_splitscreen_camera/app/main.rb)35
-rw-r--r--samples/07_advanced_rendering/08_splitscreen_camera/replay.txt226
-rw-r--r--samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_down_standing.png (renamed from samples/07_advanced_rendering/07_splitscreen_camera/sprites/player/player_down_standing.png)bin186 -> 186 bytes
-rw-r--r--samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_left_standing.png (renamed from samples/07_advanced_rendering/07_splitscreen_camera/sprites/player/player_left_standing.png)bin173 -> 173 bytes
-rw-r--r--samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_right_standing.png (renamed from samples/07_advanced_rendering/07_splitscreen_camera/sprites/player/player_right_standing.png)bin170 -> 170 bytes
-rw-r--r--samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_up_standing.png (renamed from samples/07_advanced_rendering/07_splitscreen_camera/sprites/player/player_up_standing.png)bin165 -> 165 bytes
-rw-r--r--samples/07_advanced_rendering/08_splitscreen_camera/sprites/rooms/camera_room.png (renamed from samples/07_advanced_rendering/07_splitscreen_camera/sprites/rooms/camera_room.png)bin2469 -> 2469 bytes
-rw-r--r--samples/07_advanced_rendering/09_z_targeting_camera/app/main.rb (renamed from samples/07_advanced_rendering/08_z_targeting_camera/app/main.rb)0
-rw-r--r--samples/07_advanced_rendering/09_z_targeting_camera/metadata/game_metadata.txt (renamed from samples/07_advanced_rendering/08_z_targeting_camera/metadata/game_metadata.txt)0
-rw-r--r--samples/07_advanced_rendering/09_z_targeting_camera/metadata/icon.png (renamed from samples/07_advanced_rendering/08_z_targeting_camera/metadata/icon.png)bin14417 -> 14417 bytes
-rw-r--r--samples/07_advanced_rendering/09_z_targeting_camera/replay.txt185
-rw-r--r--samples/07_advanced_rendering/09_z_targeting_camera/sprites/arena.png (renamed from samples/07_advanced_rendering/08_z_targeting_camera/sprites/arena.png)bin1072678 -> 1072678 bytes
-rw-r--r--samples/07_advanced_rendering/09_z_targeting_camera/sprites/player.png (renamed from samples/07_advanced_rendering/08_z_targeting_camera/sprites/player.png)bin9510 -> 9510 bytes
-rw-r--r--samples/07_advanced_rendering/09_z_targeting_camera/sprites/square/black.png (renamed from samples/07_advanced_rendering/08_z_targeting_camera/sprites/square/black.png)bin250 -> 250 bytes
-rw-r--r--samples/07_advanced_rendering/10_blend_modes/app/main.rb49
-rw-r--r--samples/07_advanced_rendering/10_blend_modes/sprites/blue-feathered.pngbin0 -> 7204 bytes
-rw-r--r--samples/07_advanced_rendering/11_render_target_noclear/app/main.rb47
-rw-r--r--samples/07_advanced_rendering/11_render_target_noclear/metadata/game_metadata.txt5
-rw-r--r--samples/09_performance/01_sprites_as_hash/app/main.rb6
-rw-r--r--samples/09_performance/02_sprites_as_entities/app/main.rb6
-rw-r--r--samples/09_performance/03_sprites_as_strict_entities/app/main.rb6
-rw-r--r--samples/09_performance/03_sprites_as_struct/app/main.rb82
-rw-r--r--samples/09_performance/03_sprites_as_struct/license-for-sample.txt9
-rw-r--r--samples/09_performance/03_sprites_as_struct/sprites/tiny-star.pngbin0 -> 112 bytes
-rw-r--r--samples/09_performance/04_sprites_as_classes/app/main.rb5
-rw-r--r--samples/09_performance/04_sprites_as_strict_entities/app/main.rb72
-rw-r--r--samples/09_performance/04_sprites_as_strict_entities/license-for-sample.txt (renamed from samples/99_genre_rpg_roguelike/roguelike_line_of_sight/license-for-sample.txt)0
-rw-r--r--samples/09_performance/04_sprites_as_strict_entities/sprites/tiny-star.pngbin0 -> 112 bytes
-rw-r--r--samples/09_performance/05_sprites_as_classes/app/main.rb55
-rw-r--r--samples/09_performance/05_sprites_as_classes/license-for-sample.txt (renamed from samples/99_genre_rpg_roguelike/roguelike_starting_point/license-for-sample.txt)0
-rw-r--r--samples/09_performance/05_sprites_as_classes/sprites/tiny-star.pngbin0 -> 112 bytes
-rw-r--r--samples/09_performance/05_static_sprites_as_classes/app/main.rb7
-rw-r--r--samples/09_performance/06_static_sprites_as_classes/app/main.rb56
-rw-r--r--samples/09_performance/06_static_sprites_as_classes/license-for-sample.txt9
-rw-r--r--samples/09_performance/06_static_sprites_as_classes/sprites/tiny-star.pngbin0 -> 112 bytes
-rw-r--r--samples/09_performance/06_static_sprites_as_classes_with_custom_drawing/app/main.rb18
-rw-r--r--samples/09_performance/07_collision_limits/app/main.rb2
-rw-r--r--samples/09_performance/07_static_sprites_as_classes_with_custom_drawing/app/main.rb88
-rw-r--r--samples/09_performance/07_static_sprites_as_classes_with_custom_drawing/license-for-sample.txt9
-rw-r--r--samples/09_performance/07_static_sprites_as_classes_with_custom_drawing/sprites/tiny-star.pngbin0 -> 112 bytes
-rw-r--r--samples/09_performance/08_collision_limits/app/main.rb55
-rw-r--r--samples/09_performance/08_collision_limits/license-for-sample.txt9
-rw-r--r--samples/10_advanced_debugging/00_logging/app/main.rb19
-rw-r--r--samples/10_advanced_debugging/03_unit_tests/benchmark_api_tests.rb43
-rw-r--r--samples/10_advanced_debugging/03_unit_tests/pretty_format_tests.rb130
-rw-r--r--samples/10_advanced_debugging/03_unit_tests/run-bash.sh4
-rw-r--r--samples/10_advanced_debugging/03_unit_tests/run-tests.sh27
-rw-r--r--samples/10_advanced_debugging/03_unit_tests/serialize_deserialize_tests.rb18
-rw-r--r--samples/11_http/01_retrieve_images/app/main.rb4
-rw-r--r--samples/11_http/02_in_game_web_server_http_get/app/main.rb28
-rw-r--r--samples/11_http/02_in_game_web_server_http_get/license-for-sample.txt9
-rw-r--r--samples/11_http/03_in_game_web_server_http_post/app/main.rb72
-rw-r--r--samples/11_http/03_in_game_web_server_http_post/replay.txt415
-rw-r--r--samples/12_c_extensions/.gitignore2
-rw-r--r--samples/12_c_extensions/01_basics/native/ext-bindings.c37
-rw-r--r--samples/12_c_extensions/02_intermediate/native/re-bindings.c67
-rw-r--r--samples/12_c_extensions/03_native_pixel_arrays/native/ext-bindings.c37
-rw-r--r--samples/12_c_extensions/README.md28
-rw-r--r--samples/13_path_finding_algorithms/01_breadth_first_search/app/main.rb174
-rw-r--r--samples/13_path_finding_algorithms/01_breadth_first_search/replay.txt203
-rw-r--r--samples/13_path_finding_algorithms/02_detailed_breadth_first_search/replay.txt241
-rw-r--r--samples/13_path_finding_algorithms/03_breadcrumbs/app/main.rb136
-rw-r--r--samples/13_path_finding_algorithms/03_breadcrumbs/replay.txt365
-rw-r--r--samples/13_path_finding_algorithms/04_early_exit/app/main.rb204
-rw-r--r--samples/13_path_finding_algorithms/04_early_exit/replay.txt364
-rw-r--r--samples/13_path_finding_algorithms/05_dijkstra/app/main.rb218
-rw-r--r--samples/13_path_finding_algorithms/05_dijkstra/replay.txt686
-rw-r--r--samples/13_path_finding_algorithms/06_heuristic/app/main.rb218
-rw-r--r--samples/13_path_finding_algorithms/06_heuristic/replay.txt719
-rw-r--r--samples/13_path_finding_algorithms/07_heuristic_with_walls/app/main.rb218
-rw-r--r--samples/13_path_finding_algorithms/07_heuristic_with_walls/replay.txt352
-rw-r--r--samples/13_path_finding_algorithms/08_a_star/app/main.rb258
-rw-r--r--samples/13_path_finding_algorithms/08_a_star/replay.txt434
-rw-r--r--samples/99_genre_3d/02_wireframe/replay.txt242
-rw-r--r--samples/99_genre_3d/03_yaw_pitch_roll/app/main.rb351
-rw-r--r--samples/99_genre_3d/03_yaw_pitch_roll/replay.txt361
-rw-r--r--samples/99_genre_3d/3d_cube/app/main.rb50
-rw-r--r--samples/99_genre_arcade/bullet_hell/replay.txt126
-rw-r--r--samples/99_genre_arcade/flappy_dragon/app/main.rb97
-rw-r--r--samples/99_genre_arcade/twinstick/replay.txt174
-rw-r--r--samples/99_genre_crafting/farming_game_starting_point/app/main.rb84
-rw-r--r--samples/99_genre_crafting/farming_game_starting_point/app/repl.rb307
-rw-r--r--samples/99_genre_crafting/farming_game_starting_point/app/tests.rb29
-rw-r--r--samples/99_genre_crafting/farming_game_starting_point/replay.txt170
-rw-r--r--samples/99_genre_crafting/farming_game_starting_point/sprites/background.pngbin0 -> 29236 bytes
-rw-r--r--samples/99_genre_crafting/replay.txt170
-rw-r--r--samples/99_genre_dev_tools/animation_creator_starting_point/app/main.rb38
-rw-r--r--samples/99_genre_dev_tools/tile_editor_starting_point/app/main.rb4
-rw-r--r--samples/99_genre_dungeon_crawl/classics_jam/app/main.rb213
-rw-r--r--samples/99_genre_dungeon_crawl/classics_jam/replay.txt197
-rw-r--r--samples/99_genre_dungeon_crawl/classics_jam/sprites/circle/green.png (renamed from samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-green.png)bin2887 -> 2887 bytes
-rw-r--r--samples/99_genre_dungeon_crawl/classics_jam/sprites/square/blue.png (renamed from samples/99_genre_3d/3d_cube/sprites/square-blue.png)bin283 -> 283 bytes
-rw-r--r--samples/99_genre_dungeon_crawl/classics_jam/sprites/square/gray.png (renamed from samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-gray.png)bin251 -> 251 bytes
-rw-r--r--samples/99_genre_dungeon_crawl/classics_jam/sprites/square/red.png (renamed from samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-red.png)bin274 -> 274 bytes
-rw-r--r--samples/99_genre_fighting/01_special_move_inputs/app/main.rb297
-rw-r--r--samples/99_genre_fighting/01_special_move_inputs/sprites/isometric/indigo.png (renamed from samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-indigo.png)bin361 -> 361 bytes
-rw-r--r--samples/99_genre_fighting/01_special_move_inputs/sprites/isometric/violet.png (renamed from samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-violet.png)bin361 -> 361 bytes
-rw-r--r--samples/99_genre_fighting/01_special_move_inputs/sprites/square/blue.png (renamed from samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-blue.png)bin283 -> 283 bytes
-rw-r--r--samples/99_genre_fighting/01_special_move_inputs/sprites/square/indigo.png (renamed from samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-indigo.png)bin283 -> 283 bytes
-rw-r--r--samples/99_genre_fighting/01_special_move_inputs/sprites/square/white.png (renamed from samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-white.png)bin279 -> 279 bytes
-rw-r--r--samples/99_genre_fighting/01_special_move_inputs/sprites/square/yellow.png (renamed from samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-yellow.png)bin286 -> 286 bytes
-rw-r--r--samples/99_genre_lowrez/nokia_3310/app/main.rb4
-rw-r--r--samples/99_genre_lowrez/nokia_3310/app/nokia.rb4
-rw-r--r--samples/99_genre_lowrez/resolution_64x64/app/main.rb8
-rw-r--r--samples/99_genre_mario/01_jumping/app/main.rb78
-rw-r--r--samples/99_genre_mario/01_jumping/replay.txt52
-rw-r--r--samples/99_genre_mario/01_jumping/sprites/square/red.pngbin0 -> 335 bytes
-rw-r--r--samples/99_genre_mario/02_jumping_and_collisions/app/main.rb281
-rw-r--r--samples/99_genre_mario/02_jumping_and_collisions/replay.txt159
-rw-r--r--samples/99_genre_mario/02_jumping_and_collisions/sprites/square/red.pngbin0 -> 335 bytes
-rw-r--r--samples/99_genre_mario/02_jumping_and_collisions/sprites/square/white.pngbin0 -> 325 bytes
-rw-r--r--samples/99_genre_platformer/clepto_frog/app/main.rb171
-rw-r--r--samples/99_genre_platformer/clepto_frog/app/map.rb5
-rw-r--r--samples/99_genre_platformer/clepto_frog/replay.txt249
-rw-r--r--samples/99_genre_platformer/gorillas_basic/app/repl.rb17
-rw-r--r--samples/99_genre_platformer/the_little_probe/app/main.rb10
-rw-r--r--samples/99_genre_platformer/the_little_probe/bug-replay.txt205
-rw-r--r--samples/99_genre_rpg_narrative/choose_your_own_adventure/app/main.rb4
-rw-r--r--samples/99_genre_rpg_narrative/return_of_serenity/app/repl.rb1
-rw-r--r--samples/99_genre_rpg_roguelike/01_roguelike_starting_point/replay.txt196
-rw-r--r--samples/99_genre_rpg_roguelike/roguelike_line_of_sight/app/constants.rb8
-rw-r--r--samples/99_genre_rpg_roguelike/roguelike_line_of_sight/app/legend.rb65
-rw-r--r--samples/99_genre_rpg_roguelike/roguelike_line_of_sight/app/main.rb97
-rw-r--r--samples/99_genre_rpg_roguelike/roguelike_line_of_sight/app/sprite_lookup.rb124
-rw-r--r--samples/99_genre_rpg_roguelike/roguelike_line_of_sight/sprites/simple-mood-16x16.pngbin14424 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_roguelike/roguelike_starting_point/app/main.rb438
-rw-r--r--samples/99_genre_rpg_roguelike/roguelike_starting_point/replay.txt555
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/app/main.rb529
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/border-black.pngbin908 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-black.pngbin1882 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-blue.pngbin2901 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-gray.pngbin3006 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-indigo.pngbin2433 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-orange.pngbin2670 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-red.pngbin2233 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-violet.pngbin2439 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-white.pngbin1754 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-yellow.pngbin2456 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-0.pngbin12896 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-1.pngbin2964 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-2.pngbin3047 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-3.pngbin2655 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-4.pngbin2725 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-5.pngbin2655 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-0.pngbin267 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-1.pngbin4585 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-2.pngbin4675 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-3.pngbin4724 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-4.pngbin4773 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-5.pngbin4742 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-6.pngbin4665 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-sheet.pngbin2584 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-black.pngbin2602 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-blue.pngbin4842 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-gray.pngbin5184 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-green.pngbin4695 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-indigo.pngbin4918 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-orange.pngbin4825 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-red.pngbin3753 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-violet.pngbin5069 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-white.pngbin5326 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-yellow.pngbin5249 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-black.pngbin264 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-blue.pngbin361 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-gray.pngbin493 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-green.pngbin361 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-orange.pngbin361 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-red.pngbin361 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-white.pngbin361 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-yellow.pngbin361 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/roy-0.pngbin20775 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/roy-1.pngbin3132 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-black.pngbin250 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-orange.pngbin282 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-violet.pngbin284 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/star.pngbin711 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/water-1.pngbin656794 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/gameboard_movement/sprites/water-2.pngbin655810 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/taking_turns/app/main.rb189
-rw-r--r--samples/99_genre_rpg_tactical/taking_turns/run.bat6
-rw-r--r--samples/99_genre_rpg_tactical/taking_turns/sprites/circle-blue.pngbin2901 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/taking_turns/sprites/circle-gray.pngbin3006 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/taking_turns/sprites/circle-green.pngbin2887 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/taking_turns/sprites/circle-orange.pngbin2670 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-0.pngbin267 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-1.pngbin4585 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-2.pngbin4675 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-3.pngbin4724 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-4.pngbin4773 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-5.pngbin4742 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-6.pngbin4665 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_tactical/taking_turns/sprites/star.pngbin711 -> 0 bytes
-rw-r--r--samples/99_genre_rpg_topdown/topdown_casino/app/main.rb139
-rw-r--r--samples/99_genre_rpg_topdown/topdown_casino/license-for-sample.txt9
-rw-r--r--samples/99_genre_rpg_topdown/topdown_casino/replay.txt123
-rw-r--r--samples/99_genre_rpg_topdown/topdown_casino/sprites/fire.pngbin0 -> 893 bytes
-rw-r--r--samples/99_genre_rpg_topdown/topdown_casino/sprites/gem200.pngbin0 -> 916 bytes
-rw-r--r--samples/99_genre_rpg_topdown/topdown_casino/sprites/gem400.pngbin0 -> 920 bytes
-rw-r--r--samples/99_genre_rpg_topdown/topdown_casino/sprites/herodown100.pngbin0 -> 3600 bytes
-rw-r--r--samples/99_genre_rpg_topdown/topdown_casino/sprites/herodown200.pngbin0 -> 3600 bytes
-rw-r--r--samples/99_genre_rpg_topdown/topdown_casino/sprites/heroleft100.pngbin0 -> 3600 bytes
-rw-r--r--samples/99_genre_rpg_topdown/topdown_casino/sprites/heroleft200.pngbin0 -> 3600 bytes
-rw-r--r--samples/99_genre_rpg_topdown/topdown_casino/sprites/heroright100.pngbin0 -> 3600 bytes
-rw-r--r--samples/99_genre_rpg_topdown/topdown_casino/sprites/heroright200.pngbin0 -> 3600 bytes
-rw-r--r--samples/99_genre_rpg_topdown/topdown_casino/sprites/heroup100.pngbin0 -> 3600 bytes
-rw-r--r--samples/99_genre_rpg_topdown/topdown_casino/sprites/heroup200.pngbin0 -> 3600 bytes
-rw-r--r--samples/99_genre_rpg_topdown/topdown_casino/sprites/oldman.pngbin0 -> 967 bytes
-rw-r--r--samples/99_genre_rpg_topdown/topdown_starting_point/app/main.rb1
-rw-r--r--samples/99_genre_teenytiny/app/main.rb162
-rw-r--r--samples/99_genre_teenytiny/license.txt9
-rw-r--r--samples/99_genre_teenytiny/metadata/game_metadata.txt6
-rw-r--r--samples/99_genre_teenytiny/metadata/icon.pngbin0 -> 157056 bytes
-rw-r--r--samples/99_genre_teenytiny/sprites/square-green.pngbin0 -> 283 bytes
-rw-r--r--samples/99_genre_teenytiny/sprites/square-red.pngbin0 -> 274 bytes
-rw-r--r--samples/99_genre_teenytiny/teenytiny_starting_point/app/main.rb162
-rw-r--r--samples/99_genre_teenytiny/teenytiny_starting_point/license.txt9
-rw-r--r--samples/99_genre_teenytiny/teenytiny_starting_point/sprites/square-green.pngbin0 -> 283 bytes
-rw-r--r--samples/99_genre_teenytiny/teenytiny_starting_point/sprites/square-red.pngbin0 -> 274 bytes
283 files changed, 14285 insertions, 3952 deletions
diff --git a/samples/00_learn_ruby_optional/00_intermediate_ruby_primer/app/repl.rb b/samples/00_learn_ruby_optional/00_intermediate_ruby_primer/app/repl.rb
deleted file mode 100644
index e69de29..0000000
--- a/samples/00_learn_ruby_optional/00_intermediate_ruby_primer/app/repl.rb
+++ /dev/null
diff --git a/samples/01_rendering_basics/01_labels/app/main.rb b/samples/01_rendering_basics/01_labels/app/main.rb
index c3e1afc..837954f 100644
--- a/samples/01_rendering_basics/01_labels/app/main.rb
+++ b/samples/01_rendering_basics/01_labels/app/main.rb
@@ -67,7 +67,7 @@ def tick args
g: 0,
b: 200,
a: 255,
- font: "manaspc.ttf" }.label
+ font: "manaspc.ttf" }.label!
# Primitives can hold anything, and can be given a label in the following forms
args.outputs.primitives << [690 + 150, 330 - 80, "Custom font (.primitives Array)", 0, 1, 125, 0, 200, 255, "manaspc.ttf" ].label
@@ -81,7 +81,7 @@ def tick args
g: 0,
b: 200,
a: 255,
- font: "manaspc.ttf" }.label
+ font: "manaspc.ttf" }.label!
end
def tick_instructions args, text, y = 715
diff --git a/samples/01_rendering_basics/03_solids_borders/app/main.rb b/samples/01_rendering_basics/03_solids_borders/app/main.rb
index 2b9b1c4..8d1bfef 100644
--- a/samples/01_rendering_basics/03_solids_borders/app/main.rb
+++ b/samples/01_rendering_basics/03_solids_borders/app/main.rb
@@ -15,7 +15,7 @@ APIs listing that haven't been encountered in a previous sample apps:
# Borders are added to args.outputs.borders
# The parameters required for rects are:
-# 1. The bottom left corner (x, y)
+# 1. The upper right corner (x, y)
# 2. The width (w)
# 3. The height (h)
# 4. The rgba values for the color and transparency (r, g, b, a)
diff --git a/samples/01_rendering_basics/05_sounds/app/main.rb b/samples/01_rendering_basics/05_sounds/app/main.rb
index 630ce11..787d303 100644
--- a/samples/01_rendering_basics/05_sounds/app/main.rb
+++ b/samples/01_rendering_basics/05_sounds/app/main.rb
@@ -13,16 +13,7 @@
- args.outputs.labels: An array. The values generate a label.
The parameters are [X, Y, TEXT, SIZE, ALIGNMENT, RED, GREEN, BLUE, ALPHA, FONT STYLE]
-
- - reject: Removes elements from a collection if they meet certain requirements.
-
- - first: Returns the first element of an array.
-
- - inside_rect: Returns true or false depending on if the point is inside the rect.
-
- - to_sym: Returns symbol corresponding to string. Will create a symbol if it does
- not already exist.
-
+ For more information about labels, go to mygame/documentation/02-labels.md.
=end
# This sample app allows users to test their musical skills by matching the piano sound that plays in each
@@ -30,153 +21,11 @@
# Runs all the methods necessary for the game to function properly.
def tick args
- defaults args
- render args
- calc args
- input_mouse args
- tick_instructions args, "Sample app shows how to play sounds. args.outputs.sounds << \"path_to_wav.wav\""
-end
-
-# Sets default values and creates empty collections
-# Initialization happens in the first frame only
-def defaults _
- _.state.notes ||= []
- _.state.click_feedbacks ||= []
- _.state.current_level ||= 1
- _.state.times_wrong ||= 0 # when game starts, user hasn't guessed wrong yet
-end
-
-# Uses a label to display current level, and shows the score
-# Creates a button to play the sample note, and displays the available notes that could be a potential match
-def render _
-
- # grid.w_half positions the label in the horizontal center of the screen.
- _.outputs.labels << [_.grid.w_half, _.grid.top.shift_down(40), "Hole #{_.state.current_level} of 9", 0, 1, 0, 0, 0]
-
- render_score _ # shows score on screen
-
- if _.state.game_over # if game is over, a "play again" button is shown
- # Calculations ensure that Play Again label is displayed in center of border
- # Remove calculations from y parameters and see what happens to border and label placement
- _.state.play_again_border ||= _.state.with_meta([560, _.grid.h * 3 / 4 - 40, 160, 60], 'again') # array definition, text/title
- _.outputs.labels << [_.grid.w_half, _.grid.h * 3 / 4, "Play Again", 0, 1, 0, 0, 0] # outputs label
- _.outputs.borders << _.state.play_again_border # outputs border
- else # otherwise, if game is not over
- # Calculations ensure that label appears in center of border
- _.state.play_note_border ||= _.state.with_meta([560, _.grid.h * 3 / 4 - 40, 160, 60], 'play') # array definition, text/title
- _.outputs.labels << [_.grid.w_half, _.grid.h * 3 / 4, "Play Note ##{_.state.current_level}", 0, 1, 0, 0, 0] # outputs label
- _.outputs.borders << _.state.play_note_border # outputs border
- end
-
- return if _.state.game_over # return if game is over
-
- _.outputs.labels << [_.grid.w_half, 400, "I think the note is a(n)...", 0, 1, 0, 0, 0] # outputs label
-
- # Shows all of the available notes that can be potential matches.
- available_notes.each_with_index do |note, i|
- _.state.notes[i] ||= piano_button(_, note, i + 1) # calls piano_button method on each note (creates label and border)
- _.outputs.labels << _.state.notes[i].label # outputs note on screen with a label and a border
- _.outputs.borders << _.state.notes[i].border
- end
-
- # Shows whether or not the user is correct by filling the screen with either red or green
- _.outputs.solids << _.state.click_feedbacks.map { |c| c.solid }
-end
-
-# Shows the score (number of times the user guesses wrong) onto the screen using labels.
-def render_score _
- if _.state.times_wrong == 0 # if the user has guessed wrong zero times, the score is par
- _.outputs.labels << [_.grid.w_half, _.grid.top.shift_down(80), "Score: PAR", 0, 1, 0, 0, 0]
- else # otherwise, number of times the user has guessed wrong is shown
- _.outputs.labels << [_.grid.w_half, _.grid.top.shift_down(80), "Score: +#{_.state.times_wrong}", 0, 1, 0, 0, 0] # shows score using string interpolation
- end
-end
-
-# Sets the target note for the level and performs calculations on click_feedbacks.
-def calc _
- _.state.target_note ||= available_notes.sample # chooses a note from available_notes collection as target note
- _.state.click_feedbacks.each { |c| c.solid[-1] -= 5 } # remove this line and solid color will remain on screen indefinitely
- # comment this line out and the solid color will keep flashing on screen instead of being removed from click_feedbacks collection
- _.state.click_feedbacks.reject! { |c| c.solid[-1] <= 0 }
-end
-
-# Uses input from the user to play the target note, as well as the other notes that could be a potential match.
-def input_mouse _
- return unless _.inputs.mouse.click # return unless the mouse is clicked
-
- # finds button that was clicked by user
- button_clicked = _.outputs.borders.find_all do |b| # go through borders collection to find all borders that meet requirements
- _.inputs.mouse.click.point.inside_rect? b # find button border that mouse was clicked inside of
- end.reject {|b| !_.state.meta(b)}.first # reject, return first element
-
- return unless button_clicked # return unless button_clicked as a value (a button was clicked)
+ args.outputs.labels << [640, 360, "Click anywhere to play a random sound.", 0, 1]
+ args.state.notes ||= [:C3, :D3, :E3, :F3, :G3, :A3, :B3, :C4]
- queue_click_feedback _, # calls queue_click_feedback method on the button that was clicked
- button_clicked.x,
- button_clicked.y,
- button_clicked.w,
- button_clicked.h,
- 150, 100, 200 # sets color of button to shade of purple
-
- if _.state.meta(button_clicked) == 'play' # if "play note" button is pressed
- _.outputs.sounds << "sounds/#{_.state.target_note}.wav" # sound of target note is output
- elsif _.state.meta(button_clicked) == 'again' # if "play game again" button is pressed
- _.state.target_note = nil # no target note
- _.state.current_level = 1 # starts at level 1 again
- _.state.times_wrong = 0 # starts off with 0 wrong guesses
- _.state.game_over = false # the game is not over (because it has just been restarted)
- else # otherwise if neither of those buttons were pressed
- _.outputs.sounds << "sounds/#{_.state.meta(button_clicked)}.wav" # sound of clicked note is played
- if _.state.meta(button_clicked).to_sym == _.state.target_note # if clicked note is target note
- _.state.target_note = nil # target note is emptied
-
- if _.state.current_level < 9 # if game hasn't reached level 9
- _.state.current_level += 1 # game goes to next level
- else # otherwise, if game has reached level 9
- _.state.game_over = true # the game is over
- end
-
- queue_click_feedback _, 0, 0, _.grid.w, _.grid.h, 100, 200, 100 # green shown if user guesses correctly
- else # otherwise, if clicked note is not target note
- _.state.times_wrong += 1 # increments times user guessed wrong
- queue_click_feedback _, 0, 0, _.grid.w, _.grid.h, 200, 100, 100 # red shown is user guesses wrong
- end
+ if args.inputs.mouse.click
+ # Play a sound by adding a string to args.outputs.sounds
+ args.outputs.sounds << "sounds/#{args.state.notes.sample}.wav" # sound of target note is output
end
end
-
-# Creates a collection of all of the available notes as symbols
-def available_notes
- [:C3, :D3, :E3, :F3, :G3, :A3, :B3, :C4]
-end
-
-# Creates buttons for each note, and sets a label (the note's name) and border for each note's button.
-def piano_button _, note, position
- _.state.new_entity(:button) do |b| # declares button as new entity
- b.label = [460 + 40.mult(position), _.grid.h * 0.4, "#{note}", 0, 1, 0, 0, 0] # label definition
- b.border = _.state.with_meta([460 + 40.mult(position) - 20, _.grid.h * 0.4 - 32, 40, 40], note) # border definition, text/title; 20 subtracted so label is in center of border
- end
-end
-
-# Color of click feedback changes depending on what button was clicked, and whether the guess is right or wrong
-# If a button is clicked, the inside of button is purple (see input_mouse method)
-# If correct note is clicked, screen turns green
-# If incorrect note is clicked, screen turns red (again, see input_mouse method)
-def queue_click_feedback _, x, y, w, h, *color
- _.state.click_feedbacks << _.state.new_entity(:click_feedback) do |c| # declares feedback as new entity
- c.solid = [x, y, w, h, *color, 255] # sets color
- end
-end
-
-def tick_instructions args, text, y = 715
- return if args.state.key_event_occurred
- if args.inputs.mouse.click ||
- args.inputs.keyboard.directional_vector ||
- args.inputs.keyboard.key_down.enter ||
- args.inputs.keyboard.key_down.escape
- args.state.key_event_occurred = true
- end
-
- args.outputs.debug << [0, y - 50, 1280, 60].solid
- args.outputs.debug << [640, y, text, 1, 1, 255, 255, 255].label
- args.outputs.debug << [640, y - 25, "(click to dismiss instructions)" , -2, 1, 255, 255, 255].label
-end
diff --git a/samples/01_rendering_basics/06_audio_mixer/app/main.rb b/samples/01_rendering_basics/06_audio_mixer/app/main.rb
deleted file mode 100644
index ce48d3f..0000000
--- a/samples/01_rendering_basics/06_audio_mixer/app/main.rb
+++ /dev/null
@@ -1,160 +0,0 @@
-$gtk.reset
-
-$boxsize = 30
-
-def render_sources args
- mouse_in_panel = (args.state.selected != 0) && args.inputs.mouse.position.inside_rect?([900, 450, 340, 250])
- mouse_new_down = (args.state.mouse_held == 1)
-
- if (mouse_new_down && !mouse_in_panel)
- args.state.selected = 0 # will reset below if we hit something.
- end
-
- args.audio.keys.each { |k|
- s = args.audio[k]
-
- if (mouse_new_down) && !mouse_in_panel && args.inputs.mouse.position.inside_rect?([s[:screenx], s[:screeny], $boxsize, $boxsize])
- args.state.selected = k
- args.state.dragging_source = true
- end
-
- isselected = (k == args.state.selected)
-
- if isselected && args.state.dragging_source
- # you can hang anything on the audio hashes you want, so we store the
- # actual screen position so it doesn't scale weirdly vs your mouse.
- s[:screenx] = args.inputs.mouse.x - ($boxsize / 2)
- s[:screeny] = args.inputs.mouse.y - ($boxsize / 2)
-
- s[:screeny] = 50 if s[:screeny] < 50
- s[:screeny] = (719 - $boxsize) if s[:screeny] > (719 - $boxsize)
- s[:screenx] = 0 if s[:screenx] < 0
- s[:screenx] = (1279 - $boxsize) if s[:screenx] > (1279 - $boxsize)
-
- s[:x] = ((s[:screenx] / 1279.0) * 2.0) - 1.0 # scale to -1.0 - 1.0 range
- s[:y] = ((s[:screeny] / 719.0) * 2.0) - 1.0 # scale to -1.0 - 1.0 range
- end
-
- color = isselected ? [ 0, 255, 0, 255 ] : [ 0, 0, 255, 255 ]
- args.outputs.primitives << [s[:screenx], s[:screeny], $boxsize, $boxsize, *color].solid
- }
-end
-
-def render_panel args
- s = args.audio[args.state.selected]
- return if s.nil?
- mouse_down = (args.state.mouse_held > 0)
-
- args.outputs.primitives << [900, 450, 340, 250, 127, 127, 200, 255].solid
- args.outputs.primitives << [1075, 690, "Source ##{args.state.selected}", 3, 1, 255, 255, 255].label
- args.outputs.primitives << [910, 660, 1230, 660, 255, 255, 255].line
- args.outputs.primitives << [910, 650, "screen: (#{s[:screenx].to_i}, #{s[:screeny].to_i})", 0, 0, 255, 255, 255].label
- args.outputs.primitives << [910, 625, "position: (#{s[:x].round(5).to_s[0..6]}, #{s[:y].round(5).to_s[0..6]})", 0, 0, 255, 255, 255].label
-
- slider = [1022, 586, 200, 7]
- if mouse_down && args.inputs.mouse.position.inside_rect?(slider)
- s[:pitch] = ((args.inputs.mouse.x - slider[0]).to_f / (slider[2]-1.0)) * 2.0
- end
- slidercolor = (s[:pitch] / 2.0) * 255
- args.outputs.primitives << [*slider, slidercolor, slidercolor, slidercolor, 255].solid
- args.outputs.primitives << [910, 600, "pitch: #{s[:pitch].round(3).to_s[0..2]}", 0, 0, 255, 255, 255].label
-
- slider = [1022, 561, 200, 7]
- if mouse_down && args.inputs.mouse.position.inside_rect?(slider)
- s[:gain] = (args.inputs.mouse.x - slider[0]).to_f / (slider[2]-1.0)
- end
- slidercolor = s[:gain] * 255
- args.outputs.primitives << [*slider, slidercolor, slidercolor, slidercolor, 255].solid
- args.outputs.primitives << [910, 575, "gain: #{s[:gain].round(3).to_s[0..2]}", 0, 0, 255, 255, 255].label
-
- checkbox = [1022, 533, 10, 12]
- if (args.state.mouse_held == 1) && args.inputs.mouse.position.inside_rect?(checkbox)
- s[:looping] = !s[:looping]
- end
- checkboxcolor = s[:looping] ? 255 : 0
- args.outputs.primitives << [*checkbox, checkboxcolor, checkboxcolor, checkboxcolor, 255].solid
- args.outputs.primitives << [910, 550, "looping:", 0, 0, 255, 255, 255].label
-
- checkbox = [1022, 508, 10, 12]
- if (args.state.mouse_held == 1) && args.inputs.mouse.position.inside_rect?(checkbox)
- s[:paused] = !s[:paused]
- end
- checkboxcolor = s[:paused] ? 255 : 0
- args.outputs.primitives << [*checkbox, checkboxcolor, checkboxcolor, checkboxcolor, 255].solid
- args.outputs.primitives << [910, 525, "paused:", 0, 0, 255, 255, 255].label
-
- button = [910, 460, 320, 20]
- if (args.state.mouse_held == 1) && args.inputs.mouse.position.inside_rect?(button)
- args.audio.delete(args.state.selected)
- args.state.selected = 0
- end
- args.outputs.primitives << [*button, 255, 0, 0, 255].solid
- args.outputs.primitives << [button[0] + (button[2] / 2), button[1]+20, "DELETE SOURCE", 0, 1, 255, 255, 0].label
-end
-
-def spawn_new_sound args, num
- input = nil
- input = "sounds/#{num}.#{(num == 6) ? 'ogg' : 'wav'}"
-
- # Spawn randomly in an area that won't be covered by UI.
- screenx = (rand * 600.0) + 200.0
- screeny = (rand * 400.0) + 100.0
-
- args.state.next_sound_index += 1
-
- # you can hang anything on the audio hashes you want, so we store the
- # actual screen position in here for convenience.
- args.audio[args.state.next_sound_index] = {
- input: input,
- screenx: screenx,
- screeny: screeny,
- x: ((screenx / 1279.0) * 2.0) - 1.0, # scale to -1.0 - 1.0 range
- y: ((screeny / 719.0) * 2.0) - 1.0, # scale to -1.0 - 1.0 range
- z: 0.0,
- gain: 1.0,
- pitch: 1.0,
- looping: true,
- paused: false
- }
-
- args.state.selected = args.state.next_sound_index
-end
-
-def render_launcher args
- total = 6
- x = (1280 - (total * $boxsize * 3)) / 2
- y = 10
- args.outputs.primitives << [0, 0, 1280, ((y*2) + $boxsize), 127, 127, 127, 255].solid
- for i in 1..total
- args.outputs.primitives << [x, y, $boxsize, $boxsize, 255, 255, 255, 255].solid
- args.outputs.primitives << [x+8, y+28, i.to_s, 3, 0, 0, 0, 255, 255].label
- if args.inputs.mouse.click && args.inputs.mouse.click.point.inside_rect?([x, y, $boxsize, $boxsize])
- spawn_new_sound args, i
- end
- x = x + ($boxsize * 3)
- end
-end
-
-def render_ui args
- render_launcher args
- render_panel args
-end
-
-def tick args
- args.state.mouse_held ||= 0
- args.state.dragging_source ||= false
- args.state.selected ||= 0
- args.state.next_sound_index ||= 0
-
- if args.inputs.mouse.up
- args.state.mouse_held = 0
- args.state.dragging_source = false
- elsif args.inputs.mouse.down || (args.state.mouse_held > 0)
- args.state.mouse_held += 1
- else
- end
-
- args.outputs.background_color = [ 0, 0, 0, 255 ]
- render_sources args
- render_ui args
-end
diff --git a/samples/01_rendering_basics/07_sound_synthesis/sprites/square-black.png b/samples/01_rendering_basics/07_sound_synthesis/sprites/square-black.png
deleted file mode 100644
index cea7bd7..0000000
--- a/samples/01_rendering_basics/07_sound_synthesis/sprites/square-black.png
+++ /dev/null
Binary files differ
diff --git a/samples/02_input_basics/01_keyboard/app/main.rb b/samples/02_input_basics/01_keyboard/app/main.rb
index 3c5e1b4..f97c134 100644
--- a/samples/02_input_basics/01_keyboard/app/main.rb
+++ b/samples/02_input_basics/01_keyboard/app/main.rb
@@ -4,7 +4,8 @@ APIs listing that haven't been encountered in a previous sample apps:
- args.inputs.keyboard.key_up.KEY: The value of the properties will be set
to the frame that the key_up event occurred (the frame correlates
- to args.state.tick_count). Otherwise the value will be nil.
+ to args.state.tick_count). Otherwise the value will be nil. For a
+ full listing of keys, take a look at mygame/documentation/06-keyboard.md.
- args.state.PROPERTY: The state property on args is a dynamic
structure. You can define ANY property here with ANY type of
arbitrary nesting. Properties defined on args.state will be retained
@@ -24,9 +25,9 @@ APIs listing that haven't been encountered in a previous sample apps:
def tick args
tick_instructions args, "Sample app shows how keyboard events are registered and accessed.", 360
# Notice how small_font accounts for all the remaining parameters
- args.outputs.labels << [460, row_to_px(args, 0), "Current game time: #{args.state.tick_count}", small_font]
- args.outputs.labels << [460, row_to_px(args, 2), "Keyboard input: args.inputs.keyboard.key_up.h", small_font]
- args.outputs.labels << [460, row_to_px(args, 3), "Press \"h\" on the keyboard.", small_font]
+ args.outputs.labels << { x: 460, y: row_to_px(args, 0), text: "Current game time: #{args.state.tick_count}", size_enum: -1 }
+ args.outputs.labels << { x: 460, y: row_to_px(args, 2), text: "Keyboard input: args.inputs.keyboard.key_up.h", size_enum: -1 }
+ args.outputs.labels << { x: 460, y: row_to_px(args, 3), text: "Press \"h\" on the keyboard.", size_enum: -1 }
# Input on a specifc key can be found through args.inputs.keyboard.key_up followed by the key
if args.inputs.keyboard.key_up.h
@@ -37,27 +38,19 @@ def tick args
args.state.h_pressed_at ||= false
if args.state.h_pressed_at
- args.outputs.labels << [460, row_to_px(args, 4), "\"h\" was pressed at time: #{args.state.h_pressed_at}", small_font]
+ args.outputs.labels << { x: 460, y: row_to_px(args, 4), text: "\"h\" was pressed at time: #{args.state.h_pressed_at}", size_enum: -1 }
else
- args.outputs.labels << [460, row_to_px(args, 4), "\"h\" has never been pressed.", small_font]
+ args.outputs.labels << { x: 460, y: row_to_px(args, 4), text: "\"h\" has never been pressed.", size_enum: -1 }
end
tick_help_text args
end
-def small_font
- # This method provides some values for the construction of labels
- # Specifically, Size, Alignment, & RGBA
- # This makes it so that custom parameters don't have to be repeatedly typed.
- # Additionally "small_font" provides programmers with more information than some numbers
- [-2, 0, 0, 0, 0, 255]
-end
-
-def row_to_px args, row_number
+def row_to_px args, row_number, y_offset = 20
# This takes a row_number and converts it to pixels DragonRuby understands.
# Row 0 starts 5 units below the top of the grid
# Each row afterward is 20 units lower
- args.grid.top.shift_down(5).shift_down(20 * row_number)
+ args.grid.top - 5 - (y_offset * row_number)
end
# Don't worry about understanding the code within this method just yet.
@@ -87,17 +80,17 @@ def tick_help_text args
end
end
- args.outputs.labels << [10, row_to_px(args, 6), "Advanced Help:", small_font]
+ args.outputs.labels << { x: 10, y: row_to_px(args, 6), text: "This is the api for the keys you've pressed:", size_enum: -1, r: 180 }
if !args.state.help_available
args.outputs.labels << [10, row_to_px(args, 7), "Press a key and I'll show code to access the key and what value will be returned if you used the code.", small_font]
return
end
- args.outputs.labels << [10 , row_to_px(args, 7), "args.inputs.keyboard", small_font]
- args.outputs.labels << [330, row_to_px(args, 7), "args.inputs.keyboard.key_down", small_font]
- args.outputs.labels << [650, row_to_px(args, 7), "args.inputs.keyboard.key_held", small_font]
- args.outputs.labels << [990, row_to_px(args, 7), "args.inputs.keyboard.key_up", small_font]
+ args.outputs.labels << { x: 10 , y: row_to_px(args, 7), text: "args.inputs.keyboard", size_enum: -2 }
+ args.outputs.labels << { x: 330, y: row_to_px(args, 7), text: "args.inputs.keyboard.key_down", size_enum: -2 }
+ args.outputs.labels << { x: 650, y: row_to_px(args, 7), text: "args.inputs.keyboard.key_held", size_enum: -2 }
+ args.outputs.labels << { x: 990, y: row_to_px(args, 7), text: "args.inputs.keyboard.key_up", size_enum: -2 }
fill_history args, :key_value_history, :down_or_held, nil
fill_history args, :key_down_value_history, :down, :key_down
@@ -143,12 +136,8 @@ def render_help_labels args, history_key, state_key, keyboard_method, x
end
idx += 2
[
- [x, row_to_px(args, idx - 2),
- " .#{k} is #{current_value || "nil"}",
- small_font],
- [x, row_to_px(args, idx - 1),
- " was #{v}",
- small_font]
+ { x: x, y: row_to_px(args, idx + 0, 16), text: " .#{k} is #{current_value || "nil"}", size_enum: -2 },
+ { x: x, y: row_to_px(args, idx + 1, 16), text: " was #{v}", size_enum: -2 }
]
end
end
@@ -163,7 +152,9 @@ def tick_instructions args, text, y = 715
args.state.key_event_occurred = true
end
- args.outputs.debug << [0, y - 50, 1280, 60].solid
- args.outputs.debug << [640, y, text, 1, 1, 255, 255, 255].label
- args.outputs.debug << [640, y - 25, "(click to dismiss instructions)" , -2, 1, 255, 255, 255].label
+ args.outputs.debug << { x: 0, y: y - 50, w: 1280, h: 60 }.solid!
+ args.outputs.debug << { x: 640, y: y, text: text,
+ size_enum: 1, alignment_enum: 1, r: 255, g: 255, b: 255 }.label!
+ args.outputs.debug << { x: 640, y: y - 25, text: "(click to dismiss instructions)",
+ size_enum: -2, alignment_enum: 1, r: 255, g: 255, b: 255 }.label!
end
diff --git a/samples/02_input_basics/01_moving_a_sprite/app/main.rb b/samples/02_input_basics/01_moving_a_sprite/app/main.rb
new file mode 100644
index 0000000..da699a0
--- /dev/null
+++ b/samples/02_input_basics/01_moving_a_sprite/app/main.rb
@@ -0,0 +1,30 @@
+def tick args
+ # create a player and set default values
+ # for the player's x, y, w (width), and h (height)
+ args.state.player.x ||= 100
+ args.state.player.y ||= 100
+ args.state.player.w ||= 50
+ args.state.player.h ||= 50
+
+ # render the player to the screen
+ args.outputs.sprites << { x: args.state.player.x,
+ y: args.state.player.y,
+ w: args.state.player.w,
+ h: args.state.player.h,
+ path: 'sprites/square/green.png' }
+
+ # move the player around using the keyboard
+ if args.inputs.up
+ args.state.player.y += 10
+ elsif args.inputs.down
+ args.state.player.y -= 10
+ end
+
+ if args.inputs.left
+ args.state.player.x -= 10
+ elsif args.inputs.right
+ args.state.player.x += 10
+ end
+end
+
+$gtk.reset
diff --git a/samples/01_rendering_basics/06_audio_mixer/license-for-sample.txt b/samples/02_input_basics/01_moving_a_sprite/license-for-sample.txt
index 100dcec..100dcec 100644
--- a/samples/01_rendering_basics/06_audio_mixer/license-for-sample.txt
+++ b/samples/02_input_basics/01_moving_a_sprite/license-for-sample.txt
diff --git a/samples/02_input_basics/01_moving_a_sprite/replay.txt b/samples/02_input_basics/01_moving_a_sprite/replay.txt
new file mode 100644
index 0000000..1ec5f3a
--- /dev/null
+++ b/samples/02_input_basics/01_moving_a_sprite/replay.txt
@@ -0,0 +1,73 @@
+replay_version 2.0
+stopped_at 442
+seed 100
+recorded_at 2021-11-20 11:06:58 -0600
+[:mouse_button_up, 1, 0, 1, 1, 5]
+[:key_down_raw, 1073741903, 0, 2, 2, 147]
+[:key_down_raw, 1073741903, 0, 2, 3, 162]
+[:key_down_raw, 1073741903, 0, 2, 4, 164]
+[:key_down_raw, 1073741903, 0, 2, 5, 166]
+[:key_down_raw, 1073741903, 0, 2, 6, 168]
+[:key_down_raw, 1073741903, 0, 2, 7, 170]
+[:key_down_raw, 1073741903, 0, 2, 8, 172]
+[:key_down_raw, 1073741906, 0, 2, 9, 172]
+[:key_down_raw, 1073741905, 0, 2, 10, 182]
+[:key_up_raw, 1073741903, 0, 2, 11, 185]
+[:key_up_raw, 1073741906, 0, 2, 12, 188]
+[:key_down_raw, 1073741904, 0, 2, 13, 195]
+[:key_up_raw, 1073741905, 0, 2, 14, 202]
+[:key_up_raw, 1073741904, 0, 2, 15, 208]
+[:key_down_raw, 1073741903, 0, 2, 16, 210]
+[:key_down_raw, 1073741903, 0, 2, 17, 225]
+[:key_down_raw, 1073741903, 0, 2, 18, 227]
+[:key_down_raw, 1073741903, 0, 2, 19, 229]
+[:key_down_raw, 1073741903, 0, 2, 20, 231]
+[:key_down_raw, 1073741903, 0, 2, 21, 233]
+[:key_down_raw, 1073741903, 0, 2, 22, 235]
+[:key_down_raw, 1073741903, 0, 2, 23, 237]
+[:key_down_raw, 1073741903, 0, 2, 24, 239]
+[:key_down_raw, 1073741903, 0, 2, 25, 241]
+[:key_down_raw, 1073741903, 0, 2, 26, 243]
+[:key_down_raw, 1073741903, 0, 2, 27, 245]
+[:key_down_raw, 1073741903, 0, 2, 28, 247]
+[:key_down_raw, 1073741903, 0, 2, 29, 249]
+[:key_down_raw, 1073741903, 0, 2, 30, 251]
+[:key_down_raw, 1073741903, 0, 2, 31, 253]
+[:key_down_raw, 1073741903, 0, 2, 32, 255]
+[:key_down_raw, 1073741903, 0, 2, 33, 257]
+[:key_down_raw, 1073741903, 0, 2, 34, 259]
+[:key_down_raw, 1073741903, 0, 2, 35, 261]
+[:key_down_raw, 1073741903, 0, 2, 36, 263]
+[:key_down_raw, 1073741903, 0, 2, 37, 265]
+[:key_down_raw, 1073741903, 0, 2, 38, 267]
+[:key_down_raw, 1073741903, 0, 2, 39, 269]
+[:key_down_raw, 1073741903, 0, 2, 40, 271]
+[:key_down_raw, 1073741906, 0, 2, 41, 271]
+[:key_up_raw, 1073741903, 0, 2, 42, 282]
+[:key_down_raw, 1073741906, 0, 2, 43, 286]
+[:key_down_raw, 1073741906, 0, 2, 44, 288]
+[:key_down_raw, 1073741906, 0, 2, 45, 290]
+[:key_down_raw, 1073741906, 0, 2, 46, 292]
+[:key_down_raw, 1073741906, 0, 2, 47, 294]
+[:key_down_raw, 1073741906, 0, 2, 48, 296]
+[:key_down_raw, 1073741906, 0, 2, 49, 298]
+[:key_down_raw, 1073741906, 0, 2, 50, 301]
+[:key_down_raw, 1073741905, 0, 2, 51, 302]
+[:key_up_raw, 1073741906, 0, 2, 52, 313]
+[:key_down_raw, 1073741904, 0, 2, 53, 315]
+[:key_up_raw, 1073741905, 0, 2, 54, 322]
+[:key_down_raw, 1073741904, 0, 2, 55, 330]
+[:key_down_raw, 1073741904, 0, 2, 56, 332]
+[:key_down_raw, 1073741904, 0, 2, 57, 334]
+[:key_down_raw, 1073741904, 0, 2, 58, 336]
+[:key_down_raw, 1073741904, 0, 2, 59, 338]
+[:key_down_raw, 1073741904, 0, 2, 60, 340]
+[:key_down_raw, 1073741904, 0, 2, 61, 342]
+[:key_down_raw, 1073741904, 0, 2, 62, 344]
+[:key_down_raw, 1073741904, 0, 2, 63, 346]
+[:key_down_raw, 1073741904, 0, 2, 64, 348]
+[:key_down_raw, 1073741904, 0, 2, 65, 350]
+[:key_up_raw, 1073741904, 0, 2, 66, 351]
+[:key_down_raw, 96, 0, 2, 67, 359]
+[:key_up_raw, 96, 0, 2, 68, 364]
+[:key_down_raw, 13, 0, 2, 69, 442]
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-green.png b/samples/02_input_basics/01_moving_a_sprite/sprites/square/green.png
index 5ef7f75..5ef7f75 100644
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-green.png
+++ b/samples/02_input_basics/01_moving_a_sprite/sprites/square/green.png
Binary files differ
diff --git a/samples/02_input_basics/02_mouse/app/main.rb b/samples/02_input_basics/02_mouse/app/main.rb
index 43217f5..23cb619 100644
--- a/samples/02_input_basics/02_mouse/app/main.rb
+++ b/samples/02_input_basics/02_mouse/app/main.rb
@@ -32,7 +32,7 @@ Reminder:
# Use args.inputs.mouse.click.created_at
# To see how many frames its been since the click occurred
-# Use args.inputs.mouse.click.creat_at_elapsed
+# Use args.inputs.mouse.click.created_at_elapsed
# Saving the click in args.state can be quite useful
@@ -61,11 +61,7 @@ def small_label args, x, row, message
# This method effectively combines the row_to_px and small_font methods
# It changes the given row value to a DragonRuby pixel value
# and adds the customization parameters
- [x, row_to_px(args, row), message, small_font]
-end
-
-def small_font
- [-2, 0, 0, 0, 0, 255]
+ { x: x, y: row_to_px(args, row), text: message, alignment_enum: -2 }
end
def row_to_px args, row_number
@@ -81,7 +77,7 @@ def tick_instructions args, text, y = 715
args.state.key_event_occurred = true
end
- args.outputs.debug << [0, y - 50, 1280, 60].solid
- args.outputs.debug << [640, y, text, 1, 1, 255, 255, 255].label
- args.outputs.debug << [640, y - 25, "(click to dismiss instructions)" , -2, 1, 255, 255, 255].label
+ args.outputs.debug << { x: 0, y: y - 50, w: 1280, h: 60 }.solid!
+ args.outputs.debug << { x: 640, y: y, text: text, size_enum: 1, alignment_enum: 1, r: 255, g: 255, b: 255 }.label!
+ args.outputs.debug << { x: 640, y: y - 25, text: "(click to dismiss instructions)", size_enum: -2, alignment_enum: 1, r: 255, g: 255, b: 255 }.label!
end
diff --git a/samples/02_input_basics/03_mouse_point_to_rect/app/main.rb b/samples/02_input_basics/03_mouse_point_to_rect/app/main.rb
index 7dd627f..7d4394c 100644
--- a/samples/02_input_basics/03_mouse_point_to_rect/app/main.rb
+++ b/samples/02_input_basics/03_mouse_point_to_rect/app/main.rb
@@ -42,7 +42,7 @@ def tick args
args.outputs.labels << small_label(args, x, 15, "Click inside the blue box maybe ---->")
- box = [785, 370, 50, 50, 0, 0, 170]
+ box = { x: 785, y: 370, w: 50, h: 50, r: 0, g: 0, b: 170 }
args.outputs.borders << box
# Saves the most recent click into args.state
@@ -64,11 +64,7 @@ def tick args
end
def small_label args, x, row, message
- [x, row_to_px(args, row), message, small_font]
-end
-
-def small_font
- [-2, 0, 0, 0, 0, 255]
+ { x: x, y: row_to_px(args, row), text: message, size_enum: -2 }
end
def row_to_px args, row_number
@@ -84,7 +80,7 @@ def tick_instructions args, text, y = 715
args.state.key_event_occurred = true
end
- args.outputs.debug << [0, y - 50, 1280, 60].solid
- args.outputs.debug << [640, y, text, 1, 1, 255, 255, 255].label
- args.outputs.debug << [640, y - 25, "(click to dismiss instructions)" , -2, 1, 255, 255, 255].label
+ args.outputs.debug << { x: 0, y: y - 50, w: 1280, h: 60 }.solid!
+ args.outputs.debug << { x: 640, y: y, text: text, size_enum: 1, alignment_enum: 1, r: 255, g: 255, b: 255 }.label!
+ args.outputs.debug << { x: 640, y: y - 25, text: "(click to dismiss instructions)", size_enum: -2, alignment_enum: 1, r: 255, g: 255, b: 255 }.label!
end
diff --git a/samples/02_input_basics/04_mouse_rect_to_rect/app/main.rb b/samples/02_input_basics/04_mouse_rect_to_rect/app/main.rb
index 1a00a41..8250598 100644
--- a/samples/02_input_basics/04_mouse_rect_to_rect/app/main.rb
+++ b/samples/02_input_basics/04_mouse_rect_to_rect/app/main.rb
@@ -42,9 +42,15 @@ def tick args
# They are stored in game so that they do not get reset every tick
if args.inputs.mouse.click
if !args.state.box_collision_one
- args.state.box_collision_one = [args.inputs.mouse.click.point.x - 25, args.inputs.mouse.click.point.y - 25, 125, 125, 180, 0, 0, 180]
+ args.state.box_collision_one = { x: args.inputs.mouse.click.point.x - 25,
+ y: args.inputs.mouse.click.point.y - 25,
+ w: 125, h: 125,
+ r: 180, g: 0, b: 0, a: 180 }
elsif !args.state.box_collision_two
- args.state.box_collision_two = [args.inputs.mouse.click.point.x - 25, args.inputs.mouse.click.point.y - 25, 125, 125, 0, 0, 180, 180]
+ args.state.box_collision_two = { x: args.inputs.mouse.click.point.x - 25,
+ y: args.inputs.mouse.click.point.y - 25,
+ w: 125, h: 125,
+ r: 0, g: 0, b: 180, a: 180 }
else
args.state.box_collision_one = nil
args.state.box_collision_two = nil
@@ -71,15 +77,11 @@ def tick args
end
def small_label args, x, row, message
- [x, row_to_px(args, row), message, small_font]
-end
-
-def small_font
- [-2, 0, 0, 0, 0, 255]
+ { x: x, y: row_to_px(args, row), text: message, size_enum: -2 }
end
def row_to_px args, row_number
- args.grid.top.shift_down(5).shift_down(20 * row_number)
+ args.grid.top - 5 - (20 * row_number)
end
def tick_instructions args, text, y = 715
diff --git a/samples/02_input_basics/05_controller/app/main.rb b/samples/02_input_basics/05_controller/app/main.rb
index c986fa9..0ca4bbb 100644
--- a/samples/02_input_basics/05_controller/app/main.rb
+++ b/samples/02_input_basics/05_controller/app/main.rb
@@ -7,6 +7,8 @@
If there is more than one controller being used, they can be differentiated by
using names like controller_one and controller_two.
+ For a full listing of buttons, take a look at mygame/documentation/08-controllers.md.
+
Reminder:
- args.state.PROPERTY: The state property on args is a dynamic
@@ -40,57 +42,51 @@ class ControllerDemo
def process_inputs
state.buttons = []
- state.buttons << [100, 500, inputs.controller_one.key_held.l1, "L1"]
- state.buttons << [100, 600, inputs.controller_one.key_held.l2, "L2"]
-
- state.buttons << [1100, 500, inputs.controller_one.key_held.r1, "R1"]
- state.buttons << [1100, 600, inputs.controller_one.key_held.r2, "R2"]
-
- state.buttons << [540, 450, inputs.controller_one.key_held.select, "Select"]
- state.buttons << [660, 450, inputs.controller_one.key_held.start, "Start"]
-
- state.buttons << [200, 300, inputs.controller_one.key_held.left, "Left"]
- state.buttons << [300, 400, inputs.controller_one.key_held.up, "Up"]
- state.buttons << [400, 300, inputs.controller_one.key_held.right, "Right"]
- state.buttons << [300, 200, inputs.controller_one.key_held.down, "Down"]
-
- state.buttons << [800, 300, inputs.controller_one.key_held.x, "X"]
- state.buttons << [900, 400, inputs.controller_one.key_held.y, "Y"]
- state.buttons << [1000, 300, inputs.controller_one.key_held.a, "A"]
- state.buttons << [900, 200, inputs.controller_one.key_held.b, "B"]
-
- state.buttons << [450 + inputs.controller_one.left_analog_x_perc * 100,
- 100 + inputs.controller_one.left_analog_y_perc * 100,
- inputs.controller_one.key_held.l3,
- "L3"]
-
- state.buttons << [750 + inputs.controller_one.right_analog_x_perc * 100,
- 100 + inputs.controller_one.right_analog_y_perc * 100,
- inputs.controller_one.key_held.r3,
- "R3"]
+ state.buttons << { x: 100, y: 500, active: inputs.controller_one.key_held.l1, text: "L1"}
+ state.buttons << { x: 100, y: 600, active: inputs.controller_one.key_held.l2, text: "L2"}
+ state.buttons << { x: 1100, y: 500, active: inputs.controller_one.key_held.r1, text: "R1"}
+ state.buttons << { x: 1100, y: 600, active: inputs.controller_one.key_held.r2, text: "R2"}
+ state.buttons << { x: 540, y: 450, active: inputs.controller_one.key_held.select, text: "Select"}
+ state.buttons << { x: 660, y: 450, active: inputs.controller_one.key_held.start, text: "Start"}
+ state.buttons << { x: 200, y: 300, active: inputs.controller_one.key_held.left, text: "Left"}
+ state.buttons << { x: 300, y: 400, active: inputs.controller_one.key_held.up, text: "Up"}
+ state.buttons << { x: 400, y: 300, active: inputs.controller_one.key_held.right, text: "Right"}
+ state.buttons << { x: 300, y: 200, active: inputs.controller_one.key_held.down, text: "Down"}
+ state.buttons << { x: 800, y: 300, active: inputs.controller_one.key_held.x, text: "X"}
+ state.buttons << { x: 900, y: 400, active: inputs.controller_one.key_held.y, text: "Y"}
+ state.buttons << { x: 1000, y: 300, active: inputs.controller_one.key_held.a, text: "A"}
+ state.buttons << { x: 900, y: 200, active: inputs.controller_one.key_held.b, text: "B"}
+ state.buttons << { x: 450 + inputs.controller_one.left_analog_x_perc * 100,
+ y: 100 + inputs.controller_one.left_analog_y_perc * 100,
+ active: inputs.controller_one.key_held.l3,
+ text: "L3" }
+ state.buttons << { x: 750 + inputs.controller_one.right_analog_x_perc * 100,
+ y: 100 + inputs.controller_one.right_analog_y_perc * 100,
+ active: inputs.controller_one.key_held.r3,
+ text: "R3" }
end
# Gives each button a square shape.
# If the button is being pressed or held (which means it is considered active),
# the square is filled in. Otherwise, the button simply has a border.
def render
- state.buttons.each do |x, y, active, text|
- rect = [x, y, 75, 75]
+ state.buttons.each do |b|
+ rect = { x: b.x, y: b.y, w: 75, h: 75 }
- if active # if button is pressed
+ if b.active # if button is pressed
outputs.solids << rect # rect is output as solid (filled in)
else
outputs.borders << rect # otherwise, output as border
end
# Outputs the text of each button using labels.
- outputs.labels << [x, y + 95, text] # add 95 to place label above button
+ outputs.labels << { x: b.x, y: b.y + 95, text: b.text } # add 95 to place label above button
end
- outputs.labels << [10, 60, "Left Analog x: #{inputs.controller_one.left_analog_x_raw} (#{inputs.controller_one.left_analog_x_perc * 100}%)"]
- outputs.labels << [10, 30, "Left Analog y: #{inputs.controller_one.left_analog_y_raw} (#{inputs.controller_one.left_analog_y_perc * 100}%)"]
- outputs.labels << [900, 60, "Right Analog x: #{inputs.controller_one.right_analog_x_raw} (#{inputs.controller_one.right_analog_x_perc * 100}%)"]
- outputs.labels << [900, 30, "Right Analog y: #{inputs.controller_one.right_analog_y_raw} (#{inputs.controller_one.right_analog_y_perc * 100}%)"]
+ outputs.labels << { x: 10, y: 60, text: "Left Analog x: #{inputs.controller_one.left_analog_x_raw} (#{inputs.controller_one.left_analog_x_perc * 100}%)" }
+ outputs.labels << { x: 10, y: 30, text: "Left Analog y: #{inputs.controller_one.left_analog_y_raw} (#{inputs.controller_one.left_analog_y_perc * 100}%)" }
+ outputs.labels << { x: 900, y: 60, text: "Right Analog x: #{inputs.controller_one.right_analog_x_raw} (#{inputs.controller_one.right_analog_x_perc * 100}%)" }
+ outputs.labels << { x: 900, y: 30, text: "Right Analog y: #{inputs.controller_one.right_analog_y_raw} (#{inputs.controller_one.right_analog_y_perc * 100}%)" }
end
end
diff --git a/samples/02_input_basics/06_touch/app/main.rb b/samples/02_input_basics/06_touch/app/main.rb
index 8b006c7..501fa74 100644
--- a/samples/02_input_basics/06_touch/app/main.rb
+++ b/samples/02_input_basics/06_touch/app/main.rb
@@ -11,10 +11,12 @@ def tick args
# the next new touch will be finger_one again, but until then, new touches
# don't fill in earlier slots.
if !args.inputs.finger_one.nil?
- args.outputs.primitives << [640, 650, "Finger #1 is touching at (#{args.inputs.finger_one.x}, #{args.inputs.finger_one.y}).", 5, 1, 255, 255, 255].label
+ args.outputs.primitives << { x: 640, y: 650, text: "Finger #1 is touching at (#{args.inputs.finger_one.x}, #{args.inputs.finger_one.y}).",
+ size_enum: 5, alignment_enum: 1, r: 255, g: 255, b: 255 }.label!
end
if !args.inputs.finger_two.nil?
- args.outputs.primitives << [640, 600, "Finger #2 is touching at (#{args.inputs.finger_two.x}, #{args.inputs.finger_two.y}).", 5, 1, 255, 255, 255].label
+ args.outputs.primitives << { x: 640, y: 600, text: "Finger #2 is touching at (#{args.inputs.finger_two.x}, #{args.inputs.finger_two.y}).",
+ size_enum: 5, alignment_enum: 1, r: 255, g: 255, b: 255 }.label!
end
# Here's the more flexible interface: this will report as many simultaneous
@@ -35,8 +37,7 @@ def tick args
r = (color & 0xFF0000) >> 16
g = (color & 0x00FF00) >> 8
b = (color & 0x0000FF)
- args.outputs.primitives << [v.x - (size / 2), v.y + (size / 2), size, size, r, g, b, 255].solid
- args.outputs.primitives << [v.x, v.y + size, k.to_s, 0, 1, 0, 0, 0].label
+ args.outputs.primitives << { x: v.x - (size / 2), y: v.y + (size / 2), w: size, h: size, r: r, g: g, b: b, a: 255 }.solid!
+ args.outputs.primitives << { x: v.x, y: v.y + size, text: k.to_s, alignment_enum: 1 }.label!
}
end
-
diff --git a/samples/03_rendering_sprites/01_animation_using_separate_pngs/app/main.rb b/samples/03_rendering_sprites/01_animation_using_separate_pngs/app/main.rb
index c5622e8..b25aa83 100644
--- a/samples/03_rendering_sprites/01_animation_using_separate_pngs/app/main.rb
+++ b/samples/03_rendering_sprites/01_animation_using_separate_pngs/app/main.rb
@@ -10,12 +10,15 @@
- args.outputs.sprites: An array. Values in this array generate sprites on the screen.
The parameters are [X, Y, WIDTH, HEIGHT, IMAGE PATH]
+ For more information about sprites, go to mygame/documentation/05-sprites.md.
- args.outputs.labels: An array. Values in the array generate labels on the screen.
The parameters are [X, Y, TEXT, SIZE, ALIGNMENT, RED, GREEN, BLUE, ALPHA, FONT STYLE]
+ For more information about labels, go to mygame/documentation/02-labels.md.
- args.inputs.keyboard.key_down.KEY: Determines if a key is in the down state, or pressed.
Stores the frame that key was pressed on.
+ For more information about the keyboard, go to mygame/documentation/06-keyboard.md.
=end
@@ -28,6 +31,8 @@
# in this tick "entry point": `looping_animation`, and the
# second method is `one_time_animation`.
def tick args
+ # uncomment the line below to see animation play out in slow motion
+ # args.gtk.slowmo! 6
looping_animation args
one_time_animation args
end
@@ -60,22 +65,22 @@ def looping_animation args
does_sprite_loop
# Now that we have `sprite_index, we can present the correct file.
- args.outputs.sprites << [100, 100, 100, 100, "sprites/dragon_fly_#{sprite_index}.png"]
+ args.outputs.sprites << { x: 100, y: 100, w: 100, h: 100, path: "sprites/dragon_fly_#{sprite_index}.png" }
# Try changing the numbers below to see how the animation changes:
- args.outputs.sprites << [100, 200, 100, 100, "sprites/dragon_fly_#{0.frame_index 6, 4, true}.png"]
+ args.outputs.sprites << { x: 100, y: 200, w: 100, h: 100, path: "sprites/dragon_fly_#{0.frame_index 6, 4, true}.png" }
end
# This function shows how to animate a sprite that executes
# only once when the "f" key is pressed.
def one_time_animation args
# This is just a label the shows instructions within the game.
- args.outputs.labels << [220, 350, "(press f to animate)"]
+ args.outputs.labels << { x: 220, y: 350, text: "(press f to animate)" }
# If "f" is pressed on the keyboard...
if args.inputs.keyboard.key_down.f
# Print the frame that "f" was pressed on.
- puts "Hello from main.rb! The \"f\" key was in the down state on frame: #{args.inputs.keyboard.key_down.f}"
+ puts "Hello from main.rb! The \"f\" key was in the down state on frame: #{args.state.tick_count}"
# And MOST IMPORTANTLY set the point it time to start the animation,
# equal to "now" which is represented as args.state.tick_count.
@@ -108,7 +113,7 @@ def one_time_animation args
sprite_index ||= 0
# Present the sprite.
- args.outputs.sprites << [100, 300, 100, 100, "sprites/dragon_fly_#{sprite_index}.png"]
+ args.outputs.sprites << { x: 100, y: 300, w: 100, h: 100, path: "sprites/dragon_fly_#{sprite_index}.png" }
tick_instructions args, "Sample app shows how to use Numeric#frame_index and string interpolation to animate a sprite over time."
end
diff --git a/samples/03_rendering_sprites/02_animation_using_sprite_sheet/replay.txt b/samples/03_rendering_sprites/02_animation_using_sprite_sheet/replay.txt
new file mode 100644
index 0000000..8927ef0
--- /dev/null
+++ b/samples/03_rendering_sprites/02_animation_using_sprite_sheet/replay.txt
@@ -0,0 +1,241 @@
+replay_version 2.0
+stopped_at 805
+seed 100
+recorded_at Sat Jul 17 09:26:10 2021
+[:mouse_button_up, 1, 0, 1, 1, 6]
+[:key_down_raw, 1073741906, 0, 2, 2, 69]
+[:key_down_raw, 1073741906, 0, 2, 3, 83]
+[:key_down_raw, 1073741906, 0, 2, 4, 85]
+[:key_down_raw, 1073741906, 0, 2, 5, 87]
+[:key_down_raw, 1073741906, 0, 2, 6, 89]
+[:key_down_raw, 1073741906, 0, 2, 7, 91]
+[:key_down_raw, 1073741906, 0, 2, 8, 93]
+[:key_down_raw, 1073741906, 0, 2, 9, 95]
+[:key_down_raw, 1073741906, 0, 2, 10, 97]
+[:key_down_raw, 1073741906, 0, 2, 11, 99]
+[:key_down_raw, 1073741906, 0, 2, 12, 101]
+[:key_down_raw, 1073741906, 0, 2, 13, 103]
+[:key_down_raw, 1073741906, 0, 2, 14, 105]
+[:key_down_raw, 1073741906, 0, 2, 15, 107]
+[:key_down_raw, 1073741906, 0, 2, 16, 109]
+[:key_down_raw, 1073741906, 0, 2, 17, 111]
+[:key_down_raw, 1073741906, 0, 2, 18, 113]
+[:key_down_raw, 1073741906, 0, 2, 19, 115]
+[:key_down_raw, 1073741906, 0, 2, 20, 117]
+[:key_down_raw, 1073741906, 0, 2, 21, 119]
+[:key_down_raw, 1073741906, 0, 2, 22, 121]
+[:key_down_raw, 1073741906, 0, 2, 23, 123]
+[:key_down_raw, 1073741906, 0, 2, 24, 125]
+[:key_down_raw, 1073741906, 0, 2, 25, 127]
+[:key_down_raw, 1073741906, 0, 2, 26, 129]
+[:key_up_raw, 1073741906, 0, 2, 27, 130]
+[:key_down_raw, 1073741903, 0, 2, 28, 131]
+[:key_down_raw, 1073741903, 0, 2, 29, 146]
+[:key_down_raw, 1073741903, 0, 2, 30, 148]
+[:key_down_raw, 1073741903, 0, 2, 31, 150]
+[:key_down_raw, 1073741903, 0, 2, 32, 152]
+[:key_down_raw, 1073741903, 0, 2, 33, 154]
+[:key_down_raw, 1073741903, 0, 2, 34, 156]
+[:key_down_raw, 1073741903, 0, 2, 35, 158]
+[:key_down_raw, 1073741903, 0, 2, 36, 160]
+[:key_down_raw, 1073741903, 0, 2, 37, 162]
+[:key_down_raw, 1073741903, 0, 2, 38, 164]
+[:key_down_raw, 1073741903, 0, 2, 39, 166]
+[:key_down_raw, 1073741903, 0, 2, 40, 168]
+[:key_down_raw, 1073741903, 0, 2, 41, 170]
+[:key_down_raw, 1073741903, 0, 2, 42, 172]
+[:key_down_raw, 1073741903, 0, 2, 43, 174]
+[:key_down_raw, 1073741903, 0, 2, 44, 176]
+[:key_down_raw, 1073741903, 0, 2, 45, 178]
+[:key_down_raw, 1073741903, 0, 2, 46, 180]
+[:key_down_raw, 1073741903, 0, 2, 47, 182]
+[:key_down_raw, 1073741903, 0, 2, 48, 184]
+[:key_down_raw, 1073741903, 0, 2, 49, 186]
+[:key_down_raw, 1073741903, 0, 2, 50, 189]
+[:key_down_raw, 1073741903, 0, 2, 51, 190]
+[:key_down_raw, 1073741903, 0, 2, 52, 192]
+[:key_down_raw, 1073741903, 0, 2, 53, 194]
+[:key_down_raw, 1073741903, 0, 2, 54, 196]
+[:key_down_raw, 1073741903, 0, 2, 55, 198]
+[:key_down_raw, 1073741903, 0, 2, 56, 200]
+[:key_down_raw, 1073741903, 0, 2, 57, 203]
+[:key_down_raw, 1073741903, 0, 2, 58, 204]
+[:key_down_raw, 1073741903, 0, 2, 59, 206]
+[:key_down_raw, 1073741903, 0, 2, 60, 208]
+[:key_down_raw, 1073741903, 0, 2, 61, 210]
+[:key_down_raw, 1073741903, 0, 2, 62, 212]
+[:key_down_raw, 1073741903, 0, 2, 63, 214]
+[:key_down_raw, 1073741903, 0, 2, 64, 216]
+[:key_down_raw, 1073741903, 0, 2, 65, 218]
+[:key_down_raw, 1073741903, 0, 2, 66, 220]
+[:key_down_raw, 1073741904, 0, 2, 67, 221]
+[:key_up_raw, 1073741903, 0, 2, 68, 225]
+[:key_down_raw, 1073741904, 0, 2, 69, 236]
+[:key_down_raw, 1073741904, 0, 2, 70, 238]
+[:key_down_raw, 1073741904, 0, 2, 71, 240]
+[:key_down_raw, 1073741904, 0, 2, 72, 242]
+[:key_down_raw, 1073741904, 0, 2, 73, 244]
+[:key_down_raw, 1073741904, 0, 2, 74, 246]
+[:key_down_raw, 1073741904, 0, 2, 75, 248]
+[:key_down_raw, 1073741904, 0, 2, 76, 250]
+[:key_up_raw, 1073741904, 0, 2, 77, 251]
+[:key_down_raw, 1073741906, 0, 2, 78, 253]
+[:key_down_raw, 1073741906, 0, 2, 79, 268]
+[:key_down_raw, 1073741906, 0, 2, 80, 270]
+[:key_down_raw, 1073741906, 0, 2, 81, 272]
+[:key_down_raw, 1073741906, 0, 2, 82, 275]
+[:key_down_raw, 1073741906, 0, 2, 83, 276]
+[:key_down_raw, 1073741906, 0, 2, 84, 278]
+[:key_down_raw, 1073741906, 0, 2, 85, 280]
+[:key_down_raw, 1073741906, 0, 2, 86, 283]
+[:key_down_raw, 1073741906, 0, 2, 87, 285]
+[:key_down_raw, 1073741906, 0, 2, 88, 287]
+[:key_down_raw, 1073741906, 0, 2, 89, 289]
+[:key_down_raw, 1073741906, 0, 2, 90, 291]
+[:key_down_raw, 1073741906, 0, 2, 91, 293]
+[:key_down_raw, 1073741906, 0, 2, 92, 294]
+[:key_down_raw, 1073741906, 0, 2, 93, 296]
+[:key_down_raw, 1073741906, 0, 2, 94, 299]
+[:key_down_raw, 1073741906, 0, 2, 95, 301]
+[:key_down_raw, 1073741906, 0, 2, 96, 303]
+[:key_up_raw, 1073741906, 0, 2, 97, 303]
+[:key_down_raw, 1073741905, 0, 2, 98, 307]
+[:key_down_raw, 1073741905, 0, 2, 99, 322]
+[:key_down_raw, 1073741905, 0, 2, 100, 324]
+[:key_down_raw, 1073741905, 0, 2, 101, 326]
+[:key_down_raw, 1073741905, 0, 2, 102, 328]
+[:key_down_raw, 1073741905, 0, 2, 103, 330]
+[:key_down_raw, 1073741905, 0, 2, 104, 332]
+[:key_down_raw, 1073741905, 0, 2, 105, 334]
+[:key_down_raw, 1073741905, 0, 2, 106, 336]
+[:key_up_raw, 1073741905, 0, 2, 107, 336]
+[:key_down_raw, 1073741903, 0, 2, 108, 337]
+[:key_down_raw, 1073741906, 0, 2, 109, 342]
+[:key_down_raw, 1073741906, 0, 2, 110, 357]
+[:key_down_raw, 1073741906, 0, 2, 111, 359]
+[:key_down_raw, 1073741906, 0, 2, 112, 361]
+[:key_down_raw, 1073741906, 0, 2, 113, 363]
+[:key_down_raw, 1073741906, 0, 2, 114, 365]
+[:key_down_raw, 1073741906, 0, 2, 115, 367]
+[:key_down_raw, 1073741906, 0, 2, 116, 369]
+[:key_down_raw, 1073741906, 0, 2, 117, 371]
+[:key_down_raw, 1073741906, 0, 2, 118, 373]
+[:key_down_raw, 1073741906, 0, 2, 119, 375]
+[:key_down_raw, 1073741906, 0, 2, 120, 377]
+[:key_down_raw, 1073741906, 0, 2, 121, 379]
+[:key_down_raw, 1073741906, 0, 2, 122, 381]
+[:key_down_raw, 1073741906, 0, 2, 123, 383]
+[:key_down_raw, 1073741906, 0, 2, 124, 385]
+[:key_down_raw, 1073741906, 0, 2, 125, 387]
+[:key_down_raw, 1073741906, 0, 2, 126, 389]
+[:key_down_raw, 1073741906, 0, 2, 127, 391]
+[:key_up_raw, 1073741903, 0, 2, 128, 392]
+[:key_down_raw, 1073741906, 0, 2, 129, 393]
+[:key_up_raw, 1073741906, 0, 2, 130, 394]
+[:key_down_raw, 1073741904, 0, 2, 131, 404]
+[:key_down_raw, 1073741905, 0, 2, 132, 407]
+[:key_down_raw, 1073741905, 0, 2, 133, 421]
+[:key_down_raw, 1073741905, 0, 2, 134, 423]
+[:key_down_raw, 1073741905, 0, 2, 135, 425]
+[:key_down_raw, 1073741905, 0, 2, 136, 428]
+[:key_down_raw, 1073741905, 0, 2, 137, 429]
+[:key_down_raw, 1073741905, 0, 2, 138, 431]
+[:key_down_raw, 1073741905, 0, 2, 139, 433]
+[:key_down_raw, 1073741905, 0, 2, 140, 435]
+[:key_down_raw, 1073741905, 0, 2, 141, 437]
+[:key_down_raw, 1073741905, 0, 2, 142, 439]
+[:key_down_raw, 1073741905, 0, 2, 143, 441]
+[:key_down_raw, 1073741905, 0, 2, 144, 443]
+[:key_down_raw, 1073741905, 0, 2, 145, 445]
+[:key_down_raw, 1073741905, 0, 2, 146, 447]
+[:key_down_raw, 1073741905, 0, 2, 147, 449]
+[:key_up_raw, 1073741905, 0, 2, 148, 451]
+[:key_up_raw, 1073741904, 0, 2, 149, 453]
+[:key_down_raw, 1073741904, 0, 2, 150, 456]
+[:key_up_raw, 1073741904, 0, 2, 151, 462]
+[:key_down_raw, 1073741905, 0, 2, 152, 464]
+[:key_down_raw, 1073741905, 0, 2, 153, 479]
+[:key_down_raw, 1073741905, 0, 2, 154, 481]
+[:key_down_raw, 1073741905, 0, 2, 155, 483]
+[:key_down_raw, 1073741905, 0, 2, 156, 485]
+[:key_down_raw, 1073741905, 0, 2, 157, 487]
+[:key_down_raw, 1073741905, 0, 2, 158, 489]
+[:key_down_raw, 1073741905, 0, 2, 159, 491]
+[:key_down_raw, 1073741905, 0, 2, 160, 493]
+[:key_down_raw, 1073741905, 0, 2, 161, 495]
+[:key_down_raw, 1073741905, 0, 2, 162, 497]
+[:key_down_raw, 1073741905, 0, 2, 163, 499]
+[:key_down_raw, 1073741906, 0, 2, 164, 500]
+[:key_down_raw, 1073741906, 0, 2, 165, 515]
+[:key_down_raw, 1073741906, 0, 2, 166, 517]
+[:key_down_raw, 1073741906, 0, 2, 167, 519]
+[:key_down_raw, 1073741906, 0, 2, 168, 521]
+[:key_down_raw, 1073741906, 0, 2, 169, 523]
+[:key_down_raw, 1073741906, 0, 2, 170, 525]
+[:key_down_raw, 1073741906, 0, 2, 171, 527]
+[:key_down_raw, 1073741906, 0, 2, 172, 529]
+[:key_down_raw, 1073741906, 0, 2, 173, 531]
+[:key_down_raw, 1073741906, 0, 2, 174, 533]
+[:key_down_raw, 1073741906, 0, 2, 175, 535]
+[:key_down_raw, 1073741906, 0, 2, 176, 537]
+[:key_down_raw, 1073741906, 0, 2, 177, 539]
+[:key_down_raw, 1073741906, 0, 2, 178, 541]
+[:key_down_raw, 1073741906, 0, 2, 179, 543]
+[:key_down_raw, 1073741906, 0, 2, 180, 545]
+[:key_down_raw, 1073741903, 0, 2, 181, 547]
+[:key_up_raw, 1073741905, 0, 2, 182, 555]
+[:key_down_raw, 1073741905, 0, 2, 183, 558]
+[:key_up_raw, 1073741906, 0, 2, 184, 564]
+[:key_down_raw, 1073741905, 0, 2, 185, 573]
+[:key_down_raw, 1073741905, 0, 2, 186, 575]
+[:key_down_raw, 1073741905, 0, 2, 187, 577]
+[:key_down_raw, 1073741905, 0, 2, 188, 579]
+[:key_down_raw, 1073741905, 0, 2, 189, 581]
+[:key_down_raw, 1073741905, 0, 2, 190, 583]
+[:key_down_raw, 1073741905, 0, 2, 191, 585]
+[:key_down_raw, 1073741905, 0, 2, 192, 587]
+[:key_down_raw, 1073741905, 0, 2, 193, 589]
+[:key_down_raw, 1073741905, 0, 2, 194, 591]
+[:key_down_raw, 1073741905, 0, 2, 195, 593]
+[:key_down_raw, 1073741905, 0, 2, 196, 595]
+[:key_down_raw, 1073741905, 0, 2, 197, 597]
+[:key_down_raw, 1073741905, 0, 2, 198, 599]
+[:key_down_raw, 1073741905, 0, 2, 199, 601]
+[:key_down_raw, 1073741905, 0, 2, 200, 603]
+[:key_down_raw, 1073741905, 0, 2, 201, 605]
+[:key_up_raw, 1073741905, 0, 2, 202, 605]
+[:key_up_raw, 1073741903, 0, 2, 203, 606]
+[:key_down_raw, 96, 0, 2, 204, 640]
+[:key_up_raw, 96, 0, 2, 205, 646]
+[:mouse_move, 796, 95, 2, 206, 683]
+[:mouse_move, 798, 95, 2, 207, 684]
+[:mouse_move, 808, 94, 2, 208, 685]
+[:mouse_move, 814, 94, 2, 209, 686]
+[:mouse_move, 826, 94, 2, 210, 687]
+[:mouse_move, 832, 94, 2, 211, 688]
+[:mouse_move, 842, 94, 2, 212, 689]
+[:mouse_move, 846, 94, 2, 213, 690]
+[:mouse_move, 856, 93, 2, 214, 691]
+[:mouse_move, 860, 93, 2, 215, 692]
+[:mouse_move, 867, 93, 2, 216, 693]
+[:mouse_move, 869, 93, 2, 217, 694]
+[:mouse_move, 870, 93, 2, 218, 695]
+[:mouse_move, 871, 93, 2, 219, 697]
+[:mouse_move, 872, 93, 2, 220, 698]
+[:mouse_move, 873, 93, 2, 221, 699]
+[:mouse_move, 874, 93, 2, 222, 701]
+[:mouse_move, 875, 93, 2, 223, 703]
+[:mouse_move, 877, 94, 2, 224, 704]
+[:mouse_move, 878, 94, 2, 225, 705]
+[:mouse_move, 879, 94, 2, 226, 706]
+[:mouse_move, 869, 95, 2, 227, 758]
+[:mouse_move, 864, 96, 2, 228, 759]
+[:mouse_move, 856, 96, 2, 229, 760]
+[:mouse_move, 852, 96, 2, 230, 761]
+[:mouse_move, 834, 96, 2, 231, 762]
+[:mouse_move, 821, 96, 2, 232, 763]
+[:mouse_move, 797, 96, 2, 233, 764]
+[:mouse_move, 789, 96, 2, 234, 765]
+[:mouse_move, 780, 94, 2, 235, 766]
+[:mouse_move, 779, 94, 2, 236, 767]
+[:key_down_raw, 13, 0, 2, 237, 805]
diff --git a/samples/03_rendering_sprites/03_animation_states/replay.txt b/samples/03_rendering_sprites/03_animation_states/replay.txt
new file mode 100644
index 0000000..f9d1962
--- /dev/null
+++ b/samples/03_rendering_sprites/03_animation_states/replay.txt
@@ -0,0 +1,182 @@
+replay_version 2.0
+stopped_at 770
+seed 100
+recorded_at Sat Jul 17 09:29:30 2021
+[:mouse_button_up, 1, 0, 1, 1, 4]
+[:key_down_raw, 1073741903, 0, 2, 2, 75]
+[:key_down_raw, 1073741903, 0, 2, 3, 89]
+[:key_down_raw, 1073741903, 0, 2, 4, 91]
+[:key_down_raw, 1073741903, 0, 2, 5, 93]
+[:key_down_raw, 1073741903, 0, 2, 6, 95]
+[:key_down_raw, 1073741903, 0, 2, 7, 97]
+[:key_down_raw, 1073741903, 0, 2, 8, 99]
+[:key_down_raw, 1073741903, 0, 2, 9, 101]
+[:key_down_raw, 1073741903, 0, 2, 10, 103]
+[:key_down_raw, 1073741903, 0, 2, 11, 105]
+[:key_down_raw, 1073741903, 0, 2, 12, 107]
+[:key_down_raw, 1073741903, 0, 2, 13, 109]
+[:key_down_raw, 1073741903, 0, 2, 14, 111]
+[:key_down_raw, 1073741903, 0, 2, 15, 113]
+[:key_down_raw, 1073741903, 0, 2, 16, 115]
+[:key_down_raw, 1073741903, 0, 2, 17, 117]
+[:key_down_raw, 1073741903, 0, 2, 18, 119]
+[:key_down_raw, 1073741903, 0, 2, 19, 121]
+[:key_down_raw, 1073741903, 0, 2, 20, 123]
+[:key_down_raw, 1073741903, 0, 2, 21, 125]
+[:key_down_raw, 1073741903, 0, 2, 22, 127]
+[:key_down_raw, 1073741903, 0, 2, 23, 129]
+[:key_down_raw, 1073741903, 0, 2, 24, 131]
+[:key_down_raw, 1073741903, 0, 2, 25, 133]
+[:key_down_raw, 1073741903, 0, 2, 26, 135]
+[:key_down_raw, 1073741903, 0, 2, 27, 137]
+[:key_down_raw, 1073741903, 0, 2, 28, 139]
+[:key_down_raw, 1073741903, 0, 2, 29, 141]
+[:key_down_raw, 1073741903, 0, 2, 30, 143]
+[:key_down_raw, 1073741903, 0, 2, 31, 145]
+[:key_down_raw, 1073741903, 0, 2, 32, 147]
+[:key_down_raw, 1073741903, 0, 2, 33, 149]
+[:key_down_raw, 1073741903, 0, 2, 34, 151]
+[:key_down_raw, 1073741903, 0, 2, 35, 153]
+[:key_down_raw, 1073741903, 0, 2, 36, 155]
+[:key_down_raw, 1073741903, 0, 2, 37, 157]
+[:key_down_raw, 1073741903, 0, 2, 38, 159]
+[:key_down_raw, 1073741903, 0, 2, 39, 161]
+[:key_down_raw, 1073741903, 0, 2, 40, 163]
+[:key_down_raw, 1073741903, 0, 2, 41, 165]
+[:key_down_raw, 1073741903, 0, 2, 42, 167]
+[:key_down_raw, 1073741903, 0, 2, 43, 169]
+[:key_down_raw, 1073741903, 0, 2, 44, 171]
+[:key_down_raw, 1073741903, 0, 2, 45, 173]
+[:key_down_raw, 1073741903, 0, 2, 46, 175]
+[:key_down_raw, 1073741903, 0, 2, 47, 177]
+[:key_down_raw, 1073741903, 0, 2, 48, 179]
+[:key_down_raw, 1073741903, 0, 2, 49, 181]
+[:key_down_raw, 1073741903, 0, 2, 50, 183]
+[:key_down_raw, 1073741903, 0, 2, 51, 185]
+[:key_down_raw, 1073741903, 0, 2, 52, 187]
+[:key_down_raw, 1073741903, 0, 2, 53, 189]
+[:key_down_raw, 1073741903, 0, 2, 54, 191]
+[:key_down_raw, 1073741903, 0, 2, 55, 193]
+[:key_down_raw, 1073741903, 0, 2, 56, 195]
+[:key_down_raw, 1073741903, 0, 2, 57, 197]
+[:key_down_raw, 1073741903, 0, 2, 58, 199]
+[:key_down_raw, 1073741903, 0, 2, 59, 201]
+[:key_down_raw, 1073741903, 0, 2, 60, 203]
+[:key_down_raw, 1073741903, 0, 2, 61, 205]
+[:key_down_raw, 1073741903, 0, 2, 62, 207]
+[:key_down_raw, 1073741903, 0, 2, 63, 209]
+[:key_down_raw, 1073741903, 0, 2, 64, 211]
+[:key_down_raw, 1073741903, 0, 2, 65, 213]
+[:key_down_raw, 1073741903, 0, 2, 66, 215]
+[:key_down_raw, 1073741903, 0, 2, 67, 217]
+[:key_down_raw, 1073741903, 0, 2, 68, 219]
+[:key_down_raw, 1073741903, 0, 2, 69, 221]
+[:key_down_raw, 1073741903, 0, 2, 70, 223]
+[:key_down_raw, 1073741903, 0, 2, 71, 225]
+[:key_down_raw, 1073741903, 0, 2, 72, 227]
+[:key_down_raw, 1073741903, 0, 2, 73, 229]
+[:key_down_raw, 1073741903, 0, 2, 74, 231]
+[:key_down_raw, 1073741903, 0, 2, 75, 233]
+[:key_down_raw, 1073741903, 0, 2, 76, 235]
+[:key_down_raw, 1073741903, 0, 2, 77, 237]
+[:key_down_raw, 1073741903, 0, 2, 78, 239]
+[:key_down_raw, 1073741903, 0, 2, 79, 241]
+[:key_down_raw, 1073741903, 0, 2, 80, 243]
+[:key_down_raw, 1073741903, 0, 2, 81, 245]
+[:key_down_raw, 1073741903, 0, 2, 82, 247]
+[:key_down_raw, 1073741903, 0, 2, 83, 249]
+[:key_up_raw, 1073741903, 0, 2, 84, 250]
+[:key_down_raw, 106, 0, 2, 85, 269]
+[:key_up_raw, 106, 0, 2, 86, 277]
+[:key_down_raw, 1073741905, 0, 2, 87, 299]
+[:key_down_raw, 1073741905, 0, 2, 88, 314]
+[:key_down_raw, 1073741905, 0, 2, 89, 316]
+[:key_down_raw, 1073741905, 0, 2, 90, 318]
+[:key_down_raw, 1073741905, 0, 2, 91, 320]
+[:key_down_raw, 1073741905, 0, 2, 92, 322]
+[:key_down_raw, 1073741905, 0, 2, 93, 324]
+[:key_down_raw, 1073741905, 0, 2, 94, 326]
+[:key_down_raw, 1073741905, 0, 2, 95, 328]
+[:key_down_raw, 1073741905, 0, 2, 96, 330]
+[:key_down_raw, 1073741905, 0, 2, 97, 332]
+[:key_down_raw, 1073741905, 0, 2, 98, 334]
+[:key_down_raw, 1073741905, 0, 2, 99, 336]
+[:key_down_raw, 1073741905, 0, 2, 100, 338]
+[:key_down_raw, 1073741905, 0, 2, 101, 340]
+[:key_down_raw, 1073741904, 0, 2, 102, 341]
+[:key_down_raw, 1073741904, 0, 2, 103, 356]
+[:key_down_raw, 1073741904, 0, 2, 104, 358]
+[:key_down_raw, 1073741904, 0, 2, 105, 360]
+[:key_down_raw, 1073741904, 0, 2, 106, 362]
+[:key_down_raw, 1073741904, 0, 2, 107, 364]
+[:key_down_raw, 1073741904, 0, 2, 108, 366]
+[:key_down_raw, 1073741904, 0, 2, 109, 368]
+[:key_down_raw, 1073741904, 0, 2, 110, 370]
+[:key_up_raw, 1073741904, 0, 2, 111, 371]
+[:key_up_raw, 1073741905, 0, 2, 112, 373]
+[:key_down_raw, 1073741906, 0, 2, 113, 378]
+[:key_down_raw, 1073741906, 0, 2, 114, 393]
+[:key_down_raw, 1073741906, 0, 2, 115, 395]
+[:key_down_raw, 1073741906, 0, 2, 116, 397]
+[:key_down_raw, 1073741906, 0, 2, 117, 399]
+[:key_up_raw, 1073741906, 0, 2, 118, 401]
+[:key_down_raw, 1073741904, 0, 2, 119, 402]
+[:key_down_raw, 1073741904, 0, 2, 120, 419]
+[:key_down_raw, 1073741904, 0, 2, 121, 421]
+[:key_down_raw, 1073741904, 0, 2, 122, 423]
+[:key_down_raw, 1073741904, 0, 2, 123, 425]
+[:key_down_raw, 1073741904, 0, 2, 124, 427]
+[:key_up_raw, 1073741904, 0, 2, 125, 429]
+[:key_down_raw, 1073741904, 0, 2, 126, 434]
+[:key_up_raw, 1073741904, 0, 2, 127, 437]
+[:key_down_raw, 106, 0, 2, 128, 457]
+[:key_up_raw, 106, 0, 2, 129, 463]
+[:key_down_raw, 1073741903, 0, 2, 130, 490]
+[:key_up_raw, 1073741903, 0, 2, 131, 500]
+[:key_down_raw, 1073741906, 0, 2, 132, 501]
+[:key_down_raw, 1073741906, 0, 2, 133, 516]
+[:key_down_raw, 1073741906, 0, 2, 134, 518]
+[:key_down_raw, 1073741906, 0, 2, 135, 520]
+[:key_up_raw, 1073741906, 0, 2, 136, 521]
+[:key_down_raw, 1073741904, 0, 2, 137, 532]
+[:key_down_raw, 1073741904, 0, 2, 138, 547]
+[:key_down_raw, 1073741904, 0, 2, 139, 549]
+[:key_up_raw, 1073741904, 0, 2, 140, 550]
+[:key_down_raw, 1073741903, 0, 2, 141, 552]
+[:key_down_raw, 1073741903, 0, 2, 142, 567]
+[:key_up_raw, 1073741903, 0, 2, 143, 568]
+[:key_down_raw, 106, 0, 2, 144, 574]
+[:key_up_raw, 106, 0, 2, 145, 580]
+[:key_down_raw, 96, 0, 2, 146, 661]
+[:key_up_raw, 96, 0, 2, 147, 666]
+[:mouse_move, 799, 92, 2, 148, 693]
+[:mouse_move, 803, 92, 2, 149, 694]
+[:mouse_move, 811, 91, 2, 150, 695]
+[:mouse_move, 816, 90, 2, 151, 696]
+[:mouse_move, 827, 88, 2, 152, 697]
+[:mouse_move, 830, 87, 2, 153, 698]
+[:mouse_move, 835, 87, 2, 154, 699]
+[:mouse_move, 837, 87, 2, 155, 700]
+[:mouse_move, 838, 87, 2, 156, 701]
+[:mouse_move, 838, 86, 2, 157, 702]
+[:mouse_move, 839, 86, 2, 158, 704]
+[:mouse_move, 838, 86, 2, 159, 712]
+[:mouse_move, 838, 87, 2, 160, 713]
+[:mouse_move, 835, 87, 2, 161, 714]
+[:mouse_move, 832, 87, 2, 162, 715]
+[:mouse_move, 824, 87, 2, 163, 716]
+[:mouse_move, 820, 87, 2, 164, 717]
+[:mouse_move, 809, 87, 2, 165, 718]
+[:mouse_move, 805, 87, 2, 166, 719]
+[:mouse_move, 800, 86, 2, 167, 720]
+[:mouse_move, 799, 86, 2, 168, 721]
+[:mouse_move, 798, 86, 2, 169, 722]
+[:mouse_move, 797, 86, 2, 170, 723]
+[:mouse_move, 796, 86, 2, 171, 724]
+[:mouse_move, 798, 86, 2, 172, 742]
+[:mouse_move, 805, 86, 2, 173, 743]
+[:mouse_move, 807, 86, 2, 174, 744]
+[:mouse_move, 810, 86, 2, 175, 745]
+[:mouse_move, 811, 86, 2, 176, 747]
+[:mouse_move, 811, 85, 2, 177, 760]
+[:key_down_raw, 13, 0, 2, 178, 770]
diff --git a/samples/03_rendering_sprites/04_color_and_rotation/app/main.rb b/samples/03_rendering_sprites/04_color_and_rotation/app/main.rb
index 072feaf..c3f2d8f 100644
--- a/samples/03_rendering_sprites/04_color_and_rotation/app/main.rb
+++ b/samples/03_rendering_sprites/04_color_and_rotation/app/main.rb
@@ -21,10 +21,14 @@
- args.outputs.sprites: An array. The values generate a sprite.
The parameters are [X, Y, WIDTH, HEIGHT, PATH, ANGLE, ALPHA, RED, GREEN, BLUE]
+ Before continuing with this sample app, it is HIGHLY recommended that you look
+ at mygame/documentation/05-sprites.md.
- args.inputs.keyboard.key_held.KEY: Determines if a key is being pressed.
+ For more information about the keyboard, go to mygame/documentation/06-keyboard.md.
- args.inputs.controller_one: Takes input from the controller based on what key is pressed.
+ For more information about the controller, go to mygame/documentation/08-controllers.md.
- num1.lesser(num2): Finds the lower value of the given options.
diff --git a/samples/04_physics_and_collisions/02_moving_objects/app/main.rb b/samples/04_physics_and_collisions/02_moving_objects/app/main.rb
index e3e9261..35eabfb 100644
--- a/samples/04_physics_and_collisions/02_moving_objects/app/main.rb
+++ b/samples/04_physics_and_collisions/02_moving_objects/app/main.rb
@@ -48,11 +48,13 @@
Reminders:
- args.inputs.keyboard.KEY: Determines if a key has been pressed.
+ For more information about the keyboard, take a look at mygame/documentation/06-keyboard.md.
- ARRAY#intersect_rect?: Returns true or false depending on if the two rectangles intersect.
- args.outputs.solids: An array. The values generate a solid.
The parameters are [X, Y, WIDTH, HEIGHT, RED, GREEN, BLUE]
+ For more information about solids, go to mygame/documentation/03-solids-and-borders.md.
=end
diff --git a/samples/04_physics_and_collisions/06_box_collision_3/app/main.rb b/samples/04_physics_and_collisions/06_box_collision_3/app/main.rb
index 2e32eee..e2210c2 100644
--- a/samples/04_physics_and_collisions/06_box_collision_3/app/main.rb
+++ b/samples/04_physics_and_collisions/06_box_collision_3/app/main.rb
@@ -46,9 +46,9 @@ class Game
mouse_overlay = mouse_overlay.merge r: 255 if state.delete_mode
if state.mouse_held
- outputs.primitives << mouse_overlay.border
+ outputs.primitives << mouse_overlay.border!
else
- outputs.primitives << mouse_overlay.solid
+ outputs.primitives << mouse_overlay.solid!
end
end
@@ -112,7 +112,7 @@ class Game
def calc_below
return unless player.dy <= 0
- tiles_below = find_tiles { |t| t.rect.top <= player.y }
+ tiles_below = find_tiles { |t| t.rect.top <= player.prev_rect.y }
collision = find_colliding_tile tiles_below, (player.rect.merge y: player.next_rect.y)
return unless collision
if collision.neighbors.b == :none && player.jumped_down_at.elapsed_time < 10
@@ -143,7 +143,7 @@ class Game
def calc_above
return unless player.dy > 0
- tiles_above = find_tiles { |t| t.rect.y >= player.y }
+ tiles_above = find_tiles { |t| t.rect.y >= player.prev_rect.y }
collision = find_colliding_tile tiles_above, (player.rect.merge y: player.next_rect.y)
return unless collision
return if collision.neighbors.t == :none
@@ -152,17 +152,17 @@ class Game
end
def calc_player_dx
- player.y += player.dy
- player.dy += state.gravity
- player.dy += player.dy * state.drag ** 2 * -1
- end
-
- def calc_player_dy
player.dx = player.dx.clamp(-5, 5)
player.dx *= 0.9
player.x += player.dx
end
+ def calc_player_dy
+ player.y += player.dy
+ player.dy += state.gravity
+ player.dy += player.dy * state.drag ** 2 * -1
+ end
+
def reset_player
player.x = 100
player.y = 720
diff --git a/samples/04_physics_and_collisions/06_box_collision_3/replay.txt b/samples/04_physics_and_collisions/06_box_collision_3/replay.txt
new file mode 100644
index 0000000..0f4373e
--- /dev/null
+++ b/samples/04_physics_and_collisions/06_box_collision_3/replay.txt
@@ -0,0 +1,687 @@
+replay_version 2.0
+stopped_at 2166
+seed 100
+recorded_at Sat Jul 17 09:33:34 2021
+[:mouse_button_up, 1, 0, 1, 1, 5]
+[:mouse_move, 805, 89, 2, 2, 19]
+[:mouse_move, 805, 91, 2, 3, 20]
+[:mouse_move, 803, 96, 2, 4, 21]
+[:mouse_move, 802, 99, 2, 5, 22]
+[:mouse_move, 799, 103, 2, 6, 23]
+[:mouse_move, 797, 107, 2, 7, 24]
+[:mouse_move, 786, 124, 2, 8, 25]
+[:mouse_move, 772, 141, 2, 9, 26]
+[:mouse_move, 716, 207, 2, 10, 27]
+[:mouse_move, 638, 289, 2, 11, 29]
+[:mouse_move, 608, 314, 2, 12, 29]
+[:mouse_move, 562, 342, 2, 13, 31]
+[:mouse_move, 541, 350, 2, 14, 31]
+[:mouse_move, 520, 356, 2, 15, 32]
+[:mouse_move, 459, 360, 2, 16, 34]
+[:mouse_move, 411, 357, 2, 17, 34]
+[:mouse_move, 319, 340, 2, 18, 35]
+[:mouse_move, 287, 330, 2, 19, 37]
+[:mouse_move, 248, 308, 2, 20, 37]
+[:mouse_move, 233, 298, 2, 21, 38]
+[:mouse_move, 211, 283, 2, 22, 39]
+[:mouse_move, 204, 278, 2, 23, 40]
+[:mouse_move, 195, 272, 2, 24, 42]
+[:mouse_move, 192, 269, 2, 25, 42]
+[:mouse_move, 187, 266, 2, 26, 44]
+[:mouse_move, 184, 263, 2, 27, 44]
+[:mouse_move, 181, 261, 2, 28, 45]
+[:mouse_move, 174, 255, 2, 29, 46]
+[:mouse_move, 170, 252, 2, 30, 47]
+[:mouse_move, 155, 244, 2, 31, 48]
+[:mouse_move, 122, 232, 2, 32, 50]
+[:mouse_move, 107, 227, 2, 33, 50]
+[:mouse_move, 88, 224, 2, 34, 52]
+[:mouse_move, 80, 223, 2, 35, 52]
+[:mouse_move, 73, 223, 2, 36, 53]
+[:mouse_move, 57, 224, 2, 37, 54]
+[:mouse_move, 54, 224, 2, 38, 55]
+[:mouse_move, 51, 224, 2, 39, 56]
+[:mouse_move, 51, 223, 2, 40, 60]
+[:mouse_move, 52, 221, 2, 41, 62]
+[:mouse_move, 54, 219, 2, 42, 64]
+[:mouse_move, 54, 218, 2, 43, 64]
+[:mouse_move, 54, 219, 2, 44, 73]
+[:mouse_move, 55, 221, 2, 45, 75]
+[:mouse_move, 55, 224, 2, 46, 75]
+[:mouse_move, 55, 230, 2, 47, 77]
+[:mouse_move, 55, 232, 2, 48, 77]
+[:mouse_move, 55, 238, 2, 49, 79]
+[:mouse_move, 55, 243, 2, 50, 79]
+[:mouse_move, 57, 254, 2, 51, 81]
+[:mouse_move, 58, 256, 2, 52, 81]
+[:mouse_button_pressed, 1, 0, 1, 53, 91]
+[:mouse_move, 60, 256, 2, 54, 95]
+[:mouse_move, 63, 256, 2, 55, 97]
+[:mouse_move, 73, 256, 2, 56, 97]
+[:mouse_move, 83, 256, 2, 57, 99]
+[:mouse_move, 111, 257, 2, 58, 99]
+[:mouse_move, 128, 257, 2, 59, 101]
+[:mouse_move, 163, 257, 2, 60, 101]
+[:mouse_move, 179, 257, 2, 61, 103]
+[:mouse_move, 203, 257, 2, 62, 103]
+[:mouse_move, 214, 257, 2, 63, 105]
+[:mouse_move, 236, 257, 2, 64, 105]
+[:mouse_move, 247, 257, 2, 65, 107]
+[:mouse_move, 267, 257, 2, 66, 107]
+[:mouse_move, 276, 257, 2, 67, 109]
+[:mouse_move, 288, 257, 2, 68, 109]
+[:mouse_move, 293, 257, 2, 69, 111]
+[:mouse_move, 302, 257, 2, 70, 111]
+[:mouse_move, 308, 257, 2, 71, 113]
+[:mouse_move, 322, 257, 2, 72, 113]
+[:mouse_move, 330, 257, 2, 73, 115]
+[:mouse_move, 334, 257, 2, 74, 115]
+[:mouse_move, 340, 257, 2, 75, 117]
+[:mouse_move, 342, 257, 2, 76, 117]
+[:mouse_move, 348, 257, 2, 77, 119]
+[:mouse_move, 350, 257, 2, 78, 119]
+[:mouse_move, 354, 257, 2, 79, 121]
+[:mouse_button_up, 1, 0, 1, 80, 135]
+[:mouse_move, 351, 257, 2, 81, 145]
+[:mouse_move, 345, 257, 2, 82, 145]
+[:mouse_move, 339, 258, 2, 83, 147]
+[:mouse_move, 314, 261, 2, 84, 147]
+[:mouse_move, 300, 262, 2, 85, 149]
+[:mouse_move, 278, 264, 2, 86, 149]
+[:mouse_move, 264, 265, 2, 87, 151]
+[:mouse_move, 231, 265, 2, 88, 151]
+[:mouse_move, 215, 264, 2, 89, 153]
+[:mouse_move, 194, 262, 2, 90, 153]
+[:mouse_move, 190, 261, 2, 91, 155]
+[:mouse_move, 186, 260, 2, 92, 155]
+[:mouse_move, 185, 260, 2, 93, 157]
+[:mouse_move, 184, 259, 2, 94, 157]
+[:mouse_move, 183, 259, 2, 95, 159]
+[:mouse_move, 179, 259, 2, 96, 161]
+[:mouse_move, 172, 259, 2, 97, 163]
+[:mouse_move, 153, 259, 2, 98, 163]
+[:mouse_move, 142, 259, 2, 99, 165]
+[:mouse_move, 129, 258, 2, 100, 165]
+[:mouse_move, 127, 257, 2, 101, 167]
+[:mouse_move, 126, 257, 2, 102, 167]
+[:mouse_move, 125, 257, 2, 103, 169]
+[:mouse_move, 126, 257, 2, 104, 175]
+[:mouse_move, 127, 257, 2, 105, 175]
+[:mouse_move, 128, 257, 2, 106, 177]
+[:mouse_move, 130, 257, 2, 107, 179]
+[:mouse_move, 131, 257, 2, 108, 181]
+[:mouse_move, 132, 256, 2, 109, 183]
+[:mouse_move, 133, 256, 2, 110, 185]
+[:mouse_move, 134, 256, 2, 111, 187]
+[:mouse_move, 135, 256, 2, 112, 187]
+[:mouse_move, 136, 256, 2, 113, 189]
+[:mouse_move, 137, 256, 2, 114, 191]
+[:mouse_move, 138, 256, 2, 115, 193]
+[:mouse_button_pressed, 1, 0, 1, 116, 199]
+[:mouse_move, 138, 255, 2, 117, 201]
+[:mouse_button_up, 1, 0, 1, 118, 206]
+[:mouse_move, 138, 256, 2, 119, 211]
+[:mouse_move, 138, 257, 2, 120, 215]
+[:mouse_move, 142, 267, 2, 121, 216]
+[:mouse_move, 146, 274, 2, 122, 217]
+[:mouse_move, 158, 291, 2, 123, 218]
+[:mouse_move, 172, 304, 2, 124, 219]
+[:mouse_move, 246, 354, 2, 125, 220]
+[:mouse_move, 292, 380, 2, 126, 221]
+[:mouse_move, 382, 424, 2, 127, 222]
+[:mouse_move, 403, 436, 2, 128, 225]
+[:mouse_move, 408, 437, 2, 129, 282]
+[:mouse_move, 409, 437, 2, 130, 283]
+[:mouse_move, 408, 438, 2, 131, 293]
+[:mouse_move, 393, 438, 2, 132, 295]
+[:mouse_move, 373, 435, 2, 133, 296]
+[:mouse_move, 305, 421, 2, 134, 297]
+[:mouse_move, 265, 410, 2, 135, 298]
+[:mouse_move, 191, 391, 2, 136, 299]
+[:mouse_move, 170, 386, 2, 137, 300]
+[:mouse_move, 154, 380, 2, 138, 301]
+[:mouse_move, 153, 381, 2, 139, 305]
+[:mouse_move, 152, 381, 2, 140, 313]
+[:mouse_move, 150, 381, 2, 141, 314]
+[:mouse_move, 148, 379, 2, 142, 315]
+[:mouse_move, 137, 372, 2, 143, 316]
+[:mouse_move, 128, 366, 2, 144, 317]
+[:mouse_move, 112, 359, 2, 145, 318]
+[:mouse_move, 111, 359, 2, 146, 319]
+[:mouse_move, 111, 358, 2, 147, 320]
+[:mouse_move, 110, 358, 2, 148, 322]
+[:mouse_move, 107, 357, 2, 149, 324]
+[:mouse_move, 107, 356, 2, 150, 325]
+[:mouse_move, 105, 356, 2, 151, 326]
+[:mouse_move, 104, 356, 2, 152, 327]
+[:mouse_move, 101, 354, 2, 153, 328]
+[:mouse_move, 99, 352, 2, 154, 329]
+[:mouse_move, 95, 350, 2, 155, 330]
+[:mouse_move, 92, 348, 2, 156, 331]
+[:mouse_move, 82, 345, 2, 157, 332]
+[:mouse_move, 76, 343, 2, 158, 333]
+[:mouse_move, 74, 342, 2, 159, 334]
+[:mouse_move, 73, 342, 2, 160, 336]
+[:mouse_move, 72, 342, 2, 161, 337]
+[:mouse_move, 71, 343, 2, 162, 338]
+[:mouse_move, 70, 343, 2, 163, 341]
+[:mouse_move, 69, 343, 2, 164, 342]
+[:mouse_move, 66, 344, 2, 165, 343]
+[:mouse_move, 63, 345, 2, 166, 344]
+[:mouse_move, 55, 348, 2, 167, 345]
+[:mouse_move, 52, 348, 2, 168, 346]
+[:mouse_move, 48, 350, 2, 169, 347]
+[:mouse_move, 47, 350, 2, 170, 348]
+[:mouse_move, 46, 350, 2, 171, 350]
+[:mouse_move, 46, 349, 2, 172, 351]
+[:mouse_move, 46, 348, 2, 173, 357]
+[:mouse_move, 47, 348, 2, 174, 359]
+[:mouse_move, 47, 347, 2, 175, 360]
+[:mouse_move, 47, 346, 2, 176, 362]
+[:mouse_move, 48, 345, 2, 177, 366]
+[:mouse_button_pressed, 1, 0, 1, 178, 370]
+[:mouse_move, 49, 346, 2, 179, 376]
+[:mouse_move, 53, 346, 2, 180, 377]
+[:mouse_move, 64, 348, 2, 181, 378]
+[:mouse_move, 71, 348, 2, 182, 379]
+[:mouse_move, 85, 350, 2, 183, 380]
+[:mouse_move, 95, 351, 2, 184, 381]
+[:mouse_move, 116, 351, 2, 185, 382]
+[:mouse_move, 128, 351, 2, 186, 383]
+[:mouse_move, 153, 351, 2, 187, 384]
+[:mouse_move, 166, 352, 2, 188, 385]
+[:mouse_move, 189, 354, 2, 189, 386]
+[:mouse_move, 198, 354, 2, 190, 387]
+[:mouse_move, 217, 354, 2, 191, 388]
+[:mouse_move, 226, 354, 2, 192, 389]
+[:mouse_move, 249, 355, 2, 193, 390]
+[:mouse_move, 261, 355, 2, 194, 391]
+[:mouse_move, 282, 355, 2, 195, 392]
+[:mouse_move, 291, 355, 2, 196, 393]
+[:mouse_move, 299, 354, 2, 197, 394]
+[:mouse_move, 309, 353, 2, 198, 395]
+[:mouse_move, 310, 353, 2, 199, 396]
+[:mouse_move, 311, 353, 2, 200, 398]
+[:mouse_move, 317, 352, 2, 201, 399]
+[:mouse_move, 320, 352, 2, 202, 400]
+[:mouse_move, 327, 352, 2, 203, 401]
+[:mouse_move, 330, 352, 2, 204, 402]
+[:mouse_move, 333, 351, 2, 205, 403]
+[:mouse_move, 335, 351, 2, 206, 404]
+[:mouse_move, 337, 351, 2, 207, 405]
+[:mouse_move, 338, 351, 2, 208, 412]
+[:mouse_move, 339, 351, 2, 209, 417]
+[:mouse_move, 340, 351, 2, 210, 420]
+[:mouse_move, 341, 351, 2, 211, 421]
+[:mouse_move, 343, 351, 2, 212, 422]
+[:mouse_move, 349, 351, 2, 213, 424]
+[:mouse_move, 351, 351, 2, 214, 425]
+[:mouse_move, 353, 351, 2, 215, 426]
+[:mouse_move, 354, 351, 2, 216, 427]
+[:mouse_move, 355, 351, 2, 217, 428]
+[:mouse_move, 356, 351, 2, 218, 428]
+[:mouse_move, 357, 351, 2, 219, 429]
+[:mouse_move, 358, 351, 2, 220, 430]
+[:mouse_move, 359, 351, 2, 221, 431]
+[:mouse_move, 360, 351, 2, 222, 432]
+[:mouse_move, 361, 351, 2, 223, 433]
+[:mouse_move, 362, 351, 2, 224, 434]
+[:mouse_move, 365, 351, 2, 225, 435]
+[:mouse_move, 366, 351, 2, 226, 436]
+[:mouse_move, 367, 351, 2, 227, 439]
+[:mouse_move, 368, 351, 2, 228, 446]
+[:mouse_move, 369, 351, 2, 229, 456]
+[:mouse_move, 370, 351, 2, 230, 460]
+[:mouse_button_up, 1, 0, 1, 231, 471]
+[:key_down_raw, 1073741905, 0, 2, 232, 514]
+[:key_down_raw, 1073741905, 0, 2, 233, 528]
+[:key_down_raw, 32, 0, 2, 234, 529]
+[:key_up_raw, 32, 0, 2, 235, 535]
+[:key_up_raw, 1073741905, 0, 2, 236, 547]
+[:key_down_raw, 1073741905, 0, 2, 237, 567]
+[:key_down_raw, 32, 0, 2, 238, 577]
+[:key_up_raw, 32, 0, 2, 239, 584]
+[:key_up_raw, 1073741905, 0, 2, 240, 589]
+[:key_down_raw, 32, 0, 2, 241, 608]
+[:key_up_raw, 32, 0, 2, 242, 612]
+[:key_down_raw, 32, 0, 2, 243, 619]
+[:key_up_raw, 32, 0, 2, 244, 623]
+[:key_down_raw, 32, 0, 2, 245, 627]
+[:key_up_raw, 32, 0, 2, 246, 631]
+[:mouse_move, 363, 354, 2, 247, 695]
+[:mouse_move, 355, 354, 2, 248, 696]
+[:mouse_move, 337, 351, 2, 249, 697]
+[:mouse_move, 323, 347, 2, 250, 698]
+[:mouse_move, 252, 326, 2, 251, 699]
+[:mouse_move, 206, 312, 2, 252, 700]
+[:mouse_move, 146, 292, 2, 253, 701]
+[:mouse_move, 127, 286, 2, 254, 702]
+[:mouse_move, 104, 279, 2, 255, 703]
+[:mouse_move, 100, 277, 2, 256, 704]
+[:mouse_move, 99, 277, 2, 257, 706]
+[:mouse_move, 100, 277, 2, 258, 714]
+[:mouse_move, 102, 277, 2, 259, 715]
+[:mouse_move, 103, 277, 2, 260, 716]
+[:mouse_move, 104, 276, 2, 261, 717]
+[:mouse_move, 107, 273, 2, 262, 718]
+[:mouse_move, 107, 272, 2, 263, 719]
+[:mouse_move, 110, 270, 2, 264, 720]
+[:mouse_move, 110, 269, 2, 265, 721]
+[:mouse_move, 110, 268, 2, 266, 722]
+[:mouse_move, 111, 266, 2, 267, 724]
+[:mouse_move, 112, 264, 2, 268, 725]
+[:mouse_move, 112, 261, 2, 269, 726]
+[:mouse_move, 112, 260, 2, 270, 727]
+[:mouse_move, 112, 259, 2, 271, 728]
+[:key_down_raw, 120, 0, 2, 272, 739]
+[:mouse_move, 111, 259, 2, 273, 745]
+[:key_down_raw, 120, 0, 2, 274, 754]
+[:key_down_raw, 120, 0, 2, 275, 756]
+[:key_down_raw, 120, 0, 2, 276, 758]
+[:key_down_raw, 120, 0, 2, 277, 760]
+[:key_down_raw, 120, 0, 2, 278, 762]
+[:mouse_button_pressed, 1, 0, 1, 279, 763]
+[:key_down_raw, 120, 0, 2, 280, 764]
+[:key_down_raw, 120, 0, 2, 281, 766]
+[:key_down_raw, 120, 0, 2, 282, 768]
+[:key_down_raw, 120, 0, 2, 283, 770]
+[:mouse_button_up, 1, 0, 1, 284, 770]
+[:key_down_raw, 120, 0, 2, 285, 772]
+[:key_down_raw, 120, 0, 2, 286, 774]
+[:key_down_raw, 120, 0, 2, 287, 776]
+[:key_down_raw, 120, 0, 2, 288, 778]
+[:mouse_move, 111, 262, 2, 289, 779]
+[:mouse_move, 111, 271, 2, 290, 780]
+[:key_down_raw, 120, 0, 2, 291, 780]
+[:mouse_move, 110, 276, 2, 292, 781]
+[:mouse_move, 108, 288, 2, 293, 782]
+[:key_down_raw, 120, 0, 2, 294, 782]
+[:mouse_move, 107, 295, 2, 295, 783]
+[:mouse_move, 104, 312, 2, 296, 784]
+[:key_down_raw, 120, 0, 2, 297, 784]
+[:mouse_move, 104, 317, 2, 298, 785]
+[:mouse_move, 102, 325, 2, 299, 786]
+[:key_down_raw, 120, 0, 2, 300, 786]
+[:mouse_move, 102, 328, 2, 301, 787]
+[:mouse_move, 102, 332, 2, 302, 788]
+[:key_down_raw, 120, 0, 2, 303, 788]
+[:mouse_move, 102, 335, 2, 304, 789]
+[:mouse_move, 102, 341, 2, 305, 790]
+[:key_down_raw, 120, 0, 2, 306, 790]
+[:mouse_move, 102, 343, 2, 307, 791]
+[:mouse_move, 102, 345, 2, 308, 792]
+[:key_down_raw, 120, 0, 2, 309, 792]
+[:mouse_move, 102, 346, 2, 310, 793]
+[:key_down_raw, 120, 0, 2, 311, 794]
+[:mouse_move, 102, 347, 2, 312, 795]
+[:key_down_raw, 120, 0, 2, 313, 796]
+[:key_down_raw, 120, 0, 2, 314, 798]
+[:mouse_move, 102, 348, 2, 315, 799]
+[:key_down_raw, 120, 0, 2, 316, 800]
+[:mouse_move, 103, 348, 2, 317, 801]
+[:key_down_raw, 120, 0, 2, 318, 802]
+[:key_down_raw, 120, 0, 2, 319, 804]
+[:key_down_raw, 120, 0, 2, 320, 806]
+[:key_down_raw, 120, 0, 2, 321, 808]
+[:key_down_raw, 120, 0, 2, 322, 810]
+[:mouse_move, 103, 349, 2, 323, 810]
+[:mouse_move, 104, 349, 2, 324, 811]
+[:key_down_raw, 120, 0, 2, 325, 812]
+[:mouse_move, 104, 350, 2, 326, 813]
+[:key_down_raw, 120, 0, 2, 327, 814]
+[:key_down_raw, 120, 0, 2, 328, 816]
+[:mouse_move, 105, 350, 2, 329, 817]
+[:mouse_button_pressed, 1, 0, 1, 330, 817]
+[:key_down_raw, 120, 0, 2, 331, 818]
+[:key_down_raw, 120, 0, 2, 332, 820]
+[:key_down_raw, 120, 0, 2, 333, 822]
+[:key_down_raw, 120, 0, 2, 334, 824]
+[:mouse_button_up, 1, 0, 1, 335, 826]
+[:key_down_raw, 120, 0, 2, 336, 826]
+[:key_down_raw, 120, 0, 2, 337, 828]
+[:key_down_raw, 120, 0, 2, 338, 830]
+[:key_down_raw, 120, 0, 2, 339, 832]
+[:key_down_raw, 120, 0, 2, 340, 834]
+[:mouse_move, 106, 350, 2, 341, 836]
+[:key_down_raw, 120, 0, 2, 342, 836]
+[:key_down_raw, 120, 0, 2, 343, 838]
+[:key_up_raw, 120, 0, 2, 344, 839]
+[:mouse_move, 107, 348, 2, 345, 842]
+[:mouse_move, 108, 345, 2, 346, 843]
+[:mouse_move, 109, 343, 2, 347, 844]
+[:mouse_move, 109, 342, 2, 348, 845]
+[:mouse_move, 109, 341, 2, 349, 852]
+[:mouse_move, 111, 337, 2, 350, 853]
+[:mouse_move, 113, 332, 2, 351, 854]
+[:mouse_move, 116, 322, 2, 352, 855]
+[:mouse_move, 118, 316, 2, 353, 856]
+[:mouse_move, 119, 303, 2, 354, 857]
+[:mouse_move, 120, 295, 2, 355, 858]
+[:mouse_move, 120, 282, 2, 356, 859]
+[:mouse_move, 120, 279, 2, 357, 860]
+[:mouse_move, 121, 278, 2, 358, 861]
+[:mouse_move, 121, 277, 2, 359, 865]
+[:mouse_move, 121, 276, 2, 360, 868]
+[:mouse_move, 120, 275, 2, 361, 869]
+[:mouse_move, 120, 274, 2, 362, 870]
+[:mouse_move, 118, 270, 2, 363, 871]
+[:mouse_move, 118, 269, 2, 364, 872]
+[:mouse_move, 117, 267, 2, 365, 873]
+[:mouse_move, 117, 266, 2, 366, 880]
+[:mouse_move, 118, 266, 2, 367, 881]
+[:mouse_move, 118, 264, 2, 368, 882]
+[:mouse_move, 118, 263, 2, 369, 883]
+[:mouse_move, 118, 262, 2, 370, 884]
+[:mouse_move, 118, 261, 2, 371, 887]
+[:mouse_move, 119, 261, 2, 372, 888]
+[:mouse_button_pressed, 1, 0, 1, 373, 909]
+[:mouse_button_up, 1, 0, 1, 374, 912]
+[:mouse_move, 118, 264, 2, 375, 914]
+[:mouse_move, 116, 269, 2, 376, 915]
+[:mouse_move, 113, 280, 2, 377, 916]
+[:mouse_move, 111, 285, 2, 378, 917]
+[:mouse_move, 109, 293, 2, 379, 918]
+[:mouse_move, 108, 297, 2, 380, 919]
+[:mouse_move, 105, 307, 2, 381, 920]
+[:mouse_move, 103, 315, 2, 382, 921]
+[:mouse_move, 101, 328, 2, 383, 922]
+[:mouse_move, 101, 333, 2, 384, 923]
+[:mouse_move, 102, 341, 2, 385, 924]
+[:mouse_move, 102, 342, 2, 386, 925]
+[:mouse_move, 103, 346, 2, 387, 926]
+[:mouse_move, 103, 347, 2, 388, 927]
+[:mouse_move, 103, 349, 2, 389, 928]
+[:mouse_move, 104, 350, 2, 390, 930]
+[:mouse_move, 104, 351, 2, 391, 933]
+[:mouse_move, 104, 352, 2, 392, 939]
+[:mouse_move, 105, 352, 2, 393, 940]
+[:mouse_move, 106, 358, 2, 394, 941]
+[:mouse_move, 107, 363, 2, 395, 942]
+[:mouse_move, 108, 370, 2, 396, 943]
+[:mouse_move, 109, 371, 2, 397, 944]
+[:mouse_move, 109, 372, 2, 398, 945]
+[:mouse_move, 109, 369, 2, 399, 953]
+[:mouse_move, 109, 368, 2, 400, 954]
+[:mouse_move, 109, 360, 2, 401, 955]
+[:mouse_move, 109, 358, 2, 402, 956]
+[:mouse_move, 109, 356, 2, 403, 957]
+[:mouse_move, 109, 355, 2, 404, 958]
+[:mouse_button_pressed, 1, 0, 1, 405, 970]
+[:mouse_move, 109, 354, 2, 406, 970]
+[:mouse_button_up, 1, 0, 1, 407, 975]
+[:mouse_move, 109, 353, 2, 408, 985]
+[:mouse_move, 109, 352, 2, 409, 987]
+[:mouse_move, 109, 350, 2, 410, 988]
+[:mouse_move, 109, 349, 2, 411, 990]
+[:mouse_move, 109, 355, 2, 412, 996]
+[:mouse_move, 109, 357, 2, 413, 997]
+[:mouse_move, 106, 366, 2, 414, 998]
+[:mouse_move, 104, 374, 2, 415, 999]
+[:mouse_move, 100, 387, 2, 416, 1000]
+[:mouse_move, 100, 391, 2, 417, 1001]
+[:mouse_move, 101, 391, 2, 418, 1002]
+[:mouse_move, 101, 390, 2, 419, 1008]
+[:mouse_move, 102, 389, 2, 420, 1009]
+[:mouse_move, 103, 387, 2, 421, 1010]
+[:mouse_move, 103, 384, 2, 422, 1011]
+[:mouse_move, 104, 382, 2, 423, 1012]
+[:mouse_move, 104, 381, 2, 424, 1013]
+[:mouse_move, 104, 380, 2, 425, 1014]
+[:mouse_move, 105, 380, 2, 426, 1015]
+[:mouse_move, 105, 379, 2, 427, 1030]
+[:mouse_button_pressed, 1, 0, 1, 428, 1031]
+[:mouse_move, 107, 379, 2, 429, 1039]
+[:mouse_move, 111, 380, 2, 430, 1040]
+[:mouse_move, 113, 380, 2, 431, 1041]
+[:mouse_move, 124, 380, 2, 432, 1042]
+[:mouse_move, 133, 381, 2, 433, 1043]
+[:mouse_move, 145, 381, 2, 434, 1044]
+[:mouse_move, 149, 381, 2, 435, 1045]
+[:mouse_move, 152, 382, 2, 436, 1045]
+[:mouse_move, 153, 382, 2, 437, 1046]
+[:mouse_move, 154, 382, 2, 438, 1047]
+[:mouse_move, 155, 382, 2, 439, 1048]
+[:mouse_move, 158, 382, 2, 440, 1049]
+[:mouse_move, 159, 382, 2, 441, 1050]
+[:mouse_move, 162, 383, 2, 442, 1051]
+[:mouse_move, 164, 383, 2, 443, 1052]
+[:mouse_move, 168, 383, 2, 444, 1053]
+[:mouse_move, 170, 384, 2, 445, 1053]
+[:mouse_move, 172, 384, 2, 446, 1054]
+[:mouse_move, 173, 384, 2, 447, 1055]
+[:mouse_move, 176, 384, 2, 448, 1056]
+[:mouse_move, 178, 384, 2, 449, 1057]
+[:mouse_move, 180, 384, 2, 450, 1058]
+[:mouse_move, 181, 384, 2, 451, 1059]
+[:mouse_move, 183, 384, 2, 452, 1075]
+[:mouse_move, 184, 384, 2, 453, 1076]
+[:mouse_move, 186, 384, 2, 454, 1077]
+[:mouse_move, 187, 384, 2, 455, 1078]
+[:mouse_move, 190, 384, 2, 456, 1079]
+[:mouse_move, 191, 384, 2, 457, 1080]
+[:mouse_move, 193, 385, 2, 458, 1081]
+[:mouse_move, 194, 385, 2, 459, 1083]
+[:mouse_move, 195, 385, 2, 460, 1087]
+[:mouse_move, 196, 385, 2, 461, 1090]
+[:mouse_move, 197, 385, 2, 462, 1091]
+[:mouse_move, 198, 385, 2, 463, 1093]
+[:mouse_button_up, 1, 0, 1, 464, 1108]
+[:mouse_move, 199, 385, 2, 465, 1110]
+[:key_down_raw, 1073741905, 0, 2, 466, 1148]
+[:key_down_raw, 1073741905, 0, 2, 467, 1163]
+[:key_down_raw, 1073741905, 0, 2, 468, 1165]
+[:key_down_raw, 1073741905, 0, 2, 469, 1167]
+[:key_down_raw, 32, 0, 2, 470, 1168]
+[:key_up_raw, 32, 0, 2, 471, 1174]
+[:key_down_raw, 32, 0, 2, 472, 1210]
+[:key_up_raw, 32, 0, 2, 473, 1217]
+[:key_down_raw, 32, 0, 2, 474, 1225]
+[:key_up_raw, 32, 0, 2, 475, 1231]
+[:key_up_raw, 1073741905, 0, 2, 476, 1238]
+[:mouse_move, 204, 382, 2, 477, 1263]
+[:mouse_move, 213, 375, 2, 478, 1264]
+[:mouse_move, 217, 364, 2, 479, 1265]
+[:mouse_move, 217, 358, 2, 480, 1266]
+[:mouse_move, 212, 345, 2, 481, 1267]
+[:mouse_move, 208, 337, 2, 482, 1268]
+[:mouse_move, 194, 319, 2, 483, 1269]
+[:mouse_move, 183, 305, 2, 484, 1270]
+[:mouse_move, 160, 280, 2, 485, 1271]
+[:mouse_move, 150, 270, 2, 486, 1272]
+[:mouse_move, 137, 258, 2, 487, 1273]
+[:mouse_move, 135, 256, 2, 488, 1274]
+[:key_down_raw, 32, 0, 2, 489, 1303]
+[:key_up_raw, 32, 0, 2, 490, 1307]
+[:key_down_raw, 1073741905, 0, 2, 491, 1341]
+[:key_down_raw, 1073741905, 0, 2, 492, 1356]
+[:key_down_raw, 1073741905, 0, 2, 493, 1358]
+[:key_down_raw, 1073741905, 0, 2, 494, 1360]
+[:key_down_raw, 32, 0, 2, 495, 1361]
+[:key_up_raw, 32, 0, 2, 496, 1367]
+[:key_up_raw, 1073741905, 0, 2, 497, 1381]
+[:key_down_raw, 1073741904, 0, 2, 498, 1397]
+[:key_up_raw, 1073741904, 0, 2, 499, 1403]
+[:key_down_raw, 1073741905, 0, 2, 500, 1425]
+[:key_down_raw, 1073741905, 0, 2, 501, 1440]
+[:key_down_raw, 32, 0, 2, 502, 1441]
+[:key_up_raw, 32, 0, 2, 503, 1450]
+[:key_up_raw, 1073741905, 0, 2, 504, 1457]
+[:key_down_raw, 1073741903, 0, 2, 505, 1470]
+[:key_down_raw, 32, 0, 2, 506, 1479]
+[:key_up_raw, 32, 0, 2, 507, 1485]
+[:key_up_raw, 1073741903, 0, 2, 508, 1499]
+[:key_down_raw, 32, 0, 2, 509, 1500]
+[:key_up_raw, 32, 0, 2, 510, 1506]
+[:key_down_raw, 32, 0, 2, 511, 1511]
+[:key_up_raw, 32, 0, 2, 512, 1516]
+[:key_down_raw, 32, 0, 2, 513, 1520]
+[:key_up_raw, 32, 0, 2, 514, 1524]
+[:key_down_raw, 32, 0, 2, 515, 1528]
+[:key_up_raw, 32, 0, 2, 516, 1534]
+[:key_down_raw, 32, 0, 2, 517, 1538]
+[:key_down_raw, 1073741903, 0, 2, 518, 1540]
+[:key_up_raw, 32, 0, 2, 519, 1545]
+[:key_down_raw, 1073741903, 0, 2, 520, 1555]
+[:key_down_raw, 32, 0, 2, 521, 1557]
+[:key_up_raw, 1073741903, 0, 2, 522, 1558]
+[:key_up_raw, 32, 0, 2, 523, 1563]
+[:key_down_raw, 32, 0, 2, 524, 1567]
+[:key_up_raw, 32, 0, 2, 525, 1581]
+[:key_down_raw, 1073741904, 0, 2, 526, 1592]
+[:key_down_raw, 1073741904, 0, 2, 527, 1607]
+[:key_down_raw, 1073741904, 0, 2, 528, 1609]
+[:key_down_raw, 1073741904, 0, 2, 529, 1611]
+[:key_down_raw, 1073741904, 0, 2, 530, 1613]
+[:key_down_raw, 1073741904, 0, 2, 531, 1615]
+[:key_down_raw, 1073741904, 0, 2, 532, 1617]
+[:key_down_raw, 1073741904, 0, 2, 533, 1619]
+[:key_down_raw, 1073741904, 0, 2, 534, 1621]
+[:key_down_raw, 1073741904, 0, 2, 535, 1623]
+[:key_down_raw, 1073741904, 0, 2, 536, 1625]
+[:key_down_raw, 1073741904, 0, 2, 537, 1627]
+[:key_down_raw, 1073741904, 0, 2, 538, 1629]
+[:key_down_raw, 1073741904, 0, 2, 539, 1631]
+[:key_down_raw, 1073741904, 0, 2, 540, 1633]
+[:key_up_raw, 1073741904, 0, 2, 541, 1633]
+[:mouse_move, 137, 254, 2, 542, 1666]
+[:mouse_move, 137, 253, 2, 543, 1667]
+[:mouse_move, 137, 252, 2, 544, 1668]
+[:mouse_move, 138, 248, 2, 545, 1669]
+[:mouse_move, 141, 243, 2, 546, 1670]
+[:mouse_move, 141, 242, 2, 547, 1675]
+[:mouse_move, 142, 240, 2, 548, 1676]
+[:mouse_move, 143, 240, 2, 549, 1677]
+[:mouse_move, 143, 239, 2, 550, 1678]
+[:mouse_move, 143, 238, 2, 551, 1682]
+[:mouse_move, 144, 237, 2, 552, 1683]
+[:mouse_move, 144, 236, 2, 553, 1684]
+[:mouse_move, 144, 235, 2, 554, 1685]
+[:mouse_move, 144, 234, 2, 555, 1686]
+[:mouse_move, 146, 228, 2, 556, 1687]
+[:mouse_move, 147, 226, 2, 557, 1688]
+[:mouse_move, 147, 225, 2, 558, 1689]
+[:mouse_button_pressed, 1, 0, 1, 559, 1703]
+[:mouse_move, 148, 225, 2, 560, 1713]
+[:mouse_move, 150, 225, 2, 561, 1714]
+[:mouse_move, 157, 225, 2, 562, 1715]
+[:mouse_move, 160, 225, 2, 563, 1716]
+[:mouse_move, 170, 226, 2, 564, 1717]
+[:mouse_move, 174, 226, 2, 565, 1718]
+[:mouse_move, 179, 226, 2, 566, 1718]
+[:mouse_move, 181, 226, 2, 567, 1719]
+[:mouse_move, 185, 226, 2, 568, 1720]
+[:mouse_move, 188, 226, 2, 569, 1721]
+[:mouse_move, 195, 226, 2, 570, 1722]
+[:mouse_move, 199, 226, 2, 571, 1723]
+[:mouse_move, 205, 226, 2, 572, 1724]
+[:mouse_move, 208, 226, 2, 573, 1724]
+[:mouse_move, 216, 226, 2, 574, 1725]
+[:mouse_move, 220, 226, 2, 575, 1726]
+[:mouse_move, 225, 226, 2, 576, 1727]
+[:mouse_move, 229, 226, 2, 577, 1728]
+[:mouse_move, 236, 226, 2, 578, 1729]
+[:mouse_move, 238, 226, 2, 579, 1729]
+[:mouse_move, 240, 226, 2, 580, 1730]
+[:mouse_move, 242, 226, 2, 581, 1731]
+[:mouse_button_up, 1, 0, 1, 582, 1747]
+[:mouse_move, 243, 227, 2, 583, 1749]
+[:key_down_raw, 1073741903, 0, 2, 584, 1774]
+[:key_up_raw, 1073741903, 0, 2, 585, 1783]
+[:key_down_raw, 1073741906, 0, 2, 586, 1785]
+[:key_up_raw, 1073741906, 0, 2, 587, 1789]
+[:key_down_raw, 32, 0, 2, 588, 1815]
+[:key_up_raw, 32, 0, 2, 589, 1819]
+[:key_down_raw, 32, 0, 2, 590, 1825]
+[:key_up_raw, 32, 0, 2, 591, 1831]
+[:key_down_raw, 32, 0, 2, 592, 1845]
+[:key_up_raw, 32, 0, 2, 593, 1851]
+[:key_down_raw, 32, 0, 2, 594, 1856]
+[:key_up_raw, 32, 0, 2, 595, 1863]
+[:key_down_raw, 1073741904, 0, 2, 596, 1881]
+[:key_down_raw, 1073741904, 0, 2, 597, 1896]
+[:key_down_raw, 1073741904, 0, 2, 598, 1898]
+[:key_down_raw, 1073741904, 0, 2, 599, 1900]
+[:key_down_raw, 1073741904, 0, 2, 600, 1903]
+[:key_down_raw, 1073741904, 0, 2, 601, 1904]
+[:key_down_raw, 1073741904, 0, 2, 602, 1906]
+[:key_up_raw, 1073741904, 0, 2, 603, 1908]
+[:key_down_raw, 32, 0, 2, 604, 1920]
+[:key_down_raw, 32, 0, 2, 605, 1935]
+[:key_down_raw, 1073741903, 0, 2, 606, 1936]
+[:key_down_raw, 1073741903, 0, 2, 607, 1951]
+[:key_down_raw, 1073741903, 0, 2, 608, 1953]
+[:key_up_raw, 32, 0, 2, 609, 1954]
+[:key_up_raw, 1073741903, 0, 2, 610, 1954]
+[:key_down_raw, 32, 0, 2, 611, 1985]
+[:key_down_raw, 1073741903, 0, 2, 612, 1989]
+[:key_up_raw, 32, 0, 2, 613, 1999]
+[:key_up_raw, 1073741903, 0, 2, 614, 2002]
+[:mouse_move, 245, 226, 2, 615, 2037]
+[:mouse_move, 308, 213, 2, 616, 2038]
+[:mouse_move, 380, 203, 2, 617, 2039]
+[:mouse_move, 567, 189, 2, 618, 2040]
+[:mouse_move, 663, 187, 2, 619, 2041]
+[:mouse_move, 862, 189, 2, 620, 2042]
+[:mouse_move, 931, 190, 2, 621, 2043]
+[:mouse_move, 1002, 195, 2, 622, 2044]
+[:mouse_move, 1016, 195, 2, 623, 2045]
+[:mouse_move, 1031, 195, 2, 624, 2046]
+[:key_down_raw, 96, 0, 2, 625, 2064]
+[:key_up_raw, 96, 0, 2, 626, 2069]
+[:mouse_move, 1031, 193, 2, 627, 2074]
+[:mouse_move, 1031, 191, 2, 628, 2074]
+[:mouse_move, 1031, 189, 2, 629, 2075]
+[:mouse_move, 1031, 188, 2, 630, 2077]
+[:mouse_move, 1031, 187, 2, 631, 2079]
+[:mouse_move, 1029, 185, 2, 632, 2082]
+[:mouse_move, 1023, 174, 2, 633, 2082]
+[:mouse_move, 1017, 168, 2, 634, 2083]
+[:mouse_move, 1005, 155, 2, 635, 2084]
+[:mouse_move, 1000, 149, 2, 636, 2085]
+[:mouse_move, 986, 140, 2, 637, 2086]
+[:mouse_move, 980, 138, 2, 638, 2086]
+[:mouse_move, 965, 131, 2, 639, 2087]
+[:mouse_move, 953, 126, 2, 640, 2088]
+[:mouse_move, 925, 115, 2, 641, 2089]
+[:mouse_move, 912, 109, 2, 642, 2089]
+[:mouse_move, 902, 105, 2, 643, 2090]
+[:mouse_move, 891, 101, 2, 644, 2091]
+[:mouse_move, 886, 99, 2, 645, 2092]
+[:mouse_move, 877, 98, 2, 646, 2092]
+[:mouse_move, 861, 97, 2, 647, 2093]
+[:mouse_move, 857, 97, 2, 648, 2094]
+[:mouse_move, 850, 98, 2, 649, 2095]
+[:mouse_move, 849, 98, 2, 650, 2096]
+[:mouse_move, 847, 99, 2, 651, 2096]
+[:mouse_move, 846, 99, 2, 652, 2097]
+[:mouse_move, 845, 99, 2, 653, 2098]
+[:mouse_move, 842, 101, 2, 654, 2099]
+[:mouse_move, 841, 101, 2, 655, 2100]
+[:mouse_move, 840, 102, 2, 656, 2100]
+[:mouse_move, 839, 103, 2, 657, 2104]
+[:mouse_move, 840, 103, 2, 658, 2109]
+[:mouse_move, 841, 103, 2, 659, 2110]
+[:mouse_move, 843, 103, 2, 660, 2112]
+[:mouse_move, 845, 103, 2, 661, 2113]
+[:mouse_move, 846, 102, 2, 662, 2115]
+[:mouse_move, 848, 102, 2, 663, 2116]
+[:mouse_move, 855, 101, 2, 664, 2116]
+[:mouse_move, 858, 100, 2, 665, 2117]
+[:mouse_move, 862, 99, 2, 666, 2118]
+[:mouse_move, 865, 98, 2, 667, 2119]
+[:mouse_move, 867, 98, 2, 668, 2120]
+[:mouse_move, 868, 97, 2, 669, 2121]
+[:mouse_move, 869, 97, 2, 670, 2122]
+[:mouse_move, 868, 97, 2, 671, 2128]
+[:mouse_move, 864, 95, 2, 672, 2129]
+[:mouse_move, 846, 92, 2, 673, 2129]
+[:mouse_move, 834, 90, 2, 674, 2130]
+[:mouse_move, 818, 88, 2, 675, 2131]
+[:mouse_move, 813, 87, 2, 676, 2132]
+[:mouse_move, 806, 87, 2, 677, 2132]
+[:mouse_move, 803, 87, 2, 678, 2133]
+[:mouse_move, 798, 87, 2, 679, 2134]
+[:mouse_move, 796, 87, 2, 680, 2134]
+[:mouse_move, 795, 87, 2, 681, 2135]
+[:mouse_move, 794, 87, 2, 682, 2137]
+[:key_down_raw, 13, 0, 2, 683, 2166]
diff --git a/samples/04_physics_and_collisions/06_jump_physics/app/main.rb b/samples/04_physics_and_collisions/06_jump_physics/app/main.rb
deleted file mode 100644
index da01e91..0000000
--- a/samples/04_physics_and_collisions/06_jump_physics/app/main.rb
+++ /dev/null
@@ -1,195 +0,0 @@
-=begin
-
- Reminders:
-
- - args.state.new_entity: Used when we want to create a new object, like a sprite or button.
- For example, if we want to create a new button, we would declare it as a new entity and
- then define its properties. (Remember, you can use state to define ANY property and it will
- be retained across frames.)
-
- - args.outputs.solids: An array. The values generate a solid.
- The parameters for a solid are [X, Y, WIDTH, HEIGHT, RED, GREEN, BLUE]
-
- - num1.greater(num2): Returns the greater value.
-
- - Hashes: Collection of unique keys and their corresponding values. The value can be found
- using their keys.
-
- - ARRAY#inside_rect?: Returns true or false depending on if the point is inside the rect.
-
-=end
-
-# This sample app is a game that requires the user to jump from one platform to the next.
-# As the player successfully clears platforms, they become smaller and move faster.
-
-class VerticalPlatformer
- attr_gtk
-
- # declares vertical platformer as new entity
- def s
- state.vertical_platformer ||= state.new_entity(:vertical_platformer)
- state.vertical_platformer
- end
-
- # creates a new platform using a hash
- def new_platform hash
- s.new_entity_strict(:platform, hash) # platform key
- end
-
- # calls methods needed for game to run properly
- def tick
- defaults
- render
- calc
- input
- end
-
- # Sets default values
- def defaults
- s.platforms ||= [ # initializes platforms collection with two platforms using hashes
- new_platform(x: 0, y: 0, w: 700, h: 32, dx: 1, speed: 0, rect: nil),
- new_platform(x: 0, y: 300, w: 700, h: 32, dx: 1, speed: 0, rect: nil), # 300 pixels higher
- ]
-
- s.tick_count = args.state.tick_count
- s.gravity = -0.3 # what goes up must come down because of gravity
- s.player.platforms_cleared ||= 0 # counts how many platforms the player has successfully cleared
- s.player.x ||= 0 # sets player values
- s.player.y ||= 100
- s.player.w ||= 64
- s.player.h ||= 64
- s.player.dy ||= 0 # change in position
- s.player.dx ||= 0
- s.player_jump_power = 15
- s.player_jump_power_duration = 10
- s.player_max_run_speed = 5
- s.player_speed_slowdown_rate = 0.9
- s.player_acceleration = 1
- s.camera ||= { y: -100 } # shows view on screen (as the player moves upward, the camera does too)
- end
-
- # Outputs objects onto the screen
- def render
- outputs.solids << s.platforms.map do |p| # outputs platforms onto screen
- [p.x + 300, p.y - s.camera[:y], p.w, p.h] # add 300 to place platform in horizontal center
- # don't forget, position of platform is denoted by bottom left hand corner
- end
-
- # outputs player using hash
- outputs.solids << {
- x: s.player.x + 300, # player positioned on top of platform
- y: s.player.y - s.camera[:y],
- w: s.player.w,
- h: s.player.h,
- r: 100, # color saturation
- g: 100,
- b: 200
- }
- end
-
- # Performs calculations
- def calc
- s.platforms.each do |p| # for each platform in the collection
- p.rect = [p.x, p.y, p.w, p.h] # set the definition
- end
-
- # sets player point by adding half the player's width to the player's x
- s.player.point = [s.player.x + s.player.w.half, s.player.y] # change + to - and see what happens!
-
- # search the platforms collection to find if the player's point is inside the rect of a platform
- collision = s.platforms.find { |p| s.player.point.inside_rect? p.rect }
-
- # if collision occurred and player is moving down (or not moving vertically at all)
- if collision && s.player.dy <= 0
- s.player.y = collision.rect.y + collision.rect.h - 2 # player positioned on top of platform
- s.player.dy = 0 if s.player.dy < 0 # player stops moving vertically
- if !s.player.platform
- s.player.dx = 0 # no horizontal movement
- end
- # changes horizontal position of player by multiplying collision change in x (dx) by speed and adding it to current x
- s.player.x += collision.dx * collision.speed
- s.player.platform = collision # player is on the platform that it collided with (or landed on)
- if s.player.falling # if player is falling
- s.player.dx = 0 # no horizontal movement
- end
- s.player.falling = false
- s.player.jumped_at = nil
- else
- s.player.platform = nil # player is not on a platform
- s.player.y += s.player.dy # velocity is the change in position
- s.player.dy += s.gravity # acceleration is the change in velocity; what goes up must come down
- end
-
- s.platforms.each do |p| # for each platform in the collection
- p.x += p.dx * p.speed # x is incremented by product of dx and speed (causes platform to move horizontally)
- # changes platform's x so it moves left and right across the screen (between -300 and 300 pixels)
- if p.x < -300 # if platform goes too far left
- p.dx *= -1 # dx is scaled down
- p.x = -300 # as far left as possible within scope
- elsif p.x > (1000 - p.w) # if platform's x is greater than 300
- p.dx *= -1
- p.x = (1000 - p.w) # set to 300 (as far right as possible within scope)
- end
- end
-
- delta = (s.player.y - s.camera[:y] - 100) # used to position camera view
-
- if delta > -200
- s.camera[:y] += delta * 0.01 # allows player to see view as they move upwards
- s.player.x += s.player.dx # velocity is change in position; change in x increases by dx
-
- # searches platform collection to find platforms located more than 300 pixels above the player
- has_platforms = s.platforms.find { |p| p.y > (s.player.y + 300) }
- if !has_platforms # if there are no platforms 300 pixels above the player
- width = 700 - (700 * (0.1 * s.player.platforms_cleared)) # the next platform is smaller than previous
- s.player.platforms_cleared += 1 # player successfully cleared another platform
- last_platform = s.platforms[-1] # platform just cleared becomes last platform
- # another platform is created 300 pixels above the last platform, and this
- # new platform has a smaller width and moves faster than all previous platforms
- s.platforms << new_platform(x: (700 - width) * rand, # random x position
- y: last_platform.y + 300,
- w: width,
- h: 32,
- dx: 1.randomize(:sign), # random change in x
- speed: 2 * s.player.platforms_cleared,
- rect: nil)
- end
- else
- s.as_hash.clear # otherwise clear the hash (no new platform is necessary)
- end
- end
-
- # Takes input from the user to move the player
- def input
- if inputs.keyboard.space # if the space bar is pressed
- s.player.jumped_at ||= s.tick_count # set to current frame
-
- # if the time that has passed since the jump is less than the duration of a jump (10 frames)
- # and the player is not falling
- if s.player.jumped_at.elapsed_time < s.player_jump_power_duration && !s.player.falling
- s.player.dy = s.player_jump_power # player jumps up
- end
- end
-
- if inputs.keyboard.key_up.space # if space bar is in "up" state
- s.player.falling = true # player is falling
- end
-
- if inputs.keyboard.left # if left key is pressed
- s.player.dx -= s.player_acceleration # player's position changes, decremented by acceleration
- s.player.dx = s.player.dx.greater(-s.player_max_run_speed) # dx is either current dx or -5, whichever is greater
- elsif inputs.keyboard.right # if right key is pressed
- s.player.dx += s.player_acceleration # player's position changes, incremented by acceleration
- s.player.dx = s.player.dx.lesser(s.player_max_run_speed) # dx is either current dx or 5, whichever is lesser
- else
- s.player.dx *= s.player_speed_slowdown_rate # scales dx down
- end
- end
-end
-
-$game = VerticalPlatformer.new
-
-def tick args
- $game.args = args
- $game.tick
-end
diff --git a/samples/04_physics_and_collisions/06_jump_physics/replay.txt b/samples/04_physics_and_collisions/06_jump_physics/replay.txt
deleted file mode 100644
index 966dbcd..0000000
--- a/samples/04_physics_and_collisions/06_jump_physics/replay.txt
+++ /dev/null
@@ -1,124 +0,0 @@
-replay_version 2.0
-stopped_at 1260
-seed 100
-recorded_at Sun Sep 29 22:23:22 2019
-[:key_down_raw, 1073741903, 0, 2, 1, 45]
-[:key_down_raw, 1073741903, 0, 2, 2, 70]
-[:key_down_raw, 1073741903, 0, 2, 3, 72]
-[:key_down_raw, 1073741903, 0, 2, 4, 74]
-[:key_down_raw, 1073741903, 0, 2, 5, 76]
-[:key_down_raw, 1073741903, 0, 2, 6, 78]
-[:key_down_raw, 1073741903, 0, 2, 7, 80]
-[:key_down_raw, 1073741903, 0, 2, 8, 82]
-[:key_down_raw, 1073741903, 0, 2, 9, 84]
-[:key_down_raw, 1073741903, 0, 2, 10, 86]
-[:key_down_raw, 1073741903, 0, 2, 11, 88]
-[:key_up_raw, 1073741903, 0, 2, 12, 89]
-[:key_down_raw, 1073741904, 0, 2, 13, 92]
-[:key_down_raw, 1073741903, 0, 2, 14, 112]
-[:key_up_raw, 1073741904, 0, 2, 15, 115]
-[:key_down_raw, 1073741903, 0, 2, 16, 137]
-[:key_down_raw, 1073741903, 0, 2, 17, 139]
-[:key_down_raw, 8, 0, 2, 18, 141]
-[:key_up_raw, 1073741903, 0, 2, 19, 146]
-[:key_down_raw, 1073741903, 0, 2, 20, 147]
-[:key_up_raw, 1073741903, 0, 2, 21, 147]
-[:key_down_raw, 1073741904, 0, 2, 22, 154]
-[:key_up_raw, 8, 0, 2, 23, 172]
-[:key_down_raw, 1073741903, 0, 2, 24, 175]
-[:key_up_raw, 1073741904, 0, 2, 25, 175]
-[:key_down_raw, 32, 0, 2, 26, 194]
-[:key_down_raw, 1073741904, 0, 2, 27, 201]
-[:key_up_raw, 1073741903, 0, 2, 28, 202]
-[:key_down_raw, 1073741903, 0, 2, 29, 222]
-[:key_up_raw, 1073741904, 0, 2, 30, 226]
-[:key_up_raw, 32, 0, 2, 31, 233]
-[:key_down_raw, 1073741903, 0, 2, 32, 247]
-[:key_down_raw, 1073741903, 0, 2, 33, 249]
-[:key_down_raw, 1073741903, 0, 2, 34, 251]
-[:key_down_raw, 1073741903, 0, 2, 35, 253]
-[:key_down_raw, 1073741903, 0, 2, 36, 255]
-[:key_down_raw, 1073741903, 0, 2, 37, 257]
-[:key_down_raw, 1073741903, 0, 2, 38, 259]
-[:key_down_raw, 1073741903, 0, 2, 39, 261]
-[:key_down_raw, 1073741903, 0, 2, 40, 263]
-[:key_down_raw, 1073741903, 0, 2, 41, 265]
-[:key_down_raw, 1073741903, 0, 2, 42, 267]
-[:key_down_raw, 1073741903, 0, 2, 43, 269]
-[:key_down_raw, 1073741903, 0, 2, 44, 271]
-[:key_down_raw, 1073741903, 0, 2, 45, 273]
-[:key_down_raw, 1073741903, 0, 2, 46, 275]
-[:key_up_raw, 1073741903, 0, 2, 47, 276]
-[:key_down_raw, 1073741904, 0, 2, 48, 280]
-[:key_up_raw, 1073741904, 0, 2, 49, 297]
-[:key_down_raw, 1073741903, 0, 2, 50, 300]
-[:key_down_raw, 32, 0, 2, 51, 303]
-[:key_up_raw, 32, 0, 2, 52, 308]
-[:key_up_raw, 1073741903, 0, 2, 53, 334]
-[:key_down_raw, 1073741904, 0, 2, 54, 336]
-[:key_down_raw, 1073741903, 0, 2, 55, 355]
-[:key_up_raw, 1073741904, 0, 2, 56, 355]
-[:key_up_raw, 1073741903, 0, 2, 57, 373]
-[:key_down_raw, 1073741904, 0, 2, 58, 380]
-[:key_down_raw, 32, 0, 2, 59, 398]
-[:key_up_raw, 32, 0, 2, 60, 404]
-[:key_up_raw, 1073741904, 0, 2, 61, 490]
-[:key_down_raw, 32, 0, 2, 62, 510]
-[:key_up_raw, 32, 0, 2, 63, 516]
-[:key_down_raw, 1073741903, 0, 2, 64, 517]
-[:key_up_raw, 1073741903, 0, 2, 65, 537]
-[:key_down_raw, 1073741904, 0, 2, 66, 538]
-[:key_up_raw, 1073741904, 0, 2, 67, 553]
-[:key_down_raw, 32, 0, 2, 68, 653]
-[:key_up_raw, 32, 0, 2, 69, 659]
-[:key_down_raw, 1073741903, 0, 2, 70, 661]
-[:key_down_raw, 1073741903, 0, 2, 71, 686]
-[:key_up_raw, 1073741903, 0, 2, 72, 687]
-[:key_down_raw, 1073741904, 0, 2, 73, 690]
-[:key_down_raw, 1073741904, 0, 2, 74, 715]
-[:key_down_raw, 1073741904, 0, 2, 75, 717]
-[:key_down_raw, 1073741904, 0, 2, 76, 719]
-[:key_down_raw, 1073741904, 0, 2, 77, 721]
-[:key_down_raw, 1073741904, 0, 2, 78, 723]
-[:key_down_raw, 1073741904, 0, 2, 79, 725]
-[:key_down_raw, 1073741904, 0, 2, 80, 727]
-[:key_down_raw, 1073741904, 0, 2, 81, 729]
-[:key_up_raw, 1073741904, 0, 2, 82, 731]
-[:key_down_raw, 1073741903, 0, 2, 83, 740]
-[:key_down_raw, 32, 0, 2, 84, 749]
-[:key_up_raw, 32, 0, 2, 85, 756]
-[:key_up_raw, 1073741903, 0, 2, 86, 789]
-[:key_down_raw, 1073741904, 0, 2, 87, 792]
-[:key_down_raw, 1073741904, 0, 2, 88, 817]
-[:key_up_raw, 1073741904, 0, 2, 89, 817]
-[:key_down_raw, 32, 0, 2, 90, 844]
-[:key_down_raw, 1073741903, 0, 2, 91, 846]
-[:key_up_raw, 32, 0, 2, 92, 852]
-[:key_down_raw, 1073741903, 0, 2, 93, 871]
-[:key_down_raw, 1073741903, 0, 2, 94, 873]
-[:key_down_raw, 1073741903, 0, 2, 95, 875]
-[:key_down_raw, 1073741903, 0, 2, 96, 877]
-[:key_down_raw, 1073741903, 0, 2, 97, 879]
-[:key_down_raw, 1073741903, 0, 2, 98, 881]
-[:key_down_raw, 1073741903, 0, 2, 99, 883]
-[:key_down_raw, 1073741903, 0, 2, 100, 885]
-[:key_down_raw, 1073741903, 0, 2, 101, 887]
-[:key_up_raw, 1073741903, 0, 2, 102, 887]
-[:key_down_raw, 1073741904, 0, 2, 103, 897]
-[:key_up_raw, 1073741904, 0, 2, 104, 901]
-[:key_down_raw, 32, 0, 2, 105, 948]
-[:key_up_raw, 32, 0, 2, 106, 953]
-[:key_down_raw, 1073741904, 0, 2, 107, 977]
-[:key_up_raw, 1073741904, 0, 2, 108, 991]
-[:key_down_raw, 32, 0, 2, 109, 1056]
-[:key_up_raw, 32, 0, 2, 110, 1060]
-[:key_down_raw, 1073741904, 0, 2, 111, 1065]
-[:key_down_raw, 1073741904, 0, 2, 112, 1090]
-[:key_down_raw, 1073741904, 0, 2, 113, 1092]
-[:key_down_raw, 1073741904, 0, 2, 114, 1094]
-[:key_down_raw, 1073741904, 0, 2, 115, 1096]
-[:key_up_raw, 1073741904, 0, 2, 116, 1098]
-[:key_down_raw, 1073741903, 0, 2, 117, 1108]
-[:key_up_raw, 1073741903, 0, 2, 118, 1127]
-[:key_down_raw, 1073742051, 1024, 2, 119, 1258]
-[:key_down_raw, 113, 1024, 2, 120, 1259]
diff --git a/samples/04_physics_and_collisions/07_jump_physics/app/main.rb b/samples/04_physics_and_collisions/07_jump_physics/app/main.rb
index da01e91..8db98be 100644
--- a/samples/04_physics_and_collisions/07_jump_physics/app/main.rb
+++ b/samples/04_physics_and_collisions/07_jump_physics/app/main.rb
@@ -9,6 +9,7 @@
- args.outputs.solids: An array. The values generate a solid.
The parameters for a solid are [X, Y, WIDTH, HEIGHT, RED, GREEN, BLUE]
+ For more information about solids, go to mygame/documentation/03-solids-and-borders.md.
- num1.greater(num2): Returns the greater value.
@@ -44,8 +45,7 @@ class VerticalPlatformer
input
end
- # Sets default values
- def defaults
+ def init_game
s.platforms ||= [ # initializes platforms collection with two platforms using hashes
new_platform(x: 0, y: 0, w: 700, h: 32, dx: 1, speed: 0, rect: nil),
new_platform(x: 0, y: 300, w: 700, h: 32, dx: 1, speed: 0, rect: nil), # 300 pixels higher
@@ -68,6 +68,11 @@ class VerticalPlatformer
s.camera ||= { y: -100 } # shows view on screen (as the player moves upward, the camera does too)
end
+ # Sets default values
+ def defaults
+ init_game
+ end
+
# Outputs objects onto the screen
def render
outputs.solids << s.platforms.map do |p| # outputs platforms onto screen
@@ -155,7 +160,9 @@ class VerticalPlatformer
rect: nil)
end
else
+ # game over
s.as_hash.clear # otherwise clear the hash (no new platform is necessary)
+ init_game
end
end
diff --git a/samples/04_physics_and_collisions/08_bouncing_on_collision/app/block.rb b/samples/04_physics_and_collisions/08_bouncing_on_collision/app/block.rb
index 9254ee4..ca0cb3a 100644
--- a/samples/04_physics_and_collisions/08_bouncing_on_collision/app/block.rb
+++ b/samples/04_physics_and_collisions/08_bouncing_on_collision/app/block.rb
@@ -1,14 +1,14 @@
DEGREES_TO_RADIANS = Math::PI / 180
-class Block
+class Block
def initialize(x, y, block_size, rotation)
@x = x
- @y = y
+ @y = y
@block_size = block_size
@rotation = rotation
#The repel velocity?
- @velocity = {x: 2, y: 0}
+ @velocity = {x: 2, y: 0}
horizontal_offset = (3 * block_size) * Math.cos(rotation * DEGREES_TO_RADIANS)
vertical_offset = block_size * Math.sin(rotation * DEGREES_TO_RADIANS)
@@ -36,7 +36,7 @@ class Block
@imaginary_line = [ @x1, @y1, @x2, @y2 ]
end
-
+
end
def draw args
@@ -80,7 +80,7 @@ class Block
collision = false
if @rotation >= 0
- if (current_area < min_area &&
+ if (current_area < min_area &&
current_area > 0 &&
args.state.ball.center.y > @y1 &&
args.state.ball.center.x < @x2)
@@ -88,7 +88,7 @@ class Block
collision = true
end
else
- if (current_area < min_area &&
+ if (current_area < min_area &&
current_area > 0 &&
args.state.ball.center.y > @y2 &&
args.state.ball.center.x > @x1)
@@ -96,7 +96,7 @@ class Block
collision = true
end
end
-
+
return collision
end
@@ -117,7 +117,7 @@ class Block
x:args.state.ball.center.x-args.state.ball.velocity.x,
y:args.state.ball.center.y-args.state.ball.velocity.y
}
-
+
velocityMag = (args.state.ball.velocity.x**2 + args.state.ball.velocity.y**2)**0.5 # the current velocity magnitude of the ball
theta_ball = Math.atan2(args.state.ball.velocity.y, args.state.ball.velocity.x) #the angle of the ball's velocity
theta_repel = (180 * DEGREES_TO_RADIANS) - theta_ball + (@rotation * DEGREES_TO_RADIANS)
@@ -139,7 +139,7 @@ class Block
dampener = 0.3
ynew *= dampener * 0.5
-
+
#If the bounce is very low, that means the ball is rolling and we don't want to dampenen the X velocity
if ynew > -0.1
xnew *= dampener
@@ -148,7 +148,7 @@ class Block
#Add the sine component of gravity back in (X component)
gravity_x = 4 * Math.sin(@rotation * DEGREES_TO_RADIANS)
xnew += gravity_x
-
+
args.state.ball.velocity.x = -xnew
args.state.ball.velocity.y = -ynew
diff --git a/samples/04_physics_and_collisions/08_bouncing_on_collision/docs/LinearCollider.md b/samples/04_physics_and_collisions/08_bouncing_on_collision/docs/LinearCollider.md
index 41227a2..315ecf8 100644
--- a/samples/04_physics_and_collisions/08_bouncing_on_collision/docs/LinearCollider.md
+++ b/samples/04_physics_and_collisions/08_bouncing_on_collision/docs/LinearCollider.md
@@ -1,13 +1,13 @@
-<br/>
-<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_1.png?raw=true" width="300" height="271">
-<br/>
-<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_2.png?raw=true" width="300" height="271">
-<br/>
-<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_3.png?raw=true" width="300" height="271">
-<br/>
-<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_4.png?raw=true" width="634" height="72">
-<br/>
-<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_5.png?raw=true" width="1226" height="92">
-<br/>
-<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_6.png?raw=true" width="300" height="271">
-<br/>
+<br/>
+<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_1.png?raw=true" width="300" height="271">
+<br/>
+<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_2.png?raw=true" width="300" height="271">
+<br/>
+<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_3.png?raw=true" width="300" height="271">
+<br/>
+<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_4.png?raw=true" width="634" height="72">
+<br/>
+<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_5.png?raw=true" width="1226" height="92">
+<br/>
+<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_6.png?raw=true" width="300" height="271">
+<br/>
diff --git a/samples/04_physics_and_collisions/09_arbitrary_collision/docs/LinearCollider.md b/samples/04_physics_and_collisions/09_arbitrary_collision/docs/LinearCollider.md
index 41227a2..315ecf8 100644
--- a/samples/04_physics_and_collisions/09_arbitrary_collision/docs/LinearCollider.md
+++ b/samples/04_physics_and_collisions/09_arbitrary_collision/docs/LinearCollider.md
@@ -1,13 +1,13 @@
-<br/>
-<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_1.png?raw=true" width="300" height="271">
-<br/>
-<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_2.png?raw=true" width="300" height="271">
-<br/>
-<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_3.png?raw=true" width="300" height="271">
-<br/>
-<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_4.png?raw=true" width="634" height="72">
-<br/>
-<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_5.png?raw=true" width="1226" height="92">
-<br/>
-<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_6.png?raw=true" width="300" height="271">
-<br/>
+<br/>
+<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_1.png?raw=true" width="300" height="271">
+<br/>
+<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_2.png?raw=true" width="300" height="271">
+<br/>
+<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_3.png?raw=true" width="300" height="271">
+<br/>
+<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_4.png?raw=true" width="634" height="72">
+<br/>
+<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_5.png?raw=true" width="1226" height="92">
+<br/>
+<img src="https://github.com/DragonRuby/dragonruby-game-toolkit-physics/blob/master/docs/docImages/LinearCollider_6.png?raw=true" width="300" height="271">
+<br/>
diff --git a/samples/05_mouse/01_mouse_click/app/main.rb b/samples/05_mouse/01_mouse_click/app/main.rb
index c1a6e29..e37a753 100644
--- a/samples/05_mouse/01_mouse_click/app/main.rb
+++ b/samples/05_mouse/01_mouse_click/app/main.rb
@@ -33,9 +33,11 @@
- args.outputs.borders: An array. The values generate a border.
The parameters are [X, Y, WIDTH, HEIGHT, RED, GREEN, BLUE]
+ For more information about borders, go to mygame/documentation/03-solids-and-borders.md.
- args.outputs.labels: An array. The values generate a label.
The parameters are [X, Y, TEXT, SIZE, ALIGNMENT, RED, GREEN, BLUE, ALPHA, FONT STYLE]
+ For more information about labels, go to mygame/documentation/02-labels.
=end
@@ -47,12 +49,23 @@ class TicTacToe
# Starts the game with player x's turn and creates an array (to_a) for space combinations.
# Calls methods necessary for the game to run properly.
def tick
- state.current_turn ||= :x
- state.space_combinations = [-1, 0, 1].product([-1, 0, 1]).to_a
+ init_new_game
render_board
input_board
end
+ def init_new_game
+ state.current_turn ||= :x
+ state.space_combinations ||= [-1, 0, 1].product([-1, 0, 1]).to_a
+
+ state.spaces ||= {}
+
+ state.space_combinations.each do |x, y|
+ state.spaces[x] ||= {}
+ state.spaces[x][y] ||= state.new_entity(:space)
+ end
+ end
+
# Uses borders to create grid squares for the game's board. Also outputs the game pieces using labels.
def render_board
square_size = 80
@@ -128,6 +141,7 @@ class TicTacToe
def input_restart_game
return unless state.game_over
gtk.reset
+ init_new_game
end
# Checks if x or o won the game.
diff --git a/samples/05_mouse/02_mouse_move/app/main.rb b/samples/05_mouse/02_mouse_move/app/main.rb
index b015277..d9387dc 100644
--- a/samples/05_mouse/02_mouse_move/app/main.rb
+++ b/samples/05_mouse/02_mouse_move/app/main.rb
@@ -14,9 +14,11 @@
- args.inputs.keyboard.key_down.KEY: Determines if a key is being held or pressed.
Stores the frame the "down" event occurred.
+ For more information about the keyboard, go to mygame/documentation/06-keyboard.md.
- args.outputs.sprites: An array. The values generate a sprite.
The parameters are [X, Y, WIDTH, HEIGHT, PATH, ANGLE, ALPHA, RED, GREEN, BLUE]
+ For more information about sprites, go to mygame/documentation/05-sprites.md.
- args.state.new_entity: Used when we want to create a new object, like a sprite or button.
When we want to create a new object, we can declare it as a new entity and then define
@@ -194,7 +196,7 @@ class ProtectThePuppiesFromTheZombies
def calc_kill_zombie
# Find all zombies that intersect with the player. They are considered killed.
- killed_this_frame = state.zombies.find_all { |z| z.sprite.intersect_rect? state.player_sprite }
+ killed_this_frame = state.zombies.find_all { |z| z.sprite && (z.sprite.intersect_rect? state.player_sprite) }
state.zombies = state.zombies - killed_this_frame # remove newly killed zombies from zombies collection
state.killed_zombies += killed_this_frame # add newly killed zombies to killed zombies
diff --git a/samples/05_mouse/03_mouse_move_paint_app/app/main.rb b/samples/05_mouse/03_mouse_move_paint_app/app/main.rb
index b177fd6..9303949 100644
--- a/samples/05_mouse/03_mouse_move_paint_app/app/main.rb
+++ b/samples/05_mouse/03_mouse_move_paint_app/app/main.rb
@@ -34,6 +34,7 @@
- args.outputs.labels: An array. The values in the array generate a label.
The parameters are [X, Y, TEXT, SIZE, ALIGN, RED, GREEN, BLUE, ALPHA, FONT STYLE]
+ For more information about labels, go to mygame/documentation/02-labels.md.
- ARRAY#inside_rect?: Returns true or false depending on if the point is inside the rect.
diff --git a/samples/05_mouse/04_coordinate_systems/app/main.rb b/samples/05_mouse/04_coordinate_systems/app/main.rb
index 8e5578f..fcfa090 100644
--- a/samples/05_mouse/04_coordinate_systems/app/main.rb
+++ b/samples/05_mouse/04_coordinate_systems/app/main.rb
@@ -5,6 +5,7 @@
- args.inputs.mouse.click.position: Coordinates of the mouse's position on the screen.
Unlike args.inputs.mouse.click.point, the mouse does not need to be pressed down for
position to know the mouse's coordinates.
+ For more information about the mouse, go to mygame/documentation/07-mouse.md.
Reminders:
@@ -20,12 +21,15 @@
- args.outputs.labels: An array that generates a label.
The parameters are [X, Y, TEXT, SIZE, ALIGN, RED, GREEN, BLUE, ALPHA, FONT STYLE]
+ For more information about labels, go to mygame/documentation/02-labels.md.
- args.outputs.solids: An array that generates a solid.
The parameters are [X, Y, WIDTH, HEIGHT, RED, GREEN, BLUE, ALPHA]
+ For more information about solids, go to mygame/documentation/03-solids-and-borders.md.
- args.outputs.lines: An array that generates a line.
The parameters are [X, Y, X2, Y2, RED, GREEN, BLUE, ALPHA]
+ For more information about lines, go to mygame/documentation/04-lines.md.
=end
diff --git a/samples/06_save_load/01_save_load_game/app/main.rb b/samples/06_save_load/01_save_load_game/app/main.rb
index cc52770..251848a 100644
--- a/samples/06_save_load/01_save_load_game/app/main.rb
+++ b/samples/06_save_load/01_save_load_game/app/main.rb
@@ -36,6 +36,7 @@
- args.outputs.labels: An array. Values generate a label.
Parameters are [X, Y, TEXT, SIZE, ALIGN, RED, GREEN, BLUE, ALPHA, FONT STYLE]
+ For more information, go to mygame/documentation/02-labels.md.
- ARRAY#inside_rect?: An array with at least two values is considered a point. An array
with at least four values is considered a rect. The inside_rect? function returns true
diff --git a/samples/07_advanced_audio/01_audio_mixer/app/main.rb b/samples/07_advanced_audio/01_audio_mixer/app/main.rb
new file mode 100644
index 0000000..9cdc62f
--- /dev/null
+++ b/samples/07_advanced_audio/01_audio_mixer/app/main.rb
@@ -0,0 +1,377 @@
+# these are the properties that you can sent on args.audio
+def spawn_new_sound args, name, path
+ # Spawn randomly in an area that won't be covered by UI.
+ screenx = (rand * 600.0) + 200.0
+ screeny = (rand * 400.0) + 100.0
+
+ id = new_sound_id! args
+ # you can hang anything on the audio hashes you want, so we store the
+ # actual screen position in here for convenience.
+ args.audio[id] = {
+ name: name,
+ input: path,
+ screenx: screenx,
+ screeny: screeny,
+ x: ((screenx / 1279.0) * 2.0) - 1.0, # scale to -1.0 - 1.0 range
+ y: ((screeny / 719.0) * 2.0) - 1.0, # scale to -1.0 - 1.0 range
+ z: 0.0,
+ gain: 1.0,
+ pitch: 1.0,
+ looping: true,
+ paused: false
+ }
+
+ args.state.selected = id
+end
+
+# these are values you can change on the ~args.audio~ data structure
+def input_panel args
+ return unless args.state.panel
+ return if args.state.dragging
+
+ audio_entry = args.audio[args.state.selected]
+ results = args.state.panel
+
+ if args.state.mouse_state == :held && args.inputs.mouse.position.inside_rect?(results.pitch_slider_rect.rect)
+ audio_entry.pitch = 2.0 * ((args.inputs.mouse.x - results.pitch_slider_rect.x).to_f / (results.pitch_slider_rect.w - 1.0))
+ elsif args.state.mouse_state == :held && args.inputs.mouse.position.inside_rect?(results.playtime_slider_rect.rect)
+ audio_entry.playtime = audio_entry.length_ * ((args.inputs.mouse.x - results.playtime_slider_rect.x).to_f / (results.playtime_slider_rect.w - 1.0))
+ elsif args.state.mouse_state == :held && args.inputs.mouse.position.inside_rect?(results.gain_slider_rect.rect)
+ audio_entry.gain = (args.inputs.mouse.x - results.gain_slider_rect.x).to_f / (results.gain_slider_rect.w - 1.0)
+ elsif args.inputs.mouse.click && args.inputs.mouse.position.inside_rect?(results.looping_checkbox_rect.rect)
+ audio_entry.looping = !audio_entry.looping
+ elsif args.inputs.mouse.click && args.inputs.mouse.position.inside_rect?(results.paused_checkbox_rect.rect)
+ audio_entry.paused = !audio_entry.paused
+ elsif args.inputs.mouse.click && args.inputs.mouse.position.inside_rect?(results.delete_button_rect.rect)
+ args.audio.delete args.state.selected
+ end
+end
+
+def render_sources args
+ args.outputs.primitives << args.audio.keys.map do |k|
+ s = args.audio[k]
+
+ isselected = (k == args.state.selected)
+
+ color = isselected ? [ 0, 255, 0, 255 ] : [ 0, 0, 255, 255 ]
+ [
+ [s.screenx, s.screeny, args.state.boxsize, args.state.boxsize, *color].solid,
+
+ {
+ x: s.screenx + args.state.boxsize.half,
+ y: s.screeny,
+ text: s.name,
+ r: 255,
+ g: 255,
+ b: 255,
+ alignment_enum: 1
+ }.label!
+ ]
+ end
+end
+
+def playtime_str t
+ return "" unless t
+ minutes = (t / 60.0).floor
+ seconds = t - (minutes * 60.0).to_f
+ return minutes.to_s + ':' + seconds.floor.to_s + ((seconds - seconds.floor).to_s + "000")[1..3]
+end
+
+def label_with_drop_shadow x, y, text
+ [
+ { x: x + 1, y: y + 1, text: text, vertical_alignment_enum: 1, alignment_enum: 1, r: 0, g: 0, b: 0 }.label!,
+ { x: x + 2, y: y + 0, text: text, vertical_alignment_enum: 1, alignment_enum: 1, r: 0, g: 0, b: 0 }.label!,
+ { x: x + 0, y: y + 1, text: text, vertical_alignment_enum: 1, alignment_enum: 1, r: 200, g: 200, b: 200 }.label!
+ ]
+end
+
+def check_box opts = {}
+ checkbox_template = opts.args.layout.rect(w: 0.5, h: 0.5, col: 2)
+ final_rect = checkbox_template.center_inside_rect_y(opts.args.layout.rect(row: opts.row, col: opts.col))
+ color = { r: 0, g: 0, b: 0 }
+ color = { r: 255, g: 255, b: 255 } if opts.checked
+
+ {
+ rect: final_rect,
+ primitives: [
+ (final_rect.to_solid color)
+ ]
+ }
+end
+
+def progress_bar opts = {}
+ outer_rect = opts.args.layout.rect(row: opts.row, col: opts.col, w: 5, h: 1)
+ color = opts.percentage * 255
+ baseline_progress_bar = opts.args
+ .layout
+ .rect(w: 5, h: 0.5)
+
+ final_rect = baseline_progress_bar.center_inside_rect(outer_rect)
+ center = final_rect.rect_center_point
+
+ {
+ rect: final_rect,
+ primitives: [
+ final_rect.merge(r: color, g: color, b: color, a: 128).solid!,
+ label_with_drop_shadow(center.x, center.y, opts.text)
+ ]
+ }
+end
+
+def panel_primitives args, audio_entry
+ results = { primitives: [] }
+
+ return results unless audio_entry
+
+ # this uses DRGTK's layout apis to layout the controls
+ # imagine the screen is split into equal cells (24 cells across, 12 cells up and down)
+ # args.layout.rect returns a hash which we merge values with to create primitives
+ # using args.layout.rect removes the need for pixel pushing
+
+ # args.outputs.debug << args.layout.debug_primitives(r: 255, g: 255, b: 255)
+
+ white_color = { r: 255, g: 255, b: 255 }
+ label_style = white_color.merge(vertical_alignment_enum: 1)
+
+ # panel background
+ results.primitives << args.layout.rect(row: 0, col: 0, w: 7, h: 6, include_col_gutter: true, include_row_gutter: true)
+ .border!(r: 255, g: 255, b: 255)
+
+ # title
+ results.primitives << args.layout.point(row: 0, col: 3.5, row_anchor: 0.5)
+ .merge(label_style)
+ .merge(text: "Source #{args.state.selected} (#{args.audio[args.state.selected].name})",
+ size_enum: 3,
+ alignment_enum: 1)
+
+ # seperator line
+ results.primitives << args.layout.rect(row: 1, col: 0, w: 7, h: 0)
+ .line!(white_color)
+
+ # screen location
+ results.primitives << args.layout.point(row: 1.0, col: 0, row_anchor: 0.5)
+ .merge(label_style)
+ .merge(text: "screen:")
+
+ results.primitives << args.layout.point(row: 1.0, col: 2, row_anchor: 0.5)
+ .merge(label_style)
+ .merge(text: "(#{audio_entry.screenx.to_i}, #{audio_entry.screeny.to_i})")
+
+ # position
+ results.primitives << args.layout.point(row: 1.5, col: 0, row_anchor: 0.5)
+ .merge(label_style)
+ .merge(text: "position:")
+
+ results.primitives << args.layout.point(row: 1.5, col: 2, row_anchor: 0.5)
+ .merge(label_style)
+ .merge(text: "(#{audio_entry[:x].round(5).to_s[0..6]}, #{audio_entry[:y].round(5).to_s[0..6]})")
+
+ results.primitives << args.layout.point(row: 2.0, col: 0, row_anchor: 0.5)
+ .merge(label_style)
+ .merge(text: "pitch:")
+
+ results.pitch_slider_rect = progress_bar(row: 2.0, col: 2,
+ percentage: audio_entry.pitch / 2.0,
+ text: "#{audio_entry.pitch.to_sf}",
+ args: args)
+
+ results.primitives << results.pitch_slider_rect.primitives
+
+ results.primitives << args.layout.point(row: 2.5, col: 0, row_anchor: 0.5)
+ .merge(label_style)
+ .merge(text: "playtime:")
+
+ results.playtime_slider_rect = progress_bar(args: args,
+ row: 2.5,
+ col: 2,
+ percentage: (audio_entry.playtime || 1) / (audio_entry.length_ || 1),
+ text: "#{playtime_str(audio_entry.playtime)} / #{playtime_str(audio_entry.length_)}")
+
+ results.primitives << results.playtime_slider_rect.primitives
+
+ results.primitives << args.layout.point(row: 3.0, col: 0, row_anchor: 0.5)
+ .merge(label_style)
+ .merge(text: "gain:")
+
+ results.gain_slider_rect = progress_bar(args: args,
+ row: 3.0,
+ col: 2,
+ percentage: audio_entry.gain,
+ text: "#{audio_entry.gain.to_sf}")
+
+ results.primitives << results.gain_slider_rect.primitives
+
+
+ results.primitives << args.layout.point(row: 3.5, col: 0, row_anchor: 0.5)
+ .merge(label_style)
+ .merge(text: "looping:")
+
+ checkbox_template = args.layout.rect(w: 0.5, h: 0.5, col: 2)
+
+ results.looping_checkbox_rect = check_box(args: args, row: 3.5, col: 2, checked: audio_entry.looping)
+ results.primitives << results.looping_checkbox_rect.primitives
+
+ results.primitives << args.layout.point(row: 4.0, col: 0, row_anchor: 0.5)
+ .merge(label_style)
+ .merge(text: "paused:")
+
+ checkbox_template = args.layout.rect(w: 0.5, h: 0.5, col: 2)
+
+ results.paused_checkbox_rect = check_box(args: args, row: 4.0, col: 2, checked: !audio_entry.paused)
+ results.primitives << results.paused_checkbox_rect.primitives
+
+ results.delete_button_rect = { rect: args.layout.rect(row: 5, col: 0, w: 7, h: 1) }
+
+ results.primitives << results.delete_button_rect.to_solid(r: 180)
+
+ results.primitives << args.layout.point(row: 5, col: 3.5, row_anchor: 0.5)
+ .merge(label_style)
+ .merge(text: "DELETE", alignment_enum: 1)
+
+ return results
+end
+
+def render_panel args
+ args.state.panel = nil
+ audio_entry = args.audio[args.state.selected]
+ return unless audio_entry
+
+ mouse_down = (args.state.mouse_held >= 0)
+ args.state.panel = panel_primitives args, audio_entry
+ args.outputs.primitives << args.state.panel.primitives
+end
+
+def new_sound_id! args
+ args.state.sound_id ||= 0
+ args.state.sound_id += 1
+ args.state.sound_id
+end
+
+def render_launcher args
+ args.outputs.primitives << args.state.spawn_sound_buttons.map(&:primitives)
+end
+
+def render_ui args
+ render_launcher args
+ render_panel args
+end
+
+def tick args
+ defaults args
+ render args
+ input args
+end
+
+def input args
+ if !args.audio[args.state.selected]
+ args.state.selected = nil
+ args.state.dragging = nil
+ end
+
+ # spawn button and node interaction
+ if args.inputs.mouse.click
+ spawn_sound_button = args.state.spawn_sound_buttons.find { |b| args.inputs.mouse.inside_rect? b.rect }
+
+ audio_click_key, audio_click_value = args.audio.find do |k, v|
+ args.inputs.mouse.inside_rect? [v.screenx, v.screeny, args.state.boxsize, args.state.boxsize]
+ end
+
+ if spawn_sound_button
+ args.state.selected = nil
+ spawn_new_sound args, spawn_sound_button.name, spawn_sound_button.path
+ elsif audio_click_key
+ args.state.selected = audio_click_key
+ end
+ end
+
+ if args.state.mouse_state == :held && args.state.selected
+ v = args.audio[args.state.selected]
+ if args.inputs.mouse.inside_rect? [v.screenx, v.screeny, args.state.boxsize, args.state.boxsize]
+ args.state.dragging = args.state.selected
+ end
+
+ if args.state.dragging
+ s = args.audio[args.state.selected]
+ # you can hang anything on the audio hashes you want, so we store the
+ # actual screen position so it doesn't scale weirdly vs your mouse.
+ s.screenx = args.inputs.mouse.x - (args.state.boxsize / 2)
+ s.screeny = args.inputs.mouse.y - (args.state.boxsize / 2)
+
+ s.screeny = 50 if s.screeny < 50
+ s.screeny = (719 - args.state.boxsize) if s.screeny > (719 - args.state.boxsize)
+ s.screenx = 0 if s.screenx < 0
+ s.screenx = (1279 - args.state.boxsize) if s.screenx > (1279 - args.state.boxsize)
+
+ s.x = ((s.screenx / 1279.0) * 2.0) - 1.0 # scale to -1.0 - 1.0 range
+ s.y = ((s.screeny / 719.0) * 2.0) - 1.0 # scale to -1.0 - 1.0 range
+ end
+ elsif args.state.mouse_state == :released
+ args.state.dragging = nil
+ end
+
+ input_panel args
+end
+
+def defaults args
+ args.state.mouse_state ||= :released
+ args.state.dragging_source ||= false
+ args.state.selected ||= 0
+ args.state.next_sound_index ||= 0
+ args.state.boxsize ||= 30
+ args.state.sound_files ||= [
+ { name: :tada, path: "sounds/tada.wav" },
+ { name: :splash, path: "sounds/splash.wav" },
+ { name: :drum, path: "sounds/drum.mp3" },
+ { name: :spring, path: "sounds/spring.wav" },
+ { name: :music, path: "sounds/music.ogg" }
+ ]
+
+ # generate buttons based off the sound collection above
+ args.state.spawn_sound_buttons ||= begin
+ # create a group of buttons
+ # column centered (using col_offset to calculate the column offset)
+ # where each item is 2 columns apart
+ rects = args.layout.rect_group row: 11,
+ col_offset: {
+ count: args.state.sound_files.length,
+ w: 2
+ },
+ dcol: 2,
+ w: 2,
+ h: 1,
+ group: args.state.sound_files
+
+ # now that you have the rects
+ # construct the metadata for the buttons
+ rects.map do |rect|
+ {
+ rect: rect,
+ name: rect.name,
+ path: rect.path,
+ primitives: [
+ rect.to_border(r: 255, g: 255, b: 255),
+ rect.to_label(x: rect.center_x,
+ y: rect.center_y,
+ text: "#{rect.name}",
+ alignment_enum: 1,
+ vertical_alignment_enum: 1,
+ r: 255, g: 255, b: 255)
+ ]
+ }
+ end
+ end
+
+ if args.inputs.mouse.up
+ args.state.mouse_state = :released
+ args.state.dragging_source = false
+ elsif args.inputs.mouse.down
+ args.state.mouse_state = :held
+ end
+
+ args.outputs.background_color = [ 0, 0, 0, 255 ]
+end
+
+def render args
+ render_ui args
+ render_sources args
+end
diff --git a/samples/07_advanced_audio/01_audio_mixer/app/server_ip_address.txt b/samples/07_advanced_audio/01_audio_mixer/app/server_ip_address.txt
new file mode 100644
index 0000000..531e136
--- /dev/null
+++ b/samples/07_advanced_audio/01_audio_mixer/app/server_ip_address.txt
@@ -0,0 +1 @@
+192.168.1.65 \ No newline at end of file
diff --git a/samples/01_rendering_basics/06_audio_mixer/license-for-audio.txt b/samples/07_advanced_audio/01_audio_mixer/license-for-audio.txt
index f05c25c..f05c25c 100644
--- a/samples/01_rendering_basics/06_audio_mixer/license-for-audio.txt
+++ b/samples/07_advanced_audio/01_audio_mixer/license-for-audio.txt
diff --git a/samples/01_rendering_basics/07_sound_synthesis/license-for-sample.txt b/samples/07_advanced_audio/01_audio_mixer/license-for-sample.txt
index 100dcec..100dcec 100644
--- a/samples/01_rendering_basics/07_sound_synthesis/license-for-sample.txt
+++ b/samples/07_advanced_audio/01_audio_mixer/license-for-sample.txt
diff --git a/samples/01_rendering_basics/07_sound_synthesis/metadata/game_metadata.txt b/samples/07_advanced_audio/01_audio_mixer/metadata/game_metadata.txt
index 16cef1d..16cef1d 100644
--- a/samples/01_rendering_basics/07_sound_synthesis/metadata/game_metadata.txt
+++ b/samples/07_advanced_audio/01_audio_mixer/metadata/game_metadata.txt
diff --git a/samples/01_rendering_basics/07_sound_synthesis/metadata/icon.png b/samples/07_advanced_audio/01_audio_mixer/metadata/icon.png
index e20e8c2..e20e8c2 100644
--- a/samples/01_rendering_basics/07_sound_synthesis/metadata/icon.png
+++ b/samples/07_advanced_audio/01_audio_mixer/metadata/icon.png
Binary files differ
diff --git a/samples/07_advanced_audio/01_audio_mixer/metadata/ios_metadata.txt b/samples/07_advanced_audio/01_audio_mixer/metadata/ios_metadata.txt
new file mode 100644
index 0000000..fbd92f5
--- /dev/null
+++ b/samples/07_advanced_audio/01_audio_mixer/metadata/ios_metadata.txt
@@ -0,0 +1,9 @@
+# ios_metadata.txt is used by the Pro version of DragonRuby Game Toolkit to create iOS apps.
+# Information about the Pro version can be found at: http://dragonruby.org/toolkit/game#purchase
+
+# teamid needs to be set to your assigned Team Id which can be found at https://developer.apple.com/account/#/membership/
+teamid=
+# appid needs to be set to your application identifier which can be found at https://developer.apple.com/account/resources/identifiers/list
+appid=
+# appname is the name you want to show up underneath the app icon on the device. Keep it under 10 characters.
+appname=
diff --git a/samples/07_advanced_audio/01_audio_mixer/replay.txt b/samples/07_advanced_audio/01_audio_mixer/replay.txt
new file mode 100644
index 0000000..3ddde51
--- /dev/null
+++ b/samples/07_advanced_audio/01_audio_mixer/replay.txt
@@ -0,0 +1,995 @@
+replay_version 2.0
+stopped_at 2551
+seed 100
+recorded_at Wed Jul 14 23:43:22 2021
+[:mouse_button_up, 1, 0, 1, 1, 3]
+[:mouse_move, 797, 90, 2, 2, 111]
+[:mouse_move, 796, 93, 2, 3, 112]
+[:mouse_move, 794, 97, 2, 4, 113]
+[:mouse_move, 794, 98, 2, 5, 114]
+[:mouse_move, 794, 104, 2, 6, 115]
+[:mouse_move, 793, 106, 2, 7, 116]
+[:mouse_move, 794, 105, 2, 8, 117]
+[:mouse_move, 796, 104, 2, 9, 128]
+[:mouse_move, 798, 103, 2, 10, 129]
+[:mouse_move, 802, 100, 2, 11, 130]
+[:mouse_move, 805, 100, 2, 12, 131]
+[:mouse_move, 809, 100, 2, 13, 132]
+[:mouse_move, 810, 100, 2, 14, 133]
+[:mouse_move, 811, 100, 2, 15, 134]
+[:mouse_move, 812, 100, 2, 16, 135]
+[:mouse_move, 814, 102, 2, 17, 138]
+[:mouse_move, 817, 105, 2, 18, 139]
+[:mouse_move, 823, 118, 2, 19, 140]
+[:mouse_move, 826, 130, 2, 20, 141]
+[:mouse_move, 832, 169, 2, 21, 142]
+[:mouse_move, 834, 196, 2, 22, 143]
+[:mouse_move, 834, 262, 2, 23, 144]
+[:mouse_move, 833, 295, 2, 24, 145]
+[:mouse_move, 829, 327, 2, 25, 146]
+[:mouse_move, 825, 352, 2, 26, 147]
+[:mouse_move, 815, 390, 2, 27, 148]
+[:mouse_move, 805, 414, 2, 28, 149]
+[:mouse_move, 798, 424, 2, 29, 150]
+[:mouse_move, 786, 439, 2, 30, 151]
+[:mouse_move, 783, 443, 2, 31, 152]
+[:mouse_move, 779, 450, 2, 32, 153]
+[:mouse_move, 777, 454, 2, 33, 154]
+[:mouse_move, 775, 461, 2, 34, 155]
+[:mouse_move, 775, 465, 2, 35, 157]
+[:mouse_move, 777, 470, 2, 36, 158]
+[:mouse_move, 783, 490, 2, 37, 159]
+[:mouse_move, 787, 502, 2, 38, 160]
+[:mouse_move, 791, 528, 2, 39, 161]
+[:mouse_move, 794, 548, 2, 40, 162]
+[:mouse_move, 802, 623, 2, 41, 163]
+[:mouse_move, 809, 662, 2, 42, 164]
+[:mouse_move, 819, 691, 2, 43, 165]
+[:mouse_move, 820, 692, 2, 44, 166]
+[:mouse_move, 820, 690, 2, 45, 169]
+[:mouse_move, 821, 685, 2, 46, 170]
+[:mouse_move, 823, 681, 2, 47, 171]
+[:mouse_move, 823, 680, 2, 48, 172]
+[:mouse_move, 823, 679, 2, 49, 173]
+[:mouse_move, 824, 678, 2, 50, 174]
+[:mouse_move, 825, 677, 2, 51, 175]
+[:mouse_move, 826, 675, 2, 52, 176]
+[:mouse_move, 827, 674, 2, 53, 177]
+[:mouse_move, 828, 673, 2, 54, 178]
+[:mouse_move, 829, 673, 2, 55, 179]
+[:mouse_move, 831, 672, 2, 56, 180]
+[:mouse_move, 832, 671, 2, 57, 181]
+[:mouse_move, 835, 669, 2, 58, 182]
+[:mouse_move, 837, 667, 2, 59, 183]
+[:mouse_move, 839, 663, 2, 60, 184]
+[:mouse_move, 839, 662, 2, 61, 185]
+[:mouse_move, 840, 661, 2, 62, 189]
+[:mouse_move, 841, 659, 2, 63, 190]
+[:mouse_move, 841, 658, 2, 64, 191]
+[:mouse_move, 842, 654, 2, 65, 192]
+[:mouse_move, 843, 652, 2, 66, 193]
+[:mouse_move, 845, 644, 2, 67, 194]
+[:mouse_move, 846, 641, 2, 68, 195]
+[:mouse_move, 847, 640, 2, 69, 196]
+[:mouse_button_pressed, 1, 0, 1, 70, 221]
+[:mouse_button_up, 1, 0, 1, 71, 225]
+[:mouse_move, 846, 640, 2, 72, 227]
+[:mouse_move, 839, 634, 2, 73, 254]
+[:mouse_move, 830, 624, 2, 74, 255]
+[:mouse_move, 782, 580, 2, 75, 256]
+[:mouse_move, 735, 541, 2, 76, 257]
+[:mouse_move, 650, 468, 2, 77, 258]
+[:mouse_move, 626, 444, 2, 78, 259]
+[:mouse_move, 615, 431, 2, 79, 260]
+[:mouse_move, 601, 412, 2, 80, 261]
+[:mouse_move, 597, 405, 2, 81, 262]
+[:mouse_move, 589, 393, 2, 82, 263]
+[:mouse_move, 587, 388, 2, 83, 264]
+[:mouse_move, 585, 383, 2, 84, 265]
+[:mouse_move, 585, 381, 2, 85, 266]
+[:mouse_move, 581, 372, 2, 86, 267]
+[:mouse_move, 576, 365, 2, 87, 268]
+[:mouse_move, 568, 350, 2, 88, 269]
+[:mouse_move, 566, 345, 2, 89, 270]
+[:mouse_move, 563, 340, 2, 90, 271]
+[:mouse_move, 563, 339, 2, 91, 272]
+[:mouse_move, 562, 337, 2, 92, 273]
+[:mouse_move, 562, 336, 2, 93, 275]
+[:mouse_move, 561, 336, 2, 94, 278]
+[:mouse_move, 560, 336, 2, 95, 279]
+[:mouse_move, 559, 336, 2, 96, 280]
+[:mouse_move, 557, 335, 2, 97, 281]
+[:mouse_move, 556, 335, 2, 98, 282]
+[:mouse_move, 555, 335, 2, 99, 287]
+[:mouse_move, 555, 336, 2, 100, 288]
+[:mouse_move, 554, 337, 2, 101, 290]
+[:mouse_move, 547, 340, 2, 102, 292]
+[:mouse_move, 544, 340, 2, 103, 293]
+[:mouse_move, 537, 342, 2, 104, 294]
+[:mouse_move, 533, 343, 2, 105, 295]
+[:mouse_move, 525, 343, 2, 106, 296]
+[:mouse_move, 524, 343, 2, 107, 297]
+[:mouse_move, 524, 342, 2, 108, 304]
+[:mouse_move, 524, 341, 2, 109, 306]
+[:mouse_move, 524, 340, 2, 110, 307]
+[:mouse_move, 524, 339, 2, 111, 308]
+[:mouse_move, 525, 338, 2, 112, 310]
+[:mouse_move, 525, 337, 2, 113, 311]
+[:mouse_move, 525, 336, 2, 114, 314]
+[:mouse_move, 526, 336, 2, 115, 316]
+[:mouse_button_pressed, 1, 0, 1, 116, 318]
+[:mouse_move, 520, 336, 2, 117, 321]
+[:mouse_move, 512, 337, 2, 118, 322]
+[:mouse_move, 488, 340, 2, 119, 323]
+[:mouse_move, 471, 344, 2, 120, 324]
+[:mouse_move, 426, 353, 2, 121, 325]
+[:mouse_move, 400, 359, 2, 122, 326]
+[:mouse_move, 354, 371, 2, 123, 327]
+[:mouse_move, 335, 375, 2, 124, 328]
+[:mouse_move, 306, 381, 2, 125, 329]
+[:mouse_move, 295, 385, 2, 126, 330]
+[:mouse_move, 278, 390, 2, 127, 331]
+[:mouse_move, 268, 393, 2, 128, 332]
+[:mouse_move, 247, 401, 2, 129, 333]
+[:mouse_move, 238, 407, 2, 130, 334]
+[:mouse_move, 225, 416, 2, 131, 335]
+[:mouse_move, 219, 420, 2, 132, 336]
+[:mouse_move, 208, 428, 2, 133, 337]
+[:mouse_move, 201, 434, 2, 134, 338]
+[:mouse_move, 186, 444, 2, 135, 339]
+[:mouse_move, 181, 448, 2, 136, 340]
+[:mouse_move, 177, 452, 2, 137, 341]
+[:mouse_button_up, 1, 0, 1, 138, 349]
+[:mouse_move, 178, 452, 2, 139, 349]
+[:mouse_move, 192, 442, 2, 140, 350]
+[:mouse_move, 208, 432, 2, 141, 351]
+[:mouse_move, 259, 405, 2, 142, 352]
+[:mouse_move, 294, 391, 2, 143, 353]
+[:mouse_move, 380, 369, 2, 144, 354]
+[:mouse_move, 415, 361, 2, 145, 355]
+[:mouse_move, 459, 351, 2, 146, 356]
+[:mouse_move, 475, 348, 2, 147, 357]
+[:mouse_move, 505, 342, 2, 148, 358]
+[:mouse_move, 519, 341, 2, 149, 359]
+[:mouse_move, 538, 337, 2, 150, 360]
+[:mouse_move, 544, 335, 2, 151, 361]
+[:mouse_move, 546, 334, 2, 152, 362]
+[:mouse_button_pressed, 1, 0, 1, 153, 379]
+[:mouse_move, 542, 336, 2, 154, 383]
+[:mouse_move, 537, 340, 2, 155, 384]
+[:mouse_move, 509, 356, 2, 156, 385]
+[:mouse_move, 489, 366, 2, 157, 386]
+[:mouse_move, 435, 389, 2, 158, 387]
+[:mouse_move, 409, 400, 2, 159, 388]
+[:mouse_move, 353, 423, 2, 160, 389]
+[:mouse_move, 332, 432, 2, 161, 390]
+[:mouse_move, 301, 445, 2, 162, 391]
+[:mouse_move, 290, 450, 2, 163, 392]
+[:mouse_move, 278, 457, 2, 164, 393]
+[:mouse_move, 275, 459, 2, 165, 394]
+[:mouse_move, 267, 465, 2, 166, 395]
+[:mouse_move, 261, 469, 2, 167, 396]
+[:mouse_move, 254, 474, 2, 168, 397]
+[:mouse_move, 244, 481, 2, 169, 398]
+[:mouse_move, 241, 484, 2, 170, 399]
+[:mouse_move, 240, 485, 2, 171, 400]
+[:mouse_move, 237, 488, 2, 172, 402]
+[:mouse_move, 234, 491, 2, 173, 404]
+[:mouse_move, 231, 493, 2, 174, 405]
+[:mouse_move, 224, 500, 2, 175, 406]
+[:mouse_move, 222, 502, 2, 176, 407]
+[:mouse_move, 219, 505, 2, 177, 408]
+[:mouse_move, 218, 505, 2, 178, 409]
+[:mouse_move, 214, 506, 2, 179, 412]
+[:mouse_move, 211, 507, 2, 180, 413]
+[:mouse_move, 202, 509, 2, 181, 414]
+[:mouse_move, 198, 509, 2, 182, 415]
+[:mouse_move, 183, 511, 2, 183, 416]
+[:mouse_move, 174, 511, 2, 184, 417]
+[:mouse_move, 169, 511, 2, 185, 418]
+[:mouse_move, 166, 511, 2, 186, 420]
+[:mouse_move, 164, 511, 2, 187, 421]
+[:mouse_move, 163, 511, 2, 188, 422]
+[:mouse_move, 164, 511, 2, 189, 434]
+[:mouse_move, 164, 510, 2, 190, 436]
+[:mouse_move, 166, 510, 2, 191, 437]
+[:mouse_move, 167, 510, 2, 192, 438]
+[:mouse_move, 171, 509, 2, 193, 439]
+[:mouse_move, 174, 508, 2, 194, 440]
+[:mouse_move, 186, 504, 2, 195, 441]
+[:mouse_move, 197, 501, 2, 196, 442]
+[:mouse_move, 247, 487, 2, 197, 443]
+[:mouse_move, 298, 477, 2, 198, 444]
+[:mouse_move, 429, 457, 2, 199, 445]
+[:mouse_move, 481, 451, 2, 200, 446]
+[:mouse_move, 586, 439, 2, 201, 447]
+[:mouse_move, 632, 437, 2, 202, 448]
+[:mouse_move, 728, 439, 2, 203, 449]
+[:mouse_move, 785, 440, 2, 204, 450]
+[:mouse_move, 905, 441, 2, 205, 451]
+[:mouse_move, 943, 445, 2, 206, 452]
+[:mouse_move, 981, 449, 2, 207, 453]
+[:mouse_move, 997, 451, 2, 208, 454]
+[:mouse_move, 1020, 455, 2, 209, 455]
+[:mouse_move, 1034, 456, 2, 210, 456]
+[:mouse_move, 1049, 458, 2, 211, 457]
+[:mouse_move, 1065, 459, 2, 212, 458]
+[:mouse_move, 1088, 460, 2, 213, 459]
+[:mouse_move, 1101, 461, 2, 214, 460]
+[:mouse_move, 1106, 461, 2, 215, 461]
+[:mouse_move, 1116, 463, 2, 216, 462]
+[:mouse_move, 1123, 465, 2, 217, 463]
+[:mouse_move, 1137, 468, 2, 218, 464]
+[:mouse_move, 1140, 468, 2, 219, 465]
+[:mouse_move, 1141, 468, 2, 220, 466]
+[:mouse_move, 1141, 469, 2, 221, 469]
+[:mouse_move, 1142, 469, 2, 222, 472]
+[:mouse_move, 1143, 469, 2, 223, 476]
+[:mouse_move, 1144, 469, 2, 224, 478]
+[:mouse_move, 1143, 469, 2, 225, 487]
+[:mouse_move, 1137, 469, 2, 226, 488]
+[:mouse_move, 1106, 463, 2, 227, 489]
+[:mouse_move, 1082, 456, 2, 228, 490]
+[:mouse_move, 1025, 442, 2, 229, 491]
+[:mouse_move, 985, 434, 2, 230, 492]
+[:mouse_move, 889, 417, 2, 231, 493]
+[:mouse_move, 841, 410, 2, 232, 494]
+[:mouse_move, 749, 402, 2, 233, 495]
+[:mouse_move, 705, 399, 2, 234, 496]
+[:mouse_move, 647, 396, 2, 235, 497]
+[:mouse_move, 632, 396, 2, 236, 498]
+[:mouse_move, 609, 398, 2, 237, 499]
+[:mouse_move, 597, 400, 2, 238, 500]
+[:mouse_move, 585, 403, 2, 239, 501]
+[:mouse_move, 584, 403, 2, 240, 502]
+[:mouse_move, 585, 403, 2, 241, 521]
+[:mouse_move, 585, 402, 2, 242, 522]
+[:mouse_move, 587, 400, 2, 243, 523]
+[:mouse_move, 595, 395, 2, 244, 524]
+[:mouse_move, 602, 392, 2, 245, 525]
+[:mouse_move, 617, 388, 2, 246, 526]
+[:mouse_move, 626, 387, 2, 247, 527]
+[:mouse_move, 641, 385, 2, 248, 528]
+[:mouse_move, 645, 385, 2, 249, 529]
+[:mouse_move, 646, 385, 2, 250, 530]
+[:mouse_move, 646, 384, 2, 251, 539]
+[:mouse_move, 645, 384, 2, 252, 545]
+[:mouse_move, 644, 384, 2, 253, 547]
+[:mouse_button_up, 1, 0, 1, 254, 547]
+[:mouse_move, 641, 383, 2, 255, 547]
+[:mouse_move, 634, 381, 2, 256, 548]
+[:mouse_move, 608, 370, 2, 257, 549]
+[:mouse_move, 573, 355, 2, 258, 550]
+[:mouse_move, 415, 301, 2, 259, 551]
+[:mouse_move, 315, 267, 2, 260, 552]
+[:mouse_move, 161, 209, 2, 261, 553]
+[:mouse_move, 117, 193, 2, 262, 554]
+[:mouse_move, 91, 178, 2, 263, 555]
+[:mouse_move, 91, 177, 2, 264, 556]
+[:mouse_move, 92, 176, 2, 265, 557]
+[:mouse_move, 94, 174, 2, 266, 559]
+[:mouse_move, 97, 172, 2, 267, 560]
+[:mouse_move, 101, 169, 2, 268, 561]
+[:mouse_move, 102, 169, 2, 269, 562]
+[:mouse_move, 107, 163, 2, 270, 563]
+[:mouse_move, 109, 159, 2, 271, 564]
+[:mouse_move, 114, 154, 2, 272, 565]
+[:mouse_move, 116, 153, 2, 273, 566]
+[:mouse_move, 118, 153, 2, 274, 567]
+[:mouse_move, 124, 154, 2, 275, 568]
+[:mouse_move, 131, 156, 2, 276, 569]
+[:mouse_move, 156, 162, 2, 277, 570]
+[:mouse_move, 166, 165, 2, 278, 571]
+[:mouse_move, 185, 170, 2, 279, 572]
+[:mouse_move, 194, 172, 2, 280, 573]
+[:mouse_move, 205, 175, 2, 281, 574]
+[:mouse_move, 206, 176, 2, 282, 575]
+[:mouse_move, 203, 176, 2, 283, 580]
+[:mouse_move, 202, 176, 2, 284, 582]
+[:mouse_button_pressed, 1, 0, 1, 285, 607]
+[:mouse_move, 206, 176, 2, 286, 615]
+[:mouse_move, 210, 176, 2, 287, 616]
+[:mouse_move, 222, 178, 2, 288, 617]
+[:mouse_move, 228, 180, 2, 289, 618]
+[:mouse_move, 243, 183, 2, 290, 619]
+[:mouse_move, 248, 184, 2, 291, 620]
+[:mouse_move, 254, 185, 2, 292, 621]
+[:mouse_move, 263, 186, 2, 293, 622]
+[:mouse_move, 268, 187, 2, 294, 623]
+[:mouse_move, 274, 187, 2, 295, 624]
+[:mouse_move, 276, 188, 2, 296, 625]
+[:mouse_move, 280, 188, 2, 297, 626]
+[:mouse_move, 282, 188, 2, 298, 627]
+[:mouse_move, 291, 189, 2, 299, 628]
+[:mouse_move, 295, 189, 2, 300, 629]
+[:mouse_move, 303, 191, 2, 301, 630]
+[:mouse_move, 307, 191, 2, 302, 631]
+[:mouse_move, 313, 192, 2, 303, 632]
+[:mouse_move, 317, 192, 2, 304, 633]
+[:mouse_move, 327, 193, 2, 305, 634]
+[:mouse_move, 332, 193, 2, 306, 635]
+[:mouse_move, 339, 193, 2, 307, 636]
+[:mouse_move, 341, 193, 2, 308, 637]
+[:mouse_move, 344, 193, 2, 309, 638]
+[:mouse_move, 346, 194, 2, 310, 639]
+[:mouse_move, 350, 194, 2, 311, 640]
+[:mouse_move, 352, 194, 2, 312, 641]
+[:mouse_move, 353, 194, 2, 313, 642]
+[:mouse_move, 354, 194, 2, 314, 643]
+[:mouse_move, 354, 193, 2, 315, 644]
+[:mouse_move, 355, 193, 2, 316, 645]
+[:mouse_move, 356, 193, 2, 317, 649]
+[:mouse_move, 357, 192, 2, 318, 651]
+[:mouse_move, 358, 192, 2, 319, 654]
+[:mouse_move, 359, 191, 2, 320, 659]
+[:mouse_move, 360, 191, 2, 321, 660]
+[:mouse_move, 361, 190, 2, 322, 661]
+[:mouse_move, 362, 189, 2, 323, 662]
+[:mouse_move, 363, 189, 2, 324, 663]
+[:mouse_move, 364, 188, 2, 325, 664]
+[:mouse_move, 365, 188, 2, 326, 665]
+[:mouse_move, 366, 188, 2, 327, 667]
+[:mouse_move, 367, 187, 2, 328, 669]
+[:mouse_move, 368, 187, 2, 329, 671]
+[:mouse_move, 369, 187, 2, 330, 672]
+[:mouse_move, 370, 186, 2, 331, 673]
+[:mouse_move, 371, 186, 2, 332, 675]
+[:mouse_move, 371, 185, 2, 333, 676]
+[:mouse_move, 372, 185, 2, 334, 678]
+[:mouse_move, 372, 184, 2, 335, 679]
+[:mouse_move, 372, 183, 2, 336, 683]
+[:mouse_move, 371, 183, 2, 337, 684]
+[:mouse_move, 372, 183, 2, 338, 692]
+[:mouse_move, 372, 182, 2, 339, 694]
+[:mouse_move, 373, 182, 2, 340, 695]
+[:mouse_move, 374, 182, 2, 341, 696]
+[:mouse_move, 374, 181, 2, 342, 698]
+[:mouse_move, 375, 181, 2, 343, 699]
+[:mouse_move, 376, 180, 2, 344, 700]
+[:mouse_move, 377, 180, 2, 345, 702]
+[:mouse_move, 376, 180, 2, 346, 709]
+[:mouse_move, 375, 180, 2, 347, 711]
+[:mouse_move, 374, 180, 2, 348, 715]
+[:mouse_move, 371, 180, 2, 349, 730]
+[:mouse_move, 363, 180, 2, 350, 731]
+[:mouse_move, 358, 180, 2, 351, 732]
+[:mouse_move, 352, 180, 2, 352, 733]
+[:mouse_move, 338, 182, 2, 353, 734]
+[:mouse_move, 333, 182, 2, 354, 735]
+[:mouse_move, 327, 183, 2, 355, 736]
+[:mouse_move, 324, 183, 2, 356, 737]
+[:mouse_move, 309, 183, 2, 357, 738]
+[:mouse_move, 303, 183, 2, 358, 739]
+[:mouse_move, 295, 182, 2, 359, 740]
+[:mouse_move, 293, 182, 2, 360, 741]
+[:mouse_move, 292, 182, 2, 361, 742]
+[:mouse_move, 291, 182, 2, 362, 744]
+[:mouse_move, 288, 182, 2, 363, 746]
+[:mouse_move, 286, 182, 2, 364, 747]
+[:mouse_move, 281, 182, 2, 365, 748]
+[:mouse_move, 278, 182, 2, 366, 749]
+[:mouse_move, 270, 183, 2, 367, 750]
+[:mouse_move, 268, 183, 2, 368, 751]
+[:mouse_move, 266, 183, 2, 369, 752]
+[:mouse_move, 265, 183, 2, 370, 753]
+[:mouse_move, 262, 183, 2, 371, 754]
+[:mouse_move, 257, 183, 2, 372, 755]
+[:mouse_move, 252, 183, 2, 373, 756]
+[:mouse_move, 251, 183, 2, 374, 757]
+[:mouse_move, 250, 183, 2, 375, 758]
+[:mouse_move, 249, 183, 2, 376, 769]
+[:mouse_move, 247, 182, 2, 377, 773]
+[:mouse_move, 243, 182, 2, 378, 774]
+[:mouse_move, 242, 182, 2, 379, 775]
+[:mouse_move, 243, 182, 2, 380, 796]
+[:mouse_move, 244, 182, 2, 381, 800]
+[:mouse_move, 245, 182, 2, 382, 806]
+[:mouse_move, 246, 182, 2, 383, 824]
+[:mouse_move, 247, 182, 2, 384, 827]
+[:mouse_move, 248, 183, 2, 385, 850]
+[:mouse_move, 249, 183, 2, 386, 855]
+[:mouse_button_up, 1, 0, 1, 387, 893]
+[:mouse_move, 249, 184, 2, 388, 904]
+[:mouse_move, 249, 185, 2, 389, 905]
+[:mouse_move, 249, 191, 2, 390, 906]
+[:mouse_move, 249, 196, 2, 391, 907]
+[:mouse_move, 247, 208, 2, 392, 908]
+[:mouse_move, 246, 214, 2, 393, 909]
+[:mouse_move, 244, 223, 2, 394, 910]
+[:mouse_move, 244, 225, 2, 395, 911]
+[:mouse_move, 243, 226, 2, 396, 912]
+[:mouse_move, 243, 227, 2, 397, 913]
+[:mouse_move, 242, 229, 2, 398, 914]
+[:mouse_move, 241, 229, 2, 399, 915]
+[:mouse_move, 241, 230, 2, 400, 916]
+[:mouse_move, 240, 230, 2, 401, 919]
+[:mouse_move, 240, 231, 2, 402, 920]
+[:mouse_move, 239, 232, 2, 403, 922]
+[:mouse_move, 239, 231, 2, 404, 945]
+[:mouse_move, 240, 230, 2, 405, 947]
+[:mouse_button_pressed, 1, 0, 1, 406, 960]
+[:mouse_button_up, 1, 0, 1, 407, 966]
+[:mouse_move, 243, 230, 2, 408, 1005]
+[:mouse_move, 245, 229, 2, 409, 1007]
+[:mouse_move, 247, 229, 2, 410, 1009]
+[:mouse_move, 251, 229, 2, 411, 1010]
+[:mouse_move, 259, 228, 2, 412, 1011]
+[:mouse_move, 262, 228, 2, 413, 1012]
+[:mouse_move, 264, 228, 2, 414, 1013]
+[:mouse_move, 271, 227, 2, 415, 1014]
+[:mouse_move, 277, 227, 2, 416, 1015]
+[:mouse_move, 288, 226, 2, 417, 1016]
+[:mouse_move, 292, 225, 2, 418, 1017]
+[:mouse_move, 304, 225, 2, 419, 1018]
+[:mouse_move, 308, 225, 2, 420, 1019]
+[:mouse_move, 316, 225, 2, 421, 1020]
+[:mouse_move, 319, 224, 2, 422, 1021]
+[:mouse_move, 324, 223, 2, 423, 1022]
+[:mouse_move, 327, 222, 2, 424, 1023]
+[:mouse_move, 334, 222, 2, 425, 1024]
+[:mouse_move, 340, 222, 2, 426, 1025]
+[:mouse_move, 351, 224, 2, 427, 1026]
+[:mouse_move, 355, 225, 2, 428, 1027]
+[:mouse_move, 359, 225, 2, 429, 1028]
+[:mouse_move, 360, 225, 2, 430, 1029]
+[:mouse_move, 361, 225, 2, 431, 1034]
+[:mouse_move, 362, 225, 2, 432, 1036]
+[:mouse_move, 363, 225, 2, 433, 1037]
+[:mouse_move, 365, 225, 2, 434, 1038]
+[:mouse_move, 366, 226, 2, 435, 1040]
+[:mouse_move, 367, 227, 2, 436, 1043]
+[:mouse_move, 368, 227, 2, 437, 1047]
+[:mouse_move, 369, 227, 2, 438, 1051]
+[:mouse_move, 370, 227, 2, 439, 1052]
+[:mouse_move, 371, 228, 2, 440, 1053]
+[:mouse_move, 372, 228, 2, 441, 1054]
+[:mouse_move, 373, 228, 2, 442, 1057]
+[:mouse_move, 374, 228, 2, 443, 1061]
+[:mouse_button_pressed, 1, 0, 1, 444, 1066]
+[:mouse_move, 375, 229, 2, 445, 1079]
+[:mouse_move, 377, 229, 2, 446, 1080]
+[:mouse_move, 378, 229, 2, 447, 1082]
+[:mouse_move, 378, 230, 2, 448, 1088]
+[:mouse_move, 379, 230, 2, 449, 1089]
+[:mouse_move, 380, 230, 2, 450, 1090]
+[:mouse_move, 381, 230, 2, 451, 1091]
+[:mouse_move, 382, 230, 2, 452, 1092]
+[:mouse_move, 383, 230, 2, 453, 1094]
+[:mouse_button_up, 1, 0, 1, 454, 1123]
+[:mouse_move, 382, 230, 2, 455, 1124]
+[:mouse_move, 381, 230, 2, 456, 1125]
+[:mouse_move, 377, 229, 2, 457, 1126]
+[:mouse_move, 371, 229, 2, 458, 1127]
+[:mouse_move, 351, 233, 2, 459, 1128]
+[:mouse_move, 340, 236, 2, 460, 1129]
+[:mouse_move, 312, 244, 2, 461, 1130]
+[:mouse_move, 232, 261, 2, 462, 1132]
+[:mouse_move, 213, 263, 2, 463, 1133]
+[:mouse_move, 185, 265, 2, 464, 1134]
+[:mouse_move, 172, 265, 2, 465, 1135]
+[:mouse_move, 155, 265, 2, 466, 1136]
+[:mouse_move, 153, 265, 2, 467, 1137]
+[:mouse_move, 152, 265, 2, 468, 1143]
+[:mouse_move, 152, 264, 2, 469, 1148]
+[:mouse_move, 151, 264, 2, 470, 1150]
+[:mouse_move, 150, 264, 2, 471, 1151]
+[:mouse_move, 147, 266, 2, 472, 1152]
+[:mouse_move, 142, 271, 2, 473, 1153]
+[:mouse_move, 141, 273, 2, 474, 1154]
+[:mouse_move, 139, 279, 2, 475, 1155]
+[:mouse_move, 139, 280, 2, 476, 1156]
+[:mouse_move, 138, 283, 2, 477, 1157]
+[:mouse_move, 138, 285, 2, 478, 1158]
+[:mouse_move, 138, 286, 2, 479, 1159]
+[:mouse_move, 138, 287, 2, 480, 1163]
+[:mouse_move, 138, 288, 2, 481, 1164]
+[:mouse_move, 139, 289, 2, 482, 1165]
+[:mouse_move, 138, 289, 2, 483, 1171]
+[:mouse_move, 137, 288, 2, 484, 1172]
+[:mouse_move, 136, 286, 2, 485, 1173]
+[:mouse_move, 135, 285, 2, 486, 1174]
+[:mouse_move, 135, 284, 2, 487, 1177]
+[:mouse_button_pressed, 1, 0, 1, 488, 1183]
+[:mouse_button_up, 1, 0, 1, 489, 1186]
+[:mouse_move, 136, 284, 2, 490, 1190]
+[:mouse_move, 137, 284, 2, 491, 1193]
+[:mouse_button_pressed, 1, 0, 1, 492, 1231]
+[:mouse_button_up, 1, 0, 1, 493, 1233]
+[:mouse_move, 138, 281, 2, 494, 1242]
+[:mouse_move, 140, 279, 2, 495, 1243]
+[:mouse_move, 150, 267, 2, 496, 1244]
+[:mouse_move, 157, 260, 2, 497, 1245]
+[:mouse_move, 171, 248, 2, 498, 1246]
+[:mouse_move, 180, 242, 2, 499, 1247]
+[:mouse_move, 206, 229, 2, 500, 1248]
+[:mouse_move, 222, 224, 2, 501, 1249]
+[:mouse_move, 248, 217, 2, 502, 1250]
+[:mouse_move, 257, 216, 2, 503, 1251]
+[:mouse_move, 266, 215, 2, 504, 1252]
+[:mouse_move, 266, 214, 2, 505, 1261]
+[:mouse_move, 266, 208, 2, 506, 1263]
+[:mouse_move, 265, 207, 2, 507, 1264]
+[:mouse_move, 258, 202, 2, 508, 1265]
+[:mouse_move, 256, 201, 2, 509, 1266]
+[:mouse_move, 250, 200, 2, 510, 1267]
+[:mouse_move, 249, 200, 2, 511, 1268]
+[:mouse_move, 249, 199, 2, 512, 1269]
+[:mouse_move, 248, 199, 2, 513, 1272]
+[:mouse_move, 248, 200, 2, 514, 1285]
+[:mouse_move, 245, 202, 2, 515, 1286]
+[:mouse_move, 244, 205, 2, 516, 1287]
+[:mouse_move, 243, 205, 2, 517, 1288]
+[:mouse_move, 241, 207, 2, 518, 1289]
+[:mouse_move, 241, 208, 2, 519, 1290]
+[:mouse_move, 240, 208, 2, 520, 1291]
+[:mouse_move, 239, 209, 2, 521, 1292]
+[:mouse_move, 238, 209, 2, 522, 1293]
+[:mouse_move, 238, 208, 2, 523, 1299]
+[:mouse_move, 238, 207, 2, 524, 1300]
+[:mouse_move, 238, 206, 2, 525, 1302]
+[:mouse_move, 238, 205, 2, 526, 1304]
+[:mouse_move, 239, 205, 2, 527, 1305]
+[:mouse_move, 239, 204, 2, 528, 1306]
+[:mouse_move, 243, 205, 2, 529, 1336]
+[:mouse_move, 257, 207, 2, 530, 1337]
+[:mouse_move, 267, 208, 2, 531, 1338]
+[:mouse_move, 294, 210, 2, 532, 1339]
+[:mouse_move, 308, 211, 2, 533, 1340]
+[:mouse_move, 337, 212, 2, 534, 1341]
+[:mouse_move, 350, 212, 2, 535, 1342]
+[:mouse_move, 361, 212, 2, 536, 1343]
+[:mouse_move, 363, 211, 2, 537, 1344]
+[:mouse_move, 365, 211, 2, 538, 1345]
+[:mouse_move, 366, 211, 2, 539, 1346]
+[:mouse_move, 367, 210, 2, 540, 1348]
+[:mouse_button_pressed, 1, 0, 1, 541, 1356]
+[:mouse_button_up, 1, 0, 1, 542, 1361]
+[:mouse_move, 363, 210, 2, 543, 1388]
+[:mouse_move, 346, 213, 2, 544, 1389]
+[:mouse_move, 331, 214, 2, 545, 1390]
+[:mouse_move, 290, 218, 2, 546, 1391]
+[:mouse_move, 271, 218, 2, 547, 1392]
+[:mouse_move, 241, 218, 2, 548, 1393]
+[:mouse_move, 232, 218, 2, 549, 1394]
+[:mouse_move, 224, 217, 2, 550, 1395]
+[:mouse_move, 222, 217, 2, 551, 1396]
+[:mouse_move, 218, 216, 2, 552, 1397]
+[:mouse_move, 215, 215, 2, 553, 1398]
+[:mouse_move, 211, 214, 2, 554, 1399]
+[:mouse_move, 211, 213, 2, 555, 1400]
+[:mouse_move, 210, 213, 2, 556, 1401]
+[:mouse_move, 210, 212, 2, 557, 1404]
+[:mouse_move, 211, 212, 2, 558, 1405]
+[:mouse_move, 212, 212, 2, 559, 1406]
+[:mouse_move, 213, 211, 2, 560, 1407]
+[:mouse_move, 215, 210, 2, 561, 1408]
+[:mouse_move, 218, 210, 2, 562, 1409]
+[:mouse_move, 224, 210, 2, 563, 1410]
+[:mouse_button_pressed, 1, 0, 1, 564, 1414]
+[:mouse_button_up, 1, 0, 1, 565, 1420]
+[:mouse_move, 227, 210, 2, 566, 1427]
+[:mouse_move, 233, 209, 2, 567, 1428]
+[:mouse_move, 236, 209, 2, 568, 1429]
+[:mouse_move, 237, 209, 2, 569, 1430]
+[:mouse_move, 239, 208, 2, 570, 1431]
+[:mouse_move, 241, 208, 2, 571, 1433]
+[:mouse_move, 242, 208, 2, 572, 1434]
+[:mouse_move, 244, 207, 2, 573, 1435]
+[:mouse_move, 245, 207, 2, 574, 1436]
+[:mouse_move, 246, 207, 2, 575, 1437]
+[:mouse_move, 247, 207, 2, 576, 1450]
+[:mouse_move, 249, 207, 2, 577, 1451]
+[:mouse_move, 251, 206, 2, 578, 1452]
+[:mouse_move, 255, 205, 2, 579, 1453]
+[:mouse_move, 256, 205, 2, 580, 1455]
+[:mouse_move, 255, 205, 2, 581, 1470]
+[:mouse_move, 251, 206, 2, 582, 1471]
+[:mouse_move, 233, 207, 2, 583, 1472]
+[:mouse_move, 223, 207, 2, 584, 1473]
+[:mouse_move, 201, 208, 2, 585, 1474]
+[:mouse_move, 185, 209, 2, 586, 1475]
+[:mouse_move, 127, 210, 2, 587, 1476]
+[:mouse_move, 107, 211, 2, 588, 1477]
+[:mouse_move, 97, 211, 2, 589, 1478]
+[:mouse_move, 98, 211, 2, 590, 1485]
+[:mouse_move, 99, 211, 2, 591, 1486]
+[:mouse_move, 100, 211, 2, 592, 1487]
+[:mouse_move, 102, 210, 2, 593, 1488]
+[:mouse_move, 106, 209, 2, 594, 1489]
+[:mouse_move, 110, 208, 2, 595, 1490]
+[:mouse_move, 119, 206, 2, 596, 1491]
+[:mouse_move, 124, 206, 2, 597, 1492]
+[:mouse_move, 126, 205, 2, 598, 1493]
+[:mouse_move, 127, 205, 2, 599, 1494]
+[:mouse_move, 128, 205, 2, 600, 1499]
+[:mouse_move, 128, 204, 2, 601, 1502]
+[:mouse_move, 128, 203, 2, 602, 1507]
+[:mouse_move, 127, 203, 2, 603, 1511]
+[:mouse_button_pressed, 1, 0, 1, 604, 1516]
+[:mouse_button_up, 1, 0, 1, 605, 1521]
+[:mouse_move, 131, 205, 2, 606, 1534]
+[:mouse_move, 132, 206, 2, 607, 1535]
+[:mouse_move, 138, 211, 2, 608, 1536]
+[:mouse_move, 142, 214, 2, 609, 1537]
+[:mouse_move, 151, 223, 2, 610, 1538]
+[:mouse_move, 157, 229, 2, 611, 1539]
+[:mouse_move, 171, 248, 2, 612, 1540]
+[:mouse_move, 179, 259, 2, 613, 1541]
+[:mouse_move, 184, 270, 2, 614, 1542]
+[:mouse_move, 195, 289, 2, 615, 1543]
+[:mouse_move, 200, 297, 2, 616, 1544]
+[:mouse_move, 207, 309, 2, 617, 1545]
+[:mouse_move, 209, 313, 2, 618, 1546]
+[:mouse_move, 211, 316, 2, 619, 1547]
+[:mouse_move, 211, 317, 2, 620, 1548]
+[:mouse_move, 212, 319, 2, 621, 1549]
+[:mouse_move, 212, 320, 2, 622, 1551]
+[:mouse_move, 213, 320, 2, 623, 1552]
+[:mouse_move, 213, 322, 2, 624, 1554]
+[:mouse_move, 216, 327, 2, 625, 1555]
+[:mouse_move, 217, 329, 2, 626, 1556]
+[:mouse_move, 220, 333, 2, 627, 1557]
+[:mouse_move, 221, 335, 2, 628, 1558]
+[:mouse_move, 221, 336, 2, 629, 1559]
+[:mouse_move, 222, 337, 2, 630, 1560]
+[:mouse_move, 223, 340, 2, 631, 1561]
+[:mouse_move, 226, 343, 2, 632, 1562]
+[:mouse_move, 232, 348, 2, 633, 1563]
+[:mouse_move, 235, 350, 2, 634, 1564]
+[:mouse_move, 236, 350, 2, 635, 1565]
+[:mouse_move, 236, 349, 2, 636, 1602]
+[:mouse_move, 241, 339, 2, 637, 1603]
+[:mouse_move, 242, 332, 2, 638, 1604]
+[:mouse_move, 246, 318, 2, 639, 1605]
+[:mouse_move, 246, 311, 2, 640, 1606]
+[:mouse_move, 245, 288, 2, 641, 1607]
+[:mouse_move, 241, 271, 2, 642, 1608]
+[:mouse_move, 226, 240, 2, 643, 1609]
+[:mouse_move, 219, 228, 2, 644, 1610]
+[:mouse_move, 214, 218, 2, 645, 1611]
+[:mouse_move, 214, 217, 2, 646, 1612]
+[:mouse_move, 214, 215, 2, 647, 1613]
+[:mouse_move, 214, 214, 2, 648, 1614]
+[:mouse_move, 214, 213, 2, 649, 1617]
+[:mouse_move, 215, 212, 2, 650, 1619]
+[:mouse_move, 216, 212, 2, 651, 1620]
+[:mouse_move, 223, 214, 2, 652, 1621]
+[:mouse_move, 226, 216, 2, 653, 1622]
+[:mouse_move, 230, 218, 2, 654, 1623]
+[:mouse_move, 231, 218, 2, 655, 1624]
+[:mouse_move, 232, 218, 2, 656, 1625]
+[:mouse_move, 232, 219, 2, 657, 1628]
+[:mouse_move, 233, 220, 2, 658, 1633]
+[:mouse_move, 237, 223, 2, 659, 1634]
+[:mouse_move, 238, 224, 2, 660, 1635]
+[:mouse_move, 241, 226, 2, 661, 1636]
+[:mouse_move, 242, 227, 2, 662, 1637]
+[:mouse_move, 243, 227, 2, 663, 1640]
+[:mouse_move, 244, 227, 2, 664, 1642]
+[:mouse_move, 245, 227, 2, 665, 1644]
+[:mouse_move, 246, 227, 2, 666, 1651]
+[:mouse_move, 247, 227, 2, 667, 1654]
+[:mouse_move, 248, 228, 2, 668, 1656]
+[:mouse_button_pressed, 1, 0, 1, 669, 1675]
+[:mouse_button_up, 1, 0, 1, 670, 1679]
+[:mouse_move, 250, 235, 2, 671, 1698]
+[:mouse_move, 254, 245, 2, 672, 1699]
+[:mouse_move, 265, 275, 2, 673, 1700]
+[:mouse_move, 274, 296, 2, 674, 1701]
+[:mouse_move, 301, 366, 2, 675, 1702]
+[:mouse_move, 322, 417, 2, 676, 1703]
+[:mouse_move, 346, 474, 2, 677, 1704]
+[:mouse_move, 386, 571, 2, 678, 1705]
+[:mouse_move, 409, 614, 2, 679, 1706]
+[:mouse_move, 417, 626, 2, 680, 1707]
+[:mouse_move, 425, 638, 2, 681, 1708]
+[:mouse_move, 435, 657, 2, 682, 1710]
+[:mouse_move, 437, 662, 2, 683, 1710]
+[:mouse_move, 438, 664, 2, 684, 1711]
+[:mouse_move, 438, 665, 2, 685, 1712]
+[:mouse_move, 438, 666, 2, 686, 1714]
+[:mouse_move, 434, 672, 2, 687, 1715]
+[:mouse_move, 430, 675, 2, 688, 1716]
+[:mouse_move, 429, 678, 2, 689, 1717]
+[:mouse_move, 429, 679, 2, 690, 1721]
+[:mouse_move, 428, 683, 2, 691, 1722]
+[:mouse_move, 424, 694, 2, 692, 1723]
+[:mouse_move, 423, 697, 2, 693, 1724]
+[:mouse_move, 423, 698, 2, 694, 1725]
+[:mouse_move, 424, 698, 2, 695, 1727]
+[:mouse_move, 424, 697, 2, 696, 1728]
+[:mouse_move, 430, 686, 2, 697, 1729]
+[:mouse_move, 430, 679, 2, 698, 1730]
+[:mouse_move, 434, 669, 2, 699, 1731]
+[:mouse_move, 435, 667, 2, 700, 1732]
+[:mouse_move, 435, 664, 2, 701, 1733]
+[:mouse_move, 435, 663, 2, 702, 1734]
+[:mouse_move, 435, 662, 2, 703, 1735]
+[:mouse_move, 435, 661, 2, 704, 1736]
+[:mouse_move, 435, 660, 2, 705, 1738]
+[:mouse_move, 436, 659, 2, 706, 1739]
+[:mouse_move, 436, 658, 2, 707, 1740]
+[:mouse_move, 437, 655, 2, 708, 1741]
+[:mouse_move, 440, 649, 2, 709, 1742]
+[:mouse_move, 440, 648, 2, 710, 1744]
+[:mouse_move, 440, 647, 2, 711, 1744]
+[:mouse_move, 458, 647, 2, 712, 1761]
+[:mouse_move, 473, 647, 2, 713, 1762]
+[:mouse_move, 503, 646, 2, 714, 1763]
+[:mouse_move, 511, 644, 2, 715, 1764]
+[:mouse_move, 512, 644, 2, 716, 1765]
+[:mouse_move, 515, 644, 2, 717, 1770]
+[:mouse_move, 533, 641, 2, 718, 1771]
+[:mouse_move, 546, 641, 2, 719, 1772]
+[:mouse_move, 580, 640, 2, 720, 1773]
+[:mouse_move, 600, 640, 2, 721, 1774]
+[:mouse_move, 643, 639, 2, 722, 1775]
+[:mouse_move, 661, 639, 2, 723, 1776]
+[:mouse_move, 682, 639, 2, 724, 1777]
+[:mouse_move, 690, 639, 2, 725, 1778]
+[:mouse_move, 693, 639, 2, 726, 1779]
+[:mouse_move, 696, 639, 2, 727, 1783]
+[:mouse_move, 697, 639, 2, 728, 1784]
+[:mouse_move, 698, 639, 2, 729, 1785]
+[:mouse_move, 699, 639, 2, 730, 1786]
+[:mouse_move, 702, 641, 2, 731, 1787]
+[:mouse_move, 704, 643, 2, 732, 1788]
+[:mouse_move, 709, 645, 2, 733, 1789]
+[:mouse_move, 712, 645, 2, 734, 1790]
+[:mouse_move, 715, 645, 2, 735, 1791]
+[:mouse_move, 717, 645, 2, 736, 1792]
+[:mouse_move, 721, 645, 2, 737, 1793]
+[:mouse_move, 723, 645, 2, 738, 1794]
+[:mouse_move, 724, 645, 2, 739, 1795]
+[:mouse_move, 730, 645, 2, 740, 1796]
+[:mouse_move, 733, 645, 2, 741, 1797]
+[:mouse_move, 734, 645, 2, 742, 1798]
+[:mouse_button_pressed, 1, 0, 1, 743, 1800]
+[:mouse_move, 735, 645, 2, 744, 1801]
+[:mouse_button_up, 1, 0, 1, 745, 1804]
+[:mouse_move, 735, 644, 2, 746, 1810]
+[:mouse_move, 734, 644, 2, 747, 1818]
+[:mouse_move, 728, 642, 2, 748, 1820]
+[:mouse_move, 719, 637, 2, 749, 1821]
+[:mouse_move, 708, 632, 2, 750, 1822]
+[:mouse_move, 665, 611, 2, 751, 1823]
+[:mouse_move, 623, 591, 2, 752, 1824]
+[:mouse_move, 509, 533, 2, 753, 1825]
+[:mouse_move, 473, 514, 2, 754, 1826]
+[:mouse_move, 453, 502, 2, 755, 1827]
+[:mouse_move, 451, 500, 2, 756, 1829]
+[:mouse_move, 448, 495, 2, 757, 1829]
+[:mouse_move, 440, 482, 2, 758, 1831]
+[:mouse_move, 439, 480, 2, 759, 1832]
+[:mouse_move, 434, 474, 2, 760, 1833]
+[:mouse_move, 430, 469, 2, 761, 1834]
+[:mouse_move, 417, 459, 2, 762, 1835]
+[:mouse_move, 411, 456, 2, 763, 1836]
+[:mouse_move, 399, 452, 2, 764, 1837]
+[:mouse_move, 390, 449, 2, 765, 1838]
+[:mouse_move, 369, 442, 2, 766, 1839]
+[:mouse_move, 362, 440, 2, 767, 1840]
+[:mouse_move, 357, 439, 2, 768, 1841]
+[:mouse_move, 360, 440, 2, 769, 1848]
+[:mouse_move, 362, 441, 2, 770, 1849]
+[:mouse_move, 364, 442, 2, 771, 1850]
+[:mouse_move, 365, 442, 2, 772, 1854]
+[:mouse_move, 365, 443, 2, 773, 1856]
+[:mouse_move, 367, 443, 2, 774, 1856]
+[:mouse_move, 368, 443, 2, 775, 1858]
+[:mouse_move, 370, 443, 2, 776, 1859]
+[:mouse_move, 375, 445, 2, 777, 1860]
+[:mouse_move, 378, 445, 2, 778, 1861]
+[:mouse_move, 381, 445, 2, 779, 1862]
+[:mouse_move, 382, 445, 2, 780, 1863]
+[:mouse_move, 383, 445, 2, 781, 1865]
+[:mouse_move, 383, 444, 2, 782, 1927]
+[:mouse_button_pressed, 1, 0, 1, 783, 1936]
+[:mouse_move, 377, 443, 2, 784, 1937]
+[:mouse_move, 370, 443, 2, 785, 1939]
+[:mouse_move, 347, 443, 2, 786, 1940]
+[:mouse_move, 331, 444, 2, 787, 1941]
+[:mouse_move, 301, 448, 2, 788, 1942]
+[:mouse_move, 281, 452, 2, 789, 1943]
+[:mouse_move, 239, 461, 2, 790, 1944]
+[:mouse_move, 219, 467, 2, 791, 1945]
+[:mouse_move, 188, 476, 2, 792, 1946]
+[:mouse_move, 179, 482, 2, 793, 1947]
+[:mouse_move, 168, 491, 2, 794, 1948]
+[:mouse_move, 164, 495, 2, 795, 1949]
+[:mouse_move, 160, 499, 2, 796, 1950]
+[:mouse_move, 160, 500, 2, 797, 1951]
+[:mouse_move, 162, 498, 2, 798, 1961]
+[:mouse_move, 165, 496, 2, 799, 1962]
+[:mouse_move, 183, 486, 2, 800, 1963]
+[:mouse_move, 200, 476, 2, 801, 1964]
+[:mouse_move, 281, 430, 2, 802, 1965]
+[:mouse_move, 344, 398, 2, 803, 1966]
+[:mouse_move, 506, 339, 2, 804, 1967]
+[:mouse_move, 596, 318, 2, 805, 1968]
+[:mouse_move, 743, 293, 2, 806, 1969]
+[:mouse_move, 795, 284, 2, 807, 1970]
+[:mouse_move, 874, 275, 2, 808, 1971]
+[:mouse_move, 900, 274, 2, 809, 1972]
+[:mouse_move, 942, 275, 2, 810, 1973]
+[:mouse_move, 959, 278, 2, 811, 1974]
+[:mouse_move, 994, 284, 2, 812, 1975]
+[:mouse_move, 1008, 288, 2, 813, 1976]
+[:mouse_move, 1031, 295, 2, 814, 1976]
+[:mouse_move, 1044, 299, 2, 815, 1978]
+[:mouse_move, 1068, 310, 2, 816, 1979]
+[:mouse_move, 1080, 314, 2, 817, 1980]
+[:mouse_move, 1103, 325, 2, 818, 1981]
+[:mouse_move, 1110, 328, 2, 819, 1982]
+[:mouse_move, 1121, 334, 2, 820, 1983]
+[:mouse_move, 1123, 336, 2, 821, 1984]
+[:mouse_move, 1126, 338, 2, 822, 1985]
+[:mouse_move, 1127, 338, 2, 823, 1986]
+[:mouse_move, 1126, 338, 2, 824, 1995]
+[:mouse_move, 1112, 335, 2, 825, 1996]
+[:mouse_move, 1097, 332, 2, 826, 1997]
+[:mouse_move, 1053, 323, 2, 827, 1998]
+[:mouse_move, 1020, 317, 2, 828, 1999]
+[:mouse_move, 948, 304, 2, 829, 2000]
+[:mouse_move, 915, 298, 2, 830, 2001]
+[:mouse_move, 832, 290, 2, 831, 2002]
+[:mouse_move, 788, 288, 2, 832, 2003]
+[:mouse_move, 722, 287, 2, 833, 2004]
+[:mouse_move, 691, 291, 2, 834, 2005]
+[:mouse_move, 628, 305, 2, 835, 2006]
+[:mouse_move, 601, 315, 2, 836, 2007]
+[:mouse_move, 557, 333, 2, 837, 2008]
+[:mouse_move, 538, 343, 2, 838, 2009]
+[:mouse_move, 502, 361, 2, 839, 2010]
+[:mouse_move, 486, 372, 2, 840, 2011]
+[:mouse_move, 463, 390, 2, 841, 2012]
+[:mouse_move, 458, 394, 2, 842, 2013]
+[:mouse_move, 458, 396, 2, 843, 2016]
+[:mouse_move, 457, 397, 2, 844, 2017]
+[:mouse_move, 457, 398, 2, 845, 2018]
+[:mouse_move, 457, 399, 2, 846, 2019]
+[:mouse_move, 456, 400, 2, 847, 2020]
+[:mouse_move, 454, 405, 2, 848, 2021]
+[:mouse_move, 454, 406, 2, 849, 2022]
+[:mouse_move, 453, 408, 2, 850, 2029]
+[:mouse_move, 453, 409, 2, 851, 2030]
+[:mouse_move, 450, 413, 2, 852, 2031]
+[:mouse_move, 449, 416, 2, 853, 2032]
+[:mouse_move, 448, 418, 2, 854, 2033]
+[:mouse_button_up, 1, 0, 1, 855, 2054]
+[:mouse_move, 449, 416, 2, 856, 2073]
+[:mouse_move, 450, 415, 2, 857, 2074]
+[:mouse_move, 450, 414, 2, 858, 2075]
+[:mouse_move, 449, 412, 2, 859, 2076]
+[:mouse_move, 436, 402, 2, 860, 2077]
+[:mouse_move, 419, 393, 2, 861, 2078]
+[:mouse_move, 337, 363, 2, 862, 2079]
+[:mouse_move, 279, 346, 2, 863, 2080]
+[:mouse_move, 192, 321, 2, 864, 2081]
+[:mouse_move, 175, 315, 2, 865, 2082]
+[:mouse_move, 162, 308, 2, 866, 2083]
+[:mouse_move, 161, 307, 2, 867, 2084]
+[:mouse_move, 157, 306, 2, 868, 2085]
+[:mouse_move, 156, 306, 2, 869, 2086]
+[:mouse_move, 154, 306, 2, 870, 2087]
+[:mouse_move, 154, 305, 2, 871, 2088]
+[:mouse_move, 153, 304, 2, 872, 2090]
+[:mouse_move, 150, 301, 2, 873, 2091]
+[:mouse_move, 148, 300, 2, 874, 2092]
+[:mouse_move, 142, 294, 2, 875, 2093]
+[:mouse_move, 136, 289, 2, 876, 2094]
+[:mouse_move, 125, 277, 2, 877, 2095]
+[:mouse_move, 122, 274, 2, 878, 2096]
+[:mouse_move, 122, 273, 2, 879, 2097]
+[:mouse_move, 122, 272, 2, 880, 2098]
+[:mouse_move, 128, 273, 2, 881, 2104]
+[:mouse_move, 137, 274, 2, 882, 2105]
+[:mouse_move, 166, 275, 2, 883, 2106]
+[:mouse_move, 199, 276, 2, 884, 2107]
+[:mouse_move, 320, 286, 2, 885, 2108]
+[:mouse_move, 394, 295, 2, 886, 2109]
+[:mouse_move, 533, 320, 2, 887, 2110]
+[:mouse_move, 591, 335, 2, 888, 2111]
+[:mouse_move, 645, 351, 2, 889, 2112]
+[:mouse_move, 654, 354, 2, 890, 2113]
+[:mouse_move, 667, 360, 2, 891, 2114]
+[:mouse_move, 675, 365, 2, 892, 2115]
+[:mouse_move, 690, 378, 2, 893, 2116]
+[:mouse_move, 695, 383, 2, 894, 2117]
+[:mouse_move, 699, 389, 2, 895, 2118]
+[:mouse_move, 699, 390, 2, 896, 2119]
+[:mouse_move, 700, 390, 2, 897, 2120]
+[:mouse_move, 692, 387, 2, 898, 2124]
+[:mouse_move, 681, 384, 2, 899, 2125]
+[:mouse_move, 656, 381, 2, 900, 2126]
+[:mouse_move, 650, 381, 2, 901, 2127]
+[:mouse_move, 647, 381, 2, 902, 2128]
+[:mouse_move, 649, 381, 2, 903, 2137]
+[:mouse_move, 650, 382, 2, 904, 2138]
+[:mouse_move, 651, 382, 2, 905, 2139]
+[:mouse_button_pressed, 1, 0, 1, 906, 2144]
+[:mouse_button_up, 1, 0, 1, 907, 2148]
+[:mouse_move, 650, 382, 2, 908, 2165]
+[:mouse_move, 647, 383, 2, 909, 2166]
+[:mouse_move, 643, 384, 2, 910, 2167]
+[:mouse_move, 629, 387, 2, 911, 2168]
+[:mouse_move, 617, 390, 2, 912, 2169]
+[:mouse_move, 587, 395, 2, 913, 2170]
+[:mouse_move, 573, 397, 2, 914, 2171]
+[:mouse_move, 541, 399, 2, 915, 2172]
+[:mouse_move, 524, 401, 2, 916, 2173]
+[:mouse_move, 488, 405, 2, 917, 2174]
+[:mouse_move, 476, 407, 2, 918, 2175]
+[:mouse_move, 465, 409, 2, 919, 2176]
+[:mouse_move, 464, 409, 2, 920, 2177]
+[:mouse_move, 462, 410, 2, 921, 2178]
+[:mouse_move, 461, 410, 2, 922, 2179]
+[:mouse_move, 459, 411, 2, 923, 2180]
+[:mouse_move, 459, 412, 2, 924, 2186]
+[:mouse_move, 459, 413, 2, 925, 2189]
+[:mouse_move, 458, 413, 2, 926, 2190]
+[:mouse_move, 451, 419, 2, 927, 2191]
+[:mouse_move, 449, 421, 2, 928, 2192]
+[:mouse_move, 448, 421, 2, 929, 2193]
+[:mouse_move, 447, 421, 2, 930, 2194]
+[:mouse_move, 445, 422, 2, 931, 2195]
+[:mouse_move, 444, 422, 2, 932, 2196]
+[:mouse_button_pressed, 1, 0, 1, 933, 2216]
+[:mouse_button_up, 1, 0, 1, 934, 2220]
+[:mouse_move, 442, 420, 2, 935, 2229]
+[:mouse_move, 424, 411, 2, 936, 2230]
+[:mouse_move, 406, 403, 2, 937, 2231]
+[:mouse_move, 336, 378, 2, 938, 2232]
+[:mouse_move, 286, 359, 2, 939, 2233]
+[:mouse_move, 225, 334, 2, 940, 2234]
+[:mouse_move, 213, 328, 2, 941, 2235]
+[:mouse_move, 201, 321, 2, 942, 2236]
+[:mouse_move, 198, 318, 2, 943, 2237]
+[:mouse_move, 191, 314, 2, 944, 2238]
+[:mouse_move, 185, 310, 2, 945, 2239]
+[:mouse_move, 179, 305, 2, 946, 2240]
+[:mouse_move, 171, 299, 2, 947, 2241]
+[:mouse_move, 170, 297, 2, 948, 2242]
+[:mouse_move, 170, 295, 2, 949, 2243]
+[:mouse_move, 170, 294, 2, 950, 2244]
+[:mouse_move, 169, 293, 2, 951, 2245]
+[:mouse_move, 169, 291, 2, 952, 2246]
+[:mouse_move, 168, 289, 2, 953, 2247]
+[:mouse_move, 167, 289, 2, 954, 2248]
+[:mouse_move, 167, 287, 2, 955, 2249]
+[:mouse_move, 167, 286, 2, 956, 2250]
+[:mouse_move, 164, 283, 2, 957, 2251]
+[:mouse_move, 160, 279, 2, 958, 2252]
+[:mouse_move, 143, 270, 2, 959, 2253]
+[:mouse_move, 136, 267, 2, 960, 2254]
+[:mouse_move, 130, 265, 2, 961, 2255]
+[:mouse_move, 128, 265, 2, 962, 2256]
+[:mouse_move, 125, 264, 2, 963, 2257]
+[:mouse_move, 123, 263, 2, 964, 2258]
+[:mouse_move, 120, 262, 2, 965, 2259]
+[:mouse_move, 120, 261, 2, 966, 2260]
+[:mouse_move, 120, 260, 2, 967, 2265]
+[:mouse_move, 120, 259, 2, 968, 2267]
+[:mouse_move, 121, 259, 2, 969, 2268]
+[:mouse_move, 122, 259, 2, 970, 2269]
+[:mouse_move, 124, 258, 2, 971, 2270]
+[:mouse_move, 126, 257, 2, 972, 2271]
+[:mouse_move, 130, 256, 2, 973, 2272]
+[:mouse_move, 131, 256, 2, 974, 2274]
+[:mouse_move, 132, 256, 2, 975, 2275]
+[:mouse_button_pressed, 1, 0, 1, 976, 2290]
+[:mouse_button_up, 1, 0, 1, 977, 2292]
+[:mouse_move, 132, 258, 2, 978, 2305]
+[:mouse_move, 133, 262, 2, 979, 2306]
+[:mouse_move, 135, 278, 2, 980, 2307]
+[:mouse_move, 136, 290, 2, 981, 2308]
+[:mouse_move, 143, 325, 2, 982, 2309]
+[:mouse_move, 146, 347, 2, 983, 2310]
+[:mouse_move, 162, 411, 2, 984, 2311]
+[:mouse_move, 173, 445, 2, 985, 2312]
+[:mouse_move, 189, 482, 2, 986, 2313]
+[:mouse_move, 195, 490, 2, 987, 2314]
+[:mouse_move, 198, 492, 2, 988, 2315]
+[:key_down_raw, 96, 0, 2, 989, 2426]
+[:key_up_raw, 96, 0, 2, 990, 2430]
+[:key_down_raw, 13, 0, 2, 991, 2551]
diff --git a/samples/07_advanced_audio/01_audio_mixer/sounds/drum.mp3 b/samples/07_advanced_audio/01_audio_mixer/sounds/drum.mp3
new file mode 100644
index 0000000..e41e671
--- /dev/null
+++ b/samples/07_advanced_audio/01_audio_mixer/sounds/drum.mp3
Binary files differ
diff --git a/samples/01_rendering_basics/06_audio_mixer/sounds/3.wav b/samples/07_advanced_audio/01_audio_mixer/sounds/drum.wav
index c7bde27..c7bde27 100644
--- a/samples/01_rendering_basics/06_audio_mixer/sounds/3.wav
+++ b/samples/07_advanced_audio/01_audio_mixer/sounds/drum.wav
Binary files differ
diff --git a/samples/01_rendering_basics/06_audio_mixer/sounds/6.ogg b/samples/07_advanced_audio/01_audio_mixer/sounds/music.ogg
index a952191..a952191 100644
--- a/samples/01_rendering_basics/06_audio_mixer/sounds/6.ogg
+++ b/samples/07_advanced_audio/01_audio_mixer/sounds/music.ogg
Binary files differ
diff --git a/samples/01_rendering_basics/06_audio_mixer/sounds/2.wav b/samples/07_advanced_audio/01_audio_mixer/sounds/splash.wav
index 52a09c2..52a09c2 100644
--- a/samples/01_rendering_basics/06_audio_mixer/sounds/2.wav
+++ b/samples/07_advanced_audio/01_audio_mixer/sounds/splash.wav
Binary files differ
diff --git a/samples/01_rendering_basics/06_audio_mixer/sounds/5.wav b/samples/07_advanced_audio/01_audio_mixer/sounds/spring.wav
index 112f3cc..112f3cc 100644
--- a/samples/01_rendering_basics/06_audio_mixer/sounds/5.wav
+++ b/samples/07_advanced_audio/01_audio_mixer/sounds/spring.wav
Binary files differ
diff --git a/samples/01_rendering_basics/06_audio_mixer/sounds/1.wav b/samples/07_advanced_audio/01_audio_mixer/sounds/tada.wav
index 8aa1be3..8aa1be3 100644
--- a/samples/01_rendering_basics/06_audio_mixer/sounds/1.wav
+++ b/samples/07_advanced_audio/01_audio_mixer/sounds/tada.wav
Binary files differ
diff --git a/samples/01_rendering_basics/06_audio_mixer/sounds/4.wav b/samples/07_advanced_audio/01_audio_mixer/sounds/tink.wav
index 193cf54..193cf54 100644
--- a/samples/01_rendering_basics/06_audio_mixer/sounds/4.wav
+++ b/samples/07_advanced_audio/01_audio_mixer/sounds/tink.wav
Binary files differ
diff --git a/samples/01_rendering_basics/07_sound_synthesis/app/main.rb b/samples/07_advanced_audio/02_sound_synthesis/app/main.rb
index 391ce68..af2be9d 100644
--- a/samples/01_rendering_basics/07_sound_synthesis/app/main.rb
+++ b/samples/07_advanced_audio/02_sound_synthesis/app/main.rb
@@ -35,14 +35,14 @@ begin # region: top level tick methods
def input args
args.state.buttons.each do |b|
- if args.inputs.mouse.click.inside_rect? b[:rect]
+ if args.inputs.mouse.click && (args.inputs.mouse.click.inside_rect? b[:rect])
parameter_string = (b.slice :frequency, :note, :octave).map { |k, v| "#{k}: #{v}" }.join ", "
args.gtk.notify! "#{b[:method_to_call]} #{parameter_string}"
send b[:method_to_call], args, b
end
end
- if args.inputs.mouse.click.inside_rect? (args.layout.rect(row: 0).yield_self { |r| r.merge y: r.y + r.h.half, h: r.h.half })
+ if args.inputs.mouse.click && (args.inputs.mouse.click.inside_rect? (args.layout.rect(row: 0).yield_self { |r| r.merge y: r.y + r.h.half, h: r.h.half }))
args.gtk.openurl 'https://www.youtube.com/watch?v=zEzovM5jT-k&ab_channel=AmirRajan'
end
end
diff --git a/samples/07_advanced_rendering/02_render_targets_with_alphas/license-for-sample.txt b/samples/07_advanced_audio/02_sound_synthesis/license-for-sample.txt
index 100dcec..100dcec 100644
--- a/samples/07_advanced_rendering/02_render_targets_with_alphas/license-for-sample.txt
+++ b/samples/07_advanced_audio/02_sound_synthesis/license-for-sample.txt
diff --git a/samples/07_advanced_audio/02_sound_synthesis/metadata/game_metadata.txt b/samples/07_advanced_audio/02_sound_synthesis/metadata/game_metadata.txt
new file mode 100644
index 0000000..16cef1d
--- /dev/null
+++ b/samples/07_advanced_audio/02_sound_synthesis/metadata/game_metadata.txt
@@ -0,0 +1,6 @@
+devid=amirrajan
+devtitle=Amir Rajan
+gameid=hello-world
+gametitle=Hello World
+version=1.0
+icon=metadata/icon.png
diff --git a/samples/07_advanced_audio/02_sound_synthesis/metadata/icon.png b/samples/07_advanced_audio/02_sound_synthesis/metadata/icon.png
new file mode 100644
index 0000000..e20e8c2
--- /dev/null
+++ b/samples/07_advanced_audio/02_sound_synthesis/metadata/icon.png
Binary files differ
diff --git a/samples/07_advanced_audio/02_sound_synthesis/replay.txt b/samples/07_advanced_audio/02_sound_synthesis/replay.txt
new file mode 100644
index 0000000..0d7c6d5
--- /dev/null
+++ b/samples/07_advanced_audio/02_sound_synthesis/replay.txt
@@ -0,0 +1,237 @@
+replay_version 2.0
+stopped_at 425
+seed 100
+recorded_at Sat Jul 17 09:17:17 2021
+[:mouse_button_up, 1, 0, 1, 1, 4]
+[:mouse_move, 790, 90, 2, 2, 31]
+[:mouse_move, 781, 91, 2, 3, 32]
+[:mouse_move, 753, 101, 2, 4, 33]
+[:mouse_move, 737, 106, 2, 5, 34]
+[:mouse_move, 716, 109, 2, 6, 35]
+[:mouse_move, 633, 122, 2, 7, 36]
+[:mouse_move, 583, 132, 2, 8, 37]
+[:mouse_move, 489, 167, 2, 9, 38]
+[:mouse_move, 443, 189, 2, 10, 39]
+[:mouse_move, 356, 237, 2, 11, 40]
+[:mouse_move, 330, 255, 2, 12, 41]
+[:mouse_move, 307, 276, 2, 13, 42]
+[:mouse_move, 300, 282, 2, 14, 43]
+[:mouse_move, 285, 293, 2, 15, 43]
+[:mouse_move, 271, 298, 2, 16, 44]
+[:mouse_move, 222, 308, 2, 17, 45]
+[:mouse_move, 178, 314, 2, 18, 46]
+[:mouse_move, 104, 327, 2, 19, 47]
+[:mouse_move, 82, 331, 2, 20, 48]
+[:mouse_move, 55, 332, 2, 21, 49]
+[:mouse_move, 47, 330, 2, 22, 50]
+[:mouse_move, 41, 325, 2, 23, 51]
+[:mouse_move, 38, 322, 2, 24, 52]
+[:mouse_move, 35, 315, 2, 25, 53]
+[:mouse_move, 33, 312, 2, 26, 54]
+[:mouse_move, 35, 299, 2, 27, 55]
+[:mouse_move, 37, 290, 2, 28, 56]
+[:mouse_move, 43, 277, 2, 29, 57]
+[:mouse_move, 47, 271, 2, 30, 58]
+[:mouse_move, 54, 262, 2, 31, 59]
+[:mouse_move, 61, 256, 2, 32, 60]
+[:mouse_move, 71, 247, 2, 33, 61]
+[:mouse_move, 90, 231, 2, 34, 62]
+[:mouse_move, 103, 223, 2, 35, 63]
+[:mouse_move, 128, 209, 2, 36, 64]
+[:mouse_move, 138, 205, 2, 37, 65]
+[:mouse_move, 157, 194, 2, 38, 66]
+[:mouse_move, 168, 186, 2, 39, 67]
+[:mouse_move, 187, 169, 2, 40, 68]
+[:mouse_move, 193, 163, 2, 41, 69]
+[:mouse_move, 197, 157, 2, 42, 70]
+[:mouse_move, 199, 154, 2, 43, 71]
+[:mouse_move, 202, 148, 2, 44, 72]
+[:mouse_move, 204, 143, 2, 45, 73]
+[:mouse_move, 206, 139, 2, 46, 74]
+[:mouse_move, 204, 142, 2, 47, 82]
+[:mouse_move, 203, 145, 2, 48, 83]
+[:mouse_move, 194, 152, 2, 49, 84]
+[:mouse_move, 189, 157, 2, 50, 85]
+[:mouse_move, 169, 172, 2, 51, 86]
+[:mouse_move, 155, 185, 2, 52, 87]
+[:mouse_move, 128, 217, 2, 53, 88]
+[:mouse_move, 119, 232, 2, 54, 89]
+[:mouse_move, 112, 243, 2, 55, 90]
+[:mouse_move, 106, 255, 2, 56, 91]
+[:mouse_move, 104, 258, 2, 57, 92]
+[:mouse_move, 102, 262, 2, 58, 93]
+[:mouse_move, 101, 265, 2, 59, 94]
+[:mouse_move, 96, 272, 2, 60, 95]
+[:mouse_move, 95, 273, 2, 61, 96]
+[:mouse_move, 93, 274, 2, 62, 100]
+[:mouse_move, 85, 277, 2, 63, 101]
+[:mouse_move, 84, 277, 2, 64, 102]
+[:mouse_move, 83, 277, 2, 65, 103]
+[:mouse_button_pressed, 1, 0, 1, 66, 106]
+[:mouse_button_up, 1, 0, 1, 67, 112]
+[:mouse_move, 83, 278, 2, 68, 113]
+[:mouse_move, 84, 285, 2, 69, 114]
+[:mouse_move, 82, 292, 2, 70, 116]
+[:mouse_move, 78, 309, 2, 71, 117]
+[:mouse_move, 76, 318, 2, 72, 118]
+[:mouse_move, 76, 326, 2, 73, 119]
+[:mouse_move, 76, 333, 2, 74, 120]
+[:mouse_move, 75, 336, 2, 75, 122]
+[:mouse_move, 73, 344, 2, 76, 123]
+[:mouse_move, 71, 347, 2, 77, 124]
+[:mouse_move, 70, 349, 2, 78, 125]
+[:mouse_button_pressed, 1, 0, 1, 79, 131]
+[:mouse_button_up, 1, 0, 1, 80, 136]
+[:mouse_move, 70, 350, 2, 81, 142]
+[:mouse_move, 70, 353, 2, 82, 143]
+[:mouse_move, 68, 362, 2, 83, 144]
+[:mouse_move, 68, 367, 2, 84, 145]
+[:mouse_move, 67, 370, 2, 85, 146]
+[:mouse_move, 66, 376, 2, 86, 147]
+[:mouse_move, 66, 379, 2, 87, 148]
+[:mouse_move, 65, 385, 2, 88, 149]
+[:mouse_move, 65, 387, 2, 89, 150]
+[:mouse_move, 66, 387, 2, 90, 151]
+[:mouse_button_pressed, 1, 0, 1, 91, 155]
+[:mouse_button_up, 1, 0, 1, 92, 160]
+[:mouse_move, 68, 386, 2, 93, 160]
+[:mouse_move, 84, 365, 2, 94, 161]
+[:mouse_move, 99, 342, 2, 95, 162]
+[:mouse_move, 142, 284, 2, 96, 163]
+[:mouse_move, 159, 260, 2, 97, 164]
+[:mouse_move, 181, 220, 2, 98, 165]
+[:mouse_move, 189, 189, 2, 99, 167]
+[:mouse_move, 190, 177, 2, 100, 168]
+[:mouse_move, 190, 167, 2, 101, 169]
+[:mouse_move, 192, 149, 2, 102, 170]
+[:mouse_move, 192, 147, 2, 103, 171]
+[:mouse_move, 190, 152, 2, 104, 178]
+[:mouse_move, 187, 157, 2, 105, 179]
+[:mouse_move, 184, 168, 2, 106, 180]
+[:mouse_move, 183, 171, 2, 107, 181]
+[:mouse_move, 183, 173, 2, 108, 182]
+[:mouse_move, 183, 172, 2, 109, 186]
+[:mouse_move, 184, 172, 2, 110, 187]
+[:mouse_move, 184, 171, 2, 111, 188]
+[:mouse_move, 185, 168, 2, 112, 189]
+[:mouse_move, 187, 163, 2, 113, 190]
+[:mouse_move, 188, 160, 2, 114, 191]
+[:mouse_move, 188, 159, 2, 115, 192]
+[:mouse_button_pressed, 1, 0, 1, 116, 193]
+[:mouse_button_up, 1, 0, 1, 117, 198]
+[:mouse_move, 189, 159, 2, 118, 198]
+[:mouse_move, 195, 163, 2, 119, 200]
+[:mouse_move, 202, 167, 2, 120, 201]
+[:mouse_move, 214, 173, 2, 121, 202]
+[:mouse_move, 240, 187, 2, 122, 203]
+[:mouse_move, 251, 194, 2, 123, 204]
+[:mouse_move, 269, 205, 2, 124, 205]
+[:mouse_move, 277, 210, 2, 125, 206]
+[:mouse_move, 290, 216, 2, 126, 207]
+[:mouse_move, 291, 217, 2, 127, 208]
+[:mouse_button_pressed, 1, 0, 1, 128, 217]
+[:mouse_button_up, 1, 0, 1, 129, 219]
+[:mouse_move, 292, 217, 2, 130, 220]
+[:mouse_move, 298, 222, 2, 131, 220]
+[:mouse_move, 306, 226, 2, 132, 221]
+[:mouse_move, 322, 234, 2, 133, 221]
+[:mouse_move, 330, 238, 2, 134, 221]
+[:mouse_move, 338, 241, 2, 135, 222]
+[:mouse_move, 351, 244, 2, 136, 222]
+[:mouse_move, 359, 246, 2, 137, 223]
+[:mouse_move, 374, 251, 2, 138, 223]
+[:mouse_move, 382, 253, 2, 139, 223]
+[:mouse_move, 392, 256, 2, 140, 224]
+[:mouse_move, 393, 256, 2, 141, 224]
+[:mouse_button_pressed, 1, 0, 1, 142, 227]
+[:mouse_button_up, 1, 0, 1, 143, 232]
+[:mouse_move, 402, 262, 2, 144, 235]
+[:mouse_move, 410, 268, 2, 145, 236]
+[:mouse_move, 431, 279, 2, 146, 237]
+[:mouse_move, 440, 283, 2, 147, 238]
+[:mouse_move, 448, 287, 2, 148, 239]
+[:mouse_move, 458, 292, 2, 149, 240]
+[:mouse_move, 463, 295, 2, 150, 242]
+[:mouse_move, 471, 299, 2, 151, 243]
+[:mouse_move, 474, 301, 2, 152, 244]
+[:mouse_move, 478, 302, 2, 153, 245]
+[:mouse_button_pressed, 1, 0, 1, 154, 253]
+[:mouse_button_up, 1, 0, 1, 155, 259]
+[:mouse_move, 479, 303, 2, 156, 259]
+[:mouse_move, 484, 307, 2, 157, 260]
+[:mouse_move, 504, 321, 2, 158, 261]
+[:mouse_move, 516, 329, 2, 159, 262]
+[:mouse_move, 538, 342, 2, 160, 263]
+[:mouse_move, 546, 345, 2, 161, 264]
+[:mouse_move, 555, 349, 2, 162, 265]
+[:mouse_move, 558, 350, 2, 163, 267]
+[:mouse_move, 560, 351, 2, 164, 268]
+[:mouse_move, 561, 351, 2, 165, 270]
+[:mouse_move, 562, 351, 2, 166, 271]
+[:mouse_move, 563, 351, 2, 167, 273]
+[:mouse_move, 564, 351, 2, 168, 274]
+[:mouse_move, 565, 352, 2, 169, 278]
+[:mouse_button_pressed, 1, 0, 1, 170, 281]
+[:mouse_button_up, 1, 0, 1, 171, 287]
+[:mouse_move, 563, 358, 2, 172, 287]
+[:mouse_move, 559, 363, 2, 173, 288]
+[:mouse_move, 553, 371, 2, 174, 289]
+[:mouse_move, 550, 375, 2, 175, 291]
+[:mouse_move, 543, 381, 2, 176, 292]
+[:mouse_move, 539, 384, 2, 177, 293]
+[:mouse_move, 529, 389, 2, 178, 294]
+[:mouse_move, 523, 393, 2, 179, 295]
+[:mouse_move, 503, 402, 2, 180, 296]
+[:mouse_move, 494, 405, 2, 181, 299]
+[:mouse_move, 493, 406, 2, 182, 301]
+[:mouse_move, 492, 406, 2, 183, 302]
+[:mouse_button_pressed, 1, 0, 1, 184, 307]
+[:mouse_button_up, 1, 0, 1, 185, 312]
+[:mouse_move, 483, 413, 2, 186, 314]
+[:mouse_move, 476, 417, 2, 187, 315]
+[:mouse_move, 460, 424, 2, 188, 316]
+[:mouse_move, 452, 427, 2, 189, 317]
+[:mouse_move, 433, 433, 2, 190, 318]
+[:mouse_move, 423, 436, 2, 191, 320]
+[:mouse_move, 404, 443, 2, 192, 321]
+[:mouse_move, 396, 448, 2, 193, 322]
+[:mouse_move, 386, 453, 2, 194, 323]
+[:mouse_move, 383, 454, 2, 195, 324]
+[:mouse_move, 374, 456, 2, 196, 325]
+[:mouse_move, 369, 457, 2, 197, 327]
+[:mouse_move, 365, 458, 2, 198, 328]
+[:mouse_button_pressed, 1, 0, 1, 199, 334]
+[:mouse_button_up, 1, 0, 1, 200, 341]
+[:mouse_move, 364, 460, 2, 201, 343]
+[:mouse_move, 364, 461, 2, 202, 344]
+[:mouse_move, 359, 465, 2, 203, 345]
+[:mouse_move, 352, 467, 2, 204, 346]
+[:mouse_move, 341, 471, 2, 205, 347]
+[:mouse_move, 336, 473, 2, 206, 348]
+[:mouse_move, 324, 478, 2, 207, 349]
+[:mouse_move, 316, 482, 2, 208, 351]
+[:mouse_move, 297, 491, 2, 209, 352]
+[:mouse_move, 288, 494, 2, 210, 353]
+[:mouse_move, 278, 498, 2, 211, 354]
+[:mouse_move, 274, 499, 2, 212, 355]
+[:mouse_move, 270, 502, 2, 213, 356]
+[:mouse_move, 269, 502, 2, 214, 357]
+[:mouse_move, 269, 503, 2, 215, 358]
+[:mouse_move, 268, 503, 2, 216, 359]
+[:mouse_move, 266, 505, 2, 217, 360]
+[:mouse_move, 266, 506, 2, 218, 362]
+[:mouse_move, 265, 506, 2, 219, 364]
+[:mouse_move, 265, 507, 2, 220, 365]
+[:mouse_move, 265, 508, 2, 221, 367]
+[:mouse_button_pressed, 1, 0, 1, 222, 370]
+[:mouse_button_up, 1, 0, 1, 223, 372]
+[:mouse_move, 266, 508, 2, 224, 375]
+[:mouse_move, 267, 508, 2, 225, 382]
+[:mouse_move, 268, 508, 2, 226, 383]
+[:mouse_move, 270, 509, 2, 227, 383]
+[:mouse_move, 271, 509, 2, 228, 385]
+[:mouse_move, 272, 509, 2, 229, 385]
+[:key_down_raw, 96, 0, 2, 230, 386]
+[:mouse_move, 272, 508, 2, 231, 386]
+[:key_up_raw, 96, 0, 2, 232, 388]
+[:key_down_raw, 13, 0, 2, 233, 425]
diff --git a/samples/01_rendering_basics/07_sound_synthesis/sprites/square-white.png b/samples/07_advanced_audio/02_sound_synthesis/sprites/square-white.png
index 378c565..378c565 100644
--- a/samples/01_rendering_basics/07_sound_synthesis/sprites/square-white.png
+++ b/samples/07_advanced_audio/02_sound_synthesis/sprites/square-white.png
Binary files differ
diff --git a/samples/07_advanced_rendering/00_labels_with_wrapped_text/app/main.rb b/samples/07_advanced_rendering/00_labels_with_wrapped_text/app/main.rb
new file mode 100644
index 0000000..71eefa9
--- /dev/null
+++ b/samples/07_advanced_rendering/00_labels_with_wrapped_text/app/main.rb
@@ -0,0 +1,88 @@
+def tick args
+ # defaults
+ args.state.scroll_location ||= 0
+ args.state.textbox.messages ||= []
+ args.state.textbox.scroll ||= 0
+
+ # render
+ args.outputs.background_color = [0, 0, 0, 255]
+ render_messages args
+ render_instructions args
+
+ # inputs
+ if args.inputs.keyboard.key_down.one
+ queue_message args, "Hello there neighbour! my name is mark, how is your day today?"
+ end
+
+ if args.inputs.keyboard.key_down.two
+ queue_message args, "I'm doing great sir, actually I'm having a picnic today"
+ end
+
+ if args.inputs.keyboard.key_down.three
+ queue_message args, "Well that sounds wonderful!"
+ end
+
+ if args.inputs.keyboard.key_down.home
+ args.state.scroll_location = 1
+ end
+
+ if args.inputs.keyboard.key_down.delete
+ clear_message_queue args
+ end
+end
+
+def queue_message args, msg
+ args.state.textbox.messages.concat msg.wrapped_lines 50
+end
+
+def clear_message_queue args
+ args.state.textbox.messages = nil
+ args.state.textbox.scroll = 0
+end
+
+def render_messages args
+ args.outputs[:textbox].w = 400
+ args.outputs[:textbox].h = 720
+
+ args.outputs.primitives << args.state.textbox.messages.each_with_index.map do |s, idx|
+ {
+ x: 0,
+ y: 20 * (args.state.textbox.messages.size - idx) + args.state.textbox.scroll * 20,
+ text: s,
+ size_enum: -3,
+ alignment_enum: 0,
+ r: 255, g:255, b: 255, a: 255
+ }
+ end
+
+ args.outputs[:textbox].labels << args.state.textbox.messages.each_with_index.map do |s, idx|
+ {
+ x: 0,
+ y: 20 * (args.state.textbox.messages.size - idx) + args.state.textbox.scroll * 20,
+ text: s,
+ size_enum: -3,
+ alignment_enum: 0,
+ r: 255, g:255, b: 255, a: 255
+ }
+ end
+
+ args.outputs[:textbox].borders << [0, 0, args.outputs[:textbox].w, 720]
+
+ args.state.textbox.scroll += args.inputs.mouse.wheel.y unless args.inputs.mouse.wheel.nil?
+
+ if args.state.scroll_location > 0
+ args.state.textbox.scroll = 0
+ args.state.scroll_location = 0
+ end
+
+ args.outputs.sprites << [900, 0, args.outputs[:textbox].w, 720, :textbox]
+end
+
+def render_instructions args
+ args.outputs.labels << [30,
+ 30.from_top,
+ "press 1, 2, 3 to display messages, MOUSE WHEEL to scroll, HOME to go to top, BACKSPACE to delete.",
+ 0, 255, 255]
+
+ args.outputs.primitives << [0, 55.from_top, 1280, 30, :pixel, 0, 255, 0, 0, 0].sprite
+end
diff --git a/samples/07_advanced_rendering/00_labels_with_wrapped_text/replay.txt b/samples/07_advanced_rendering/00_labels_with_wrapped_text/replay.txt
new file mode 100644
index 0000000..8153881
--- /dev/null
+++ b/samples/07_advanced_rendering/00_labels_with_wrapped_text/replay.txt
@@ -0,0 +1,93 @@
+replay_version 2.0
+stopped_at 461
+seed 100
+recorded_at 2021-11-20 11:11:30 -0600
+[:mouse_button_up, 1, 0, 1, 1, 5]
+[:mouse_move, 789, 84, 2, 2, 33]
+[:mouse_move, 790, 84, 2, 3, 35]
+[:mouse_move, 791, 84, 2, 4, 37]
+[:key_down_raw, 49, 0, 2, 5, 72]
+[:key_up_raw, 49, 0, 2, 6, 78]
+[:key_down_raw, 50, 0, 2, 7, 90]
+[:key_up_raw, 50, 0, 2, 8, 97]
+[:mouse_move, 789, 85, 2, 9, 108]
+[:mouse_move, 784, 86, 2, 10, 109]
+[:mouse_move, 780, 88, 2, 11, 110]
+[:mouse_move, 780, 89, 2, 12, 112]
+[:mouse_move, 780, 90, 2, 13, 114]
+[:mouse_move, 780, 91, 2, 14, 115]
+[:key_down_raw, 49, 0, 2, 15, 123]
+[:key_up_raw, 49, 0, 2, 16, 131]
+[:key_down_raw, 49, 0, 2, 17, 150]
+[:key_up_raw, 49, 0, 2, 18, 157]
+[:key_down_raw, 50, 0, 2, 19, 161]
+[:key_up_raw, 50, 0, 2, 20, 169]
+[:key_down_raw, 51, 0, 2, 21, 179]
+[:key_up_raw, 51, 0, 2, 22, 186]
+[:mouse_move, 780, 92, 2, 23, 186]
+[:mouse_move, 781, 92, 2, 24, 187]
+[:mouse_move, 777, 92, 2, 25, 225]
+[:mouse_move, 769, 94, 2, 26, 226]
+[:mouse_move, 761, 96, 2, 27, 227]
+[:mouse_move, 759, 97, 2, 28, 228]
+[:mouse_move, 760, 99, 2, 29, 231]
+[:mouse_move, 762, 101, 2, 30, 232]
+[:mouse_move, 768, 112, 2, 31, 233]
+[:mouse_move, 769, 112, 2, 32, 234]
+[:mouse_wheel, 0, 1, 2, 33, 234]
+[:mouse_move, 769, 113, 2, 34, 234]
+[:mouse_wheel, 0, 2, 2, 35, 235]
+[:mouse_move, 770, 114, 2, 36, 235]
+[:mouse_wheel, 0, 4, 2, 37, 236]
+[:mouse_move, 771, 115, 2, 38, 237]
+[:mouse_wheel, 0, 6, 2, 39, 237]
+[:mouse_move, 771, 116, 2, 40, 239]
+[:mouse_wheel, 0, 7, 2, 41, 239]
+[:mouse_move, 772, 119, 2, 42, 240]
+[:mouse_move, 773, 120, 2, 43, 241]
+[:mouse_move, 773, 121, 2, 44, 242]
+[:mouse_move, 774, 121, 2, 45, 243]
+[:mouse_move, 774, 122, 2, 46, 244]
+[:mouse_move, 775, 124, 2, 47, 246]
+[:mouse_move, 780, 132, 2, 48, 247]
+[:mouse_move, 784, 142, 2, 49, 248]
+[:mouse_move, 788, 149, 2, 50, 249]
+[:mouse_move, 789, 150, 2, 51, 250]
+[:mouse_move, 789, 151, 2, 52, 251]
+[:mouse_move, 790, 151, 2, 53, 252]
+[:mouse_move, 790, 152, 2, 54, 262]
+[:mouse_wheel, 0, 1, 2, 55, 273]
+[:mouse_wheel, 0, 1, 2, 56, 274]
+[:mouse_wheel, 0, 4, 2, 57, 275]
+[:mouse_wheel, 0, 6, 2, 58, 277]
+[:mouse_move, 790, 151, 2, 59, 288]
+[:mouse_wheel, 0, -1, 2, 60, 297]
+[:mouse_wheel, 0, -1, 2, 61, 299]
+[:mouse_wheel, 0, -4, 2, 62, 300]
+[:mouse_wheel, 0, -6, 2, 63, 301]
+[:mouse_wheel, 0, -1, 2, 64, 317]
+[:mouse_wheel, 0, -1, 2, 65, 318]
+[:mouse_wheel, 0, -4, 2, 66, 319]
+[:mouse_wheel, 0, -6, 2, 67, 320]
+[:mouse_wheel, 0, -7, 2, 68, 321]
+[:mouse_move, 791, 151, 2, 69, 322]
+[:key_down_raw, 49, 0, 2, 70, 339]
+[:key_up_raw, 49, 0, 2, 71, 343]
+[:mouse_move, 791, 150, 2, 72, 343]
+[:key_down_raw, 49, 0, 2, 73, 348]
+[:key_up_raw, 49, 0, 2, 74, 351]
+[:key_down_raw, 49, 0, 2, 75, 356]
+[:key_up_raw, 49, 0, 2, 76, 361]
+[:key_down_raw, 96, 0, 2, 77, 388]
+[:mouse_move, 792, 150, 2, 78, 389]
+[:key_up_raw, 96, 0, 2, 79, 392]
+[:mouse_move, 792, 149, 2, 80, 394]
+[:mouse_move, 787, 157, 2, 81, 418]
+[:mouse_move, 776, 165, 2, 82, 419]
+[:mouse_move, 768, 168, 2, 83, 420]
+[:mouse_move, 766, 168, 2, 84, 421]
+[:mouse_move, 767, 168, 2, 85, 424]
+[:mouse_move, 772, 168, 2, 86, 425]
+[:mouse_move, 777, 168, 2, 87, 426]
+[:mouse_move, 778, 168, 2, 88, 427]
+[:key_down_raw, 13, 0, 2, 89, 461]
diff --git a/samples/07_advanced_rendering/00_rotating_label/app/main.rb b/samples/07_advanced_rendering/00_rotating_label/app/main.rb
new file mode 100644
index 0000000..8b21fb8
--- /dev/null
+++ b/samples/07_advanced_rendering/00_rotating_label/app/main.rb
@@ -0,0 +1,32 @@
+def tick args
+ # set the render target width and height to match the label
+ args.outputs[:scene].w = 220
+ args.outputs[:scene].h = 30
+
+
+ # make the background transparent
+ args.outputs[:scene].background_color = [255, 255, 255, 0]
+
+ # set the blendmode of the label to 0 (no blending)
+ # center it inside of the scene
+ # set the vertical_alignment_enum to 1 (center)
+ args.outputs[:scene].labels << { x: 0,
+ y: 15,
+ text: "label in render target",
+ blendmode_enum: 0,
+ vertical_alignment_enum: 1 }
+
+ # add a border to the render target
+ args.outputs[:scene].borders << { x: 0,
+ y: 0,
+ w: args.outputs[:scene].w,
+ h: args.outputs[:scene].h }
+
+ # add the rendertarget to the main output as a sprite
+ args.outputs.sprites << { x: 640 - args.outputs[:scene].w.half,
+ y: 360 - args.outputs[:scene].h.half,
+ w: args.outputs[:scene].w,
+ h: args.outputs[:scene].h,
+ angle: args.state.tick_count,
+ path: :scene }
+end
diff --git a/samples/07_advanced_rendering/02_render_targets_with_alphas/app/main.rb b/samples/07_advanced_rendering/02_render_targets_with_alphas/app/main.rb
deleted file mode 100644
index 2caec43..0000000
--- a/samples/07_advanced_rendering/02_render_targets_with_alphas/app/main.rb
+++ /dev/null
@@ -1,95 +0,0 @@
-# This sample is meant to show you how to do that dripping transition thing
-# at the start of the original Doom. Most of this file is here to animate
-# a scene to wipe away; the actual wipe effect is in the last 20 lines or
-# so.
-
-$gtk.reset # reset all game state if reloaded.
-
-def circle_of_blocks pass, xoffset, yoffset, angleoffset, blocksize, distance
- numblocks = 10
-
- for i in 1..numblocks do
- angle = ((360 / numblocks) * i) + angleoffset
- radians = angle * (Math::PI / 180)
- x = (xoffset + (distance * Math.cos(radians))).round
- y = (yoffset + (distance * Math.sin(radians))).round
- pass.solids << [ x, y, blocksize, blocksize, 255, 255, 0 ]
- end
-end
-
-def draw_scene args, pass
- pass.solids << [0, 360, 1280, 360, 0, 0, 200]
- pass.solids << [0, 0, 1280, 360, 0, 127, 0]
-
- blocksize = 100
- angleoffset = args.state.tick_count * 2.5
- centerx = (1280 - blocksize) / 2
- centery = (720 - blocksize) / 2
-
- circle_of_blocks pass, centerx, centery, angleoffset, blocksize * 2, 500
- circle_of_blocks pass, centerx, centery, angleoffset, blocksize, 325
- circle_of_blocks pass, centerx, centery, angleoffset, blocksize / 2, 200
- circle_of_blocks pass, centerx, centery, angleoffset, blocksize / 4, 100
-end
-
-def tick args
- segments = 160
-
- # On the first tick, initialize some stuff.
- if !args.state.yoffsets
- args.state.baseyoff = 0
- args.state.yoffsets = []
- for i in 0..segments do
- args.state.yoffsets << rand * 100
- end
- end
-
- # Just draw some random stuff for a few seconds.
- args.state.static_debounce ||= 60 * 2.5
- if args.state.static_debounce > 0
- last_frame = args.state.static_debounce == 1
- target = last_frame ? args.render_target(:last_frame) : args.outputs
- draw_scene args, target
- args.state.static_debounce -= 1
- return unless last_frame
- end
-
- # build up the wipe...
-
- # this is the thing we're wiping to.
- args.outputs.sprites << [ 0, 0, 1280, 720, 'dragonruby.png' ]
-
- return if (args.state.baseyoff > (1280 + 100)) # stop when done sliding
-
- segmentw = 1280 / segments
-
- x = 0
- for i in 0..segments do
- yoffset = 0
- if args.state.yoffsets[i] < args.state.baseyoff
- yoffset = args.state.baseyoff - args.state.yoffsets[i]
- end
-
- # (720 - yoffset) flips the coordinate system, (- 720) adjusts for the height of the segment.
- args.outputs.sprites << [ x, (720 - yoffset) - 720, segmentw, 720, 'last_frame', 0, 255, 255, 255, 255, x, 0, segmentw, 720 ]
- x += segmentw
- end
-
- args.state.baseyoff += 4
-
- tick_instructions args, "Sample app shows an advanced usage of render_target."
-end
-
-def tick_instructions args, text, y = 715
- return if args.state.key_event_occurred
- if args.inputs.mouse.click ||
- args.inputs.keyboard.directional_vector ||
- args.inputs.keyboard.key_down.enter ||
- args.inputs.keyboard.key_down.escape
- args.state.key_event_occurred = true
- end
-
- args.outputs.debug << [0, y - 50, 1280, 60].solid
- args.outputs.debug << [640, y, text, 1, 1, 255, 255, 255].label
- args.outputs.debug << [640, y - 25, "(click to dismiss instructions)" , -2, 1, 255, 255, 255].label
-end
diff --git a/samples/07_advanced_rendering/03_render_target_viewports/app/main.rb b/samples/07_advanced_rendering/03_render_target_viewports/app/main.rb
index b748ffa..dbceab3 100644
--- a/samples/07_advanced_rendering/03_render_target_viewports/app/main.rb
+++ b/samples/07_advanced_rendering/03_render_target_viewports/app/main.rb
@@ -48,10 +48,12 @@
- ARRAY#intersect_rect?: Returns true or false depending on if the two rectangles intersect.
- args.inputs.mouse.click: This property will be set if the mouse was clicked.
+ For more information about the mouse, go to mygame/documentation/07-mouse.md.
- args.inputs.keyboard.key_up.KEY: The value of the properties will be set
to the frame that the key_up event occurred (the frame correlates
to args.state.tick_count).
+ For more information about the keyboard, go to mygame/documentation/06-keyboard.md.
- args.state.labels:
The parameters for a label are
@@ -61,6 +63,7 @@
4. the alignment
5. the color (red, green, and blue saturations)
6. the alpha (or transparency)
+ For more information about labels, go to mygame/documentation/02-labels.md.
- args.state.lines:
The parameters for a line are
@@ -68,6 +71,7 @@
2. the ending position (x2, y2)
3. the color (red, green, and blue saturations)
4. the alpha (or transparency)
+ For more information about lines, go to mygame/documentation/04-lines.md.
- args.state.solids (and args.state.borders):
The parameters for a solid (or border) are
@@ -76,6 +80,7 @@
3. the height (h)
4. the color (r, g, b)
5. the alpha (or transparency)
+ For more information about solids and borders, go to mygame/documentation/03-solids-and-borders.md.
- args.state.sprites:
The parameters for a sprite are
@@ -85,7 +90,7 @@
4. the image path
5. the angle
6. the alpha (or transparency)
-
+ For more information about sprites, go to mygame/documentation/05-sprites.md.
=end
# This sample app shows different objects that can be used when making games, such as labels,
diff --git a/samples/07_advanced_rendering/04_render_primitive_hierarchies/app/main.rb b/samples/07_advanced_rendering/04_render_primitive_hierarchies/app/main.rb
index 7f345ac..aedd830 100644
--- a/samples/07_advanced_rendering/04_render_primitive_hierarchies/app/main.rb
+++ b/samples/07_advanced_rendering/04_render_primitive_hierarchies/app/main.rb
@@ -39,6 +39,7 @@
Here is an example of a (red) border or solid definition:
[100, 100, 400, 500, 255, 0, 0]
It will be a solid or border depending on if it is added to args.outputs.solids or args.outputs.borders.
+ For more information about solids and borders, go to mygame/documentation/03-solids-and-borders.md.
- args.outputs.sprites: An array. The values generate a sprite.
The parameters for sprites are
@@ -49,6 +50,7 @@
Here is an example of a sprite definition:
[100, 100, 400, 500, 'sprites/dragonruby.png']
+ For more information about sprites, go to mygame/documentation/05-sprites.md.
=end
diff --git a/samples/07_advanced_rendering/05_render_primitives_as_hash/app/main.rb b/samples/07_advanced_rendering/05_render_primitives_as_hash/app/main.rb
index 53e0f3d..907b0fb 100644
--- a/samples/07_advanced_rendering/05_render_primitives_as_hash/app/main.rb
+++ b/samples/07_advanced_rendering/05_render_primitives_as_hash/app/main.rb
@@ -16,18 +16,23 @@
- args.outputs.sprites: An array. The values generate a sprite.
The parameters are [X, Y, WIDTH, HEIGHT, PATH, ANGLE, ALPHA, RED, GREEN, BLUE]
+ For more information about sprites, go to mygame/documentation/05-sprites.md.
- args.outputs.labels: An array. The values generate a label.
The parameters are [X, Y, TEXT, SIZE, ALIGNMENT, RED, GREEN, BLUE, ALPHA, FONT STYLE]
+ For more information about labels, go to mygame/documentation/02-labels.md.
- args.outputs.solids: An array. The values generate a solid.
The parameters are [X, Y, WIDTH, HEIGHT, RED, GREEN, BLUE, ALPHA]
+ For more information about solids, go to mygame/documentation/03-solids-and-borders.md.
- args.outputs.borders: An array. The values generate a border.
The parameters are the same as a solid.
+ For more information about borders, go to mygame/documentation/03-solids-and-borders.md.
- args.outputs.lines: An array. The values generate a line.
The parameters are [X1, Y1, X2, Y2, RED, GREEN, BLUE]
+ For more information about labels, go to mygame/documentation/02-labels.md.
=end
@@ -131,7 +136,7 @@ def tick args
flip_horizontally: false,
angle_anchor_x: 0.5, # rotation center set to middle
angle_anchor_y: 0.5
- }.sprite
+ }.sprite!
# Outputs label as primitive using a hash
args.outputs.primitives << {
@@ -145,7 +150,7 @@ def tick args
b: 50,
a: 255, # transparency
font: "fonts/manaspc.ttf" # font style
- }.label
+ }.label!
# Outputs solid as primitive using a hash
args.outputs.primitives << {
@@ -157,7 +162,7 @@ def tick args
g: 50,
b: 50,
a: 255 # transparency
- }.solid
+ }.solid!
# Outputs border as primitive using a hash
# Same parameters as solid
@@ -170,7 +175,7 @@ def tick args
g: 50,
b: 50,
a: 255 # transparency
- }.border
+ }.border!
# Outputs line as primitive using a hash
args.outputs.primitives << {
@@ -182,5 +187,5 @@ def tick args
g: 50,
b: 50,
a: 255 # transparency
- }.line
+ }.line!
end
diff --git a/samples/07_advanced_rendering/07_simple_camera/app/main.rb b/samples/07_advanced_rendering/07_simple_camera/app/main.rb
new file mode 100644
index 0000000..e8d96ea
--- /dev/null
+++ b/samples/07_advanced_rendering/07_simple_camera/app/main.rb
@@ -0,0 +1,93 @@
+def tick args
+ # variables you can play around with
+ args.state.world.w ||= 1280
+ args.state.world.h ||= 720
+
+ args.state.player.x ||= 0
+ args.state.player.y ||= 0
+ args.state.player.size ||= 32
+
+ args.state.enemy.x ||= 700
+ args.state.enemy.y ||= 700
+ args.state.enemy.size ||= 16
+
+ args.state.camera.x ||= 640
+ args.state.camera.y ||= 300
+ args.state.camera.scale ||= 1.0
+ args.state.camera.show_empty_space ||= :yes
+
+ # instructions
+ args.outputs.primitives << { x: 0, y: 80.from_top, w: 360, h: 80, r: 0, g: 0, b: 0, a: 128 }.solid!
+ args.outputs.primitives << { x: 10, y: 10.from_top, text: "arrow keys to move around", r: 255, g: 255, b: 255}.label!
+ args.outputs.primitives << { x: 10, y: 30.from_top, text: "+/- to change zoom of camera", r: 255, g: 255, b: 255}.label!
+ args.outputs.primitives << { x: 10, y: 50.from_top, text: "tab to change camera edge behavior", r: 255, g: 255, b: 255}.label!
+
+ # render scene
+ args.outputs[:scene].w = args.state.world.w
+ args.outputs[:scene].h = args.state.world.h
+
+ args.outputs[:scene].solids << { x: 0, y: 0, w: args.state.world.w, h: args.state.world.h, r: 20, g: 60, b: 80 }
+ args.outputs[:scene].solids << { x: args.state.player.x, y: args.state.player.y,
+ w: args.state.player.size, h: args.state.player.size, r: 80, g: 155, b: 80 }
+ args.outputs[:scene].solids << { x: args.state.enemy.x, y: args.state.enemy.y,
+ w: args.state.enemy.size, h: args.state.enemy.size, r: 155, g: 80, b: 80 }
+
+ # render camera
+ scene_position = calc_scene_position args
+ args.outputs.sprites << { x: scene_position.x,
+ y: scene_position.y,
+ w: scene_position.w,
+ h: scene_position.h,
+ path: :scene }
+
+ # move player
+ if args.inputs.directional_angle
+ args.state.player.x += args.inputs.directional_angle.vector_x * 5
+ args.state.player.y += args.inputs.directional_angle.vector_y * 5
+ args.state.player.x = args.state.player.x.clamp(0, args.state.world.w - args.state.player.size)
+ args.state.player.y = args.state.player.y.clamp(0, args.state.world.h - args.state.player.size)
+ end
+
+ # +/- to zoom in and out
+ if args.inputs.keyboard.plus && args.state.tick_count.zmod?(3)
+ args.state.camera.scale += 0.05
+ elsif args.inputs.keyboard.hyphen && args.state.tick_count.zmod?(3)
+ args.state.camera.scale -= 0.05
+ elsif args.inputs.keyboard.key_down.tab
+ if args.state.camera.show_empty_space == :yes
+ args.state.camera.show_empty_space = :no
+ else
+ args.state.camera.show_empty_space = :yes
+ end
+ end
+
+ args.state.camera.scale = args.state.camera.scale.greater(0.1)
+end
+
+def calc_scene_position args
+ result = { x: args.state.camera.x - (args.state.player.x * args.state.camera.scale),
+ y: args.state.camera.y - (args.state.player.y * args.state.camera.scale),
+ w: args.state.world.w * args.state.camera.scale,
+ h: args.state.world.h * args.state.camera.scale,
+ scale: args.state.camera.scale }
+
+ return result if args.state.camera.show_empty_space == :yes
+
+ if result.w < args.grid.w
+ result.merge!(x: (args.grid.w - result.w).half)
+ elsif (args.state.player.x * result.scale) < args.grid.w.half
+ result.merge!(x: 10)
+ elsif (result.x + result.w) < args.grid.w
+ result.merge!(x: - result.w + (args.grid.w - 10))
+ end
+
+ if result.h < args.grid.h
+ result.merge!(y: (args.grid.h - result.h).half)
+ elsif (result.y) > 10
+ result.merge!(y: 10)
+ elsif (result.y + result.h) < args.grid.h
+ result.merge!(y: - result.h + (args.grid.h - 10))
+ end
+
+ result
+end
diff --git a/samples/07_advanced_rendering/07_simple_camera/replay.txt b/samples/07_advanced_rendering/07_simple_camera/replay.txt
new file mode 100644
index 0000000..532f46c
--- /dev/null
+++ b/samples/07_advanced_rendering/07_simple_camera/replay.txt
@@ -0,0 +1,232 @@
+replay_version 2.0
+stopped_at 1551
+seed 100
+recorded_at Sat Jul 17 09:21:44 2021
+[:mouse_button_up, 1, 0, 1, 1, 6]
+[:mouse_button_pressed, 1, 0, 1, 2, 140]
+[:mouse_button_up, 1, 0, 1, 3, 146]
+[:key_down_raw, 1073741903, 0, 2, 4, 245]
+[:key_down_raw, 1073741903, 0, 2, 5, 259]
+[:key_down_raw, 1073741903, 0, 2, 6, 261]
+[:key_down_raw, 1073741903, 0, 2, 7, 263]
+[:key_down_raw, 1073741903, 0, 2, 8, 265]
+[:key_down_raw, 1073741903, 0, 2, 9, 267]
+[:key_down_raw, 1073741903, 0, 2, 10, 269]
+[:key_down_raw, 1073741906, 0, 2, 11, 269]
+[:key_up_raw, 1073741903, 0, 2, 12, 280]
+[:key_down_raw, 1073741903, 0, 2, 13, 284]
+[:key_down_raw, 1073741903, 0, 2, 14, 299]
+[:key_down_raw, 1073741903, 0, 2, 15, 301]
+[:key_down_raw, 1073741903, 0, 2, 16, 303]
+[:key_down_raw, 1073741903, 0, 2, 17, 305]
+[:key_down_raw, 1073741903, 0, 2, 18, 307]
+[:key_down_raw, 1073741903, 0, 2, 19, 309]
+[:key_down_raw, 1073741903, 0, 2, 20, 311]
+[:key_down_raw, 1073741903, 0, 2, 21, 313]
+[:key_down_raw, 1073741903, 0, 2, 22, 315]
+[:key_down_raw, 1073741903, 0, 2, 23, 317]
+[:key_down_raw, 1073741903, 0, 2, 24, 319]
+[:key_down_raw, 1073741903, 0, 2, 25, 321]
+[:key_down_raw, 1073741903, 0, 2, 26, 323]
+[:key_down_raw, 1073741903, 0, 2, 27, 325]
+[:key_down_raw, 1073741903, 0, 2, 28, 327]
+[:key_down_raw, 1073741903, 0, 2, 29, 329]
+[:key_down_raw, 1073741903, 0, 2, 30, 331]
+[:key_down_raw, 1073741903, 0, 2, 31, 333]
+[:key_down_raw, 1073741903, 0, 2, 32, 335]
+[:key_down_raw, 1073741903, 0, 2, 33, 337]
+[:key_down_raw, 1073741903, 0, 2, 34, 339]
+[:key_up_raw, 1073741906, 0, 2, 35, 341]
+[:key_down_raw, 1073741903, 0, 2, 36, 341]
+[:key_down_raw, 1073741903, 0, 2, 37, 343]
+[:key_down_raw, 1073741903, 0, 2, 38, 345]
+[:key_down_raw, 1073741903, 0, 2, 39, 347]
+[:key_down_raw, 1073741903, 0, 2, 40, 349]
+[:key_down_raw, 1073741903, 0, 2, 41, 351]
+[:key_down_raw, 1073741903, 0, 2, 42, 353]
+[:key_down_raw, 1073741903, 0, 2, 43, 355]
+[:key_down_raw, 1073741906, 0, 2, 44, 357]
+[:key_down_raw, 1073741906, 0, 2, 45, 372]
+[:key_down_raw, 1073741906, 0, 2, 46, 374]
+[:key_down_raw, 1073741906, 0, 2, 47, 376]
+[:key_down_raw, 1073741906, 0, 2, 48, 378]
+[:key_down_raw, 1073741906, 0, 2, 49, 380]
+[:key_down_raw, 1073741906, 0, 2, 50, 382]
+[:key_down_raw, 1073741906, 0, 2, 51, 384]
+[:key_down_raw, 1073741906, 0, 2, 52, 386]
+[:key_down_raw, 1073741906, 0, 2, 53, 388]
+[:key_down_raw, 1073741906, 0, 2, 54, 390]
+[:key_down_raw, 1073741906, 0, 2, 55, 392]
+[:key_down_raw, 1073741906, 0, 2, 56, 395]
+[:key_up_raw, 1073741906, 0, 2, 57, 396]
+[:key_up_raw, 1073741903, 0, 2, 58, 397]
+[:key_down_raw, 8, 0, 2, 59, 466]
+[:key_up_raw, 8, 0, 2, 60, 466]
+[:key_down_raw, 8, 0, 2, 61, 470]
+[:key_up_raw, 8, 0, 2, 62, 475]
+[:key_down_raw, 45, 0, 2, 63, 540]
+[:key_up_raw, 45, 0, 2, 64, 545]
+[:key_down_raw, 45, 0, 2, 65, 551]
+[:key_up_raw, 45, 0, 2, 66, 556]
+[:key_down_raw, 45, 0, 2, 67, 566]
+[:key_up_raw, 45, 0, 2, 68, 571]
+[:key_down_raw, 45, 0, 2, 69, 577]
+[:key_up_raw, 45, 0, 2, 70, 581]
+[:key_down_raw, 45, 0, 2, 71, 595]
+[:key_up_raw, 45, 0, 2, 72, 600]
+[:key_down_raw, 1073741905, 0, 2, 73, 715]
+[:key_down_raw, 1073741905, 0, 2, 74, 730]
+[:key_down_raw, 1073741905, 0, 2, 75, 732]
+[:key_down_raw, 1073741905, 0, 2, 76, 734]
+[:key_down_raw, 1073741905, 0, 2, 77, 736]
+[:key_down_raw, 1073741905, 0, 2, 78, 738]
+[:key_down_raw, 1073741904, 0, 2, 79, 739]
+[:key_up_raw, 1073741905, 0, 2, 80, 743]
+[:key_down_raw, 1073741904, 0, 2, 81, 754]
+[:key_down_raw, 1073741904, 0, 2, 82, 756]
+[:key_down_raw, 1073741904, 0, 2, 83, 758]
+[:key_down_raw, 1073741904, 0, 2, 84, 760]
+[:key_down_raw, 1073741904, 0, 2, 85, 762]
+[:key_down_raw, 1073741904, 0, 2, 86, 764]
+[:key_down_raw, 1073741904, 0, 2, 87, 766]
+[:key_down_raw, 1073741904, 0, 2, 88, 768]
+[:key_down_raw, 1073741904, 0, 2, 89, 770]
+[:key_down_raw, 1073741904, 0, 2, 90, 772]
+[:key_down_raw, 1073741905, 0, 2, 91, 774]
+[:key_down_raw, 1073741906, 0, 2, 92, 781]
+[:key_up_raw, 1073741904, 0, 2, 93, 785]
+[:key_up_raw, 1073741905, 0, 2, 94, 791]
+[:key_down_raw, 1073741906, 0, 2, 95, 796]
+[:key_down_raw, 1073741903, 0, 2, 96, 797]
+[:key_up_raw, 1073741906, 0, 2, 97, 804]
+[:key_up_raw, 1073741903, 0, 2, 98, 810]
+[:key_down_raw, 1073742049, 1, 2, 99, 884]
+[:key_down_raw, 61, 1, 2, 100, 885]
+[:key_up_raw, 61, 1, 2, 101, 888]
+[:key_up_raw, 1073742049, 0, 2, 102, 888]
+[:key_down_raw, 1073742049, 1, 2, 103, 898]
+[:key_down_raw, 61, 1, 2, 104, 899]
+[:key_up_raw, 61, 1, 2, 105, 903]
+[:key_up_raw, 1073742049, 0, 2, 106, 903]
+[:key_down_raw, 1073742049, 1, 2, 107, 909]
+[:key_down_raw, 61, 1, 2, 108, 909]
+[:key_up_raw, 61, 1, 2, 109, 912]
+[:key_up_raw, 1073742049, 0, 2, 110, 913]
+[:key_down_raw, 1073742049, 1, 2, 111, 918]
+[:key_down_raw, 61, 1, 2, 112, 918]
+[:key_up_raw, 61, 1, 2, 113, 921]
+[:key_up_raw, 1073742049, 0, 2, 114, 922]
+[:key_down_raw, 1073742049, 1, 2, 115, 926]
+[:key_down_raw, 61, 1, 2, 116, 926]
+[:key_up_raw, 61, 1, 2, 117, 930]
+[:key_up_raw, 1073742049, 0, 2, 118, 931]
+[:key_down_raw, 1073742049, 1, 2, 119, 935]
+[:key_down_raw, 61, 1, 2, 120, 935]
+[:key_up_raw, 61, 1, 2, 121, 940]
+[:key_up_raw, 1073742049, 0, 2, 122, 941]
+[:key_down_raw, 1073742049, 1, 2, 123, 947]
+[:key_down_raw, 61, 1, 2, 124, 947]
+[:key_up_raw, 61, 1, 2, 125, 950]
+[:key_up_raw, 1073742049, 0, 2, 126, 951]
+[:key_down_raw, 1073742049, 1, 2, 127, 955]
+[:key_down_raw, 61, 1, 2, 128, 956]
+[:key_up_raw, 61, 1, 2, 129, 960]
+[:key_up_raw, 1073742049, 0, 2, 130, 960]
+[:key_down_raw, 9, 0, 2, 131, 986]
+[:key_up_raw, 9, 0, 2, 132, 991]
+[:key_down_raw, 1073741904, 0, 2, 133, 1015]
+[:key_down_raw, 1073741904, 0, 2, 134, 1030]
+[:key_down_raw, 1073741904, 0, 2, 135, 1032]
+[:key_down_raw, 1073741904, 0, 2, 136, 1034]
+[:key_down_raw, 1073741904, 0, 2, 137, 1036]
+[:key_down_raw, 1073741904, 0, 2, 138, 1038]
+[:key_down_raw, 1073741904, 0, 2, 139, 1040]
+[:key_down_raw, 1073741904, 0, 2, 140, 1042]
+[:key_up_raw, 1073741904, 0, 2, 141, 1044]
+[:key_down_raw, 1073741903, 0, 2, 142, 1048]
+[:key_down_raw, 1073741903, 0, 2, 143, 1063]
+[:key_down_raw, 1073741903, 0, 2, 144, 1065]
+[:key_down_raw, 1073741903, 0, 2, 145, 1067]
+[:key_down_raw, 1073741903, 0, 2, 146, 1069]
+[:key_down_raw, 1073741903, 0, 2, 147, 1071]
+[:key_down_raw, 1073741903, 0, 2, 148, 1073]
+[:key_down_raw, 1073741903, 0, 2, 149, 1075]
+[:key_down_raw, 1073741903, 0, 2, 150, 1077]
+[:key_down_raw, 1073741903, 0, 2, 151, 1079]
+[:key_down_raw, 1073741903, 0, 2, 152, 1081]
+[:key_down_raw, 1073741903, 0, 2, 153, 1083]
+[:key_down_raw, 1073741903, 0, 2, 154, 1085]
+[:key_down_raw, 1073741903, 0, 2, 155, 1087]
+[:key_down_raw, 1073741903, 0, 2, 156, 1089]
+[:key_down_raw, 1073741903, 0, 2, 157, 1091]
+[:key_down_raw, 1073741903, 0, 2, 158, 1093]
+[:key_down_raw, 1073741903, 0, 2, 159, 1095]
+[:key_down_raw, 1073741903, 0, 2, 160, 1097]
+[:key_down_raw, 1073741903, 0, 2, 161, 1099]
+[:key_down_raw, 1073741903, 0, 2, 162, 1101]
+[:key_down_raw, 1073741903, 0, 2, 163, 1103]
+[:key_down_raw, 1073741903, 0, 2, 164, 1105]
+[:key_down_raw, 1073741903, 0, 2, 165, 1107]
+[:key_down_raw, 1073741903, 0, 2, 166, 1109]
+[:key_down_raw, 1073741903, 0, 2, 167, 1111]
+[:key_down_raw, 1073741903, 0, 2, 168, 1113]
+[:key_down_raw, 1073741903, 0, 2, 169, 1115]
+[:key_down_raw, 1073741903, 0, 2, 170, 1117]
+[:key_down_raw, 1073741903, 0, 2, 171, 1119]
+[:key_down_raw, 1073741903, 0, 2, 172, 1121]
+[:key_down_raw, 1073741903, 0, 2, 173, 1123]
+[:key_down_raw, 1073741903, 0, 2, 174, 1125]
+[:key_down_raw, 1073741903, 0, 2, 175, 1127]
+[:key_down_raw, 1073741903, 0, 2, 176, 1129]
+[:key_down_raw, 1073741903, 0, 2, 177, 1131]
+[:key_down_raw, 1073741903, 0, 2, 178, 1133]
+[:key_down_raw, 1073741903, 0, 2, 179, 1135]
+[:key_down_raw, 1073741903, 0, 2, 180, 1137]
+[:key_down_raw, 1073741903, 0, 2, 181, 1139]
+[:key_down_raw, 1073741903, 0, 2, 182, 1141]
+[:key_down_raw, 1073741903, 0, 2, 183, 1143]
+[:key_down_raw, 1073741903, 0, 2, 184, 1145]
+[:key_down_raw, 1073741903, 0, 2, 185, 1147]
+[:key_down_raw, 1073741903, 0, 2, 186, 1149]
+[:key_down_raw, 1073741903, 0, 2, 187, 1151]
+[:key_down_raw, 1073741903, 0, 2, 188, 1153]
+[:key_down_raw, 1073741903, 0, 2, 189, 1155]
+[:key_down_raw, 1073741903, 0, 2, 190, 1157]
+[:key_down_raw, 1073741903, 0, 2, 191, 1159]
+[:key_down_raw, 1073741903, 0, 2, 192, 1161]
+[:key_down_raw, 1073741903, 0, 2, 193, 1163]
+[:key_down_raw, 1073741905, 0, 2, 194, 1164]
+[:key_down_raw, 1073741905, 0, 2, 195, 1180]
+[:key_down_raw, 1073741905, 0, 2, 196, 1182]
+[:key_down_raw, 1073741905, 0, 2, 197, 1184]
+[:key_down_raw, 1073741905, 0, 2, 198, 1186]
+[:key_down_raw, 1073741905, 0, 2, 199, 1188]
+[:key_down_raw, 1073741905, 0, 2, 200, 1190]
+[:key_down_raw, 1073741905, 0, 2, 201, 1192]
+[:key_down_raw, 1073741905, 0, 2, 202, 1194]
+[:key_down_raw, 1073741905, 0, 2, 203, 1196]
+[:key_down_raw, 1073741905, 0, 2, 204, 1198]
+[:key_down_raw, 1073741905, 0, 2, 205, 1200]
+[:key_down_raw, 1073741905, 0, 2, 206, 1202]
+[:key_down_raw, 1073741905, 0, 2, 207, 1204]
+[:key_down_raw, 1073741905, 0, 2, 208, 1206]
+[:key_down_raw, 1073741905, 0, 2, 209, 1208]
+[:key_down_raw, 1073741905, 0, 2, 210, 1210]
+[:key_down_raw, 1073741905, 0, 2, 211, 1212]
+[:key_down_raw, 1073741905, 0, 2, 212, 1214]
+[:key_down_raw, 1073741905, 0, 2, 213, 1216]
+[:key_up_raw, 1073741903, 0, 2, 214, 1216]
+[:key_up_raw, 1073741905, 0, 2, 215, 1217]
+[:key_down_raw, 45, 0, 2, 216, 1263]
+[:key_up_raw, 45, 0, 2, 217, 1265]
+[:key_down_raw, 45, 0, 2, 218, 1271]
+[:key_up_raw, 45, 0, 2, 219, 1275]
+[:key_down_raw, 45, 0, 2, 220, 1282]
+[:key_up_raw, 45, 0, 2, 221, 1287]
+[:key_down_raw, 45, 0, 2, 222, 1296]
+[:key_up_raw, 45, 0, 2, 223, 1301]
+[:key_down_raw, 45, 0, 2, 224, 1308]
+[:key_up_raw, 45, 0, 2, 225, 1312]
+[:key_down_raw, 96, 0, 2, 226, 1386]
+[:key_up_raw, 96, 0, 2, 227, 1391]
+[:key_down_raw, 13, 0, 2, 228, 1551]
diff --git a/samples/07_advanced_rendering/07_splitscreen_camera/run.bat b/samples/07_advanced_rendering/07_splitscreen_camera/run.bat
deleted file mode 100644
index 08e7ed8..0000000
--- a/samples/07_advanced_rendering/07_splitscreen_camera/run.bat
+++ /dev/null
@@ -1,6 +0,0 @@
-cd /d %~dp0
-
-cd ..
-cd ..
-cd ..
-dragonruby samples/99_camera/splitscreen
diff --git a/samples/07_advanced_rendering/07_splitscreen_camera/app/main.rb b/samples/07_advanced_rendering/08_splitscreen_camera/app/main.rb
index 9b08e1e..9d22918 100644
--- a/samples/07_advanced_rendering/07_splitscreen_camera/app/main.rb
+++ b/samples/07_advanced_rendering/08_splitscreen_camera/app/main.rb
@@ -6,7 +6,7 @@ class CameraMovement
def serialize
{state: state, inputs: inputs, outputs: outputs, grid: grid }
end
-
+
def inspect
serialize.to_s
end
@@ -76,12 +76,12 @@ class CameraMovement
default_player(0, 0, 64, 64,
"sprites/player/player_#{state.player_cyan.orientation}_standing.png")
end
-
+
def new_player_magenta
default_player(64, 0, 64, 64,
"sprites/player/player_#{state.player_magenta.orientation}_standing.png")
end
-
+
def new_camera_magenta
default_camera(0,0,720,720)
end
@@ -93,7 +93,8 @@ class CameraMovement
def new_camera_center
default_camera(0,0,1280,720)
end
-
+
+
def new_room
default_floor_tile(0,0,1024,1024,'sprites/rooms/camera_room.png')
end
@@ -118,7 +119,7 @@ class CameraMovement
state.player_cyan.x += state.player_cyan.dx
state.player_cyan.y += state.player_cyan.dy
end
-
+
def calc_player_magenta
state.player_magenta.x += state.player_magenta.dx
state.player_magenta.y += state.player_magenta.dy
@@ -133,7 +134,7 @@ class CameraMovement
state.camera_center.x += (targetX - state.camera_center.x) * 0.1 * timeScale
state.camera_center.y += (targetY - state.camera_center.y) * 0.1 * timeScale
end
-
+
def calc_camera_magenta
timeScale = 1
@@ -170,7 +171,7 @@ class CameraMovement
def calc_trauma_decay
state.trauma = state.trauma * 0.9
end
-
+
def calc_random_float_range(min, max)
rand * (max-min) + min
end
@@ -198,7 +199,7 @@ class CameraMovement
g: 255,
b: 255}
end
-
+
def render_player_magenta
outputs[:scene].sprites << {x: state.player_magenta.x,
y: state.player_magenta.y,
@@ -244,16 +245,16 @@ class CameraMovement
render_camera_magenta_scene
render_camera_cyan_scene
- angle = Math.atan((state.player_magenta.y - state.player_cyan.y)/(state.player_magenta.x- state.player_cyan.x)) * 180/Math::PI
+ angle = Math.atan((state.player_magenta.y - state.player_cyan.y)/(state.player_magenta.x- state.player_cyan.x)) * 180/Math::PI
output_split_camera angle
-
+
end
def render_camera_magenta_scene
zoomFactor = 1
offsetX = 32
offsetY = 32
-
+
outputs[:scene_magenta].sprites << {x: (-state.camera_magenta.x*2),
y: (-state.camera_magenta.y),
w: outputs[:scene].width*2,
@@ -279,7 +280,7 @@ class CameraMovement
outputs.labels << [128,64,"#{quadrant}",8,2,255,0,255,255]
if quadrant == 1
set_camera_attributes(w: 640, h: 720, m_x: 640, m_y: 0, c_x: 0, c_y: 0)
-
+
elsif quadrant == 2
set_camera_attributes(w: 1280, h: 360, m_x: 0, m_y: 360, c_x: 0, c_y: 0)
@@ -297,7 +298,7 @@ class CameraMovement
state.camera_cyan.h = h + 64
outputs[:scene_cyan].width = (w) * 2
outputs[:scene_cyan].height = h
-
+
state.camera_magenta.w = w + 64
state.camera_magenta.h = h + 64
outputs[:scene_magenta].width = (w) * 2
@@ -309,7 +310,7 @@ class CameraMovement
path: :scene_magenta}
outputs.sprites << {x: c_x,
y: c_y,
- w: w,
+ w: w,
h: h,
path: :scene_cyan}
end
@@ -317,7 +318,7 @@ class CameraMovement
def add_trauma amount
state.trauma = [state.trauma + amount, 1.0].min
end
-
+
def remove_trauma amount
state.trauma = [state.trauma - amount, 0.0].max
end
@@ -357,7 +358,7 @@ class CameraMovement
outputs.labels << [128,512,"#{state.player_cyan.x.round()}",8,2,0,255,255,255]
outputs.labels << [128,480,"#{state.player_cyan.y.round()}",8,2,0,255,255,255]
end
-
+
def input_move_magenta
if inputs.keyboard.key_held.w
state.player_magenta.dy = 5
@@ -391,5 +392,5 @@ def tick args
$camera_movement.outputs = args.outputs
$camera_movement.state = args.state
$camera_movement.grid = args.grid
- $camera_movement.tick
+ $camera_movement.tick
end
diff --git a/samples/07_advanced_rendering/08_splitscreen_camera/replay.txt b/samples/07_advanced_rendering/08_splitscreen_camera/replay.txt
new file mode 100644
index 0000000..b0c548e
--- /dev/null
+++ b/samples/07_advanced_rendering/08_splitscreen_camera/replay.txt
@@ -0,0 +1,226 @@
+replay_version 2.0
+stopped_at 1047
+seed 100
+recorded_at Sat Jul 17 09:23:22 2021
+[:mouse_button_up, 1, 0, 1, 1, 5]
+[:mouse_move, 795, 98, 2, 2, 75]
+[:mouse_move, 797, 100, 2, 3, 77]
+[:mouse_move, 799, 101, 2, 4, 78]
+[:mouse_move, 800, 101, 2, 5, 78]
+[:mouse_button_pressed, 1, 0, 1, 6, 88]
+[:mouse_button_up, 1, 0, 1, 7, 92]
+[:key_down_raw, 1073741903, 0, 2, 8, 124]
+[:key_down_raw, 1073741903, 0, 2, 9, 138]
+[:key_down_raw, 1073741903, 0, 2, 10, 141]
+[:key_down_raw, 1073741903, 0, 2, 11, 142]
+[:key_down_raw, 1073741903, 0, 2, 12, 144]
+[:key_down_raw, 1073741903, 0, 2, 13, 147]
+[:key_down_raw, 1073741903, 0, 2, 14, 148]
+[:key_down_raw, 1073741903, 0, 2, 15, 151]
+[:key_down_raw, 1073741906, 0, 2, 16, 151]
+[:key_down_raw, 1073741906, 0, 2, 17, 166]
+[:key_down_raw, 1073741906, 0, 2, 18, 169]
+[:key_down_raw, 1073741906, 0, 2, 19, 170]
+[:key_down_raw, 1073741906, 0, 2, 20, 172]
+[:key_down_raw, 1073741906, 0, 2, 21, 174]
+[:key_down_raw, 1073741906, 0, 2, 22, 177]
+[:key_down_raw, 1073741906, 0, 2, 23, 178]
+[:key_down_raw, 1073741906, 0, 2, 24, 180]
+[:key_down_raw, 1073741906, 0, 2, 25, 182]
+[:key_down_raw, 1073741906, 0, 2, 26, 184]
+[:key_down_raw, 1073741906, 0, 2, 27, 186]
+[:key_down_raw, 1073741906, 0, 2, 28, 188]
+[:key_down_raw, 1073741906, 0, 2, 29, 190]
+[:key_down_raw, 1073741906, 0, 2, 30, 193]
+[:key_down_raw, 1073741906, 0, 2, 31, 194]
+[:key_up_raw, 1073741906, 0, 2, 32, 195]
+[:key_up_raw, 1073741903, 0, 2, 33, 291]
+[:key_down_raw, 119, 0, 2, 34, 360]
+[:key_down_raw, 119, 0, 2, 35, 375]
+[:key_down_raw, 119, 0, 2, 36, 378]
+[:key_down_raw, 119, 0, 2, 37, 379]
+[:key_down_raw, 119, 0, 2, 38, 381]
+[:key_down_raw, 119, 0, 2, 39, 383]
+[:key_down_raw, 119, 0, 2, 40, 385]
+[:key_down_raw, 119, 0, 2, 41, 387]
+[:key_down_raw, 119, 0, 2, 42, 389]
+[:key_down_raw, 119, 0, 2, 43, 391]
+[:key_down_raw, 119, 0, 2, 44, 393]
+[:key_down_raw, 119, 0, 2, 45, 395]
+[:key_down_raw, 119, 0, 2, 46, 397]
+[:key_down_raw, 119, 0, 2, 47, 401]
+[:key_down_raw, 119, 0, 2, 48, 403]
+[:key_down_raw, 119, 0, 2, 49, 405]
+[:key_down_raw, 119, 0, 2, 50, 407]
+[:key_down_raw, 119, 0, 2, 51, 409]
+[:key_down_raw, 119, 0, 2, 52, 411]
+[:key_down_raw, 119, 0, 2, 53, 412]
+[:key_down_raw, 119, 0, 2, 54, 414]
+[:key_down_raw, 119, 0, 2, 55, 416]
+[:key_down_raw, 119, 0, 2, 56, 419]
+[:key_down_raw, 119, 0, 2, 57, 421]
+[:key_down_raw, 119, 0, 2, 58, 422]
+[:key_down_raw, 119, 0, 2, 59, 424]
+[:key_down_raw, 119, 0, 2, 60, 426]
+[:key_down_raw, 119, 0, 2, 61, 429]
+[:key_down_raw, 119, 0, 2, 62, 431]
+[:key_down_raw, 119, 0, 2, 63, 432]
+[:key_down_raw, 119, 0, 2, 64, 434]
+[:key_down_raw, 119, 0, 2, 65, 436]
+[:key_down_raw, 119, 0, 2, 66, 438]
+[:key_down_raw, 119, 0, 2, 67, 441]
+[:key_down_raw, 119, 0, 2, 68, 443]
+[:key_down_raw, 119, 0, 2, 69, 444]
+[:key_down_raw, 119, 0, 2, 70, 446]
+[:key_down_raw, 119, 0, 2, 71, 449]
+[:key_down_raw, 119, 0, 2, 72, 451]
+[:key_down_raw, 119, 0, 2, 73, 453]
+[:key_down_raw, 119, 0, 2, 74, 455]
+[:key_down_raw, 119, 0, 2, 75, 457]
+[:key_down_raw, 119, 0, 2, 76, 459]
+[:key_down_raw, 119, 0, 2, 77, 460]
+[:key_down_raw, 119, 0, 2, 78, 462]
+[:key_down_raw, 119, 0, 2, 79, 464]
+[:key_down_raw, 119, 0, 2, 80, 467]
+[:key_down_raw, 119, 0, 2, 81, 468]
+[:key_down_raw, 119, 0, 2, 82, 471]
+[:key_down_raw, 119, 0, 2, 83, 473]
+[:key_down_raw, 119, 0, 2, 84, 474]
+[:key_down_raw, 119, 0, 2, 85, 476]
+[:key_down_raw, 119, 0, 2, 86, 478]
+[:key_down_raw, 119, 0, 2, 87, 481]
+[:key_down_raw, 119, 0, 2, 88, 482]
+[:key_down_raw, 119, 0, 2, 89, 484]
+[:key_down_raw, 119, 0, 2, 90, 486]
+[:key_down_raw, 119, 0, 2, 91, 489]
+[:key_down_raw, 119, 0, 2, 92, 491]
+[:key_down_raw, 119, 0, 2, 93, 493]
+[:key_down_raw, 119, 0, 2, 94, 494]
+[:key_down_raw, 119, 0, 2, 95, 496]
+[:key_down_raw, 119, 0, 2, 96, 498]
+[:key_down_raw, 119, 0, 2, 97, 501]
+[:key_down_raw, 119, 0, 2, 98, 502]
+[:key_down_raw, 119, 0, 2, 99, 505]
+[:key_down_raw, 119, 0, 2, 100, 507]
+[:key_down_raw, 119, 0, 2, 101, 509]
+[:key_down_raw, 119, 0, 2, 102, 511]
+[:key_down_raw, 119, 0, 2, 103, 512]
+[:key_down_raw, 119, 0, 2, 104, 514]
+[:key_down_raw, 119, 0, 2, 105, 516]
+[:key_down_raw, 119, 0, 2, 106, 519]
+[:key_down_raw, 119, 0, 2, 107, 521]
+[:key_down_raw, 119, 0, 2, 108, 523]
+[:key_down_raw, 119, 0, 2, 109, 524]
+[:key_down_raw, 119, 0, 2, 110, 526]
+[:key_down_raw, 119, 0, 2, 111, 529]
+[:key_down_raw, 119, 0, 2, 112, 530]
+[:key_down_raw, 119, 0, 2, 113, 533]
+[:key_down_raw, 119, 0, 2, 114, 535]
+[:key_down_raw, 119, 0, 2, 115, 536]
+[:key_up_raw, 119, 0, 2, 116, 536]
+[:key_down_raw, 100, 0, 2, 117, 548]
+[:key_down_raw, 100, 0, 2, 118, 563]
+[:key_down_raw, 100, 0, 2, 119, 565]
+[:key_down_raw, 100, 0, 2, 120, 567]
+[:key_down_raw, 100, 0, 2, 121, 569]
+[:key_down_raw, 100, 0, 2, 122, 572]
+[:key_down_raw, 100, 0, 2, 123, 573]
+[:key_down_raw, 100, 0, 2, 124, 576]
+[:key_down_raw, 100, 0, 2, 125, 577]
+[:key_down_raw, 100, 0, 2, 126, 579]
+[:key_down_raw, 100, 0, 2, 127, 582]
+[:key_down_raw, 100, 0, 2, 128, 584]
+[:key_down_raw, 100, 0, 2, 129, 585]
+[:key_down_raw, 100, 0, 2, 130, 588]
+[:key_down_raw, 100, 0, 2, 131, 589]
+[:key_down_raw, 100, 0, 2, 132, 591]
+[:key_down_raw, 100, 0, 2, 133, 593]
+[:key_down_raw, 100, 0, 2, 134, 595]
+[:key_down_raw, 100, 0, 2, 135, 597]
+[:key_down_raw, 100, 0, 2, 136, 599]
+[:key_down_raw, 100, 0, 2, 137, 601]
+[:key_down_raw, 100, 0, 2, 138, 603]
+[:key_down_raw, 100, 0, 2, 139, 605]
+[:key_down_raw, 100, 0, 2, 140, 607]
+[:key_up_raw, 100, 0, 2, 141, 608]
+[:key_down_raw, 100, 0, 2, 142, 646]
+[:key_up_raw, 100, 0, 2, 143, 654]
+[:key_down_raw, 1073741906, 0, 2, 144, 696]
+[:key_down_raw, 1073741906, 0, 2, 145, 711]
+[:key_down_raw, 1073741906, 0, 2, 146, 713]
+[:key_down_raw, 1073741906, 0, 2, 147, 715]
+[:key_down_raw, 1073741906, 0, 2, 148, 717]
+[:key_down_raw, 1073741906, 0, 2, 149, 719]
+[:key_down_raw, 1073741906, 0, 2, 150, 721]
+[:key_down_raw, 1073741906, 0, 2, 151, 723]
+[:key_down_raw, 1073741906, 0, 2, 152, 725]
+[:key_down_raw, 1073741906, 0, 2, 153, 727]
+[:key_down_raw, 1073741906, 0, 2, 154, 729]
+[:key_down_raw, 1073741906, 0, 2, 155, 731]
+[:key_down_raw, 1073741906, 0, 2, 156, 733]
+[:key_down_raw, 1073741906, 0, 2, 157, 735]
+[:key_down_raw, 1073741906, 0, 2, 158, 737]
+[:key_down_raw, 1073741906, 0, 2, 159, 739]
+[:key_down_raw, 1073741906, 0, 2, 160, 741]
+[:key_down_raw, 1073741906, 0, 2, 161, 743]
+[:key_down_raw, 1073741906, 0, 2, 162, 745]
+[:key_down_raw, 1073741906, 0, 2, 163, 747]
+[:key_down_raw, 1073741906, 0, 2, 164, 749]
+[:key_down_raw, 1073741906, 0, 2, 165, 751]
+[:key_down_raw, 1073741906, 0, 2, 166, 753]
+[:key_down_raw, 1073741906, 0, 2, 167, 755]
+[:key_down_raw, 1073741906, 0, 2, 168, 757]
+[:key_down_raw, 1073741906, 0, 2, 169, 759]
+[:key_down_raw, 1073741906, 0, 2, 170, 761]
+[:key_down_raw, 1073741906, 0, 2, 171, 763]
+[:key_down_raw, 1073741906, 0, 2, 172, 765]
+[:key_down_raw, 1073741906, 0, 2, 173, 767]
+[:key_down_raw, 1073741906, 0, 2, 174, 769]
+[:key_down_raw, 1073741906, 0, 2, 175, 771]
+[:key_down_raw, 1073741906, 0, 2, 176, 773]
+[:key_down_raw, 1073741906, 0, 2, 177, 775]
+[:key_down_raw, 1073741906, 0, 2, 178, 777]
+[:key_down_raw, 1073741906, 0, 2, 179, 779]
+[:key_down_raw, 1073741906, 0, 2, 180, 781]
+[:key_down_raw, 1073741906, 0, 2, 181, 783]
+[:key_down_raw, 1073741904, 0, 2, 182, 784]
+[:key_down_raw, 1073741904, 0, 2, 183, 798]
+[:key_down_raw, 1073741904, 0, 2, 184, 800]
+[:key_down_raw, 1073741904, 0, 2, 185, 802]
+[:key_down_raw, 1073741904, 0, 2, 186, 804]
+[:key_down_raw, 1073741904, 0, 2, 187, 806]
+[:key_down_raw, 1073741904, 0, 2, 188, 810]
+[:key_down_raw, 1073741904, 0, 2, 189, 810]
+[:key_down_raw, 1073741904, 0, 2, 190, 814]
+[:key_down_raw, 1073741904, 0, 2, 191, 815]
+[:key_down_raw, 1073741904, 0, 2, 192, 818]
+[:key_down_raw, 1073741904, 0, 2, 193, 819]
+[:key_down_raw, 1073741904, 0, 2, 194, 822]
+[:key_down_raw, 1073741904, 0, 2, 195, 824]
+[:key_up_raw, 1073741906, 0, 2, 196, 824]
+[:key_down_raw, 1073741904, 0, 2, 197, 825]
+[:key_down_raw, 1073741904, 0, 2, 198, 828]
+[:key_up_raw, 1073741904, 0, 2, 199, 828]
+[:key_down_raw, 96, 0, 2, 200, 870]
+[:key_up_raw, 96, 0, 2, 201, 875]
+[:mouse_move, 802, 100, 2, 202, 933]
+[:mouse_move, 803, 100, 2, 203, 934]
+[:mouse_move, 806, 99, 2, 204, 935]
+[:mouse_move, 808, 98, 2, 205, 936]
+[:mouse_move, 813, 96, 2, 206, 937]
+[:mouse_move, 816, 95, 2, 207, 938]
+[:mouse_move, 824, 93, 2, 208, 939]
+[:mouse_move, 827, 92, 2, 209, 940]
+[:mouse_move, 837, 90, 2, 210, 941]
+[:mouse_move, 843, 90, 2, 211, 942]
+[:mouse_move, 857, 89, 2, 212, 943]
+[:mouse_move, 864, 89, 2, 213, 944]
+[:mouse_move, 874, 88, 2, 214, 945]
+[:mouse_move, 876, 88, 2, 215, 946]
+[:mouse_move, 878, 88, 2, 216, 947]
+[:mouse_move, 881, 87, 2, 217, 948]
+[:mouse_move, 882, 87, 2, 218, 950]
+[:mouse_move, 884, 87, 2, 219, 950]
+[:mouse_move, 885, 87, 2, 220, 951]
+[:mouse_move, 887, 87, 2, 221, 952]
+[:key_down_raw, 13, 0, 2, 222, 1047]
diff --git a/samples/07_advanced_rendering/07_splitscreen_camera/sprites/player/player_down_standing.png b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_down_standing.png
index 9e27489..9e27489 100644
--- a/samples/07_advanced_rendering/07_splitscreen_camera/sprites/player/player_down_standing.png
+++ b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_down_standing.png
Binary files differ
diff --git a/samples/07_advanced_rendering/07_splitscreen_camera/sprites/player/player_left_standing.png b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_left_standing.png
index 2fea35b..2fea35b 100644
--- a/samples/07_advanced_rendering/07_splitscreen_camera/sprites/player/player_left_standing.png
+++ b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_left_standing.png
Binary files differ
diff --git a/samples/07_advanced_rendering/07_splitscreen_camera/sprites/player/player_right_standing.png b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_right_standing.png
index 6f3402e..6f3402e 100644
--- a/samples/07_advanced_rendering/07_splitscreen_camera/sprites/player/player_right_standing.png
+++ b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_right_standing.png
Binary files differ
diff --git a/samples/07_advanced_rendering/07_splitscreen_camera/sprites/player/player_up_standing.png b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_up_standing.png
index 9ebdca7..9ebdca7 100644
--- a/samples/07_advanced_rendering/07_splitscreen_camera/sprites/player/player_up_standing.png
+++ b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_up_standing.png
Binary files differ
diff --git a/samples/07_advanced_rendering/07_splitscreen_camera/sprites/rooms/camera_room.png b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/rooms/camera_room.png
index e0ca375..e0ca375 100644
--- a/samples/07_advanced_rendering/07_splitscreen_camera/sprites/rooms/camera_room.png
+++ b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/rooms/camera_room.png
Binary files differ
diff --git a/samples/07_advanced_rendering/08_z_targeting_camera/app/main.rb b/samples/07_advanced_rendering/09_z_targeting_camera/app/main.rb
index ecdbfd3..ecdbfd3 100644
--- a/samples/07_advanced_rendering/08_z_targeting_camera/app/main.rb
+++ b/samples/07_advanced_rendering/09_z_targeting_camera/app/main.rb
diff --git a/samples/07_advanced_rendering/08_z_targeting_camera/metadata/game_metadata.txt b/samples/07_advanced_rendering/09_z_targeting_camera/metadata/game_metadata.txt
index 3ad3a1a..3ad3a1a 100644
--- a/samples/07_advanced_rendering/08_z_targeting_camera/metadata/game_metadata.txt
+++ b/samples/07_advanced_rendering/09_z_targeting_camera/metadata/game_metadata.txt
diff --git a/samples/07_advanced_rendering/08_z_targeting_camera/metadata/icon.png b/samples/07_advanced_rendering/09_z_targeting_camera/metadata/icon.png
index 57254fe..57254fe 100644
--- a/samples/07_advanced_rendering/08_z_targeting_camera/metadata/icon.png
+++ b/samples/07_advanced_rendering/09_z_targeting_camera/metadata/icon.png
Binary files differ
diff --git a/samples/07_advanced_rendering/09_z_targeting_camera/replay.txt b/samples/07_advanced_rendering/09_z_targeting_camera/replay.txt
new file mode 100644
index 0000000..db9130a
--- /dev/null
+++ b/samples/07_advanced_rendering/09_z_targeting_camera/replay.txt
@@ -0,0 +1,185 @@
+replay_version 2.0
+stopped_at 741
+seed 100
+recorded_at Sat Jul 17 09:24:36 2021
+[:mouse_button_up, 1, 0, 1, 1, 4]
+[:key_down_raw, 1073741906, 0, 2, 2, 104]
+[:key_down_raw, 1073741906, 0, 2, 3, 118]
+[:key_down_raw, 1073741906, 0, 2, 4, 120]
+[:key_down_raw, 1073741906, 0, 2, 5, 122]
+[:key_down_raw, 1073741906, 0, 2, 6, 124]
+[:key_down_raw, 1073741906, 0, 2, 7, 126]
+[:key_down_raw, 1073741906, 0, 2, 8, 128]
+[:key_down_raw, 1073741906, 0, 2, 9, 130]
+[:key_down_raw, 1073741906, 0, 2, 10, 132]
+[:key_down_raw, 1073741906, 0, 2, 11, 134]
+[:key_down_raw, 1073741906, 0, 2, 12, 136]
+[:key_down_raw, 1073741906, 0, 2, 13, 138]
+[:key_down_raw, 1073741906, 0, 2, 14, 140]
+[:key_down_raw, 1073741906, 0, 2, 15, 142]
+[:key_down_raw, 1073741906, 0, 2, 16, 144]
+[:key_down_raw, 1073741906, 0, 2, 17, 146]
+[:key_down_raw, 1073741906, 0, 2, 18, 148]
+[:key_down_raw, 1073741906, 0, 2, 19, 150]
+[:key_down_raw, 1073741906, 0, 2, 20, 152]
+[:key_down_raw, 1073741906, 0, 2, 21, 154]
+[:key_up_raw, 1073741906, 0, 2, 22, 156]
+[:key_down_raw, 1073741904, 0, 2, 23, 165]
+[:key_down_raw, 1073741904, 0, 2, 24, 180]
+[:key_down_raw, 1073741904, 0, 2, 25, 182]
+[:key_down_raw, 1073741904, 0, 2, 26, 184]
+[:key_down_raw, 1073741904, 0, 2, 27, 186]
+[:key_down_raw, 1073741904, 0, 2, 28, 188]
+[:key_down_raw, 1073741904, 0, 2, 29, 190]
+[:key_down_raw, 1073741904, 0, 2, 30, 192]
+[:key_down_raw, 1073741904, 0, 2, 31, 194]
+[:key_down_raw, 1073741904, 0, 2, 32, 196]
+[:key_down_raw, 1073741904, 0, 2, 33, 198]
+[:key_down_raw, 1073741904, 0, 2, 34, 200]
+[:key_down_raw, 1073741904, 0, 2, 35, 202]
+[:key_down_raw, 1073741904, 0, 2, 36, 204]
+[:key_down_raw, 1073741904, 0, 2, 37, 206]
+[:key_down_raw, 1073741904, 0, 2, 38, 208]
+[:key_down_raw, 1073741904, 0, 2, 39, 210]
+[:key_down_raw, 1073741904, 0, 2, 40, 212]
+[:key_down_raw, 1073741904, 0, 2, 41, 214]
+[:key_down_raw, 1073741904, 0, 2, 42, 216]
+[:key_down_raw, 1073741904, 0, 2, 43, 218]
+[:key_down_raw, 1073741904, 0, 2, 44, 220]
+[:key_down_raw, 1073741904, 0, 2, 45, 222]
+[:key_down_raw, 1073741904, 0, 2, 46, 224]
+[:key_down_raw, 1073741904, 0, 2, 47, 226]
+[:key_down_raw, 1073741904, 0, 2, 48, 228]
+[:key_down_raw, 1073741904, 0, 2, 49, 230]
+[:key_down_raw, 1073741904, 0, 2, 50, 232]
+[:key_down_raw, 1073741904, 0, 2, 51, 234]
+[:key_down_raw, 1073741904, 0, 2, 52, 236]
+[:key_down_raw, 1073741904, 0, 2, 53, 238]
+[:key_down_raw, 1073741904, 0, 2, 54, 240]
+[:key_down_raw, 1073741904, 0, 2, 55, 242]
+[:key_down_raw, 1073741904, 0, 2, 56, 244]
+[:key_down_raw, 1073741904, 0, 2, 57, 246]
+[:key_down_raw, 1073741904, 0, 2, 58, 248]
+[:key_down_raw, 1073741904, 0, 2, 59, 250]
+[:key_down_raw, 1073741904, 0, 2, 60, 252]
+[:key_down_raw, 1073741904, 0, 2, 61, 254]
+[:key_down_raw, 1073741906, 0, 2, 62, 256]
+[:key_down_raw, 1073741906, 0, 2, 63, 271]
+[:key_down_raw, 1073741906, 0, 2, 64, 273]
+[:key_down_raw, 1073741906, 0, 2, 65, 275]
+[:key_down_raw, 1073741906, 0, 2, 66, 277]
+[:key_down_raw, 1073741906, 0, 2, 67, 279]
+[:key_down_raw, 1073741906, 0, 2, 68, 281]
+[:key_down_raw, 1073741906, 0, 2, 69, 283]
+[:key_down_raw, 1073741906, 0, 2, 70, 285]
+[:key_down_raw, 1073741906, 0, 2, 71, 287]
+[:key_down_raw, 1073741906, 0, 2, 72, 289]
+[:key_down_raw, 1073741906, 0, 2, 73, 291]
+[:key_down_raw, 1073741906, 0, 2, 74, 293]
+[:key_down_raw, 1073741906, 0, 2, 75, 295]
+[:key_down_raw, 1073741906, 0, 2, 76, 297]
+[:key_down_raw, 1073741906, 0, 2, 77, 299]
+[:key_down_raw, 1073741906, 0, 2, 78, 301]
+[:key_down_raw, 1073741906, 0, 2, 79, 303]
+[:key_down_raw, 1073741906, 0, 2, 80, 305]
+[:key_down_raw, 1073741906, 0, 2, 81, 307]
+[:key_down_raw, 1073741906, 0, 2, 82, 309]
+[:key_down_raw, 1073741906, 0, 2, 83, 311]
+[:key_down_raw, 1073741906, 0, 2, 84, 313]
+[:key_up_raw, 1073741906, 0, 2, 85, 314]
+[:key_up_raw, 1073741904, 0, 2, 86, 316]
+[:key_down_raw, 1073741903, 0, 2, 87, 338]
+[:key_down_raw, 1073741903, 0, 2, 88, 353]
+[:key_down_raw, 1073741903, 0, 2, 89, 355]
+[:key_down_raw, 1073741903, 0, 2, 90, 357]
+[:key_down_raw, 1073741903, 0, 2, 91, 359]
+[:key_down_raw, 1073741903, 0, 2, 92, 361]
+[:key_down_raw, 1073741903, 0, 2, 93, 363]
+[:key_down_raw, 1073741903, 0, 2, 94, 365]
+[:key_down_raw, 1073741903, 0, 2, 95, 367]
+[:key_down_raw, 1073741903, 0, 2, 96, 369]
+[:key_down_raw, 1073741903, 0, 2, 97, 371]
+[:key_down_raw, 1073741903, 0, 2, 98, 373]
+[:key_down_raw, 1073741903, 0, 2, 99, 375]
+[:key_down_raw, 1073741903, 0, 2, 100, 377]
+[:key_down_raw, 1073741903, 0, 2, 101, 379]
+[:key_down_raw, 1073741903, 0, 2, 102, 381]
+[:key_down_raw, 1073741905, 0, 2, 103, 382]
+[:key_down_raw, 1073741905, 0, 2, 104, 397]
+[:key_down_raw, 1073741905, 0, 2, 105, 399]
+[:key_down_raw, 1073741905, 0, 2, 106, 401]
+[:key_down_raw, 1073741905, 0, 2, 107, 403]
+[:key_down_raw, 1073741905, 0, 2, 108, 405]
+[:key_down_raw, 1073741905, 0, 2, 109, 407]
+[:key_down_raw, 1073741905, 0, 2, 110, 409]
+[:key_down_raw, 1073741905, 0, 2, 111, 411]
+[:key_down_raw, 1073741905, 0, 2, 112, 413]
+[:key_down_raw, 1073741905, 0, 2, 113, 415]
+[:key_down_raw, 1073741905, 0, 2, 114, 417]
+[:key_down_raw, 1073741905, 0, 2, 115, 419]
+[:key_down_raw, 1073741905, 0, 2, 116, 421]
+[:key_down_raw, 1073741905, 0, 2, 117, 423]
+[:key_down_raw, 1073741905, 0, 2, 118, 425]
+[:key_down_raw, 1073741905, 0, 2, 119, 427]
+[:key_down_raw, 1073741905, 0, 2, 120, 429]
+[:key_down_raw, 1073741905, 0, 2, 121, 431]
+[:key_down_raw, 1073741905, 0, 2, 122, 433]
+[:key_up_raw, 1073741905, 0, 2, 123, 435]
+[:key_down_raw, 1073741905, 0, 2, 124, 447]
+[:key_up_raw, 1073741905, 0, 2, 125, 460]
+[:key_down_raw, 1073741905, 0, 2, 126, 485]
+[:key_down_raw, 1073741905, 0, 2, 127, 500]
+[:key_down_raw, 1073741905, 0, 2, 128, 502]
+[:key_down_raw, 1073741905, 0, 2, 129, 504]
+[:key_down_raw, 1073741905, 0, 2, 130, 506]
+[:key_up_raw, 1073741905, 0, 2, 131, 507]
+[:key_up_raw, 1073741903, 0, 2, 132, 548]
+[:key_down_raw, 1073741905, 0, 2, 133, 561]
+[:key_down_raw, 1073741905, 0, 2, 134, 576]
+[:key_down_raw, 1073741905, 0, 2, 135, 578]
+[:key_down_raw, 1073741905, 0, 2, 136, 580]
+[:key_down_raw, 1073741905, 0, 2, 137, 582]
+[:key_up_raw, 1073741905, 0, 2, 138, 584]
+[:key_down_raw, 96, 0, 2, 139, 648]
+[:key_up_raw, 96, 0, 2, 140, 653]
+[:mouse_move, 815, 98, 2, 141, 654]
+[:mouse_move, 816, 101, 2, 142, 655]
+[:mouse_move, 816, 104, 2, 143, 656]
+[:mouse_move, 816, 112, 2, 144, 657]
+[:mouse_move, 816, 117, 2, 145, 658]
+[:mouse_move, 810, 130, 2, 146, 659]
+[:mouse_move, 803, 137, 2, 147, 660]
+[:mouse_move, 782, 157, 2, 148, 661]
+[:mouse_move, 767, 168, 2, 149, 662]
+[:mouse_move, 734, 188, 2, 150, 663]
+[:mouse_move, 716, 197, 2, 151, 664]
+[:mouse_move, 682, 215, 2, 152, 665]
+[:mouse_move, 665, 223, 2, 153, 666]
+[:mouse_move, 645, 234, 2, 154, 667]
+[:mouse_move, 643, 235, 2, 155, 668]
+[:mouse_move, 643, 236, 2, 156, 669]
+[:mouse_move, 647, 237, 2, 157, 672]
+[:mouse_move, 670, 244, 2, 158, 673]
+[:mouse_move, 687, 245, 2, 159, 674]
+[:mouse_move, 720, 242, 2, 160, 675]
+[:mouse_move, 737, 237, 2, 161, 676]
+[:mouse_move, 764, 224, 2, 162, 677]
+[:mouse_move, 777, 216, 2, 163, 678]
+[:mouse_move, 796, 197, 2, 164, 679]
+[:mouse_move, 804, 187, 2, 165, 680]
+[:mouse_move, 815, 164, 2, 166, 681]
+[:mouse_move, 820, 152, 2, 167, 682]
+[:mouse_move, 825, 142, 2, 168, 683]
+[:mouse_move, 831, 128, 2, 169, 684]
+[:mouse_move, 832, 126, 2, 170, 685]
+[:mouse_move, 832, 125, 2, 171, 686]
+[:mouse_move, 833, 123, 2, 172, 688]
+[:mouse_move, 836, 120, 2, 173, 690]
+[:mouse_move, 837, 118, 2, 174, 691]
+[:mouse_move, 842, 113, 2, 175, 692]
+[:mouse_move, 844, 112, 2, 176, 693]
+[:mouse_move, 844, 111, 2, 177, 694]
+[:mouse_move, 844, 110, 2, 178, 696]
+[:mouse_move, 845, 110, 2, 179, 697]
+[:mouse_move, 845, 109, 2, 180, 699]
+[:key_down_raw, 13, 0, 2, 181, 741]
diff --git a/samples/07_advanced_rendering/08_z_targeting_camera/sprites/arena.png b/samples/07_advanced_rendering/09_z_targeting_camera/sprites/arena.png
index 5c92e91..5c92e91 100644
--- a/samples/07_advanced_rendering/08_z_targeting_camera/sprites/arena.png
+++ b/samples/07_advanced_rendering/09_z_targeting_camera/sprites/arena.png
Binary files differ
diff --git a/samples/07_advanced_rendering/08_z_targeting_camera/sprites/player.png b/samples/07_advanced_rendering/09_z_targeting_camera/sprites/player.png
index 332a80b..332a80b 100644
--- a/samples/07_advanced_rendering/08_z_targeting_camera/sprites/player.png
+++ b/samples/07_advanced_rendering/09_z_targeting_camera/sprites/player.png
Binary files differ
diff --git a/samples/07_advanced_rendering/08_z_targeting_camera/sprites/square/black.png b/samples/07_advanced_rendering/09_z_targeting_camera/sprites/square/black.png
index cea7bd7..cea7bd7 100644
--- a/samples/07_advanced_rendering/08_z_targeting_camera/sprites/square/black.png
+++ b/samples/07_advanced_rendering/09_z_targeting_camera/sprites/square/black.png
Binary files differ
diff --git a/samples/07_advanced_rendering/10_blend_modes/app/main.rb b/samples/07_advanced_rendering/10_blend_modes/app/main.rb
new file mode 100644
index 0000000..7e28ba8
--- /dev/null
+++ b/samples/07_advanced_rendering/10_blend_modes/app/main.rb
@@ -0,0 +1,49 @@
+$gtk.reset
+
+def draw_blendmode args, mode
+ w = 160
+ h = w
+ args.state.x += (1280-w) / (args.state.blendmodes.length + 1)
+ x = args.state.x
+ y = (720 - h) / 2
+ s = 'sprites/blue-feathered.png'
+ args.outputs.sprites << { blendmode_enum: mode.value, x: x, y: y, w: w, h: h, path: s }
+ args.outputs.labels << [x + (w/2), y, mode.name.to_s, 1, 1, 255, 255, 255]
+end
+
+def tick args
+
+ # Different blend modes do different things, depending on what they
+ # blend against (in this case, the pixels of the background color).
+ args.state.bg_element ||= 1
+ args.state.bg_color ||= 255
+ args.state.bg_color_direction ||= 1
+ bg_r = (args.state.bg_element == 1) ? args.state.bg_color : 0
+ bg_g = (args.state.bg_element == 2) ? args.state.bg_color : 0
+ bg_b = (args.state.bg_element == 3) ? args.state.bg_color : 0
+ args.state.bg_color += args.state.bg_color_direction
+ if (args.state.bg_color_direction > 0) && (args.state.bg_color >= 255)
+ args.state.bg_color_direction = -1
+ args.state.bg_color = 255
+ elsif (args.state.bg_color_direction < 0) && (args.state.bg_color <= 0)
+ args.state.bg_color_direction = 1
+ args.state.bg_color = 0
+ args.state.bg_element += 1
+ if args.state.bg_element >= 4
+ args.state.bg_element = 1
+ end
+ end
+
+ args.outputs.background_color = [ bg_r, bg_g, bg_b, 255 ]
+
+ args.state.blendmodes ||= [
+ { name: :none, value: 0 },
+ { name: :blend, value: 1 },
+ { name: :add, value: 2 },
+ { name: :mod, value: 3 },
+ { name: :mul, value: 4 }
+ ]
+
+ args.state.x = 0 # reset this, draw_blendmode will increment it.
+ args.state.blendmodes.each { |blendmode| draw_blendmode args, blendmode }
+end
diff --git a/samples/07_advanced_rendering/10_blend_modes/sprites/blue-feathered.png b/samples/07_advanced_rendering/10_blend_modes/sprites/blue-feathered.png
new file mode 100644
index 0000000..a8bf6b5
--- /dev/null
+++ b/samples/07_advanced_rendering/10_blend_modes/sprites/blue-feathered.png
Binary files differ
diff --git a/samples/07_advanced_rendering/11_render_target_noclear/app/main.rb b/samples/07_advanced_rendering/11_render_target_noclear/app/main.rb
new file mode 100644
index 0000000..9e5dffd
--- /dev/null
+++ b/samples/07_advanced_rendering/11_render_target_noclear/app/main.rb
@@ -0,0 +1,47 @@
+def tick args
+ args.state.x ||= 500
+ args.state.y ||= 350
+ args.state.xinc ||= 7
+ args.state.yinc ||= 7
+ args.state.bgcolor ||= 1
+ args.state.bginc ||= 1
+
+ # clear the render target on the first tick, and then never again. Draw
+ # another box to it every tick, accumulating over time.
+ clear_target = (args.state.tick_count == 0) || (args.inputs.keyboard.key_down.space)
+ args.render_target(:accumulation).background_color = [ 0, 0, 0, 0 ];
+ args.render_target(:accumulation).clear_before_render = clear_target
+ args.render_target(:accumulation).solids << [args.state.x, args.state.y, 25, 25, 255, 0, 0, 255];
+ args.state.x += args.state.xinc
+ args.state.y += args.state.yinc
+ args.state.bgcolor += args.state.bginc
+
+ # animation upkeep...change where we draw the next box and what color the
+ # window background will be.
+ if args.state.xinc > 0 && args.state.x >= 1280
+ args.state.xinc = -7
+ elsif args.state.xinc < 0 && args.state.x < 0
+ args.state.xinc = 7
+ end
+
+ if args.state.yinc > 0 && args.state.y >= 720
+ args.state.yinc = -7
+ elsif args.state.yinc < 0 && args.state.y < 0
+ args.state.yinc = 7
+ end
+
+ if args.state.bginc > 0 && args.state.bgcolor >= 255
+ args.state.bginc = -1
+ elsif args.state.bginc < 0 && args.state.bgcolor <= 0
+ args.state.bginc = 1
+ end
+
+ # clear the screen to a shade of blue and draw the render target, which
+ # is not clearing every frame, on top of it. Note that you can NOT opt to
+ # skip clearing the screen, only render targets. The screen clears every
+ # frame; double-buffering would prevent correct updates between frames.
+ args.outputs.background_color = [ 0, 0, args.state.bgcolor, 255 ]
+ args.outputs.sprites << [ 0, 0, 1280, 720, :accumulation ]
+end
+
+$gtk.reset
diff --git a/samples/07_advanced_rendering/11_render_target_noclear/metadata/game_metadata.txt b/samples/07_advanced_rendering/11_render_target_noclear/metadata/game_metadata.txt
new file mode 100644
index 0000000..3d0bd06
--- /dev/null
+++ b/samples/07_advanced_rendering/11_render_target_noclear/metadata/game_metadata.txt
@@ -0,0 +1,5 @@
+devid=dragonruby
+devtitle=DragonRuby LLC
+gameid=render_target_noclear
+gametitle=Render targets that don't clear every frame.
+version=1.0
diff --git a/samples/09_performance/01_sprites_as_hash/app/main.rb b/samples/09_performance/01_sprites_as_hash/app/main.rb
index 6bbb295..d032900 100644
--- a/samples/09_performance/01_sprites_as_hash/app/main.rb
+++ b/samples/09_performance/01_sprites_as_hash/app/main.rb
@@ -39,7 +39,11 @@ def tick args
# sets console command when sample app initially opens
if Kernel.global_tick_count == 0
- puts "* INFO - Please specify the number of sprites to render."
+ puts ""
+ puts ""
+ puts "========================================================="
+ puts "* INFO: Sprites, Hashes"
+ puts "* INFO: Please specify the number of sprites to render."
args.gtk.console.set_command "reset_with count: 100"
end
diff --git a/samples/09_performance/02_sprites_as_entities/app/main.rb b/samples/09_performance/02_sprites_as_entities/app/main.rb
index 21babda..dba02ae 100644
--- a/samples/09_performance/02_sprites_as_entities/app/main.rb
+++ b/samples/09_performance/02_sprites_as_entities/app/main.rb
@@ -39,7 +39,11 @@ def tick args
# sets console command when sample app initially opens
if Kernel.global_tick_count == 0
- puts "* INFO - Please specify the number of sprites to render."
+ puts ""
+ puts ""
+ puts "========================================================="
+ puts "* INFO: Sprites, Open Entities"
+ puts "* INFO: Please specify the number of sprites to render."
args.gtk.console.set_command "reset_with count: 100"
end
diff --git a/samples/09_performance/03_sprites_as_strict_entities/app/main.rb b/samples/09_performance/03_sprites_as_strict_entities/app/main.rb
index 376d9a1..a2688c2 100644
--- a/samples/09_performance/03_sprites_as_strict_entities/app/main.rb
+++ b/samples/09_performance/03_sprites_as_strict_entities/app/main.rb
@@ -43,7 +43,11 @@ def tick args
# sets console command when sample app initially opens
if Kernel.global_tick_count == 0
- puts "* INFO - Please specify the number of sprites to render."
+ puts ""
+ puts ""
+ puts "========================================================="
+ puts "* INFO: Sprites, Strict Entities"
+ puts "* INFO: Please specify the number of sprites to render."
args.gtk.console.set_command "reset_with count: 100"
end
diff --git a/samples/09_performance/03_sprites_as_struct/app/main.rb b/samples/09_performance/03_sprites_as_struct/app/main.rb
new file mode 100644
index 0000000..7b738b7
--- /dev/null
+++ b/samples/09_performance/03_sprites_as_struct/app/main.rb
@@ -0,0 +1,82 @@
+# create a Struct variant that allows for named parameters on construction.
+class NamedStruct < Struct
+ def initialize **opts
+ super(*members.map { |k| opts[k] })
+ end
+end
+
+# create a Star NamedStruct
+Star = NamedStruct.new(:x, :y, :w, :h, :path, :s,
+ :angle, :angle_anchor_x, :angle_anchor_y,
+ :r, :g, :b, :a,
+ :tile_x, :tile_y,
+ :tile_w, :tile_h,
+ :source_x, :source_y,
+ :source_w, :source_h,
+ :flip_horizontally, :flip_vertically,
+ :blendmode_enum)
+
+# Sprites represented as Structs. They require a little bit more code than Hashes,
+# but are the a little faster to render too.
+def random_x args
+ (args.grid.w.randomize :ratio) * -1
+end
+
+def random_y args
+ (args.grid.h.randomize :ratio) * -1
+end
+
+def random_speed
+ 1 + (4.randomize :ratio)
+end
+
+def new_star args
+ Star.new x: (random_x args),
+ y: (random_y args),
+ w: 4, h: 4,
+ path: 'sprites/tiny-star.png',
+ s: random_speed
+end
+
+def move_star args, star
+ star.x += star[:s]
+ star.y += star[:s]
+ if star.x > args.grid.w || star.y > args.grid.h
+ star.x = (random_x args)
+ star.y = (random_y args)
+ star[:s] = random_speed
+ end
+end
+
+def tick args
+ args.state.star_count ||= 0
+
+ # sets console command when sample app initially opens
+ if Kernel.global_tick_count == 0
+ puts ""
+ puts ""
+ puts "========================================================="
+ puts "* INFO: Sprites, Structs"
+ puts "* INFO: Please specify the number of sprites to render."
+ args.gtk.console.set_command "reset_with count: 100"
+ end
+
+ # init
+ if args.state.tick_count == 0
+ args.state.stars = args.state.star_count.map { |i| new_star args }
+ end
+
+ # update
+ args.state.stars.each { |s| move_star args, s }
+
+ # render
+ args.outputs.sprites << args.state.stars
+ args.outputs.background_color = [0, 0, 0]
+ args.outputs.primitives << args.gtk.current_framerate_primitives
+end
+
+# resets game, and assigns star count given by user
+def reset_with count: count
+ $gtk.reset
+ $gtk.args.state.star_count = count
+end
diff --git a/samples/09_performance/03_sprites_as_struct/license-for-sample.txt b/samples/09_performance/03_sprites_as_struct/license-for-sample.txt
new file mode 100644
index 0000000..175ac25
--- /dev/null
+++ b/samples/09_performance/03_sprites_as_struct/license-for-sample.txt
@@ -0,0 +1,9 @@
+Copyright 2021 DragonRuby LLC
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/samples/09_performance/03_sprites_as_struct/sprites/tiny-star.png b/samples/09_performance/03_sprites_as_struct/sprites/tiny-star.png
new file mode 100644
index 0000000..e04786a
--- /dev/null
+++ b/samples/09_performance/03_sprites_as_struct/sprites/tiny-star.png
Binary files differ
diff --git a/samples/09_performance/04_sprites_as_classes/app/main.rb b/samples/09_performance/04_sprites_as_classes/app/main.rb
index 2b43a98..67cde79 100644
--- a/samples/09_performance/04_sprites_as_classes/app/main.rb
+++ b/samples/09_performance/04_sprites_as_classes/app/main.rb
@@ -26,6 +26,11 @@ end
def tick args
# sets console command when sample app initially opens
if Kernel.global_tick_count == 0
+ puts ""
+ puts ""
+ puts "========================================================="
+ puts "* INFO: Sprites, Classes"
+ puts "* INFO: Please specify the number of sprites to render."
args.gtk.console.set_command "reset_with count: 100"
end
diff --git a/samples/09_performance/04_sprites_as_strict_entities/app/main.rb b/samples/09_performance/04_sprites_as_strict_entities/app/main.rb
new file mode 100644
index 0000000..a2688c2
--- /dev/null
+++ b/samples/09_performance/04_sprites_as_strict_entities/app/main.rb
@@ -0,0 +1,72 @@
+# Sprites represented as StrictEntities using the queue ~args.outputs.sprites~
+# yields apis access similar to Entities, but all properties that can be set on the
+# entity must be predefined with a default value. Strict entities do not support the
+# addition of new properties after the fact. They are more performant than OpenEntities
+# because of this constraint.
+def random_x args
+ (args.grid.w.randomize :ratio) * -1
+end
+
+def random_y args
+ (args.grid.h.randomize :ratio) * -1
+end
+
+def random_speed
+ 1 + (4.randomize :ratio)
+end
+
+def new_star args
+ args.state.new_entity_strict(:star,
+ x: (random_x args),
+ y: (random_y args),
+ w: 4, h: 4,
+ path: 'sprites/tiny-star.png',
+ s: random_speed) do |entity|
+ # invoke attr_sprite so that it responds to
+ # all properties that are required to render a sprite
+ entity.attr_sprite
+ end
+end
+
+def move_star args, star
+ star.x += star.s
+ star.y += star.s
+ if star.x > args.grid.w || star.y > args.grid.h
+ star.x = (random_x args)
+ star.y = (random_y args)
+ star.s = random_speed
+ end
+end
+
+def tick args
+ args.state.star_count ||= 0
+
+ # sets console command when sample app initially opens
+ if Kernel.global_tick_count == 0
+ puts ""
+ puts ""
+ puts "========================================================="
+ puts "* INFO: Sprites, Strict Entities"
+ puts "* INFO: Please specify the number of sprites to render."
+ args.gtk.console.set_command "reset_with count: 100"
+ end
+
+ # init
+ if args.state.tick_count == 0
+ args.state.stars = args.state.star_count.map { |i| new_star args }
+ end
+
+ # update
+ args.state.stars.each { |s| move_star args, s }
+
+ # render
+ args.outputs.sprites << args.state.stars
+ args.outputs.background_color = [0, 0, 0]
+ args.outputs.primitives << args.gtk.current_framerate_primitives
+end
+
+# resets game, and assigns star count given by user
+def reset_with count: count
+ $gtk.reset
+ $gtk.args.state.star_count = count
+end
diff --git a/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/license-for-sample.txt b/samples/09_performance/04_sprites_as_strict_entities/license-for-sample.txt
index 100dcec..100dcec 100644
--- a/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/license-for-sample.txt
+++ b/samples/09_performance/04_sprites_as_strict_entities/license-for-sample.txt
diff --git a/samples/09_performance/04_sprites_as_strict_entities/sprites/tiny-star.png b/samples/09_performance/04_sprites_as_strict_entities/sprites/tiny-star.png
new file mode 100644
index 0000000..e04786a
--- /dev/null
+++ b/samples/09_performance/04_sprites_as_strict_entities/sprites/tiny-star.png
Binary files differ
diff --git a/samples/09_performance/05_sprites_as_classes/app/main.rb b/samples/09_performance/05_sprites_as_classes/app/main.rb
new file mode 100644
index 0000000..67cde79
--- /dev/null
+++ b/samples/09_performance/05_sprites_as_classes/app/main.rb
@@ -0,0 +1,55 @@
+# Sprites represented as Classes using the queue ~args.outputs.sprites~.
+# gives you full control of property declaration and method invocation.
+# They are more performant than OpenEntities and StrictEntities, but more code upfront.
+class Star
+ attr_sprite
+
+ def initialize grid
+ @grid = grid
+ @x = (rand @grid.w) * -1
+ @y = (rand @grid.h) * -1
+ @w = 4
+ @h = 4
+ @s = 1 + (4.randomize :ratio)
+ @path = 'sprites/tiny-star.png'
+ end
+
+ def move
+ @x += @s
+ @y += @s
+ @x = (rand @grid.w) * -1 if @x > @grid.right
+ @y = (rand @grid.h) * -1 if @y > @grid.top
+ end
+end
+
+# calls methods needed for game to run properly
+def tick args
+ # sets console command when sample app initially opens
+ if Kernel.global_tick_count == 0
+ puts ""
+ puts ""
+ puts "========================================================="
+ puts "* INFO: Sprites, Classes"
+ puts "* INFO: Please specify the number of sprites to render."
+ args.gtk.console.set_command "reset_with count: 100"
+ end
+
+ # init
+ if args.state.tick_count == 0
+ args.state.stars = args.state.star_count.map { |i| Star.new args.grid }
+ end
+
+ # update
+ args.state.stars.each(&:move)
+
+ # render
+ args.outputs.sprites << args.state.stars
+ args.outputs.background_color = [0, 0, 0]
+ args.outputs.primitives << args.gtk.current_framerate_primitives
+end
+
+# resets game, and assigns star count given by user
+def reset_with count: count
+ $gtk.reset
+ $gtk.args.state.star_count = count
+end
diff --git a/samples/99_genre_rpg_roguelike/roguelike_starting_point/license-for-sample.txt b/samples/09_performance/05_sprites_as_classes/license-for-sample.txt
index 100dcec..100dcec 100644
--- a/samples/99_genre_rpg_roguelike/roguelike_starting_point/license-for-sample.txt
+++ b/samples/09_performance/05_sprites_as_classes/license-for-sample.txt
diff --git a/samples/09_performance/05_sprites_as_classes/sprites/tiny-star.png b/samples/09_performance/05_sprites_as_classes/sprites/tiny-star.png
new file mode 100644
index 0000000..e04786a
--- /dev/null
+++ b/samples/09_performance/05_sprites_as_classes/sprites/tiny-star.png
Binary files differ
diff --git a/samples/09_performance/05_static_sprites_as_classes/app/main.rb b/samples/09_performance/05_static_sprites_as_classes/app/main.rb
index cbfe00a..db5bf8e 100644
--- a/samples/09_performance/05_static_sprites_as_classes/app/main.rb
+++ b/samples/09_performance/05_static_sprites_as_classes/app/main.rb
@@ -27,19 +27,24 @@ end
def tick args
# sets console command when sample app initially opens
if Kernel.global_tick_count == 0
+ puts ""
+ puts ""
+ puts "========================================================="
+ puts "* INFO: Static Sprites, Classes"
+ puts "* INFO: Please specify the number of sprites to render."
args.gtk.console.set_command "reset_with count: 100"
end
# init
if args.state.tick_count == 0
args.state.stars = args.state.star_count.map { |i| Star.new args.grid }
+ args.outputs.static_sprites << args.state.stars
end
# update
args.state.stars.each(&:move)
# render
- args.outputs.sprites << args.state.stars
args.outputs.background_color = [0, 0, 0]
args.outputs.primitives << args.gtk.current_framerate_primitives
end
diff --git a/samples/09_performance/06_static_sprites_as_classes/app/main.rb b/samples/09_performance/06_static_sprites_as_classes/app/main.rb
new file mode 100644
index 0000000..db5bf8e
--- /dev/null
+++ b/samples/09_performance/06_static_sprites_as_classes/app/main.rb
@@ -0,0 +1,56 @@
+# Sprites represented as Classes using the queue ~args.outputs.static_sprites~.
+# bypasses the queue behavior of ~args.outputs.sprites~. All instances are held
+# by reference. You get better performance, but you are mutating state of held objects
+# which is less functional/data oriented.
+class Star
+ attr_sprite
+
+ def initialize grid
+ @grid = grid
+ @x = (rand @grid.w) * -1
+ @y = (rand @grid.h) * -1
+ @w = 4
+ @h = 4
+ @s = 1 + (4.randomize :ratio)
+ @path = 'sprites/tiny-star.png'
+ end
+
+ def move
+ @x += @s
+ @y += @s
+ @x = (rand @grid.w) * -1 if @x > @grid.right
+ @y = (rand @grid.h) * -1 if @y > @grid.top
+ end
+end
+
+# calls methods needed for game to run properly
+def tick args
+ # sets console command when sample app initially opens
+ if Kernel.global_tick_count == 0
+ puts ""
+ puts ""
+ puts "========================================================="
+ puts "* INFO: Static Sprites, Classes"
+ puts "* INFO: Please specify the number of sprites to render."
+ args.gtk.console.set_command "reset_with count: 100"
+ end
+
+ # init
+ if args.state.tick_count == 0
+ args.state.stars = args.state.star_count.map { |i| Star.new args.grid }
+ args.outputs.static_sprites << args.state.stars
+ end
+
+ # update
+ args.state.stars.each(&:move)
+
+ # render
+ args.outputs.background_color = [0, 0, 0]
+ args.outputs.primitives << args.gtk.current_framerate_primitives
+end
+
+# resets game, and assigns star count given by user
+def reset_with count: count
+ $gtk.reset
+ $gtk.args.state.star_count = count
+end
diff --git a/samples/09_performance/06_static_sprites_as_classes/license-for-sample.txt b/samples/09_performance/06_static_sprites_as_classes/license-for-sample.txt
new file mode 100644
index 0000000..100dcec
--- /dev/null
+++ b/samples/09_performance/06_static_sprites_as_classes/license-for-sample.txt
@@ -0,0 +1,9 @@
+Copyright 2019 DragonRuby LLC
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/samples/09_performance/06_static_sprites_as_classes/sprites/tiny-star.png b/samples/09_performance/06_static_sprites_as_classes/sprites/tiny-star.png
new file mode 100644
index 0000000..e04786a
--- /dev/null
+++ b/samples/09_performance/06_static_sprites_as_classes/sprites/tiny-star.png
Binary files differ
diff --git a/samples/09_performance/06_static_sprites_as_classes_with_custom_drawing/app/main.rb b/samples/09_performance/06_static_sprites_as_classes_with_custom_drawing/app/main.rb
index 4d8719d..3291f5e 100644
--- a/samples/09_performance/06_static_sprites_as_classes_with_custom_drawing/app/main.rb
+++ b/samples/09_performance/06_static_sprites_as_classes_with_custom_drawing/app/main.rb
@@ -39,11 +39,22 @@ class Star
# x, y, w, h,
# path,
# angle,
- # alpha, red_saturation, green_saturation, blue_saturation,
+ # alpha, red_saturation, green_saturation, blue_saturation
# tile_x, tile_y, tile_w, tile_h,
# flip_horizontally, flip_vertically,
# angle_anchor_x, angle_anchor_y,
# source_x, source_y, source_w, source_h
+
+ # The argument order for ffi_draw.draw_sprite_4 is:
+ # x, y, w, h,
+ # path,
+ # angle,
+ # alpha, red_saturation, green_saturation, blue_saturation
+ # tile_x, tile_y, tile_w, tile_h,
+ # flip_horizontally, flip_vertically,
+ # angle_anchor_x, angle_anchor_y,
+ # source_x, source_y, source_w, source_h,
+ # blendmode_enum
end
end
@@ -51,6 +62,11 @@ end
def tick args
# sets console command when sample app initially opens
if Kernel.global_tick_count == 0
+ puts ""
+ puts ""
+ puts "========================================================="
+ puts "* INFO: Static Sprites, Classes, Draw Override"
+ puts "* INFO: Please specify the number of sprites to render."
args.gtk.console.set_command "reset_with count: 100"
end
diff --git a/samples/09_performance/07_collision_limits/app/main.rb b/samples/09_performance/07_collision_limits/app/main.rb
index 4a7945c..01ad308 100644
--- a/samples/09_performance/07_collision_limits/app/main.rb
+++ b/samples/09_performance/07_collision_limits/app/main.rb
@@ -6,9 +6,11 @@
- args.outputs.solids: An array. The values generate a solid.
The parameters are [X, Y, WIDTH, HEIGHT, RED, GREEN, BLUE]
+ For more information about solids, go to mygame/documentation/03-solids-and-borders.md.
- args.outputs.labels: An array. The values generate a label.
The parameters are [X, Y, TEXT, SIZE, ALIGNMENT, RED, GREEN, BLUE, ALPHA, FONT STYLE]
+ For more information about labels, go to mygame/documentation/02-labels.md.
- ARRAY#intersect_rect?: Returns true or false depending on if two rectangles intersect.
diff --git a/samples/09_performance/07_static_sprites_as_classes_with_custom_drawing/app/main.rb b/samples/09_performance/07_static_sprites_as_classes_with_custom_drawing/app/main.rb
new file mode 100644
index 0000000..3291f5e
--- /dev/null
+++ b/samples/09_performance/07_static_sprites_as_classes_with_custom_drawing/app/main.rb
@@ -0,0 +1,88 @@
+# Sprites represented as Classes, with a draw_override method, and using the queue ~args.outputs.static_sprites~.
+# is the fastest approach. This is comparable to what other game engines set as the default behavior.
+# There are tradeoffs for all this speed if the creation of a full blown class, and bypassing
+# functional/data-oriented practices.
+class Star
+ def initialize grid
+ @grid = grid
+ @x = (rand @grid.w) * -1
+ @y = (rand @grid.h) * -1
+ @w = 4
+ @h = 4
+ @s = 1 + (4.randomize :ratio)
+ @path = 'sprites/tiny-star.png'
+ end
+
+ def move
+ @x += @s
+ @y += @s
+ @x = (rand @grid.w) * -1 if @x > @grid.right
+ @y = (rand @grid.h) * -1 if @y > @grid.top
+ end
+
+ # if the object that is in args.outputs.sprites (or static_sprites)
+ # respond_to? :draw_override, then the method is invoked giving you
+ # access to the class used to draw to the canvas.
+ def draw_override ffi_draw
+ # first move then draw
+ move
+
+ # The argument order for ffi.draw_sprite is:
+ # x, y, w, h, path
+ ffi_draw.draw_sprite @x, @y, @w, @h, @path
+
+ # The argument order for ffi_draw.draw_sprite_2 is (pass in nil for default value):
+ # x, y, w, h, path,
+ # angle, alpha
+
+ # The argument order for ffi_draw.draw_sprite_3 is:
+ # x, y, w, h,
+ # path,
+ # angle,
+ # alpha, red_saturation, green_saturation, blue_saturation
+ # tile_x, tile_y, tile_w, tile_h,
+ # flip_horizontally, flip_vertically,
+ # angle_anchor_x, angle_anchor_y,
+ # source_x, source_y, source_w, source_h
+
+ # The argument order for ffi_draw.draw_sprite_4 is:
+ # x, y, w, h,
+ # path,
+ # angle,
+ # alpha, red_saturation, green_saturation, blue_saturation
+ # tile_x, tile_y, tile_w, tile_h,
+ # flip_horizontally, flip_vertically,
+ # angle_anchor_x, angle_anchor_y,
+ # source_x, source_y, source_w, source_h,
+ # blendmode_enum
+ end
+end
+
+# calls methods needed for game to run properly
+def tick args
+ # sets console command when sample app initially opens
+ if Kernel.global_tick_count == 0
+ puts ""
+ puts ""
+ puts "========================================================="
+ puts "* INFO: Static Sprites, Classes, Draw Override"
+ puts "* INFO: Please specify the number of sprites to render."
+ args.gtk.console.set_command "reset_with count: 100"
+ end
+
+ # init
+ if args.state.tick_count == 0
+ args.state.stars = args.state.star_count.map { |i| Star.new args.grid }
+ args.outputs.static_sprites << args.state.stars
+ end
+
+ # render framerate
+ args.outputs.background_color = [0, 0, 0]
+ args.outputs.primitives << args.gtk.current_framerate_primitives
+end
+
+# resets game, and assigns star count given by user
+def reset_with count: count
+ $gtk.reset
+ $gtk.args.state.star_count = count
+end
diff --git a/samples/09_performance/07_static_sprites_as_classes_with_custom_drawing/license-for-sample.txt b/samples/09_performance/07_static_sprites_as_classes_with_custom_drawing/license-for-sample.txt
new file mode 100644
index 0000000..100dcec
--- /dev/null
+++ b/samples/09_performance/07_static_sprites_as_classes_with_custom_drawing/license-for-sample.txt
@@ -0,0 +1,9 @@
+Copyright 2019 DragonRuby LLC
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/samples/09_performance/07_static_sprites_as_classes_with_custom_drawing/sprites/tiny-star.png b/samples/09_performance/07_static_sprites_as_classes_with_custom_drawing/sprites/tiny-star.png
new file mode 100644
index 0000000..e04786a
--- /dev/null
+++ b/samples/09_performance/07_static_sprites_as_classes_with_custom_drawing/sprites/tiny-star.png
Binary files differ
diff --git a/samples/09_performance/08_collision_limits/app/main.rb b/samples/09_performance/08_collision_limits/app/main.rb
new file mode 100644
index 0000000..01ad308
--- /dev/null
+++ b/samples/09_performance/08_collision_limits/app/main.rb
@@ -0,0 +1,55 @@
+=begin
+
+ Reminders:
+ - find_all: Finds all elements of a collection that meet certain requirements.
+ In this sample app, we're finding all bodies that intersect with the center body.
+
+ - args.outputs.solids: An array. The values generate a solid.
+ The parameters are [X, Y, WIDTH, HEIGHT, RED, GREEN, BLUE]
+ For more information about solids, go to mygame/documentation/03-solids-and-borders.md.
+
+ - args.outputs.labels: An array. The values generate a label.
+ The parameters are [X, Y, TEXT, SIZE, ALIGNMENT, RED, GREEN, BLUE, ALPHA, FONT STYLE]
+ For more information about labels, go to mygame/documentation/02-labels.md.
+
+ - ARRAY#intersect_rect?: Returns true or false depending on if two rectangles intersect.
+
+=end
+
+# This code demonstrates moving objects that loop around once they exceed the scope of the screen,
+# which has dimensions of 1280 by 720, and also detects collisions between objects called "bodies".
+
+def body_count num
+ $gtk.args.state.other_bodies = num.map { [1280 * rand, 720 * rand, 10, 10] } # other_bodies set using num collection
+end
+
+def tick args
+
+ # Center body's values are set using an array
+ # Map is used to set values of 2000 other bodies
+ # All bodies that intersect with center body are stored in collisions collection
+ args.state.center_body ||= [640 - 100, 360 - 100, 200, 200] # calculations done to place body in center
+ args.state.other_bodies ||= 2000.map { [1280 * rand, 720 * rand, 10, 10] } # 2000 bodies given random position on screen
+
+ # finds all bodies that intersect with center body, stores them in collisions
+ collisions = args.state.other_bodies.find_all { |b| b.intersect_rect? args.state.center_body }
+
+ args.borders << args.state.center_body # outputs center body as a black border
+
+ # transparency changes based on number of collisions; the more collisions, the redder (more transparent) the box becomes
+ args.solids << [args.state.center_body, 255, 0, 0, collisions.length * 5] # center body is red solid
+ args.solids << args.state.other_bodies # other bodies are output as (black) solids, as well
+
+ args.labels << [10, 30, args.gtk.current_framerate] # outputs frame rate in bottom left corner
+
+ # Bodies are returned to bottom left corner if positions exceed scope of screen
+ args.state.other_bodies.each do |b| # for each body in the other_bodies collection
+ b.x += 5 # x and y are both incremented by 5
+ b.y += 5
+ b.x = 0 if b.x > 1280 # x becomes 0 if star exceeds scope of screen (goes too far right)
+ b.y = 0 if b.y > 720 # y becomes 0 if star exceeds scope of screen (goes too far up)
+ end
+end
+
+# Resets the game.
+$gtk.reset
diff --git a/samples/09_performance/08_collision_limits/license-for-sample.txt b/samples/09_performance/08_collision_limits/license-for-sample.txt
new file mode 100644
index 0000000..100dcec
--- /dev/null
+++ b/samples/09_performance/08_collision_limits/license-for-sample.txt
@@ -0,0 +1,9 @@
+Copyright 2019 DragonRuby LLC
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/samples/10_advanced_debugging/00_logging/app/main.rb b/samples/10_advanced_debugging/00_logging/app/main.rb
new file mode 100644
index 0000000..f97b9d8
--- /dev/null
+++ b/samples/10_advanced_debugging/00_logging/app/main.rb
@@ -0,0 +1,19 @@
+def tick args
+ args.outputs.background_color = [255, 255, 255, 0]
+ if args.state.tick_count == 0
+ args.gtk.log_spam "log level spam"
+ args.gtk.log_debug "log level debug"
+ args.gtk.log_info "log level info"
+ args.gtk.log_warn "log level warn"
+ args.gtk.log_error "log level error"
+ args.gtk.log_unfiltered "log level unfiltered"
+ puts "This is a puts call"
+ args.gtk.console.show
+ end
+
+ if args.state.tick_count == 60
+ puts "This is a puts call on tick 60"
+ elsif args.state.tick_count == 120
+ puts "This is a puts call on tick 120"
+ end
+end
diff --git a/samples/10_advanced_debugging/03_unit_tests/benchmark_api_tests.rb b/samples/10_advanced_debugging/03_unit_tests/benchmark_api_tests.rb
new file mode 100644
index 0000000..2c06f1a
--- /dev/null
+++ b/samples/10_advanced_debugging/03_unit_tests/benchmark_api_tests.rb
@@ -0,0 +1,43 @@
+def test_benchmark_api args, assert
+ result = args.gtk.benchmark iterations: 100,
+ only_one: -> () {
+ r = 0
+ (1..100).each do |i|
+ r += 1
+ end
+ }
+
+ assert.equal! result.first_place.name, :only_one
+
+ result = args.gtk.benchmark iterations: 100,
+ iterations_100: -> () {
+ r = 0
+ (1..100).each do |i|
+ r += 1
+ end
+ },
+ iterations_50: -> () {
+ r = 0
+ (1..50).each do |i|
+ r += 1
+ end
+ }
+
+ assert.equal! result.first_place.name, :iterations_50
+
+ result = args.gtk.benchmark iterations: 1,
+ iterations_100: -> () {
+ r = 0
+ (1..100).each do |i|
+ r += 1
+ end
+ },
+ iterations_50: -> () {
+ r = 0
+ (1..50).each do |i|
+ r += 1
+ end
+ }
+
+ assert.equal! result.too_small_to_measure, true
+end
diff --git a/samples/10_advanced_debugging/03_unit_tests/pretty_format_tests.rb b/samples/10_advanced_debugging/03_unit_tests/pretty_format_tests.rb
new file mode 100644
index 0000000..6ac7b05
--- /dev/null
+++ b/samples/10_advanced_debugging/03_unit_tests/pretty_format_tests.rb
@@ -0,0 +1,130 @@
+def H opts
+ opts
+end
+
+def A *opts
+ opts
+end
+
+def assert_format args, assert, hash, expected
+ actual = args.fn.pretty_format hash
+ assert.are_equal! actual, expected
+end
+
+def test_pretty_print args, assert
+ # =============================
+ # hash with single value
+ # =============================
+ input = (H first_name: "John")
+ expected = <<-S
+{:first_name "John"}
+S
+ (assert_format args, assert, input, expected)
+
+ # =============================
+ # hash with two values
+ # =============================
+ input = (H first_name: "John", last_name: "Smith")
+ expected = <<-S
+{:first_name "John"
+ :last_name "Smith"}
+S
+
+ (assert_format args, assert, input, expected)
+
+ # =============================
+ # hash with inner hash
+ # =============================
+ input = (H first_name: "John",
+ last_name: "Smith",
+ middle_initial: "I",
+ so: (H first_name: "Pocahontas",
+ last_name: "Tsenacommacah"),
+ friends: (A (H first_name: "Side", last_name: "Kick"),
+ (H first_name: "Tim", last_name: "Wizard")))
+ expected = <<-S
+{:first_name "John"
+ :last_name "Smith"
+ :middle_initial "I"
+ :so {:first_name "Pocahontas"
+ :last_name "Tsenacommacah"}
+ :friends [{:first_name "Side"
+ :last_name "Kick"}
+ {:first_name "Tim"
+ :last_name "Wizard"}]}
+S
+
+ (assert_format args, assert, input, expected)
+
+ # =============================
+ # array with one value
+ # =============================
+ input = (A 1)
+ expected = <<-S
+[1]
+S
+ (assert_format args, assert, input, expected)
+
+ # =============================
+ # array with multiple values
+ # =============================
+ input = (A 1, 2, 3)
+ expected = <<-S
+[1
+ 2
+ 3]
+S
+ (assert_format args, assert, input, expected)
+
+ # =============================
+ # array with multiple values hashes
+ # =============================
+ input = (A (H first_name: "Side", last_name: "Kick"),
+ (H first_name: "Tim", last_name: "Wizard"))
+ expected = <<-S
+[{:first_name "Side"
+ :last_name "Kick"}
+ {:first_name "Tim"
+ :last_name "Wizard"}]
+S
+
+ (assert_format args, assert, input, expected)
+end
+
+def test_nested_nested args, assert
+ # =============================
+ # nested array in nested hash
+ # =============================
+ input = (H type: :root,
+ text: "Root",
+ children: (A (H level: 1,
+ text: "Level 1",
+ children: (A (H level: 2,
+ text: "Level 2",
+ children: [])))))
+
+ expected = <<-S
+{:type :root
+ :text "Root"
+ :children [{:level 1
+ :text "Level 1"
+ :children [{:level 2
+ :text "Level 2"
+ :children []}]}]}
+
+S
+
+ (assert_format args, assert, input, expected)
+end
+
+def test_scene args, assert
+ script = <<-S
+* Scene 1
+** Narrator
+They say happy endings don't exist.
+** Narrator
+They say true love is a lie.
+S
+ input = parse_org args, script
+ puts (args.fn.pretty_format input)
+end
diff --git a/samples/10_advanced_debugging/03_unit_tests/run-bash.sh b/samples/10_advanced_debugging/03_unit_tests/run-bash.sh
deleted file mode 100644
index 005077b..0000000
--- a/samples/10_advanced_debugging/03_unit_tests/run-bash.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-sh ./amir-build-and-run.sh --eval samples/99_zz_gtk_unit_tests/geometry_tests.rb --no-tick
-sh ./amir-build-and-run.sh --eval samples/99_zz_gtk_unit_tests/parsing_tests.rb --no-tick
-sh ./amir-build-and-run.sh --eval samples/99_zz_gtk_unit_tests/http_tests.rb --no-tick
-sh ./amir-build-and-run.sh --eval samples/99_zz_gtk_unit_tests/array_to_primitive_tests.rb --no-tick
diff --git a/samples/10_advanced_debugging/03_unit_tests/run-tests.sh b/samples/10_advanced_debugging/03_unit_tests/run-tests.sh
index e551edf..d8b1a4a 100644
--- a/samples/10_advanced_debugging/03_unit_tests/run-tests.sh
+++ b/samples/10_advanced_debugging/03_unit_tests/run-tests.sh
@@ -1,10 +1,17 @@
-./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/require_tests.rb
-./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/gen_docs.rb
-./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/geometry_tests.rb
-./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/http_tests.rb
-./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/object_to_primitive_tests.rb
-./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/parsing_tests.rb
-./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/require_tests.rb
-./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/serialize_deserialize_tests.rb
-./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/state_serialization_experimental_tests.rb
-./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/suggest_autocompletion_tests.rb
+# fswatch ./samples/10_advanced_debugging/03_unit_tests/benchmark_api_tests.rb | xargs -n1 -I{} sh ./samples/10_advanced_debugging/03_unit_tests/run-tests.sh
+# set -e
+# rake
+# ./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/require_tests.rb
+# ./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/gen_docs.rb
+# ./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/geometry_tests.rb
+# ./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/http_tests.rb
+# ./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/object_to_primitive_tests.rb
+# ./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/parsing_tests.rb
+# ./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/require_tests.rb
+# ./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/serialize_deserialize_tests.rb
+# ./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/state_serialization_experimental_tests.rb
+# ./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/suggest_autocompletion_tests.rb
+# ./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/nil_coercion_tests.rb
+# ./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/fn_tests.rb
+# ./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/pretty_format_test.rb
+./dragonruby mygame --test samples/10_advanced_debugging/03_unit_tests/benchmark_api_tests.rb
diff --git a/samples/10_advanced_debugging/03_unit_tests/serialize_deserialize_tests.rb b/samples/10_advanced_debugging/03_unit_tests/serialize_deserialize_tests.rb
index 8505bdf..12c08f6 100644
--- a/samples/10_advanced_debugging/03_unit_tests/serialize_deserialize_tests.rb
+++ b/samples/10_advanced_debugging/03_unit_tests/serialize_deserialize_tests.rb
@@ -2,12 +2,12 @@ def test_serialize args, assert
GTK::Entity.__reset_id__!
args.state.player_one = "test"
result = args.gtk.serialize_state args.state
- assert.equal! result, "{:entity_id=>3, :entity_keys_by_ref=>{}, :tick_count=>-1, :player_one=>\"test\"}"
+ assert.equal! result, "{:entity_id=>4, :entity_keys_by_ref=>{}, :tick_count=>-1, :player_one=>\"test\"}"
GTK::Entity.__reset_id__!
args.gtk.write_file 'state.txt', ''
result = args.gtk.serialize_state 'state.txt', args.state
- assert.equal! result, "{:entity_id=>3, :entity_keys_by_ref=>{}, :tick_count=>-1, :player_one=>\"test\"}"
+ assert.equal! result, "{:entity_id=>4, :entity_keys_by_ref=>{}, :tick_count=>-1, :player_one=>\"test\"}"
end
def test_deserialize args, assert
@@ -56,7 +56,7 @@ def test_strict_entity_serialization_with_nil args, assert
args.state.player_two = args.state.new_entity_strict(:player_strict, name: "Ken", blood_type: nil)
serialized_state = args.gtk.serialize_state args.state
- assert.equal! serialized_state, '{:entity_id=>9, :entity_keys_by_ref=>{}, :tick_count=>-1, :player_one=>{:entity_id=>1, :entity_name=>:player, :entity_keys_by_ref=>{}, :entity_type=>:player, :created_at=>-1, :global_created_at=>-1, :name=>"Ryu"}, :player_two=>{:entity_id=>2, :entity_name=>:player_strict, :entity_type=>:player_strict, :created_at=>-1, :global_created_at_elapsed=>-1, :entity_strict=>true, :entity_keys_by_ref=>{:entity_type=>:entity_name, :global_created_at_elapsed=>:created_at}, :name=>"Ken", :blood_type=>nil}}'
+ assert.equal! serialized_state, '{:entity_id=>7, :entity_keys_by_ref=>{}, :tick_count=>-1, :player_one=>{:entity_id=>1, :entity_name=>:player, :entity_keys_by_ref=>{}, :entity_type=>:player, :created_at=>-1, :global_created_at=>-1, :name=>"Ryu"}, :player_two=>{:entity_id=>2, :entity_name=>:player_strict, :entity_type=>:player_strict, :created_at=>-1, :global_created_at_elapsed=>-1, :entity_strict=>true, :entity_keys_by_ref=>{:entity_type=>:entity_name, :global_created_at_elapsed=>:created_at}, :name=>"Ken", :blood_type=>nil}}'
GTK::Entity.__reset_id__!
deserialized_state = args.gtk.deserialize_state serialized_state
@@ -113,3 +113,15 @@ def test_by_reference_state_strict_entities args, assert
deserialized_state = args.gtk.deserialize_state serialized_state
assert.equal! deserialized_state.strict_entity.one, deserialized_state.strict_entity.two
end
+
+def test_serialization_excludes_thrash_count args, assert
+ GTK::Entity.__reset_id__!
+ args.state.player.name = "Ryu"
+ # force a nil pun
+ if args.state.player.age > 30
+ end
+ assert.equal! args.state.player.as_hash[:__thrash_count__][:>], 1
+ result = args.gtk.serialize_state args.state
+ assert.false! (result.include? "__thrash_count__"),
+ "The __thrash_count__ key exists in state when it shouldn't have."
+end
diff --git a/samples/11_http/01_retrieve_images/app/main.rb b/samples/11_http/01_retrieve_images/app/main.rb
index 53ece84..2a6a294 100644
--- a/samples/11_http/01_retrieve_images/app/main.rb
+++ b/samples/11_http/01_retrieve_images/app/main.rb
@@ -1,8 +1,10 @@
+$gtk.register_cvar 'app.warn_seconds', "seconds to wait before starting", :uint, 11
+
def tick args
args.outputs.background_color = [0, 0, 0]
# Show a warning at the start.
- args.state.warning_debounce ||= 11 * 60
+ args.state.warning_debounce ||= args.cvars['app.warn_seconds'].value * 60
if args.state.warning_debounce > 0
args.state.warning_debounce -= 1
args.outputs.labels << [640, 600, "This app shows random images from the Internet.", 10, 1, 255, 255, 255]
diff --git a/samples/11_http/02_in_game_web_server_http_get/app/main.rb b/samples/11_http/02_in_game_web_server_http_get/app/main.rb
new file mode 100644
index 0000000..7fd67f7
--- /dev/null
+++ b/samples/11_http/02_in_game_web_server_http_get/app/main.rb
@@ -0,0 +1,28 @@
+def tick args
+ args.state.port ||= 3000
+ args.state.reqnum ||= 0
+ # by default the embedded webserver runs on port 9001 (the port number is over 9000) and is disabled in a production build
+ # to enable the http server in a production build, you need to manually start
+ # the server up:
+ args.gtk.start_server! port: args.state.port, enable_in_prod: true
+ args.outputs.background_color = [0, 0, 0]
+ args.outputs.labels << [640, 600, "Point your web browser at http://localhost:#{args.state.port}/", 10, 1, 255, 255, 255]
+
+ args.inputs.http_requests.each { |req|
+ puts("METHOD: #{req.method}");
+ puts("URI: #{req.uri}");
+ puts("HEADERS:");
+ req.headers.each { |k,v| puts(" #{k}: #{v}") }
+
+ if (req.uri == '/')
+ # headers and body can be nil if you don't care about them.
+ # If you don't set the Content-Type, it will default to
+ # "text/html; charset=utf-8".
+ # Don't set Content-Length; we'll ignore it and calculate it for you
+ args.state.reqnum += 1
+ req.respond 200, "<html><head><title>hello</title></head><body><h1>This #{req.method} was request number #{args.state.reqnum}!</h1></body></html>\n", { 'X-DRGTK-header' => 'Powered by DragonRuby!' }
+ else
+ req.reject
+ end
+ }
+end
diff --git a/samples/11_http/02_in_game_web_server_http_get/license-for-sample.txt b/samples/11_http/02_in_game_web_server_http_get/license-for-sample.txt
new file mode 100644
index 0000000..175ac25
--- /dev/null
+++ b/samples/11_http/02_in_game_web_server_http_get/license-for-sample.txt
@@ -0,0 +1,9 @@
+Copyright 2021 DragonRuby LLC
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/samples/11_http/03_in_game_web_server_http_post/app/main.rb b/samples/11_http/03_in_game_web_server_http_post/app/main.rb
new file mode 100644
index 0000000..8116358
--- /dev/null
+++ b/samples/11_http/03_in_game_web_server_http_post/app/main.rb
@@ -0,0 +1,72 @@
+def tick args
+ # defaults
+ args.state.post_button = args.layout.rect(row: 0, col: 0, w: 5, h: 1).merge(text: "execute http_post")
+ args.state.post_body_button = args.layout.rect(row: 1, col: 0, w: 5, h: 1).merge(text: "execute http_post_body")
+ args.state.request_to_s ||= ""
+ args.state.request_body ||= ""
+
+ # render
+ args.state.post_button.yield_self do |b|
+ args.outputs.borders << b
+ args.outputs.labels << b.merge(text: b.text,
+ y: b.y + 30,
+ x: b.x + 10)
+ end
+
+ args.state.post_body_button.yield_self do |b|
+ args.outputs.borders << b
+ args.outputs.labels << b.merge(text: b.text,
+ y: b.y + 30,
+ x: b.x + 10)
+ end
+
+ draw_label args, 0, 6, "Request:", args.state.request_to_s
+ draw_label args, 0, 14, "Request Body Unaltered:", args.state.request_body
+
+ # input
+ if args.inputs.mouse.click
+ # ============= HTTP_POST =============
+ if (args.inputs.mouse.inside_rect? args.state.post_button)
+ # ========= DATA TO SEND ===========
+ form_fields = { "userId" => "#{Time.now.to_i}" }
+ # ==================================
+
+ args.gtk.http_post "http://localhost:9001/testing",
+ form_fields,
+ ["Content-Type: application/x-www-form-urlencoded"]
+
+ args.gtk.notify! "http_post"
+ end
+
+ # ============= HTTP_POST_BODY =============
+ if (args.inputs.mouse.inside_rect? args.state.post_body_button)
+ # =========== DATA TO SEND ==============
+ json = "{ \"userId\": \"#{Time.now.to_i}\"}"
+ # ==================================
+
+ args.gtk.http_post_body "http://localhost:9001/testing",
+ json,
+ ["Content-Type: application/json", "Content-Length: #{json.length}"]
+
+ args.gtk.notify! "http_post_body"
+ end
+ end
+
+ # calc
+ args.inputs.http_requests.each do |r|
+ puts "#{r}"
+ if r.uri == "/testing"
+ puts r
+ args.state.request_to_s = "#{r}"
+ args.state.request_body = r.raw_body
+ r.respond 200, "ok"
+ end
+ end
+end
+
+def draw_label args, row, col, header, text
+ label_pos = args.layout.rect(row: row, col: col, w: 0, h: 0)
+ args.outputs.labels << "#{header}\n\n#{text}".wrapped_lines(80).map_with_index do |l, i|
+ { x: label_pos.x, y: label_pos.y - (i * 15), text: l, size_enum: -2 }
+ end
+end
diff --git a/samples/11_http/03_in_game_web_server_http_post/replay.txt b/samples/11_http/03_in_game_web_server_http_post/replay.txt
new file mode 100644
index 0000000..527f46d
--- /dev/null
+++ b/samples/11_http/03_in_game_web_server_http_post/replay.txt
@@ -0,0 +1,415 @@
+replay_version 2.0
+stopped_at 680
+seed 100
+recorded_at 2021-11-20 11:16:26 -0600
+[:mouse_button_up, 1, 0, 1, 1, 3]
+[:mouse_move, 782, 90, 2, 2, 12]
+[:mouse_move, 780, 90, 2, 3, 13]
+[:mouse_move, 771, 90, 2, 4, 14]
+[:mouse_move, 759, 90, 2, 5, 15]
+[:mouse_move, 739, 90, 2, 6, 16]
+[:mouse_move, 703, 90, 2, 7, 17]
+[:mouse_move, 681, 94, 2, 8, 18]
+[:mouse_move, 657, 95, 2, 9, 19]
+[:mouse_move, 631, 99, 2, 10, 20]
+[:mouse_move, 599, 99, 2, 11, 21]
+[:mouse_move, 560, 99, 2, 12, 22]
+[:mouse_move, 518, 97, 2, 13, 23]
+[:mouse_move, 476, 92, 2, 14, 24]
+[:mouse_move, 435, 90, 2, 15, 25]
+[:mouse_move, 391, 90, 2, 16, 26]
+[:mouse_move, 345, 90, 2, 17, 27]
+[:mouse_move, 304, 90, 2, 18, 28]
+[:mouse_move, 254, 90, 2, 19, 29]
+[:mouse_move, 230, 90, 2, 20, 30]
+[:mouse_move, 213, 90, 2, 21, 31]
+[:mouse_move, 207, 90, 2, 22, 32]
+[:mouse_move, 207, 89, 2, 23, 34]
+[:mouse_move, 207, 87, 2, 24, 35]
+[:mouse_move, 209, 84, 2, 25, 36]
+[:mouse_move, 210, 82, 2, 26, 37]
+[:mouse_move, 211, 82, 2, 27, 38]
+[:mouse_move, 211, 81, 2, 28, 40]
+[:mouse_move, 212, 80, 2, 29, 41]
+[:mouse_move, 212, 79, 2, 30, 42]
+[:mouse_button_pressed, 1, 0, 1, 31, 89]
+[:mouse_button_up, 1, 0, 1, 32, 93]
+[:mouse_move, 212, 83, 2, 33, 151]
+[:mouse_move, 216, 104, 2, 34, 152]
+[:mouse_move, 229, 135, 2, 35, 153]
+[:mouse_move, 242, 168, 2, 36, 154]
+[:mouse_move, 250, 197, 2, 37, 155]
+[:mouse_move, 254, 218, 2, 38, 156]
+[:mouse_move, 264, 240, 2, 39, 157]
+[:mouse_move, 274, 266, 2, 40, 158]
+[:mouse_move, 285, 293, 2, 41, 159]
+[:mouse_move, 295, 316, 2, 42, 160]
+[:mouse_move, 304, 345, 2, 43, 161]
+[:mouse_move, 308, 358, 2, 44, 162]
+[:mouse_move, 316, 381, 2, 45, 163]
+[:mouse_move, 328, 408, 2, 46, 164]
+[:mouse_move, 333, 431, 2, 47, 165]
+[:mouse_move, 336, 447, 2, 48, 166]
+[:mouse_move, 337, 455, 2, 49, 167]
+[:mouse_move, 337, 459, 2, 50, 168]
+[:mouse_move, 336, 459, 2, 51, 175]
+[:mouse_move, 336, 460, 2, 52, 177]
+[:mouse_move, 336, 461, 2, 53, 178]
+[:mouse_move, 334, 462, 2, 54, 179]
+[:mouse_move, 331, 462, 2, 55, 180]
+[:mouse_move, 328, 462, 2, 56, 181]
+[:mouse_move, 323, 462, 2, 57, 182]
+[:mouse_move, 318, 455, 2, 58, 183]
+[:mouse_move, 310, 438, 2, 59, 184]
+[:mouse_move, 306, 414, 2, 60, 185]
+[:mouse_move, 306, 405, 2, 61, 186]
+[:mouse_move, 307, 402, 2, 62, 187]
+[:mouse_move, 310, 395, 2, 63, 188]
+[:mouse_move, 318, 384, 2, 64, 189]
+[:mouse_move, 327, 374, 2, 65, 190]
+[:mouse_move, 338, 364, 2, 66, 191]
+[:mouse_move, 351, 355, 2, 67, 192]
+[:mouse_move, 367, 347, 2, 68, 193]
+[:mouse_move, 385, 340, 2, 69, 194]
+[:mouse_move, 406, 335, 2, 70, 195]
+[:mouse_move, 431, 330, 2, 71, 196]
+[:mouse_move, 471, 330, 2, 72, 197]
+[:mouse_move, 491, 335, 2, 73, 198]
+[:mouse_move, 505, 339, 2, 74, 199]
+[:mouse_move, 514, 342, 2, 75, 200]
+[:mouse_move, 520, 346, 2, 76, 201]
+[:mouse_move, 526, 352, 2, 77, 202]
+[:mouse_move, 530, 363, 2, 78, 203]
+[:mouse_move, 530, 378, 2, 79, 204]
+[:mouse_move, 530, 396, 2, 80, 205]
+[:mouse_move, 530, 415, 2, 81, 206]
+[:mouse_move, 524, 434, 2, 82, 207]
+[:mouse_move, 517, 446, 2, 83, 208]
+[:mouse_move, 509, 458, 2, 84, 209]
+[:mouse_move, 503, 466, 2, 85, 210]
+[:mouse_move, 499, 472, 2, 86, 211]
+[:mouse_move, 496, 478, 2, 87, 212]
+[:mouse_move, 493, 486, 2, 88, 213]
+[:mouse_move, 488, 493, 2, 89, 214]
+[:mouse_move, 476, 501, 2, 90, 215]
+[:mouse_move, 465, 509, 2, 91, 216]
+[:mouse_move, 453, 515, 2, 92, 217]
+[:mouse_move, 441, 521, 2, 93, 218]
+[:mouse_move, 426, 524, 2, 94, 219]
+[:mouse_move, 410, 524, 2, 95, 220]
+[:mouse_move, 391, 527, 2, 96, 221]
+[:mouse_move, 379, 527, 2, 97, 222]
+[:mouse_move, 368, 527, 2, 98, 223]
+[:mouse_move, 360, 528, 2, 99, 224]
+[:mouse_move, 359, 528, 2, 100, 225]
+[:mouse_move, 358, 528, 2, 101, 226]
+[:mouse_move, 364, 529, 2, 102, 232]
+[:mouse_move, 387, 533, 2, 103, 233]
+[:mouse_move, 410, 535, 2, 104, 234]
+[:mouse_move, 434, 535, 2, 105, 235]
+[:mouse_move, 468, 535, 2, 106, 236]
+[:mouse_move, 506, 535, 2, 107, 237]
+[:mouse_move, 546, 535, 2, 108, 238]
+[:mouse_move, 582, 535, 2, 109, 239]
+[:mouse_move, 614, 531, 2, 110, 240]
+[:mouse_move, 647, 521, 2, 111, 241]
+[:mouse_move, 679, 510, 2, 112, 242]
+[:mouse_move, 705, 496, 2, 113, 243]
+[:mouse_move, 722, 479, 2, 114, 244]
+[:mouse_move, 727, 447, 2, 115, 245]
+[:mouse_move, 715, 426, 2, 116, 246]
+[:mouse_move, 692, 401, 2, 117, 247]
+[:mouse_move, 665, 382, 2, 118, 248]
+[:mouse_move, 641, 371, 2, 119, 249]
+[:mouse_move, 601, 361, 2, 120, 250]
+[:mouse_move, 582, 358, 2, 121, 251]
+[:mouse_move, 510, 350, 2, 122, 252]
+[:mouse_move, 486, 350, 2, 123, 253]
+[:mouse_move, 439, 350, 2, 124, 254]
+[:mouse_move, 395, 350, 2, 125, 255]
+[:mouse_move, 362, 355, 2, 126, 256]
+[:mouse_move, 322, 370, 2, 127, 257]
+[:mouse_move, 306, 380, 2, 128, 258]
+[:mouse_move, 298, 395, 2, 129, 259]
+[:mouse_move, 296, 420, 2, 130, 260]
+[:mouse_move, 303, 439, 2, 131, 261]
+[:mouse_move, 310, 450, 2, 132, 262]
+[:mouse_move, 345, 476, 2, 133, 263]
+[:mouse_move, 376, 489, 2, 134, 264]
+[:mouse_move, 408, 495, 2, 135, 265]
+[:mouse_move, 447, 498, 2, 136, 266]
+[:mouse_move, 487, 498, 2, 137, 267]
+[:mouse_move, 526, 492, 2, 138, 268]
+[:mouse_move, 588, 476, 2, 139, 269]
+[:mouse_move, 630, 455, 2, 140, 270]
+[:mouse_move, 682, 424, 2, 141, 271]
+[:mouse_move, 733, 384, 2, 142, 272]
+[:mouse_move, 774, 341, 2, 143, 273]
+[:mouse_move, 811, 302, 2, 144, 274]
+[:mouse_move, 825, 270, 2, 145, 275]
+[:mouse_move, 828, 240, 2, 146, 276]
+[:mouse_move, 824, 211, 2, 147, 277]
+[:mouse_move, 810, 185, 2, 148, 278]
+[:mouse_move, 799, 170, 2, 149, 279]
+[:mouse_move, 793, 165, 2, 150, 280]
+[:mouse_move, 787, 162, 2, 151, 281]
+[:mouse_move, 779, 158, 2, 152, 282]
+[:mouse_move, 768, 154, 2, 153, 283]
+[:mouse_move, 759, 151, 2, 154, 284]
+[:mouse_move, 757, 150, 2, 155, 285]
+[:mouse_move, 757, 151, 2, 156, 288]
+[:mouse_move, 765, 159, 2, 157, 289]
+[:mouse_move, 775, 168, 2, 158, 290]
+[:mouse_move, 790, 172, 2, 159, 291]
+[:mouse_move, 812, 177, 2, 160, 292]
+[:mouse_move, 859, 180, 2, 161, 293]
+[:mouse_move, 902, 180, 2, 162, 294]
+[:mouse_move, 944, 178, 2, 163, 295]
+[:mouse_move, 985, 172, 2, 164, 296]
+[:mouse_move, 1025, 163, 2, 165, 297]
+[:mouse_move, 1053, 152, 2, 166, 298]
+[:mouse_move, 1075, 142, 2, 167, 299]
+[:mouse_move, 1090, 131, 2, 168, 300]
+[:mouse_move, 1096, 121, 2, 169, 301]
+[:mouse_move, 1096, 110, 2, 170, 302]
+[:mouse_move, 1088, 96, 2, 171, 303]
+[:mouse_move, 1065, 77, 2, 172, 304]
+[:mouse_move, 1030, 58, 2, 173, 305]
+[:mouse_move, 1014, 54, 2, 174, 306]
+[:mouse_move, 999, 50, 2, 175, 307]
+[:mouse_move, 978, 45, 2, 176, 308]
+[:mouse_move, 951, 41, 2, 177, 309]
+[:mouse_move, 912, 36, 2, 178, 310]
+[:mouse_move, 870, 33, 2, 179, 311]
+[:mouse_move, 833, 33, 2, 180, 312]
+[:mouse_move, 809, 39, 2, 181, 313]
+[:mouse_move, 793, 45, 2, 182, 314]
+[:mouse_move, 782, 51, 2, 183, 315]
+[:mouse_move, 777, 55, 2, 184, 316]
+[:mouse_move, 776, 70, 2, 185, 317]
+[:mouse_move, 784, 90, 2, 186, 318]
+[:mouse_move, 802, 114, 2, 187, 319]
+[:mouse_move, 827, 138, 2, 188, 320]
+[:mouse_move, 865, 156, 2, 189, 321]
+[:mouse_move, 905, 168, 2, 190, 322]
+[:mouse_move, 942, 171, 2, 191, 323]
+[:mouse_move, 972, 171, 2, 192, 324]
+[:mouse_move, 992, 167, 2, 193, 325]
+[:mouse_move, 1000, 157, 2, 194, 326]
+[:mouse_move, 1000, 140, 2, 195, 327]
+[:mouse_move, 982, 117, 2, 196, 328]
+[:mouse_move, 958, 99, 2, 197, 329]
+[:mouse_move, 903, 81, 2, 198, 330]
+[:mouse_move, 880, 75, 2, 199, 331]
+[:mouse_move, 763, 60, 2, 200, 332]
+[:mouse_move, 716, 58, 2, 201, 333]
+[:mouse_move, 604, 58, 2, 202, 334]
+[:mouse_move, 440, 65, 2, 203, 335]
+[:mouse_move, 355, 82, 2, 204, 336]
+[:mouse_move, 282, 95, 2, 205, 337]
+[:mouse_move, 221, 103, 2, 206, 338]
+[:mouse_move, 179, 109, 2, 207, 339]
+[:mouse_move, 146, 109, 2, 208, 340]
+[:mouse_move, 128, 109, 2, 209, 341]
+[:mouse_move, 116, 109, 2, 210, 342]
+[:mouse_move, 112, 108, 2, 211, 343]
+[:mouse_move, 115, 111, 2, 212, 349]
+[:mouse_move, 117, 113, 2, 213, 350]
+[:mouse_move, 118, 115, 2, 214, 351]
+[:mouse_move, 118, 116, 2, 215, 352]
+[:mouse_move, 119, 117, 2, 216, 353]
+[:mouse_move, 123, 119, 2, 217, 354]
+[:mouse_move, 127, 120, 2, 218, 355]
+[:mouse_move, 128, 120, 2, 219, 356]
+[:mouse_button_pressed, 1, 0, 1, 220, 369]
+[:mouse_button_up, 1, 0, 1, 221, 372]
+[:mouse_move, 131, 121, 2, 222, 399]
+[:mouse_move, 147, 128, 2, 223, 400]
+[:mouse_move, 165, 133, 2, 224, 401]
+[:mouse_move, 186, 138, 2, 225, 402]
+[:mouse_move, 210, 145, 2, 226, 403]
+[:mouse_move, 231, 151, 2, 227, 404]
+[:mouse_move, 252, 160, 2, 228, 405]
+[:mouse_move, 276, 176, 2, 229, 406]
+[:mouse_move, 304, 197, 2, 230, 407]
+[:mouse_move, 332, 224, 2, 231, 408]
+[:mouse_move, 352, 261, 2, 232, 409]
+[:mouse_move, 360, 293, 2, 233, 410]
+[:mouse_move, 365, 322, 2, 234, 411]
+[:mouse_move, 366, 351, 2, 235, 412]
+[:mouse_move, 358, 385, 2, 236, 413]
+[:mouse_move, 344, 403, 2, 237, 414]
+[:mouse_move, 331, 412, 2, 238, 415]
+[:mouse_move, 318, 417, 2, 239, 416]
+[:mouse_move, 307, 420, 2, 240, 417]
+[:mouse_move, 303, 422, 2, 241, 418]
+[:mouse_move, 302, 422, 2, 242, 419]
+[:mouse_move, 301, 422, 2, 243, 421]
+[:mouse_move, 298, 418, 2, 244, 422]
+[:mouse_move, 295, 410, 2, 245, 423]
+[:mouse_move, 295, 407, 2, 246, 424]
+[:mouse_move, 293, 403, 2, 247, 425]
+[:mouse_move, 293, 399, 2, 248, 426]
+[:mouse_move, 293, 396, 2, 249, 427]
+[:mouse_move, 294, 391, 2, 250, 428]
+[:mouse_move, 300, 380, 2, 251, 429]
+[:mouse_move, 306, 370, 2, 252, 430]
+[:mouse_move, 315, 361, 2, 253, 431]
+[:mouse_move, 318, 360, 2, 254, 432]
+[:mouse_move, 319, 360, 2, 255, 433]
+[:mouse_move, 321, 362, 2, 256, 434]
+[:mouse_move, 321, 363, 2, 257, 435]
+[:mouse_move, 322, 364, 2, 258, 439]
+[:mouse_move, 333, 367, 2, 259, 440]
+[:mouse_move, 357, 372, 2, 260, 441]
+[:mouse_move, 387, 375, 2, 261, 442]
+[:mouse_move, 426, 380, 2, 262, 443]
+[:mouse_move, 468, 387, 2, 263, 444]
+[:mouse_move, 506, 389, 2, 264, 445]
+[:mouse_move, 539, 389, 2, 265, 446]
+[:mouse_move, 570, 387, 2, 266, 447]
+[:mouse_move, 593, 381, 2, 267, 448]
+[:mouse_move, 614, 376, 2, 268, 449]
+[:mouse_move, 622, 376, 2, 269, 450]
+[:mouse_move, 626, 377, 2, 270, 451]
+[:mouse_move, 628, 379, 2, 271, 452]
+[:mouse_move, 628, 382, 2, 272, 453]
+[:mouse_move, 627, 388, 2, 273, 454]
+[:mouse_move, 621, 400, 2, 274, 455]
+[:mouse_move, 609, 411, 2, 275, 456]
+[:mouse_move, 594, 422, 2, 276, 457]
+[:mouse_move, 573, 429, 2, 277, 458]
+[:mouse_move, 551, 433, 2, 278, 459]
+[:mouse_move, 523, 437, 2, 279, 460]
+[:mouse_move, 481, 440, 2, 280, 461]
+[:mouse_move, 453, 439, 2, 281, 462]
+[:mouse_move, 425, 432, 2, 282, 463]
+[:mouse_move, 393, 423, 2, 283, 464]
+[:mouse_move, 368, 416, 2, 284, 465]
+[:mouse_move, 353, 415, 2, 285, 466]
+[:mouse_move, 343, 413, 2, 286, 467]
+[:mouse_move, 337, 409, 2, 287, 468]
+[:mouse_move, 332, 405, 2, 288, 469]
+[:mouse_move, 327, 395, 2, 289, 470]
+[:mouse_move, 324, 382, 2, 290, 471]
+[:mouse_move, 324, 375, 2, 291, 472]
+[:mouse_move, 336, 367, 2, 292, 473]
+[:mouse_move, 351, 361, 2, 293, 474]
+[:mouse_move, 369, 357, 2, 294, 475]
+[:mouse_move, 388, 356, 2, 295, 476]
+[:mouse_move, 405, 353, 2, 296, 477]
+[:mouse_move, 423, 352, 2, 297, 478]
+[:mouse_move, 441, 355, 2, 298, 479]
+[:mouse_move, 464, 367, 2, 299, 480]
+[:mouse_move, 482, 380, 2, 300, 481]
+[:mouse_move, 494, 395, 2, 301, 482]
+[:mouse_move, 496, 405, 2, 302, 483]
+[:mouse_move, 491, 413, 2, 303, 484]
+[:mouse_move, 467, 428, 2, 304, 485]
+[:mouse_move, 447, 439, 2, 305, 486]
+[:mouse_move, 427, 447, 2, 306, 487]
+[:mouse_move, 407, 450, 2, 307, 488]
+[:mouse_move, 385, 450, 2, 308, 489]
+[:mouse_move, 361, 449, 2, 309, 490]
+[:mouse_move, 345, 447, 2, 310, 491]
+[:mouse_move, 332, 441, 2, 311, 492]
+[:mouse_move, 321, 434, 2, 312, 493]
+[:mouse_move, 312, 424, 2, 313, 494]
+[:mouse_move, 307, 412, 2, 314, 495]
+[:mouse_move, 306, 401, 2, 315, 496]
+[:mouse_move, 310, 384, 2, 316, 497]
+[:mouse_move, 322, 369, 2, 317, 498]
+[:mouse_move, 346, 357, 2, 318, 499]
+[:mouse_move, 388, 346, 2, 319, 500]
+[:mouse_move, 434, 332, 2, 320, 501]
+[:mouse_move, 500, 314, 2, 321, 502]
+[:mouse_move, 564, 295, 2, 322, 503]
+[:mouse_move, 630, 276, 2, 323, 504]
+[:mouse_move, 676, 262, 2, 324, 505]
+[:mouse_move, 716, 248, 2, 325, 506]
+[:mouse_move, 753, 232, 2, 326, 507]
+[:mouse_move, 785, 217, 2, 327, 508]
+[:mouse_move, 820, 194, 2, 328, 509]
+[:mouse_move, 831, 186, 2, 329, 510]
+[:mouse_move, 832, 185, 2, 330, 511]
+[:mouse_move, 833, 184, 2, 331, 512]
+[:mouse_move, 834, 186, 2, 332, 518]
+[:mouse_move, 835, 189, 2, 333, 519]
+[:mouse_move, 833, 190, 2, 334, 521]
+[:mouse_move, 821, 188, 2, 335, 522]
+[:mouse_move, 793, 174, 2, 336, 523]
+[:mouse_move, 753, 152, 2, 337, 524]
+[:mouse_move, 725, 132, 2, 338, 525]
+[:mouse_move, 715, 117, 2, 339, 526]
+[:mouse_move, 710, 93, 2, 340, 527]
+[:mouse_move, 709, 69, 2, 341, 528]
+[:mouse_move, 713, 47, 2, 342, 529]
+[:mouse_move, 730, 29, 2, 343, 530]
+[:mouse_move, 763, 18, 2, 344, 531]
+[:mouse_move, 812, 16, 2, 345, 532]
+[:mouse_move, 894, 24, 2, 346, 533]
+[:mouse_move, 965, 43, 2, 347, 534]
+[:mouse_move, 1015, 64, 2, 348, 535]
+[:mouse_move, 1049, 80, 2, 349, 536]
+[:mouse_move, 1070, 97, 2, 350, 537]
+[:mouse_move, 1079, 114, 2, 351, 538]
+[:mouse_move, 1079, 126, 2, 352, 539]
+[:mouse_move, 1071, 139, 2, 353, 540]
+[:mouse_move, 1052, 147, 2, 354, 541]
+[:mouse_move, 1026, 151, 2, 355, 542]
+[:mouse_move, 986, 152, 2, 356, 543]
+[:mouse_move, 937, 152, 2, 357, 544]
+[:mouse_move, 835, 143, 2, 358, 545]
+[:mouse_move, 768, 125, 2, 359, 546]
+[:mouse_move, 711, 105, 2, 360, 547]
+[:mouse_move, 667, 86, 2, 361, 548]
+[:mouse_move, 639, 74, 2, 362, 549]
+[:mouse_move, 630, 69, 2, 363, 550]
+[:mouse_move, 630, 64, 2, 364, 551]
+[:mouse_move, 638, 53, 2, 365, 552]
+[:mouse_move, 659, 41, 2, 366, 553]
+[:mouse_move, 688, 33, 2, 367, 554]
+[:mouse_move, 723, 23, 2, 368, 555]
+[:mouse_move, 759, 19, 2, 369, 556]
+[:mouse_move, 810, 19, 2, 370, 557]
+[:mouse_move, 840, 25, 2, 371, 558]
+[:mouse_move, 866, 37, 2, 372, 559]
+[:mouse_move, 878, 47, 2, 373, 560]
+[:mouse_move, 878, 57, 2, 374, 561]
+[:mouse_move, 866, 69, 2, 375, 562]
+[:mouse_move, 835, 76, 2, 376, 563]
+[:mouse_move, 783, 77, 2, 377, 564]
+[:mouse_move, 722, 77, 2, 378, 565]
+[:mouse_move, 652, 77, 2, 379, 566]
+[:mouse_move, 559, 67, 2, 380, 567]
+[:mouse_move, 445, 36, 2, 381, 568]
+[:mouse_move, 274, 0, 2, 382, 569]
+[:mouse_move, 110, 0, 2, 383, 598]
+[:mouse_move, 131, 5, 2, 384, 599]
+[:mouse_move, 162, 14, 2, 385, 600]
+[:mouse_move, 201, 24, 2, 386, 601]
+[:mouse_move, 244, 32, 2, 387, 602]
+[:key_down_raw, 96, 0, 2, 388, 602]
+[:mouse_move, 288, 38, 2, 389, 603]
+[:mouse_move, 338, 46, 2, 390, 604]
+[:mouse_move, 422, 70, 2, 391, 605]
+[:mouse_move, 490, 90, 2, 392, 606]
+[:mouse_move, 553, 113, 2, 393, 607]
+[:key_up_raw, 96, 0, 2, 394, 608]
+[:mouse_move, 600, 129, 2, 395, 608]
+[:mouse_move, 638, 146, 2, 396, 609]
+[:mouse_move, 663, 159, 2, 397, 610]
+[:mouse_move, 686, 168, 2, 398, 611]
+[:mouse_move, 708, 177, 2, 399, 612]
+[:mouse_move, 725, 184, 2, 400, 613]
+[:mouse_move, 733, 189, 2, 401, 614]
+[:mouse_move, 735, 189, 2, 402, 615]
+[:mouse_move, 729, 189, 2, 403, 616]
+[:mouse_move, 704, 185, 2, 404, 617]
+[:mouse_move, 721, 189, 2, 405, 628]
+[:mouse_move, 744, 191, 2, 406, 629]
+[:mouse_move, 745, 191, 2, 407, 630]
+[:mouse_move, 744, 191, 2, 408, 637]
+[:mouse_move, 743, 191, 2, 409, 638]
+[:mouse_move, 744, 191, 2, 410, 665]
+[:key_down_raw, 13, 0, 2, 411, 680]
diff --git a/samples/12_c_extensions/.gitignore b/samples/12_c_extensions/.gitignore
new file mode 100644
index 0000000..a90a836
--- /dev/null
+++ b/samples/12_c_extensions/.gitignore
@@ -0,0 +1,2 @@
+ext.dylib
+
diff --git a/samples/12_c_extensions/01_basics/native/ext-bindings.c b/samples/12_c_extensions/01_basics/native/ext-bindings.c
index c805961..86b7090 100644
--- a/samples/12_c_extensions/01_basics/native/ext-bindings.c
+++ b/samples/12_c_extensions/01_basics/native/ext-bindings.c
@@ -14,7 +14,13 @@
#undef mrb_int
#endif
+void *(*drb_symbol_lookup)(const char *sym) = NULL;
+
static void (*drb_free_foreign_object_f)(mrb_state *, void *);
+static void (*drb_typecheck_float_f)(mrb_state *, mrb_value);
+static void (*drb_typecheck_int_f)(mrb_state *, mrb_value);
+static void (*drb_typecheck_bool_f)(mrb_state *, mrb_value);
+static void (*drb_typecheck_aggregate_f)(mrb_state *, mrb_value, struct RClass *, mrb_data_type *);
static struct RClass *(*mrb_module_get_f)(mrb_state *, const char *);
static mrb_int (*mrb_get_args_f)(mrb_state *, mrb_args_format, ...);
static struct RClass *(*mrb_module_get_under_f)(mrb_state *, struct RClass *, const char *);
@@ -27,7 +33,13 @@ static void (*mrb_define_class_method_f)(mrb_state *, struct RClass *, const cha
static struct RData *(*mrb_data_object_alloc_f)(mrb_state *, struct RClass *, void *, const mrb_data_type *);
static mrb_value (*mrb_str_new_cstr_f)(mrb_state *, const char *);
static void (*mrb_raise_f)(mrb_state *, struct RClass *, const char *);
+static mrb_value (*drb_float_value_f)(mrb_state *, mrb_float);
+static struct RClass *(*drb_getruntime_error_f)(mrb_state *);
+static void drb_free_foreign_object_indirect(mrb_state *state, void *pointer) {
+ drb_free_foreign_object_f(state, pointer);
+}
static int drb_ffi__ZTSi_FromRuby(mrb_state *state, mrb_value self) {
+ drb_typecheck_int_f(state, self);
return mrb_fixnum(self);
}
static mrb_value drb_ffi__ZTSi_ToRuby(mrb_state *state, int value) {
@@ -51,18 +63,25 @@ void drb_register_c_extensions(void *(*lookup)(const char *), mrb_state *state,
mrb_define_module_function_f(state, module, "square", drb_ffi_square_Binding, MRB_ARGS_REQ(1));
}
static int drb_ffi_init_indirect_functions(void *(*lookup)(const char *fnname)) {
- if (!(mrb_raise_f = (void (*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_raise"))) return -1;
- if (!(mrb_module_get_f = (struct RClass *(*)(mrb_state *, const char *)) lookup("mrb_module_get"))) return -1;
- if (!(mrb_class_get_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_class_get_under"))) return -1;
- if (!(mrb_get_args_f = (mrb_int (*)(mrb_state *, mrb_args_format, ...)) lookup("mrb_get_args"))) return -1;
+ drb_symbol_lookup = lookup;
+ if (!(drb_float_value_f = (mrb_value (*)(mrb_state *, mrb_float)) lookup("drb_float_value"))) return -1;
if (!(drb_free_foreign_object_f = (void (*)(mrb_state *, void *)) lookup("drb_free_foreign_object"))) return -1;
- if (!(mrb_define_module_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_define_module_under"))) return -1;
- if (!(mrb_str_new_cstr_f = (mrb_value (*)(mrb_state *, const char *)) lookup("mrb_str_new_cstr"))) return -1;
+ if (!(drb_getruntime_error_f = (struct RClass *(*)(mrb_state *)) lookup("drb_getruntime_error"))) return -1;
+ if (!(drb_typecheck_aggregate_f = (void (*)(mrb_state *, mrb_value, struct RClass *, mrb_data_type *)) lookup("drb_typecheck_aggregate"))) return -1;
+ if (!(drb_typecheck_bool_f = (void (*)(mrb_state *, mrb_value)) lookup("drb_typecheck_bool"))) return -1;
+ if (!(drb_typecheck_float_f = (void (*)(mrb_state *, mrb_value)) lookup("drb_typecheck_float"))) return -1;
+ if (!(drb_typecheck_int_f = (void (*)(mrb_state *, mrb_value)) lookup("drb_typecheck_int"))) return -1;
+ if (!(mrb_class_get_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_class_get_under"))) return -1;
+ if (!(mrb_data_object_alloc_f = (struct RData *(*)(mrb_state *, struct RClass *, void *, const mrb_data_type *)) lookup("mrb_data_object_alloc"))) return -1;
+ if (!(mrb_define_class_method_f = (void (*)(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec)) lookup("mrb_define_class_method"))) return -1;
if (!(mrb_define_class_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *, struct RClass *)) lookup("mrb_define_class_under"))) return -1;
+ if (!(mrb_define_method_f = (void (*)(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec)) lookup("mrb_define_method"))) return -1;
if (!(mrb_define_module_function_f = (void (*)(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec)) lookup("mrb_define_module_function"))) return -1;
- if (!(mrb_data_object_alloc_f = (struct RData *(*)(mrb_state *, struct RClass *, void *, const mrb_data_type *)) lookup("mrb_data_object_alloc"))) return -1;
+ if (!(mrb_define_module_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_define_module_under"))) return -1;
+ if (!(mrb_get_args_f = (mrb_int (*)(mrb_state *, mrb_args_format, ...)) lookup("mrb_get_args"))) return -1;
+ if (!(mrb_module_get_f = (struct RClass *(*)(mrb_state *, const char *)) lookup("mrb_module_get"))) return -1;
if (!(mrb_module_get_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_module_get_under"))) return -1;
- if (!(mrb_define_method_f = (void (*)(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec)) lookup("mrb_define_method"))) return -1;
- if (!(mrb_define_class_method_f = (void (*)(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec)) lookup("mrb_define_class_method"))) return -1;
+ if (!(mrb_raise_f = (void (*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_raise"))) return -1;
+ if (!(mrb_str_new_cstr_f = (mrb_value (*)(mrb_state *, const char *)) lookup("mrb_str_new_cstr"))) return -1;
return 0;
}
diff --git a/samples/12_c_extensions/02_intermediate/native/re-bindings.c b/samples/12_c_extensions/02_intermediate/native/re-bindings.c
index 6aa5630..6bd9869 100644
--- a/samples/12_c_extensions/02_intermediate/native/re-bindings.c
+++ b/samples/12_c_extensions/02_intermediate/native/re-bindings.c
@@ -14,7 +14,13 @@
#undef mrb_int
#endif
+void *(*drb_symbol_lookup)(const char *sym) = NULL;
+
static void (*drb_free_foreign_object_f)(mrb_state *, void *);
+static void (*drb_typecheck_float_f)(mrb_state *, mrb_value);
+static void (*drb_typecheck_int_f)(mrb_state *, mrb_value);
+static void (*drb_typecheck_bool_f)(mrb_state *, mrb_value);
+static void (*drb_typecheck_aggregate_f)(mrb_state *, mrb_value, struct RClass *, mrb_data_type *);
static struct RClass *(*mrb_module_get_f)(mrb_state *, const char *);
static mrb_int (*mrb_get_args_f)(mrb_state *, mrb_args_format, ...);
static struct RClass *(*mrb_module_get_under_f)(mrb_state *, struct RClass *, const char *);
@@ -27,10 +33,18 @@ static void (*mrb_define_class_method_f)(mrb_state *, struct RClass *, const cha
static struct RData *(*mrb_data_object_alloc_f)(mrb_state *, struct RClass *, void *, const mrb_data_type *);
static mrb_value (*mrb_str_new_cstr_f)(mrb_state *, const char *);
static void (*mrb_raise_f)(mrb_state *, struct RClass *, const char *);
-static struct RClass *(*mrb_exc_get_f)(mrb_state *, const char *);
+static mrb_value (*drb_float_value_f)(mrb_state *, mrb_float);
+static struct RClass *(*drb_getruntime_error_f)(mrb_state *);
static void drb_free_foreign_object_indirect(mrb_state *state, void *pointer) {
drb_free_foreign_object_f(state, pointer);
}
+static int drb_ffi__ZTSi_FromRuby(mrb_state *state, mrb_value self) {
+ drb_typecheck_int_f(state, self);
+ return mrb_fixnum(self);
+}
+static mrb_value drb_ffi__ZTSi_ToRuby(mrb_state *state, int value) {
+ return mrb_fixnum_value(value);
+}
struct drb_foreign_object_ZTSP7regex_t {
drb_foreign_object_kind kind;
struct regex_t *value;
@@ -40,6 +54,10 @@ static mrb_data_type ForeignObjectType_ZTSP7regex_t = {"regex_t*", drb_free_fore
static struct regex_t *drb_ffi__ZTSP7regex_t_FromRuby(mrb_state *state, mrb_value self) {
if (mrb_nil_p(self))
return 0;
+ struct RClass *FFI = mrb_module_get_f(state, "FFI");
+ struct RClass *module = mrb_module_get_under_f(state, FFI, "RE");
+ struct RClass *klass = mrb_class_get_under_f(state, module, "Regex_tPointer");
+ drb_typecheck_aggregate_f(state, self, klass, &ForeignObjectType_ZTSP7regex_t);
return ((struct drb_foreign_object_ZTSP7regex_t *)DATA_PTR(self))->value;
}
static mrb_value drb_ffi__ZTSP7regex_t_ToRuby(mrb_state *state, struct regex_t *value) {
@@ -63,6 +81,10 @@ static char *drb_ffi__ZTSPc_FromRuby(mrb_state *state, mrb_value self) {
return 0;
if (mrb_type(self) == MRB_TT_STRING)
return RSTRING_PTR(self);
+ struct RClass *FFI = mrb_module_get_f(state, "FFI");
+ struct RClass *module = mrb_module_get_under_f(state, FFI, "RE");
+ struct RClass *klass = mrb_class_get_under_f(state, module, "CharPointer");
+ drb_typecheck_aggregate_f(state, self, klass, &ForeignObjectType_ZTSPc);
return ((struct drb_foreign_object_ZTSPc *)DATA_PTR(self))->value;
}
static mrb_value drb_ffi__ZTSPc_ToRuby(mrb_state *state, char *value) {
@@ -75,12 +97,6 @@ static mrb_value drb_ffi__ZTSPc_ToRuby(mrb_state *state, char *value) {
struct RData *rdata = mrb_data_object_alloc_f(state, klass, ptr, &ForeignObjectType_ZTSPc);
return mrb_obj_value(rdata);
}
-static int drb_ffi__ZTSi_FromRuby(mrb_state *state, mrb_value self) {
- return mrb_fixnum(self);
-}
-static mrb_value drb_ffi__ZTSi_ToRuby(mrb_state *state, int value) {
- return mrb_fixnum_value(value);
-}
struct drb_foreign_object_ZTSPi {
drb_foreign_object_kind kind;
int *value;
@@ -90,6 +106,10 @@ static mrb_data_type ForeignObjectType_ZTSPi = {"int*", drb_free_foreign_object_
static int *drb_ffi__ZTSPi_FromRuby(mrb_state *state, mrb_value self) {
if (mrb_nil_p(self))
return 0;
+ struct RClass *FFI = mrb_module_get_f(state, "FFI");
+ struct RClass *module = mrb_module_get_under_f(state, FFI, "RE");
+ struct RClass *klass = mrb_class_get_under_f(state, module, "IntPointer");
+ drb_typecheck_aggregate_f(state, self, klass, &ForeignObjectType_ZTSPi);
return ((struct drb_foreign_object_ZTSPi *)DATA_PTR(self))->value;
}
static mrb_value drb_ffi__ZTSPi_ToRuby(mrb_state *state, int *value) {
@@ -103,17 +123,18 @@ static mrb_value drb_ffi__ZTSPi_ToRuby(mrb_state *state, int *value) {
return mrb_obj_value(rdata);
}
static char drb_ffi__ZTSc_FromRuby(mrb_state *state, mrb_value self) {
+ drb_typecheck_int_f(state, self);
return mrb_fixnum(self);
}
static mrb_value drb_ffi__ZTSc_ToRuby(mrb_state *state, char value) {
return mrb_fixnum_value(value);
}
static mrb_value drb_ffi__ZTSP7regex_t_New(mrb_state *mrb, mrb_value self) {
- mrb_raise_f(mrb, mrb_exc_get_f(mrb, "RuntimeError"), "Cannot allocate pointer of incomplete type");
+ mrb_raise_f(mrb, drb_getruntime_error_f(mrb), "Cannot allocate pointer of incomplete type");
return mrb_nil_value();
}
static mrb_value drb_ffi__ZTSP7regex_t_GetValue(mrb_state *mrb, mrb_value value) {
- mrb_raise_f(mrb, mrb_exc_get_f(mrb, "RuntimeError"), "Cannot access value of incomplete type");
+ mrb_raise_f(mrb, drb_getruntime_error_f(mrb), "Cannot access value of incomplete type");
return mrb_nil_value();
}
static mrb_value drb_ffi__ZTSP7regex_t_IsNil(mrb_state *state, mrb_value self) {
@@ -123,11 +144,11 @@ static mrb_value drb_ffi__ZTSP7regex_t_IsNil(mrb_state *state, mrb_value self) {
return mrb_false_value();
}
static mrb_value drb_ffi__ZTSP7regex_t_GetAt(mrb_state *mrb, mrb_value self) {
- mrb_raise_f(mrb, mrb_exc_get_f(mrb, "RuntimeError"), "Cannot access value of incomplete type");
+ mrb_raise_f(mrb, drb_getruntime_error_f(mrb), "Cannot access value of incomplete type");
return mrb_nil_value();
}
static mrb_value drb_ffi__ZTSP7regex_t_SetAt(mrb_state *mrb, mrb_value self) {
- mrb_raise_f(mrb, mrb_exc_get_f(mrb, "RuntimeError"), "Cannot change value of incomplete type");
+ mrb_raise_f(mrb, drb_getruntime_error_f(mrb), "Cannot change value of incomplete type");
return mrb_nil_value();
}
static mrb_value drb_ffi__ZTSPc_New(mrb_state *mrb, mrb_value self) {
@@ -264,19 +285,25 @@ void drb_register_c_extensions(void *(*lookup)(const char *), mrb_state *state,
mrb_define_method_f(state, IntPointerClass, "nil?", drb_ffi__ZTSPi_IsNil, MRB_ARGS_REQ(0));
}
static int drb_ffi_init_indirect_functions(void *(*lookup)(const char *fnname)) {
- if (!(mrb_raise_f = (void (*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_raise"))) return -1;
- if (!(mrb_str_new_cstr_f = (mrb_value (*)(mrb_state *, const char *)) lookup("mrb_str_new_cstr"))) return -1;
- if (!(mrb_define_class_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *, struct RClass *)) lookup("mrb_define_class_under"))) return -1;
- if (!(mrb_define_class_method_f = (void (*)(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec)) lookup("mrb_define_class_method"))) return -1;
- if (!(mrb_class_get_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_class_get_under"))) return -1;
- if (!(mrb_module_get_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_module_get_under"))) return -1;
+ drb_symbol_lookup = lookup;
+ if (!(drb_float_value_f = (mrb_value (*)(mrb_state *, mrb_float)) lookup("drb_float_value"))) return -1;
if (!(drb_free_foreign_object_f = (void (*)(mrb_state *, void *)) lookup("drb_free_foreign_object"))) return -1;
+ if (!(drb_getruntime_error_f = (struct RClass *(*)(mrb_state *)) lookup("drb_getruntime_error"))) return -1;
+ if (!(drb_typecheck_aggregate_f = (void (*)(mrb_state *, mrb_value, struct RClass *, mrb_data_type *)) lookup("drb_typecheck_aggregate"))) return -1;
+ if (!(drb_typecheck_bool_f = (void (*)(mrb_state *, mrb_value)) lookup("drb_typecheck_bool"))) return -1;
+ if (!(drb_typecheck_float_f = (void (*)(mrb_state *, mrb_value)) lookup("drb_typecheck_float"))) return -1;
+ if (!(drb_typecheck_int_f = (void (*)(mrb_state *, mrb_value)) lookup("drb_typecheck_int"))) return -1;
+ if (!(mrb_class_get_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_class_get_under"))) return -1;
if (!(mrb_data_object_alloc_f = (struct RData *(*)(mrb_state *, struct RClass *, void *, const mrb_data_type *)) lookup("mrb_data_object_alloc"))) return -1;
- if (!(mrb_get_args_f = (mrb_int (*)(mrb_state *, mrb_args_format, ...)) lookup("mrb_get_args"))) return -1;
- if (!(mrb_module_get_f = (struct RClass *(*)(mrb_state *, const char *)) lookup("mrb_module_get"))) return -1;
+ if (!(mrb_define_class_method_f = (void (*)(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec)) lookup("mrb_define_class_method"))) return -1;
+ if (!(mrb_define_class_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *, struct RClass *)) lookup("mrb_define_class_under"))) return -1;
if (!(mrb_define_method_f = (void (*)(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec)) lookup("mrb_define_method"))) return -1;
- if (!(mrb_exc_get_f = (struct RClass *(*)(mrb_state *, const char *)) lookup("mrb_exc_get"))) return -1;
if (!(mrb_define_module_function_f = (void (*)(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec)) lookup("mrb_define_module_function"))) return -1;
if (!(mrb_define_module_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_define_module_under"))) return -1;
+ if (!(mrb_get_args_f = (mrb_int (*)(mrb_state *, mrb_args_format, ...)) lookup("mrb_get_args"))) return -1;
+ if (!(mrb_module_get_f = (struct RClass *(*)(mrb_state *, const char *)) lookup("mrb_module_get"))) return -1;
+ if (!(mrb_module_get_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_module_get_under"))) return -1;
+ if (!(mrb_raise_f = (void (*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_raise"))) return -1;
+ if (!(mrb_str_new_cstr_f = (mrb_value (*)(mrb_state *, const char *)) lookup("mrb_str_new_cstr"))) return -1;
return 0;
}
diff --git a/samples/12_c_extensions/03_native_pixel_arrays/native/ext-bindings.c b/samples/12_c_extensions/03_native_pixel_arrays/native/ext-bindings.c
index c0a923c..bdba6e7 100644
--- a/samples/12_c_extensions/03_native_pixel_arrays/native/ext-bindings.c
+++ b/samples/12_c_extensions/03_native_pixel_arrays/native/ext-bindings.c
@@ -17,6 +17,10 @@
void *(*drb_symbol_lookup)(const char *sym) = NULL;
static void (*drb_free_foreign_object_f)(mrb_state *, void *);
+static void (*drb_typecheck_float_f)(mrb_state *, mrb_value);
+static void (*drb_typecheck_int_f)(mrb_state *, mrb_value);
+static void (*drb_typecheck_bool_f)(mrb_state *, mrb_value);
+static void (*drb_typecheck_aggregate_f)(mrb_state *, mrb_value, struct RClass *, mrb_data_type *);
static struct RClass *(*mrb_module_get_f)(mrb_state *, const char *);
static mrb_int (*mrb_get_args_f)(mrb_state *, mrb_args_format, ...);
static struct RClass *(*mrb_module_get_under_f)(mrb_state *, struct RClass *, const char *);
@@ -29,10 +33,18 @@ static void (*mrb_define_class_method_f)(mrb_state *, struct RClass *, const cha
static struct RData *(*mrb_data_object_alloc_f)(mrb_state *, struct RClass *, void *, const mrb_data_type *);
static mrb_value (*mrb_str_new_cstr_f)(mrb_state *, const char *);
static void (*mrb_raise_f)(mrb_state *, struct RClass *, const char *);
-static struct RClass *(*mrb_exc_get_f)(mrb_state *, const char *);
+static mrb_value (*drb_float_value_f)(mrb_state *, mrb_float);
+static struct RClass *(*drb_getruntime_error_f)(mrb_state *);
static void drb_free_foreign_object_indirect(mrb_state *state, void *pointer) {
drb_free_foreign_object_f(state, pointer);
}
+static int drb_ffi__ZTSi_FromRuby(mrb_state *state, mrb_value self) {
+ drb_typecheck_int_f(state, self);
+ return mrb_fixnum(self);
+}
+static mrb_value drb_ffi__ZTSi_ToRuby(mrb_state *state, int value) {
+ return mrb_fixnum_value(value);
+}
static mrb_value drb_ffi_update_scanner_texture_Binding(mrb_state *state, mrb_value value) {
update_scanner_texture();
return mrb_nil_value();
@@ -48,19 +60,24 @@ void drb_register_c_extensions(void *(*lookup)(const char *), mrb_state *state,
}
static int drb_ffi_init_indirect_functions(void *(*lookup)(const char *fnname)) {
drb_symbol_lookup = lookup;
- if (!(mrb_exc_get_f = (struct RClass *(*)(mrb_state *, const char *)) lookup("mrb_exc_get"))) return -1;
- if (!(mrb_raise_f = (void (*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_raise"))) return -1;
- if (!(mrb_class_get_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_class_get_under"))) return -1;
- if (!(mrb_module_get_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_module_get_under"))) return -1;
+ if (!(drb_float_value_f = (mrb_value (*)(mrb_state *, mrb_float)) lookup("drb_float_value"))) return -1;
if (!(drb_free_foreign_object_f = (void (*)(mrb_state *, void *)) lookup("drb_free_foreign_object"))) return -1;
- if (!(mrb_module_get_f = (struct RClass *(*)(mrb_state *, const char *)) lookup("mrb_module_get"))) return -1;
- if (!(mrb_define_module_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_define_module_under"))) return -1;
+ if (!(drb_getruntime_error_f = (struct RClass *(*)(mrb_state *)) lookup("drb_getruntime_error"))) return -1;
+ if (!(drb_typecheck_aggregate_f = (void (*)(mrb_state *, mrb_value, struct RClass *, mrb_data_type *)) lookup("drb_typecheck_aggregate"))) return -1;
+ if (!(drb_typecheck_bool_f = (void (*)(mrb_state *, mrb_value)) lookup("drb_typecheck_bool"))) return -1;
+ if (!(drb_typecheck_float_f = (void (*)(mrb_state *, mrb_value)) lookup("drb_typecheck_float"))) return -1;
+ if (!(drb_typecheck_int_f = (void (*)(mrb_state *, mrb_value)) lookup("drb_typecheck_int"))) return -1;
+ if (!(mrb_class_get_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_class_get_under"))) return -1;
if (!(mrb_data_object_alloc_f = (struct RData *(*)(mrb_state *, struct RClass *, void *, const mrb_data_type *)) lookup("mrb_data_object_alloc"))) return -1;
+ if (!(mrb_define_class_method_f = (void (*)(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec)) lookup("mrb_define_class_method"))) return -1;
+ if (!(mrb_define_class_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *, struct RClass *)) lookup("mrb_define_class_under"))) return -1;
+ if (!(mrb_define_method_f = (void (*)(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec)) lookup("mrb_define_method"))) return -1;
if (!(mrb_define_module_function_f = (void (*)(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec)) lookup("mrb_define_module_function"))) return -1;
+ if (!(mrb_define_module_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_define_module_under"))) return -1;
if (!(mrb_get_args_f = (mrb_int (*)(mrb_state *, mrb_args_format, ...)) lookup("mrb_get_args"))) return -1;
- if (!(mrb_define_method_f = (void (*)(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec)) lookup("mrb_define_method"))) return -1;
- if (!(mrb_define_class_method_f = (void (*)(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec)) lookup("mrb_define_class_method"))) return -1;
+ if (!(mrb_module_get_f = (struct RClass *(*)(mrb_state *, const char *)) lookup("mrb_module_get"))) return -1;
+ if (!(mrb_module_get_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_module_get_under"))) return -1;
+ if (!(mrb_raise_f = (void (*)(mrb_state *, struct RClass *, const char *)) lookup("mrb_raise"))) return -1;
if (!(mrb_str_new_cstr_f = (mrb_value (*)(mrb_state *, const char *)) lookup("mrb_str_new_cstr"))) return -1;
- if (!(mrb_define_class_under_f = (struct RClass *(*)(mrb_state *, struct RClass *, const char *, struct RClass *)) lookup("mrb_define_class_under"))) return -1;
return 0;
}
diff --git a/samples/12_c_extensions/README.md b/samples/12_c_extensions/README.md
index 8950e53..aef3864 100644
--- a/samples/12_c_extensions/README.md
+++ b/samples/12_c_extensions/README.md
@@ -350,6 +350,34 @@ dragonruby-bind --ffi-module=CoolStuff bridge.c
Then one can use `include FFI::CoolStuff` instead.
+### Type checks
+
+C extensions expect the right types in the right place!
+
+Given the following C code:
+
+```c
+void take_int(int x) { ... }
+void take_struct(struct S) { ... }
+```
+
+the next calls from the Ruby side
+
+```ruby
+take_int(15.0)
+take_struct(42)
+```
+
+may not work as you would expect.
+In the case of `take_int`, you'll likely see some garbage instead of "expected" `15`.
+The call to `take_struct` will likely crash.
+
+To prevent this from happening, `dragonruby-bind` emits code that does type checking:
+if you use the wrong types DragonRuby will throw an exception.
+
+If the type checking takes CPU cycles out of your game (or if you feel brave) you can
+disable type checks via `--no-typecheck` CLI argument when emitting C bindings.
+
### Pitfalls
There is no so-called marshalling when it comes to structs. When you read or
diff --git a/samples/13_path_finding_algorithms/01_breadth_first_search/app/main.rb b/samples/13_path_finding_algorithms/01_breadth_first_search/app/main.rb
index 7f98509..8b84f1c 100644
--- a/samples/13_path_finding_algorithms/01_breadth_first_search/app/main.rb
+++ b/samples/13_path_finding_algorithms/01_breadth_first_search/app/main.rb
@@ -35,19 +35,19 @@ class BreadthFirstSearch
# Stores which step of the animation is being rendered
# When the user moves the star or messes with the walls,
# the breadth first search is recalculated up to this step
- args.state.anim_steps = 0
+ args.state.anim_steps = 0
# At some step the animation will end,
# and further steps won't change anything (the whole grid will be explored)
# This step is roughly the grid's width * height
# When anim_steps equals max_steps no more calculations will occur
# and the slider will be at the end
- args.state.max_steps = args.state.grid.width * args.state.grid.height
+ args.state.max_steps = args.state.grid.width * args.state.grid.height
# Whether the animation should play or not
# If true, every tick moves anim_steps forward one
# Pressing the stepwise animation buttons will pause the animation
- args.state.play = true
+ args.state.play = true
# The location of the star and walls of the grid
# They can be modified to have a different initial grid
@@ -116,7 +116,7 @@ class BreadthFirstSearch
[24, 9] => true,
[25, 8] => true,
[25, 9] => true,
- }
+ }
# Variables that are used by the breadth first search
# Storing cells that the search has visited, prevents unnecessary steps
@@ -132,7 +132,7 @@ class BreadthFirstSearch
# We store this value, because we want to remember the value even when
# the user's cursor is no longer over what they're interacting with, but
# they are still clicking down on the mouse.
- args.state.click_and_drag = :none
+ args.state.click_and_drag = :none
# Store the rects of the buttons that control the animation
# They are here for user customization
@@ -166,13 +166,13 @@ class BreadthFirstSearch
# User input is processed, and
# The next step in the search is calculated
def tick
- render
- input
+ render
+ input
# If animation is playing, and max steps have not been reached
# Move the search a step forward
if state.play && state.anim_steps < state.max_steps
# Variable that tells the program what step to recalculate up to
- state.anim_steps += 1
+ state.anim_steps += 1
calc
end
end
@@ -182,8 +182,8 @@ class BreadthFirstSearch
render_buttons
render_slider
- render_background
- render_visited
+ render_background
+ render_visited
render_frontier
render_walls
render_star
@@ -260,8 +260,8 @@ class BreadthFirstSearch
# Draws what the grid looks like with nothing on it
def render_background
- render_unvisited
- render_grid_lines
+ render_unvisited
+ render_grid_lines
end
# Draws a rectangle the size of the entire grid to represent unvisited cells
@@ -276,7 +276,7 @@ class BreadthFirstSearch
end
for y in 0..grid.height
- outputs.lines << horizontal_line(y)
+ outputs.lines << horizontal_line(y)
end
end
@@ -294,28 +294,28 @@ class BreadthFirstSearch
# The frontier is the most outward parts of the search
def render_frontier
outputs.solids << state.frontier.map do |cell|
- [scale_up(cell), frontier_color]
+ [scale_up([cell.x, cell.y]), frontier_color]
end
end
# Draws the walls
def render_walls
outputs.solids << state.walls.map do |wall|
- [scale_up(wall), wall_color]
+ [scale_up([wall.x, wall.y]), wall_color]
end
end
# Renders cells that have been searched in the appropriate color
def render_visited
outputs.solids << state.visited.map do |cell|
- [scale_up(cell), visited_color]
+ [scale_up([cell.x, cell.y]), visited_color]
end
end
# Renders the star
def render_star
outputs.sprites << [scale_up(state.star), 'star.png']
- end
+ end
# In code, the cells are represented as 1x1 rectangles
# When drawn, the cells are larger than 1x1 rectangles
@@ -369,20 +369,20 @@ class BreadthFirstSearch
# The detection and processing of click and drag inputs are separate
# The program has to remember that the user is dragging an object
# even when the mouse is no longer over that object
- detect_click_and_drag
- process_click_and_drag
+ detect_click_and_drag
+ process_click_and_drag
end
# Detects and Process input for each button
def input_buttons
- input_left_button
- input_center_button
- input_next_step_button
+ input_left_button
+ input_center_button
+ input_next_step_button
end
# Checks if the previous step button is clicked
# If it is, it pauses the animation and moves the search one step backward
- def input_left_button
+ def input_left_button
if left_button_clicked?
state.play = false
state.anim_steps -= 1
@@ -394,7 +394,7 @@ class BreadthFirstSearch
# Inverses whether the animation is playing or not when clicked
def input_center_button
if center_button_clicked? or inputs.keyboard.key_down.space
- state.play = !state.play
+ state.play = !state.play
end
end
@@ -402,8 +402,8 @@ class BreadthFirstSearch
# If it is, it pauses the animation and moves the search one step forward
def input_next_step_button
if right_button_clicked?
- state.play = false
- state.anim_steps += 1
+ state.play = false
+ state.anim_steps += 1
calc
end
end
@@ -412,29 +412,29 @@ class BreadthFirstSearch
# Storing the value allows the user to continue the same edit as long as the
# mouse left click is held
def detect_click_and_drag
- if inputs.mouse.up
- state.click_and_drag = :none
- elsif star_clicked?
- state.click_and_drag = :star
- elsif wall_clicked?
- state.click_and_drag = :remove_wall
- elsif grid_clicked?
- state.click_and_drag = :add_wall
- elsif slider_clicked?
- state.click_and_drag = :slider
+ if inputs.mouse.up
+ state.click_and_drag = :none
+ elsif star_clicked?
+ state.click_and_drag = :star
+ elsif wall_clicked?
+ state.click_and_drag = :remove_wall
+ elsif grid_clicked?
+ state.click_and_drag = :add_wall
+ elsif slider_clicked?
+ state.click_and_drag = :slider
end
end
# Processes click and drag based on what the user is currently dragging
def process_click_and_drag
- if state.click_and_drag == :star
- input_star
- elsif state.click_and_drag == :remove_wall
- input_remove_wall
- elsif state.click_and_drag == :add_wall
- input_add_wall
- elsif state.click_and_drag == :slider
- input_slider
+ if state.click_and_drag == :star
+ input_star
+ elsif state.click_and_drag == :remove_wall
+ input_remove_wall
+ elsif state.click_and_drag == :add_wall
+ input_add_wall
+ elsif state.click_and_drag == :slider
+ input_slider
end
end
@@ -442,10 +442,10 @@ class BreadthFirstSearch
# Only recalculates the search if the star changes position
# Called whenever the user is editing the star (puts mouse down on star)
def input_star
- old_star = state.star.clone
+ old_star = state.star.clone
state.star = cell_closest_to_mouse
- unless old_star == state.star
- recalculate
+ unless old_star == state.star
+ recalculate
end
end
@@ -454,20 +454,20 @@ class BreadthFirstSearch
# The mouse needs to be inside the grid, because we only want to remove walls
# the cursor is directly over
# Recalculations should only occur when a wall is actually deleted
- if mouse_inside_grid?
+ if mouse_inside_grid?
if state.walls.has_key?(cell_closest_to_mouse)
- state.walls.delete(cell_closest_to_mouse)
- recalculate
+ state.walls.delete(cell_closest_to_mouse)
+ recalculate
end
end
end
# Adds walls at cells under the cursor
def input_add_wall
- if mouse_inside_grid?
+ if mouse_inside_grid?
unless state.walls.has_key?(cell_closest_to_mouse)
- state.walls[cell_closest_to_mouse] = true
- recalculate
+ state.walls[cell_closest_to_mouse] = true
+ recalculate
end
end
end
@@ -477,18 +477,18 @@ class BreadthFirstSearch
# on the slider
# Changes the step of the search to be animated
def input_slider
- state.play = false
+ state.play = false
mouse_x = inputs.mouse.point.x
# Bounds the mouse_x to the closest x value on the slider line
- mouse_x = slider.x if mouse_x < slider.x
- mouse_x = slider.x + slider.w if mouse_x > slider.x + slider.w
+ mouse_x = slider.x if mouse_x < slider.x
+ mouse_x = slider.x + slider.w if mouse_x > slider.x + slider.w
# Sets the current search step to the one represented by the mouse x value
# The slider's circle moves due to the render_slider method using anim_steps
state.anim_steps = ((mouse_x - slider.x) / slider.spacing).to_i
- recalculate
+ recalculate
end
# Whenever the user edits the grid,
@@ -496,11 +496,11 @@ class BreadthFirstSearch
# with the current grid as the initial state of the grid
def recalculate
# Resets the search
- state.frontier = []
- state.visited = {}
+ state.frontier = []
+ state.visited = {}
# Moves the animation forward one step at a time
- state.anim_steps.times { calc }
+ state.anim_steps.times { calc }
end
@@ -515,39 +515,39 @@ class BreadthFirstSearch
# The setup to the search
# Runs once when the there is no frontier or visited cells
- if state.frontier.empty? && state.visited.empty?
- state.frontier << state.star
- state.visited[state.star] = true
+ if state.frontier.empty? && state.visited.empty?
+ state.frontier << state.star
+ state.visited[state.star] = true
end
# A step in the search
- unless state.frontier.empty?
+ unless state.frontier.empty?
# Takes the next frontier cell
- new_frontier = state.frontier.shift
+ new_frontier = state.frontier.shift
# For each of its neighbors
- adjacent_neighbors(new_frontier).each do |neighbor|
+ adjacent_neighbors(new_frontier).each do |neighbor|
# That have not been visited and are not walls
- unless state.visited.has_key?(neighbor) || state.walls.has_key?(neighbor)
+ unless state.visited.has_key?(neighbor) || state.walls.has_key?(neighbor)
# Add them to the frontier and mark them as visited
- state.frontier << neighbor
- state.visited[neighbor] = true
+ state.frontier << neighbor
+ state.visited[neighbor] = true
end
end
end
end
-
+
# Returns a list of adjacent cells
# Used to determine what the next cells to be added to the frontier are
def adjacent_neighbors(cell)
- neighbors = []
+ neighbors = []
- neighbors << [cell.x, cell.y + 1] unless cell.y == grid.height - 1
- neighbors << [cell.x + 1, cell.y] unless cell.x == grid.width - 1
- neighbors << [cell.x, cell.y - 1] unless cell.y == 0
- neighbors << [cell.x - 1, cell.y] unless cell.x == 0
+ neighbors << [cell.x, cell.y + 1] unless cell.y == grid.height - 1
+ neighbors << [cell.x + 1, cell.y] unless cell.x == grid.width - 1
+ neighbors << [cell.x, cell.y - 1] unless cell.y == 0
+ neighbors << [cell.x - 1, cell.y] unless cell.x == 0
- neighbors
+ neighbors
end
# When the user grabs the star and puts their cursor to the far right
@@ -555,13 +555,13 @@ class BreadthFirstSearch
# Finding the cell closest to the mouse helps with this
def cell_closest_to_mouse
# Closest cell to the mouse
- x = (inputs.mouse.point.x / grid.cell_size).to_i
- y = (inputs.mouse.point.y / grid.cell_size).to_i
+ x = (inputs.mouse.point.x / grid.cell_size).to_i
+ y = (inputs.mouse.point.y / grid.cell_size).to_i
# Bound x and y to the grid
- x = grid.width - 1 if x > grid.width - 1
- y = grid.height - 1 if y > grid.height - 1
+ x = grid.width - 1 if x > grid.width - 1
+ y = grid.height - 1 if y > grid.height - 1
# Return closest cell
- [x, y]
+ [x, y]
end
# These methods detect when the buttons are clicked
@@ -605,7 +605,7 @@ class BreadthFirstSearch
# Part of the condition that checks whether the user is removing a wall
def mouse_inside_a_wall?
state.walls.each_key do | wall |
- return true if inputs.mouse.point.inside_rect?(scale_up(wall))
+ return true if inputs.mouse.point.inside_rect?(scale_up([wall.x, wall.y]))
end
false
@@ -622,27 +622,27 @@ class BreadthFirstSearch
# Light brown
def unvisited_color
- [221, 212, 213]
+ [221, 212, 213]
end
# Black
def grid_line_color
- [255, 255, 255]
+ [255, 255, 255]
end
# Dark Brown
def visited_color
- [204, 191, 179]
+ [204, 191, 179]
end
# Blue
def frontier_color
- [103, 136, 204]
+ [103, 136, 204]
end
# Camo Green
def wall_color
- [134, 134, 120]
+ [134, 134, 120]
end
# Button Background
diff --git a/samples/13_path_finding_algorithms/01_breadth_first_search/replay.txt b/samples/13_path_finding_algorithms/01_breadth_first_search/replay.txt
new file mode 100644
index 0000000..62f4aca
--- /dev/null
+++ b/samples/13_path_finding_algorithms/01_breadth_first_search/replay.txt
@@ -0,0 +1,203 @@
+replay_version 2.0
+stopped_at 213
+seed 100
+recorded_at 2021-11-20 11:17:21 -0600
+[:mouse_button_up, 1, 0, 1, 1, 4]
+[:mouse_move, 780, 95, 2, 2, 11]
+[:mouse_move, 781, 95, 2, 3, 12]
+[:mouse_move, 782, 95, 2, 4, 13]
+[:mouse_move, 783, 95, 2, 5, 14]
+[:mouse_move, 771, 95, 2, 6, 32]
+[:mouse_move, 752, 95, 2, 7, 32]
+[:mouse_move, 718, 95, 2, 8, 34]
+[:mouse_move, 652, 95, 2, 9, 34]
+[:mouse_move, 549, 95, 2, 10, 35]
+[:mouse_move, 462, 101, 2, 11, 36]
+[:mouse_move, 425, 106, 2, 12, 37]
+[:mouse_move, 405, 108, 2, 13, 38]
+[:mouse_move, 406, 109, 2, 14, 39]
+[:mouse_move, 412, 111, 2, 15, 40]
+[:mouse_move, 429, 111, 2, 16, 41]
+[:mouse_move, 450, 109, 2, 17, 42]
+[:mouse_move, 460, 107, 2, 18, 42]
+[:mouse_move, 460, 106, 2, 19, 43]
+[:mouse_move, 460, 105, 2, 20, 45]
+[:mouse_move, 460, 104, 2, 21, 46]
+[:mouse_move, 456, 104, 2, 22, 47]
+[:mouse_move, 469, 104, 2, 23, 49]
+[:mouse_move, 489, 103, 2, 24, 50]
+[:mouse_move, 512, 100, 2, 25, 51]
+[:mouse_move, 536, 96, 2, 26, 52]
+[:mouse_move, 565, 92, 2, 27, 52]
+[:mouse_move, 587, 92, 2, 28, 53]
+[:mouse_move, 597, 92, 2, 29, 54]
+[:mouse_move, 599, 92, 2, 30, 55]
+[:mouse_button_pressed, 1, 0, 1, 31, 59]
+[:mouse_button_up, 1, 0, 1, 32, 62]
+[:mouse_move, 599, 91, 2, 33, 65]
+[:mouse_move, 590, 86, 2, 34, 65]
+[:mouse_move, 570, 78, 2, 35, 66]
+[:mouse_move, 543, 70, 2, 36, 66]
+[:mouse_move, 516, 65, 2, 37, 67]
+[:mouse_move, 481, 61, 2, 38, 68]
+[:mouse_move, 449, 59, 2, 39, 69]
+[:mouse_move, 429, 57, 2, 40, 69]
+[:mouse_move, 424, 56, 2, 41, 70]
+[:mouse_move, 426, 56, 2, 42, 74]
+[:mouse_move, 429, 56, 2, 43, 75]
+[:mouse_move, 431, 56, 2, 44, 75]
+[:mouse_move, 433, 56, 2, 45, 76]
+[:mouse_move, 435, 55, 2, 46, 77]
+[:mouse_move, 437, 55, 2, 47, 78]
+[:mouse_move, 440, 55, 2, 48, 78]
+[:mouse_move, 444, 55, 2, 49, 79]
+[:mouse_move, 445, 54, 2, 50, 79]
+[:mouse_move, 444, 53, 2, 51, 81]
+[:mouse_move, 444, 52, 2, 52, 82]
+[:mouse_move, 443, 51, 2, 53, 89]
+[:mouse_button_pressed, 1, 0, 1, 54, 89]
+[:mouse_move, 442, 51, 2, 55, 89]
+[:mouse_move, 436, 51, 2, 56, 90]
+[:mouse_move, 432, 49, 2, 57, 91]
+[:mouse_move, 431, 49, 2, 58, 91]
+[:mouse_move, 429, 49, 2, 59, 92]
+[:mouse_move, 428, 49, 2, 60, 93]
+[:mouse_move, 426, 49, 2, 61, 94]
+[:mouse_move, 425, 49, 2, 62, 94]
+[:mouse_move, 424, 49, 2, 63, 95]
+[:mouse_move, 423, 49, 2, 64, 96]
+[:mouse_move, 422, 49, 2, 65, 98]
+[:mouse_move, 421, 49, 2, 66, 99]
+[:mouse_move, 420, 49, 2, 67, 99]
+[:mouse_move, 419, 49, 2, 68, 100]
+[:mouse_move, 417, 49, 2, 69, 100]
+[:mouse_move, 415, 49, 2, 70, 101]
+[:mouse_move, 414, 49, 2, 71, 102]
+[:mouse_move, 413, 49, 2, 72, 108]
+[:mouse_move, 415, 49, 2, 73, 124]
+[:mouse_move, 416, 49, 2, 74, 125]
+[:mouse_move, 420, 49, 2, 75, 126]
+[:mouse_move, 424, 49, 2, 76, 127]
+[:mouse_move, 429, 49, 2, 77, 128]
+[:mouse_move, 433, 49, 2, 78, 128]
+[:mouse_move, 441, 49, 2, 79, 129]
+[:mouse_move, 450, 49, 2, 80, 129]
+[:mouse_move, 460, 49, 2, 81, 130]
+[:mouse_move, 472, 49, 2, 82, 131]
+[:mouse_move, 480, 49, 2, 83, 131]
+[:mouse_move, 486, 49, 2, 84, 132]
+[:mouse_move, 488, 49, 2, 85, 132]
+[:mouse_move, 492, 49, 2, 86, 132]
+[:mouse_move, 498, 49, 2, 87, 133]
+[:mouse_move, 507, 49, 2, 88, 133]
+[:mouse_move, 513, 48, 2, 89, 134]
+[:mouse_move, 518, 47, 2, 90, 134]
+[:mouse_move, 523, 47, 2, 91, 134]
+[:mouse_move, 529, 46, 2, 92, 135]
+[:mouse_move, 533, 46, 2, 93, 135]
+[:mouse_move, 538, 46, 2, 94, 135]
+[:mouse_move, 543, 46, 2, 95, 136]
+[:mouse_move, 545, 46, 2, 96, 136]
+[:mouse_move, 546, 46, 2, 97, 136]
+[:mouse_move, 551, 46, 2, 98, 137]
+[:mouse_move, 558, 46, 2, 99, 137]
+[:mouse_move, 567, 46, 2, 100, 138]
+[:mouse_move, 573, 46, 2, 101, 138]
+[:mouse_move, 576, 45, 2, 102, 138]
+[:mouse_move, 579, 45, 2, 103, 138]
+[:mouse_move, 581, 45, 2, 104, 138]
+[:mouse_move, 584, 45, 2, 105, 139]
+[:mouse_move, 590, 45, 2, 106, 139]
+[:mouse_move, 597, 45, 2, 107, 139]
+[:mouse_move, 602, 45, 2, 108, 140]
+[:mouse_move, 606, 45, 2, 109, 140]
+[:mouse_move, 611, 45, 2, 110, 140]
+[:mouse_move, 617, 45, 2, 111, 140]
+[:mouse_move, 625, 45, 2, 112, 140]
+[:mouse_move, 632, 45, 2, 113, 140]
+[:mouse_move, 638, 45, 2, 114, 141]
+[:mouse_move, 643, 45, 2, 115, 141]
+[:mouse_move, 644, 44, 2, 116, 141]
+[:mouse_move, 646, 44, 2, 117, 141]
+[:mouse_move, 647, 44, 2, 118, 142]
+[:mouse_move, 650, 44, 2, 119, 142]
+[:mouse_move, 653, 44, 2, 120, 142]
+[:mouse_move, 656, 44, 2, 121, 142]
+[:mouse_move, 658, 43, 2, 122, 142]
+[:mouse_move, 659, 43, 2, 123, 143]
+[:mouse_move, 663, 43, 2, 124, 143]
+[:mouse_move, 665, 43, 2, 125, 143]
+[:mouse_move, 667, 43, 2, 126, 143]
+[:mouse_move, 669, 43, 2, 127, 143]
+[:mouse_move, 670, 43, 2, 128, 143]
+[:mouse_move, 671, 43, 2, 129, 143]
+[:mouse_move, 672, 43, 2, 130, 144]
+[:mouse_move, 674, 43, 2, 131, 144]
+[:mouse_move, 677, 43, 2, 132, 144]
+[:mouse_move, 679, 43, 2, 133, 144]
+[:mouse_move, 680, 43, 2, 134, 144]
+[:mouse_move, 681, 43, 2, 135, 144]
+[:mouse_move, 683, 43, 2, 136, 145]
+[:mouse_move, 684, 43, 2, 137, 145]
+[:mouse_move, 685, 43, 2, 138, 145]
+[:mouse_move, 686, 43, 2, 139, 145]
+[:mouse_move, 687, 43, 2, 140, 145]
+[:mouse_move, 688, 43, 2, 141, 146]
+[:mouse_button_up, 1, 0, 1, 142, 150]
+[:mouse_move, 688, 44, 2, 143, 150]
+[:mouse_move, 685, 45, 2, 144, 150]
+[:mouse_move, 674, 47, 2, 145, 150]
+[:mouse_move, 657, 52, 2, 146, 150]
+[:mouse_move, 621, 57, 2, 147, 151]
+[:mouse_move, 593, 62, 2, 148, 151]
+[:mouse_move, 568, 65, 2, 149, 151]
+[:mouse_move, 550, 68, 2, 150, 151]
+[:mouse_move, 542, 69, 2, 151, 152]
+[:mouse_move, 539, 69, 2, 152, 152]
+[:mouse_move, 536, 70, 2, 153, 152]
+[:mouse_move, 534, 70, 2, 154, 153]
+[:mouse_move, 531, 72, 2, 155, 153]
+[:mouse_move, 528, 73, 2, 156, 153]
+[:mouse_move, 522, 75, 2, 157, 154]
+[:mouse_move, 515, 80, 2, 158, 154]
+[:mouse_move, 514, 81, 2, 159, 154]
+[:mouse_move, 513, 81, 2, 160, 154]
+[:mouse_move, 509, 84, 2, 161, 156]
+[:mouse_move, 502, 88, 2, 162, 156]
+[:mouse_move, 491, 93, 2, 163, 156]
+[:mouse_move, 487, 97, 2, 164, 156]
+[:mouse_move, 486, 97, 2, 165, 156]
+[:mouse_move, 487, 96, 2, 166, 157]
+[:mouse_button_pressed, 1, 0, 1, 167, 159]
+[:mouse_button_up, 1, 0, 1, 168, 160]
+[:mouse_button_pressed, 1, 0, 1, 169, 161]
+[:mouse_move, 488, 96, 2, 170, 161]
+[:mouse_button_up, 1, 0, 1, 171, 161]
+[:mouse_move, 488, 97, 2, 172, 166]
+[:mouse_move, 487, 97, 2, 173, 166]
+[:mouse_move, 486, 97, 2, 174, 167]
+[:mouse_move, 485, 97, 2, 175, 167]
+[:mouse_move, 484, 97, 2, 176, 168]
+[:mouse_button_pressed, 1, 0, 1, 177, 172]
+[:mouse_button_up, 1, 0, 1, 178, 173]
+[:mouse_move, 485, 97, 2, 179, 185]
+[:key_down_raw, 96, 0, 2, 180, 191]
+[:mouse_move, 486, 96, 2, 181, 192]
+[:mouse_move, 488, 96, 2, 182, 192]
+[:mouse_move, 495, 94, 2, 183, 192]
+[:key_up_raw, 96, 0, 2, 184, 192]
+[:mouse_move, 503, 93, 2, 185, 193]
+[:mouse_move, 514, 92, 2, 186, 193]
+[:mouse_move, 544, 92, 2, 187, 193]
+[:mouse_move, 573, 92, 2, 188, 194]
+[:mouse_move, 607, 92, 2, 189, 194]
+[:mouse_move, 641, 89, 2, 190, 194]
+[:mouse_move, 674, 89, 2, 191, 194]
+[:mouse_move, 705, 89, 2, 192, 194]
+[:mouse_move, 735, 89, 2, 193, 195]
+[:mouse_move, 759, 89, 2, 194, 195]
+[:mouse_move, 776, 89, 2, 195, 195]
+[:mouse_move, 784, 89, 2, 196, 195]
+[:mouse_move, 786, 89, 2, 197, 196]
+[:mouse_move, 786, 90, 2, 198, 204]
+[:key_down_raw, 13, 0, 2, 199, 213]
diff --git a/samples/13_path_finding_algorithms/02_detailed_breadth_first_search/replay.txt b/samples/13_path_finding_algorithms/02_detailed_breadth_first_search/replay.txt
new file mode 100644
index 0000000..aa8719b
--- /dev/null
+++ b/samples/13_path_finding_algorithms/02_detailed_breadth_first_search/replay.txt
@@ -0,0 +1,241 @@
+replay_version 2.0
+stopped_at 435
+seed 100
+recorded_at 2021-11-20 11:18:03 -0600
+[:mouse_button_up, 1, 0, 1, 1, 4]
+[:mouse_move, 789, 89, 2, 2, 27]
+[:mouse_move, 785, 90, 2, 3, 28]
+[:mouse_move, 768, 94, 2, 4, 29]
+[:mouse_move, 752, 99, 2, 5, 30]
+[:mouse_move, 737, 104, 2, 6, 31]
+[:mouse_move, 729, 104, 2, 7, 32]
+[:mouse_move, 724, 104, 2, 8, 33]
+[:mouse_move, 720, 103, 2, 9, 34]
+[:mouse_move, 711, 103, 2, 10, 35]
+[:mouse_move, 702, 103, 2, 11, 36]
+[:mouse_move, 698, 103, 2, 12, 37]
+[:mouse_move, 697, 103, 2, 13, 38]
+[:mouse_move, 696, 103, 2, 14, 40]
+[:mouse_move, 694, 104, 2, 15, 41]
+[:mouse_move, 684, 104, 2, 16, 42]
+[:mouse_move, 666, 104, 2, 17, 43]
+[:mouse_move, 645, 105, 2, 18, 44]
+[:mouse_move, 626, 106, 2, 19, 45]
+[:mouse_move, 615, 106, 2, 20, 46]
+[:mouse_move, 609, 106, 2, 21, 47]
+[:mouse_move, 606, 106, 2, 22, 48]
+[:mouse_move, 605, 106, 2, 23, 49]
+[:mouse_move, 600, 104, 2, 24, 50]
+[:mouse_move, 590, 100, 2, 25, 51]
+[:mouse_move, 579, 97, 2, 26, 52]
+[:mouse_move, 575, 96, 2, 27, 53]
+[:mouse_move, 581, 96, 2, 28, 58]
+[:mouse_move, 596, 98, 2, 29, 59]
+[:mouse_move, 614, 98, 2, 30, 60]
+[:mouse_move, 635, 97, 2, 31, 61]
+[:mouse_move, 652, 94, 2, 32, 62]
+[:mouse_move, 657, 93, 2, 33, 63]
+[:mouse_move, 658, 92, 2, 34, 64]
+[:mouse_button_pressed, 1, 0, 1, 35, 70]
+[:mouse_move, 659, 92, 2, 36, 70]
+[:mouse_button_up, 1, 0, 1, 37, 74]
+[:mouse_move, 660, 92, 2, 38, 87]
+[:mouse_button_pressed, 1, 0, 1, 39, 92]
+[:mouse_button_up, 1, 0, 1, 40, 98]
+[:mouse_move, 661, 92, 2, 41, 101]
+[:mouse_button_pressed, 1, 0, 1, 42, 103]
+[:mouse_button_up, 1, 0, 1, 43, 108]
+[:mouse_move, 662, 92, 2, 44, 112]
+[:mouse_button_pressed, 1, 0, 1, 45, 113]
+[:mouse_button_up, 1, 0, 1, 46, 119]
+[:mouse_move, 657, 92, 2, 47, 125]
+[:mouse_move, 641, 92, 2, 48, 126]
+[:mouse_move, 623, 93, 2, 49, 127]
+[:mouse_move, 610, 95, 2, 50, 128]
+[:mouse_move, 599, 97, 2, 51, 129]
+[:mouse_move, 588, 98, 2, 52, 130]
+[:mouse_move, 584, 99, 2, 53, 131]
+[:mouse_move, 581, 99, 2, 54, 132]
+[:mouse_move, 580, 99, 2, 55, 133]
+[:mouse_move, 575, 99, 2, 56, 134]
+[:mouse_move, 572, 99, 2, 57, 135]
+[:mouse_move, 570, 99, 2, 58, 136]
+[:mouse_move, 564, 101, 2, 59, 137]
+[:mouse_move, 559, 101, 2, 60, 138]
+[:mouse_move, 557, 101, 2, 61, 139]
+[:mouse_move, 555, 102, 2, 62, 140]
+[:mouse_move, 554, 102, 2, 63, 141]
+[:mouse_button_pressed, 1, 0, 1, 64, 145]
+[:mouse_button_up, 1, 0, 1, 65, 149]
+[:mouse_button_pressed, 1, 0, 1, 66, 154]
+[:mouse_move, 555, 102, 2, 67, 154]
+[:mouse_button_up, 1, 0, 1, 68, 159]
+[:mouse_button_pressed, 1, 0, 1, 69, 163]
+[:mouse_button_up, 1, 0, 1, 70, 168]
+[:mouse_move, 555, 103, 2, 71, 168]
+[:mouse_move, 539, 103, 2, 72, 169]
+[:mouse_move, 519, 100, 2, 73, 170]
+[:mouse_move, 498, 95, 2, 74, 171]
+[:mouse_move, 488, 90, 2, 75, 172]
+[:mouse_move, 484, 88, 2, 76, 173]
+[:mouse_move, 475, 81, 2, 77, 174]
+[:mouse_move, 460, 73, 2, 78, 175]
+[:mouse_move, 441, 64, 2, 79, 176]
+[:mouse_move, 424, 57, 2, 80, 177]
+[:mouse_move, 413, 53, 2, 81, 178]
+[:mouse_move, 408, 50, 2, 82, 179]
+[:mouse_move, 407, 49, 2, 83, 182]
+[:mouse_move, 405, 47, 2, 84, 183]
+[:mouse_move, 404, 46, 2, 85, 184]
+[:mouse_move, 404, 45, 2, 86, 185]
+[:mouse_move, 403, 45, 2, 87, 186]
+[:mouse_button_pressed, 1, 0, 1, 88, 195]
+[:mouse_move, 406, 45, 2, 89, 197]
+[:mouse_move, 413, 45, 2, 90, 198]
+[:mouse_move, 423, 45, 2, 91, 199]
+[:mouse_move, 434, 45, 2, 92, 200]
+[:mouse_move, 446, 45, 2, 93, 201]
+[:mouse_move, 461, 45, 2, 94, 202]
+[:mouse_move, 472, 45, 2, 95, 203]
+[:mouse_move, 480, 45, 2, 96, 204]
+[:mouse_move, 486, 45, 2, 97, 205]
+[:mouse_move, 492, 45, 2, 98, 206]
+[:mouse_move, 495, 45, 2, 99, 207]
+[:mouse_move, 496, 45, 2, 100, 208]
+[:mouse_move, 497, 45, 2, 101, 209]
+[:mouse_move, 498, 45, 2, 102, 210]
+[:mouse_move, 501, 45, 2, 103, 211]
+[:mouse_move, 507, 45, 2, 104, 212]
+[:mouse_move, 512, 45, 2, 105, 213]
+[:mouse_move, 516, 45, 2, 106, 214]
+[:mouse_move, 518, 45, 2, 107, 215]
+[:mouse_move, 519, 45, 2, 108, 216]
+[:mouse_move, 520, 45, 2, 109, 217]
+[:mouse_move, 522, 45, 2, 110, 218]
+[:mouse_move, 525, 45, 2, 111, 219]
+[:mouse_move, 533, 45, 2, 112, 220]
+[:mouse_move, 537, 45, 2, 113, 221]
+[:mouse_move, 541, 45, 2, 114, 222]
+[:mouse_move, 545, 45, 2, 115, 223]
+[:mouse_move, 546, 45, 2, 116, 224]
+[:mouse_move, 547, 45, 2, 117, 226]
+[:mouse_move, 549, 45, 2, 118, 227]
+[:mouse_move, 554, 45, 2, 119, 228]
+[:mouse_move, 556, 45, 2, 120, 229]
+[:mouse_move, 560, 45, 2, 121, 230]
+[:mouse_move, 566, 45, 2, 122, 231]
+[:mouse_move, 570, 45, 2, 123, 232]
+[:mouse_move, 577, 45, 2, 124, 233]
+[:mouse_move, 585, 45, 2, 125, 234]
+[:mouse_move, 593, 46, 2, 126, 235]
+[:mouse_move, 602, 48, 2, 127, 236]
+[:mouse_move, 609, 48, 2, 128, 237]
+[:mouse_move, 614, 48, 2, 129, 238]
+[:mouse_move, 619, 48, 2, 130, 239]
+[:mouse_move, 625, 49, 2, 131, 240]
+[:mouse_move, 633, 49, 2, 132, 241]
+[:mouse_move, 643, 49, 2, 133, 242]
+[:mouse_move, 651, 49, 2, 134, 243]
+[:mouse_move, 658, 49, 2, 135, 243]
+[:mouse_move, 664, 49, 2, 136, 244]
+[:mouse_move, 669, 49, 2, 137, 245]
+[:mouse_move, 675, 49, 2, 138, 246]
+[:mouse_move, 679, 49, 2, 139, 247]
+[:mouse_move, 682, 49, 2, 140, 248]
+[:mouse_move, 686, 49, 2, 141, 249]
+[:mouse_move, 689, 49, 2, 142, 250]
+[:mouse_move, 691, 49, 2, 143, 251]
+[:mouse_move, 697, 49, 2, 144, 252]
+[:mouse_move, 706, 49, 2, 145, 253]
+[:mouse_move, 715, 49, 2, 146, 254]
+[:mouse_move, 723, 49, 2, 147, 255]
+[:mouse_move, 730, 49, 2, 148, 256]
+[:mouse_move, 733, 49, 2, 149, 256]
+[:mouse_move, 734, 49, 2, 150, 257]
+[:mouse_move, 737, 49, 2, 151, 258]
+[:mouse_move, 742, 49, 2, 152, 259]
+[:mouse_move, 749, 49, 2, 153, 260]
+[:mouse_move, 755, 49, 2, 154, 261]
+[:mouse_move, 758, 49, 2, 155, 262]
+[:mouse_move, 760, 49, 2, 156, 263]
+[:mouse_move, 761, 49, 2, 157, 264]
+[:mouse_move, 762, 49, 2, 158, 266]
+[:mouse_move, 763, 49, 2, 159, 268]
+[:mouse_move, 763, 48, 2, 160, 269]
+[:mouse_move, 757, 48, 2, 161, 290]
+[:mouse_move, 746, 48, 2, 162, 291]
+[:mouse_move, 732, 48, 2, 163, 291]
+[:mouse_move, 716, 48, 2, 164, 292]
+[:mouse_move, 698, 48, 2, 165, 293]
+[:mouse_move, 684, 47, 2, 166, 294]
+[:mouse_move, 673, 46, 2, 167, 295]
+[:mouse_move, 665, 44, 2, 168, 296]
+[:mouse_move, 660, 44, 2, 169, 297]
+[:mouse_move, 656, 44, 2, 170, 297]
+[:mouse_move, 652, 44, 2, 171, 298]
+[:mouse_move, 648, 44, 2, 172, 299]
+[:mouse_move, 637, 44, 2, 173, 300]
+[:mouse_move, 628, 44, 2, 174, 301]
+[:mouse_move, 618, 44, 2, 175, 302]
+[:mouse_move, 609, 44, 2, 176, 303]
+[:mouse_move, 602, 44, 2, 177, 304]
+[:mouse_move, 598, 43, 2, 178, 305]
+[:mouse_move, 596, 43, 2, 179, 306]
+[:mouse_move, 595, 43, 2, 180, 307]
+[:mouse_move, 594, 42, 2, 181, 308]
+[:mouse_move, 593, 42, 2, 182, 308]
+[:mouse_move, 591, 42, 2, 183, 309]
+[:mouse_move, 588, 42, 2, 184, 310]
+[:mouse_move, 586, 42, 2, 185, 311]
+[:mouse_move, 584, 42, 2, 186, 312]
+[:mouse_move, 582, 42, 2, 187, 313]
+[:mouse_move, 576, 42, 2, 188, 314]
+[:mouse_move, 570, 42, 2, 189, 315]
+[:mouse_move, 562, 42, 2, 190, 316]
+[:mouse_move, 554, 42, 2, 191, 317]
+[:mouse_move, 547, 42, 2, 192, 318]
+[:mouse_move, 537, 42, 2, 193, 319]
+[:mouse_move, 532, 42, 2, 194, 320]
+[:mouse_move, 528, 42, 2, 195, 321]
+[:mouse_move, 527, 42, 2, 196, 322]
+[:mouse_move, 526, 42, 2, 197, 323]
+[:mouse_move, 525, 42, 2, 198, 324]
+[:mouse_move, 524, 42, 2, 199, 325]
+[:mouse_move, 522, 42, 2, 200, 326]
+[:mouse_move, 521, 42, 2, 201, 327]
+[:mouse_move, 520, 42, 2, 202, 328]
+[:mouse_move, 519, 42, 2, 203, 329]
+[:mouse_move, 516, 42, 2, 204, 330]
+[:mouse_move, 513, 42, 2, 205, 331]
+[:mouse_move, 512, 42, 2, 206, 332]
+[:mouse_move, 509, 42, 2, 207, 333]
+[:mouse_move, 497, 42, 2, 208, 334]
+[:mouse_move, 490, 42, 2, 209, 335]
+[:mouse_move, 486, 42, 2, 210, 336]
+[:mouse_move, 483, 42, 2, 211, 337]
+[:mouse_move, 482, 42, 2, 212, 338]
+[:mouse_move, 481, 42, 2, 213, 339]
+[:mouse_button_up, 1, 0, 1, 214, 354]
+[:mouse_move, 484, 43, 2, 215, 361]
+[:mouse_move, 497, 47, 2, 216, 362]
+[:mouse_move, 513, 51, 2, 217, 363]
+[:mouse_move, 530, 55, 2, 218, 364]
+[:mouse_move, 544, 58, 2, 219, 365]
+[:mouse_move, 562, 63, 2, 220, 366]
+[:mouse_move, 589, 71, 2, 221, 367]
+[:mouse_move, 623, 81, 2, 222, 368]
+[:mouse_move, 656, 91, 2, 223, 369]
+[:mouse_move, 687, 95, 2, 224, 370]
+[:mouse_move, 731, 102, 2, 225, 371]
+[:mouse_move, 762, 110, 2, 226, 372]
+[:mouse_move, 792, 117, 2, 227, 373]
+[:mouse_move, 819, 123, 2, 228, 374]
+[:key_down_raw, 96, 0, 2, 229, 375]
+[:mouse_move, 842, 125, 2, 230, 375]
+[:mouse_move, 859, 128, 2, 231, 376]
+[:mouse_move, 871, 130, 2, 232, 377]
+[:mouse_move, 878, 131, 2, 233, 378]
+[:mouse_move, 879, 131, 2, 234, 379]
+[:key_up_raw, 96, 0, 2, 235, 379]
+[:mouse_move, 878, 131, 2, 236, 411]
+[:key_down_raw, 13, 0, 2, 237, 435]
diff --git a/samples/13_path_finding_algorithms/03_breadcrumbs/app/main.rb b/samples/13_path_finding_algorithms/03_breadcrumbs/app/main.rb
index 648805a..533a962 100644
--- a/samples/13_path_finding_algorithms/03_breadcrumbs/app/main.rb
+++ b/samples/13_path_finding_algorithms/03_breadcrumbs/app/main.rb
@@ -12,8 +12,8 @@ class Breadcrumbs
calc
# Calc Path
end
- render
- input
+ render
+ input
end
def defaults
@@ -90,7 +90,7 @@ class Breadcrumbs
[24, 9] => true,
[25, 8] => true,
[25, 9] => true,
- }
+ }
# Variables that are used by the breadth first search
# Storing cells that the search has visited, prevents unnecessary steps
@@ -109,36 +109,36 @@ class Breadcrumbs
# We store this value, because we want to remember the value even when
# the user's cursor is no longer over what they're interacting with, but
# they are still clicking down on the mouse.
- state.current_input ||= :none
+ state.current_input ||= :none
end
def calc
# Setup the search to start from the star
- search.frontier << grid.star
+ search.frontier << grid.star
search.came_from[grid.star] = nil
# Until there are no more cells to expand from
- until search.frontier.empty?
+ until search.frontier.empty?
# Takes the next frontier cell
- new_frontier = search.frontier.shift
+ new_frontier = search.frontier.shift
# For each of its neighbors
- adjacent_neighbors(new_frontier).each do |neighbor|
+ adjacent_neighbors(new_frontier).each do |neighbor|
# That have not been visited and are not walls
- unless search.came_from.has_key?(neighbor) || grid.walls.has_key?(neighbor)
+ unless search.came_from.has_key?(neighbor) || grid.walls.has_key?(neighbor)
# Add them to the frontier and mark them as visited in the first grid
# Unless the target has been visited
# Add the neighbor to the frontier and remember which cell it came from
- search.frontier << neighbor
+ search.frontier << neighbor
search.came_from[neighbor] = new_frontier
end
end
end
end
-
+
# Draws everything onto the screen
def render
- render_background
+ render_background
# render_heat_map
render_walls
# render_path
@@ -157,7 +157,7 @@ class Breadcrumbs
if current_cell && parent_cell
outputs.lines << [(current_cell.x + 0.5) * grid.cell_size, (current_cell.y + 0.5) * grid.cell_size,
(parent_cell.x + 0.5) * grid.cell_size, (parent_cell.y + 0.5) * grid.cell_size, purple]
-
+
end
render_trail(parent_cell)
end
@@ -183,8 +183,8 @@ class Breadcrumbs
# Draws what the grid looks like with nothing on it
def render_background
- render_unvisited
- render_grid_lines
+ render_unvisited
+ render_grid_lines
end
# Draws both grids
@@ -199,7 +199,7 @@ class Breadcrumbs
end
for y in 0..grid.height
- outputs.lines << horizontal_line(y)
+ outputs.lines << horizontal_line(y)
end
end
@@ -215,7 +215,7 @@ class Breadcrumbs
# Draws the walls on both grids
def render_walls
- grid.walls.each_key do |wall|
+ grid.walls.each_key do |wall|
outputs.solids << [scale_up(wall), wall_color]
end
end
@@ -223,12 +223,12 @@ class Breadcrumbs
# Renders the star on both grids
def render_star
outputs.sprites << [scale_up(grid.star), 'star.png']
- end
+ end
# Renders the target on both grids
def render_target
outputs.sprites << [scale_up(grid.target), 'target.png']
- end
+ end
# Labels the grids
def render_labels
@@ -288,14 +288,14 @@ class Breadcrumbs
# The program has to remember that the user is dragging an object
# even when the mouse is no longer over that object
# So detecting input and processing input is separate
- # detect_input
- # process_input
+ # detect_input
+ # process_input
if inputs.mouse.up
state.current_input = :none
elsif star_clicked?
state.current_input = :star
end
-
+
if mouse_inside_grid?
unless grid.target == cell_closest_to_mouse
grid.target = cell_closest_to_mouse
@@ -313,33 +313,33 @@ class Breadcrumbs
# mouse left click is held
def detect_input
# When the mouse is up, nothing is being edited
- if inputs.mouse.up
- state.current_input = :none
+ if inputs.mouse.up
+ state.current_input = :none
# When the star in the no second grid is clicked
- elsif star_clicked?
- state.current_input = :star
+ elsif star_clicked?
+ state.current_input = :star
# When the target in the no second grid is clicked
- elsif target_clicked?
- state.current_input = :target
+ elsif target_clicked?
+ state.current_input = :target
# When a wall in the first grid is clicked
- elsif wall_clicked?
- state.current_input = :remove_wall
+ elsif wall_clicked?
+ state.current_input = :remove_wall
# When the first grid is clicked
- elsif grid_clicked?
+ elsif grid_clicked?
state.current_input = :add_wall
end
end
# Processes click and drag based on what the user is currently dragging
def process_input
- if state.current_input == :star
- input_star
- elsif state.current_input == :target
- input_target
- elsif state.current_input == :remove_wall
- input_remove_wall
- elsif state.current_input == :add_wall
- input_add_wall
+ if state.current_input == :star
+ input_star
+ elsif state.current_input == :target
+ input_target
+ elsif state.current_input == :remove_wall
+ input_remove_wall
+ elsif state.current_input == :add_wall
+ input_add_wall
end
end
@@ -347,10 +347,10 @@ class Breadcrumbs
# Only resets the search if the star changes position
# Called whenever the user is editing the star (puts mouse down on star)
def input_star
- old_star = grid.star.clone
+ old_star = grid.star.clone
grid.star = cell_closest_to_mouse
- unless old_star == grid.star
- reset_search
+ unless old_star == grid.star
+ reset_search
end
end
@@ -358,10 +358,10 @@ class Breadcrumbs
# Only reset_searchs the search if the target changes position
# Called whenever the user is editing the target (puts mouse down on target)
def input_target
- old_target = grid.target.clone
+ old_target = grid.target.clone
grid.target = cell_closest_to_mouse
- unless old_target == grid.target
- reset_search
+ unless old_target == grid.target
+ reset_search
end
end
@@ -370,32 +370,32 @@ class Breadcrumbs
# The mouse needs to be inside the grid, because we only want to remove walls
# the cursor is directly over
# Recalculations should only occur when a wall is actually deleted
- if mouse_inside_grid?
+ if mouse_inside_grid?
if grid.walls.has_key?(cell_closest_to_mouse)
- grid.walls.delete(cell_closest_to_mouse)
- reset_search
+ grid.walls.delete(cell_closest_to_mouse)
+ reset_search
end
end
end
# Adds a wall in the first grid in the cell the mouse is over
def input_add_wall
- if mouse_inside_grid?
+ if mouse_inside_grid?
unless grid.walls.has_key?(cell_closest_to_mouse)
- grid.walls[cell_closest_to_mouse] = true
- reset_search
+ grid.walls[cell_closest_to_mouse] = true
+ reset_search
end
end
end
-
+
# Whenever the user edits the grid,
# The search has to be reset_searchd upto the current step
# with the current grid as the initial state of the grid
def reset_search
# Reset_Searchs the search
- search.frontier = []
- search.came_from = {}
+ search.frontier = []
+ search.came_from = {}
search.path = {}
end
@@ -403,21 +403,21 @@ class Breadcrumbs
# Returns a list of adjacent cells
# Used to determine what the next cells to be added to the frontier are
def adjacent_neighbors(cell)
- neighbors = []
+ neighbors = []
# Gets all the valid neighbors into the array
# From southern neighbor, clockwise
- neighbors << [cell.x, cell.y - 1] unless cell.y == 0
- neighbors << [cell.x - 1, cell.y] unless cell.x == 0
- neighbors << [cell.x, cell.y + 1] unless cell.y == grid.height - 1
- neighbors << [cell.x + 1, cell.y] unless cell.x == grid.width - 1
+ neighbors << [cell.x, cell.y - 1] unless cell.y == 0
+ neighbors << [cell.x - 1, cell.y] unless cell.x == 0
+ neighbors << [cell.x, cell.y + 1] unless cell.y == grid.height - 1
+ neighbors << [cell.x + 1, cell.y] unless cell.x == grid.width - 1
# Sorts the neighbors so the rendered path is a zigzag path
# Cells in a diagonal direction are given priority
# Comment this line to see the difference
neighbors = neighbors.sort_by { |neighbor_x, neighbor_y| proximity_to_star(neighbor_x, neighbor_y) }
- neighbors
+ neighbors
end
# Finds the vertical and horizontal distance of a cell from the star
@@ -442,13 +442,13 @@ class Breadcrumbs
# Finding the cell closest to the mouse helps with this
def cell_closest_to_mouse
# Closest cell to the mouse in the first grid
- x = (inputs.mouse.point.x / grid.cell_size).to_i
- y = (inputs.mouse.point.y / grid.cell_size).to_i
+ x = (inputs.mouse.point.x / grid.cell_size).to_i
+ y = (inputs.mouse.point.y / grid.cell_size).to_i
# Bound x and y to the grid
- x = grid.width - 1 if x > grid.width - 1
- y = grid.height - 1 if y > grid.height - 1
+ x = grid.width - 1 if x > grid.width - 1
+ y = grid.height - 1 if y > grid.height - 1
# Return closest cell
- [x, y]
+ [x, y]
end
# Signal that the user is going to be moving the star from the first grid
@@ -476,13 +476,13 @@ class Breadcrumbs
# Light brown
def unvisited_color
- [221, 212, 213]
+ [221, 212, 213]
# [255, 255, 255]
end
# Camo Green
def wall_color
- [134, 134, 120]
+ [134, 134, 120]
end
# Pastel White
@@ -520,7 +520,7 @@ def tick args
end
# Every tick, new args are passed, and the Breadth First Search tick is called
- $breadcrumbs ||= Breadcrumbs.new(args)
+ $breadcrumbs ||= Breadcrumbs.new
$breadcrumbs.args = args
$breadcrumbs.tick
end
diff --git a/samples/13_path_finding_algorithms/03_breadcrumbs/replay.txt b/samples/13_path_finding_algorithms/03_breadcrumbs/replay.txt
new file mode 100644
index 0000000..4e98cf7
--- /dev/null
+++ b/samples/13_path_finding_algorithms/03_breadcrumbs/replay.txt
@@ -0,0 +1,365 @@
+replay_version 2.0
+stopped_at 211
+seed 100
+recorded_at 2021-11-20 11:18:41 -0600
+[:mouse_button_up, 1, 0, 1, 1, 1]
+[:mouse_move, 778, 91, 2, 2, 7]
+[:mouse_move, 778, 90, 2, 3, 7]
+[:mouse_move, 773, 94, 2, 4, 10]
+[:mouse_move, 748, 101, 2, 5, 11]
+[:mouse_move, 704, 112, 2, 6, 11]
+[:mouse_move, 656, 127, 2, 7, 11]
+[:mouse_move, 617, 138, 2, 8, 12]
+[:mouse_move, 595, 142, 2, 9, 12]
+[:mouse_move, 582, 143, 2, 10, 13]
+[:mouse_move, 574, 143, 2, 11, 13]
+[:mouse_move, 561, 144, 2, 12, 13]
+[:mouse_move, 550, 148, 2, 13, 13]
+[:mouse_move, 536, 155, 2, 14, 14]
+[:mouse_move, 519, 162, 2, 15, 14]
+[:mouse_move, 497, 168, 2, 16, 14]
+[:mouse_move, 475, 174, 2, 17, 15]
+[:mouse_move, 450, 179, 2, 18, 15]
+[:mouse_move, 420, 188, 2, 19, 15]
+[:mouse_move, 385, 200, 2, 20, 16]
+[:mouse_move, 350, 219, 2, 21, 16]
+[:mouse_move, 317, 239, 2, 22, 16]
+[:mouse_move, 278, 272, 2, 23, 17]
+[:mouse_move, 251, 292, 2, 24, 17]
+[:mouse_move, 229, 314, 2, 25, 17]
+[:mouse_move, 213, 335, 2, 26, 18]
+[:mouse_move, 205, 355, 2, 27, 18]
+[:mouse_move, 201, 375, 2, 28, 19]
+[:mouse_move, 199, 394, 2, 29, 19]
+[:mouse_move, 199, 409, 2, 30, 20]
+[:mouse_move, 199, 419, 2, 31, 20]
+[:mouse_move, 198, 427, 2, 32, 20]
+[:mouse_move, 198, 434, 2, 33, 20]
+[:mouse_move, 198, 441, 2, 34, 21]
+[:mouse_move, 198, 453, 2, 35, 21]
+[:mouse_move, 197, 457, 2, 36, 21]
+[:mouse_move, 188, 464, 2, 37, 22]
+[:mouse_move, 178, 470, 2, 38, 22]
+[:mouse_move, 169, 477, 2, 39, 22]
+[:mouse_move, 161, 484, 2, 40, 23]
+[:mouse_move, 148, 491, 2, 41, 23]
+[:mouse_move, 128, 499, 2, 42, 24]
+[:mouse_move, 109, 509, 2, 43, 24]
+[:mouse_move, 94, 521, 2, 44, 25]
+[:mouse_move, 86, 530, 2, 45, 25]
+[:mouse_move, 80, 540, 2, 46, 25]
+[:mouse_move, 76, 550, 2, 47, 25]
+[:mouse_move, 76, 552, 2, 48, 26]
+[:mouse_move, 77, 555, 2, 49, 26]
+[:mouse_move, 78, 556, 2, 50, 27]
+[:mouse_move, 86, 560, 2, 51, 27]
+[:mouse_move, 99, 564, 2, 52, 27]
+[:mouse_move, 111, 568, 2, 53, 27]
+[:mouse_move, 125, 571, 2, 54, 28]
+[:mouse_move, 142, 572, 2, 55, 28]
+[:mouse_move, 164, 572, 2, 56, 29]
+[:mouse_move, 190, 572, 2, 57, 29]
+[:mouse_move, 215, 572, 2, 58, 29]
+[:mouse_move, 249, 568, 2, 59, 30]
+[:mouse_move, 271, 565, 2, 60, 30]
+[:mouse_move, 288, 563, 2, 61, 31]
+[:mouse_move, 303, 561, 2, 62, 31]
+[:mouse_move, 314, 559, 2, 63, 31]
+[:mouse_move, 323, 556, 2, 64, 31]
+[:mouse_move, 330, 553, 2, 65, 32]
+[:mouse_move, 335, 550, 2, 66, 32]
+[:mouse_move, 342, 547, 2, 67, 32]
+[:mouse_move, 351, 543, 2, 68, 33]
+[:mouse_move, 359, 538, 2, 69, 33]
+[:mouse_move, 370, 533, 2, 70, 34]
+[:mouse_move, 393, 521, 2, 71, 34]
+[:mouse_move, 412, 511, 2, 72, 34]
+[:mouse_move, 432, 503, 2, 73, 35]
+[:mouse_move, 451, 497, 2, 74, 35]
+[:mouse_move, 468, 493, 2, 75, 35]
+[:mouse_move, 479, 492, 2, 76, 36]
+[:mouse_move, 487, 490, 2, 77, 36]
+[:mouse_move, 494, 489, 2, 78, 37]
+[:mouse_move, 501, 489, 2, 79, 37]
+[:mouse_move, 506, 487, 2, 80, 37]
+[:mouse_move, 507, 487, 2, 81, 38]
+[:mouse_move, 508, 486, 2, 82, 38]
+[:mouse_move, 502, 486, 2, 83, 38]
+[:mouse_move, 500, 486, 2, 84, 39]
+[:mouse_move, 496, 487, 2, 85, 39]
+[:mouse_move, 491, 489, 2, 86, 40]
+[:mouse_move, 492, 489, 2, 87, 45]
+[:mouse_move, 499, 487, 2, 88, 46]
+[:mouse_move, 509, 484, 2, 89, 46]
+[:mouse_move, 526, 480, 2, 90, 46]
+[:mouse_move, 548, 475, 2, 91, 47]
+[:mouse_move, 580, 468, 2, 92, 47]
+[:mouse_move, 598, 465, 2, 93, 47]
+[:mouse_move, 615, 461, 2, 94, 48]
+[:mouse_move, 628, 459, 2, 95, 48]
+[:mouse_move, 636, 459, 2, 96, 49]
+[:mouse_move, 641, 459, 2, 97, 49]
+[:mouse_move, 645, 459, 2, 98, 49]
+[:mouse_move, 647, 459, 2, 99, 50]
+[:mouse_move, 648, 459, 2, 100, 50]
+[:mouse_move, 650, 459, 2, 101, 51]
+[:mouse_move, 651, 459, 2, 102, 51]
+[:mouse_move, 652, 459, 2, 103, 52]
+[:mouse_move, 655, 459, 2, 104, 52]
+[:mouse_move, 661, 459, 2, 105, 52]
+[:mouse_move, 667, 459, 2, 106, 53]
+[:mouse_move, 674, 459, 2, 107, 53]
+[:mouse_move, 680, 460, 2, 108, 54]
+[:mouse_move, 687, 461, 2, 109, 54]
+[:mouse_move, 695, 462, 2, 110, 54]
+[:mouse_move, 699, 463, 2, 111, 55]
+[:mouse_move, 700, 463, 2, 112, 55]
+[:mouse_move, 702, 463, 2, 113, 56]
+[:mouse_move, 705, 463, 2, 114, 56]
+[:mouse_move, 709, 464, 2, 115, 56]
+[:mouse_move, 714, 464, 2, 116, 57]
+[:mouse_move, 718, 464, 2, 117, 57]
+[:mouse_move, 721, 464, 2, 118, 57]
+[:mouse_move, 723, 464, 2, 119, 58]
+[:mouse_move, 726, 465, 2, 120, 58]
+[:mouse_move, 729, 465, 2, 121, 59]
+[:mouse_move, 731, 465, 2, 122, 59]
+[:mouse_move, 732, 465, 2, 123, 60]
+[:mouse_move, 733, 465, 2, 124, 61]
+[:mouse_move, 734, 465, 2, 125, 61]
+[:mouse_move, 737, 465, 2, 126, 61]
+[:mouse_move, 739, 465, 2, 127, 62]
+[:mouse_move, 743, 465, 2, 128, 62]
+[:mouse_move, 751, 467, 2, 129, 62]
+[:mouse_move, 761, 469, 2, 130, 63]
+[:mouse_move, 772, 469, 2, 131, 63]
+[:mouse_move, 782, 469, 2, 132, 63]
+[:mouse_move, 793, 471, 2, 133, 64]
+[:mouse_move, 808, 471, 2, 134, 64]
+[:mouse_move, 818, 472, 2, 135, 64]
+[:mouse_move, 829, 473, 2, 136, 65]
+[:mouse_move, 839, 475, 2, 137, 65]
+[:mouse_move, 849, 477, 2, 138, 66]
+[:mouse_move, 861, 479, 2, 139, 66]
+[:mouse_move, 876, 480, 2, 140, 66]
+[:mouse_move, 893, 480, 2, 141, 67]
+[:mouse_move, 912, 480, 2, 142, 67]
+[:mouse_move, 933, 482, 2, 143, 68]
+[:mouse_move, 952, 482, 2, 144, 68]
+[:mouse_move, 967, 482, 2, 145, 68]
+[:mouse_move, 983, 482, 2, 146, 68]
+[:mouse_move, 1007, 482, 2, 147, 69]
+[:mouse_move, 1021, 482, 2, 148, 69]
+[:mouse_move, 1031, 482, 2, 149, 70]
+[:mouse_move, 1041, 482, 2, 150, 70]
+[:mouse_move, 1045, 482, 2, 151, 71]
+[:mouse_move, 1049, 481, 2, 152, 71]
+[:mouse_move, 1052, 481, 2, 153, 71]
+[:mouse_move, 1053, 481, 2, 154, 71]
+[:mouse_move, 1054, 481, 2, 155, 72]
+[:mouse_move, 1055, 480, 2, 156, 73]
+[:mouse_move, 1057, 480, 2, 157, 73]
+[:mouse_move, 1060, 479, 2, 158, 74]
+[:mouse_move, 1062, 479, 2, 159, 74]
+[:mouse_move, 1063, 478, 2, 160, 75]
+[:mouse_move, 1064, 478, 2, 161, 75]
+[:mouse_move, 1065, 478, 2, 162, 77]
+[:mouse_move, 1066, 478, 2, 163, 77]
+[:mouse_move, 1067, 478, 2, 164, 78]
+[:mouse_move, 1069, 478, 2, 165, 83]
+[:mouse_move, 1074, 477, 2, 166, 84]
+[:mouse_move, 1082, 476, 2, 167, 84]
+[:mouse_move, 1093, 469, 2, 168, 85]
+[:mouse_move, 1106, 459, 2, 169, 85]
+[:mouse_move, 1117, 447, 2, 170, 85]
+[:mouse_move, 1125, 433, 2, 171, 85]
+[:mouse_move, 1130, 414, 2, 172, 85]
+[:mouse_move, 1130, 382, 2, 173, 86]
+[:mouse_move, 1127, 358, 2, 174, 86]
+[:mouse_move, 1119, 333, 2, 175, 87]
+[:mouse_move, 1109, 309, 2, 176, 87]
+[:mouse_move, 1102, 293, 2, 177, 87]
+[:mouse_move, 1094, 280, 2, 178, 88]
+[:mouse_move, 1089, 272, 2, 179, 88]
+[:mouse_move, 1087, 264, 2, 180, 89]
+[:mouse_move, 1086, 258, 2, 181, 89]
+[:mouse_move, 1086, 248, 2, 182, 89]
+[:mouse_move, 1084, 241, 2, 183, 89]
+[:mouse_move, 1084, 240, 2, 184, 90]
+[:mouse_button_pressed, 1, 0, 1, 185, 95]
+[:mouse_button_up, 1, 0, 1, 186, 97]
+[:mouse_move, 1086, 251, 2, 187, 105]
+[:mouse_move, 1086, 267, 2, 188, 105]
+[:mouse_move, 1087, 287, 2, 189, 106]
+[:mouse_move, 1087, 310, 2, 190, 106]
+[:mouse_move, 1087, 339, 2, 191, 107]
+[:mouse_move, 1078, 387, 2, 192, 107]
+[:mouse_move, 1064, 422, 2, 193, 107]
+[:mouse_move, 1050, 449, 2, 194, 108]
+[:mouse_move, 1033, 470, 2, 195, 108]
+[:mouse_move, 1015, 485, 2, 196, 108]
+[:mouse_move, 995, 494, 2, 197, 109]
+[:mouse_move, 973, 500, 2, 198, 109]
+[:mouse_move, 955, 505, 2, 199, 109]
+[:mouse_move, 936, 506, 2, 200, 110]
+[:mouse_move, 919, 510, 2, 201, 110]
+[:mouse_move, 906, 510, 2, 202, 110]
+[:mouse_move, 891, 513, 2, 203, 111]
+[:mouse_move, 873, 516, 2, 204, 111]
+[:mouse_move, 854, 520, 2, 205, 111]
+[:mouse_move, 843, 522, 2, 206, 112]
+[:mouse_move, 830, 525, 2, 207, 112]
+[:mouse_move, 816, 526, 2, 208, 112]
+[:mouse_move, 804, 527, 2, 209, 113]
+[:mouse_move, 794, 527, 2, 210, 113]
+[:mouse_move, 784, 527, 2, 211, 114]
+[:mouse_move, 775, 526, 2, 212, 114]
+[:mouse_move, 765, 522, 2, 213, 114]
+[:mouse_move, 755, 518, 2, 214, 115]
+[:mouse_move, 746, 513, 2, 215, 115]
+[:mouse_move, 732, 505, 2, 216, 116]
+[:mouse_move, 706, 483, 2, 217, 116]
+[:mouse_move, 694, 463, 2, 218, 116]
+[:mouse_move, 689, 446, 2, 219, 116]
+[:mouse_move, 689, 429, 2, 220, 117]
+[:mouse_move, 689, 409, 2, 221, 117]
+[:mouse_move, 689, 388, 2, 222, 118]
+[:mouse_move, 689, 361, 2, 223, 118]
+[:mouse_move, 683, 327, 2, 224, 119]
+[:mouse_move, 677, 295, 2, 225, 119]
+[:mouse_move, 666, 266, 2, 226, 119]
+[:mouse_move, 656, 245, 2, 227, 119]
+[:mouse_move, 650, 233, 2, 228, 120]
+[:mouse_move, 640, 215, 2, 229, 120]
+[:mouse_move, 630, 203, 2, 230, 121]
+[:mouse_move, 612, 189, 2, 231, 121]
+[:mouse_move, 586, 178, 2, 232, 121]
+[:mouse_move, 553, 168, 2, 233, 121]
+[:mouse_move, 528, 166, 2, 234, 122]
+[:mouse_move, 510, 165, 2, 235, 122]
+[:mouse_move, 498, 165, 2, 236, 123]
+[:mouse_move, 482, 165, 2, 237, 123]
+[:mouse_move, 466, 165, 2, 238, 123]
+[:mouse_move, 450, 165, 2, 239, 124]
+[:mouse_move, 426, 165, 2, 240, 124]
+[:mouse_move, 416, 165, 2, 241, 125]
+[:mouse_move, 411, 166, 2, 242, 125]
+[:mouse_move, 407, 168, 2, 243, 126]
+[:mouse_move, 405, 169, 2, 244, 126]
+[:mouse_move, 400, 172, 2, 245, 126]
+[:mouse_move, 391, 178, 2, 246, 126]
+[:mouse_move, 381, 185, 2, 247, 127]
+[:mouse_move, 368, 195, 2, 248, 127]
+[:mouse_move, 355, 207, 2, 249, 128]
+[:mouse_move, 345, 223, 2, 250, 128]
+[:mouse_move, 343, 243, 2, 251, 128]
+[:mouse_move, 343, 273, 2, 252, 129]
+[:mouse_move, 343, 290, 2, 253, 129]
+[:mouse_move, 343, 308, 2, 254, 129]
+[:mouse_move, 342, 326, 2, 255, 130]
+[:mouse_move, 340, 343, 2, 256, 130]
+[:mouse_move, 339, 363, 2, 257, 130]
+[:mouse_move, 339, 384, 2, 258, 131]
+[:mouse_move, 339, 407, 2, 259, 131]
+[:mouse_move, 338, 427, 2, 260, 132]
+[:mouse_move, 333, 446, 2, 261, 132]
+[:mouse_move, 330, 463, 2, 262, 132]
+[:mouse_move, 325, 477, 2, 263, 133]
+[:mouse_move, 317, 488, 2, 264, 133]
+[:mouse_move, 313, 494, 2, 265, 133]
+[:mouse_move, 308, 500, 2, 266, 134]
+[:mouse_move, 302, 511, 2, 267, 134]
+[:mouse_move, 295, 522, 2, 268, 135]
+[:mouse_move, 285, 535, 2, 269, 135]
+[:mouse_move, 277, 547, 2, 270, 135]
+[:mouse_move, 267, 558, 2, 271, 136]
+[:mouse_move, 259, 568, 2, 272, 136]
+[:mouse_move, 250, 574, 2, 273, 137]
+[:mouse_move, 241, 580, 2, 274, 137]
+[:mouse_move, 233, 586, 2, 275, 137]
+[:mouse_move, 222, 593, 2, 276, 138]
+[:mouse_move, 213, 599, 2, 277, 138]
+[:mouse_move, 206, 606, 2, 278, 138]
+[:mouse_move, 203, 615, 2, 279, 139]
+[:mouse_move, 202, 622, 2, 280, 139]
+[:mouse_move, 200, 625, 2, 281, 139]
+[:mouse_move, 199, 627, 2, 282, 140]
+[:mouse_move, 198, 628, 2, 283, 140]
+[:mouse_move, 197, 628, 2, 284, 141]
+[:mouse_move, 194, 630, 2, 285, 141]
+[:mouse_move, 190, 632, 2, 286, 141]
+[:mouse_move, 186, 633, 2, 287, 142]
+[:mouse_move, 180, 635, 2, 288, 142]
+[:mouse_move, 175, 636, 2, 289, 143]
+[:mouse_move, 174, 636, 2, 290, 144]
+[:mouse_move, 173, 636, 2, 291, 144]
+[:mouse_move, 170, 636, 2, 292, 144]
+[:mouse_move, 164, 636, 2, 293, 144]
+[:mouse_move, 155, 636, 2, 294, 145]
+[:mouse_move, 147, 634, 2, 295, 145]
+[:mouse_move, 141, 634, 2, 296, 146]
+[:mouse_move, 139, 634, 2, 297, 146]
+[:mouse_move, 138, 634, 2, 298, 146]
+[:mouse_move, 136, 634, 2, 299, 147]
+[:mouse_move, 135, 633, 2, 300, 148]
+[:mouse_move, 134, 633, 2, 301, 148]
+[:mouse_move, 133, 633, 2, 302, 148]
+[:key_down_raw, 96, 0, 2, 303, 159]
+[:mouse_move, 134, 632, 2, 304, 160]
+[:mouse_move, 138, 632, 2, 305, 161]
+[:key_up_raw, 96, 0, 2, 306, 161]
+[:mouse_move, 144, 630, 2, 307, 161]
+[:mouse_move, 155, 628, 2, 308, 161]
+[:mouse_move, 170, 623, 2, 309, 161]
+[:mouse_move, 189, 618, 2, 310, 161]
+[:mouse_move, 213, 611, 2, 311, 162]
+[:mouse_move, 243, 600, 2, 312, 162]
+[:mouse_move, 281, 586, 2, 313, 163]
+[:mouse_move, 330, 565, 2, 314, 163]
+[:mouse_move, 400, 533, 2, 315, 163]
+[:mouse_move, 476, 492, 2, 316, 164]
+[:mouse_move, 564, 445, 2, 317, 164]
+[:mouse_move, 703, 362, 2, 318, 164]
+[:mouse_move, 797, 306, 2, 319, 165]
+[:mouse_move, 872, 251, 2, 320, 165]
+[:mouse_move, 951, 196, 2, 321, 165]
+[:mouse_move, 1012, 147, 2, 322, 166]
+[:mouse_move, 1058, 112, 2, 323, 166]
+[:mouse_move, 1085, 87, 2, 324, 166]
+[:mouse_move, 1100, 67, 2, 325, 166]
+[:mouse_move, 1111, 51, 2, 326, 167]
+[:mouse_move, 1117, 42, 2, 327, 167]
+[:mouse_move, 1118, 39, 2, 328, 168]
+[:mouse_move, 1110, 35, 2, 329, 170]
+[:mouse_move, 1101, 34, 2, 330, 171]
+[:mouse_move, 1095, 34, 2, 331, 171]
+[:mouse_move, 1087, 34, 2, 332, 171]
+[:mouse_move, 1076, 34, 2, 333, 172]
+[:mouse_move, 1064, 34, 2, 334, 172]
+[:mouse_move, 1045, 38, 2, 335, 172]
+[:mouse_move, 1031, 42, 2, 336, 172]
+[:mouse_move, 1018, 45, 2, 337, 173]
+[:mouse_move, 1002, 50, 2, 338, 173]
+[:mouse_move, 978, 53, 2, 339, 173]
+[:mouse_move, 947, 54, 2, 340, 174]
+[:mouse_move, 908, 54, 2, 341, 174]
+[:mouse_move, 864, 54, 2, 342, 174]
+[:mouse_move, 830, 54, 2, 343, 174]
+[:mouse_move, 810, 58, 2, 344, 175]
+[:mouse_move, 807, 59, 2, 345, 175]
+[:mouse_move, 808, 59, 2, 346, 177]
+[:mouse_move, 810, 61, 2, 347, 178]
+[:mouse_move, 814, 65, 2, 348, 178]
+[:mouse_move, 816, 66, 2, 349, 178]
+[:mouse_move, 818, 69, 2, 350, 178]
+[:mouse_move, 819, 71, 2, 351, 179]
+[:mouse_move, 820, 73, 2, 352, 179]
+[:mouse_move, 820, 74, 2, 353, 179]
+[:mouse_move, 819, 75, 2, 354, 183]
+[:mouse_move, 817, 77, 2, 355, 183]
+[:mouse_move, 814, 81, 2, 356, 184]
+[:mouse_move, 810, 84, 2, 357, 184]
+[:mouse_move, 809, 85, 2, 358, 184]
+[:mouse_move, 810, 85, 2, 359, 211]
+[:key_down_raw, 13, 0, 2, 360, 211]
+[:mouse_move, 811, 85, 2, 361, 211]
diff --git a/samples/13_path_finding_algorithms/04_early_exit/app/main.rb b/samples/13_path_finding_algorithms/04_early_exit/app/main.rb
index 1e9305b..40a3ba5 100644
--- a/samples/13_path_finding_algorithms/04_early_exit/app/main.rb
+++ b/samples/13_path_finding_algorithms/04_early_exit/app/main.rb
@@ -26,8 +26,8 @@ class EarlyExitBreadthFirstSearch
# And calculate the path
calc_path
end
- render
- input
+ render
+ input
end
def defaults
@@ -43,14 +43,14 @@ class EarlyExitBreadthFirstSearch
# This step is roughly the grid's width * height
# When anim_steps equals max_steps no more calculations will occur
# and the slider will be at the end
- state.max_steps ||= args.state.grid.width * args.state.grid.height
+ state.max_steps ||= args.state.grid.width * args.state.grid.height
# The location of the star and walls of the grid
# They can be modified to have a different initial grid
# Walls are stored in a hash for quick look up when doing the search
state.star ||= [2, 8]
state.target ||= [10, 5]
- state.walls ||= {}
+ state.walls ||= {}
# Variables that are used by the breadth first search
# Storing cells that the search has visited, prevents unnecessary steps
@@ -73,12 +73,12 @@ class EarlyExitBreadthFirstSearch
# We store this value, because we want to remember the value even when
# the user's cursor is no longer over what they're interacting with, but
# they are still clicking down on the mouse.
- state.current_input ||= :none
+ state.current_input ||= :none
end
# Draws everything onto the screen
def render
- render_background
+ render_background
render_heat_map
render_walls
render_path
@@ -91,8 +91,8 @@ class EarlyExitBreadthFirstSearch
# Draws what the grid looks like with nothing on it
def render_background
- render_unvisited
- render_grid_lines
+ render_unvisited
+ render_grid_lines
end
# Draws both grids
@@ -109,7 +109,7 @@ class EarlyExitBreadthFirstSearch
end
for y in 0..grid.height
- outputs.lines << horizontal_line(y)
+ outputs.lines << horizontal_line(y)
outputs.lines << early_exit_horizontal_line(y)
end
end
@@ -136,7 +136,7 @@ class EarlyExitBreadthFirstSearch
# Draws the walls on both grids
def render_walls
- state.walls.each_key do |wall|
+ state.walls.each_key do |wall|
outputs.solids << [scale_up(wall), wall_color]
outputs.solids << [early_exit_scale_up(wall), wall_color]
end
@@ -146,13 +146,13 @@ class EarlyExitBreadthFirstSearch
def render_star
outputs.sprites << [scale_up(state.star), 'star.png']
outputs.sprites << [early_exit_scale_up(state.star), 'star.png']
- end
+ end
# Renders the target on both grids
def render_target
outputs.sprites << [scale_up(state.target), 'target.png']
outputs.sprites << [early_exit_scale_up(state.target), 'target.png']
- end
+ end
# Labels the grids
def render_labels
@@ -244,8 +244,8 @@ class EarlyExitBreadthFirstSearch
# The program has to remember that the user is dragging an object
# even when the mouse is no longer over that object
# So detecting input and processing input is separate
- detect_input
- process_input
+ detect_input
+ process_input
end
# Determines what the user is editing and stores the value
@@ -253,53 +253,53 @@ class EarlyExitBreadthFirstSearch
# mouse left click is held
def detect_input
# When the mouse is up, nothing is being edited
- if inputs.mouse.up
- state.current_input = :none
+ if inputs.mouse.up
+ state.current_input = :none
# When the star in the no second grid is clicked
- elsif star_clicked?
- state.current_input = :star
+ elsif star_clicked?
+ state.current_input = :star
# When the star in the second grid is clicked
- elsif star2_clicked?
- state.current_input = :star2
+ elsif star2_clicked?
+ state.current_input = :star2
# When the target in the no second grid is clicked
- elsif target_clicked?
- state.current_input = :target
+ elsif target_clicked?
+ state.current_input = :target
# When the target in the second grid is clicked
- elsif target2_clicked?
- state.current_input = :target2
+ elsif target2_clicked?
+ state.current_input = :target2
# When a wall in the first grid is clicked
- elsif wall_clicked?
- state.current_input = :remove_wall
+ elsif wall_clicked?
+ state.current_input = :remove_wall
# When a wall in the second grid is clicked
- elsif wall2_clicked?
+ elsif wall2_clicked?
state.current_input = :remove_wall2
# When the first grid is clicked
- elsif grid_clicked?
+ elsif grid_clicked?
state.current_input = :add_wall
# When the second grid is clicked
- elsif grid2_clicked?
+ elsif grid2_clicked?
state.current_input = :add_wall2
end
end
# Processes click and drag based on what the user is currently dragging
def process_input
- if state.current_input == :star
- input_star
+ if state.current_input == :star
+ input_star
elsif state.current_input == :star2
- input_star2
- elsif state.current_input == :target
- input_target
- elsif state.current_input == :target2
- input_target2
- elsif state.current_input == :remove_wall
- input_remove_wall
+ input_star2
+ elsif state.current_input == :target
+ input_target
+ elsif state.current_input == :target2
+ input_target2
+ elsif state.current_input == :remove_wall
+ input_remove_wall
elsif state.current_input == :remove_wall2
- input_remove_wall2
- elsif state.current_input == :add_wall
- input_add_wall
- elsif state.current_input == :add_wall2
- input_add_wall2
+ input_remove_wall2
+ elsif state.current_input == :add_wall
+ input_add_wall
+ elsif state.current_input == :add_wall2
+ input_add_wall2
end
end
@@ -307,10 +307,10 @@ class EarlyExitBreadthFirstSearch
# Only resets the search if the star changes position
# Called whenever the user is editing the star (puts mouse down on star)
def input_star
- old_star = state.star.clone
+ old_star = state.star.clone
state.star = cell_closest_to_mouse
- unless old_star == state.star
- reset_search
+ unless old_star == state.star
+ reset_search
end
end
@@ -318,10 +318,10 @@ class EarlyExitBreadthFirstSearch
# Only resets the search if the star changes position
# Called whenever the user is editing the star (puts mouse down on star)
def input_star2
- old_star = state.star.clone
+ old_star = state.star.clone
state.star = cell_closest_to_mouse2
- unless old_star == state.star
- reset_search
+ unless old_star == state.star
+ reset_search
end
end
@@ -329,10 +329,10 @@ class EarlyExitBreadthFirstSearch
# Only reset_searchs the search if the target changes position
# Called whenever the user is editing the target (puts mouse down on target)
def input_target
- old_target = state.target.clone
+ old_target = state.target.clone
state.target = cell_closest_to_mouse
- unless old_target == state.target
- reset_search
+ unless old_target == state.target
+ reset_search
end
end
@@ -340,10 +340,10 @@ class EarlyExitBreadthFirstSearch
# Only reset_searchs the search if the target changes position
# Called whenever the user is editing the target (puts mouse down on target)
def input_target2
- old_target = state.target.clone
+ old_target = state.target.clone
state.target = cell_closest_to_mouse2
- unless old_target == state.target
- reset_search
+ unless old_target == state.target
+ reset_search
end
end
@@ -352,10 +352,10 @@ class EarlyExitBreadthFirstSearch
# The mouse needs to be inside the grid, because we only want to remove walls
# the cursor is directly over
# Recalculations should only occur when a wall is actually deleted
- if mouse_inside_grid?
+ if mouse_inside_grid?
if state.walls.has_key?(cell_closest_to_mouse)
- state.walls.delete(cell_closest_to_mouse)
- reset_search
+ state.walls.delete(cell_closest_to_mouse)
+ reset_search
end
end
end
@@ -365,31 +365,31 @@ class EarlyExitBreadthFirstSearch
# The mouse needs to be inside the grid, because we only want to remove walls
# the cursor is directly over
# Recalculations should only occur when a wall is actually deleted
- if mouse_inside_grid2?
+ if mouse_inside_grid2?
if state.walls.has_key?(cell_closest_to_mouse2)
- state.walls.delete(cell_closest_to_mouse2)
- reset_search
+ state.walls.delete(cell_closest_to_mouse2)
+ reset_search
end
end
end
# Adds a wall in the first grid in the cell the mouse is over
def input_add_wall
- if mouse_inside_grid?
+ if mouse_inside_grid?
unless state.walls.has_key?(cell_closest_to_mouse)
- state.walls[cell_closest_to_mouse] = true
- reset_search
+ state.walls[cell_closest_to_mouse] = true
+ reset_search
end
end
end
-
+
# Adds a wall in the second grid in the cell the mouse is over
def input_add_wall2
- if mouse_inside_grid2?
+ if mouse_inside_grid2?
unless state.walls.has_key?(cell_closest_to_mouse2)
- state.walls[cell_closest_to_mouse2] = true
- reset_search
+ state.walls[cell_closest_to_mouse2] = true
+ reset_search
end
end
end
@@ -399,10 +399,10 @@ class EarlyExitBreadthFirstSearch
# with the current grid as the initial state of the grid
def reset_search
# Reset_Searchs the search
- state.frontier = []
- state.visited = {}
- state.early_exit_visited = {}
- state.came_from = {}
+ state.frontier = []
+ state.visited = {}
+ state.early_exit_visited = {}
+ state.came_from = {}
state.path = {}
end
@@ -410,23 +410,23 @@ class EarlyExitBreadthFirstSearch
def step
# The setup to the search
# Runs once when there are no visited cells
- if state.visited.empty?
- state.visited[state.star] = true
- state.early_exit_visited[state.star] = true
- state.frontier << state.star
+ if state.visited.empty?
+ state.visited[state.star] = true
+ state.early_exit_visited[state.star] = true
+ state.frontier << state.star
state.came_from[state.star] = nil
end
# A step in the search
- unless state.frontier.empty?
+ unless state.frontier.empty?
# Takes the next frontier cell
- new_frontier = state.frontier.shift
+ new_frontier = state.frontier.shift
# For each of its neighbors
- adjacent_neighbors(new_frontier).each do |neighbor|
+ adjacent_neighbors(new_frontier).each do |neighbor|
# That have not been visited and are not walls
- unless state.visited.has_key?(neighbor) || state.walls.has_key?(neighbor)
+ unless state.visited.has_key?(neighbor) || state.walls.has_key?(neighbor)
# Add them to the frontier and mark them as visited in the first grid
- state.visited[neighbor] = true
+ state.visited[neighbor] = true
# Unless the target has been visited
unless state.visited.has_key?(state.target)
# Mark the neighbor as visited in the second grid as well
@@ -434,32 +434,32 @@ class EarlyExitBreadthFirstSearch
end
# Add the neighbor to the frontier and remember which cell it came from
- state.frontier << neighbor
+ state.frontier << neighbor
state.came_from[neighbor] = new_frontier
end
end
end
end
-
+
# Returns a list of adjacent cells
# Used to determine what the next cells to be added to the frontier are
def adjacent_neighbors(cell)
- neighbors = []
+ neighbors = []
# Gets all the valid neighbors into the array
# From southern neighbor, clockwise
- neighbors << [cell.x, cell.y - 1] unless cell.y == 0
- neighbors << [cell.x - 1, cell.y] unless cell.x == 0
- neighbors << [cell.x, cell.y + 1] unless cell.y == grid.height - 1
- neighbors << [cell.x + 1, cell.y] unless cell.x == grid.width - 1
+ neighbors << [cell.x, cell.y - 1] unless cell.y == 0
+ neighbors << [cell.x - 1, cell.y] unless cell.x == 0
+ neighbors << [cell.x, cell.y + 1] unless cell.y == grid.height - 1
+ neighbors << [cell.x + 1, cell.y] unless cell.x == grid.width - 1
# Sorts the neighbors so the rendered path is a zigzag path
# Cells in a diagonal direction are given priority
# Comment this line to see the difference
neighbors = neighbors.sort_by { |neighbor_x, neighbor_y| proximity_to_star(neighbor_x, neighbor_y) }
- neighbors
+ neighbors
end
# Finds the vertical and horizontal distance of a cell from the star
@@ -484,13 +484,13 @@ class EarlyExitBreadthFirstSearch
# Finding the cell closest to the mouse helps with this
def cell_closest_to_mouse
# Closest cell to the mouse in the first grid
- x = (inputs.mouse.point.x / grid.cell_size).to_i
- y = (inputs.mouse.point.y / grid.cell_size).to_i
+ x = (inputs.mouse.point.x / grid.cell_size).to_i
+ y = (inputs.mouse.point.y / grid.cell_size).to_i
# Bound x and y to the grid
- x = grid.width - 1 if x > grid.width - 1
- y = grid.height - 1 if y > grid.height - 1
+ x = grid.width - 1 if x > grid.width - 1
+ y = grid.height - 1 if y > grid.height - 1
# Return closest cell
- [x, y]
+ [x, y]
end
# When the user grabs the star and puts their cursor to the far right
@@ -498,15 +498,15 @@ class EarlyExitBreadthFirstSearch
# Finding the cell closest to the mouse in the second grid helps with this
def cell_closest_to_mouse2
# Closest cell grid to the mouse in the second
- x = (inputs.mouse.point.x / grid.cell_size).to_i
- y = (inputs.mouse.point.y / grid.cell_size).to_i
+ x = (inputs.mouse.point.x / grid.cell_size).to_i
+ y = (inputs.mouse.point.y / grid.cell_size).to_i
# Translate the cell to the first grid
x -= grid.width + 1
# Bound x and y to the first grid
- x = grid.width - 1 if x > grid.width - 1
- y = grid.height - 1 if y > grid.height - 1
+ x = grid.width - 1 if x > grid.width - 1
+ y = grid.height - 1 if y > grid.height - 1
# Return closest cell
- [x, y]
+ [x, y]
end
# Signal that the user is going to be moving the star from the first grid
@@ -585,12 +585,12 @@ class EarlyExitBreadthFirstSearch
# Light brown
def unvisited_color
- [221, 212, 213]
+ [221, 212, 213]
end
# Camo Green
def wall_color
- [134, 134, 120]
+ [134, 134, 120]
end
# Pastel White
@@ -620,7 +620,7 @@ def tick args
end
# Every tick, new args are passed, and the Breadth First Search tick is called
- $early_exit_breadth_first_search ||= EarlyExitBreadthFirstSearch.new(args)
+ $early_exit_breadth_first_search ||= EarlyExitBreadthFirstSearch.new
$early_exit_breadth_first_search.args = args
$early_exit_breadth_first_search.tick
end
diff --git a/samples/13_path_finding_algorithms/04_early_exit/replay.txt b/samples/13_path_finding_algorithms/04_early_exit/replay.txt
new file mode 100644
index 0000000..3ec9254
--- /dev/null
+++ b/samples/13_path_finding_algorithms/04_early_exit/replay.txt
@@ -0,0 +1,364 @@
+replay_version 2.0
+stopped_at 322
+seed 100
+recorded_at 2021-11-20 11:19:30 -0600
+[:mouse_button_up, 1, 0, 1, 1, 1]
+[:mouse_move, 806, 92, 2, 2, 12]
+[:mouse_move, 799, 105, 2, 3, 13]
+[:mouse_move, 786, 126, 2, 4, 13]
+[:mouse_move, 761, 154, 2, 5, 13]
+[:mouse_move, 722, 199, 2, 6, 14]
+[:mouse_move, 692, 230, 2, 7, 14]
+[:mouse_move, 659, 263, 2, 8, 14]
+[:mouse_move, 629, 297, 2, 9, 14]
+[:mouse_move, 598, 337, 2, 10, 15]
+[:mouse_move, 569, 376, 2, 11, 15]
+[:mouse_move, 538, 412, 2, 12, 15]
+[:mouse_move, 510, 438, 2, 13, 16]
+[:mouse_move, 488, 456, 2, 14, 16]
+[:mouse_move, 471, 467, 2, 15, 16]
+[:mouse_move, 459, 477, 2, 16, 17]
+[:mouse_move, 455, 481, 2, 17, 17]
+[:mouse_move, 455, 484, 2, 18, 18]
+[:mouse_move, 454, 485, 2, 19, 18]
+[:mouse_move, 464, 481, 2, 20, 23]
+[:mouse_move, 482, 477, 2, 21, 23]
+[:mouse_move, 490, 470, 2, 22, 23]
+[:mouse_move, 491, 469, 2, 23, 24]
+[:mouse_move, 492, 467, 2, 24, 24]
+[:mouse_move, 493, 466, 2, 25, 25]
+[:mouse_move, 485, 466, 2, 26, 26]
+[:mouse_move, 474, 468, 2, 27, 27]
+[:mouse_move, 460, 472, 2, 28, 27]
+[:mouse_move, 441, 476, 2, 29, 27]
+[:mouse_move, 419, 479, 2, 30, 27]
+[:mouse_move, 392, 480, 2, 31, 28]
+[:mouse_move, 359, 480, 2, 32, 28]
+[:mouse_move, 329, 483, 2, 33, 29]
+[:mouse_move, 306, 486, 2, 34, 29]
+[:mouse_move, 281, 493, 2, 35, 30]
+[:mouse_move, 271, 496, 2, 36, 30]
+[:mouse_move, 270, 496, 2, 37, 30]
+[:mouse_move, 272, 496, 2, 38, 32]
+[:mouse_move, 275, 496, 2, 39, 32]
+[:mouse_move, 279, 495, 2, 40, 32]
+[:mouse_move, 283, 494, 2, 41, 33]
+[:mouse_move, 289, 494, 2, 42, 33]
+[:mouse_move, 292, 494, 2, 43, 34]
+[:mouse_move, 293, 495, 2, 44, 35]
+[:mouse_button_pressed, 1, 0, 1, 45, 39]
+[:mouse_button_up, 1, 0, 1, 46, 40]
+[:mouse_move, 294, 495, 2, 47, 49]
+[:mouse_move, 294, 494, 2, 48, 50]
+[:mouse_move, 295, 491, 2, 49, 50]
+[:mouse_move, 296, 488, 2, 50, 50]
+[:mouse_move, 297, 484, 2, 51, 50]
+[:mouse_move, 297, 481, 2, 52, 51]
+[:mouse_move, 298, 477, 2, 53, 51]
+[:mouse_move, 298, 476, 2, 54, 51]
+[:mouse_move, 299, 475, 2, 55, 52]
+[:mouse_move, 300, 473, 2, 56, 52]
+[:mouse_move, 300, 472, 2, 57, 53]
+[:mouse_move, 300, 471, 2, 58, 55]
+[:mouse_move, 300, 470, 2, 59, 56]
+[:mouse_move, 300, 469, 2, 60, 57]
+[:mouse_move, 300, 467, 2, 61, 57]
+[:mouse_move, 300, 466, 2, 62, 57]
+[:mouse_button_pressed, 1, 0, 1, 63, 59]
+[:mouse_button_up, 1, 0, 1, 64, 61]
+[:mouse_move, 300, 465, 2, 65, 61]
+[:mouse_move, 300, 462, 2, 66, 62]
+[:mouse_move, 300, 456, 2, 67, 62]
+[:mouse_move, 300, 449, 2, 68, 62]
+[:mouse_move, 300, 443, 2, 69, 63]
+[:mouse_move, 299, 441, 2, 70, 63]
+[:mouse_move, 299, 440, 2, 71, 63]
+[:mouse_move, 299, 438, 2, 72, 64]
+[:mouse_move, 299, 437, 2, 73, 65]
+[:mouse_move, 299, 436, 2, 74, 65]
+[:mouse_move, 299, 434, 2, 75, 65]
+[:mouse_move, 299, 432, 2, 76, 65]
+[:mouse_move, 299, 431, 2, 77, 67]
+[:mouse_move, 299, 430, 2, 78, 67]
+[:mouse_move, 299, 429, 2, 79, 68]
+[:mouse_move, 299, 428, 2, 80, 68]
+[:mouse_move, 299, 424, 2, 81, 68]
+[:mouse_move, 300, 417, 2, 82, 69]
+[:mouse_move, 301, 413, 2, 83, 69]
+[:mouse_move, 302, 412, 2, 84, 70]
+[:mouse_button_pressed, 1, 0, 1, 85, 72]
+[:mouse_move, 302, 411, 2, 86, 72]
+[:mouse_button_up, 1, 0, 1, 87, 74]
+[:mouse_move, 302, 408, 2, 88, 94]
+[:mouse_move, 302, 396, 2, 89, 94]
+[:mouse_move, 302, 383, 2, 90, 95]
+[:mouse_move, 302, 375, 2, 91, 95]
+[:mouse_move, 303, 374, 2, 92, 95]
+[:mouse_move, 303, 373, 2, 93, 95]
+[:mouse_move, 303, 374, 2, 94, 99]
+[:mouse_button_pressed, 1, 0, 1, 95, 101]
+[:mouse_button_up, 1, 0, 1, 96, 103]
+[:mouse_move, 303, 375, 2, 97, 103]
+[:mouse_move, 306, 375, 2, 98, 132]
+[:mouse_move, 317, 376, 2, 99, 132]
+[:mouse_move, 333, 380, 2, 100, 133]
+[:mouse_move, 352, 384, 2, 101, 133]
+[:mouse_move, 374, 385, 2, 102, 133]
+[:mouse_move, 401, 390, 2, 103, 134]
+[:mouse_move, 424, 392, 2, 104, 134]
+[:mouse_move, 442, 395, 2, 105, 134]
+[:mouse_move, 455, 397, 2, 106, 135]
+[:mouse_move, 458, 398, 2, 107, 135]
+[:mouse_move, 460, 398, 2, 108, 136]
+[:mouse_move, 466, 398, 2, 109, 136]
+[:mouse_move, 473, 398, 2, 110, 136]
+[:mouse_move, 477, 398, 2, 111, 136]
+[:mouse_move, 478, 397, 2, 112, 136]
+[:mouse_move, 479, 397, 2, 113, 137]
+[:mouse_move, 480, 396, 2, 114, 137]
+[:mouse_move, 480, 395, 2, 115, 138]
+[:mouse_move, 480, 396, 2, 116, 138]
+[:mouse_move, 478, 404, 2, 117, 139]
+[:mouse_move, 474, 418, 2, 118, 139]
+[:mouse_move, 472, 426, 2, 119, 139]
+[:mouse_move, 466, 438, 2, 120, 140]
+[:mouse_move, 461, 453, 2, 121, 140]
+[:mouse_move, 453, 466, 2, 122, 140]
+[:mouse_move, 448, 473, 2, 123, 141]
+[:mouse_move, 446, 475, 2, 124, 141]
+[:mouse_move, 444, 477, 2, 125, 142]
+[:mouse_move, 441, 481, 2, 126, 142]
+[:mouse_move, 435, 489, 2, 127, 142]
+[:mouse_move, 426, 496, 2, 128, 143]
+[:mouse_move, 422, 498, 2, 129, 143]
+[:mouse_move, 422, 499, 2, 130, 143]
+[:mouse_move, 421, 499, 2, 131, 145]
+[:mouse_move, 420, 499, 2, 132, 145]
+[:mouse_button_pressed, 1, 0, 1, 133, 147]
+[:mouse_move, 419, 499, 2, 134, 148]
+[:mouse_move, 419, 497, 2, 135, 148]
+[:mouse_move, 421, 494, 2, 136, 149]
+[:mouse_move, 426, 484, 2, 137, 149]
+[:mouse_move, 432, 472, 2, 138, 149]
+[:mouse_move, 439, 460, 2, 139, 150]
+[:mouse_move, 445, 450, 2, 140, 150]
+[:mouse_move, 456, 434, 2, 141, 150]
+[:mouse_move, 466, 422, 2, 142, 150]
+[:mouse_move, 474, 411, 2, 143, 151]
+[:mouse_move, 480, 403, 2, 144, 151]
+[:mouse_move, 485, 397, 2, 145, 151]
+[:mouse_move, 489, 392, 2, 146, 151]
+[:mouse_move, 491, 389, 2, 147, 151]
+[:mouse_move, 494, 384, 2, 148, 151]
+[:mouse_move, 495, 381, 2, 149, 152]
+[:mouse_move, 497, 378, 2, 150, 152]
+[:mouse_move, 499, 376, 2, 151, 152]
+[:mouse_move, 500, 373, 2, 152, 152]
+[:mouse_move, 501, 372, 2, 153, 152]
+[:mouse_move, 501, 371, 2, 154, 152]
+[:mouse_move, 502, 370, 2, 155, 153]
+[:mouse_move, 502, 369, 2, 156, 153]
+[:mouse_move, 503, 369, 2, 157, 157]
+[:mouse_move, 504, 369, 2, 158, 158]
+[:mouse_move, 505, 368, 2, 159, 158]
+[:mouse_move, 508, 366, 2, 160, 158]
+[:mouse_move, 512, 364, 2, 161, 159]
+[:mouse_move, 513, 364, 2, 162, 159]
+[:mouse_move, 514, 364, 2, 163, 159]
+[:mouse_move, 515, 364, 2, 164, 160]
+[:mouse_move, 519, 364, 2, 165, 161]
+[:mouse_move, 526, 366, 2, 166, 161]
+[:mouse_move, 538, 372, 2, 167, 161]
+[:mouse_move, 550, 382, 2, 168, 161]
+[:mouse_move, 563, 397, 2, 169, 162]
+[:mouse_move, 570, 411, 2, 170, 162]
+[:mouse_move, 574, 425, 2, 171, 162]
+[:mouse_move, 576, 439, 2, 172, 163]
+[:mouse_move, 576, 448, 2, 173, 163]
+[:mouse_move, 576, 459, 2, 174, 163]
+[:mouse_move, 576, 470, 2, 175, 163]
+[:mouse_move, 576, 477, 2, 176, 163]
+[:mouse_move, 576, 481, 2, 177, 163]
+[:mouse_move, 576, 483, 2, 178, 163]
+[:mouse_move, 576, 485, 2, 179, 164]
+[:mouse_move, 576, 488, 2, 180, 164]
+[:mouse_move, 576, 494, 2, 181, 164]
+[:mouse_move, 577, 500, 2, 182, 164]
+[:mouse_move, 577, 501, 2, 183, 164]
+[:mouse_move, 579, 504, 2, 184, 164]
+[:mouse_move, 579, 505, 2, 185, 164]
+[:mouse_move, 581, 509, 2, 186, 165]
+[:mouse_move, 583, 512, 2, 187, 165]
+[:mouse_move, 584, 514, 2, 188, 165]
+[:mouse_move, 585, 516, 2, 189, 165]
+[:mouse_move, 586, 519, 2, 190, 165]
+[:mouse_move, 587, 521, 2, 191, 165]
+[:mouse_move, 588, 523, 2, 192, 166]
+[:mouse_move, 588, 524, 2, 193, 166]
+[:mouse_move, 588, 525, 2, 194, 166]
+[:mouse_move, 588, 526, 2, 195, 167]
+[:mouse_move, 588, 527, 2, 196, 167]
+[:mouse_move, 588, 526, 2, 197, 173]
+[:mouse_move, 586, 521, 2, 198, 173]
+[:mouse_move, 586, 516, 2, 199, 174]
+[:mouse_move, 585, 508, 2, 200, 174]
+[:mouse_move, 582, 500, 2, 201, 174]
+[:mouse_move, 578, 489, 2, 202, 174]
+[:mouse_move, 573, 476, 2, 203, 175]
+[:mouse_move, 568, 466, 2, 204, 175]
+[:mouse_move, 566, 461, 2, 205, 176]
+[:mouse_move, 565, 460, 2, 206, 176]
+[:mouse_move, 564, 460, 2, 207, 176]
+[:mouse_move, 563, 459, 2, 208, 176]
+[:mouse_move, 562, 459, 2, 209, 177]
+[:mouse_move, 561, 459, 2, 210, 177]
+[:mouse_move, 549, 459, 2, 211, 177]
+[:mouse_move, 522, 456, 2, 212, 177]
+[:mouse_move, 484, 456, 2, 213, 177]
+[:mouse_move, 423, 456, 2, 214, 177]
+[:mouse_move, 385, 454, 2, 215, 177]
+[:mouse_move, 359, 454, 2, 216, 178]
+[:mouse_move, 345, 452, 2, 217, 178]
+[:mouse_move, 343, 452, 2, 218, 178]
+[:mouse_move, 342, 451, 2, 219, 180]
+[:mouse_move, 343, 451, 2, 220, 180]
+[:mouse_move, 344, 449, 2, 221, 180]
+[:mouse_move, 348, 446, 2, 222, 180]
+[:mouse_move, 352, 444, 2, 223, 180]
+[:mouse_move, 362, 442, 2, 224, 181]
+[:mouse_move, 369, 441, 2, 225, 181]
+[:mouse_move, 376, 440, 2, 226, 181]
+[:mouse_move, 381, 439, 2, 227, 182]
+[:mouse_move, 385, 438, 2, 228, 182]
+[:mouse_move, 386, 438, 2, 229, 182]
+[:mouse_move, 387, 437, 2, 230, 183]
+[:mouse_move, 387, 436, 2, 231, 183]
+[:mouse_move, 388, 434, 2, 232, 183]
+[:mouse_move, 388, 430, 2, 233, 183]
+[:mouse_move, 387, 428, 2, 234, 183]
+[:mouse_move, 387, 427, 2, 235, 183]
+[:mouse_move, 386, 425, 2, 236, 184]
+[:mouse_move, 383, 425, 2, 237, 184]
+[:mouse_move, 382, 425, 2, 238, 185]
+[:mouse_move, 381, 425, 2, 239, 185]
+[:mouse_move, 380, 424, 2, 240, 185]
+[:mouse_move, 379, 424, 2, 241, 187]
+[:mouse_move, 378, 424, 2, 242, 189]
+[:mouse_move, 377, 424, 2, 243, 192]
+[:mouse_move, 376, 424, 2, 244, 192]
+[:mouse_move, 375, 424, 2, 245, 194]
+[:mouse_move, 374, 424, 2, 246, 195]
+[:mouse_move, 373, 424, 2, 247, 196]
+[:mouse_move, 372, 424, 2, 248, 197]
+[:mouse_move, 370, 425, 2, 249, 197]
+[:mouse_move, 368, 425, 2, 250, 198]
+[:mouse_move, 367, 425, 2, 251, 198]
+[:mouse_move, 366, 425, 2, 252, 198]
+[:mouse_button_up, 1, 0, 1, 253, 203]
+[:mouse_move, 365, 423, 2, 254, 204]
+[:mouse_move, 360, 418, 2, 255, 204]
+[:mouse_move, 356, 413, 2, 256, 205]
+[:mouse_move, 350, 407, 2, 257, 205]
+[:mouse_move, 344, 401, 2, 258, 205]
+[:mouse_move, 337, 396, 2, 259, 206]
+[:mouse_move, 326, 390, 2, 260, 206]
+[:mouse_move, 311, 381, 2, 261, 207]
+[:mouse_move, 303, 377, 2, 262, 207]
+[:mouse_move, 297, 374, 2, 263, 207]
+[:mouse_move, 296, 374, 2, 264, 207]
+[:mouse_button_pressed, 1, 0, 1, 265, 211]
+[:mouse_button_up, 1, 0, 1, 266, 212]
+[:mouse_move, 297, 374, 2, 267, 213]
+[:mouse_move, 298, 374, 2, 268, 220]
+[:mouse_move, 300, 378, 2, 269, 221]
+[:mouse_move, 301, 384, 2, 270, 221]
+[:mouse_move, 301, 393, 2, 271, 222]
+[:mouse_move, 301, 401, 2, 272, 222]
+[:mouse_move, 301, 409, 2, 273, 223]
+[:mouse_move, 301, 412, 2, 274, 223]
+[:mouse_move, 301, 413, 2, 275, 224]
+[:mouse_move, 301, 415, 2, 276, 224]
+[:mouse_move, 302, 418, 2, 277, 225]
+[:mouse_move, 303, 419, 2, 278, 225]
+[:mouse_move, 303, 420, 2, 279, 226]
+[:mouse_button_pressed, 1, 0, 1, 280, 228]
+[:mouse_button_up, 1, 0, 1, 281, 230]
+[:mouse_move, 303, 421, 2, 282, 230]
+[:mouse_move, 303, 422, 2, 283, 231]
+[:mouse_move, 303, 426, 2, 284, 231]
+[:mouse_move, 302, 429, 2, 285, 232]
+[:mouse_move, 302, 430, 2, 286, 232]
+[:mouse_move, 302, 432, 2, 287, 232]
+[:mouse_move, 302, 436, 2, 288, 233]
+[:mouse_move, 302, 438, 2, 289, 233]
+[:mouse_move, 302, 440, 2, 290, 233]
+[:mouse_move, 302, 441, 2, 291, 234]
+[:mouse_move, 302, 442, 2, 292, 234]
+[:mouse_move, 302, 443, 2, 293, 235]
+[:mouse_move, 302, 444, 2, 294, 236]
+[:mouse_move, 302, 445, 2, 295, 236]
+[:mouse_move, 303, 447, 2, 296, 237]
+[:mouse_move, 304, 451, 2, 297, 237]
+[:mouse_move, 304, 454, 2, 298, 237]
+[:mouse_move, 304, 456, 2, 299, 238]
+[:mouse_move, 304, 458, 2, 300, 238]
+[:mouse_move, 304, 460, 2, 301, 238]
+[:mouse_move, 304, 463, 2, 302, 239]
+[:mouse_button_pressed, 1, 0, 1, 303, 242]
+[:mouse_button_up, 1, 0, 1, 304, 244]
+[:mouse_move, 304, 464, 2, 305, 244]
+[:mouse_move, 304, 465, 2, 306, 245]
+[:mouse_move, 304, 470, 2, 307, 246]
+[:mouse_move, 304, 476, 2, 308, 246]
+[:mouse_move, 303, 485, 2, 309, 246]
+[:mouse_move, 301, 495, 2, 310, 247]
+[:mouse_move, 300, 500, 2, 311, 247]
+[:mouse_move, 300, 503, 2, 312, 247]
+[:mouse_move, 300, 506, 2, 313, 248]
+[:mouse_move, 301, 508, 2, 314, 248]
+[:mouse_move, 302, 510, 2, 315, 248]
+[:mouse_move, 302, 511, 2, 316, 249]
+[:mouse_move, 303, 512, 2, 317, 249]
+[:mouse_move, 303, 513, 2, 318, 251]
+[:mouse_button_pressed, 1, 0, 1, 319, 253]
+[:mouse_button_up, 1, 0, 1, 320, 255]
+[:mouse_move, 303, 512, 2, 321, 255]
+[:mouse_move, 304, 511, 2, 322, 265]
+[:mouse_move, 305, 511, 2, 323, 265]
+[:mouse_move, 307, 510, 2, 324, 266]
+[:mouse_move, 311, 509, 2, 325, 266]
+[:mouse_move, 315, 505, 2, 326, 266]
+[:mouse_move, 317, 504, 2, 327, 267]
+[:mouse_move, 317, 503, 2, 328, 268]
+[:mouse_move, 316, 503, 2, 329, 269]
+[:mouse_move, 316, 502, 2, 330, 289]
+[:mouse_move, 317, 501, 2, 331, 291]
+[:mouse_move, 318, 501, 2, 332, 292]
+[:mouse_move, 319, 501, 2, 333, 302]
+[:mouse_move, 319, 500, 2, 334, 303]
+[:key_down_raw, 96, 0, 2, 335, 303]
+[:mouse_move, 320, 500, 2, 336, 304]
+[:mouse_move, 323, 498, 2, 337, 304]
+[:mouse_move, 331, 496, 2, 338, 305]
+[:key_up_raw, 96, 0, 2, 339, 305]
+[:mouse_move, 341, 493, 2, 340, 305]
+[:mouse_move, 351, 489, 2, 341, 305]
+[:mouse_move, 363, 484, 2, 342, 306]
+[:mouse_move, 372, 482, 2, 343, 306]
+[:mouse_move, 384, 479, 2, 344, 306]
+[:mouse_move, 395, 479, 2, 345, 307]
+[:mouse_move, 402, 477, 2, 346, 307]
+[:mouse_move, 406, 475, 2, 347, 308]
+[:mouse_move, 403, 475, 2, 348, 308]
+[:mouse_move, 397, 473, 2, 349, 309]
+[:mouse_move, 394, 467, 2, 350, 311]
+[:mouse_move, 393, 467, 2, 351, 311]
+[:mouse_move, 397, 466, 2, 352, 312]
+[:mouse_move, 398, 465, 2, 353, 313]
+[:mouse_move, 399, 465, 2, 354, 313]
+[:mouse_move, 399, 464, 2, 355, 313]
+[:mouse_move, 400, 464, 2, 356, 314]
+[:mouse_move, 400, 463, 2, 357, 316]
+[:mouse_move, 401, 463, 2, 358, 318]
+[:mouse_move, 401, 462, 2, 359, 319]
+[:key_down_raw, 13, 0, 2, 360, 322]
diff --git a/samples/13_path_finding_algorithms/05_dijkstra/app/main.rb b/samples/13_path_finding_algorithms/05_dijkstra/app/main.rb
index b335447..1223779 100644
--- a/samples/13_path_finding_algorithms/05_dijkstra/app/main.rb
+++ b/samples/13_path_finding_algorithms/05_dijkstra/app/main.rb
@@ -19,8 +19,8 @@ class Movement_Costs
# The next step in the search is calculated
def tick
defaults
- render
- input
+ render
+ input
calc
end
@@ -37,7 +37,7 @@ class Movement_Costs
# Walls are stored in a hash for quick look up when doing the search
state.star ||= [1, 5]
state.target ||= [8, 4]
- state.walls ||= {[1, 1] => true, [2, 1] => true, [3, 1] => true, [1, 2] => true, [2, 2] => true, [3, 2] => true}
+ state.walls ||= {[1, 1] => true, [2, 1] => true, [3, 1] => true, [1, 2] => true, [2, 2] => true, [3, 2] => true}
state.hills ||= {
[4, 1] => true,
[5, 1] => true,
@@ -72,7 +72,7 @@ class Movement_Costs
# We store this value, because we want to remember the value even when
# the user's cursor is no longer over what they're interacting with, but
# they are still clicking down on the mouse.
- state.user_input ||= :none
+ state.user_input ||= :none
# Values that are used for the breadth first search
# Keeping track of what cells were visited prevents counting cells multiple times
@@ -96,7 +96,7 @@ class Movement_Costs
# Draws everything onto the screen
def render
- render_background
+ render_background
render_heat_maps
@@ -111,8 +111,8 @@ class Movement_Costs
# Draws what the grid looks like with nothing on it
def render_background
- render_unvisited
- render_grid_lines
+ render_unvisited
+ render_grid_lines
render_labels
end
@@ -131,7 +131,7 @@ class Movement_Costs
end
for y in 0..grid.height
- outputs.lines << horizontal_line(y)
+ outputs.lines << horizontal_line(y)
outputs.lines << shifted_horizontal_line(y)
end
end
@@ -244,16 +244,16 @@ class Movement_Costs
def render_star
outputs.sprites << [scale_up(state.star), 'star.png']
outputs.sprites << [move_and_scale_up(state.star), 'star.png']
- end
+ end
# Renders the target on both grids
def render_target
outputs.sprites << [scale_up(state.target), 'target.png']
outputs.sprites << [move_and_scale_up(state.target), 'target.png']
- end
+ end
def render_hills
- state.hills.each_key do |hill|
+ state.hills.each_key do |hill|
outputs.solids << [scale_up(hill), hill_color]
outputs.solids << [move_and_scale_up(hill), hill_color]
end
@@ -261,7 +261,7 @@ class Movement_Costs
# Draws the walls on both grids
def render_walls
- state.walls.each_key do |wall|
+ state.walls.each_key do |wall|
outputs.solids << [scale_up(wall), wall_color]
outputs.solids << [move_and_scale_up(wall), wall_color]
end
@@ -344,7 +344,7 @@ class Movement_Costs
# If the mouse was clicked this tick
if inputs.mouse.down
# Determine what the user is editing and edit the state.user_input variable
- determine_input
+ determine_input
end
# Process user input based on user_input variable and current mouse position
@@ -357,43 +357,43 @@ class Movement_Costs
# mouse left click is held
def determine_input
# If the mouse is over the star in the first grid
- if mouse_over_star?
+ if mouse_over_star?
# The user is editing the star from the first grid
- state.user_input = :star
+ state.user_input = :star
# If the mouse is over the star in the second grid
- elsif mouse_over_star2?
+ elsif mouse_over_star2?
# The user is editing the star from the second grid
- state.user_input = :star2
+ state.user_input = :star2
# If the mouse is over the target in the first grid
- elsif mouse_over_target?
+ elsif mouse_over_target?
# The user is editing the target from the first grid
- state.user_input = :target
+ state.user_input = :target
# If the mouse is over the target in the second grid
- elsif mouse_over_target2?
+ elsif mouse_over_target2?
# The user is editing the target from the second grid
- state.user_input = :target2
+ state.user_input = :target2
# If the mouse is over a wall in the first grid
- elsif mouse_over_wall?
+ elsif mouse_over_wall?
# The user is removing a wall from the first grid
- state.user_input = :remove_wall
+ state.user_input = :remove_wall
# If the mouse is over a wall in the second grid
- elsif mouse_over_wall2?
+ elsif mouse_over_wall2?
# The user is removing a wall from the second grid
state.user_input = :remove_wall2
# If the mouse is over a hill in the first grid
- elsif mouse_over_hill?
+ elsif mouse_over_hill?
# The user is adding a wall from the first grid
- state.user_input = :add_wall
+ state.user_input = :add_wall
# If the mouse is over a hill in the second grid
- elsif mouse_over_hill2?
+ elsif mouse_over_hill2?
# The user is adding a wall from the second grid
state.user_input = :add_wall2
# If the mouse is over the first grid
- elsif mouse_over_grid?
+ elsif mouse_over_grid?
# The user is adding a hill from the first grid
state.user_input = :add_hill
# If the mouse is over the second grid
- elsif mouse_over_grid2?
+ elsif mouse_over_grid2?
# The user is adding a hill from the second grid
state.user_input = :add_hill2
end
@@ -401,26 +401,26 @@ class Movement_Costs
# Processes click and drag based on what the user is currently dragging
def process_input
- if state.user_input == :star
- input_star
+ if state.user_input == :star
+ input_star
elsif state.user_input == :star2
- input_star2
- elsif state.user_input == :target
- input_target
- elsif state.user_input == :target2
- input_target2
- elsif state.user_input == :remove_wall
- input_remove_wall
+ input_star2
+ elsif state.user_input == :target
+ input_target
+ elsif state.user_input == :target2
+ input_target2
+ elsif state.user_input == :remove_wall
+ input_remove_wall
elsif state.user_input == :remove_wall2
- input_remove_wall2
- elsif state.user_input == :add_hill
- input_add_hill
- elsif state.user_input == :add_hill2
- input_add_hill2
- elsif state.user_input == :add_wall
- input_add_wall
- elsif state.user_input == :add_wall2
- input_add_wall2
+ input_remove_wall2
+ elsif state.user_input == :add_hill
+ input_add_hill
+ elsif state.user_input == :add_hill2
+ input_add_hill2
+ elsif state.user_input == :add_wall
+ input_add_wall
+ elsif state.user_input == :add_wall2
+ input_add_wall2
end
end
@@ -433,26 +433,26 @@ class Movement_Costs
calc_dijkstra
end
end
-
+
def calc_breadth_first
# Sets up the Breadth First Search
- breadth_first_search.visited[state.star] = true
- breadth_first_search.frontier << state.star
+ breadth_first_search.visited[state.star] = true
+ breadth_first_search.frontier << state.star
breadth_first_search.came_from[state.star] = nil
until breadth_first_search.frontier.empty?
return if breadth_first_search.visited.has_key?(state.target)
# A step in the search
# Takes the next frontier cell
- new_frontier = breadth_first_search.frontier.shift
+ new_frontier = breadth_first_search.frontier.shift
# For each of its neighbors
- adjacent_neighbors(new_frontier).each do | neighbor |
+ adjacent_neighbors(new_frontier).each do | neighbor |
# That have not been visited and are not walls
- unless breadth_first_search.visited.has_key?(neighbor) || state.walls.has_key?(neighbor)
+ unless breadth_first_search.visited.has_key?(neighbor) || state.walls.has_key?(neighbor)
# Add them to the frontier and mark them as visited in the first grid
- breadth_first_search.visited[neighbor] = true
- breadth_first_search.frontier << neighbor
+ breadth_first_search.visited[neighbor] = true
+ breadth_first_search.frontier << neighbor
# Remember which cell the neighbor came from
breadth_first_search.came_from[neighbor] = new_frontier
end
@@ -512,12 +512,12 @@ class Movement_Costs
# Only resets the search if the star changes position
# Called whenever the user is editing the star (puts mouse down on star)
def input_star
- old_star = state.star.clone
+ old_star = state.star.clone
unless cell_closest_to_mouse == state.target
- state.star = cell_closest_to_mouse
+ state.star = cell_closest_to_mouse
end
- unless old_star == state.star
- reset_search
+ unless old_star == state.star
+ reset_search
end
end
@@ -525,12 +525,12 @@ class Movement_Costs
# Only resets the search if the star changes position
# Called whenever the user is editing the star (puts mouse down on star)
def input_star2
- old_star = state.star.clone
+ old_star = state.star.clone
unless cell_closest_to_mouse2 == state.target
state.star = cell_closest_to_mouse2
end
- unless old_star == state.star
- reset_search
+ unless old_star == state.star
+ reset_search
end
end
@@ -538,12 +538,12 @@ class Movement_Costs
# Only reset_searchs the search if the target changes position
# Called whenever the user is editing the target (puts mouse down on target)
def input_target
- old_target = state.target.clone
+ old_target = state.target.clone
unless cell_closest_to_mouse == state.star
state.target = cell_closest_to_mouse
end
- unless old_target == state.target
- reset_search
+ unless old_target == state.target
+ reset_search
end
end
@@ -551,12 +551,12 @@ class Movement_Costs
# Only reset_searchs the search if the target changes position
# Called whenever the user is editing the target (puts mouse down on target)
def input_target2
- old_target = state.target.clone
+ old_target = state.target.clone
unless cell_closest_to_mouse2 == state.star
state.target = cell_closest_to_mouse2
end
- unless old_target == state.target
- reset_search
+ unless old_target == state.target
+ reset_search
end
end
@@ -565,11 +565,11 @@ class Movement_Costs
# The mouse needs to be inside the grid, because we only want to remove walls
# the cursor is directly over
# Recalculations should only occur when a wall is actually deleted
- if mouse_over_grid?
+ if mouse_over_grid?
if state.walls.has_key?(cell_closest_to_mouse) or state.hills.has_key?(cell_closest_to_mouse)
- state.walls.delete(cell_closest_to_mouse)
- state.hills.delete(cell_closest_to_mouse)
- reset_search
+ state.walls.delete(cell_closest_to_mouse)
+ state.hills.delete(cell_closest_to_mouse)
+ reset_search
end
end
end
@@ -579,21 +579,21 @@ class Movement_Costs
# The mouse needs to be inside the grid, because we only want to remove walls
# the cursor is directly over
# Recalculations should only occur when a wall is actually deleted
- if mouse_over_grid2?
+ if mouse_over_grid2?
if state.walls.has_key?(cell_closest_to_mouse2) or state.hills.has_key?(cell_closest_to_mouse2)
- state.walls.delete(cell_closest_to_mouse2)
- state.hills.delete(cell_closest_to_mouse2)
- reset_search
+ state.walls.delete(cell_closest_to_mouse2)
+ state.hills.delete(cell_closest_to_mouse2)
+ reset_search
end
end
end
# Adds a hill in the first grid in the cell the mouse is over
def input_add_hill
- if mouse_over_grid?
+ if mouse_over_grid?
unless state.hills.has_key?(cell_closest_to_mouse)
- state.hills[cell_closest_to_mouse] = true
- reset_search
+ state.hills[cell_closest_to_mouse] = true
+ reset_search
end
end
end
@@ -601,32 +601,32 @@ class Movement_Costs
# Adds a hill in the second grid in the cell the mouse is over
def input_add_hill2
- if mouse_over_grid2?
+ if mouse_over_grid2?
unless state.hills.has_key?(cell_closest_to_mouse2)
- state.hills[cell_closest_to_mouse2] = true
- reset_search
+ state.hills[cell_closest_to_mouse2] = true
+ reset_search
end
end
end
# Adds a wall in the first grid in the cell the mouse is over
def input_add_wall
- if mouse_over_grid?
+ if mouse_over_grid?
unless state.walls.has_key?(cell_closest_to_mouse)
- state.hills.delete(cell_closest_to_mouse)
- state.walls[cell_closest_to_mouse] = true
- reset_search
+ state.hills.delete(cell_closest_to_mouse)
+ state.walls[cell_closest_to_mouse] = true
+ reset_search
end
end
end
# Adds a wall in the second grid in the cell the mouse is over
def input_add_wall2
- if mouse_over_grid2?
+ if mouse_over_grid2?
unless state.walls.has_key?(cell_closest_to_mouse2)
- state.hills.delete(cell_closest_to_mouse2)
- state.walls[cell_closest_to_mouse2] = true
- reset_search
+ state.hills.delete(cell_closest_to_mouse2)
+ state.walls[cell_closest_to_mouse2] = true
+ reset_search
end
end
end
@@ -649,21 +649,21 @@ class Movement_Costs
# Returns a list of adjacent cells
# Used to determine what the next cells to be added to the frontier are
def adjacent_neighbors(cell)
- neighbors = []
+ neighbors = []
# Gets all the valid neighbors into the array
# From southern neighbor, clockwise
- neighbors << [cell.x , cell.y - 1] unless cell.y == 0
- neighbors << [cell.x - 1, cell.y ] unless cell.x == 0
- neighbors << [cell.x , cell.y + 1] unless cell.y == grid.height - 1
- neighbors << [cell.x + 1, cell.y ] unless cell.x == grid.width - 1
+ neighbors << [cell.x , cell.y - 1] unless cell.y == 0
+ neighbors << [cell.x - 1, cell.y ] unless cell.x == 0
+ neighbors << [cell.x , cell.y + 1] unless cell.y == grid.height - 1
+ neighbors << [cell.x + 1, cell.y ] unless cell.x == grid.width - 1
# Sorts the neighbors so the rendered path is a zigzag path
# Cells in a diagonal direction are given priority
# Comment this line to see the difference
neighbors = neighbors.sort_by { |neighbor_x, neighbor_y| proximity_to_star(neighbor_x, neighbor_y) }
- neighbors
+ neighbors
end
# Finds the vertical and horizontal distance of a cell from the star
@@ -688,13 +688,13 @@ class Movement_Costs
# Finding the cell closest to the mouse helps with this
def cell_closest_to_mouse
# Closest cell to the mouse in the first grid
- x = (inputs.mouse.point.x / grid.cell_size).to_i
- y = (inputs.mouse.point.y / grid.cell_size).to_i
+ x = (inputs.mouse.point.x / grid.cell_size).to_i
+ y = (inputs.mouse.point.y / grid.cell_size).to_i
# Bound x and y to the grid
- x = grid.width - 1 if x > grid.width - 1
- y = grid.height - 1 if y > grid.height - 1
+ x = grid.width - 1 if x > grid.width - 1
+ y = grid.height - 1 if y > grid.height - 1
# Return closest cell
- [x, y]
+ [x, y]
end
# When the user grabs the star and puts their cursor to the far right
@@ -702,17 +702,17 @@ class Movement_Costs
# Finding the cell closest to the mouse in the second grid helps with this
def cell_closest_to_mouse2
# Closest cell grid to the mouse in the second
- x = (inputs.mouse.point.x / grid.cell_size).to_i
- y = (inputs.mouse.point.y / grid.cell_size).to_i
+ x = (inputs.mouse.point.x / grid.cell_size).to_i
+ y = (inputs.mouse.point.y / grid.cell_size).to_i
# Translate the cell to the first grid
x -= grid.width + 1
# Bound x and y to the first grid
x = 0 if x < 0
y = 0 if y < 0
- x = grid.width - 1 if x > grid.width - 1
- y = grid.height - 1 if y > grid.height - 1
+ x = grid.width - 1 if x > grid.width - 1
+ y = grid.height - 1 if y > grid.height - 1
# Return closest cell
- [x, y]
+ [x, y]
end
# Signal that the user is going to be moving the star from the first grid
@@ -785,12 +785,12 @@ class Movement_Costs
# Light brown
def unvisited_color
- [221, 212, 213]
+ [221, 212, 213]
end
# Camo Green
def wall_color
- [134, 134, 120]
+ [134, 134, 120]
end
# Pastel White
@@ -833,7 +833,7 @@ def tick args
end
# Every tick, new args are passed, and the Dijkstra tick method is called
- $movement_costs ||= Movement_Costs.new(args)
+ $movement_costs ||= Movement_Costs.new
$movement_costs.args = args
$movement_costs.tick
end
diff --git a/samples/13_path_finding_algorithms/05_dijkstra/replay.txt b/samples/13_path_finding_algorithms/05_dijkstra/replay.txt
new file mode 100644
index 0000000..a459873
--- /dev/null
+++ b/samples/13_path_finding_algorithms/05_dijkstra/replay.txt
@@ -0,0 +1,686 @@
+replay_version 2.0
+stopped_at 730
+seed 100
+recorded_at 2021-11-20 11:20:27 -0600
+[:mouse_button_up, 1, 0, 1, 1, 1]
+[:mouse_move, 782, 97, 2, 2, 14]
+[:mouse_move, 782, 98, 2, 3, 15]
+[:mouse_move, 782, 99, 2, 4, 15]
+[:mouse_move, 782, 100, 2, 5, 16]
+[:mouse_move, 780, 102, 2, 6, 16]
+[:mouse_move, 773, 111, 2, 7, 17]
+[:mouse_move, 768, 123, 2, 8, 17]
+[:mouse_move, 759, 142, 2, 9, 18]
+[:mouse_move, 740, 166, 2, 10, 18]
+[:mouse_move, 718, 196, 2, 11, 19]
+[:mouse_move, 699, 232, 2, 12, 19]
+[:mouse_move, 686, 272, 2, 13, 20]
+[:mouse_move, 673, 314, 2, 14, 20]
+[:mouse_move, 648, 355, 2, 15, 21]
+[:mouse_move, 594, 404, 2, 16, 21]
+[:mouse_move, 562, 427, 2, 17, 22]
+[:mouse_move, 532, 446, 2, 18, 22]
+[:mouse_move, 509, 458, 2, 19, 23]
+[:mouse_move, 490, 464, 2, 20, 23]
+[:mouse_move, 482, 466, 2, 21, 23]
+[:mouse_move, 481, 466, 2, 22, 24]
+[:mouse_move, 481, 460, 2, 23, 25]
+[:mouse_move, 490, 451, 2, 24, 26]
+[:mouse_move, 501, 443, 2, 25, 26]
+[:mouse_move, 506, 441, 2, 26, 26]
+[:mouse_move, 506, 442, 2, 27, 29]
+[:mouse_move, 507, 442, 2, 28, 31]
+[:mouse_move, 508, 442, 2, 29, 32]
+[:mouse_move, 509, 442, 2, 30, 37]
+[:mouse_move, 510, 442, 2, 31, 48]
+[:mouse_move, 507, 442, 2, 32, 63]
+[:mouse_move, 500, 444, 2, 33, 63]
+[:mouse_move, 488, 446, 2, 34, 64]
+[:mouse_move, 476, 447, 2, 35, 64]
+[:mouse_move, 466, 449, 2, 36, 65]
+[:mouse_move, 459, 450, 2, 37, 65]
+[:mouse_move, 449, 452, 2, 38, 66]
+[:mouse_move, 440, 453, 2, 39, 66]
+[:mouse_move, 433, 454, 2, 40, 67]
+[:mouse_move, 432, 454, 2, 41, 67]
+[:mouse_move, 436, 455, 2, 42, 69]
+[:mouse_move, 442, 455, 2, 43, 69]
+[:mouse_move, 446, 455, 2, 44, 70]
+[:mouse_move, 450, 455, 2, 45, 70]
+[:mouse_move, 456, 448, 2, 46, 70]
+[:mouse_move, 458, 437, 2, 47, 71]
+[:mouse_move, 458, 422, 2, 48, 72]
+[:mouse_move, 451, 402, 2, 49, 72]
+[:mouse_move, 440, 376, 2, 50, 72]
+[:mouse_move, 414, 334, 2, 51, 73]
+[:mouse_move, 393, 303, 2, 52, 74]
+[:mouse_move, 378, 280, 2, 53, 74]
+[:mouse_move, 367, 265, 2, 54, 75]
+[:mouse_move, 358, 255, 2, 55, 75]
+[:mouse_move, 353, 251, 2, 56, 75]
+[:mouse_move, 349, 248, 2, 57, 76]
+[:mouse_move, 348, 248, 2, 58, 76]
+[:mouse_move, 345, 249, 2, 59, 77]
+[:mouse_move, 344, 249, 2, 60, 78]
+[:mouse_move, 338, 246, 2, 61, 79]
+[:mouse_move, 332, 240, 2, 62, 79]
+[:mouse_move, 328, 231, 2, 63, 80]
+[:mouse_move, 326, 222, 2, 64, 80]
+[:mouse_move, 326, 214, 2, 65, 81]
+[:mouse_move, 331, 208, 2, 66, 81]
+[:mouse_move, 340, 204, 2, 67, 82]
+[:mouse_move, 348, 202, 2, 68, 82]
+[:mouse_move, 357, 202, 2, 69, 83]
+[:mouse_move, 363, 202, 2, 70, 84]
+[:mouse_move, 365, 202, 2, 71, 84]
+[:mouse_move, 366, 202, 2, 72, 84]
+[:mouse_move, 374, 203, 2, 73, 85]
+[:mouse_move, 380, 204, 2, 74, 85]
+[:mouse_move, 382, 204, 2, 75, 86]
+[:mouse_move, 383, 204, 2, 76, 86]
+[:mouse_button_pressed, 1, 0, 1, 77, 88]
+[:mouse_button_up, 1, 0, 1, 78, 89]
+[:mouse_move, 384, 204, 2, 79, 99]
+[:mouse_move, 384, 205, 2, 80, 100]
+[:mouse_move, 389, 210, 2, 81, 101]
+[:mouse_move, 394, 214, 2, 82, 101]
+[:mouse_move, 399, 220, 2, 83, 101]
+[:mouse_move, 405, 228, 2, 84, 102]
+[:mouse_move, 410, 242, 2, 85, 103]
+[:mouse_move, 416, 261, 2, 86, 103]
+[:mouse_move, 422, 276, 2, 87, 104]
+[:mouse_move, 428, 284, 2, 88, 104]
+[:mouse_move, 430, 287, 2, 89, 104]
+[:mouse_move, 431, 288, 2, 90, 105]
+[:mouse_move, 433, 290, 2, 91, 105]
+[:mouse_move, 434, 295, 2, 92, 106]
+[:mouse_move, 435, 306, 2, 93, 106]
+[:mouse_move, 436, 311, 2, 94, 107]
+[:mouse_move, 436, 312, 2, 95, 108]
+[:mouse_move, 438, 314, 2, 96, 112]
+[:mouse_move, 441, 320, 2, 97, 113]
+[:mouse_move, 447, 341, 2, 98, 113]
+[:mouse_move, 453, 376, 2, 99, 114]
+[:mouse_move, 456, 413, 2, 100, 114]
+[:mouse_move, 456, 445, 2, 101, 115]
+[:mouse_move, 455, 475, 2, 102, 115]
+[:mouse_move, 450, 498, 2, 103, 116]
+[:mouse_move, 446, 519, 2, 104, 116]
+[:mouse_move, 446, 541, 2, 105, 117]
+[:mouse_move, 452, 559, 2, 106, 117]
+[:mouse_move, 458, 569, 2, 107, 117]
+[:mouse_move, 464, 573, 2, 108, 118]
+[:mouse_move, 468, 573, 2, 109, 119]
+[:mouse_move, 471, 570, 2, 110, 119]
+[:mouse_move, 474, 559, 2, 111, 120]
+[:mouse_move, 476, 539, 2, 112, 120]
+[:mouse_move, 483, 527, 2, 113, 120]
+[:mouse_move, 489, 519, 2, 114, 121]
+[:mouse_move, 493, 515, 2, 115, 121]
+[:mouse_move, 493, 511, 2, 116, 122]
+[:mouse_move, 493, 505, 2, 117, 122]
+[:mouse_move, 493, 499, 2, 118, 123]
+[:mouse_move, 490, 496, 2, 119, 123]
+[:mouse_move, 488, 493, 2, 120, 124]
+[:mouse_move, 487, 493, 2, 121, 124]
+[:mouse_move, 484, 493, 2, 122, 125]
+[:mouse_move, 482, 493, 2, 123, 125]
+[:mouse_move, 479, 494, 2, 124, 126]
+[:mouse_move, 474, 495, 2, 125, 126]
+[:mouse_move, 470, 499, 2, 126, 127]
+[:mouse_move, 470, 503, 2, 127, 127]
+[:mouse_move, 470, 506, 2, 128, 128]
+[:mouse_button_pressed, 1, 0, 1, 129, 131]
+[:mouse_button_up, 1, 0, 1, 130, 132]
+[:mouse_move, 470, 503, 2, 131, 135]
+[:mouse_move, 470, 495, 2, 132, 135]
+[:mouse_move, 470, 488, 2, 133, 135]
+[:mouse_move, 472, 478, 2, 134, 136]
+[:mouse_move, 473, 470, 2, 135, 137]
+[:mouse_move, 474, 459, 2, 136, 137]
+[:mouse_move, 474, 450, 2, 137, 138]
+[:mouse_move, 474, 445, 2, 138, 138]
+[:mouse_move, 472, 441, 2, 139, 138]
+[:mouse_move, 470, 439, 2, 140, 139]
+[:mouse_move, 467, 438, 2, 141, 139]
+[:mouse_move, 465, 438, 2, 142, 140]
+[:mouse_move, 464, 438, 2, 143, 140]
+[:mouse_move, 463, 438, 2, 144, 141]
+[:mouse_move, 460, 438, 2, 145, 141]
+[:mouse_move, 459, 438, 2, 146, 142]
+[:mouse_button_pressed, 1, 0, 1, 147, 144]
+[:mouse_button_up, 1, 0, 1, 148, 145]
+[:mouse_move, 459, 439, 2, 149, 153]
+[:mouse_move, 459, 438, 2, 150, 164]
+[:mouse_move, 458, 434, 2, 151, 164]
+[:mouse_move, 458, 426, 2, 152, 165]
+[:mouse_move, 458, 414, 2, 153, 165]
+[:mouse_move, 461, 400, 2, 154, 166]
+[:mouse_move, 461, 397, 2, 155, 166]
+[:mouse_move, 461, 396, 2, 156, 166]
+[:mouse_move, 461, 395, 2, 157, 167]
+[:mouse_button_pressed, 1, 0, 1, 158, 170]
+[:mouse_button_up, 1, 0, 1, 159, 171]
+[:mouse_move, 461, 394, 2, 160, 174]
+[:mouse_move, 461, 391, 2, 161, 175]
+[:mouse_move, 461, 387, 2, 162, 175]
+[:mouse_move, 461, 381, 2, 163, 176]
+[:mouse_move, 461, 379, 2, 164, 176]
+[:mouse_move, 461, 378, 2, 165, 177]
+[:mouse_move, 461, 377, 2, 166, 177]
+[:mouse_move, 461, 375, 2, 167, 179]
+[:mouse_move, 461, 374, 2, 168, 179]
+[:mouse_move, 461, 373, 2, 169, 180]
+[:mouse_move, 461, 372, 2, 170, 181]
+[:mouse_move, 461, 370, 2, 171, 181]
+[:mouse_move, 460, 365, 2, 172, 182]
+[:mouse_move, 460, 362, 2, 173, 182]
+[:mouse_move, 460, 359, 2, 174, 182]
+[:mouse_move, 460, 358, 2, 175, 184]
+[:mouse_move, 459, 356, 2, 176, 185]
+[:mouse_move, 459, 355, 2, 177, 186]
+[:mouse_move, 459, 352, 2, 178, 186]
+[:mouse_move, 459, 351, 2, 179, 187]
+[:mouse_move, 458, 350, 2, 180, 187]
+[:mouse_move, 458, 349, 2, 181, 187]
+[:mouse_move, 457, 352, 2, 182, 191]
+[:mouse_move, 456, 369, 2, 183, 192]
+[:mouse_move, 456, 381, 2, 184, 192]
+[:mouse_move, 456, 393, 2, 185, 193]
+[:mouse_move, 460, 412, 2, 186, 193]
+[:mouse_move, 466, 429, 2, 187, 193]
+[:mouse_move, 471, 448, 2, 188, 194]
+[:mouse_move, 472, 464, 2, 189, 194]
+[:mouse_move, 473, 477, 2, 190, 195]
+[:mouse_move, 474, 488, 2, 191, 196]
+[:mouse_move, 474, 497, 2, 192, 196]
+[:mouse_move, 474, 499, 2, 193, 196]
+[:mouse_move, 472, 504, 2, 194, 197]
+[:mouse_move, 470, 513, 2, 195, 197]
+[:mouse_move, 470, 516, 2, 196, 197]
+[:mouse_move, 470, 517, 2, 197, 198]
+[:mouse_move, 470, 519, 2, 198, 199]
+[:mouse_move, 470, 521, 2, 199, 199]
+[:mouse_move, 470, 522, 2, 200, 200]
+[:mouse_move, 470, 523, 2, 201, 201]
+[:mouse_move, 467, 521, 2, 202, 203]
+[:mouse_move, 464, 518, 2, 203, 203]
+[:mouse_move, 462, 515, 2, 204, 204]
+[:mouse_move, 461, 511, 2, 205, 205]
+[:mouse_button_pressed, 1, 0, 1, 206, 210]
+[:mouse_button_up, 1, 0, 1, 207, 211]
+[:mouse_move, 462, 511, 2, 208, 218]
+[:mouse_move, 465, 510, 2, 209, 218]
+[:mouse_move, 470, 508, 2, 210, 218]
+[:mouse_move, 475, 505, 2, 211, 219]
+[:mouse_move, 483, 502, 2, 212, 219]
+[:mouse_move, 493, 498, 2, 213, 220]
+[:mouse_move, 506, 491, 2, 214, 221]
+[:mouse_move, 517, 479, 2, 215, 221]
+[:mouse_move, 521, 471, 2, 216, 221]
+[:mouse_move, 523, 467, 2, 217, 222]
+[:mouse_move, 523, 464, 2, 218, 222]
+[:mouse_move, 522, 464, 2, 219, 227]
+[:mouse_move, 521, 464, 2, 220, 227]
+[:mouse_move, 518, 464, 2, 221, 228]
+[:mouse_move, 513, 460, 2, 222, 228]
+[:mouse_move, 513, 459, 2, 223, 228]
+[:mouse_move, 512, 459, 2, 224, 229]
+[:mouse_move, 512, 458, 2, 225, 229]
+[:mouse_button_pressed, 1, 0, 1, 226, 232]
+[:mouse_move, 513, 458, 2, 227, 233]
+[:mouse_move, 514, 458, 2, 228, 234]
+[:mouse_move, 516, 458, 2, 229, 234]
+[:mouse_move, 517, 458, 2, 230, 235]
+[:mouse_move, 523, 453, 2, 231, 235]
+[:mouse_move, 531, 444, 2, 232, 235]
+[:mouse_move, 537, 436, 2, 233, 236]
+[:mouse_move, 541, 428, 2, 234, 236]
+[:mouse_move, 543, 421, 2, 235, 237]
+[:mouse_move, 545, 413, 2, 236, 237]
+[:mouse_move, 546, 405, 2, 237, 237]
+[:mouse_move, 547, 396, 2, 238, 237]
+[:mouse_move, 547, 389, 2, 239, 237]
+[:mouse_move, 547, 383, 2, 240, 237]
+[:mouse_move, 547, 379, 2, 241, 238]
+[:mouse_move, 547, 378, 2, 242, 238]
+[:mouse_move, 547, 376, 2, 243, 238]
+[:mouse_move, 546, 375, 2, 244, 238]
+[:mouse_move, 546, 374, 2, 245, 238]
+[:mouse_move, 546, 372, 2, 246, 239]
+[:mouse_move, 545, 368, 2, 247, 239]
+[:mouse_move, 544, 366, 2, 248, 239]
+[:mouse_move, 543, 363, 2, 249, 240]
+[:mouse_move, 540, 357, 2, 250, 240]
+[:mouse_move, 534, 350, 2, 251, 241]
+[:mouse_move, 528, 344, 2, 252, 241]
+[:mouse_move, 520, 339, 2, 253, 241]
+[:mouse_move, 517, 339, 2, 254, 241]
+[:mouse_move, 514, 337, 2, 255, 241]
+[:mouse_move, 513, 337, 2, 256, 242]
+[:mouse_move, 511, 336, 2, 257, 242]
+[:mouse_move, 509, 336, 2, 258, 242]
+[:mouse_move, 508, 336, 2, 259, 242]
+[:mouse_move, 507, 336, 2, 260, 242]
+[:mouse_move, 505, 335, 2, 261, 242]
+[:mouse_move, 502, 335, 2, 262, 243]
+[:mouse_move, 498, 335, 2, 263, 244]
+[:mouse_move, 494, 335, 2, 264, 244]
+[:mouse_move, 484, 335, 2, 265, 244]
+[:mouse_move, 475, 335, 2, 266, 245]
+[:mouse_move, 469, 335, 2, 267, 245]
+[:mouse_move, 459, 338, 2, 268, 246]
+[:mouse_move, 451, 342, 2, 269, 246]
+[:mouse_move, 441, 347, 2, 270, 246]
+[:mouse_move, 430, 352, 2, 271, 246]
+[:mouse_move, 421, 357, 2, 272, 247]
+[:mouse_move, 408, 366, 2, 273, 247]
+[:mouse_move, 398, 375, 2, 274, 247]
+[:mouse_move, 390, 386, 2, 275, 248]
+[:mouse_move, 380, 402, 2, 276, 248]
+[:mouse_move, 374, 412, 2, 277, 248]
+[:mouse_move, 368, 420, 2, 278, 248]
+[:mouse_move, 364, 427, 2, 279, 248]
+[:mouse_move, 362, 437, 2, 280, 249]
+[:mouse_move, 362, 448, 2, 281, 249]
+[:mouse_move, 362, 455, 2, 282, 249]
+[:mouse_move, 362, 463, 2, 283, 249]
+[:mouse_move, 362, 467, 2, 284, 249]
+[:mouse_move, 362, 473, 2, 285, 250]
+[:mouse_move, 364, 483, 2, 286, 250]
+[:mouse_move, 368, 490, 2, 287, 251]
+[:mouse_move, 372, 496, 2, 288, 251]
+[:mouse_move, 379, 505, 2, 289, 251]
+[:mouse_move, 384, 509, 2, 290, 251]
+[:mouse_move, 385, 511, 2, 291, 251]
+[:mouse_move, 387, 511, 2, 292, 252]
+[:mouse_move, 387, 512, 2, 293, 252]
+[:mouse_move, 388, 512, 2, 294, 253]
+[:mouse_move, 390, 514, 2, 295, 254]
+[:mouse_move, 392, 516, 2, 296, 254]
+[:mouse_move, 392, 517, 2, 297, 254]
+[:mouse_move, 393, 518, 2, 298, 255]
+[:mouse_move, 394, 520, 2, 299, 255]
+[:mouse_move, 395, 523, 2, 300, 256]
+[:mouse_move, 395, 527, 2, 301, 257]
+[:mouse_move, 395, 533, 2, 302, 257]
+[:mouse_move, 392, 542, 2, 303, 258]
+[:mouse_move, 392, 555, 2, 304, 258]
+[:mouse_move, 392, 567, 2, 305, 258]
+[:mouse_move, 392, 576, 2, 306, 259]
+[:mouse_move, 392, 583, 2, 307, 259]
+[:mouse_move, 392, 587, 2, 308, 259]
+[:mouse_move, 392, 590, 2, 309, 259]
+[:mouse_move, 392, 592, 2, 310, 260]
+[:mouse_move, 391, 594, 2, 311, 260]
+[:mouse_move, 391, 595, 2, 312, 261]
+[:mouse_move, 389, 597, 2, 313, 262]
+[:mouse_move, 382, 602, 2, 314, 262]
+[:mouse_move, 372, 608, 2, 315, 263]
+[:mouse_move, 359, 612, 2, 316, 263]
+[:mouse_move, 345, 619, 2, 317, 263]
+[:mouse_move, 329, 626, 2, 318, 263]
+[:mouse_move, 314, 633, 2, 319, 263]
+[:mouse_move, 301, 639, 2, 320, 263]
+[:mouse_move, 286, 643, 2, 321, 264]
+[:mouse_move, 270, 646, 2, 322, 264]
+[:mouse_move, 255, 647, 2, 323, 264]
+[:mouse_move, 236, 650, 2, 324, 264]
+[:mouse_move, 227, 650, 2, 325, 265]
+[:mouse_move, 216, 650, 2, 326, 265]
+[:mouse_move, 207, 650, 2, 327, 265]
+[:mouse_move, 203, 651, 2, 328, 265]
+[:mouse_move, 202, 651, 2, 329, 265]
+[:mouse_move, 201, 651, 2, 330, 265]
+[:mouse_move, 200, 651, 2, 331, 267]
+[:mouse_move, 199, 651, 2, 332, 267]
+[:mouse_move, 198, 651, 2, 333, 268]
+[:mouse_move, 195, 652, 2, 334, 268]
+[:mouse_move, 194, 653, 2, 335, 269]
+[:mouse_move, 193, 654, 2, 336, 269]
+[:mouse_move, 193, 655, 2, 337, 272]
+[:mouse_move, 192, 655, 2, 338, 272]
+[:mouse_move, 192, 656, 2, 339, 274]
+[:mouse_move, 192, 658, 2, 340, 275]
+[:mouse_move, 192, 661, 2, 341, 275]
+[:mouse_move, 192, 662, 2, 342, 275]
+[:mouse_move, 192, 664, 2, 343, 276]
+[:mouse_move, 192, 665, 2, 344, 277]
+[:mouse_button_up, 1, 0, 1, 345, 329]
+[:mouse_move, 192, 664, 2, 346, 337]
+[:mouse_move, 193, 664, 2, 347, 354]
+[:mouse_move, 195, 663, 2, 348, 355]
+[:mouse_move, 201, 662, 2, 349, 355]
+[:mouse_move, 211, 660, 2, 350, 356]
+[:mouse_move, 227, 659, 2, 351, 357]
+[:mouse_move, 283, 651, 2, 352, 357]
+[:mouse_move, 348, 641, 2, 353, 358]
+[:mouse_move, 431, 632, 2, 354, 358]
+[:mouse_move, 522, 622, 2, 355, 359]
+[:mouse_move, 605, 609, 2, 356, 359]
+[:mouse_move, 661, 603, 2, 357, 360]
+[:mouse_move, 687, 599, 2, 358, 361]
+[:mouse_move, 702, 596, 2, 359, 361]
+[:mouse_move, 708, 595, 2, 360, 362]
+[:mouse_move, 711, 593, 2, 361, 362]
+[:mouse_move, 712, 592, 2, 362, 364]
+[:mouse_move, 714, 590, 2, 363, 364]
+[:mouse_move, 715, 589, 2, 364, 365]
+[:mouse_move, 715, 587, 2, 365, 365]
+[:mouse_move, 713, 584, 2, 366, 366]
+[:mouse_move, 712, 584, 2, 367, 367]
+[:mouse_move, 711, 583, 2, 368, 368]
+[:mouse_move, 712, 582, 2, 369, 369]
+[:mouse_move, 716, 579, 2, 370, 370]
+[:mouse_move, 719, 578, 2, 371, 371]
+[:mouse_move, 740, 571, 2, 372, 372]
+[:mouse_move, 757, 569, 2, 373, 372]
+[:mouse_move, 764, 568, 2, 374, 372]
+[:mouse_move, 764, 567, 2, 375, 374]
+[:mouse_button_pressed, 1, 0, 1, 376, 376]
+[:mouse_button_up, 1, 0, 1, 377, 377]
+[:mouse_move, 764, 571, 2, 378, 390]
+[:mouse_move, 764, 579, 2, 379, 391]
+[:mouse_move, 764, 584, 2, 380, 391]
+[:mouse_move, 763, 586, 2, 381, 392]
+[:mouse_move, 760, 592, 2, 382, 393]
+[:mouse_move, 755, 600, 2, 383, 393]
+[:mouse_move, 752, 606, 2, 384, 393]
+[:mouse_move, 750, 607, 2, 385, 394]
+[:mouse_move, 750, 608, 2, 386, 395]
+[:mouse_move, 750, 610, 2, 387, 396]
+[:mouse_move, 750, 614, 2, 388, 396]
+[:mouse_move, 750, 615, 2, 389, 396]
+[:mouse_move, 750, 617, 2, 390, 397]
+[:mouse_move, 750, 618, 2, 391, 398]
+[:mouse_move, 750, 620, 2, 392, 399]
+[:mouse_move, 749, 622, 2, 393, 400]
+[:mouse_button_pressed, 1, 0, 1, 394, 401]
+[:mouse_button_up, 1, 0, 1, 395, 403]
+[:mouse_move, 749, 623, 2, 396, 408]
+[:mouse_move, 750, 623, 2, 397, 410]
+[:mouse_move, 754, 624, 2, 398, 410]
+[:mouse_move, 760, 625, 2, 399, 411]
+[:mouse_move, 769, 628, 2, 400, 411]
+[:mouse_move, 785, 630, 2, 401, 412]
+[:mouse_move, 791, 631, 2, 402, 413]
+[:mouse_move, 792, 631, 2, 403, 414]
+[:mouse_move, 793, 631, 2, 404, 414]
+[:mouse_move, 794, 631, 2, 405, 415]
+[:mouse_move, 795, 631, 2, 406, 415]
+[:mouse_move, 796, 631, 2, 407, 416]
+[:mouse_move, 798, 631, 2, 408, 417]
+[:mouse_move, 799, 631, 2, 409, 422]
+[:mouse_move, 799, 630, 2, 410, 423]
+[:mouse_move, 800, 627, 2, 411, 426]
+[:mouse_move, 802, 621, 2, 412, 427]
+[:mouse_move, 804, 609, 2, 413, 427]
+[:mouse_move, 806, 601, 2, 414, 428]
+[:mouse_move, 804, 595, 2, 415, 429]
+[:mouse_move, 799, 591, 2, 416, 430]
+[:mouse_move, 796, 591, 2, 417, 430]
+[:mouse_move, 792, 591, 2, 418, 430]
+[:mouse_move, 786, 593, 2, 419, 431]
+[:mouse_move, 775, 597, 2, 420, 432]
+[:mouse_move, 766, 600, 2, 421, 433]
+[:mouse_move, 763, 600, 2, 422, 434]
+[:mouse_move, 762, 600, 2, 423, 434]
+[:mouse_move, 761, 599, 2, 424, 435]
+[:mouse_move, 759, 592, 2, 425, 435]
+[:mouse_move, 756, 578, 2, 426, 436]
+[:mouse_move, 755, 571, 2, 427, 437]
+[:mouse_move, 755, 566, 2, 428, 437]
+[:mouse_button_pressed, 1, 0, 1, 429, 440]
+[:mouse_button_up, 1, 0, 1, 430, 442]
+[:mouse_move, 755, 567, 2, 431, 443]
+[:mouse_move, 756, 567, 2, 432, 444]
+[:mouse_move, 756, 568, 2, 433, 446]
+[:mouse_move, 756, 573, 2, 434, 446]
+[:mouse_move, 756, 582, 2, 435, 447]
+[:mouse_move, 756, 592, 2, 436, 448]
+[:mouse_move, 758, 599, 2, 437, 448]
+[:mouse_move, 758, 604, 2, 438, 449]
+[:mouse_move, 759, 607, 2, 439, 449]
+[:mouse_move, 760, 610, 2, 440, 450]
+[:mouse_move, 760, 611, 2, 441, 451]
+[:mouse_move, 760, 612, 2, 442, 451]
+[:mouse_move, 760, 613, 2, 443, 452]
+[:mouse_move, 760, 614, 2, 444, 452]
+[:mouse_move, 760, 615, 2, 445, 454]
+[:mouse_move, 759, 616, 2, 446, 455]
+[:mouse_move, 759, 617, 2, 447, 455]
+[:mouse_move, 759, 618, 2, 448, 456]
+[:mouse_move, 759, 619, 2, 449, 457]
+[:mouse_move, 759, 621, 2, 450, 459]
+[:mouse_move, 758, 621, 2, 451, 460]
+[:mouse_move, 758, 622, 2, 452, 463]
+[:mouse_move, 758, 623, 2, 453, 464]
+[:mouse_move, 759, 623, 2, 454, 467]
+[:mouse_move, 759, 624, 2, 455, 468]
+[:mouse_move, 767, 624, 2, 456, 468]
+[:mouse_move, 776, 625, 2, 457, 469]
+[:mouse_move, 787, 627, 2, 458, 469]
+[:mouse_move, 795, 629, 2, 459, 470]
+[:mouse_move, 797, 630, 2, 460, 470]
+[:mouse_move, 798, 630, 2, 461, 471]
+[:mouse_button_pressed, 1, 0, 1, 462, 476]
+[:mouse_move, 799, 630, 2, 463, 476]
+[:mouse_button_up, 1, 0, 1, 464, 478]
+[:mouse_move, 799, 625, 2, 465, 478]
+[:mouse_move, 800, 615, 2, 466, 479]
+[:mouse_move, 801, 602, 2, 467, 480]
+[:mouse_move, 801, 590, 2, 468, 481]
+[:mouse_move, 801, 580, 2, 469, 481]
+[:mouse_move, 801, 571, 2, 470, 482]
+[:mouse_move, 801, 570, 2, 471, 482]
+[:mouse_move, 801, 569, 2, 472, 483]
+[:mouse_move, 801, 568, 2, 473, 485]
+[:mouse_move, 802, 567, 2, 474, 487]
+[:mouse_move, 803, 567, 2, 475, 488]
+[:mouse_button_pressed, 1, 0, 1, 476, 491]
+[:mouse_button_up, 1, 0, 1, 477, 493]
+[:mouse_move, 804, 567, 2, 478, 494]
+[:mouse_move, 811, 567, 2, 479, 495]
+[:mouse_move, 822, 567, 2, 480, 495]
+[:mouse_move, 837, 567, 2, 481, 496]
+[:mouse_move, 850, 567, 2, 482, 496]
+[:mouse_move, 861, 567, 2, 483, 497]
+[:mouse_move, 873, 568, 2, 484, 497]
+[:mouse_move, 875, 568, 2, 485, 498]
+[:mouse_move, 876, 568, 2, 486, 500]
+[:mouse_move, 877, 568, 2, 487, 501]
+[:mouse_move, 877, 569, 2, 488, 501]
+[:mouse_move, 868, 570, 2, 489, 516]
+[:mouse_move, 850, 574, 2, 490, 516]
+[:mouse_move, 835, 577, 2, 491, 517]
+[:mouse_move, 818, 577, 2, 492, 517]
+[:mouse_move, 810, 577, 2, 493, 518]
+[:mouse_move, 810, 578, 2, 494, 519]
+[:mouse_move, 813, 578, 2, 495, 520]
+[:mouse_move, 816, 578, 2, 496, 521]
+[:mouse_move, 819, 578, 2, 497, 521]
+[:mouse_move, 820, 578, 2, 498, 522]
+[:mouse_button_pressed, 1, 0, 1, 499, 526]
+[:mouse_button_up, 1, 0, 1, 500, 527]
+[:mouse_move, 822, 579, 2, 501, 529]
+[:mouse_move, 823, 581, 2, 502, 530]
+[:mouse_move, 824, 581, 2, 503, 531]
+[:mouse_move, 825, 581, 2, 504, 531]
+[:mouse_move, 829, 581, 2, 505, 531]
+[:mouse_move, 836, 581, 2, 506, 532]
+[:mouse_move, 843, 580, 2, 507, 533]
+[:mouse_move, 852, 577, 2, 508, 534]
+[:mouse_move, 862, 574, 2, 509, 534]
+[:mouse_move, 864, 574, 2, 510, 535]
+[:mouse_move, 865, 574, 2, 511, 541]
+[:mouse_button_pressed, 1, 0, 1, 512, 542]
+[:mouse_button_up, 1, 0, 1, 513, 544]
+[:mouse_move, 866, 581, 2, 514, 545]
+[:mouse_move, 868, 587, 2, 515, 545]
+[:mouse_move, 870, 592, 2, 516, 546]
+[:mouse_move, 871, 595, 2, 517, 546]
+[:mouse_move, 873, 598, 2, 518, 547]
+[:mouse_move, 874, 602, 2, 519, 548]
+[:mouse_move, 875, 608, 2, 520, 548]
+[:mouse_move, 875, 610, 2, 521, 549]
+[:mouse_move, 875, 613, 2, 522, 549]
+[:mouse_move, 875, 616, 2, 523, 550]
+[:mouse_move, 875, 617, 2, 524, 551]
+[:mouse_move, 875, 618, 2, 525, 552]
+[:mouse_move, 874, 620, 2, 526, 553]
+[:mouse_move, 872, 625, 2, 527, 553]
+[:mouse_move, 871, 627, 2, 528, 554]
+[:mouse_move, 871, 628, 2, 529, 554]
+[:mouse_move, 871, 629, 2, 530, 555]
+[:mouse_move, 870, 630, 2, 531, 556]
+[:mouse_button_pressed, 1, 0, 1, 532, 558]
+[:mouse_move, 871, 630, 2, 533, 558]
+[:mouse_button_up, 1, 0, 1, 534, 560]
+[:mouse_move, 869, 630, 2, 535, 564]
+[:mouse_move, 864, 631, 2, 536, 565]
+[:mouse_move, 857, 632, 2, 537, 566]
+[:mouse_move, 845, 633, 2, 538, 567]
+[:mouse_move, 830, 635, 2, 539, 567]
+[:mouse_move, 815, 636, 2, 540, 568]
+[:mouse_move, 800, 636, 2, 541, 568]
+[:mouse_move, 782, 636, 2, 542, 569]
+[:mouse_move, 773, 636, 2, 543, 570]
+[:mouse_move, 764, 636, 2, 544, 570]
+[:mouse_move, 757, 636, 2, 545, 571]
+[:mouse_move, 748, 636, 2, 546, 571]
+[:mouse_move, 741, 634, 2, 547, 572]
+[:mouse_move, 734, 634, 2, 548, 573]
+[:mouse_move, 728, 634, 2, 549, 574]
+[:mouse_move, 720, 634, 2, 550, 574]
+[:mouse_move, 713, 633, 2, 551, 575]
+[:mouse_move, 723, 632, 2, 552, 579]
+[:mouse_move, 734, 629, 2, 553, 580]
+[:mouse_move, 745, 626, 2, 554, 581]
+[:mouse_move, 761, 623, 2, 555, 581]
+[:mouse_move, 784, 617, 2, 556, 582]
+[:mouse_move, 811, 610, 2, 557, 582]
+[:mouse_move, 834, 601, 2, 558, 583]
+[:mouse_move, 850, 594, 2, 559, 584]
+[:mouse_move, 857, 590, 2, 560, 584]
+[:mouse_move, 858, 589, 2, 561, 585]
+[:mouse_move, 858, 588, 2, 562, 585]
+[:mouse_move, 858, 587, 2, 563, 586]
+[:mouse_move, 858, 586, 2, 564, 587]
+[:mouse_move, 858, 585, 2, 565, 588]
+[:mouse_move, 858, 584, 2, 566, 593]
+[:mouse_button_pressed, 1, 0, 1, 567, 595]
+[:mouse_button_up, 1, 0, 1, 568, 597]
+[:mouse_move, 851, 587, 2, 569, 599]
+[:mouse_move, 840, 590, 2, 570, 599]
+[:mouse_move, 825, 594, 2, 571, 600]
+[:mouse_move, 803, 600, 2, 572, 600]
+[:mouse_move, 777, 605, 2, 573, 601]
+[:mouse_move, 751, 607, 2, 574, 602]
+[:mouse_move, 729, 611, 2, 575, 602]
+[:mouse_move, 713, 614, 2, 576, 603]
+[:mouse_move, 701, 615, 2, 577, 603]
+[:mouse_move, 695, 615, 2, 578, 604]
+[:mouse_move, 694, 616, 2, 579, 605]
+[:mouse_move, 692, 615, 2, 580, 605]
+[:mouse_move, 690, 614, 2, 581, 606]
+[:mouse_move, 689, 614, 2, 582, 607]
+[:mouse_move, 688, 613, 2, 583, 607]
+[:mouse_move, 688, 610, 2, 584, 608]
+[:mouse_move, 687, 605, 2, 585, 608]
+[:mouse_move, 686, 598, 2, 586, 609]
+[:mouse_move, 686, 589, 2, 587, 610]
+[:mouse_move, 686, 582, 2, 588, 610]
+[:mouse_move, 687, 576, 2, 589, 611]
+[:mouse_move, 688, 576, 2, 590, 611]
+[:mouse_move, 688, 575, 2, 591, 612]
+[:mouse_move, 689, 574, 2, 592, 613]
+[:mouse_move, 689, 573, 2, 593, 613]
+[:mouse_move, 690, 573, 2, 594, 614]
+[:mouse_button_pressed, 1, 0, 1, 595, 615]
+[:mouse_move, 690, 572, 2, 596, 616]
+[:mouse_button_up, 1, 0, 1, 597, 617]
+[:mouse_move, 690, 573, 2, 598, 617]
+[:mouse_move, 690, 574, 2, 599, 619]
+[:mouse_move, 690, 575, 2, 600, 620]
+[:mouse_move, 690, 576, 2, 601, 621]
+[:mouse_move, 690, 578, 2, 602, 621]
+[:mouse_move, 690, 579, 2, 603, 622]
+[:mouse_move, 690, 583, 2, 604, 622]
+[:mouse_move, 691, 594, 2, 605, 622]
+[:mouse_move, 693, 605, 2, 606, 623]
+[:mouse_move, 696, 614, 2, 607, 624]
+[:mouse_move, 698, 619, 2, 608, 625]
+[:mouse_move, 699, 621, 2, 609, 625]
+[:mouse_move, 700, 622, 2, 610, 626]
+[:mouse_move, 701, 622, 2, 611, 634]
+[:mouse_move, 702, 622, 2, 612, 649]
+[:mouse_move, 702, 621, 2, 613, 656]
+[:mouse_move, 705, 620, 2, 614, 656]
+[:mouse_move, 718, 614, 2, 615, 657]
+[:mouse_move, 750, 600, 2, 616, 657]
+[:mouse_move, 811, 576, 2, 617, 658]
+[:mouse_move, 895, 538, 2, 618, 659]
+[:mouse_move, 984, 489, 2, 619, 659]
+[:mouse_move, 1076, 432, 2, 620, 660]
+[:mouse_move, 1151, 376, 2, 621, 661]
+[:mouse_move, 1205, 336, 2, 622, 661]
+[:mouse_move, 1232, 312, 2, 623, 662]
+[:mouse_move, 1244, 292, 2, 624, 662]
+[:mouse_move, 1244, 286, 2, 625, 663]
+[:mouse_move, 1243, 284, 2, 626, 663]
+[:mouse_move, 1244, 284, 2, 627, 667]
+[:key_down_raw, 96, 0, 2, 628, 675]
+[:mouse_move, 1243, 284, 2, 629, 676]
+[:mouse_move, 1243, 283, 2, 630, 676]
+[:mouse_move, 1243, 282, 2, 631, 676]
+[:mouse_move, 1243, 281, 2, 632, 677]
+[:key_up_raw, 96, 0, 2, 633, 677]
+[:mouse_move, 1243, 280, 2, 634, 677]
+[:mouse_move, 1242, 279, 2, 635, 678]
+[:mouse_move, 1242, 277, 2, 636, 678]
+[:mouse_move, 1242, 274, 2, 637, 679]
+[:mouse_move, 1241, 271, 2, 638, 679]
+[:mouse_move, 1239, 268, 2, 639, 680]
+[:mouse_move, 1237, 264, 2, 640, 680]
+[:mouse_move, 1233, 261, 2, 641, 681]
+[:mouse_move, 1231, 259, 2, 642, 682]
+[:mouse_move, 1231, 258, 2, 643, 682]
+[:mouse_move, 1230, 256, 2, 644, 683]
+[:mouse_move, 1229, 255, 2, 645, 683]
+[:mouse_move, 1227, 252, 2, 646, 684]
+[:mouse_move, 1222, 247, 2, 647, 685]
+[:mouse_move, 1219, 244, 2, 648, 685]
+[:mouse_move, 1217, 242, 2, 649, 685]
+[:mouse_move, 1216, 241, 2, 650, 686]
+[:mouse_move, 1214, 240, 2, 651, 686]
+[:mouse_move, 1206, 237, 2, 652, 687]
+[:mouse_move, 1194, 232, 2, 653, 688]
+[:mouse_move, 1176, 228, 2, 654, 688]
+[:mouse_move, 1161, 224, 2, 655, 688]
+[:mouse_move, 1157, 224, 2, 656, 689]
+[:mouse_move, 1154, 222, 2, 657, 689]
+[:mouse_move, 1148, 217, 2, 658, 690]
+[:mouse_move, 1139, 205, 2, 659, 691]
+[:mouse_move, 1127, 186, 2, 660, 691]
+[:mouse_move, 1118, 165, 2, 661, 691]
+[:mouse_move, 1109, 140, 2, 662, 692]
+[:mouse_move, 1105, 120, 2, 663, 692]
+[:mouse_move, 1107, 107, 2, 664, 693]
+[:mouse_move, 1108, 105, 2, 665, 693]
+[:mouse_move, 1108, 104, 2, 666, 694]
+[:mouse_move, 1100, 103, 2, 667, 697]
+[:mouse_move, 1085, 101, 2, 668, 697]
+[:mouse_move, 1067, 99, 2, 669, 698]
+[:mouse_move, 1051, 96, 2, 670, 698]
+[:mouse_move, 1026, 94, 2, 671, 698]
+[:mouse_move, 988, 90, 2, 672, 699]
+[:mouse_move, 919, 86, 2, 673, 700]
+[:mouse_move, 868, 83, 2, 674, 700]
+[:mouse_move, 822, 83, 2, 675, 701]
+[:mouse_move, 796, 85, 2, 676, 701]
+[:mouse_move, 787, 87, 2, 677, 701]
+[:mouse_move, 786, 88, 2, 678, 702]
+[:mouse_move, 787, 88, 2, 679, 710]
+[:mouse_move, 789, 88, 2, 680, 718]
+[:mouse_move, 790, 89, 2, 681, 720]
+[:key_down_raw, 13, 0, 2, 682, 730]
diff --git a/samples/13_path_finding_algorithms/06_heuristic/app/main.rb b/samples/13_path_finding_algorithms/06_heuristic/app/main.rb
index af466a5..ad4c5ce 100644
--- a/samples/13_path_finding_algorithms/06_heuristic/app/main.rb
+++ b/samples/13_path_finding_algorithms/06_heuristic/app/main.rb
@@ -10,13 +10,13 @@ class Heuristic_With_Walls
def tick
defaults
- render
- input
+ render
+ input
# If animation is playing, and max steps have not been reached
# Move the search a step forward
if state.play && state.current_step < state.max_steps
# Variable that tells the program what step to recalculate up to
- state.current_step += 1
+ state.current_step += 1
move_searches_one_step_forward
end
end
@@ -38,7 +38,7 @@ class Heuristic_With_Walls
# We store this value, because we want to remember the value even when
# the user's cursor is no longer over what they're interacting with, but
# they are still clicking down on the mouse.
- state.user_input ||= :none
+ state.user_input ||= :none
# These variables allow the breadth first search to take place
# Came_from is a hash with a key of a cell and a value of the cell that was expanded from to find the key.
@@ -63,7 +63,7 @@ class Heuristic_With_Walls
# Unless the current step has a value
unless state.current_step
# Set the current step to 10
- state.current_step = 10
+ state.current_step = 10
# And calculate the searches up to step 10
recalculate_searches
end
@@ -73,7 +73,7 @@ class Heuristic_With_Walls
# This step is roughly the grid's width * height
# When anim_steps equals max_steps no more calculations will occur
# and the slider will be at the end
- state.max_steps = grid.width * grid.height
+ state.max_steps = grid.width * grid.height
# Whether the animation should play or not
# If true, every tick moves anim_steps forward one
@@ -166,7 +166,7 @@ class Heuristic_With_Walls
# If the mouse was clicked this tick
if inputs.mouse.down
# Determine what the user is editing and appropriately edit the state.user_input variable
- determine_input
+ determine_input
end
# Process user input based on user_input variable and current mouse position
@@ -179,35 +179,35 @@ class Heuristic_With_Walls
if mouse_over_slider?
state.user_input = :slider
# If the mouse is over the star in the first grid
- elsif bfs_mouse_over_star?
+ elsif bfs_mouse_over_star?
# The user is editing the star from the first grid
- state.user_input = :bfs_star
+ state.user_input = :bfs_star
# If the mouse is over the star in the second grid
- elsif heuristic_mouse_over_star?
+ elsif heuristic_mouse_over_star?
# The user is editing the star from the second grid
- state.user_input = :heuristic_star
+ state.user_input = :heuristic_star
# If the mouse is over the target in the first grid
- elsif bfs_mouse_over_target?
+ elsif bfs_mouse_over_target?
# The user is editing the target from the first grid
- state.user_input = :bfs_target
+ state.user_input = :bfs_target
# If the mouse is over the target in the second grid
- elsif heuristic_mouse_over_target?
+ elsif heuristic_mouse_over_target?
# The user is editing the target from the second grid
- state.user_input = :heuristic_target
+ state.user_input = :heuristic_target
# If the mouse is over a wall in the first grid
- elsif bfs_mouse_over_wall?
+ elsif bfs_mouse_over_wall?
# The user is removing a wall from the first grid
- state.user_input = :bfs_remove_wall
+ state.user_input = :bfs_remove_wall
# If the mouse is over a wall in the second grid
- elsif heuristic_mouse_over_wall?
+ elsif heuristic_mouse_over_wall?
# The user is removing a wall from the second grid
state.user_input = :heuristic_remove_wall
# If the mouse is over the first grid
- elsif bfs_mouse_over_grid?
+ elsif bfs_mouse_over_grid?
# The user is adding a wall from the first grid
state.user_input = :bfs_add_wall
# If the mouse is over the second grid
- elsif heuristic_mouse_over_grid?
+ elsif heuristic_mouse_over_grid?
# The user is adding a wall from the second grid
state.user_input = :heuristic_add_wall
end
@@ -217,22 +217,22 @@ class Heuristic_With_Walls
def process_input
if state.user_input == :slider
process_input_slider
- elsif state.user_input == :bfs_star
- process_input_bfs_star
+ elsif state.user_input == :bfs_star
+ process_input_bfs_star
elsif state.user_input == :heuristic_star
- process_input_heuristic_star
- elsif state.user_input == :bfs_target
- process_input_bfs_target
- elsif state.user_input == :heuristic_target
- process_input_heuristic_target
- elsif state.user_input == :bfs_remove_wall
- process_input_bfs_remove_wall
+ process_input_heuristic_star
+ elsif state.user_input == :bfs_target
+ process_input_bfs_target
+ elsif state.user_input == :heuristic_target
+ process_input_heuristic_target
+ elsif state.user_input == :bfs_remove_wall
+ process_input_bfs_remove_wall
elsif state.user_input == :heuristic_remove_wall
- process_input_heuristic_remove_wall
- elsif state.user_input == :bfs_add_wall
- process_input_bfs_add_wall
- elsif state.user_input == :heuristic_add_wall
- process_input_heuristic_add_wall
+ process_input_heuristic_remove_wall
+ elsif state.user_input == :bfs_add_wall
+ process_input_bfs_add_wall
+ elsif state.user_input == :heuristic_add_wall
+ process_input_heuristic_add_wall
end
end
@@ -309,7 +309,7 @@ class Heuristic_With_Walls
# The horizontal grid lines
for y in 0..grid.height
- outputs.lines << bfs_horizontal_line(y)
+ outputs.lines << bfs_horizontal_line(y)
end
end
@@ -324,10 +324,10 @@ class Heuristic_With_Walls
# The horizontal grid lines
for y in 0..grid.height
- outputs.lines << heuristic_horizontal_line(y)
+ outputs.lines << heuristic_horizontal_line(y)
end
end
-
+
# Returns a vertical line for a column of the first grid
def bfs_vertical_line column
bfs_scale_up([column, 0, column, grid.height])
@@ -362,7 +362,7 @@ class Heuristic_With_Walls
def render_bfs_target
outputs.sprites << [bfs_scale_up(grid.target), 'target.png']
end
-
+
# Renders the target on the second grid
def render_heuristic_target
outputs.sprites << [heuristic_scale_up(grid.target), 'target.png']
@@ -370,14 +370,14 @@ class Heuristic_With_Walls
# Renders the walls on the first grid
def render_bfs_walls
- grid.walls.each_key do | wall |
+ grid.walls.each_key do | wall |
outputs.solids << [bfs_scale_up(wall), wall_color]
end
end
# Renders the walls on the second grid
def render_heuristic_walls
- grid.walls.each_key do | wall |
+ grid.walls.each_key do | wall |
outputs.solids << [heuristic_scale_up(wall), wall_color]
end
end
@@ -398,14 +398,14 @@ class Heuristic_With_Walls
# Renders the frontier cells on the first grid
def render_bfs_frontier
- bfs.frontier.each do | frontier_cell |
+ bfs.frontier.each do | frontier_cell |
outputs.solids << [bfs_scale_up(frontier_cell), frontier_color, 200]
end
end
# Renders the frontier cells on the second grid
def render_heuristic_frontier
- heuristic.frontier.each do | frontier_cell |
+ heuristic.frontier.each do | frontier_cell |
outputs.solids << [heuristic_scale_up(frontier_cell), frontier_color, 200]
end
end
@@ -489,14 +489,14 @@ class Heuristic_With_Walls
# Checks and handles input for the buttons
# Called when the mouse is lifted
def input_buttons
- input_left_button
- input_center_button
- input_right_button
+ input_left_button
+ input_center_button
+ input_right_button
end
# Checks if the previous step button is clicked
# If it is, it pauses the animation and moves the search one step backward
- def input_left_button
+ def input_left_button
if left_button_clicked?
state.play = false
state.current_step -= 1
@@ -508,7 +508,7 @@ class Heuristic_With_Walls
# Inverses whether the animation is playing or not when clicked
def input_center_button
if center_button_clicked? || inputs.keyboard.key_down.space
- state.play = !state.play
+ state.play = !state.play
end
end
@@ -516,8 +516,8 @@ class Heuristic_With_Walls
# If it is, it pauses the animation and moves the search one step forward
def input_right_button
if right_button_clicked?
- state.play = false
- state.current_step += 1
+ state.play = false
+ state.current_step += 1
move_searches_one_step_forward
end
end
@@ -598,12 +598,12 @@ class Heuristic_With_Walls
# on the slider
# Changes the step of the search to be animated
def process_input_slider
- state.play = false
+ state.play = false
mouse_x = inputs.mouse.point.x
# Bounds the mouse_x to the closest x value on the slider line
- mouse_x = slider.x if mouse_x < slider.x
- mouse_x = slider.x + slider.w if mouse_x > slider.x + slider.w
+ mouse_x = slider.x if mouse_x < slider.x
+ mouse_x = slider.x + slider.w if mouse_x > slider.x + slider.w
# Sets the current search step to the one represented by the mouse x value
# The slider's circle moves due to the render_slider method using anim_steps
@@ -616,12 +616,12 @@ class Heuristic_With_Walls
# Only resets the search if the star changes position
# Called whenever the user is editing the star (puts mouse down on star)
def process_input_bfs_star
- old_star = grid.star.clone
+ old_star = grid.star.clone
unless bfs_cell_closest_to_mouse == grid.target
- grid.star = bfs_cell_closest_to_mouse
+ grid.star = bfs_cell_closest_to_mouse
end
- unless old_star == grid.star
- recalculate_searches
+ unless old_star == grid.star
+ recalculate_searches
end
end
@@ -629,12 +629,12 @@ class Heuristic_With_Walls
# Only resets the search if the star changes position
# Called whenever the user is editing the star (puts mouse down on star)
def process_input_heuristic_star
- old_star = grid.star.clone
+ old_star = grid.star.clone
unless heuristic_cell_closest_to_mouse == grid.target
grid.star = heuristic_cell_closest_to_mouse
end
- unless old_star == grid.star
- recalculate_searches
+ unless old_star == grid.star
+ recalculate_searches
end
end
@@ -642,12 +642,12 @@ class Heuristic_With_Walls
# Only recalculate_searchess the search if the target changes position
# Called whenever the user is editing the target (puts mouse down on target)
def process_input_bfs_target
- old_target = grid.target.clone
+ old_target = grid.target.clone
unless bfs_cell_closest_to_mouse == grid.star
grid.target = bfs_cell_closest_to_mouse
end
- unless old_target == grid.target
- recalculate_searches
+ unless old_target == grid.target
+ recalculate_searches
end
end
@@ -655,12 +655,12 @@ class Heuristic_With_Walls
# Only recalculate_searchess the search if the target changes position
# Called whenever the user is editing the target (puts mouse down on target)
def process_input_heuristic_target
- old_target = grid.target.clone
+ old_target = grid.target.clone
unless heuristic_cell_closest_to_mouse == grid.star
grid.target = heuristic_cell_closest_to_mouse
end
- unless old_target == grid.target
- recalculate_searches
+ unless old_target == grid.target
+ recalculate_searches
end
end
@@ -669,10 +669,10 @@ class Heuristic_With_Walls
# The mouse needs to be inside the grid, because we only want to remove walls
# the cursor is directly over
# Recalculations should only occur when a wall is actually deleted
- if bfs_mouse_over_grid?
+ if bfs_mouse_over_grid?
if grid.walls.has_key?(bfs_cell_closest_to_mouse)
- grid.walls.delete(bfs_cell_closest_to_mouse)
- recalculate_searches
+ grid.walls.delete(bfs_cell_closest_to_mouse)
+ recalculate_searches
end
end
end
@@ -682,29 +682,29 @@ class Heuristic_With_Walls
# The mouse needs to be inside the grid, because we only want to remove walls
# the cursor is directly over
# Recalculations should only occur when a wall is actually deleted
- if heuristic_mouse_over_grid?
+ if heuristic_mouse_over_grid?
if grid.walls.has_key?(heuristic_cell_closest_to_mouse)
- grid.walls.delete(heuristic_cell_closest_to_mouse)
- recalculate_searches
+ grid.walls.delete(heuristic_cell_closest_to_mouse)
+ recalculate_searches
end
end
end
# Adds a wall in the first grid in the cell the mouse is over
def process_input_bfs_add_wall
- if bfs_mouse_over_grid?
+ if bfs_mouse_over_grid?
unless grid.walls.has_key?(bfs_cell_closest_to_mouse)
- grid.walls[bfs_cell_closest_to_mouse] = true
- recalculate_searches
+ grid.walls[bfs_cell_closest_to_mouse] = true
+ recalculate_searches
end
end
end
# Adds a wall in the second grid in the cell the mouse is over
def process_input_heuristic_add_wall
- if heuristic_mouse_over_grid?
+ if heuristic_mouse_over_grid?
unless grid.walls.has_key?(heuristic_cell_closest_to_mouse)
- grid.walls[heuristic_cell_closest_to_mouse] = true
- recalculate_searches
+ grid.walls[heuristic_cell_closest_to_mouse] = true
+ recalculate_searches
end
end
end
@@ -714,13 +714,13 @@ class Heuristic_With_Walls
# Finding the cell closest to the mouse helps with this
def bfs_cell_closest_to_mouse
# Closest cell to the mouse in the first grid
- x = (inputs.mouse.point.x / grid.cell_size).to_i
- y = (inputs.mouse.point.y / grid.cell_size).to_i
+ x = (inputs.mouse.point.x / grid.cell_size).to_i
+ y = (inputs.mouse.point.y / grid.cell_size).to_i
# Bound x and y to the grid
- x = grid.width - 1 if x > grid.width - 1
- y = grid.height - 1 if y > grid.height - 1
+ x = grid.width - 1 if x > grid.width - 1
+ y = grid.height - 1 if y > grid.height - 1
# Return closest cell
- [x, y]
+ [x, y]
end
# When the user grabs the star and puts their cursor to the far right
@@ -728,17 +728,17 @@ class Heuristic_With_Walls
# Finding the cell closest to the mouse in the second grid helps with this
def heuristic_cell_closest_to_mouse
# Closest cell grid to the mouse in the second
- x = (inputs.mouse.point.x / grid.cell_size).to_i
- y = (inputs.mouse.point.y / grid.cell_size).to_i
+ x = (inputs.mouse.point.x / grid.cell_size).to_i
+ y = (inputs.mouse.point.y / grid.cell_size).to_i
# Translate the cell to the first grid
x -= grid.width + 1
# Bound x and y to the first grid
x = 0 if x < 0
y = 0 if y < 0
- x = grid.width - 1 if x > grid.width - 1
- y = grid.height - 1 if y > grid.height - 1
+ x = grid.width - 1 if x > grid.width - 1
+ y = grid.height - 1 if y > grid.height - 1
# Return closest cell
- [x, y]
+ [x, y]
end
def recalculate_searches
@@ -763,22 +763,22 @@ class Heuristic_With_Walls
return if bfs.came_from.has_key?(grid.target)
# Only runs at the beginning of the search as setup.
- if bfs.came_from.empty?
- bfs.frontier << grid.star
- bfs.came_from[grid.star] = nil
+ if bfs.came_from.empty?
+ bfs.frontier << grid.star
+ bfs.came_from[grid.star] = nil
end
# A step in the search
- unless bfs.frontier.empty?
+ unless bfs.frontier.empty?
# Takes the next frontier cell
- new_frontier = bfs.frontier.shift
+ new_frontier = bfs.frontier.shift
# For each of its neighbors
- adjacent_neighbors(new_frontier).each do |neighbor|
+ adjacent_neighbors(new_frontier).each do |neighbor|
# That have not been visited and are not walls
- unless bfs.came_from.has_key?(neighbor) || grid.walls.has_key?(neighbor)
+ unless bfs.came_from.has_key?(neighbor) || grid.walls.has_key?(neighbor)
# Add them to the frontier and mark them as visited
- bfs.frontier << neighbor
- bfs.came_from[neighbor] = new_frontier
+ bfs.frontier << neighbor
+ bfs.came_from[neighbor] = new_frontier
end
end
end
@@ -833,12 +833,12 @@ class Heuristic_With_Walls
# Get the next cell to explore from
new_frontier = heuristic.frontier.shift
# For each of its neighbors
- adjacent_neighbors(new_frontier).each do |neighbor|
+ adjacent_neighbors(new_frontier).each do |neighbor|
# That have not been visited and are not walls
- unless heuristic.came_from.has_key?(neighbor) || grid.walls.has_key?(neighbor)
+ unless heuristic.came_from.has_key?(neighbor) || grid.walls.has_key?(neighbor)
# Add them to the frontier and mark them as visited
- heuristic.frontier << neighbor
- heuristic.came_from[neighbor] = new_frontier
+ heuristic.frontier << neighbor
+ heuristic.came_from[neighbor] = new_frontier
end
end
end
@@ -882,16 +882,16 @@ class Heuristic_With_Walls
# Returns a list of adjacent cells
# Used to determine what the next cells to be added to the frontier are
def adjacent_neighbors(cell)
- neighbors = []
+ neighbors = []
# Gets all the valid neighbors into the array
# From southern neighbor, clockwise
- neighbors << [cell.x , cell.y - 1] unless cell.y == 0
- neighbors << [cell.x - 1, cell.y ] unless cell.x == 0
- neighbors << [cell.x , cell.y + 1] unless cell.y == grid.height - 1
- neighbors << [cell.x + 1, cell.y ] unless cell.x == grid.width - 1
+ neighbors << [cell.x , cell.y - 1] unless cell.y == 0
+ neighbors << [cell.x - 1, cell.y ] unless cell.x == 0
+ neighbors << [cell.x , cell.y + 1] unless cell.y == grid.height - 1
+ neighbors << [cell.x + 1, cell.y ] unless cell.x == grid.width - 1
- neighbors
+ neighbors
end
# Finds the vertical and horizontal distance of a cell from the star
@@ -940,7 +940,7 @@ class Heuristic_With_Walls
def wall_color
[134, 134, 120] # Camo Green
end
-
+
def visited_color
[204, 191, 179] # Dark Brown
end
@@ -948,7 +948,7 @@ class Heuristic_With_Walls
def frontier_color
[103, 136, 204] # Blue
end
-
+
def path_color
[231, 230, 228] # Pastel White
end
@@ -969,7 +969,7 @@ def tick args
end
# Every tick, new args are passed, and the Breadth First Search tick is called
- $heuristic_with_walls ||= Heuristic_With_Walls.new(args)
+ $heuristic_with_walls ||= Heuristic_With_Walls.new
$heuristic_with_walls.args = args
$heuristic_with_walls.tick
end
diff --git a/samples/13_path_finding_algorithms/06_heuristic/replay.txt b/samples/13_path_finding_algorithms/06_heuristic/replay.txt
new file mode 100644
index 0000000..1683449
--- /dev/null
+++ b/samples/13_path_finding_algorithms/06_heuristic/replay.txt
@@ -0,0 +1,719 @@
+replay_version 2.0
+stopped_at 1004
+seed 100
+recorded_at 2021-11-20 11:21:45 -0600
+[:mouse_button_up, 1, 0, 1, 1, 3]
+[:mouse_move, 767, 87, 2, 2, 22]
+[:mouse_move, 742, 87, 2, 3, 22]
+[:mouse_move, 713, 87, 2, 4, 23]
+[:mouse_move, 685, 87, 2, 5, 24]
+[:mouse_move, 656, 87, 2, 6, 25]
+[:mouse_move, 633, 87, 2, 7, 26]
+[:mouse_move, 616, 87, 2, 8, 27]
+[:mouse_move, 603, 85, 2, 9, 28]
+[:mouse_move, 587, 77, 2, 10, 29]
+[:mouse_move, 567, 69, 2, 11, 30]
+[:mouse_move, 543, 60, 2, 12, 31]
+[:mouse_move, 528, 55, 2, 13, 31]
+[:mouse_move, 517, 53, 2, 14, 32]
+[:mouse_move, 513, 51, 2, 15, 33]
+[:mouse_move, 511, 50, 2, 16, 34]
+[:mouse_move, 506, 49, 2, 17, 35]
+[:mouse_move, 501, 48, 2, 18, 36]
+[:mouse_move, 497, 46, 2, 19, 36]
+[:mouse_move, 496, 46, 2, 20, 37]
+[:mouse_move, 495, 46, 2, 21, 38]
+[:mouse_move, 490, 46, 2, 22, 39]
+[:mouse_move, 483, 46, 2, 23, 40]
+[:mouse_move, 470, 46, 2, 24, 41]
+[:mouse_move, 461, 46, 2, 25, 41]
+[:mouse_move, 456, 46, 2, 26, 42]
+[:mouse_move, 457, 46, 2, 27, 55]
+[:mouse_button_pressed, 1, 0, 1, 28, 58]
+[:mouse_move, 458, 46, 2, 29, 59]
+[:mouse_move, 460, 46, 2, 30, 62]
+[:mouse_move, 461, 46, 2, 31, 62]
+[:mouse_move, 463, 46, 2, 32, 63]
+[:mouse_move, 464, 46, 2, 33, 64]
+[:mouse_move, 465, 46, 2, 34, 64]
+[:mouse_move, 466, 46, 2, 35, 65]
+[:mouse_move, 467, 46, 2, 36, 65]
+[:mouse_move, 469, 46, 2, 37, 66]
+[:mouse_move, 470, 46, 2, 38, 66]
+[:mouse_move, 472, 46, 2, 39, 67]
+[:mouse_move, 473, 46, 2, 40, 67]
+[:mouse_move, 474, 46, 2, 41, 68]
+[:mouse_move, 477, 46, 2, 42, 68]
+[:mouse_move, 479, 46, 2, 43, 68]
+[:mouse_move, 480, 46, 2, 44, 69]
+[:mouse_move, 481, 46, 2, 45, 70]
+[:mouse_move, 483, 46, 2, 46, 71]
+[:mouse_move, 484, 46, 2, 47, 71]
+[:mouse_move, 485, 46, 2, 48, 71]
+[:mouse_move, 487, 46, 2, 49, 72]
+[:mouse_move, 489, 46, 2, 50, 72]
+[:mouse_move, 492, 46, 2, 51, 72]
+[:mouse_move, 496, 46, 2, 52, 72]
+[:mouse_move, 502, 47, 2, 53, 73]
+[:mouse_move, 507, 47, 2, 54, 73]
+[:mouse_move, 513, 47, 2, 55, 73]
+[:mouse_move, 519, 47, 2, 56, 73]
+[:mouse_move, 521, 47, 2, 57, 74]
+[:mouse_move, 524, 47, 2, 58, 74]
+[:mouse_move, 527, 47, 2, 59, 74]
+[:mouse_move, 531, 47, 2, 60, 74]
+[:mouse_move, 535, 47, 2, 61, 75]
+[:mouse_move, 539, 47, 2, 62, 75]
+[:mouse_move, 542, 47, 2, 63, 75]
+[:mouse_move, 544, 47, 2, 64, 75]
+[:mouse_move, 546, 47, 2, 65, 76]
+[:mouse_move, 550, 47, 2, 66, 76]
+[:mouse_move, 552, 47, 2, 67, 76]
+[:mouse_move, 553, 47, 2, 68, 76]
+[:mouse_move, 555, 47, 2, 69, 76]
+[:mouse_move, 556, 47, 2, 70, 77]
+[:mouse_move, 557, 47, 2, 71, 77]
+[:mouse_move, 558, 47, 2, 72, 77]
+[:mouse_move, 561, 47, 2, 73, 77]
+[:mouse_move, 563, 47, 2, 74, 78]
+[:mouse_move, 564, 47, 2, 75, 78]
+[:mouse_move, 566, 47, 2, 76, 78]
+[:mouse_move, 570, 47, 2, 77, 78]
+[:mouse_move, 571, 47, 2, 78, 78]
+[:mouse_move, 572, 47, 2, 79, 79]
+[:mouse_move, 573, 47, 2, 80, 79]
+[:mouse_move, 575, 47, 2, 81, 79]
+[:mouse_move, 581, 47, 2, 82, 80]
+[:mouse_move, 582, 47, 2, 83, 80]
+[:mouse_move, 585, 47, 2, 84, 80]
+[:mouse_move, 586, 47, 2, 85, 80]
+[:mouse_move, 588, 47, 2, 86, 80]
+[:mouse_move, 589, 47, 2, 87, 81]
+[:mouse_move, 591, 47, 2, 88, 81]
+[:mouse_move, 593, 47, 2, 89, 81]
+[:mouse_move, 594, 47, 2, 90, 81]
+[:mouse_move, 595, 47, 2, 91, 81]
+[:mouse_move, 596, 47, 2, 92, 82]
+[:mouse_move, 600, 47, 2, 93, 82]
+[:mouse_move, 602, 47, 2, 94, 82]
+[:mouse_move, 607, 47, 2, 95, 82]
+[:mouse_move, 611, 46, 2, 96, 82]
+[:mouse_move, 613, 46, 2, 97, 82]
+[:mouse_move, 614, 46, 2, 98, 83]
+[:mouse_move, 617, 46, 2, 99, 83]
+[:mouse_move, 621, 46, 2, 100, 83]
+[:mouse_move, 623, 46, 2, 101, 83]
+[:mouse_move, 625, 46, 2, 102, 83]
+[:mouse_move, 626, 46, 2, 103, 83]
+[:mouse_move, 627, 46, 2, 104, 84]
+[:mouse_move, 629, 46, 2, 105, 84]
+[:mouse_move, 632, 46, 2, 106, 84]
+[:mouse_move, 634, 46, 2, 107, 84]
+[:mouse_move, 636, 46, 2, 108, 84]
+[:mouse_move, 637, 46, 2, 109, 84]
+[:mouse_move, 639, 45, 2, 110, 85]
+[:mouse_move, 641, 45, 2, 111, 85]
+[:mouse_move, 643, 45, 2, 112, 85]
+[:mouse_move, 646, 44, 2, 113, 85]
+[:mouse_move, 648, 43, 2, 114, 85]
+[:mouse_move, 650, 43, 2, 115, 85]
+[:mouse_move, 652, 43, 2, 116, 85]
+[:mouse_move, 654, 43, 2, 117, 86]
+[:mouse_move, 661, 42, 2, 118, 86]
+[:mouse_move, 667, 42, 2, 119, 86]
+[:mouse_move, 676, 42, 2, 120, 86]
+[:mouse_move, 682, 42, 2, 121, 86]
+[:mouse_move, 691, 41, 2, 122, 86]
+[:mouse_move, 694, 41, 2, 123, 86]
+[:mouse_move, 697, 41, 2, 124, 87]
+[:mouse_move, 700, 41, 2, 125, 87]
+[:mouse_move, 703, 41, 2, 126, 87]
+[:mouse_move, 704, 41, 2, 127, 87]
+[:mouse_move, 706, 41, 2, 128, 87]
+[:mouse_move, 707, 41, 2, 129, 87]
+[:mouse_move, 709, 41, 2, 130, 87]
+[:mouse_move, 710, 41, 2, 131, 87]
+[:mouse_move, 713, 41, 2, 132, 88]
+[:mouse_move, 717, 41, 2, 133, 88]
+[:mouse_move, 721, 41, 2, 134, 88]
+[:mouse_move, 725, 41, 2, 135, 88]
+[:mouse_move, 726, 41, 2, 136, 88]
+[:mouse_move, 728, 41, 2, 137, 88]
+[:mouse_move, 732, 41, 2, 138, 88]
+[:mouse_move, 742, 41, 2, 139, 88]
+[:mouse_move, 754, 43, 2, 140, 89]
+[:mouse_move, 769, 45, 2, 141, 89]
+[:mouse_move, 772, 45, 2, 142, 89]
+[:mouse_move, 776, 45, 2, 143, 89]
+[:mouse_move, 777, 45, 2, 144, 89]
+[:mouse_move, 778, 45, 2, 145, 91]
+[:mouse_move, 778, 44, 2, 146, 91]
+[:mouse_move, 779, 44, 2, 147, 91]
+[:mouse_move, 780, 44, 2, 148, 91]
+[:mouse_move, 781, 44, 2, 149, 91]
+[:mouse_move, 782, 44, 2, 150, 92]
+[:mouse_move, 784, 44, 2, 151, 92]
+[:mouse_move, 785, 44, 2, 152, 92]
+[:mouse_move, 786, 44, 2, 153, 92]
+[:mouse_move, 787, 44, 2, 154, 92]
+[:mouse_move, 788, 44, 2, 155, 92]
+[:mouse_move, 789, 44, 2, 156, 93]
+[:mouse_move, 790, 44, 2, 157, 93]
+[:mouse_move, 790, 43, 2, 158, 93]
+[:mouse_move, 791, 43, 2, 159, 93]
+[:mouse_move, 792, 43, 2, 160, 93]
+[:mouse_move, 793, 43, 2, 161, 93]
+[:mouse_move, 791, 43, 2, 162, 94]
+[:mouse_move, 790, 43, 2, 163, 95]
+[:mouse_move, 785, 43, 2, 164, 95]
+[:mouse_move, 775, 43, 2, 165, 95]
+[:mouse_move, 762, 43, 2, 166, 95]
+[:mouse_move, 745, 43, 2, 167, 95]
+[:mouse_move, 727, 43, 2, 168, 95]
+[:mouse_move, 704, 43, 2, 169, 95]
+[:mouse_move, 680, 43, 2, 170, 95]
+[:mouse_move, 653, 43, 2, 171, 95]
+[:mouse_move, 628, 43, 2, 172, 95]
+[:mouse_move, 606, 43, 2, 173, 96]
+[:mouse_move, 589, 43, 2, 174, 96]
+[:mouse_move, 577, 43, 2, 175, 96]
+[:mouse_move, 568, 43, 2, 176, 96]
+[:mouse_move, 558, 43, 2, 177, 96]
+[:mouse_move, 552, 43, 2, 178, 96]
+[:mouse_move, 544, 43, 2, 179, 96]
+[:mouse_move, 532, 43, 2, 180, 97]
+[:mouse_move, 523, 43, 2, 181, 97]
+[:mouse_move, 517, 43, 2, 182, 97]
+[:mouse_move, 512, 43, 2, 183, 97]
+[:mouse_move, 508, 43, 2, 184, 97]
+[:mouse_move, 506, 43, 2, 185, 98]
+[:mouse_move, 503, 43, 2, 186, 98]
+[:mouse_move, 501, 43, 2, 187, 98]
+[:mouse_move, 500, 43, 2, 188, 98]
+[:mouse_move, 498, 43, 2, 189, 98]
+[:mouse_move, 495, 43, 2, 190, 99]
+[:mouse_move, 492, 43, 2, 191, 99]
+[:mouse_move, 489, 43, 2, 192, 99]
+[:mouse_move, 485, 43, 2, 193, 99]
+[:mouse_move, 480, 43, 2, 194, 100]
+[:mouse_move, 476, 43, 2, 195, 100]
+[:mouse_move, 472, 43, 2, 196, 100]
+[:mouse_move, 471, 43, 2, 197, 101]
+[:mouse_move, 470, 43, 2, 198, 102]
+[:mouse_move, 469, 43, 2, 199, 102]
+[:mouse_move, 468, 43, 2, 200, 103]
+[:mouse_move, 467, 43, 2, 201, 105]
+[:mouse_move, 467, 44, 2, 202, 111]
+[:mouse_move, 468, 43, 2, 203, 114]
+[:mouse_move, 469, 43, 2, 204, 115]
+[:mouse_move, 474, 43, 2, 205, 115]
+[:mouse_move, 479, 43, 2, 206, 116]
+[:mouse_move, 482, 43, 2, 207, 116]
+[:mouse_move, 484, 42, 2, 208, 117]
+[:mouse_move, 486, 42, 2, 209, 118]
+[:mouse_move, 488, 42, 2, 210, 118]
+[:mouse_move, 490, 42, 2, 211, 118]
+[:mouse_move, 492, 42, 2, 212, 118]
+[:mouse_move, 493, 42, 2, 213, 120]
+[:mouse_button_up, 1, 0, 1, 214, 123]
+[:mouse_move, 495, 47, 2, 215, 127]
+[:mouse_move, 498, 56, 2, 216, 128]
+[:mouse_move, 500, 63, 2, 217, 128]
+[:mouse_move, 500, 71, 2, 218, 129]
+[:mouse_move, 500, 73, 2, 219, 129]
+[:mouse_move, 500, 75, 2, 220, 130]
+[:mouse_move, 499, 78, 2, 221, 131]
+[:mouse_move, 497, 80, 2, 222, 131]
+[:mouse_move, 495, 82, 2, 223, 132]
+[:mouse_move, 494, 83, 2, 224, 132]
+[:mouse_move, 493, 83, 2, 225, 133]
+[:mouse_move, 493, 84, 2, 226, 141]
+[:mouse_move, 498, 90, 2, 227, 141]
+[:mouse_move, 506, 95, 2, 228, 142]
+[:mouse_move, 509, 98, 2, 229, 142]
+[:mouse_move, 510, 98, 2, 230, 143]
+[:mouse_move, 509, 98, 2, 231, 147]
+[:mouse_move, 507, 98, 2, 232, 148]
+[:mouse_move, 506, 97, 2, 233, 151]
+[:mouse_button_pressed, 1, 0, 1, 234, 152]
+[:mouse_button_up, 1, 0, 1, 235, 154]
+[:mouse_button_pressed, 1, 0, 1, 236, 170]
+[:mouse_move, 507, 97, 2, 237, 170]
+[:mouse_button_up, 1, 0, 1, 238, 173]
+[:mouse_button_pressed, 1, 0, 1, 239, 174]
+[:mouse_button_up, 1, 0, 1, 240, 178]
+[:mouse_button_pressed, 1, 0, 1, 241, 180]
+[:mouse_button_up, 1, 0, 1, 242, 183]
+[:mouse_button_pressed, 1, 0, 1, 243, 185]
+[:mouse_button_up, 1, 0, 1, 244, 189]
+[:mouse_button_pressed, 1, 0, 1, 245, 190]
+[:mouse_button_up, 1, 0, 1, 246, 195]
+[:mouse_button_pressed, 1, 0, 1, 247, 196]
+[:mouse_button_up, 1, 0, 1, 248, 199]
+[:mouse_button_pressed, 1, 0, 1, 249, 201]
+[:mouse_button_up, 1, 0, 1, 250, 203]
+[:mouse_move, 508, 97, 2, 251, 205]
+[:mouse_button_pressed, 1, 0, 1, 252, 205]
+[:mouse_button_up, 1, 0, 1, 253, 209]
+[:mouse_button_pressed, 1, 0, 1, 254, 210]
+[:mouse_button_up, 1, 0, 1, 255, 214]
+[:mouse_button_pressed, 1, 0, 1, 256, 215]
+[:mouse_button_up, 1, 0, 1, 257, 219]
+[:mouse_button_pressed, 1, 0, 1, 258, 222]
+[:mouse_button_up, 1, 0, 1, 259, 226]
+[:mouse_move, 508, 98, 2, 260, 226]
+[:mouse_button_pressed, 1, 0, 1, 261, 229]
+[:mouse_button_up, 1, 0, 1, 262, 232]
+[:mouse_move, 509, 98, 2, 263, 235]
+[:mouse_move, 509, 97, 2, 264, 237]
+[:mouse_move, 515, 96, 2, 265, 238]
+[:mouse_move, 529, 94, 2, 266, 239]
+[:mouse_move, 573, 93, 2, 267, 240]
+[:mouse_move, 609, 93, 2, 268, 242]
+[:mouse_move, 639, 93, 2, 269, 242]
+[:mouse_move, 663, 93, 2, 270, 243]
+[:mouse_move, 680, 93, 2, 271, 244]
+[:mouse_move, 691, 93, 2, 272, 245]
+[:mouse_move, 695, 93, 2, 273, 246]
+[:mouse_move, 696, 93, 2, 274, 247]
+[:mouse_move, 698, 93, 2, 275, 248]
+[:mouse_move, 701, 94, 2, 276, 249]
+[:mouse_move, 702, 94, 2, 277, 250]
+[:mouse_move, 703, 94, 2, 278, 251]
+[:mouse_move, 705, 94, 2, 279, 256]
+[:mouse_move, 707, 94, 2, 280, 256]
+[:mouse_move, 712, 94, 2, 281, 257]
+[:mouse_move, 718, 94, 2, 282, 258]
+[:mouse_move, 727, 94, 2, 283, 259]
+[:mouse_move, 734, 94, 2, 284, 260]
+[:mouse_move, 736, 94, 2, 285, 261]
+[:mouse_move, 737, 94, 2, 286, 265]
+[:mouse_move, 738, 94, 2, 287, 271]
+[:mouse_button_pressed, 1, 0, 1, 288, 272]
+[:mouse_button_up, 1, 0, 1, 289, 275]
+[:mouse_button_pressed, 1, 0, 1, 290, 280]
+[:mouse_button_up, 1, 0, 1, 291, 284]
+[:mouse_move, 739, 94, 2, 292, 287]
+[:mouse_button_pressed, 1, 0, 1, 293, 288]
+[:mouse_button_up, 1, 0, 1, 294, 292]
+[:mouse_button_pressed, 1, 0, 1, 295, 296]
+[:mouse_button_up, 1, 0, 1, 296, 300]
+[:mouse_button_pressed, 1, 0, 1, 297, 303]
+[:mouse_button_up, 1, 0, 1, 298, 306]
+[:mouse_move, 740, 94, 2, 299, 308]
+[:mouse_button_pressed, 1, 0, 1, 300, 309]
+[:mouse_button_up, 1, 0, 1, 301, 312]
+[:mouse_button_pressed, 1, 0, 1, 302, 317]
+[:mouse_button_up, 1, 0, 1, 303, 319]
+[:mouse_move, 733, 100, 2, 304, 321]
+[:mouse_move, 716, 115, 2, 305, 322]
+[:mouse_move, 694, 133, 2, 306, 322]
+[:mouse_move, 669, 152, 2, 307, 323]
+[:mouse_move, 645, 172, 2, 308, 324]
+[:mouse_move, 618, 207, 2, 309, 325]
+[:mouse_move, 602, 229, 2, 310, 325]
+[:mouse_move, 586, 244, 2, 311, 326]
+[:mouse_move, 571, 255, 2, 312, 326]
+[:mouse_move, 560, 263, 2, 313, 327]
+[:mouse_move, 558, 268, 2, 314, 328]
+[:mouse_move, 557, 274, 2, 315, 329]
+[:mouse_move, 559, 279, 2, 316, 329]
+[:mouse_move, 559, 284, 2, 317, 329]
+[:mouse_move, 553, 295, 2, 318, 330]
+[:mouse_move, 538, 310, 2, 319, 331]
+[:mouse_move, 515, 328, 2, 320, 332]
+[:mouse_move, 476, 357, 2, 321, 332]
+[:mouse_move, 448, 381, 2, 322, 333]
+[:mouse_move, 423, 406, 2, 323, 333]
+[:mouse_move, 404, 428, 2, 324, 334]
+[:mouse_move, 381, 448, 2, 325, 335]
+[:mouse_move, 354, 469, 2, 326, 336]
+[:mouse_move, 325, 492, 2, 327, 336]
+[:mouse_move, 297, 512, 2, 328, 337]
+[:mouse_move, 274, 526, 2, 329, 337]
+[:mouse_move, 252, 535, 2, 330, 338]
+[:mouse_move, 237, 544, 2, 331, 339]
+[:mouse_move, 227, 553, 2, 332, 340]
+[:mouse_move, 226, 555, 2, 333, 340]
+[:mouse_move, 226, 556, 2, 334, 341]
+[:mouse_move, 228, 557, 2, 335, 342]
+[:mouse_move, 239, 558, 2, 336, 343]
+[:mouse_move, 266, 563, 2, 337, 343]
+[:mouse_move, 303, 568, 2, 338, 344]
+[:mouse_move, 333, 575, 2, 339, 344]
+[:mouse_move, 356, 581, 2, 340, 345]
+[:mouse_move, 375, 587, 2, 341, 346]
+[:mouse_move, 390, 591, 2, 342, 347]
+[:mouse_move, 407, 598, 2, 343, 347]
+[:mouse_move, 414, 600, 2, 344, 348]
+[:mouse_move, 415, 600, 2, 345, 348]
+[:mouse_move, 416, 601, 2, 346, 349]
+[:mouse_move, 419, 602, 2, 347, 350]
+[:mouse_move, 420, 602, 2, 348, 350]
+[:mouse_button_pressed, 1, 0, 1, 349, 352]
+[:mouse_button_up, 1, 0, 1, 350, 354]
+[:mouse_move, 421, 602, 2, 351, 354]
+[:mouse_move, 422, 602, 2, 352, 356]
+[:mouse_move, 422, 603, 2, 353, 370]
+[:mouse_move, 422, 602, 2, 354, 373]
+[:mouse_move, 423, 595, 2, 355, 374]
+[:mouse_move, 426, 589, 2, 356, 374]
+[:mouse_move, 429, 583, 2, 357, 375]
+[:mouse_move, 429, 582, 2, 358, 376]
+[:mouse_move, 424, 580, 2, 359, 377]
+[:mouse_move, 416, 580, 2, 360, 378]
+[:mouse_move, 410, 579, 2, 361, 378]
+[:mouse_move, 406, 577, 2, 362, 379]
+[:mouse_move, 401, 575, 2, 363, 380]
+[:mouse_move, 392, 573, 2, 364, 380]
+[:mouse_move, 381, 571, 2, 365, 381]
+[:mouse_move, 369, 571, 2, 366, 382]
+[:mouse_move, 354, 571, 2, 367, 382]
+[:mouse_move, 333, 571, 2, 368, 383]
+[:mouse_move, 306, 571, 2, 369, 383]
+[:mouse_move, 281, 576, 2, 370, 384]
+[:mouse_move, 249, 585, 2, 371, 385]
+[:mouse_move, 230, 586, 2, 372, 385]
+[:mouse_move, 213, 590, 2, 373, 386]
+[:mouse_move, 201, 593, 2, 374, 386]
+[:mouse_move, 192, 597, 2, 375, 387]
+[:mouse_move, 188, 599, 2, 376, 388]
+[:mouse_move, 186, 601, 2, 377, 388]
+[:mouse_move, 185, 601, 2, 378, 391]
+[:mouse_move, 183, 599, 2, 379, 391]
+[:mouse_move, 183, 598, 2, 380, 393]
+[:mouse_move, 184, 596, 2, 381, 393]
+[:mouse_move, 188, 594, 2, 382, 394]
+[:mouse_move, 199, 591, 2, 383, 395]
+[:mouse_move, 221, 586, 2, 384, 395]
+[:mouse_move, 246, 578, 2, 385, 395]
+[:mouse_move, 262, 574, 2, 386, 396]
+[:mouse_move, 266, 573, 2, 387, 397]
+[:mouse_move, 271, 573, 2, 388, 398]
+[:mouse_move, 279, 573, 2, 389, 398]
+[:mouse_move, 285, 573, 2, 390, 399]
+[:mouse_move, 293, 574, 2, 391, 399]
+[:mouse_move, 302, 576, 2, 392, 400]
+[:mouse_move, 316, 580, 2, 393, 401]
+[:mouse_move, 333, 583, 2, 394, 402]
+[:mouse_move, 351, 583, 2, 395, 402]
+[:mouse_move, 363, 583, 2, 396, 403]
+[:mouse_move, 369, 583, 2, 397, 403]
+[:mouse_move, 379, 583, 2, 398, 404]
+[:mouse_move, 385, 583, 2, 399, 404]
+[:mouse_move, 390, 583, 2, 400, 405]
+[:mouse_move, 392, 583, 2, 401, 406]
+[:mouse_move, 394, 583, 2, 402, 406]
+[:mouse_move, 395, 583, 2, 403, 407]
+[:mouse_move, 395, 580, 2, 404, 408]
+[:mouse_move, 395, 578, 2, 405, 408]
+[:mouse_move, 395, 572, 2, 406, 409]
+[:mouse_move, 396, 565, 2, 407, 410]
+[:mouse_move, 402, 560, 2, 408, 410]
+[:mouse_move, 404, 559, 2, 409, 411]
+[:mouse_move, 405, 559, 2, 410, 413]
+[:mouse_move, 406, 559, 2, 411, 414]
+[:mouse_move, 407, 560, 2, 412, 416]
+[:mouse_move, 407, 561, 2, 413, 417]
+[:mouse_move, 408, 561, 2, 414, 418]
+[:mouse_move, 409, 563, 2, 415, 419]
+[:mouse_move, 410, 564, 2, 416, 420]
+[:mouse_move, 411, 565, 2, 417, 421]
+[:mouse_move, 411, 566, 2, 418, 423]
+[:mouse_button_pressed, 1, 0, 1, 419, 424]
+[:mouse_button_up, 1, 0, 1, 420, 425]
+[:mouse_move, 411, 562, 2, 421, 426]
+[:mouse_move, 411, 547, 2, 422, 426]
+[:mouse_move, 411, 532, 2, 423, 427]
+[:mouse_move, 417, 513, 2, 424, 427]
+[:mouse_move, 421, 503, 2, 425, 428]
+[:mouse_move, 424, 496, 2, 426, 429]
+[:mouse_move, 425, 494, 2, 427, 430]
+[:mouse_move, 425, 493, 2, 428, 430]
+[:mouse_move, 426, 492, 2, 429, 432]
+[:mouse_move, 426, 493, 2, 430, 436]
+[:mouse_move, 426, 494, 2, 431, 437]
+[:mouse_move, 426, 495, 2, 432, 438]
+[:mouse_move, 426, 496, 2, 433, 438]
+[:mouse_move, 425, 498, 2, 434, 440]
+[:mouse_move, 423, 503, 2, 435, 441]
+[:mouse_move, 422, 506, 2, 436, 441]
+[:mouse_move, 422, 507, 2, 437, 442]
+[:mouse_move, 422, 508, 2, 438, 446]
+[:mouse_move, 422, 514, 2, 439, 447]
+[:mouse_move, 421, 525, 2, 440, 448]
+[:mouse_move, 418, 533, 2, 441, 448]
+[:mouse_move, 416, 536, 2, 442, 449]
+[:mouse_move, 415, 537, 2, 443, 449]
+[:mouse_move, 415, 538, 2, 444, 450]
+[:mouse_button_pressed, 1, 0, 1, 445, 455]
+[:mouse_move, 414, 538, 2, 446, 456]
+[:mouse_button_up, 1, 0, 1, 447, 456]
+[:mouse_move, 412, 535, 2, 448, 456]
+[:mouse_move, 409, 529, 2, 449, 456]
+[:mouse_move, 408, 514, 2, 450, 457]
+[:mouse_move, 408, 502, 2, 451, 458]
+[:mouse_move, 411, 497, 2, 452, 458]
+[:mouse_move, 413, 492, 2, 453, 459]
+[:mouse_move, 415, 491, 2, 454, 460]
+[:mouse_move, 415, 490, 2, 455, 460]
+[:mouse_move, 415, 489, 2, 456, 461]
+[:mouse_move, 416, 489, 2, 457, 461]
+[:mouse_move, 416, 488, 2, 458, 462]
+[:mouse_move, 416, 487, 2, 459, 464]
+[:mouse_button_pressed, 1, 0, 1, 460, 465]
+[:mouse_button_up, 1, 0, 1, 461, 468]
+[:mouse_move, 417, 487, 2, 462, 470]
+[:mouse_move, 417, 486, 2, 463, 471]
+[:mouse_move, 418, 486, 2, 464, 471]
+[:mouse_move, 418, 485, 2, 465, 472]
+[:mouse_move, 418, 483, 2, 466, 473]
+[:mouse_move, 418, 478, 2, 467, 474]
+[:mouse_move, 418, 473, 2, 468, 474]
+[:mouse_move, 419, 471, 2, 469, 475]
+[:mouse_move, 420, 470, 2, 470, 475]
+[:mouse_move, 420, 469, 2, 471, 477]
+[:mouse_move, 420, 468, 2, 472, 477]
+[:mouse_move, 421, 467, 2, 473, 479]
+[:mouse_move, 421, 464, 2, 474, 479]
+[:mouse_move, 421, 462, 2, 475, 480]
+[:mouse_move, 422, 460, 2, 476, 480]
+[:mouse_button_pressed, 1, 0, 1, 477, 482]
+[:mouse_button_up, 1, 0, 1, 478, 484]
+[:mouse_move, 422, 459, 2, 479, 484]
+[:mouse_move, 422, 451, 2, 480, 484]
+[:mouse_move, 424, 443, 2, 481, 485]
+[:mouse_move, 428, 436, 2, 482, 486]
+[:mouse_move, 431, 431, 2, 483, 487]
+[:mouse_move, 433, 428, 2, 484, 487]
+[:mouse_move, 435, 424, 2, 485, 488]
+[:mouse_move, 435, 422, 2, 486, 488]
+[:mouse_move, 435, 420, 2, 487, 489]
+[:mouse_move, 435, 419, 2, 488, 490]
+[:mouse_move, 435, 418, 2, 489, 490]
+[:mouse_button_pressed, 1, 0, 1, 490, 494]
+[:mouse_button_up, 1, 0, 1, 491, 497]
+[:mouse_move, 435, 415, 2, 492, 501]
+[:mouse_move, 435, 408, 2, 493, 502]
+[:mouse_move, 435, 401, 2, 494, 503]
+[:mouse_move, 435, 398, 2, 495, 503]
+[:mouse_move, 435, 396, 2, 496, 504]
+[:mouse_move, 435, 395, 2, 497, 504]
+[:mouse_move, 435, 394, 2, 498, 507]
+[:mouse_move, 434, 393, 2, 499, 507]
+[:mouse_move, 434, 389, 2, 500, 508]
+[:mouse_move, 433, 388, 2, 501, 509]
+[:mouse_move, 433, 385, 2, 502, 509]
+[:mouse_move, 433, 384, 2, 503, 510]
+[:mouse_button_pressed, 1, 0, 1, 504, 514]
+[:mouse_button_up, 1, 0, 1, 505, 516]
+[:mouse_move, 433, 383, 2, 506, 517]
+[:mouse_move, 433, 377, 2, 507, 518]
+[:mouse_move, 433, 372, 2, 508, 518]
+[:mouse_move, 433, 365, 2, 509, 519]
+[:mouse_move, 433, 360, 2, 510, 520]
+[:mouse_move, 433, 353, 2, 511, 520]
+[:mouse_move, 433, 346, 2, 512, 520]
+[:mouse_move, 432, 338, 2, 513, 521]
+[:mouse_move, 431, 331, 2, 514, 522]
+[:mouse_move, 431, 328, 2, 515, 523]
+[:mouse_move, 431, 326, 2, 516, 523]
+[:mouse_move, 431, 325, 2, 517, 524]
+[:mouse_move, 430, 324, 2, 518, 524]
+[:mouse_button_pressed, 1, 0, 1, 519, 528]
+[:mouse_button_up, 1, 0, 1, 520, 531]
+[:mouse_move, 430, 323, 2, 521, 533]
+[:mouse_move, 430, 322, 2, 522, 534]
+[:mouse_move, 430, 321, 2, 523, 534]
+[:mouse_move, 429, 319, 2, 524, 535]
+[:mouse_move, 428, 316, 2, 525, 536]
+[:mouse_move, 428, 315, 2, 526, 537]
+[:mouse_move, 428, 314, 2, 527, 540]
+[:mouse_move, 428, 313, 2, 528, 540]
+[:mouse_move, 427, 309, 2, 529, 540]
+[:mouse_move, 427, 308, 2, 530, 541]
+[:mouse_move, 426, 306, 2, 531, 542]
+[:mouse_move, 426, 304, 2, 532, 543]
+[:mouse_move, 426, 303, 2, 533, 543]
+[:mouse_button_pressed, 1, 0, 1, 534, 544]
+[:mouse_button_up, 1, 0, 1, 535, 546]
+[:mouse_move, 426, 302, 2, 536, 548]
+[:mouse_move, 426, 299, 2, 537, 548]
+[:mouse_move, 426, 294, 2, 538, 549]
+[:mouse_move, 426, 288, 2, 539, 550]
+[:mouse_move, 426, 282, 2, 540, 550]
+[:mouse_move, 426, 276, 2, 541, 550]
+[:mouse_move, 426, 273, 2, 542, 551]
+[:mouse_move, 426, 272, 2, 543, 552]
+[:mouse_move, 426, 271, 2, 544, 553]
+[:mouse_button_pressed, 1, 0, 1, 545, 556]
+[:mouse_button_up, 1, 0, 1, 546, 557]
+[:mouse_move, 426, 269, 2, 547, 558]
+[:mouse_move, 426, 266, 2, 548, 559]
+[:mouse_move, 426, 263, 2, 549, 559]
+[:mouse_move, 426, 258, 2, 550, 560]
+[:mouse_move, 425, 256, 2, 551, 561]
+[:mouse_move, 424, 251, 2, 552, 561]
+[:mouse_move, 424, 246, 2, 553, 562]
+[:mouse_move, 424, 244, 2, 554, 563]
+[:mouse_move, 424, 241, 2, 555, 563]
+[:mouse_move, 424, 238, 2, 556, 563]
+[:mouse_move, 423, 236, 2, 557, 564]
+[:mouse_move, 423, 235, 2, 558, 565]
+[:mouse_button_pressed, 1, 0, 1, 559, 568]
+[:mouse_button_up, 1, 0, 1, 560, 569]
+[:mouse_move, 423, 233, 2, 561, 570]
+[:mouse_move, 423, 228, 2, 562, 570]
+[:mouse_move, 423, 224, 2, 563, 571]
+[:mouse_move, 423, 218, 2, 564, 572]
+[:mouse_move, 423, 214, 2, 565, 572]
+[:mouse_move, 423, 210, 2, 566, 573]
+[:mouse_move, 423, 209, 2, 567, 573]
+[:mouse_move, 423, 208, 2, 568, 574]
+[:mouse_move, 423, 207, 2, 569, 575]
+[:mouse_move, 423, 206, 2, 570, 577]
+[:mouse_button_pressed, 1, 0, 1, 571, 582]
+[:mouse_button_up, 1, 0, 1, 572, 583]
+[:mouse_move, 423, 205, 2, 573, 586]
+[:mouse_move, 423, 204, 2, 574, 587]
+[:mouse_move, 423, 201, 2, 575, 587]
+[:mouse_move, 423, 197, 2, 576, 588]
+[:mouse_move, 422, 195, 2, 577, 589]
+[:mouse_move, 422, 191, 2, 578, 589]
+[:mouse_move, 422, 189, 2, 579, 589]
+[:mouse_move, 422, 188, 2, 580, 590]
+[:mouse_move, 422, 187, 2, 581, 591]
+[:mouse_move, 422, 186, 2, 582, 592]
+[:mouse_move, 422, 188, 2, 583, 606]
+[:mouse_move, 422, 193, 2, 584, 607]
+[:mouse_move, 423, 202, 2, 585, 608]
+[:mouse_move, 425, 216, 2, 586, 609]
+[:mouse_move, 426, 223, 2, 587, 609]
+[:mouse_move, 426, 225, 2, 588, 609]
+[:mouse_button_pressed, 1, 0, 1, 589, 613]
+[:mouse_button_up, 1, 0, 1, 590, 615]
+[:mouse_move, 426, 224, 2, 591, 615]
+[:mouse_move, 424, 220, 2, 592, 615]
+[:mouse_move, 424, 209, 2, 593, 616]
+[:mouse_move, 421, 192, 2, 594, 617]
+[:mouse_move, 419, 182, 2, 595, 617]
+[:mouse_move, 418, 180, 2, 596, 618]
+[:mouse_move, 418, 179, 2, 597, 618]
+[:mouse_button_pressed, 1, 0, 1, 598, 624]
+[:mouse_button_up, 1, 0, 1, 599, 625]
+[:mouse_move, 418, 178, 2, 600, 626]
+[:mouse_move, 418, 174, 2, 601, 627]
+[:mouse_move, 418, 171, 2, 602, 628]
+[:mouse_move, 418, 164, 2, 603, 628]
+[:mouse_move, 417, 161, 2, 604, 629]
+[:mouse_move, 415, 156, 2, 605, 630]
+[:mouse_move, 415, 155, 2, 606, 631]
+[:mouse_move, 415, 154, 2, 607, 633]
+[:mouse_move, 415, 153, 2, 608, 634]
+[:mouse_move, 415, 152, 2, 609, 635]
+[:mouse_move, 416, 151, 2, 610, 635]
+[:mouse_move, 416, 150, 2, 611, 636]
+[:mouse_move, 416, 149, 2, 612, 637]
+[:mouse_move, 417, 147, 2, 613, 638]
+[:mouse_move, 418, 144, 2, 614, 639]
+[:mouse_move, 418, 142, 2, 615, 640]
+[:mouse_move, 419, 141, 2, 616, 640]
+[:mouse_move, 419, 139, 2, 617, 641]
+[:mouse_move, 420, 138, 2, 618, 642]
+[:mouse_move, 420, 137, 2, 619, 642]
+[:mouse_button_pressed, 1, 0, 1, 620, 643]
+[:mouse_button_up, 1, 0, 1, 621, 645]
+[:mouse_move, 420, 138, 2, 622, 649]
+[:mouse_move, 420, 141, 2, 623, 650]
+[:mouse_move, 421, 142, 2, 624, 651]
+[:mouse_move, 421, 147, 2, 625, 652]
+[:mouse_move, 421, 148, 2, 626, 653]
+[:mouse_move, 421, 149, 2, 627, 653]
+[:mouse_move, 421, 148, 2, 628, 674]
+[:mouse_move, 420, 147, 2, 629, 675]
+[:mouse_move, 420, 146, 2, 630, 675]
+[:mouse_move, 420, 142, 2, 631, 677]
+[:mouse_move, 422, 139, 2, 632, 677]
+[:mouse_move, 422, 138, 2, 633, 681]
+[:mouse_move, 421, 138, 2, 634, 686]
+[:mouse_move, 441, 132, 2, 635, 691]
+[:mouse_move, 483, 120, 2, 636, 692]
+[:mouse_move, 539, 103, 2, 637, 693]
+[:mouse_move, 590, 85, 2, 638, 693]
+[:mouse_move, 658, 61, 2, 639, 694]
+[:mouse_move, 677, 52, 2, 640, 694]
+[:mouse_move, 725, 34, 2, 641, 695]
+[:mouse_move, 739, 30, 2, 642, 696]
+[:mouse_move, 775, 26, 2, 643, 697]
+[:mouse_move, 791, 26, 2, 644, 697]
+[:mouse_move, 796, 26, 2, 645, 698]
+[:mouse_move, 801, 25, 2, 646, 699]
+[:mouse_move, 802, 25, 2, 647, 700]
+[:mouse_move, 803, 25, 2, 648, 701]
+[:mouse_move, 804, 25, 2, 649, 702]
+[:mouse_move, 804, 28, 2, 650, 703]
+[:mouse_move, 804, 33, 2, 651, 704]
+[:mouse_move, 793, 48, 2, 652, 705]
+[:mouse_move, 787, 54, 2, 653, 705]
+[:mouse_move, 769, 66, 2, 654, 706]
+[:mouse_move, 766, 69, 2, 655, 707]
+[:mouse_move, 759, 75, 2, 656, 708]
+[:mouse_move, 756, 78, 2, 657, 708]
+[:mouse_move, 754, 82, 2, 658, 709]
+[:mouse_move, 750, 88, 2, 659, 710]
+[:mouse_move, 747, 97, 2, 660, 710]
+[:mouse_move, 747, 98, 2, 661, 711]
+[:mouse_move, 747, 100, 2, 662, 712]
+[:mouse_move, 747, 101, 2, 663, 717]
+[:mouse_button_pressed, 1, 0, 1, 664, 717]
+[:mouse_button_up, 1, 0, 1, 665, 720]
+[:mouse_button_pressed, 1, 0, 1, 666, 723]
+[:mouse_button_up, 1, 0, 1, 667, 727]
+[:mouse_button_pressed, 1, 0, 1, 668, 731]
+[:mouse_move, 747, 100, 2, 669, 731]
+[:mouse_button_up, 1, 0, 1, 670, 734]
+[:mouse_button_pressed, 1, 0, 1, 671, 737]
+[:mouse_button_up, 1, 0, 1, 672, 741]
+[:mouse_button_pressed, 1, 0, 1, 673, 744]
+[:mouse_button_up, 1, 0, 1, 674, 747]
+[:mouse_button_pressed, 1, 0, 1, 675, 751]
+[:mouse_button_up, 1, 0, 1, 676, 753]
+[:mouse_button_pressed, 1, 0, 1, 677, 757]
+[:mouse_move, 748, 100, 2, 678, 757]
+[:mouse_button_up, 1, 0, 1, 679, 760]
+[:mouse_button_pressed, 1, 0, 1, 680, 764]
+[:mouse_button_up, 1, 0, 1, 681, 766]
+[:mouse_button_pressed, 1, 0, 1, 682, 769]
+[:mouse_button_up, 1, 0, 1, 683, 772]
+[:mouse_button_pressed, 1, 0, 1, 684, 775]
+[:mouse_button_up, 1, 0, 1, 685, 778]
+[:mouse_move, 748, 99, 2, 686, 779]
+[:mouse_move, 749, 99, 2, 687, 781]
+[:mouse_button_pressed, 1, 0, 1, 688, 781]
+[:mouse_button_up, 1, 0, 1, 689, 785]
+[:mouse_button_pressed, 1, 0, 1, 690, 788]
+[:mouse_button_up, 1, 0, 1, 691, 790]
+[:mouse_button_pressed, 1, 0, 1, 692, 795]
+[:mouse_button_up, 1, 0, 1, 693, 797]
+[:mouse_button_pressed, 1, 0, 1, 694, 800]
+[:mouse_button_up, 1, 0, 1, 695, 802]
+[:mouse_move, 748, 99, 2, 696, 802]
+[:mouse_move, 738, 99, 2, 697, 803]
+[:mouse_move, 729, 99, 2, 698, 803]
+[:mouse_move, 709, 99, 2, 699, 804]
+[:mouse_move, 689, 96, 2, 700, 805]
+[:mouse_move, 674, 95, 2, 701, 806]
+[:mouse_move, 654, 92, 2, 702, 806]
+[:mouse_move, 629, 90, 2, 703, 806]
+[:mouse_move, 623, 90, 2, 704, 807]
+[:mouse_move, 611, 90, 2, 705, 808]
+[:mouse_move, 610, 90, 2, 706, 808]
+[:mouse_move, 609, 90, 2, 707, 809]
+[:mouse_move, 611, 90, 2, 708, 811]
+[:mouse_button_pressed, 1, 0, 1, 709, 811]
+[:mouse_move, 612, 90, 2, 710, 811]
+[:mouse_button_up, 1, 0, 1, 711, 813]
+[:mouse_move, 613, 90, 2, 712, 813]
+[:key_down_raw, 96, 0, 2, 713, 986]
+[:key_up_raw, 96, 0, 2, 714, 987]
+[:key_down_raw, 13, 0, 2, 715, 1004]
diff --git a/samples/13_path_finding_algorithms/07_heuristic_with_walls/app/main.rb b/samples/13_path_finding_algorithms/07_heuristic_with_walls/app/main.rb
index 5fc0804..2dc3e74 100644
--- a/samples/13_path_finding_algorithms/07_heuristic_with_walls/app/main.rb
+++ b/samples/13_path_finding_algorithms/07_heuristic_with_walls/app/main.rb
@@ -10,13 +10,13 @@ class Heuristic
def tick
defaults
- render
- input
+ render
+ input
# If animation is playing, and max steps have not been reached
# Move the search a step forward
if state.play && state.current_step < state.max_steps
# Variable that tells the program what step to recalculate up to
- state.current_step += 1
+ state.current_step += 1
move_searches_one_step_forward
end
end
@@ -71,7 +71,7 @@ class Heuristic
# We store this value, because we want to remember the value even when
# the user's cursor is no longer over what they're interacting with, but
# they are still clicking down on the mouse.
- state.user_input ||= :none
+ state.user_input ||= :none
# These variables allow the breadth first search to take place
# Came_from is a hash with a key of a cell and a value of the cell that was expanded from to find the key.
@@ -96,7 +96,7 @@ class Heuristic
# Unless the current step has a value
unless state.current_step
# Set the current step to 10
- state.current_step = 10
+ state.current_step = 10
# And calculate the searches up to step 10
recalculate_searches
end
@@ -106,7 +106,7 @@ class Heuristic
# This step is roughly the grid's width * height
# When anim_steps equals max_steps no more calculations will occur
# and the slider will be at the end
- state.max_steps = grid.width * grid.height
+ state.max_steps = grid.width * grid.height
# Whether the animation should play or not
# If true, every tick moves anim_steps forward one
@@ -199,7 +199,7 @@ class Heuristic
# If the mouse was clicked this tick
if inputs.mouse.down
# Determine what the user is editing and appropriately edit the state.user_input variable
- determine_input
+ determine_input
end
# Process user input based on user_input variable and current mouse position
@@ -212,35 +212,35 @@ class Heuristic
if mouse_over_slider?
state.user_input = :slider
# If the mouse is over the star in the first grid
- elsif bfs_mouse_over_star?
+ elsif bfs_mouse_over_star?
# The user is editing the star from the first grid
- state.user_input = :bfs_star
+ state.user_input = :bfs_star
# If the mouse is over the star in the second grid
- elsif heuristic_mouse_over_star?
+ elsif heuristic_mouse_over_star?
# The user is editing the star from the second grid
- state.user_input = :heuristic_star
+ state.user_input = :heuristic_star
# If the mouse is over the target in the first grid
- elsif bfs_mouse_over_target?
+ elsif bfs_mouse_over_target?
# The user is editing the target from the first grid
- state.user_input = :bfs_target
+ state.user_input = :bfs_target
# If the mouse is over the target in the second grid
- elsif heuristic_mouse_over_target?
+ elsif heuristic_mouse_over_target?
# The user is editing the target from the second grid
- state.user_input = :heuristic_target
+ state.user_input = :heuristic_target
# If the mouse is over a wall in the first grid
- elsif bfs_mouse_over_wall?
+ elsif bfs_mouse_over_wall?
# The user is removing a wall from the first grid
- state.user_input = :bfs_remove_wall
+ state.user_input = :bfs_remove_wall
# If the mouse is over a wall in the second grid
- elsif heuristic_mouse_over_wall?
+ elsif heuristic_mouse_over_wall?
# The user is removing a wall from the second grid
state.user_input = :heuristic_remove_wall
# If the mouse is over the first grid
- elsif bfs_mouse_over_grid?
+ elsif bfs_mouse_over_grid?
# The user is adding a wall from the first grid
state.user_input = :bfs_add_wall
# If the mouse is over the second grid
- elsif heuristic_mouse_over_grid?
+ elsif heuristic_mouse_over_grid?
# The user is adding a wall from the second grid
state.user_input = :heuristic_add_wall
end
@@ -250,22 +250,22 @@ class Heuristic
def process_input
if state.user_input == :slider
process_input_slider
- elsif state.user_input == :bfs_star
- process_input_bfs_star
+ elsif state.user_input == :bfs_star
+ process_input_bfs_star
elsif state.user_input == :heuristic_star
- process_input_heuristic_star
- elsif state.user_input == :bfs_target
- process_input_bfs_target
- elsif state.user_input == :heuristic_target
- process_input_heuristic_target
- elsif state.user_input == :bfs_remove_wall
- process_input_bfs_remove_wall
+ process_input_heuristic_star
+ elsif state.user_input == :bfs_target
+ process_input_bfs_target
+ elsif state.user_input == :heuristic_target
+ process_input_heuristic_target
+ elsif state.user_input == :bfs_remove_wall
+ process_input_bfs_remove_wall
elsif state.user_input == :heuristic_remove_wall
- process_input_heuristic_remove_wall
- elsif state.user_input == :bfs_add_wall
- process_input_bfs_add_wall
- elsif state.user_input == :heuristic_add_wall
- process_input_heuristic_add_wall
+ process_input_heuristic_remove_wall
+ elsif state.user_input == :bfs_add_wall
+ process_input_bfs_add_wall
+ elsif state.user_input == :heuristic_add_wall
+ process_input_heuristic_add_wall
end
end
@@ -342,7 +342,7 @@ class Heuristic
# The horizontal grid lines
for y in 0..grid.height
- outputs.lines << bfs_horizontal_line(y)
+ outputs.lines << bfs_horizontal_line(y)
end
end
@@ -357,10 +357,10 @@ class Heuristic
# The horizontal grid lines
for y in 0..grid.height
- outputs.lines << heuristic_horizontal_line(y)
+ outputs.lines << heuristic_horizontal_line(y)
end
end
-
+
# Returns a vertical line for a column of the first grid
def bfs_vertical_line column
bfs_scale_up([column, 0, column, grid.height])
@@ -395,7 +395,7 @@ class Heuristic
def render_bfs_target
outputs.sprites << [bfs_scale_up(grid.target), 'target.png']
end
-
+
# Renders the target on the second grid
def render_heuristic_target
outputs.sprites << [heuristic_scale_up(grid.target), 'target.png']
@@ -403,14 +403,14 @@ class Heuristic
# Renders the walls on the first grid
def render_bfs_walls
- grid.walls.each_key do | wall |
+ grid.walls.each_key do | wall |
outputs.solids << [bfs_scale_up(wall), wall_color]
end
end
# Renders the walls on the second grid
def render_heuristic_walls
- grid.walls.each_key do | wall |
+ grid.walls.each_key do | wall |
outputs.solids << [heuristic_scale_up(wall), wall_color]
end
end
@@ -431,14 +431,14 @@ class Heuristic
# Renders the frontier cells on the first grid
def render_bfs_frontier
- bfs.frontier.each do | frontier_cell |
+ bfs.frontier.each do | frontier_cell |
outputs.solids << [bfs_scale_up(frontier_cell), frontier_color, 200]
end
end
# Renders the frontier cells on the second grid
def render_heuristic_frontier
- heuristic.frontier.each do | frontier_cell |
+ heuristic.frontier.each do | frontier_cell |
outputs.solids << [heuristic_scale_up(frontier_cell), frontier_color, 200]
end
end
@@ -522,14 +522,14 @@ class Heuristic
# Checks and handles input for the buttons
# Called when the mouse is lifted
def input_buttons
- input_left_button
- input_center_button
- input_right_button
+ input_left_button
+ input_center_button
+ input_right_button
end
# Checks if the previous step button is clicked
# If it is, it pauses the animation and moves the search one step backward
- def input_left_button
+ def input_left_button
if left_button_clicked?
state.play = false
state.current_step -= 1
@@ -541,7 +541,7 @@ class Heuristic
# Inverses whether the animation is playing or not when clicked
def input_center_button
if center_button_clicked? || inputs.keyboard.key_down.space
- state.play = !state.play
+ state.play = !state.play
end
end
@@ -549,8 +549,8 @@ class Heuristic
# If it is, it pauses the animation and moves the search one step forward
def input_right_button
if right_button_clicked?
- state.play = false
- state.current_step += 1
+ state.play = false
+ state.current_step += 1
move_searches_one_step_forward
end
end
@@ -631,12 +631,12 @@ class Heuristic
# on the slider
# Changes the step of the search to be animated
def process_input_slider
- state.play = false
+ state.play = false
mouse_x = inputs.mouse.point.x
# Bounds the mouse_x to the closest x value on the slider line
- mouse_x = slider.x if mouse_x < slider.x
- mouse_x = slider.x + slider.w if mouse_x > slider.x + slider.w
+ mouse_x = slider.x if mouse_x < slider.x
+ mouse_x = slider.x + slider.w if mouse_x > slider.x + slider.w
# Sets the current search step to the one represented by the mouse x value
# The slider's circle moves due to the render_slider method using anim_steps
@@ -649,12 +649,12 @@ class Heuristic
# Only resets the search if the star changes position
# Called whenever the user is editing the star (puts mouse down on star)
def process_input_bfs_star
- old_star = grid.star.clone
+ old_star = grid.star.clone
unless bfs_cell_closest_to_mouse == grid.target
- grid.star = bfs_cell_closest_to_mouse
+ grid.star = bfs_cell_closest_to_mouse
end
- unless old_star == grid.star
- recalculate_searches
+ unless old_star == grid.star
+ recalculate_searches
end
end
@@ -662,12 +662,12 @@ class Heuristic
# Only resets the search if the star changes position
# Called whenever the user is editing the star (puts mouse down on star)
def process_input_heuristic_star
- old_star = grid.star.clone
+ old_star = grid.star.clone
unless heuristic_cell_closest_to_mouse == grid.target
grid.star = heuristic_cell_closest_to_mouse
end
- unless old_star == grid.star
- recalculate_searches
+ unless old_star == grid.star
+ recalculate_searches
end
end
@@ -675,12 +675,12 @@ class Heuristic
# Only recalculate_searchess the search if the target changes position
# Called whenever the user is editing the target (puts mouse down on target)
def process_input_bfs_target
- old_target = grid.target.clone
+ old_target = grid.target.clone
unless bfs_cell_closest_to_mouse == grid.star
grid.target = bfs_cell_closest_to_mouse
end
- unless old_target == grid.target
- recalculate_searches
+ unless old_target == grid.target
+ recalculate_searches
end
end
@@ -688,12 +688,12 @@ class Heuristic
# Only recalculate_searchess the search if the target changes position
# Called whenever the user is editing the target (puts mouse down on target)
def process_input_heuristic_target
- old_target = grid.target.clone
+ old_target = grid.target.clone
unless heuristic_cell_closest_to_mouse == grid.star
grid.target = heuristic_cell_closest_to_mouse
end
- unless old_target == grid.target
- recalculate_searches
+ unless old_target == grid.target
+ recalculate_searches
end
end
@@ -702,10 +702,10 @@ class Heuristic
# The mouse needs to be inside the grid, because we only want to remove walls
# the cursor is directly over
# Recalculations should only occur when a wall is actually deleted
- if bfs_mouse_over_grid?
+ if bfs_mouse_over_grid?
if grid.walls.has_key?(bfs_cell_closest_to_mouse)
- grid.walls.delete(bfs_cell_closest_to_mouse)
- recalculate_searches
+ grid.walls.delete(bfs_cell_closest_to_mouse)
+ recalculate_searches
end
end
end
@@ -715,29 +715,29 @@ class Heuristic
# The mouse needs to be inside the grid, because we only want to remove walls
# the cursor is directly over
# Recalculations should only occur when a wall is actually deleted
- if heuristic_mouse_over_grid?
+ if heuristic_mouse_over_grid?
if grid.walls.has_key?(heuristic_cell_closest_to_mouse)
- grid.walls.delete(heuristic_cell_closest_to_mouse)
- recalculate_searches
+ grid.walls.delete(heuristic_cell_closest_to_mouse)
+ recalculate_searches
end
end
end
# Adds a wall in the first grid in the cell the mouse is over
def process_input_bfs_add_wall
- if bfs_mouse_over_grid?
+ if bfs_mouse_over_grid?
unless grid.walls.has_key?(bfs_cell_closest_to_mouse)
- grid.walls[bfs_cell_closest_to_mouse] = true
- recalculate_searches
+ grid.walls[bfs_cell_closest_to_mouse] = true
+ recalculate_searches
end
end
end
# Adds a wall in the second grid in the cell the mouse is over
def process_input_heuristic_add_wall
- if heuristic_mouse_over_grid?
+ if heuristic_mouse_over_grid?
unless grid.walls.has_key?(heuristic_cell_closest_to_mouse)
- grid.walls[heuristic_cell_closest_to_mouse] = true
- recalculate_searches
+ grid.walls[heuristic_cell_closest_to_mouse] = true
+ recalculate_searches
end
end
end
@@ -747,13 +747,13 @@ class Heuristic
# Finding the cell closest to the mouse helps with this
def bfs_cell_closest_to_mouse
# Closest cell to the mouse in the first grid
- x = (inputs.mouse.point.x / grid.cell_size).to_i
- y = (inputs.mouse.point.y / grid.cell_size).to_i
+ x = (inputs.mouse.point.x / grid.cell_size).to_i
+ y = (inputs.mouse.point.y / grid.cell_size).to_i
# Bound x and y to the grid
- x = grid.width - 1 if x > grid.width - 1
- y = grid.height - 1 if y > grid.height - 1
+ x = grid.width - 1 if x > grid.width - 1
+ y = grid.height - 1 if y > grid.height - 1
# Return closest cell
- [x, y]
+ [x, y]
end
# When the user grabs the star and puts their cursor to the far right
@@ -761,17 +761,17 @@ class Heuristic
# Finding the cell closest to the mouse in the second grid helps with this
def heuristic_cell_closest_to_mouse
# Closest cell grid to the mouse in the second
- x = (inputs.mouse.point.x / grid.cell_size).to_i
- y = (inputs.mouse.point.y / grid.cell_size).to_i
+ x = (inputs.mouse.point.x / grid.cell_size).to_i
+ y = (inputs.mouse.point.y / grid.cell_size).to_i
# Translate the cell to the first grid
x -= grid.width + 1
# Bound x and y to the first grid
x = 0 if x < 0
y = 0 if y < 0
- x = grid.width - 1 if x > grid.width - 1
- y = grid.height - 1 if y > grid.height - 1
+ x = grid.width - 1 if x > grid.width - 1
+ y = grid.height - 1 if y > grid.height - 1
# Return closest cell
- [x, y]
+ [x, y]
end
def recalculate_searches
@@ -796,22 +796,22 @@ class Heuristic
return if bfs.came_from.has_key?(grid.target)
# Only runs at the beginning of the search as setup.
- if bfs.came_from.empty?
- bfs.frontier << grid.star
- bfs.came_from[grid.star] = nil
+ if bfs.came_from.empty?
+ bfs.frontier << grid.star
+ bfs.came_from[grid.star] = nil
end
# A step in the search
- unless bfs.frontier.empty?
+ unless bfs.frontier.empty?
# Takes the next frontier cell
- new_frontier = bfs.frontier.shift
+ new_frontier = bfs.frontier.shift
# For each of its neighbors
- adjacent_neighbors(new_frontier).each do |neighbor|
+ adjacent_neighbors(new_frontier).each do |neighbor|
# That have not been visited and are not walls
- unless bfs.came_from.has_key?(neighbor) || grid.walls.has_key?(neighbor)
+ unless bfs.came_from.has_key?(neighbor) || grid.walls.has_key?(neighbor)
# Add them to the frontier and mark them as visited
- bfs.frontier << neighbor
- bfs.came_from[neighbor] = new_frontier
+ bfs.frontier << neighbor
+ bfs.came_from[neighbor] = new_frontier
end
end
end
@@ -866,12 +866,12 @@ class Heuristic
# Get the next cell to explore from
new_frontier = heuristic.frontier.shift
# For each of its neighbors
- adjacent_neighbors(new_frontier).each do |neighbor|
+ adjacent_neighbors(new_frontier).each do |neighbor|
# That have not been visited and are not walls
- unless heuristic.came_from.has_key?(neighbor) || grid.walls.has_key?(neighbor)
+ unless heuristic.came_from.has_key?(neighbor) || grid.walls.has_key?(neighbor)
# Add them to the frontier and mark them as visited
- heuristic.frontier << neighbor
- heuristic.came_from[neighbor] = new_frontier
+ heuristic.frontier << neighbor
+ heuristic.came_from[neighbor] = new_frontier
end
end
end
@@ -915,16 +915,16 @@ class Heuristic
# Returns a list of adjacent cells
# Used to determine what the next cells to be added to the frontier are
def adjacent_neighbors(cell)
- neighbors = []
+ neighbors = []
# Gets all the valid neighbors into the array
# From southern neighbor, clockwise
- neighbors << [cell.x , cell.y - 1] unless cell.y == 0
- neighbors << [cell.x - 1, cell.y ] unless cell.x == 0
- neighbors << [cell.x , cell.y + 1] unless cell.y == grid.height - 1
- neighbors << [cell.x + 1, cell.y ] unless cell.x == grid.width - 1
+ neighbors << [cell.x , cell.y - 1] unless cell.y == 0
+ neighbors << [cell.x - 1, cell.y ] unless cell.x == 0
+ neighbors << [cell.x , cell.y + 1] unless cell.y == grid.height - 1
+ neighbors << [cell.x + 1, cell.y ] unless cell.x == grid.width - 1
- neighbors
+ neighbors
end
# Finds the vertical and horizontal distance of a cell from the star
@@ -973,7 +973,7 @@ class Heuristic
def wall_color
[134, 134, 120] # Camo Green
end
-
+
def visited_color
[204, 191, 179] # Dark Brown
end
@@ -981,7 +981,7 @@ class Heuristic
def frontier_color
[103, 136, 204] # Blue
end
-
+
def path_color
[231, 230, 228] # Pastel White
end
@@ -1002,7 +1002,7 @@ def tick args
end
# Every tick, new args are passed, and the Breadth First Search tick is called
- $heuristic ||= Heuristic.new(args)
+ $heuristic ||= Heuristic.new
$heuristic.args = args
$heuristic.tick
end
diff --git a/samples/13_path_finding_algorithms/07_heuristic_with_walls/replay.txt b/samples/13_path_finding_algorithms/07_heuristic_with_walls/replay.txt
new file mode 100644
index 0000000..4c5a2a6
--- /dev/null
+++ b/samples/13_path_finding_algorithms/07_heuristic_with_walls/replay.txt
@@ -0,0 +1,352 @@
+replay_version 2.0
+stopped_at 637
+seed 100
+recorded_at 2021-11-20 11:23:35 -0600
+[:mouse_button_up, 1, 0, 1, 1, 2]
+[:mouse_move, 777, 81, 2, 2, 5]
+[:mouse_move, 778, 83, 2, 3, 23]
+[:mouse_move, 778, 91, 2, 4, 24]
+[:mouse_move, 778, 97, 2, 5, 25]
+[:mouse_move, 778, 101, 2, 6, 26]
+[:mouse_move, 777, 106, 2, 7, 26]
+[:mouse_move, 774, 112, 2, 8, 27]
+[:mouse_move, 769, 116, 2, 9, 28]
+[:mouse_move, 765, 119, 2, 10, 29]
+[:mouse_move, 763, 120, 2, 11, 29]
+[:mouse_move, 762, 120, 2, 12, 30]
+[:mouse_move, 761, 121, 2, 13, 31]
+[:mouse_move, 761, 122, 2, 14, 32]
+[:mouse_move, 760, 123, 2, 15, 32]
+[:mouse_move, 760, 124, 2, 16, 33]
+[:mouse_move, 759, 125, 2, 17, 34]
+[:mouse_move, 758, 126, 2, 18, 36]
+[:mouse_move, 757, 126, 2, 19, 37]
+[:mouse_move, 754, 127, 2, 20, 38]
+[:mouse_move, 753, 127, 2, 21, 39]
+[:mouse_move, 752, 127, 2, 22, 40]
+[:mouse_move, 753, 127, 2, 23, 56]
+[:mouse_move, 752, 127, 2, 24, 65]
+[:mouse_move, 745, 127, 2, 25, 66]
+[:mouse_move, 737, 127, 2, 26, 67]
+[:mouse_move, 726, 125, 2, 27, 68]
+[:mouse_move, 716, 122, 2, 28, 68]
+[:mouse_move, 709, 120, 2, 29, 69]
+[:mouse_move, 697, 117, 2, 30, 70]
+[:mouse_move, 691, 115, 2, 31, 71]
+[:mouse_move, 689, 114, 2, 32, 72]
+[:mouse_move, 686, 113, 2, 33, 72]
+[:mouse_move, 686, 112, 2, 34, 73]
+[:mouse_move, 685, 112, 2, 35, 74]
+[:mouse_move, 684, 112, 2, 36, 75]
+[:mouse_move, 683, 112, 2, 37, 76]
+[:mouse_move, 682, 111, 2, 38, 77]
+[:mouse_move, 679, 110, 2, 39, 77]
+[:mouse_move, 674, 108, 2, 40, 78]
+[:mouse_move, 665, 104, 2, 41, 79]
+[:mouse_move, 660, 101, 2, 42, 80]
+[:mouse_move, 657, 101, 2, 43, 81]
+[:mouse_move, 657, 100, 2, 44, 89]
+[:mouse_button_pressed, 1, 0, 1, 45, 109]
+[:mouse_button_up, 1, 0, 1, 46, 113]
+[:mouse_button_pressed, 1, 0, 1, 47, 228]
+[:mouse_button_up, 1, 0, 1, 48, 229]
+[:mouse_move, 657, 99, 2, 49, 240]
+[:mouse_move, 656, 96, 2, 50, 240]
+[:mouse_move, 655, 95, 2, 51, 240]
+[:mouse_move, 654, 94, 2, 52, 241]
+[:mouse_move, 654, 87, 2, 53, 242]
+[:mouse_move, 654, 80, 2, 54, 242]
+[:mouse_move, 654, 74, 2, 55, 242]
+[:mouse_move, 654, 69, 2, 56, 242]
+[:mouse_move, 654, 67, 2, 57, 243]
+[:mouse_move, 654, 63, 2, 58, 243]
+[:mouse_move, 654, 62, 2, 59, 244]
+[:mouse_move, 653, 61, 2, 60, 244]
+[:mouse_move, 651, 61, 2, 61, 245]
+[:mouse_move, 648, 60, 2, 62, 246]
+[:mouse_move, 645, 60, 2, 63, 246]
+[:mouse_move, 637, 57, 2, 64, 246]
+[:mouse_move, 633, 55, 2, 65, 246]
+[:mouse_move, 626, 53, 2, 66, 247]
+[:mouse_move, 620, 51, 2, 67, 247]
+[:mouse_move, 593, 47, 2, 68, 247]
+[:mouse_move, 580, 45, 2, 69, 248]
+[:mouse_move, 577, 45, 2, 70, 248]
+[:mouse_move, 576, 45, 2, 71, 248]
+[:mouse_move, 576, 44, 2, 72, 251]
+[:mouse_button_pressed, 1, 0, 1, 73, 251]
+[:mouse_button_up, 1, 0, 1, 74, 253]
+[:mouse_move, 577, 44, 2, 75, 257]
+[:mouse_move, 578, 45, 2, 76, 257]
+[:mouse_move, 584, 45, 2, 77, 258]
+[:mouse_move, 594, 47, 2, 78, 258]
+[:mouse_move, 606, 48, 2, 79, 258]
+[:mouse_move, 619, 50, 2, 80, 259]
+[:mouse_move, 627, 50, 2, 81, 259]
+[:mouse_move, 629, 50, 2, 82, 259]
+[:mouse_move, 630, 50, 2, 83, 259]
+[:mouse_move, 631, 50, 2, 84, 260]
+[:mouse_move, 632, 50, 2, 85, 261]
+[:mouse_button_pressed, 1, 0, 1, 86, 263]
+[:mouse_move, 629, 50, 2, 87, 264]
+[:mouse_move, 624, 50, 2, 88, 264]
+[:mouse_move, 617, 50, 2, 89, 264]
+[:mouse_move, 612, 50, 2, 90, 264]
+[:mouse_move, 609, 50, 2, 91, 264]
+[:mouse_move, 607, 50, 2, 92, 264]
+[:mouse_move, 603, 49, 2, 93, 264]
+[:mouse_move, 600, 49, 2, 94, 264]
+[:mouse_move, 597, 48, 2, 95, 265]
+[:mouse_move, 595, 48, 2, 96, 265]
+[:mouse_move, 594, 48, 2, 97, 265]
+[:mouse_move, 593, 48, 2, 98, 265]
+[:mouse_move, 592, 48, 2, 99, 265]
+[:mouse_move, 590, 48, 2, 100, 265]
+[:mouse_move, 587, 48, 2, 101, 265]
+[:mouse_move, 582, 48, 2, 102, 265]
+[:mouse_move, 575, 48, 2, 103, 265]
+[:mouse_move, 571, 47, 2, 104, 265]
+[:mouse_move, 568, 47, 2, 105, 265]
+[:mouse_move, 567, 47, 2, 106, 266]
+[:mouse_move, 566, 47, 2, 107, 266]
+[:mouse_move, 565, 46, 2, 108, 266]
+[:mouse_move, 564, 46, 2, 109, 266]
+[:mouse_move, 563, 46, 2, 110, 266]
+[:mouse_move, 562, 46, 2, 111, 266]
+[:mouse_move, 561, 46, 2, 112, 266]
+[:mouse_move, 560, 46, 2, 113, 267]
+[:mouse_move, 559, 46, 2, 114, 267]
+[:mouse_move, 558, 46, 2, 115, 267]
+[:mouse_move, 555, 46, 2, 116, 268]
+[:mouse_move, 551, 46, 2, 117, 268]
+[:mouse_move, 549, 46, 2, 118, 268]
+[:mouse_move, 548, 46, 2, 119, 268]
+[:mouse_move, 547, 46, 2, 120, 268]
+[:mouse_move, 546, 46, 2, 121, 269]
+[:mouse_move, 545, 46, 2, 122, 269]
+[:mouse_move, 540, 46, 2, 123, 269]
+[:mouse_move, 534, 46, 2, 124, 269]
+[:mouse_move, 531, 46, 2, 125, 269]
+[:mouse_move, 527, 46, 2, 126, 269]
+[:mouse_move, 525, 46, 2, 127, 269]
+[:mouse_button_up, 1, 0, 1, 128, 276]
+[:mouse_move, 526, 47, 2, 129, 287]
+[:mouse_move, 527, 47, 2, 130, 288]
+[:mouse_move, 528, 48, 2, 131, 290]
+[:mouse_move, 531, 51, 2, 132, 290]
+[:mouse_move, 534, 54, 2, 133, 290]
+[:mouse_move, 539, 61, 2, 134, 291]
+[:mouse_move, 548, 71, 2, 135, 291]
+[:mouse_move, 558, 81, 2, 136, 292]
+[:mouse_move, 570, 94, 2, 137, 292]
+[:mouse_move, 585, 110, 2, 138, 293]
+[:mouse_move, 595, 123, 2, 139, 293]
+[:mouse_move, 607, 136, 2, 140, 293]
+[:mouse_move, 618, 146, 2, 141, 294]
+[:mouse_move, 626, 154, 2, 142, 295]
+[:mouse_move, 632, 161, 2, 143, 295]
+[:mouse_move, 633, 162, 2, 144, 296]
+[:mouse_move, 633, 163, 2, 145, 296]
+[:mouse_move, 634, 164, 2, 146, 296]
+[:mouse_move, 634, 165, 2, 147, 297]
+[:mouse_move, 635, 168, 2, 148, 297]
+[:mouse_move, 635, 172, 2, 149, 298]
+[:mouse_move, 635, 178, 2, 150, 299]
+[:mouse_move, 635, 182, 2, 151, 299]
+[:mouse_move, 635, 183, 2, 152, 299]
+[:mouse_move, 635, 184, 2, 153, 300]
+[:mouse_move, 634, 187, 2, 154, 300]
+[:mouse_move, 632, 191, 2, 155, 301]
+[:mouse_move, 629, 193, 2, 156, 301]
+[:mouse_move, 627, 194, 2, 157, 302]
+[:mouse_move, 625, 194, 2, 158, 302]
+[:mouse_move, 625, 195, 2, 159, 303]
+[:mouse_move, 624, 195, 2, 160, 304]
+[:mouse_move, 619, 195, 2, 161, 305]
+[:mouse_move, 608, 195, 2, 162, 305]
+[:mouse_move, 597, 194, 2, 163, 305]
+[:mouse_move, 584, 188, 2, 164, 306]
+[:mouse_move, 572, 180, 2, 165, 307]
+[:mouse_move, 563, 173, 2, 166, 307]
+[:mouse_move, 556, 166, 2, 167, 308]
+[:mouse_move, 550, 160, 2, 168, 308]
+[:mouse_move, 548, 157, 2, 169, 308]
+[:mouse_move, 547, 154, 2, 170, 309]
+[:mouse_move, 542, 149, 2, 171, 309]
+[:mouse_move, 538, 142, 2, 172, 310]
+[:mouse_move, 533, 134, 2, 173, 310]
+[:mouse_move, 531, 132, 2, 174, 311]
+[:mouse_move, 530, 132, 2, 175, 311]
+[:mouse_move, 530, 131, 2, 176, 312]
+[:mouse_move, 528, 129, 2, 177, 312]
+[:mouse_move, 524, 127, 2, 178, 312]
+[:mouse_move, 523, 126, 2, 179, 313]
+[:mouse_move, 522, 126, 2, 180, 314]
+[:mouse_move, 520, 124, 2, 181, 314]
+[:mouse_move, 512, 118, 2, 182, 315]
+[:mouse_move, 502, 112, 2, 183, 316]
+[:mouse_move, 498, 108, 2, 184, 316]
+[:mouse_move, 495, 107, 2, 185, 317]
+[:mouse_move, 495, 106, 2, 186, 317]
+[:mouse_move, 493, 105, 2, 187, 317]
+[:mouse_move, 493, 104, 2, 188, 318]
+[:mouse_move, 492, 104, 2, 189, 318]
+[:mouse_move, 492, 103, 2, 190, 319]
+[:mouse_button_pressed, 1, 0, 1, 191, 326]
+[:mouse_button_up, 1, 0, 1, 192, 328]
+[:mouse_button_pressed, 1, 0, 1, 193, 339]
+[:mouse_button_up, 1, 0, 1, 194, 342]
+[:mouse_button_pressed, 1, 0, 1, 195, 343]
+[:mouse_button_up, 1, 0, 1, 196, 344]
+[:mouse_button_pressed, 1, 0, 1, 197, 345]
+[:mouse_button_up, 1, 0, 1, 198, 347]
+[:mouse_move, 493, 103, 2, 199, 348]
+[:mouse_move, 497, 103, 2, 200, 348]
+[:mouse_move, 507, 103, 2, 201, 348]
+[:mouse_move, 522, 103, 2, 202, 349]
+[:mouse_move, 542, 103, 2, 203, 349]
+[:mouse_move, 566, 103, 2, 204, 350]
+[:mouse_move, 595, 103, 2, 205, 350]
+[:mouse_move, 627, 103, 2, 206, 351]
+[:mouse_move, 655, 103, 2, 207, 351]
+[:mouse_move, 678, 103, 2, 208, 352]
+[:mouse_move, 693, 103, 2, 209, 352]
+[:mouse_move, 698, 103, 2, 210, 353]
+[:mouse_move, 699, 103, 2, 211, 353]
+[:mouse_move, 702, 103, 2, 212, 354]
+[:mouse_move, 704, 103, 2, 213, 354]
+[:mouse_move, 708, 103, 2, 214, 354]
+[:mouse_move, 709, 103, 2, 215, 355]
+[:mouse_move, 711, 103, 2, 216, 356]
+[:mouse_move, 714, 103, 2, 217, 357]
+[:mouse_move, 715, 103, 2, 218, 357]
+[:mouse_move, 719, 103, 2, 219, 357]
+[:mouse_move, 721, 103, 2, 220, 358]
+[:mouse_move, 723, 103, 2, 221, 359]
+[:mouse_move, 724, 103, 2, 222, 359]
+[:mouse_move, 725, 103, 2, 223, 364]
+[:mouse_move, 729, 101, 2, 224, 365]
+[:mouse_move, 732, 101, 2, 225, 365]
+[:mouse_move, 734, 100, 2, 226, 366]
+[:mouse_move, 735, 99, 2, 227, 367]
+[:mouse_button_pressed, 1, 0, 1, 228, 368]
+[:mouse_button_up, 1, 0, 1, 229, 371]
+[:mouse_button_pressed, 1, 0, 1, 230, 373]
+[:mouse_button_up, 1, 0, 1, 231, 375]
+[:mouse_button_pressed, 1, 0, 1, 232, 378]
+[:mouse_button_up, 1, 0, 1, 233, 380]
+[:mouse_button_pressed, 1, 0, 1, 234, 383]
+[:mouse_button_up, 1, 0, 1, 235, 385]
+[:mouse_button_pressed, 1, 0, 1, 236, 387]
+[:mouse_button_up, 1, 0, 1, 237, 389]
+[:mouse_move, 736, 99, 2, 238, 390]
+[:mouse_button_pressed, 1, 0, 1, 239, 392]
+[:mouse_button_up, 1, 0, 1, 240, 395]
+[:mouse_button_pressed, 1, 0, 1, 241, 432]
+[:mouse_button_up, 1, 0, 1, 242, 434]
+[:mouse_move, 736, 103, 2, 243, 446]
+[:mouse_move, 736, 113, 2, 244, 446]
+[:mouse_move, 734, 125, 2, 245, 447]
+[:mouse_move, 732, 140, 2, 246, 447]
+[:mouse_move, 726, 158, 2, 247, 448]
+[:mouse_move, 718, 174, 2, 248, 448]
+[:mouse_move, 712, 193, 2, 249, 448]
+[:mouse_move, 709, 203, 2, 250, 449]
+[:mouse_move, 709, 208, 2, 251, 449]
+[:mouse_move, 708, 211, 2, 252, 450]
+[:mouse_move, 708, 212, 2, 253, 451]
+[:mouse_move, 708, 213, 2, 254, 451]
+[:mouse_move, 707, 215, 2, 255, 451]
+[:mouse_move, 704, 217, 2, 256, 452]
+[:mouse_move, 700, 221, 2, 257, 452]
+[:mouse_move, 698, 223, 2, 258, 453]
+[:mouse_move, 697, 223, 2, 259, 454]
+[:mouse_move, 699, 223, 2, 260, 455]
+[:mouse_move, 700, 222, 2, 261, 455]
+[:mouse_move, 701, 222, 2, 262, 456]
+[:mouse_move, 702, 222, 2, 263, 456]
+[:mouse_move, 702, 221, 2, 264, 457]
+[:mouse_button_pressed, 1, 0, 1, 265, 458]
+[:mouse_button_up, 1, 0, 1, 266, 459]
+[:mouse_move, 695, 221, 2, 267, 468]
+[:mouse_move, 684, 221, 2, 268, 469]
+[:mouse_move, 673, 221, 2, 269, 469]
+[:mouse_move, 663, 221, 2, 270, 470]
+[:mouse_move, 656, 221, 2, 271, 470]
+[:mouse_move, 655, 221, 2, 272, 471]
+[:mouse_button_pressed, 1, 0, 1, 273, 475]
+[:mouse_button_up, 1, 0, 1, 274, 476]
+[:mouse_move, 657, 218, 2, 275, 479]
+[:mouse_move, 661, 213, 2, 276, 479]
+[:mouse_move, 670, 201, 2, 277, 479]
+[:mouse_move, 679, 190, 2, 278, 479]
+[:mouse_move, 687, 178, 2, 279, 480]
+[:mouse_move, 695, 165, 2, 280, 481]
+[:mouse_move, 703, 151, 2, 281, 481]
+[:mouse_move, 712, 139, 2, 282, 482]
+[:mouse_move, 720, 129, 2, 283, 482]
+[:mouse_move, 727, 121, 2, 284, 482]
+[:mouse_move, 735, 111, 2, 285, 483]
+[:mouse_move, 737, 108, 2, 286, 483]
+[:mouse_move, 739, 105, 2, 287, 484]
+[:mouse_move, 739, 104, 2, 288, 484]
+[:mouse_move, 740, 103, 2, 289, 485]
+[:mouse_move, 740, 102, 2, 290, 485]
+[:mouse_move, 740, 101, 2, 291, 486]
+[:mouse_move, 740, 100, 2, 292, 488]
+[:mouse_button_pressed, 1, 0, 1, 293, 489]
+[:mouse_move, 740, 99, 2, 294, 490]
+[:mouse_button_up, 1, 0, 1, 295, 491]
+[:mouse_button_pressed, 1, 0, 1, 296, 493]
+[:mouse_move, 740, 100, 2, 297, 493]
+[:mouse_button_up, 1, 0, 1, 298, 496]
+[:mouse_button_pressed, 1, 0, 1, 299, 498]
+[:mouse_button_up, 1, 0, 1, 300, 500]
+[:mouse_button_pressed, 1, 0, 1, 301, 502]
+[:mouse_button_up, 1, 0, 1, 302, 505]
+[:mouse_button_pressed, 1, 0, 1, 303, 508]
+[:mouse_button_up, 1, 0, 1, 304, 509]
+[:mouse_button_pressed, 1, 0, 1, 305, 511]
+[:mouse_button_up, 1, 0, 1, 306, 514]
+[:mouse_button_pressed, 1, 0, 1, 307, 516]
+[:mouse_button_up, 1, 0, 1, 308, 518]
+[:mouse_button_pressed, 1, 0, 1, 309, 520]
+[:mouse_button_up, 1, 0, 1, 310, 522]
+[:mouse_button_pressed, 1, 0, 1, 311, 524]
+[:mouse_button_up, 1, 0, 1, 312, 526]
+[:mouse_move, 738, 100, 2, 313, 528]
+[:mouse_move, 732, 101, 2, 314, 528]
+[:mouse_move, 715, 101, 2, 315, 529]
+[:mouse_move, 690, 101, 2, 316, 529]
+[:mouse_move, 677, 101, 2, 317, 530]
+[:mouse_move, 666, 101, 2, 318, 530]
+[:mouse_move, 662, 101, 2, 319, 531]
+[:mouse_move, 661, 101, 2, 320, 531]
+[:mouse_button_pressed, 1, 0, 1, 321, 534]
+[:mouse_button_up, 1, 0, 1, 322, 536]
+[:mouse_move, 660, 100, 2, 323, 550]
+[:mouse_move, 661, 100, 2, 324, 550]
+[:mouse_move, 662, 100, 2, 325, 553]
+[:key_down_raw, 96, 0, 2, 326, 615]
+[:key_up_raw, 96, 0, 2, 327, 616]
+[:mouse_move, 660, 102, 2, 328, 625]
+[:mouse_move, 657, 104, 2, 329, 626]
+[:mouse_move, 655, 107, 2, 330, 626]
+[:mouse_move, 653, 110, 2, 331, 626]
+[:mouse_move, 653, 117, 2, 332, 626]
+[:mouse_move, 655, 122, 2, 333, 626]
+[:mouse_move, 658, 124, 2, 334, 627]
+[:mouse_move, 664, 126, 2, 335, 627]
+[:mouse_move, 671, 128, 2, 336, 627]
+[:mouse_move, 681, 133, 2, 337, 627]
+[:mouse_move, 693, 141, 2, 338, 628]
+[:mouse_move, 710, 154, 2, 339, 628]
+[:mouse_move, 731, 167, 2, 340, 628]
+[:mouse_move, 753, 176, 2, 341, 628]
+[:mouse_move, 772, 181, 2, 342, 629]
+[:mouse_move, 786, 182, 2, 343, 629]
+[:mouse_move, 791, 184, 2, 344, 629]
+[:mouse_move, 790, 185, 2, 345, 629]
+[:mouse_move, 789, 187, 2, 346, 630]
+[:mouse_move, 788, 187, 2, 347, 630]
+[:key_down_raw, 13, 0, 2, 348, 637]
diff --git a/samples/13_path_finding_algorithms/08_a_star/app/main.rb b/samples/13_path_finding_algorithms/08_a_star/app/main.rb
index e9fcb8c..eaf7e09 100644
--- a/samples/13_path_finding_algorithms/08_a_star/app/main.rb
+++ b/samples/13_path_finding_algorithms/08_a_star/app/main.rb
@@ -11,8 +11,8 @@ class A_Star_Algorithm
def tick
defaults
- render
- input
+ render
+ input
if dijkstra.came_from.empty?
calc_searches
@@ -65,7 +65,7 @@ class A_Star_Algorithm
# We store this value, because we want to remember the value even when
# the user's cursor is no longer over what they're interacting with, but
# they are still clicking down on the mouse.
- state.user_input ||= :none
+ state.user_input ||= :none
# These variables allow the breadth first search to take place
# Came_from is a hash with a key of a cell and a value of the cell that was expanded from to find the key.
@@ -143,7 +143,7 @@ class A_Star_Algorithm
# If the mouse was clicked this tick
if inputs.mouse.down
# Determine what the user is editing and appropriately edit the state.user_input variable
- determine_input
+ determine_input
end
# Process user input based on user_input variable and current mouse position
@@ -154,51 +154,51 @@ class A_Star_Algorithm
# This method is called when the mouse is clicked down
def determine_input
# If the mouse is over the star in the first grid
- if dijkstra_mouse_over_star?
+ if dijkstra_mouse_over_star?
# The user is editing the star from the first grid
- state.user_input = :dijkstra_star
+ state.user_input = :dijkstra_star
# If the mouse is over the star in the second grid
- elsif greedy_mouse_over_star?
+ elsif greedy_mouse_over_star?
# The user is editing the star from the second grid
- state.user_input = :greedy_star
+ state.user_input = :greedy_star
# If the mouse is over the star in the third grid
- elsif a_star_mouse_over_star?
+ elsif a_star_mouse_over_star?
# The user is editing the star from the third grid
- state.user_input = :a_star_star
+ state.user_input = :a_star_star
# If the mouse is over the target in the first grid
- elsif dijkstra_mouse_over_target?
+ elsif dijkstra_mouse_over_target?
# The user is editing the target from the first grid
- state.user_input = :dijkstra_target
+ state.user_input = :dijkstra_target
# If the mouse is over the target in the second grid
- elsif greedy_mouse_over_target?
+ elsif greedy_mouse_over_target?
# The user is editing the target from the second grid
- state.user_input = :greedy_target
+ state.user_input = :greedy_target
# If the mouse is over the target in the third grid
- elsif a_star_mouse_over_target?
+ elsif a_star_mouse_over_target?
# The user is editing the target from the third grid
- state.user_input = :a_star_target
+ state.user_input = :a_star_target
# If the mouse is over a wall in the first grid
- elsif dijkstra_mouse_over_wall?
+ elsif dijkstra_mouse_over_wall?
# The user is removing a wall from the first grid
- state.user_input = :dijkstra_remove_wall
+ state.user_input = :dijkstra_remove_wall
# If the mouse is over a wall in the second grid
- elsif greedy_mouse_over_wall?
+ elsif greedy_mouse_over_wall?
# The user is removing a wall from the second grid
state.user_input = :greedy_remove_wall
# If the mouse is over a wall in the third grid
- elsif a_star_mouse_over_wall?
+ elsif a_star_mouse_over_wall?
# The user is removing a wall from the third grid
state.user_input = :a_star_remove_wall
# If the mouse is over the first grid
- elsif dijkstra_mouse_over_grid?
+ elsif dijkstra_mouse_over_grid?
# The user is adding a wall from the first grid
state.user_input = :dijkstra_add_wall
# If the mouse is over the second grid
- elsif greedy_mouse_over_grid?
+ elsif greedy_mouse_over_grid?
# The user is adding a wall from the second grid
state.user_input = :greedy_add_wall
# If the mouse is over the third grid
- elsif a_star_mouse_over_grid?
+ elsif a_star_mouse_over_grid?
# The user is adding a wall from the third grid
state.user_input = :a_star_add_wall
end
@@ -206,30 +206,30 @@ class A_Star_Algorithm
# Processes click and drag based on what the user is currently dragging
def process_input
- if state.user_input == :dijkstra_star
- process_input_dijkstra_star
+ if state.user_input == :dijkstra_star
+ process_input_dijkstra_star
elsif state.user_input == :greedy_star
- process_input_greedy_star
+ process_input_greedy_star
elsif state.user_input == :a_star_star
- process_input_a_star_star
- elsif state.user_input == :dijkstra_target
- process_input_dijkstra_target
- elsif state.user_input == :greedy_target
- process_input_greedy_target
- elsif state.user_input == :a_star_target
- process_input_a_star_target
- elsif state.user_input == :dijkstra_remove_wall
- process_input_dijkstra_remove_wall
+ process_input_a_star_star
+ elsif state.user_input == :dijkstra_target
+ process_input_dijkstra_target
+ elsif state.user_input == :greedy_target
+ process_input_greedy_target
+ elsif state.user_input == :a_star_target
+ process_input_a_star_target
+ elsif state.user_input == :dijkstra_remove_wall
+ process_input_dijkstra_remove_wall
elsif state.user_input == :greedy_remove_wall
- process_input_greedy_remove_wall
+ process_input_greedy_remove_wall
elsif state.user_input == :a_star_remove_wall
- process_input_a_star_remove_wall
- elsif state.user_input == :dijkstra_add_wall
- process_input_dijkstra_add_wall
- elsif state.user_input == :greedy_add_wall
- process_input_greedy_add_wall
- elsif state.user_input == :a_star_add_wall
- process_input_a_star_add_wall
+ process_input_a_star_remove_wall
+ elsif state.user_input == :dijkstra_add_wall
+ process_input_dijkstra_add_wall
+ elsif state.user_input == :greedy_add_wall
+ process_input_greedy_add_wall
+ elsif state.user_input == :a_star_add_wall
+ process_input_a_star_add_wall
end
end
@@ -244,7 +244,7 @@ class A_Star_Algorithm
# The horizontal grid lines
for y in 0..grid.height
- outputs.lines << dijkstra_horizontal_line(y)
+ outputs.lines << dijkstra_horizontal_line(y)
end
end
@@ -259,7 +259,7 @@ class A_Star_Algorithm
# The horizontal grid lines
for y in 0..grid.height
- outputs.lines << greedy_horizontal_line(y)
+ outputs.lines << greedy_horizontal_line(y)
end
end
@@ -274,10 +274,10 @@ class A_Star_Algorithm
# The horizontal grid lines
for y in 0..grid.height
- outputs.lines << a_star_horizontal_line(y)
+ outputs.lines << a_star_horizontal_line(y)
end
end
-
+
# Returns a vertical line for a column of the first grid
def dijkstra_vertical_line column
dijkstra_scale_up([column, 0, column, grid.height])
@@ -327,7 +327,7 @@ class A_Star_Algorithm
def render_dijkstra_target
outputs.sprites << [dijkstra_scale_up(grid.target), 'target.png']
end
-
+
# Renders the target on the second grid
def render_greedy_target
outputs.sprites << [greedy_scale_up(grid.target), 'target.png']
@@ -340,21 +340,21 @@ class A_Star_Algorithm
# Renders the walls on the first grid
def render_dijkstra_walls
- grid.walls.each_key do | wall |
+ grid.walls.each_key do | wall |
outputs.solids << [dijkstra_scale_up(wall), wall_color]
end
end
# Renders the walls on the second grid
def render_greedy_walls
- grid.walls.each_key do | wall |
+ grid.walls.each_key do | wall |
outputs.solids << [greedy_scale_up(wall), wall_color]
end
end
# Renders the walls on the third grid
def render_a_star_walls
- grid.walls.each_key do | wall |
+ grid.walls.each_key do | wall |
outputs.solids << [a_star_scale_up(wall), wall_color]
end
end
@@ -554,12 +554,12 @@ class A_Star_Algorithm
# Only resets the search if the star changes position
# Called whenever the user is editing the star (puts mouse down on star)
def process_input_dijkstra_star
- old_star = grid.star.clone
+ old_star = grid.star.clone
unless dijkstra_cell_closest_to_mouse == grid.target
- grid.star = dijkstra_cell_closest_to_mouse
+ grid.star = dijkstra_cell_closest_to_mouse
end
- unless old_star == grid.star
- reset_searches
+ unless old_star == grid.star
+ reset_searches
end
end
@@ -567,12 +567,12 @@ class A_Star_Algorithm
# Only resets the search if the star changes position
# Called whenever the user is editing the star (puts mouse down on star)
def process_input_greedy_star
- old_star = grid.star.clone
+ old_star = grid.star.clone
unless greedy_cell_closest_to_mouse == grid.target
grid.star = greedy_cell_closest_to_mouse
end
- unless old_star == grid.star
- reset_searches
+ unless old_star == grid.star
+ reset_searches
end
end
@@ -580,12 +580,12 @@ class A_Star_Algorithm
# Only resets the search if the star changes position
# Called whenever the user is editing the star (puts mouse down on star)
def process_input_a_star_star
- old_star = grid.star.clone
+ old_star = grid.star.clone
unless a_star_cell_closest_to_mouse == grid.target
grid.star = a_star_cell_closest_to_mouse
end
- unless old_star == grid.star
- reset_searches
+ unless old_star == grid.star
+ reset_searches
end
end
@@ -593,12 +593,12 @@ class A_Star_Algorithm
# Only reset_searchess the search if the target changes position
# Called whenever the user is editing the target (puts mouse down on target)
def process_input_dijkstra_target
- old_target = grid.target.clone
+ old_target = grid.target.clone
unless dijkstra_cell_closest_to_mouse == grid.star
grid.target = dijkstra_cell_closest_to_mouse
end
- unless old_target == grid.target
- reset_searches
+ unless old_target == grid.target
+ reset_searches
end
end
@@ -606,12 +606,12 @@ class A_Star_Algorithm
# Only reset_searchess the search if the target changes position
# Called whenever the user is editing the target (puts mouse down on target)
def process_input_greedy_target
- old_target = grid.target.clone
+ old_target = grid.target.clone
unless greedy_cell_closest_to_mouse == grid.star
grid.target = greedy_cell_closest_to_mouse
end
- unless old_target == grid.target
- reset_searches
+ unless old_target == grid.target
+ reset_searches
end
end
@@ -619,12 +619,12 @@ class A_Star_Algorithm
# Only reset_searchess the search if the target changes position
# Called whenever the user is editing the target (puts mouse down on target)
def process_input_a_star_target
- old_target = grid.target.clone
+ old_target = grid.target.clone
unless a_star_cell_closest_to_mouse == grid.star
grid.target = a_star_cell_closest_to_mouse
end
- unless old_target == grid.target
- reset_searches
+ unless old_target == grid.target
+ reset_searches
end
end
@@ -633,10 +633,10 @@ class A_Star_Algorithm
# The mouse needs to be inside the grid, because we only want to remove walls
# the cursor is directly over
# Recalculations should only occur when a wall is actually deleted
- if dijkstra_mouse_over_grid?
+ if dijkstra_mouse_over_grid?
if grid.walls.has_key?(dijkstra_cell_closest_to_mouse)
- grid.walls.delete(dijkstra_cell_closest_to_mouse)
- reset_searches
+ grid.walls.delete(dijkstra_cell_closest_to_mouse)
+ reset_searches
end
end
end
@@ -646,10 +646,10 @@ class A_Star_Algorithm
# The mouse needs to be inside the grid, because we only want to remove walls
# the cursor is directly over
# Recalculations should only occur when a wall is actually deleted
- if greedy_mouse_over_grid?
+ if greedy_mouse_over_grid?
if grid.walls.has_key?(greedy_cell_closest_to_mouse)
- grid.walls.delete(greedy_cell_closest_to_mouse)
- reset_searches
+ grid.walls.delete(greedy_cell_closest_to_mouse)
+ reset_searches
end
end
end
@@ -659,40 +659,40 @@ class A_Star_Algorithm
# The mouse needs to be inside the grid, because we only want to remove walls
# the cursor is directly over
# Recalculations should only occur when a wall is actually deleted
- if a_star_mouse_over_grid?
+ if a_star_mouse_over_grid?
if grid.walls.has_key?(a_star_cell_closest_to_mouse)
- grid.walls.delete(a_star_cell_closest_to_mouse)
- reset_searches
+ grid.walls.delete(a_star_cell_closest_to_mouse)
+ reset_searches
end
end
end
# Adds a wall in the first grid in the cell the mouse is over
def process_input_dijkstra_add_wall
- if dijkstra_mouse_over_grid?
+ if dijkstra_mouse_over_grid?
unless grid.walls.has_key?(dijkstra_cell_closest_to_mouse)
- grid.walls[dijkstra_cell_closest_to_mouse] = true
- reset_searches
+ grid.walls[dijkstra_cell_closest_to_mouse] = true
+ reset_searches
end
end
end
# Adds a wall in the second grid in the cell the mouse is over
def process_input_greedy_add_wall
- if greedy_mouse_over_grid?
+ if greedy_mouse_over_grid?
unless grid.walls.has_key?(greedy_cell_closest_to_mouse)
- grid.walls[greedy_cell_closest_to_mouse] = true
- reset_searches
+ grid.walls[greedy_cell_closest_to_mouse] = true
+ reset_searches
end
end
end
# Adds a wall in the third grid in the cell the mouse is over
def process_input_a_star_add_wall
- if a_star_mouse_over_grid?
+ if a_star_mouse_over_grid?
unless grid.walls.has_key?(a_star_cell_closest_to_mouse)
- grid.walls[a_star_cell_closest_to_mouse] = true
- reset_searches
+ grid.walls[a_star_cell_closest_to_mouse] = true
+ reset_searches
end
end
end
@@ -702,13 +702,13 @@ class A_Star_Algorithm
# Finding the cell closest to the mouse helps with this
def dijkstra_cell_closest_to_mouse
# Closest cell to the mouse in the first grid
- x = (inputs.mouse.point.x / grid.cell_size).to_i
- y = (inputs.mouse.point.y / grid.cell_size).to_i
+ x = (inputs.mouse.point.x / grid.cell_size).to_i
+ y = (inputs.mouse.point.y / grid.cell_size).to_i
# Bound x and y to the grid
- x = grid.width - 1 if x > grid.width - 1
- y = grid.height - 1 if y > grid.height - 1
+ x = grid.width - 1 if x > grid.width - 1
+ y = grid.height - 1 if y > grid.height - 1
# Return closest cell
- [x, y]
+ [x, y]
end
# When the user grabs the star and puts their cursor to the far right
@@ -716,17 +716,17 @@ class A_Star_Algorithm
# Finding the cell closest to the mouse in the second grid helps with this
def greedy_cell_closest_to_mouse
# Closest cell grid to the mouse in the second
- x = (inputs.mouse.point.x / grid.cell_size).to_i
- y = (inputs.mouse.point.y / grid.cell_size).to_i
+ x = (inputs.mouse.point.x / grid.cell_size).to_i
+ y = (inputs.mouse.point.y / grid.cell_size).to_i
# Translate the cell to the first grid
x -= grid.width + 1
# Bound x and y to the first grid
x = 0 if x < 0
y = 0 if y < 0
- x = grid.width - 1 if x > grid.width - 1
- y = grid.height - 1 if y > grid.height - 1
+ x = grid.width - 1 if x > grid.width - 1
+ y = grid.height - 1 if y > grid.height - 1
# Return closest cell
- [x, y]
+ [x, y]
end
# When the user grabs the star and puts their cursor to the far right
@@ -734,17 +734,17 @@ class A_Star_Algorithm
# Finding the cell closest to the mouse in the third grid helps with this
def a_star_cell_closest_to_mouse
# Closest cell grid to the mouse in the second
- x = (inputs.mouse.point.x / grid.cell_size).to_i
- y = (inputs.mouse.point.y / grid.cell_size).to_i
+ x = (inputs.mouse.point.x / grid.cell_size).to_i
+ y = (inputs.mouse.point.y / grid.cell_size).to_i
# Translate the cell to the first grid
x -= (grid.width + 1) * 2
# Bound x and y to the first grid
x = 0 if x < 0
y = 0 if y < 0
- x = grid.width - 1 if x > grid.width - 1
- y = grid.height - 1 if y > grid.height - 1
+ x = grid.width - 1 if x > grid.width - 1
+ y = grid.height - 1 if y > grid.height - 1
# Return closest cell
- [x, y]
+ [x, y]
end
def reset_searches
@@ -772,21 +772,21 @@ class A_Star_Algorithm
def calc_dijkstra
# Sets up the search to begin from the star
- dijkstra.frontier << grid.star
- dijkstra.came_from[grid.star] = nil
- dijkstra.cost_so_far[grid.star] = 0
+ dijkstra.frontier << grid.star
+ dijkstra.came_from[grid.star] = nil
+ dijkstra.cost_so_far[grid.star] = 0
# Until the target is found or there are no more cells to explore from
until dijkstra.came_from.has_key?(grid.target) or dijkstra.frontier.empty?
# Take the next frontier cell. The first element is the cell, the second is the priority.
new_frontier = dijkstra.frontier.shift#[0]
# For each of its neighbors
- adjacent_neighbors(new_frontier).each do | neighbor |
+ adjacent_neighbors(new_frontier).each do | neighbor |
# That have not been visited and are not walls
- unless dijkstra.came_from.has_key?(neighbor) or grid.walls.has_key?(neighbor)
+ unless dijkstra.came_from.has_key?(neighbor) or grid.walls.has_key?(neighbor)
# Add them to the frontier and mark them as visited
dijkstra.frontier << neighbor
- dijkstra.came_from[neighbor] = new_frontier
+ dijkstra.came_from[neighbor] = new_frontier
dijkstra.cost_so_far[neighbor] = dijkstra.cost_so_far[new_frontier] + 1
end
end
@@ -807,20 +807,20 @@ class A_Star_Algorithm
def calc_greedy
# Sets up the search to begin from the star
- greedy.frontier << grid.star
- greedy.came_from[grid.star] = nil
+ greedy.frontier << grid.star
+ greedy.came_from[grid.star] = nil
# Until the target is found or there are no more cells to explore from
until greedy.came_from.has_key?(grid.target) or greedy.frontier.empty?
# Take the next frontier cell
- new_frontier = greedy.frontier.shift
+ new_frontier = greedy.frontier.shift
# For each of its neighbors
- adjacent_neighbors(new_frontier).each do | neighbor |
+ adjacent_neighbors(new_frontier).each do | neighbor |
# That have not been visited and are not walls
- unless greedy.came_from.has_key?(neighbor) or grid.walls.has_key?(neighbor)
+ unless greedy.came_from.has_key?(neighbor) or grid.walls.has_key?(neighbor)
# Add them to the frontier and mark them as visited
- greedy.frontier << neighbor
- greedy.came_from[neighbor] = new_frontier
+ greedy.frontier << neighbor
+ greedy.came_from[neighbor] = new_frontier
end
end
# Sort the frontier so that cells that are in a zigzag pattern are prioritized over those in an line
@@ -850,12 +850,12 @@ class A_Star_Algorithm
current_frontier = a_star.frontier.shift
# For each of that cells neighbors
- adjacent_neighbors(current_frontier).each do | neighbor |
+ adjacent_neighbors(current_frontier).each do | neighbor |
# That have not been visited and are not walls
- unless a_star.came_from.has_key?(neighbor) or grid.walls.has_key?(neighbor)
+ unless a_star.came_from.has_key?(neighbor) or grid.walls.has_key?(neighbor)
# Add them to the frontier and mark them as visited
- a_star.frontier << neighbor
- a_star.came_from[neighbor] = current_frontier
+ a_star.frontier << neighbor
+ a_star.came_from[neighbor] = current_frontier
a_star.cost_so_far[neighbor] = a_star.cost_so_far[current_frontier] + 1
end
end
@@ -937,16 +937,16 @@ class A_Star_Algorithm
# Returns a list of adjacent cells
# Used to determine what the next cells to be added to the frontier are
def adjacent_neighbors(cell)
- neighbors = []
+ neighbors = []
# Gets all the valid neighbors into the array
# From southern neighbor, clockwise
- neighbors << [cell.x , cell.y - 1] unless cell.y == 0
- neighbors << [cell.x - 1, cell.y ] unless cell.x == 0
- neighbors << [cell.x , cell.y + 1] unless cell.y == grid.height - 1
- neighbors << [cell.x + 1, cell.y ] unless cell.x == grid.width - 1
+ neighbors << [cell.x , cell.y - 1] unless cell.y == 0
+ neighbors << [cell.x - 1, cell.y ] unless cell.x == 0
+ neighbors << [cell.x , cell.y + 1] unless cell.y == grid.height - 1
+ neighbors << [cell.x + 1, cell.y ] unless cell.x == grid.width - 1
- neighbors
+ neighbors
end
# Finds the vertical and horizontal distance of a cell from the star
@@ -991,11 +991,11 @@ class A_Star_Algorithm
def wall_color
[134, 134, 120] # Camo Green
end
-
+
def visited_color
[204, 191, 179] # Dark Brown
end
-
+
def path_color
[231, 230, 228] # Pastel White
end
@@ -1018,7 +1018,7 @@ def tick args
end
# Every tick, new args are passed, and the Breadth First Search tick is called
- $a_star_algorithm ||= A_Star_Algorithm.new(args)
+ $a_star_algorithm ||= A_Star_Algorithm.new
$a_star_algorithm.args = args
$a_star_algorithm.tick
end
diff --git a/samples/13_path_finding_algorithms/08_a_star/replay.txt b/samples/13_path_finding_algorithms/08_a_star/replay.txt
new file mode 100644
index 0000000..001a564
--- /dev/null
+++ b/samples/13_path_finding_algorithms/08_a_star/replay.txt
@@ -0,0 +1,434 @@
+replay_version 2.0
+stopped_at 341
+seed 100
+recorded_at 2021-11-20 11:24:45 -0600
+[:mouse_button_up, 1, 0, 1, 1, 1]
+[:mouse_move, 769, 97, 2, 2, 8]
+[:mouse_move, 763, 101, 2, 3, 8]
+[:mouse_move, 755, 109, 2, 4, 8]
+[:mouse_move, 748, 123, 2, 5, 8]
+[:mouse_move, 746, 148, 2, 6, 9]
+[:mouse_move, 742, 180, 2, 7, 9]
+[:mouse_move, 733, 215, 2, 8, 9]
+[:mouse_move, 719, 278, 2, 9, 9]
+[:mouse_move, 712, 336, 2, 10, 9]
+[:mouse_move, 701, 397, 2, 11, 10]
+[:mouse_move, 685, 440, 2, 12, 10]
+[:mouse_move, 667, 472, 2, 13, 10]
+[:mouse_move, 654, 493, 2, 14, 10]
+[:mouse_move, 644, 506, 2, 15, 11]
+[:mouse_move, 637, 514, 2, 16, 11]
+[:mouse_move, 635, 516, 2, 17, 11]
+[:mouse_move, 634, 517, 2, 18, 11]
+[:mouse_move, 630, 518, 2, 19, 12]
+[:mouse_move, 624, 524, 2, 20, 12]
+[:mouse_move, 619, 537, 2, 21, 12]
+[:mouse_move, 612, 553, 2, 22, 13]
+[:mouse_move, 609, 561, 2, 23, 13]
+[:mouse_move, 608, 565, 2, 24, 13]
+[:mouse_move, 613, 565, 2, 25, 14]
+[:mouse_move, 627, 565, 2, 26, 14]
+[:mouse_move, 641, 565, 2, 27, 14]
+[:mouse_move, 654, 565, 2, 28, 14]
+[:mouse_move, 658, 565, 2, 29, 15]
+[:mouse_move, 659, 565, 2, 30, 15]
+[:mouse_move, 662, 565, 2, 31, 15]
+[:mouse_move, 667, 566, 2, 32, 15]
+[:mouse_move, 671, 566, 2, 33, 16]
+[:mouse_move, 676, 566, 2, 34, 16]
+[:mouse_move, 685, 566, 2, 35, 16]
+[:mouse_move, 701, 565, 2, 36, 16]
+[:mouse_move, 719, 562, 2, 37, 17]
+[:mouse_move, 731, 560, 2, 38, 17]
+[:mouse_move, 744, 559, 2, 39, 17]
+[:mouse_move, 750, 559, 2, 40, 17]
+[:mouse_move, 757, 559, 2, 41, 17]
+[:mouse_move, 763, 559, 2, 42, 17]
+[:mouse_move, 767, 559, 2, 43, 18]
+[:mouse_move, 769, 559, 2, 44, 18]
+[:mouse_move, 770, 558, 2, 45, 18]
+[:mouse_move, 774, 557, 2, 46, 18]
+[:mouse_move, 784, 555, 2, 47, 18]
+[:mouse_move, 796, 551, 2, 48, 19]
+[:mouse_move, 804, 550, 2, 49, 19]
+[:mouse_move, 810, 548, 2, 50, 19]
+[:mouse_move, 814, 547, 2, 51, 20]
+[:mouse_move, 817, 547, 2, 52, 20]
+[:mouse_move, 818, 547, 2, 53, 20]
+[:mouse_move, 819, 547, 2, 54, 20]
+[:mouse_move, 819, 546, 2, 55, 20]
+[:mouse_move, 819, 545, 2, 56, 20]
+[:mouse_move, 820, 545, 2, 57, 21]
+[:mouse_move, 820, 544, 2, 58, 21]
+[:mouse_move, 820, 543, 2, 59, 21]
+[:mouse_move, 820, 542, 2, 60, 22]
+[:mouse_move, 820, 541, 2, 61, 22]
+[:mouse_move, 820, 540, 2, 62, 23]
+[:mouse_move, 819, 540, 2, 63, 23]
+[:mouse_button_pressed, 1, 0, 1, 64, 24]
+[:mouse_button_up, 1, 0, 1, 65, 25]
+[:mouse_move, 820, 540, 2, 66, 29]
+[:mouse_move, 820, 541, 2, 67, 29]
+[:mouse_move, 820, 542, 2, 68, 29]
+[:mouse_move, 820, 543, 2, 69, 30]
+[:mouse_move, 819, 543, 2, 70, 31]
+[:mouse_move, 818, 543, 2, 71, 31]
+[:mouse_move, 817, 542, 2, 72, 31]
+[:mouse_move, 816, 542, 2, 73, 32]
+[:mouse_move, 812, 542, 2, 74, 32]
+[:mouse_move, 808, 542, 2, 75, 32]
+[:mouse_move, 802, 542, 2, 76, 33]
+[:mouse_move, 796, 542, 2, 77, 33]
+[:mouse_move, 790, 542, 2, 78, 33]
+[:mouse_move, 784, 540, 2, 79, 33]
+[:mouse_move, 783, 540, 2, 80, 34]
+[:mouse_move, 782, 538, 2, 81, 34]
+[:mouse_move, 782, 533, 2, 82, 34]
+[:mouse_move, 785, 525, 2, 83, 34]
+[:mouse_move, 788, 512, 2, 84, 34]
+[:mouse_move, 791, 494, 2, 85, 35]
+[:mouse_move, 791, 469, 2, 86, 35]
+[:mouse_move, 785, 442, 2, 87, 35]
+[:mouse_move, 776, 417, 2, 88, 35]
+[:mouse_move, 767, 398, 2, 89, 36]
+[:mouse_move, 759, 381, 2, 90, 36]
+[:mouse_move, 747, 365, 2, 91, 36]
+[:mouse_move, 737, 356, 2, 92, 36]
+[:mouse_move, 718, 345, 2, 93, 36]
+[:mouse_move, 702, 337, 2, 94, 37]
+[:mouse_move, 693, 333, 2, 95, 37]
+[:mouse_move, 689, 331, 2, 96, 37]
+[:mouse_move, 688, 331, 2, 97, 38]
+[:mouse_move, 687, 331, 2, 98, 38]
+[:mouse_move, 686, 342, 2, 99, 38]
+[:mouse_move, 684, 352, 2, 100, 39]
+[:mouse_move, 682, 359, 2, 101, 39]
+[:mouse_move, 682, 362, 2, 102, 39]
+[:mouse_move, 682, 364, 2, 103, 40]
+[:mouse_move, 683, 364, 2, 104, 40]
+[:mouse_move, 686, 364, 2, 105, 40]
+[:mouse_move, 688, 363, 2, 106, 40]
+[:mouse_move, 692, 362, 2, 107, 40]
+[:mouse_move, 698, 362, 2, 108, 41]
+[:mouse_move, 702, 362, 2, 109, 41]
+[:mouse_move, 705, 362, 2, 110, 41]
+[:mouse_move, 706, 362, 2, 111, 42]
+[:mouse_move, 706, 361, 2, 112, 42]
+[:mouse_move, 707, 361, 2, 113, 42]
+[:mouse_move, 708, 360, 2, 114, 42]
+[:mouse_move, 709, 359, 2, 115, 43]
+[:mouse_move, 709, 358, 2, 116, 43]
+[:mouse_move, 710, 358, 2, 117, 43]
+[:mouse_button_pressed, 1, 0, 1, 118, 44]
+[:mouse_button_up, 1, 0, 1, 119, 45]
+[:mouse_move, 710, 357, 2, 120, 56]
+[:mouse_move, 713, 357, 2, 121, 56]
+[:mouse_move, 715, 357, 2, 122, 57]
+[:mouse_move, 716, 357, 2, 123, 57]
+[:mouse_move, 717, 357, 2, 124, 57]
+[:mouse_move, 719, 357, 2, 125, 58]
+[:mouse_move, 720, 357, 2, 126, 58]
+[:mouse_move, 720, 356, 2, 127, 59]
+[:mouse_move, 721, 356, 2, 128, 59]
+[:mouse_move, 723, 356, 2, 129, 59]
+[:mouse_move, 724, 356, 2, 130, 59]
+[:mouse_move, 727, 356, 2, 131, 59]
+[:mouse_move, 728, 356, 2, 132, 59]
+[:mouse_move, 730, 356, 2, 133, 60]
+[:mouse_move, 731, 355, 2, 134, 60]
+[:mouse_move, 732, 355, 2, 135, 60]
+[:mouse_move, 734, 355, 2, 136, 60]
+[:mouse_move, 735, 355, 2, 137, 60]
+[:mouse_button_pressed, 1, 0, 1, 138, 62]
+[:mouse_move, 737, 358, 2, 139, 63]
+[:mouse_move, 739, 364, 2, 140, 63]
+[:mouse_move, 739, 372, 2, 141, 63]
+[:mouse_move, 739, 381, 2, 142, 64]
+[:mouse_move, 740, 390, 2, 143, 64]
+[:mouse_move, 742, 403, 2, 144, 64]
+[:mouse_move, 744, 415, 2, 145, 64]
+[:mouse_move, 744, 426, 2, 146, 64]
+[:mouse_move, 745, 438, 2, 147, 64]
+[:mouse_move, 746, 445, 2, 148, 64]
+[:mouse_move, 747, 449, 2, 149, 64]
+[:mouse_move, 747, 450, 2, 150, 64]
+[:mouse_move, 747, 451, 2, 151, 64]
+[:mouse_move, 748, 452, 2, 152, 64]
+[:mouse_move, 749, 452, 2, 153, 64]
+[:mouse_move, 750, 452, 2, 154, 64]
+[:mouse_move, 751, 452, 2, 155, 64]
+[:mouse_move, 753, 454, 2, 156, 64]
+[:mouse_move, 754, 455, 2, 157, 64]
+[:mouse_move, 756, 456, 2, 158, 64]
+[:mouse_move, 759, 459, 2, 159, 64]
+[:mouse_move, 765, 465, 2, 160, 64]
+[:mouse_move, 769, 469, 2, 161, 64]
+[:mouse_move, 773, 474, 2, 162, 64]
+[:mouse_move, 776, 479, 2, 163, 64]
+[:mouse_move, 781, 486, 2, 164, 64]
+[:mouse_move, 782, 490, 2, 165, 65]
+[:mouse_move, 783, 494, 2, 166, 65]
+[:mouse_move, 783, 498, 2, 167, 65]
+[:mouse_move, 784, 506, 2, 168, 65]
+[:mouse_move, 786, 515, 2, 169, 65]
+[:mouse_move, 789, 526, 2, 170, 65]
+[:mouse_move, 791, 534, 2, 171, 65]
+[:mouse_move, 795, 549, 2, 172, 65]
+[:mouse_move, 798, 556, 2, 173, 65]
+[:mouse_move, 799, 561, 2, 174, 65]
+[:mouse_move, 799, 564, 2, 175, 65]
+[:mouse_move, 801, 570, 2, 176, 65]
+[:mouse_move, 802, 577, 2, 177, 65]
+[:mouse_move, 804, 583, 2, 178, 65]
+[:mouse_move, 804, 587, 2, 179, 65]
+[:mouse_move, 805, 590, 2, 180, 65]
+[:mouse_move, 807, 594, 2, 181, 65]
+[:mouse_move, 809, 598, 2, 182, 65]
+[:mouse_move, 811, 601, 2, 183, 65]
+[:mouse_move, 812, 602, 2, 184, 65]
+[:mouse_move, 812, 603, 2, 185, 65]
+[:mouse_move, 813, 604, 2, 186, 65]
+[:mouse_move, 814, 604, 2, 187, 65]
+[:mouse_move, 817, 599, 2, 188, 65]
+[:mouse_move, 819, 595, 2, 189, 65]
+[:mouse_move, 820, 594, 2, 190, 65]
+[:mouse_move, 819, 594, 2, 191, 77]
+[:mouse_button_up, 1, 0, 1, 192, 77]
+[:mouse_move, 818, 594, 2, 193, 77]
+[:mouse_move, 817, 594, 2, 194, 78]
+[:mouse_move, 816, 594, 2, 195, 79]
+[:mouse_move, 815, 593, 2, 196, 109]
+[:mouse_move, 812, 592, 2, 197, 109]
+[:mouse_move, 808, 592, 2, 198, 109]
+[:mouse_move, 799, 591, 2, 199, 109]
+[:mouse_move, 780, 588, 2, 200, 110]
+[:mouse_move, 758, 584, 2, 201, 110]
+[:mouse_move, 738, 584, 2, 202, 110]
+[:mouse_move, 724, 584, 2, 203, 110]
+[:mouse_move, 710, 584, 2, 204, 110]
+[:mouse_move, 691, 583, 2, 205, 111]
+[:mouse_move, 668, 579, 2, 206, 111]
+[:mouse_move, 647, 577, 2, 207, 111]
+[:mouse_move, 630, 577, 2, 208, 111]
+[:mouse_move, 610, 577, 2, 209, 112]
+[:mouse_move, 602, 577, 2, 210, 112]
+[:mouse_move, 597, 576, 2, 211, 112]
+[:mouse_move, 595, 575, 2, 212, 112]
+[:mouse_move, 603, 575, 2, 213, 114]
+[:mouse_move, 626, 575, 2, 214, 114]
+[:mouse_move, 651, 575, 2, 215, 114]
+[:mouse_move, 680, 579, 2, 216, 114]
+[:mouse_move, 723, 583, 2, 217, 114]
+[:mouse_move, 745, 585, 2, 218, 114]
+[:mouse_move, 756, 585, 2, 219, 115]
+[:mouse_move, 758, 585, 2, 220, 115]
+[:mouse_move, 759, 585, 2, 221, 115]
+[:mouse_move, 760, 584, 2, 222, 115]
+[:mouse_move, 761, 584, 2, 223, 116]
+[:mouse_move, 764, 584, 2, 224, 116]
+[:mouse_move, 767, 584, 2, 225, 116]
+[:mouse_move, 769, 584, 2, 226, 116]
+[:mouse_move, 773, 584, 2, 227, 117]
+[:mouse_move, 791, 588, 2, 228, 117]
+[:mouse_move, 803, 596, 2, 229, 117]
+[:mouse_move, 807, 599, 2, 230, 118]
+[:mouse_move, 808, 599, 2, 231, 118]
+[:mouse_move, 809, 599, 2, 232, 119]
+[:mouse_move, 812, 599, 2, 233, 120]
+[:mouse_move, 813, 599, 2, 234, 120]
+[:mouse_move, 814, 599, 2, 235, 120]
+[:mouse_move, 815, 599, 2, 236, 122]
+[:mouse_move, 816, 598, 2, 237, 122]
+[:mouse_move, 817, 598, 2, 238, 123]
+[:mouse_button_pressed, 1, 0, 1, 239, 123]
+[:mouse_move, 805, 598, 2, 240, 124]
+[:mouse_move, 777, 598, 2, 241, 124]
+[:mouse_move, 748, 598, 2, 242, 124]
+[:mouse_move, 722, 598, 2, 243, 124]
+[:mouse_move, 692, 598, 2, 244, 124]
+[:mouse_move, 668, 598, 2, 245, 124]
+[:mouse_move, 648, 598, 2, 246, 125]
+[:mouse_move, 624, 598, 2, 247, 125]
+[:mouse_move, 615, 598, 2, 248, 125]
+[:mouse_move, 610, 598, 2, 249, 125]
+[:mouse_move, 609, 598, 2, 250, 125]
+[:mouse_move, 607, 598, 2, 251, 125]
+[:mouse_move, 606, 598, 2, 252, 125]
+[:mouse_move, 604, 595, 2, 253, 127]
+[:mouse_move, 598, 590, 2, 254, 128]
+[:mouse_move, 592, 584, 2, 255, 128]
+[:mouse_move, 588, 581, 2, 256, 129]
+[:mouse_move, 588, 580, 2, 257, 129]
+[:mouse_move, 587, 580, 2, 258, 129]
+[:mouse_move, 586, 579, 2, 259, 130]
+[:mouse_move, 585, 579, 2, 260, 130]
+[:mouse_move, 584, 578, 2, 261, 131]
+[:mouse_move, 584, 577, 2, 262, 131]
+[:mouse_move, 584, 576, 2, 263, 132]
+[:mouse_move, 583, 576, 2, 264, 133]
+[:mouse_move, 584, 576, 2, 265, 135]
+[:mouse_button_up, 1, 0, 1, 266, 147]
+[:mouse_move, 585, 575, 2, 267, 153]
+[:mouse_move, 585, 571, 2, 268, 196]
+[:mouse_move, 585, 568, 2, 269, 197]
+[:mouse_move, 586, 563, 2, 270, 197]
+[:mouse_move, 587, 558, 2, 271, 197]
+[:mouse_move, 587, 557, 2, 272, 198]
+[:mouse_move, 587, 555, 2, 273, 199]
+[:mouse_move, 588, 555, 2, 274, 200]
+[:mouse_move, 588, 554, 2, 275, 200]
+[:mouse_move, 588, 550, 2, 276, 235]
+[:mouse_move, 594, 541, 2, 277, 236]
+[:mouse_move, 605, 525, 2, 278, 236]
+[:mouse_move, 622, 502, 2, 279, 236]
+[:mouse_move, 654, 458, 2, 280, 237]
+[:mouse_move, 672, 425, 2, 281, 237]
+[:mouse_move, 682, 391, 2, 282, 238]
+[:mouse_move, 688, 358, 2, 283, 239]
+[:mouse_move, 692, 333, 2, 284, 239]
+[:mouse_move, 694, 319, 2, 285, 239]
+[:mouse_move, 697, 308, 2, 286, 240]
+[:mouse_move, 698, 303, 2, 287, 240]
+[:mouse_move, 700, 299, 2, 288, 241]
+[:mouse_move, 702, 295, 2, 289, 241]
+[:mouse_move, 703, 291, 2, 290, 242]
+[:mouse_move, 704, 289, 2, 291, 242]
+[:mouse_move, 705, 288, 2, 292, 243]
+[:mouse_move, 706, 288, 2, 293, 245]
+[:mouse_move, 706, 291, 2, 294, 246]
+[:mouse_move, 706, 294, 2, 295, 246]
+[:mouse_move, 706, 298, 2, 296, 247]
+[:mouse_move, 706, 303, 2, 297, 247]
+[:mouse_move, 707, 308, 2, 298, 247]
+[:mouse_move, 709, 315, 2, 299, 248]
+[:mouse_move, 710, 321, 2, 300, 248]
+[:mouse_move, 711, 324, 2, 301, 249]
+[:mouse_move, 711, 325, 2, 302, 249]
+[:mouse_move, 712, 325, 2, 303, 250]
+[:mouse_move, 713, 325, 2, 304, 252]
+[:mouse_move, 713, 324, 2, 305, 252]
+[:mouse_move, 714, 324, 2, 306, 253]
+[:mouse_button_pressed, 1, 0, 1, 307, 254]
+[:mouse_button_up, 1, 0, 1, 308, 255]
+[:mouse_move, 714, 325, 2, 309, 263]
+[:mouse_move, 714, 331, 2, 310, 263]
+[:mouse_move, 714, 344, 2, 311, 264]
+[:mouse_move, 714, 365, 2, 312, 264]
+[:mouse_move, 710, 394, 2, 313, 264]
+[:mouse_move, 696, 432, 2, 314, 265]
+[:mouse_move, 678, 472, 2, 315, 265]
+[:mouse_move, 654, 506, 2, 316, 266]
+[:mouse_move, 637, 532, 2, 317, 267]
+[:mouse_move, 624, 549, 2, 318, 267]
+[:mouse_move, 615, 559, 2, 319, 267]
+[:mouse_move, 612, 562, 2, 320, 268]
+[:mouse_move, 609, 563, 2, 321, 268]
+[:mouse_move, 608, 564, 2, 322, 269]
+[:mouse_move, 606, 566, 2, 323, 269]
+[:mouse_move, 606, 568, 2, 324, 270]
+[:mouse_move, 606, 572, 2, 325, 270]
+[:mouse_move, 606, 573, 2, 326, 271]
+[:mouse_move, 606, 574, 2, 327, 271]
+[:mouse_move, 605, 573, 2, 328, 273]
+[:mouse_move, 606, 571, 2, 329, 273]
+[:mouse_move, 606, 566, 2, 330, 274]
+[:mouse_move, 606, 565, 2, 331, 274]
+[:mouse_move, 605, 565, 2, 332, 275]
+[:mouse_move, 601, 565, 2, 333, 275]
+[:mouse_move, 593, 565, 2, 334, 276]
+[:mouse_move, 583, 565, 2, 335, 276]
+[:mouse_move, 573, 567, 2, 336, 277]
+[:mouse_move, 570, 567, 2, 337, 278]
+[:mouse_move, 569, 567, 2, 338, 278]
+[:mouse_move, 570, 568, 2, 339, 284]
+[:mouse_move, 572, 568, 2, 340, 284]
+[:mouse_move, 573, 568, 2, 341, 286]
+[:mouse_button_pressed, 1, 0, 1, 342, 290]
+[:mouse_move, 574, 568, 2, 343, 290]
+[:mouse_move, 576, 568, 2, 344, 291]
+[:mouse_move, 586, 564, 2, 345, 292]
+[:mouse_move, 601, 560, 2, 346, 292]
+[:mouse_move, 622, 552, 2, 347, 292]
+[:mouse_move, 648, 544, 2, 348, 293]
+[:mouse_move, 675, 537, 2, 349, 293]
+[:mouse_move, 702, 533, 2, 350, 293]
+[:mouse_move, 726, 530, 2, 351, 293]
+[:mouse_move, 747, 526, 2, 352, 293]
+[:mouse_move, 771, 518, 2, 353, 293]
+[:mouse_move, 786, 514, 2, 354, 293]
+[:mouse_move, 802, 511, 2, 355, 294]
+[:mouse_move, 815, 508, 2, 356, 294]
+[:mouse_move, 827, 505, 2, 357, 294]
+[:mouse_move, 833, 504, 2, 358, 294]
+[:mouse_move, 835, 503, 2, 359, 294]
+[:mouse_move, 832, 503, 2, 360, 294]
+[:mouse_move, 830, 504, 2, 361, 294]
+[:mouse_move, 826, 506, 2, 362, 294]
+[:mouse_move, 822, 508, 2, 363, 294]
+[:mouse_move, 818, 511, 2, 364, 294]
+[:mouse_move, 816, 511, 2, 365, 294]
+[:mouse_move, 813, 513, 2, 366, 294]
+[:mouse_move, 813, 514, 2, 367, 294]
+[:mouse_move, 812, 515, 2, 368, 294]
+[:mouse_move, 812, 516, 2, 369, 294]
+[:mouse_move, 812, 517, 2, 370, 294]
+[:mouse_move, 813, 518, 2, 371, 295]
+[:mouse_move, 814, 518, 2, 372, 295]
+[:mouse_move, 815, 518, 2, 373, 295]
+[:mouse_move, 816, 518, 2, 374, 295]
+[:mouse_move, 817, 518, 2, 375, 295]
+[:mouse_button_up, 1, 0, 1, 376, 302]
+[:mouse_move, 817, 517, 2, 377, 313]
+[:key_down_raw, 96, 0, 2, 378, 320]
+[:key_up_raw, 96, 0, 2, 379, 321]
+[:mouse_move, 817, 518, 2, 380, 323]
+[:mouse_move, 819, 515, 2, 381, 324]
+[:mouse_move, 819, 510, 2, 382, 324]
+[:mouse_move, 811, 498, 2, 383, 324]
+[:mouse_move, 797, 486, 2, 384, 324]
+[:mouse_move, 786, 482, 2, 385, 324]
+[:mouse_move, 780, 479, 2, 386, 324]
+[:mouse_move, 779, 478, 2, 387, 324]
+[:mouse_move, 778, 479, 2, 388, 327]
+[:mouse_move, 779, 484, 2, 389, 327]
+[:mouse_move, 780, 487, 2, 390, 327]
+[:mouse_move, 781, 488, 2, 391, 327]
+[:mouse_move, 782, 488, 2, 392, 327]
+[:mouse_move, 782, 487, 2, 393, 328]
+[:mouse_move, 789, 485, 2, 394, 328]
+[:mouse_move, 800, 481, 2, 395, 328]
+[:mouse_move, 816, 472, 2, 396, 328]
+[:mouse_move, 839, 456, 2, 397, 328]
+[:mouse_move, 870, 434, 2, 398, 329]
+[:mouse_move, 904, 409, 2, 399, 329]
+[:mouse_move, 944, 380, 2, 400, 329]
+[:mouse_move, 996, 331, 2, 401, 329]
+[:mouse_move, 1011, 312, 2, 402, 329]
+[:mouse_move, 1042, 278, 2, 403, 329]
+[:mouse_move, 1081, 231, 2, 404, 329]
+[:mouse_move, 1101, 213, 2, 405, 330]
+[:mouse_move, 1114, 202, 2, 406, 330]
+[:mouse_move, 1118, 196, 2, 407, 330]
+[:mouse_move, 1118, 195, 2, 408, 330]
+[:mouse_move, 1117, 194, 2, 409, 331]
+[:mouse_move, 1115, 194, 2, 410, 331]
+[:mouse_move, 1110, 193, 2, 411, 331]
+[:mouse_move, 1102, 189, 2, 412, 331]
+[:mouse_move, 1084, 184, 2, 413, 331]
+[:mouse_move, 1052, 175, 2, 414, 332]
+[:mouse_move, 1005, 162, 2, 415, 332]
+[:mouse_move, 938, 144, 2, 416, 332]
+[:mouse_move, 892, 138, 2, 417, 332]
+[:mouse_move, 860, 134, 2, 418, 332]
+[:mouse_move, 833, 128, 2, 419, 333]
+[:mouse_move, 809, 120, 2, 420, 333]
+[:mouse_move, 782, 108, 2, 421, 333]
+[:mouse_move, 772, 104, 2, 422, 333]
+[:mouse_move, 770, 103, 2, 423, 333]
+[:mouse_move, 769, 103, 2, 424, 333]
+[:mouse_move, 766, 101, 2, 425, 334]
+[:mouse_move, 764, 100, 2, 426, 334]
+[:mouse_move, 763, 100, 2, 427, 334]
+[:mouse_move, 761, 99, 2, 428, 334]
+[:mouse_move, 760, 98, 2, 429, 334]
+[:key_down_raw, 13, 0, 2, 430, 341]
diff --git a/samples/99_genre_3d/02_wireframe/replay.txt b/samples/99_genre_3d/02_wireframe/replay.txt
new file mode 100644
index 0000000..2786904
--- /dev/null
+++ b/samples/99_genre_3d/02_wireframe/replay.txt
@@ -0,0 +1,242 @@
+replay_version 2.0
+stopped_at 706
+seed 100
+recorded_at 2021-11-20 11:26:04 -0600
+[:mouse_button_up, 1, 0, 1, 1, 4]
+[:key_down_raw, 1073741906, 0, 2, 2, 63]
+[:key_down_raw, 1073741906, 0, 2, 3, 77]
+[:key_down_raw, 1073741906, 0, 2, 4, 79]
+[:key_down_raw, 1073741906, 0, 2, 5, 81]
+[:key_down_raw, 1073741906, 0, 2, 6, 84]
+[:key_down_raw, 1073741906, 0, 2, 7, 85]
+[:key_down_raw, 1073741906, 0, 2, 8, 87]
+[:key_down_raw, 1073741906, 0, 2, 9, 90]
+[:key_down_raw, 1073741906, 0, 2, 10, 92]
+[:key_down_raw, 1073741906, 0, 2, 11, 94]
+[:key_down_raw, 1073741906, 0, 2, 12, 96]
+[:key_down_raw, 1073741906, 0, 2, 13, 98]
+[:key_down_raw, 1073741906, 0, 2, 14, 100]
+[:key_down_raw, 1073741906, 0, 2, 15, 102]
+[:key_up_raw, 1073741906, 0, 2, 16, 103]
+[:key_down_raw, 1073741905, 0, 2, 17, 110]
+[:key_down_raw, 1073741905, 0, 2, 18, 125]
+[:key_down_raw, 1073741905, 0, 2, 19, 127]
+[:key_down_raw, 1073741905, 0, 2, 20, 129]
+[:key_down_raw, 1073741905, 0, 2, 21, 131]
+[:key_down_raw, 1073741905, 0, 2, 22, 133]
+[:key_down_raw, 1073741905, 0, 2, 23, 135]
+[:key_down_raw, 1073741905, 0, 2, 24, 137]
+[:key_down_raw, 1073741905, 0, 2, 25, 139]
+[:key_down_raw, 1073741905, 0, 2, 26, 141]
+[:key_down_raw, 1073741905, 0, 2, 27, 143]
+[:key_down_raw, 1073741905, 0, 2, 28, 145]
+[:key_down_raw, 1073741905, 0, 2, 29, 147]
+[:key_down_raw, 1073741905, 0, 2, 30, 149]
+[:key_down_raw, 1073741905, 0, 2, 31, 151]
+[:key_down_raw, 1073741905, 0, 2, 32, 153]
+[:key_down_raw, 1073741905, 0, 2, 33, 155]
+[:key_down_raw, 1073741905, 0, 2, 34, 157]
+[:key_down_raw, 1073741905, 0, 2, 35, 159]
+[:key_down_raw, 1073741905, 0, 2, 36, 161]
+[:key_down_raw, 1073741905, 0, 2, 37, 163]
+[:key_down_raw, 1073741905, 0, 2, 38, 165]
+[:key_down_raw, 1073741905, 0, 2, 39, 167]
+[:key_down_raw, 1073741905, 0, 2, 40, 169]
+[:key_down_raw, 1073741905, 0, 2, 41, 171]
+[:key_up_raw, 1073741905, 0, 2, 42, 171]
+[:key_down_raw, 1073741904, 0, 2, 43, 175]
+[:key_down_raw, 1073741904, 0, 2, 44, 190]
+[:key_down_raw, 1073741904, 0, 2, 45, 192]
+[:key_down_raw, 1073741904, 0, 2, 46, 194]
+[:key_down_raw, 1073741904, 0, 2, 47, 196]
+[:key_down_raw, 1073741904, 0, 2, 48, 198]
+[:key_down_raw, 1073741904, 0, 2, 49, 200]
+[:key_down_raw, 1073741904, 0, 2, 50, 202]
+[:key_down_raw, 1073741904, 0, 2, 51, 204]
+[:key_down_raw, 1073741904, 0, 2, 52, 206]
+[:key_down_raw, 1073741904, 0, 2, 53, 208]
+[:key_down_raw, 1073741904, 0, 2, 54, 210]
+[:key_down_raw, 1073741904, 0, 2, 55, 212]
+[:key_down_raw, 1073741903, 0, 2, 56, 214]
+[:key_down_raw, 1073741903, 0, 2, 57, 229]
+[:key_down_raw, 1073741903, 0, 2, 58, 231]
+[:key_down_raw, 1073741903, 0, 2, 59, 233]
+[:key_down_raw, 1073741906, 0, 2, 60, 234]
+[:key_up_raw, 1073741904, 0, 2, 61, 238]
+[:key_down_raw, 1073741906, 0, 2, 62, 249]
+[:key_down_raw, 1073741906, 0, 2, 63, 251]
+[:key_down_raw, 1073741906, 0, 2, 64, 253]
+[:key_down_raw, 1073741906, 0, 2, 65, 255]
+[:key_down_raw, 1073741906, 0, 2, 66, 257]
+[:key_down_raw, 1073741906, 0, 2, 67, 259]
+[:key_down_raw, 1073741906, 0, 2, 68, 261]
+[:key_down_raw, 1073741906, 0, 2, 69, 263]
+[:key_down_raw, 1073741906, 0, 2, 70, 265]
+[:key_down_raw, 1073741906, 0, 2, 71, 267]
+[:key_down_raw, 1073741906, 0, 2, 72, 269]
+[:key_down_raw, 1073741906, 0, 2, 73, 271]
+[:key_down_raw, 1073741906, 0, 2, 74, 273]
+[:key_down_raw, 1073741906, 0, 2, 75, 275]
+[:key_down_raw, 1073741906, 0, 2, 76, 277]
+[:key_down_raw, 1073741906, 0, 2, 77, 279]
+[:key_down_raw, 1073741906, 0, 2, 78, 281]
+[:key_down_raw, 1073741906, 0, 2, 79, 283]
+[:key_down_raw, 1073741906, 0, 2, 80, 285]
+[:key_down_raw, 1073741906, 0, 2, 81, 287]
+[:key_down_raw, 1073741906, 0, 2, 82, 289]
+[:key_down_raw, 1073741906, 0, 2, 83, 291]
+[:key_down_raw, 1073741906, 0, 2, 84, 293]
+[:key_down_raw, 1073741906, 0, 2, 85, 295]
+[:key_down_raw, 1073741906, 0, 2, 86, 297]
+[:key_down_raw, 1073741906, 0, 2, 87, 299]
+[:key_down_raw, 1073741906, 0, 2, 88, 301]
+[:key_down_raw, 1073741905, 0, 2, 89, 301]
+[:key_up_raw, 1073741906, 0, 2, 90, 310]
+[:key_up_raw, 1073741903, 0, 2, 91, 310]
+[:key_down_raw, 1073741904, 0, 2, 92, 316]
+[:key_down_raw, 1073741904, 0, 2, 93, 331]
+[:key_down_raw, 1073741904, 0, 2, 94, 333]
+[:key_down_raw, 1073741904, 0, 2, 95, 335]
+[:key_down_raw, 1073741904, 0, 2, 96, 337]
+[:key_down_raw, 1073741904, 0, 2, 97, 339]
+[:key_down_raw, 1073741904, 0, 2, 98, 341]
+[:key_down_raw, 1073741904, 0, 2, 99, 343]
+[:key_down_raw, 1073741904, 0, 2, 100, 345]
+[:key_down_raw, 1073741904, 0, 2, 101, 347]
+[:key_down_raw, 1073741904, 0, 2, 102, 349]
+[:key_down_raw, 1073741904, 0, 2, 103, 351]
+[:key_down_raw, 1073741904, 0, 2, 104, 353]
+[:key_down_raw, 1073741904, 0, 2, 105, 355]
+[:key_down_raw, 1073741904, 0, 2, 106, 357]
+[:key_down_raw, 1073741904, 0, 2, 107, 359]
+[:key_down_raw, 1073741904, 0, 2, 108, 361]
+[:key_up_raw, 1073741905, 0, 2, 109, 363]
+[:key_down_raw, 1073741904, 0, 2, 110, 363]
+[:key_down_raw, 1073741904, 0, 2, 111, 365]
+[:key_down_raw, 1073741904, 0, 2, 112, 367]
+[:key_down_raw, 1073741904, 0, 2, 113, 369]
+[:key_down_raw, 1073741904, 0, 2, 114, 371]
+[:key_down_raw, 1073741904, 0, 2, 115, 373]
+[:key_down_raw, 1073741904, 0, 2, 116, 375]
+[:key_down_raw, 1073741904, 0, 2, 117, 377]
+[:key_down_raw, 1073741904, 0, 2, 118, 379]
+[:key_down_raw, 1073741904, 0, 2, 119, 381]
+[:key_down_raw, 1073741904, 0, 2, 120, 383]
+[:key_down_raw, 1073741904, 0, 2, 121, 385]
+[:key_down_raw, 1073741904, 0, 2, 122, 387]
+[:key_down_raw, 1073741904, 0, 2, 123, 389]
+[:key_down_raw, 1073741904, 0, 2, 124, 391]
+[:key_down_raw, 1073741904, 0, 2, 125, 393]
+[:key_down_raw, 1073741904, 0, 2, 126, 395]
+[:key_down_raw, 1073741904, 0, 2, 127, 397]
+[:key_up_raw, 1073741904, 0, 2, 128, 399]
+[:key_down_raw, 1073741903, 0, 2, 129, 400]
+[:key_down_raw, 1073741903, 0, 2, 130, 415]
+[:key_down_raw, 1073741903, 0, 2, 131, 417]
+[:key_down_raw, 1073741903, 0, 2, 132, 419]
+[:key_down_raw, 1073741903, 0, 2, 133, 421]
+[:key_down_raw, 1073741903, 0, 2, 134, 423]
+[:key_down_raw, 1073741903, 0, 2, 135, 425]
+[:key_down_raw, 1073741903, 0, 2, 136, 427]
+[:key_down_raw, 1073741903, 0, 2, 137, 429]
+[:key_down_raw, 1073741903, 0, 2, 138, 431]
+[:key_down_raw, 1073741903, 0, 2, 139, 433]
+[:key_down_raw, 1073741903, 0, 2, 140, 435]
+[:key_down_raw, 1073741903, 0, 2, 141, 437]
+[:key_down_raw, 1073741903, 0, 2, 142, 439]
+[:key_down_raw, 1073741903, 0, 2, 143, 441]
+[:key_down_raw, 1073741903, 0, 2, 144, 443]
+[:key_down_raw, 1073741903, 0, 2, 145, 445]
+[:key_down_raw, 1073741903, 0, 2, 146, 447]
+[:key_down_raw, 1073741903, 0, 2, 147, 449]
+[:key_down_raw, 1073741903, 0, 2, 148, 451]
+[:key_down_raw, 1073741903, 0, 2, 149, 453]
+[:key_down_raw, 1073741903, 0, 2, 150, 455]
+[:key_down_raw, 1073741903, 0, 2, 151, 457]
+[:key_down_raw, 1073741903, 0, 2, 152, 459]
+[:key_down_raw, 1073741903, 0, 2, 153, 461]
+[:key_down_raw, 1073741903, 0, 2, 154, 463]
+[:key_down_raw, 1073741903, 0, 2, 155, 465]
+[:key_down_raw, 1073741903, 0, 2, 156, 467]
+[:key_down_raw, 1073741903, 0, 2, 157, 469]
+[:key_down_raw, 1073741903, 0, 2, 158, 471]
+[:key_down_raw, 1073741903, 0, 2, 159, 473]
+[:key_down_raw, 1073741903, 0, 2, 160, 475]
+[:key_down_raw, 1073741903, 0, 2, 161, 477]
+[:key_down_raw, 1073741903, 0, 2, 162, 479]
+[:key_down_raw, 1073741903, 0, 2, 163, 481]
+[:key_down_raw, 1073741903, 0, 2, 164, 483]
+[:key_down_raw, 1073741903, 0, 2, 165, 485]
+[:key_down_raw, 1073741903, 0, 2, 166, 487]
+[:key_down_raw, 1073741903, 0, 2, 167, 489]
+[:key_down_raw, 1073741903, 0, 2, 168, 491]
+[:key_down_raw, 1073741903, 0, 2, 169, 493]
+[:key_down_raw, 1073741903, 0, 2, 170, 495]
+[:key_down_raw, 1073741903, 0, 2, 171, 497]
+[:key_down_raw, 1073741905, 0, 2, 172, 498]
+[:key_down_raw, 1073741905, 0, 2, 173, 513]
+[:key_down_raw, 1073741905, 0, 2, 174, 515]
+[:key_down_raw, 1073741905, 0, 2, 175, 517]
+[:key_down_raw, 1073741905, 0, 2, 176, 519]
+[:key_down_raw, 1073741905, 0, 2, 177, 521]
+[:key_down_raw, 1073741905, 0, 2, 178, 523]
+[:key_down_raw, 1073741905, 0, 2, 179, 525]
+[:key_down_raw, 1073741905, 0, 2, 180, 527]
+[:key_down_raw, 1073741905, 0, 2, 181, 529]
+[:key_down_raw, 1073741905, 0, 2, 182, 531]
+[:key_down_raw, 1073741905, 0, 2, 183, 533]
+[:key_down_raw, 1073741905, 0, 2, 184, 535]
+[:key_down_raw, 1073741905, 0, 2, 185, 537]
+[:key_down_raw, 1073741905, 0, 2, 186, 539]
+[:key_down_raw, 1073741905, 0, 2, 187, 541]
+[:key_down_raw, 1073741905, 0, 2, 188, 543]
+[:key_up_raw, 1073741905, 0, 2, 189, 543]
+[:key_up_raw, 1073741903, 0, 2, 190, 544]
+[:key_down_raw, 1073741906, 0, 2, 191, 547]
+[:key_down_raw, 1073741906, 0, 2, 192, 562]
+[:key_down_raw, 1073741906, 0, 2, 193, 564]
+[:key_down_raw, 1073741906, 0, 2, 194, 566]
+[:key_down_raw, 1073741906, 0, 2, 195, 568]
+[:key_down_raw, 1073741906, 0, 2, 196, 570]
+[:key_down_raw, 1073741906, 0, 2, 197, 572]
+[:key_down_raw, 1073741906, 0, 2, 198, 574]
+[:key_down_raw, 1073741906, 0, 2, 199, 576]
+[:key_down_raw, 1073741906, 0, 2, 200, 578]
+[:key_down_raw, 1073741906, 0, 2, 201, 580]
+[:key_down_raw, 1073741906, 0, 2, 202, 582]
+[:key_down_raw, 1073741906, 0, 2, 203, 584]
+[:key_down_raw, 1073741906, 0, 2, 204, 586]
+[:key_down_raw, 1073741906, 0, 2, 205, 588]
+[:key_down_raw, 1073741906, 0, 2, 206, 590]
+[:key_down_raw, 1073741906, 0, 2, 207, 592]
+[:key_down_raw, 1073741906, 0, 2, 208, 594]
+[:key_down_raw, 1073741906, 0, 2, 209, 596]
+[:key_down_raw, 1073741906, 0, 2, 210, 598]
+[:key_down_raw, 1073741906, 0, 2, 211, 600]
+[:key_down_raw, 1073741906, 0, 2, 212, 602]
+[:key_down_raw, 1073741906, 0, 2, 213, 604]
+[:key_down_raw, 1073741906, 0, 2, 214, 606]
+[:key_down_raw, 1073741906, 0, 2, 215, 608]
+[:key_down_raw, 1073741906, 0, 2, 216, 610]
+[:key_down_raw, 1073741906, 0, 2, 217, 612]
+[:key_down_raw, 1073741906, 0, 2, 218, 614]
+[:key_down_raw, 1073741906, 0, 2, 219, 616]
+[:key_down_raw, 1073741906, 0, 2, 220, 618]
+[:key_down_raw, 1073741906, 0, 2, 221, 620]
+[:key_down_raw, 1073741906, 0, 2, 222, 622]
+[:key_down_raw, 1073741906, 0, 2, 223, 624]
+[:key_down_raw, 1073741906, 0, 2, 224, 626]
+[:key_down_raw, 1073741906, 0, 2, 225, 628]
+[:key_down_raw, 1073741906, 0, 2, 226, 630]
+[:key_down_raw, 1073741906, 0, 2, 227, 632]
+[:key_down_raw, 1073741906, 0, 2, 228, 634]
+[:key_up_raw, 1073741906, 0, 2, 229, 634]
+[:key_down_raw, 96, 0, 2, 230, 648]
+[:key_up_raw, 96, 0, 2, 231, 652]
+[:mouse_move, 800, 84, 2, 232, 674]
+[:mouse_move, 782, 88, 2, 233, 675]
+[:mouse_move, 764, 94, 2, 234, 676]
+[:mouse_move, 760, 94, 2, 235, 677]
+[:mouse_move, 761, 94, 2, 236, 679]
+[:mouse_move, 762, 93, 2, 237, 680]
+[:key_down_raw, 13, 0, 2, 238, 706]
diff --git a/samples/99_genre_3d/03_yaw_pitch_roll/app/main.rb b/samples/99_genre_3d/03_yaw_pitch_roll/app/main.rb
new file mode 100644
index 0000000..52b5962
--- /dev/null
+++ b/samples/99_genre_3d/03_yaw_pitch_roll/app/main.rb
@@ -0,0 +1,351 @@
+class Game
+ attr_gtk
+
+ def tick
+ defaults
+ render
+ input
+ end
+
+ def matrix_mul m, v
+ (hmap x: ((m.x.x * v.x) + (m.x.y * v.y) + (m.x.z * v.z) + (m.x.w * v.w)),
+ y: ((m.y.x * v.x) + (m.y.y * v.y) + (m.y.z * v.z) + (m.y.w * v.w)),
+ z: ((m.z.x * v.x) + (m.z.y * v.y) + (m.z.z * v.z) + (m.z.w * v.w)),
+ w: ((m.w.x * v.x) + (m.w.y * v.y) + (m.w.z * v.z) + (m.w.w * v.w)))
+ end
+
+ def player_ship
+ [
+ # engine back
+ { x: -1, y: -1, z: 1, w: 0 },
+ { x: -1, y: 1, z: 1, w: 0 },
+
+ { x: -1, y: 1, z: 1, w: 0 },
+ { x: 1, y: 1, z: 1, w: 0 },
+
+ { x: 1, y: 1, z: 1, w: 0 },
+ { x: 1, y: -1, z: 1, w: 0 },
+
+ { x: 1, y: -1, z: 1, w: 0 },
+ { x: -1, y: -1, z: 1, w: 0 },
+
+ # engine front
+ { x: -1, y: -1, z: -1, w: 0 },
+ { x: -1, y: 1, z: -1, w: 0 },
+
+ { x: -1, y: 1, z: -1, w: 0 },
+ { x: 1, y: 1, z: -1, w: 0 },
+
+ { x: 1, y: 1, z: -1, w: 0 },
+ { x: 1, y: -1, z: -1, w: 0 },
+
+ { x: 1, y: -1, z: -1, w: 0 },
+ { x: -1, y: -1, z: -1, w: 0 },
+
+ # engine left
+ { x: -1, z: -1, y: -1, w: 0 },
+ { x: -1, z: -1, y: 1, w: 0 },
+
+ { x: -1, z: -1, y: 1, w: 0 },
+ { x: -1, z: 1, y: 1, w: 0 },
+
+ { x: -1, z: 1, y: 1, w: 0 },
+ { x: -1, z: 1, y: -1, w: 0 },
+
+ { x: -1, z: 1, y: -1, w: 0 },
+ { x: -1, z: -1, y: -1, w: 0 },
+
+ # engine right
+ { x: 1, z: -1, y: -1, w: 0 },
+ { x: 1, z: -1, y: 1, w: 0 },
+
+ { x: 1, z: -1, y: 1, w: 0 },
+ { x: 1, z: 1, y: 1, w: 0 },
+
+ { x: 1, z: 1, y: 1, w: 0 },
+ { x: 1, z: 1, y: -1, w: 0 },
+
+ { x: 1, z: 1, y: -1, w: 0 },
+ { x: 1, z: -1, y: -1, w: 0 },
+
+ # top front of engine to front of ship
+ { x: 1, y: 1, z: 1, w: 0 },
+ { x: 0, y: -1, z: 9, w: 0 },
+
+ { x: 0, y: -1, z: 9, w: 0 },
+ { x: -1, y: 1, z: 1, w: 0 },
+
+ # bottom front of engine
+ { x: 1, y: -1, z: 1, w: 0 },
+ { x: 0, y: -1, z: 9, w: 0 },
+
+ { x: -1, y: -1, z: 1, w: 0 },
+ { x: 0, y: -1, z: 9, w: 0 },
+
+ # right wing
+ # front of wing
+ { x: 1, y: 0.10, z: 1, w: 0 },
+ { x: 9, y: 0.10, z: -1, w: 0 },
+
+ { x: 9, y: 0.10, z: -1, w: 0 },
+ { x: 10, y: 0.10, z: -2, w: 0 },
+
+ # back of wing
+ { x: 1, y: 0.10, z: -1, w: 0 },
+ { x: 9, y: 0.10, z: -1, w: 0 },
+
+ { x: 10, y: 0.10, z: -2, w: 0 },
+ { x: 8, y: 0.10, z: -1, w: 0 },
+
+ # front of wing
+ { x: 1, y: -0.10, z: 1, w: 0 },
+ { x: 9, y: -0.10, z: -1, w: 0 },
+
+ { x: 9, y: -0.10, z: -1, w: 0 },
+ { x: 10, y: -0.10, z: -2, w: 0 },
+
+ # back of wing
+ { x: 1, y: -0.10, z: -1, w: 0 },
+ { x: 9, y: -0.10, z: -1, w: 0 },
+
+ { x: 10, y: -0.10, z: -2, w: 0 },
+ { x: 8, y: -0.10, z: -1, w: 0 },
+
+ # left wing
+ # front of wing
+ { x: -1, y: 0.10, z: 1, w: 0 },
+ { x: -9, y: 0.10, z: -1, w: 0 },
+
+ { x: -9, y: 0.10, z: -1, w: 0 },
+ { x: -10, y: 0.10, z: -2, w: 0 },
+
+ # back of wing
+ { x: -1, y: 0.10, z: -1, w: 0 },
+ { x: -9, y: 0.10, z: -1, w: 0 },
+
+ { x: -10, y: 0.10, z: -2, w: 0 },
+ { x: -8, y: 0.10, z: -1, w: 0 },
+
+ # front of wing
+ { x: -1, y: -0.10, z: 1, w: 0 },
+ { x: -9, y: -0.10, z: -1, w: 0 },
+
+ { x: -9, y: -0.10, z: -1, w: 0 },
+ { x: -10, y: -0.10, z: -2, w: 0 },
+
+ # back of wing
+ { x: -1, y: -0.10, z: -1, w: 0 },
+ { x: -9, y: -0.10, z: -1, w: 0 },
+
+ { x: -10, y: -0.10, z: -2, w: 0 },
+ { x: -8, y: -0.10, z: -1, w: 0 },
+
+ # left fin
+ # top
+ { x: -1, y: 0.10, z: 1, w: 0 },
+ { x: -1, y: 3, z: -3, w: 0 },
+
+ { x: -1, y: 0.10, z: -1, w: 0 },
+ { x: -1, y: 3, z: -3, w: 0 },
+
+ { x: -1.1, y: 0.10, z: 1, w: 0 },
+ { x: -1.1, y: 3, z: -3, w: 0 },
+
+ { x: -1.1, y: 0.10, z: -1, w: 0 },
+ { x: -1.1, y: 3, z: -3, w: 0 },
+
+ # bottom
+ { x: -1, y: -0.10, z: 1, w: 0 },
+ { x: -1, y: -2, z: -2, w: 0 },
+
+ { x: -1, y: -0.10, z: -1, w: 0 },
+ { x: -1, y: -2, z: -2, w: 0 },
+
+ { x: -1.1, y: -0.10, z: 1, w: 0 },
+ { x: -1.1, y: -2, z: -2, w: 0 },
+
+ { x: -1.1, y: -0.10, z: -1, w: 0 },
+ { x: -1.1, y: -2, z: -2, w: 0 },
+
+ # right fin
+ { x: 1, y: 0.10, z: 1, w: 0 },
+ { x: 1, y: 3, z: -3, w: 0 },
+
+ { x: 1, y: 0.10, z: -1, w: 0 },
+ { x: 1, y: 3, z: -3, w: 0 },
+
+ { x: 1.1, y: 0.10, z: 1, w: 0 },
+ { x: 1.1, y: 3, z: -3, w: 0 },
+
+ { x: 1.1, y: 0.10, z: -1, w: 0 },
+ { x: 1.1, y: 3, z: -3, w: 0 },
+
+ # bottom
+ { x: 1, y: -0.10, z: 1, w: 0 },
+ { x: 1, y: -2, z: -2, w: 0 },
+
+ { x: 1, y: -0.10, z: -1, w: 0 },
+ { x: 1, y: -2, z: -2, w: 0 },
+
+ { x: 1.1, y: -0.10, z: 1, w: 0 },
+ { x: 1.1, y: -2, z: -2, w: 0 },
+
+ { x: 1.1, y: -0.10, z: -1, w: 0 },
+ { x: 1.1, y: -2, z: -2, w: 0 },
+ ]
+ end
+
+ def defaults
+ state.points ||= player_ship
+ state.shifted_points ||= state.points.map { |point| point }
+
+ state.scale ||= 1
+ state.angle_x ||= 0
+ state.angle_y ||= 0
+ state.angle_z ||= 0
+ end
+
+ def matrix_new x0, y0, z0, w0, x1, y1, z1, w1, x2, y2, z2, w2, x3, y3, z3, w3
+ (hmap x: (hmap x: x0, y: y0, z: z0, w: w0),
+ y: (hmap x: x1, y: y1, z: z1, w: w1),
+ z: (hmap x: x2, y: y2, z: z2, w: w2),
+ w: (hmap x: x3, y: y3, z: z3, w: w3))
+ end
+
+ def angle_z_matrix degrees
+ cos_t = Math.cos degrees.to_radians
+ sin_t = Math.sin degrees.to_radians
+ (matrix_new cos_t, -sin_t, 0, 0,
+ sin_t, cos_t, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1)
+ end
+
+ def angle_y_matrix degrees
+ cos_t = Math.cos degrees.to_radians
+ sin_t = Math.sin degrees.to_radians
+ (matrix_new cos_t, 0, sin_t, 0,
+ 0, 1, 0, 0,
+ -sin_t, 0, cos_t, 0,
+ 0, 0, 0, 1)
+ end
+
+ def angle_x_matrix degrees
+ cos_t = Math.cos degrees.to_radians
+ sin_t = Math.sin degrees.to_radians
+ (matrix_new 1, 0, 0, 0,
+ 0, cos_t, -sin_t, 0,
+ 0, sin_t, cos_t, 0,
+ 0, 0, 0, 1)
+ end
+
+ def scale_matrix factor
+ (matrix_new factor, 0, 0, 0,
+ 0, factor, 0, 0,
+ 0, 0, factor, 0,
+ 0, 0, 0, 1)
+ end
+
+ def input
+ if (inputs.keyboard.shift && inputs.keyboard.p)
+ state.scale -= 0.1
+ elsif inputs.keyboard.p
+ state.scale += 0.1
+ end
+
+ if inputs.mouse.wheel
+ state.scale += inputs.mouse.wheel.y
+ end
+
+ state.scale = state.scale.clamp(0.1, 1000)
+
+ if (inputs.keyboard.shift && inputs.keyboard.y) || inputs.keyboard.right
+ state.angle_y += 1
+ elsif (inputs.keyboard.y) || inputs.keyboard.left
+ state.angle_y -= 1
+ end
+
+ if (inputs.keyboard.shift && inputs.keyboard.x) || inputs.keyboard.down
+ state.angle_x -= 1
+ elsif (inputs.keyboard.x || inputs.keyboard.up)
+ state.angle_x += 1
+ end
+
+ if inputs.keyboard.shift && inputs.keyboard.z
+ state.angle_z += 1
+ elsif inputs.keyboard.z
+ state.angle_z -= 1
+ end
+
+ if inputs.keyboard.zero
+ state.angle_x = 0
+ state.angle_y = 0
+ state.angle_z = 0
+ end
+
+ angle_x = state.angle_x
+ angle_y = state.angle_y
+ angle_z = state.angle_z
+ scale = state.scale
+
+ s_matrix = scale_matrix state.scale
+ x_matrix = angle_z_matrix angle_z
+ y_matrix = angle_y_matrix angle_y
+ z_matrix = angle_x_matrix angle_x
+
+ state.shifted_points = state.points.map do |point|
+ (matrix_mul s_matrix,
+ (matrix_mul z_matrix,
+ (matrix_mul x_matrix,
+ (matrix_mul y_matrix, point)))).merge(original: point)
+ end
+ end
+
+ def thick_line line
+ [
+ line.merge(y: line.y - 1, y2: line.y2 - 1, r: 0, g: 0, b: 0),
+ line.merge(x: line.x - 1, x2: line.x2 - 1, r: 0, g: 0, b: 0),
+ line.merge(x: line.x - 0, x2: line.x2 - 0, r: 0, g: 0, b: 0),
+ line.merge(y: line.y + 1, y2: line.y2 + 1, r: 0, g: 0, b: 0),
+ line.merge(x: line.x + 1, x2: line.x2 + 1, r: 0, g: 0, b: 0)
+ ]
+ end
+
+ def render
+ outputs.lines << state.shifted_points.each_slice(2).map do |(p1, p2)|
+ perc = 0
+ thick_line({ x: p1.x.*(10) + 640, y: p1.y.*(10) + 320,
+ x2: p2.x.*(10) + 640, y2: p2.y.*(10) + 320,
+ r: 255 * perc,
+ g: 255 * perc,
+ b: 255 * perc })
+ end
+
+ outputs.labels << [ 10, 700, "angle_x: #{state.angle_x.to_sf}", 0]
+ outputs.labels << [ 10, 670, "x, shift+x", 0]
+
+ outputs.labels << [210, 700, "angle_y: #{state.angle_y.to_sf}", 0]
+ outputs.labels << [210, 670, "y, shift+y", 0]
+
+ outputs.labels << [410, 700, "angle_z: #{state.angle_z.to_sf}", 0]
+ outputs.labels << [410, 670, "z, shift+z", 0]
+
+ outputs.labels << [610, 700, "scale: #{state.scale.to_sf}", 0]
+ outputs.labels << [610, 670, "p, shift+p", 0]
+ end
+end
+
+$game = Game.new
+
+def tick args
+ $game.args = args
+ $game.tick
+end
+
+def set_angles x, y, z
+ $game.state.angle_x = x
+ $game.state.angle_y = y
+ $game.state.angle_z = z
+end
+
+$gtk.reset
diff --git a/samples/99_genre_3d/03_yaw_pitch_roll/replay.txt b/samples/99_genre_3d/03_yaw_pitch_roll/replay.txt
new file mode 100644
index 0000000..918fc9e
--- /dev/null
+++ b/samples/99_genre_3d/03_yaw_pitch_roll/replay.txt
@@ -0,0 +1,361 @@
+replay_version 2.0
+stopped_at 493
+seed 100
+recorded_at 2021-10-18 16:32:03 -0500
+[:mouse_button_up, 1, 0, 1, 1, 1]
+[:mouse_move, 813, 82, 2, 2, 9]
+[:mouse_move, 813, 83, 2, 3, 17]
+[:mouse_move, 812, 84, 2, 4, 17]
+[:mouse_move, 809, 86, 2, 5, 17]
+[:mouse_move, 803, 91, 2, 6, 18]
+[:mouse_move, 795, 96, 2, 7, 18]
+[:mouse_move, 792, 98, 2, 8, 19]
+[:mouse_move, 791, 106, 2, 9, 19]
+[:mouse_move, 791, 120, 2, 10, 19]
+[:mouse_move, 791, 138, 2, 11, 20]
+[:mouse_move, 794, 157, 2, 12, 20]
+[:mouse_move, 795, 175, 2, 13, 21]
+[:mouse_move, 795, 193, 2, 14, 21]
+[:mouse_move, 795, 211, 2, 15, 21]
+[:mouse_move, 795, 225, 2, 16, 22]
+[:mouse_move, 795, 233, 2, 17, 22]
+[:mouse_move, 795, 236, 2, 18, 23]
+[:mouse_move, 795, 237, 2, 19, 23]
+[:mouse_move, 795, 238, 2, 20, 24]
+[:mouse_move, 795, 239, 2, 21, 24]
+[:mouse_move, 795, 240, 2, 22, 25]
+[:mouse_move, 794, 241, 2, 23, 26]
+[:mouse_button_pressed, 1, 0, 1, 24, 29]
+[:mouse_button_up, 1, 0, 1, 25, 31]
+[:key_down_raw, 120, 0, 2, 26, 49]
+[:key_down_raw, 120, 0, 2, 27, 55]
+[:key_down_raw, 120, 0, 2, 28, 56]
+[:key_down_raw, 120, 0, 2, 29, 56]
+[:key_down_raw, 120, 0, 2, 30, 57]
+[:key_down_raw, 120, 0, 2, 31, 58]
+[:key_down_raw, 120, 0, 2, 32, 59]
+[:key_down_raw, 120, 0, 2, 33, 60]
+[:key_down_raw, 120, 0, 2, 34, 60]
+[:key_down_raw, 120, 0, 2, 35, 61]
+[:key_down_raw, 120, 0, 2, 36, 62]
+[:key_down_raw, 120, 0, 2, 37, 63]
+[:key_down_raw, 120, 0, 2, 38, 64]
+[:key_down_raw, 120, 0, 2, 39, 65]
+[:key_down_raw, 120, 0, 2, 40, 66]
+[:key_down_raw, 120, 0, 2, 41, 66]
+[:key_down_raw, 120, 0, 2, 42, 67]
+[:key_down_raw, 120, 0, 2, 43, 68]
+[:key_down_raw, 120, 0, 2, 44, 69]
+[:key_down_raw, 120, 0, 2, 45, 70]
+[:key_down_raw, 120, 0, 2, 46, 70]
+[:key_down_raw, 120, 0, 2, 47, 71]
+[:key_down_raw, 120, 0, 2, 48, 72]
+[:key_down_raw, 120, 0, 2, 49, 73]
+[:key_down_raw, 120, 0, 2, 50, 74]
+[:key_down_raw, 120, 0, 2, 51, 75]
+[:key_up_raw, 120, 0, 2, 52, 75]
+[:key_down_raw, 1073742053, 2, 2, 53, 81]
+[:key_down_raw, 120, 2, 2, 54, 83]
+[:key_down_raw, 120, 2, 2, 55, 89]
+[:key_down_raw, 120, 2, 2, 56, 90]
+[:key_down_raw, 120, 2, 2, 57, 91]
+[:key_down_raw, 120, 2, 2, 58, 92]
+[:key_down_raw, 120, 2, 2, 59, 93]
+[:key_down_raw, 120, 2, 2, 60, 93]
+[:key_down_raw, 120, 2, 2, 61, 94]
+[:key_down_raw, 120, 2, 2, 62, 95]
+[:key_down_raw, 120, 2, 2, 63, 96]
+[:key_down_raw, 120, 2, 2, 64, 97]
+[:key_down_raw, 120, 2, 2, 65, 97]
+[:key_down_raw, 120, 2, 2, 66, 98]
+[:key_down_raw, 120, 2, 2, 67, 99]
+[:key_down_raw, 120, 2, 2, 68, 100]
+[:key_down_raw, 120, 2, 2, 69, 101]
+[:key_down_raw, 120, 2, 2, 70, 102]
+[:key_down_raw, 120, 2, 2, 71, 102]
+[:key_down_raw, 120, 2, 2, 72, 103]
+[:key_down_raw, 120, 2, 2, 73, 104]
+[:key_down_raw, 120, 2, 2, 74, 105]
+[:key_down_raw, 120, 2, 2, 75, 106]
+[:key_down_raw, 120, 2, 2, 76, 107]
+[:key_down_raw, 120, 2, 2, 77, 107]
+[:key_down_raw, 120, 2, 2, 78, 108]
+[:key_down_raw, 120, 2, 2, 79, 109]
+[:key_down_raw, 120, 2, 2, 80, 110]
+[:key_down_raw, 120, 2, 2, 81, 111]
+[:key_down_raw, 120, 2, 2, 82, 111]
+[:key_down_raw, 120, 2, 2, 83, 112]
+[:key_down_raw, 120, 2, 2, 84, 113]
+[:key_down_raw, 120, 2, 2, 85, 114]
+[:key_down_raw, 120, 2, 2, 86, 115]
+[:key_down_raw, 120, 2, 2, 87, 116]
+[:key_down_raw, 120, 2, 2, 88, 117]
+[:key_down_raw, 120, 2, 2, 89, 117]
+[:key_down_raw, 120, 2, 2, 90, 118]
+[:key_down_raw, 120, 2, 2, 91, 119]
+[:key_down_raw, 120, 2, 2, 92, 120]
+[:key_down_raw, 120, 2, 2, 93, 121]
+[:key_down_raw, 120, 2, 2, 94, 122]
+[:key_down_raw, 120, 2, 2, 95, 122]
+[:key_down_raw, 120, 2, 2, 96, 123]
+[:key_down_raw, 120, 2, 2, 97, 124]
+[:key_down_raw, 120, 2, 2, 98, 125]
+[:key_down_raw, 120, 2, 2, 99, 126]
+[:key_down_raw, 120, 2, 2, 100, 127]
+[:key_down_raw, 120, 2, 2, 101, 127]
+[:key_down_raw, 120, 2, 2, 102, 128]
+[:key_down_raw, 120, 2, 2, 103, 129]
+[:key_down_raw, 120, 2, 2, 104, 130]
+[:key_down_raw, 120, 2, 2, 105, 131]
+[:key_down_raw, 120, 2, 2, 106, 131]
+[:key_down_raw, 120, 2, 2, 107, 132]
+[:key_down_raw, 120, 2, 2, 108, 133]
+[:key_down_raw, 120, 2, 2, 109, 134]
+[:key_down_raw, 120, 2, 2, 110, 135]
+[:key_down_raw, 120, 2, 2, 111, 136]
+[:key_down_raw, 120, 2, 2, 112, 136]
+[:key_down_raw, 120, 2, 2, 113, 137]
+[:key_down_raw, 120, 2, 2, 114, 138]
+[:key_down_raw, 120, 2, 2, 115, 139]
+[:key_down_raw, 120, 2, 2, 116, 140]
+[:key_down_raw, 120, 2, 2, 117, 140]
+[:key_down_raw, 120, 2, 2, 118, 141]
+[:key_down_raw, 120, 2, 2, 119, 142]
+[:key_down_raw, 120, 2, 2, 120, 143]
+[:key_down_raw, 120, 2, 2, 121, 144]
+[:key_up_raw, 1073742053, 0, 2, 122, 144]
+[:key_down_raw, 120, 0, 2, 123, 145]
+[:key_up_raw, 120, 0, 2, 124, 145]
+[:key_down_raw, 121, 0, 2, 125, 158]
+[:key_down_raw, 121, 0, 2, 126, 165]
+[:key_down_raw, 121, 0, 2, 127, 166]
+[:key_down_raw, 121, 0, 2, 128, 166]
+[:key_down_raw, 121, 0, 2, 129, 167]
+[:key_down_raw, 121, 0, 2, 130, 168]
+[:key_down_raw, 121, 0, 2, 131, 169]
+[:key_down_raw, 121, 0, 2, 132, 170]
+[:key_down_raw, 121, 0, 2, 133, 171]
+[:key_down_raw, 121, 0, 2, 134, 171]
+[:key_down_raw, 121, 0, 2, 135, 172]
+[:key_down_raw, 121, 0, 2, 136, 173]
+[:key_down_raw, 121, 0, 2, 137, 174]
+[:key_down_raw, 121, 0, 2, 138, 175]
+[:key_down_raw, 121, 0, 2, 139, 175]
+[:key_down_raw, 121, 0, 2, 140, 176]
+[:key_down_raw, 121, 0, 2, 141, 177]
+[:key_down_raw, 121, 0, 2, 142, 178]
+[:key_down_raw, 121, 0, 2, 143, 179]
+[:key_down_raw, 121, 0, 2, 144, 180]
+[:key_down_raw, 121, 0, 2, 145, 180]
+[:key_down_raw, 121, 0, 2, 146, 181]
+[:key_down_raw, 121, 0, 2, 147, 182]
+[:key_down_raw, 121, 0, 2, 148, 183]
+[:key_down_raw, 121, 0, 2, 149, 184]
+[:key_down_raw, 121, 0, 2, 150, 185]
+[:key_down_raw, 121, 0, 2, 151, 185]
+[:key_down_raw, 121, 0, 2, 152, 186]
+[:key_down_raw, 121, 0, 2, 153, 187]
+[:key_down_raw, 121, 0, 2, 154, 188]
+[:key_down_raw, 121, 0, 2, 155, 189]
+[:key_down_raw, 121, 0, 2, 156, 190]
+[:key_down_raw, 121, 0, 2, 157, 190]
+[:key_up_raw, 121, 0, 2, 158, 191]
+[:key_down_raw, 1073742053, 2, 2, 159, 198]
+[:key_down_raw, 121, 2, 2, 160, 203]
+[:key_down_raw, 121, 2, 2, 161, 209]
+[:key_down_raw, 121, 2, 2, 162, 210]
+[:key_down_raw, 121, 2, 2, 163, 211]
+[:key_down_raw, 121, 2, 2, 164, 212]
+[:key_down_raw, 121, 2, 2, 165, 213]
+[:key_down_raw, 121, 2, 2, 166, 213]
+[:key_down_raw, 121, 2, 2, 167, 214]
+[:key_down_raw, 121, 2, 2, 168, 215]
+[:key_down_raw, 121, 2, 2, 169, 216]
+[:key_down_raw, 121, 2, 2, 170, 217]
+[:key_down_raw, 121, 2, 2, 171, 217]
+[:key_down_raw, 121, 2, 2, 172, 219]
+[:key_down_raw, 121, 2, 2, 173, 220]
+[:key_down_raw, 121, 2, 2, 174, 220]
+[:key_down_raw, 121, 2, 2, 175, 221]
+[:key_down_raw, 121, 2, 2, 176, 222]
+[:key_down_raw, 121, 2, 2, 177, 223]
+[:key_down_raw, 121, 2, 2, 178, 224]
+[:key_down_raw, 121, 2, 2, 179, 224]
+[:key_down_raw, 121, 2, 2, 180, 225]
+[:key_down_raw, 121, 2, 2, 181, 226]
+[:key_down_raw, 121, 2, 2, 182, 227]
+[:key_down_raw, 121, 2, 2, 183, 228]
+[:key_down_raw, 121, 2, 2, 184, 229]
+[:key_down_raw, 121, 2, 2, 185, 229]
+[:key_down_raw, 121, 2, 2, 186, 230]
+[:key_down_raw, 121, 2, 2, 187, 231]
+[:key_down_raw, 121, 2, 2, 188, 232]
+[:key_down_raw, 121, 2, 2, 189, 233]
+[:key_down_raw, 121, 2, 2, 190, 233]
+[:key_down_raw, 121, 2, 2, 191, 234]
+[:key_down_raw, 121, 2, 2, 192, 235]
+[:key_down_raw, 121, 2, 2, 193, 236]
+[:key_down_raw, 121, 2, 2, 194, 237]
+[:key_down_raw, 121, 2, 2, 195, 238]
+[:key_down_raw, 121, 2, 2, 196, 238]
+[:key_down_raw, 121, 2, 2, 197, 239]
+[:key_down_raw, 121, 2, 2, 198, 240]
+[:key_down_raw, 121, 2, 2, 199, 241]
+[:key_down_raw, 121, 2, 2, 200, 242]
+[:key_down_raw, 121, 2, 2, 201, 242]
+[:key_down_raw, 121, 2, 2, 202, 243]
+[:key_down_raw, 121, 2, 2, 203, 244]
+[:key_down_raw, 121, 2, 2, 204, 245]
+[:key_down_raw, 121, 2, 2, 205, 246]
+[:key_down_raw, 121, 2, 2, 206, 247]
+[:key_down_raw, 121, 2, 2, 207, 247]
+[:key_down_raw, 121, 2, 2, 208, 248]
+[:key_down_raw, 121, 2, 2, 209, 249]
+[:key_down_raw, 121, 2, 2, 210, 250]
+[:key_down_raw, 121, 2, 2, 211, 251]
+[:key_down_raw, 121, 2, 2, 212, 251]
+[:key_down_raw, 121, 2, 2, 213, 252]
+[:key_down_raw, 121, 2, 2, 214, 253]
+[:key_down_raw, 121, 2, 2, 215, 254]
+[:key_down_raw, 121, 2, 2, 216, 255]
+[:key_down_raw, 121, 2, 2, 217, 255]
+[:key_down_raw, 121, 2, 2, 218, 256]
+[:key_down_raw, 121, 2, 2, 219, 257]
+[:key_down_raw, 121, 2, 2, 220, 258]
+[:key_down_raw, 121, 2, 2, 221, 259]
+[:key_down_raw, 121, 2, 2, 222, 260]
+[:key_down_raw, 121, 2, 2, 223, 260]
+[:key_down_raw, 121, 2, 2, 224, 261]
+[:key_down_raw, 121, 2, 2, 225, 262]
+[:key_down_raw, 121, 2, 2, 226, 263]
+[:key_up_raw, 121, 2, 2, 227, 263]
+[:key_up_raw, 1073742053, 0, 2, 228, 266]
+[:key_down_raw, 122, 0, 2, 229, 270]
+[:key_up_raw, 122, 0, 2, 230, 272]
+[:key_down_raw, 122, 0, 2, 231, 289]
+[:key_down_raw, 122, 0, 2, 232, 295]
+[:key_down_raw, 122, 0, 2, 233, 296]
+[:key_down_raw, 122, 0, 2, 234, 297]
+[:key_down_raw, 122, 0, 2, 235, 297]
+[:key_down_raw, 122, 0, 2, 236, 298]
+[:key_down_raw, 122, 0, 2, 237, 299]
+[:key_down_raw, 122, 0, 2, 238, 300]
+[:key_down_raw, 122, 0, 2, 239, 301]
+[:key_down_raw, 122, 0, 2, 240, 302]
+[:key_down_raw, 122, 0, 2, 241, 302]
+[:key_down_raw, 122, 0, 2, 242, 303]
+[:key_down_raw, 122, 0, 2, 243, 304]
+[:key_down_raw, 122, 0, 2, 244, 305]
+[:key_down_raw, 122, 0, 2, 245, 306]
+[:key_down_raw, 122, 0, 2, 246, 306]
+[:key_down_raw, 122, 0, 2, 247, 307]
+[:key_down_raw, 122, 0, 2, 248, 308]
+[:key_down_raw, 122, 0, 2, 249, 309]
+[:key_down_raw, 122, 0, 2, 250, 310]
+[:key_up_raw, 122, 0, 2, 251, 310]
+[:key_down_raw, 1073742053, 2, 2, 252, 319]
+[:key_down_raw, 122, 2, 2, 253, 322]
+[:key_down_raw, 122, 2, 2, 254, 328]
+[:key_down_raw, 122, 2, 2, 255, 329]
+[:key_down_raw, 122, 2, 2, 256, 330]
+[:key_down_raw, 122, 2, 2, 257, 331]
+[:key_down_raw, 122, 2, 2, 258, 332]
+[:key_down_raw, 122, 2, 2, 259, 333]
+[:key_down_raw, 122, 2, 2, 260, 333]
+[:key_down_raw, 122, 2, 2, 261, 334]
+[:key_down_raw, 122, 2, 2, 262, 335]
+[:key_down_raw, 122, 2, 2, 263, 336]
+[:key_down_raw, 122, 2, 2, 264, 337]
+[:key_down_raw, 122, 2, 2, 265, 338]
+[:key_down_raw, 122, 2, 2, 266, 339]
+[:key_down_raw, 122, 2, 2, 267, 340]
+[:key_down_raw, 122, 2, 2, 268, 341]
+[:key_down_raw, 122, 2, 2, 269, 341]
+[:key_down_raw, 122, 2, 2, 270, 342]
+[:key_down_raw, 122, 2, 2, 271, 343]
+[:key_down_raw, 122, 2, 2, 272, 344]
+[:key_down_raw, 122, 2, 2, 273, 345]
+[:key_down_raw, 122, 2, 2, 274, 346]
+[:key_down_raw, 122, 2, 2, 275, 346]
+[:key_down_raw, 122, 2, 2, 276, 347]
+[:key_down_raw, 122, 2, 2, 277, 348]
+[:key_down_raw, 122, 2, 2, 278, 349]
+[:key_down_raw, 122, 2, 2, 279, 350]
+[:key_down_raw, 122, 2, 2, 280, 350]
+[:key_down_raw, 122, 2, 2, 281, 351]
+[:key_down_raw, 122, 2, 2, 282, 352]
+[:key_down_raw, 122, 2, 2, 283, 353]
+[:key_down_raw, 122, 2, 2, 284, 354]
+[:key_down_raw, 122, 2, 2, 285, 355]
+[:key_down_raw, 122, 2, 2, 286, 355]
+[:key_down_raw, 122, 2, 2, 287, 356]
+[:key_down_raw, 122, 2, 2, 288, 357]
+[:key_down_raw, 122, 2, 2, 289, 358]
+[:key_down_raw, 122, 2, 2, 290, 359]
+[:key_down_raw, 122, 2, 2, 291, 360]
+[:key_down_raw, 122, 2, 2, 292, 360]
+[:key_down_raw, 122, 2, 2, 293, 361]
+[:key_down_raw, 122, 2, 2, 294, 362]
+[:key_down_raw, 122, 2, 2, 295, 363]
+[:key_up_raw, 122, 2, 2, 296, 363]
+[:key_up_raw, 1073742053, 0, 2, 297, 366]
+[:key_down_raw, 112, 0, 2, 298, 370]
+[:key_down_raw, 112, 0, 2, 299, 376]
+[:key_down_raw, 112, 0, 2, 300, 377]
+[:key_down_raw, 112, 0, 2, 301, 378]
+[:key_down_raw, 112, 0, 2, 302, 379]
+[:key_down_raw, 112, 0, 2, 303, 380]
+[:key_down_raw, 112, 0, 2, 304, 381]
+[:key_down_raw, 112, 0, 2, 305, 381]
+[:key_down_raw, 112, 0, 2, 306, 382]
+[:key_down_raw, 112, 0, 2, 307, 383]
+[:key_down_raw, 112, 0, 2, 308, 384]
+[:key_down_raw, 112, 0, 2, 309, 385]
+[:key_down_raw, 112, 0, 2, 310, 386]
+[:key_down_raw, 112, 0, 2, 311, 386]
+[:key_down_raw, 112, 0, 2, 312, 387]
+[:key_down_raw, 112, 0, 2, 313, 388]
+[:key_down_raw, 112, 0, 2, 314, 389]
+[:key_down_raw, 112, 0, 2, 315, 390]
+[:key_down_raw, 112, 0, 2, 316, 391]
+[:key_down_raw, 112, 0, 2, 317, 391]
+[:key_down_raw, 112, 0, 2, 318, 392]
+[:key_down_raw, 112, 0, 2, 319, 393]
+[:key_down_raw, 112, 0, 2, 320, 394]
+[:key_down_raw, 112, 0, 2, 321, 395]
+[:key_up_raw, 112, 0, 2, 322, 395]
+[:key_down_raw, 1073742049, 1, 2, 323, 402]
+[:key_down_raw, 112, 1, 2, 324, 402]
+[:key_down_raw, 112, 1, 2, 325, 409]
+[:key_down_raw, 112, 1, 2, 326, 410]
+[:key_down_raw, 112, 1, 2, 327, 410]
+[:key_down_raw, 112, 1, 2, 328, 411]
+[:key_down_raw, 112, 1, 2, 329, 412]
+[:key_down_raw, 112, 1, 2, 330, 413]
+[:key_down_raw, 112, 1, 2, 331, 414]
+[:key_down_raw, 112, 1, 2, 332, 415]
+[:key_down_raw, 112, 1, 2, 333, 415]
+[:key_down_raw, 112, 1, 2, 334, 416]
+[:key_down_raw, 112, 1, 2, 335, 417]
+[:key_down_raw, 112, 1, 2, 336, 418]
+[:key_down_raw, 112, 1, 2, 337, 419]
+[:key_down_raw, 112, 1, 2, 338, 420]
+[:key_down_raw, 112, 1, 2, 339, 420]
+[:key_down_raw, 112, 1, 2, 340, 421]
+[:key_down_raw, 112, 1, 2, 341, 422]
+[:key_down_raw, 112, 1, 2, 342, 423]
+[:key_down_raw, 112, 1, 2, 343, 424]
+[:key_down_raw, 112, 1, 2, 344, 424]
+[:key_down_raw, 112, 1, 2, 345, 425]
+[:key_down_raw, 112, 1, 2, 346, 426]
+[:key_down_raw, 112, 1, 2, 347, 427]
+[:key_down_raw, 112, 1, 2, 348, 428]
+[:key_down_raw, 112, 1, 2, 349, 429]
+[:key_down_raw, 112, 1, 2, 350, 429]
+[:key_down_raw, 112, 1, 2, 351, 430]
+[:key_down_raw, 112, 1, 2, 352, 431]
+[:key_up_raw, 112, 1, 2, 353, 432]
+[:key_up_raw, 1073742049, 0, 2, 354, 433]
+[:key_down_raw, 96, 0, 2, 355, 439]
+[:key_up_raw, 96, 0, 2, 356, 441]
+[:key_down_raw, 13, 0, 2, 357, 493]
diff --git a/samples/99_genre_3d/3d_cube/app/main.rb b/samples/99_genre_3d/3d_cube/app/main.rb
deleted file mode 100644
index fc95291..0000000
--- a/samples/99_genre_3d/3d_cube/app/main.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-STARTX = 0.0
-STARTY = 0.0
-ENDY = 20.0
-ENDX = 20.0
-SPINPOINT = 10
-SPINDURATION = 400
-POINTSIZE = 8
-BOXDEPTH = 40
-YAW = 1
-DISTANCE = 10
-
-def tick args
- args.outputs.background_color = [0, 0, 0]
- a = Math.sin(args.state.tick_count / SPINDURATION) * Math.tan(args.state.tick_count / SPINDURATION)
- s = Math.sin(a)
- c = Math.cos(a)
- x = STARTX
- y = STARTY
- offset_x = (1280 - (ENDX - STARTX)) / 2
- offset_y = (360 - (ENDY - STARTY)) / 2
-
- srand(1)
- while y < ENDY do
- while x < ENDX do
- if (y == STARTY ||
- y == (ENDY / 0.5) * 2 ||
- y == (ENDY / 0.5) * 2 + 0.5 ||
- y == ENDY - 0.5 ||
- x == STARTX ||
- x == ENDX - 0.5)
- z = rand(BOXDEPTH)
- z *= Math.sin(a / 2)
- x -= SPINPOINT
- u = (x * c) - (z * s)
- v = (x * s) + (z * c)
- k = DISTANCE.fdiv(100) + (v / 500 * YAW)
- u = u / k
- v = y / k
- w = POINTSIZE / 10 / k
- args.outputs.sprites << { x: offset_x + u - w, y: offset_y + v - w, w: w, h: w, path: 'sprites/square-blue.png'}
- x += SPINPOINT
- end
- x += 0.5
- end
- y += 0.5
- x = STARTX
- end
-end
-
-$gtk.reset
diff --git a/samples/99_genre_arcade/bullet_hell/replay.txt b/samples/99_genre_arcade/bullet_hell/replay.txt
new file mode 100644
index 0000000..49a22d1
--- /dev/null
+++ b/samples/99_genre_arcade/bullet_hell/replay.txt
@@ -0,0 +1,126 @@
+replay_version 2.0
+stopped_at 718
+seed 100
+recorded_at 2021-11-20 11:26:42 -0600
+[:mouse_button_up, 1, 0, 1, 1, 4]
+[:mouse_move, 824, 91, 2, 2, 27]
+[:key_down_raw, 1073741903, 0, 2, 3, 64]
+[:key_down_raw, 1073741903, 0, 2, 4, 78]
+[:key_down_raw, 1073741903, 0, 2, 5, 80]
+[:key_down_raw, 1073741903, 0, 2, 6, 82]
+[:key_down_raw, 1073741903, 0, 2, 7, 84]
+[:key_down_raw, 1073741903, 0, 2, 8, 86]
+[:key_down_raw, 1073741903, 0, 2, 9, 88]
+[:key_down_raw, 1073741903, 0, 2, 10, 90]
+[:key_down_raw, 1073741903, 0, 2, 11, 92]
+[:key_down_raw, 1073741903, 0, 2, 12, 94]
+[:key_down_raw, 1073741903, 0, 2, 13, 96]
+[:key_down_raw, 1073741903, 0, 2, 14, 98]
+[:key_down_raw, 1073741903, 0, 2, 15, 100]
+[:key_down_raw, 1073741903, 0, 2, 16, 102]
+[:key_down_raw, 1073741903, 0, 2, 17, 104]
+[:key_down_raw, 1073741903, 0, 2, 18, 106]
+[:key_down_raw, 1073741903, 0, 2, 19, 108]
+[:key_down_raw, 32, 0, 2, 20, 108]
+[:key_up_raw, 1073741903, 0, 2, 21, 108]
+[:key_up_raw, 32, 0, 2, 22, 114]
+[:key_down_raw, 32, 0, 2, 23, 120]
+[:key_up_raw, 32, 0, 2, 24, 126]
+[:key_down_raw, 1073741903, 0, 2, 25, 127]
+[:key_down_raw, 1073741903, 0, 2, 26, 142]
+[:key_up_raw, 1073741903, 0, 2, 27, 143]
+[:key_down_raw, 32, 0, 2, 28, 144]
+[:key_up_raw, 32, 0, 2, 29, 152]
+[:key_down_raw, 32, 0, 2, 30, 156]
+[:key_down_raw, 1073741904, 0, 2, 31, 159]
+[:key_up_raw, 32, 0, 2, 32, 163]
+[:key_down_raw, 1073741904, 0, 2, 33, 174]
+[:key_down_raw, 1073741904, 0, 2, 34, 176]
+[:key_down_raw, 1073741904, 0, 2, 35, 178]
+[:key_down_raw, 1073741904, 0, 2, 36, 180]
+[:key_down_raw, 1073741904, 0, 2, 37, 182]
+[:key_down_raw, 32, 0, 2, 38, 183]
+[:key_up_raw, 1073741904, 0, 2, 39, 186]
+[:key_up_raw, 32, 0, 2, 40, 191]
+[:key_down_raw, 32, 0, 2, 41, 195]
+[:key_up_raw, 32, 0, 2, 42, 203]
+[:key_down_raw, 1073741904, 0, 2, 43, 228]
+[:key_down_raw, 1073741904, 0, 2, 44, 243]
+[:key_down_raw, 1073741904, 0, 2, 45, 245]
+[:key_down_raw, 1073741904, 0, 2, 46, 247]
+[:key_down_raw, 1073741904, 0, 2, 47, 249]
+[:key_down_raw, 1073741904, 0, 2, 48, 251]
+[:key_down_raw, 1073741904, 0, 2, 49, 253]
+[:key_down_raw, 32, 0, 2, 50, 253]
+[:key_up_raw, 1073741904, 0, 2, 51, 255]
+[:key_up_raw, 32, 0, 2, 52, 260]
+[:key_down_raw, 32, 0, 2, 53, 265]
+[:key_up_raw, 32, 0, 2, 54, 270]
+[:key_down_raw, 1073741904, 0, 2, 55, 278]
+[:key_down_raw, 1073741904, 0, 2, 56, 293]
+[:key_down_raw, 1073741904, 0, 2, 57, 295]
+[:key_down_raw, 1073741904, 0, 2, 58, 297]
+[:key_down_raw, 1073741904, 0, 2, 59, 299]
+[:key_down_raw, 1073741904, 0, 2, 60, 301]
+[:key_down_raw, 1073741904, 0, 2, 61, 303]
+[:key_up_raw, 1073741904, 0, 2, 62, 305]
+[:key_down_raw, 32, 0, 2, 63, 307]
+[:key_up_raw, 32, 0, 2, 64, 314]
+[:key_down_raw, 32, 0, 2, 65, 319]
+[:key_up_raw, 32, 0, 2, 66, 326]
+[:key_down_raw, 32, 0, 2, 67, 331]
+[:key_up_raw, 32, 0, 2, 68, 337]
+[:key_down_raw, 1073741904, 0, 2, 69, 339]
+[:key_down_raw, 1073741904, 0, 2, 70, 354]
+[:key_down_raw, 1073741904, 0, 2, 71, 356]
+[:key_down_raw, 1073741904, 0, 2, 72, 358]
+[:key_down_raw, 1073741904, 0, 2, 73, 360]
+[:key_down_raw, 32, 0, 2, 74, 361]
+[:key_up_raw, 1073741904, 0, 2, 75, 361]
+[:key_up_raw, 32, 0, 2, 76, 368]
+[:key_down_raw, 32, 0, 2, 77, 373]
+[:key_up_raw, 32, 0, 2, 78, 379]
+[:key_down_raw, 1073741903, 0, 2, 79, 397]
+[:key_down_raw, 1073741903, 0, 2, 80, 412]
+[:key_down_raw, 1073741903, 0, 2, 81, 414]
+[:key_down_raw, 1073741903, 0, 2, 82, 416]
+[:key_down_raw, 1073741903, 0, 2, 83, 418]
+[:key_down_raw, 1073741903, 0, 2, 84, 420]
+[:key_down_raw, 1073741903, 0, 2, 85, 422]
+[:key_down_raw, 1073741903, 0, 2, 86, 424]
+[:key_down_raw, 1073741903, 0, 2, 87, 426]
+[:key_down_raw, 1073741903, 0, 2, 88, 428]
+[:key_down_raw, 32, 0, 2, 89, 428]
+[:key_up_raw, 1073741903, 0, 2, 90, 429]
+[:key_up_raw, 32, 0, 2, 91, 435]
+[:key_down_raw, 1073741903, 0, 2, 92, 456]
+[:key_down_raw, 32, 0, 2, 93, 468]
+[:key_up_raw, 1073741903, 0, 2, 94, 468]
+[:key_up_raw, 32, 0, 2, 95, 475]
+[:key_down_raw, 32, 0, 2, 96, 480]
+[:key_up_raw, 32, 0, 2, 97, 487]
+[:key_down_raw, 32, 0, 2, 98, 493]
+[:key_up_raw, 32, 0, 2, 99, 499]
+[:key_down_raw, 1073741903, 0, 2, 100, 516]
+[:key_down_raw, 32, 0, 2, 101, 522]
+[:key_up_raw, 32, 0, 2, 102, 529]
+[:key_up_raw, 1073741903, 0, 2, 103, 529]
+[:key_down_raw, 32, 0, 2, 104, 535]
+[:key_up_raw, 32, 0, 2, 105, 542]
+[:key_down_raw, 1073741903, 0, 2, 106, 582]
+[:key_up_raw, 1073741903, 0, 2, 107, 591]
+[:key_down_raw, 96, 0, 2, 108, 652]
+[:mouse_move, 824, 90, 2, 109, 656]
+[:key_up_raw, 96, 0, 2, 110, 658]
+[:mouse_move, 833, 91, 2, 111, 684]
+[:mouse_move, 852, 92, 2, 112, 685]
+[:mouse_move, 873, 95, 2, 113, 686]
+[:mouse_move, 895, 98, 2, 114, 687]
+[:mouse_move, 914, 101, 2, 115, 688]
+[:mouse_move, 921, 102, 2, 116, 689]
+[:mouse_move, 922, 102, 2, 117, 690]
+[:mouse_move, 913, 106, 2, 118, 692]
+[:mouse_move, 902, 110, 2, 119, 693]
+[:mouse_move, 892, 114, 2, 120, 694]
+[:mouse_move, 890, 114, 2, 121, 695]
+[:key_down_raw, 13, 0, 2, 122, 718]
diff --git a/samples/99_genre_arcade/flappy_dragon/app/main.rb b/samples/99_genre_arcade/flappy_dragon/app/main.rb
index 56ce3ec..7ddc5a0 100644
--- a/samples/99_genre_arcade/flappy_dragon/app/main.rb
+++ b/samples/99_genre_arcade/flappy_dragon/app/main.rb
@@ -38,31 +38,36 @@ class FlappyDragon
end
def render_score
- outputs.primitives << [10, 710, "HI SCORE: #{state.hi_score}", large_white_typeset].label
- outputs.primitives << [10, 680, "SCORE: #{state.score}", large_white_typeset].label
- outputs.primitives << [10, 650, "DIFFICULTY: #{state.difficulty.upcase}", large_white_typeset].label
+ outputs.primitives << { x: 10, y: 710, text: "HI SCORE: #{state.hi_score}", **large_white_typeset }
+ outputs.primitives << { x: 10, y: 680, text: "SCORE: #{state.score}", **large_white_typeset }
+ outputs.primitives << { x: 10, y: 650, text: "DIFFICULTY: #{state.difficulty.upcase}", **large_white_typeset }
end
def render_menu
return unless state.scene == :menu
render_overlay
- outputs.labels << [640, 700, "Flappy Dragon", 50, 1, 255, 255, 255]
- outputs.labels << [640, 500, "Instructions: Press Spacebar to flap. Don't die.", 4, 1, 255, 255, 255]
- outputs.labels << [430, 430, "[Tab] Change difficulty", 4, 0, 255, 255, 255]
- outputs.labels << [430, 400, "[Enter] Start at New Difficulty ", 4, 0, 255, 255, 255]
- outputs.labels << [430, 370, "[Escape] Cancel/Resume ", 4, 0, 255, 255, 255]
- outputs.labels << [640, 300, "(mouse, touch, and game controllers work, too!) ", 4, 1, 255, 255, 255]
- outputs.labels << [640, 200, "Difficulty: #{state.new_difficulty.capitalize}", 4, 1, 255, 255, 255]
-
- outputs.labels << [10, 100, "Code: @amirrajan", 255, 255, 255]
- outputs.labels << [10, 80, "Art: @mobypixel", 255, 255, 255]
- outputs.labels << [10, 60, "Music: @mobypixel", 255, 255, 255]
- outputs.labels << [10, 40, "Engine: DragonRuby GTK", 255, 255, 255]
+ outputs.labels << { x: 640, y: 700, text: "Flappy Dragon", size_enum: 50, alignment_enum: 1, **white }
+ outputs.labels << { x: 640, y: 500, text: "Instructions: Press Spacebar to flap. Don't die.", size_enum: 4, alignment_enum: 1, **white }
+ outputs.labels << { x: 430, y: 430, text: "[Tab] Change difficulty", size_enum: 4, alignment_enum: 0, **white }
+ outputs.labels << { x: 430, y: 400, text: "[Enter] Start at New Difficulty ", size_enum: 4, alignment_enum: 0, **white }
+ outputs.labels << { x: 430, y: 370, text: "[Escape] Cancel/Resume ", size_enum: 4, alignment_enum: 0, **white }
+ outputs.labels << { x: 640, y: 300, text: "(mouse, touch, and game controllers work, too!) ", size_enum: 4, alignment_enum: 1, **white }
+ outputs.labels << { x: 640, y: 200, text: "Difficulty: #{state.new_difficulty.capitalize}", size_enum: 4, alignment_enum: 1, **white }
+
+ outputs.labels << { x: 10, y: 100, text: "Code: @amirrajan", **white }
+ outputs.labels << { x: 10, y: 80, text: "Art: @mobypixel", **white }
+ outputs.labels << { x: 10, y: 60, text: "Music: @mobypixel", **white }
+ outputs.labels << { x: 10, y: 40, text: "Engine: DragonRuby GTK", **white }
end
def render_overlay
- outputs.primitives << [grid.rect.scale_rect(1.1, 0, 0), 0, 0, 0, 230].solid
+ overlay_rect = grid.rect.scale_rect(1.1, 0, 0)
+ outputs.primitives << { x: overlay_rect.x,
+ y: overlay_rect.y,
+ w: overlay_rect.w,
+ h: overlay_rect.h,
+ r: 0, g: 0, b: 0, a: 230 }.solid!
end
def render_game
@@ -75,14 +80,14 @@ class FlappyDragon
def render_game_over
return unless state.scene == :game
- outputs.labels << [638, 358, score_text, 20, 1]
- outputs.labels << [635, 360, score_text, 20, 1, 255, 255, 255]
- outputs.labels << [638, 428, countdown_text, 20, 1]
- outputs.labels << [635, 430, countdown_text, 20, 1, 255, 255, 255]
+ outputs.labels << { x: 638, y: 358, text: score_text, size_enum: 20, alignment_enum: 1 }
+ outputs.labels << { x: 635, y: 360, text: score_text, size_enum: 20, alignment_enum: 1, r: 255, g: 255, b: 255 }
+ outputs.labels << { x: 638, y: 428, text: countdown_text, size_enum: 20, alignment_enum: 1 }
+ outputs.labels << { x: 635, y: 430, text: countdown_text, size_enum: 20, alignment_enum: 1, r: 255, g: 255, b: 255 }
end
def render_background
- outputs.sprites << [0, 0, 1280, 720, 'sprites/background.png']
+ outputs.sprites << { x: 0, y: 0, w: 1280, h: 720, path: 'sprites/background.png' }
scroll_point_at = state.tick_count
scroll_point_at = state.scene_at if state.scene == :menu
@@ -94,11 +99,18 @@ class FlappyDragon
outputs.sprites << scrolling_background(scroll_point_at, 'sprites/parallax_front.png', 1.00, -80)
end
+ def scrolling_background at, path, rate, y = 0
+ [
+ { x: 0 - at.*(rate) % 1440, y: y, w: 1440, h: 720, path: path },
+ { x: 1440 - at.*(rate) % 1440, y: y, w: 1440, h: 720, path: path }
+ ]
+ end
+
def render_walls
state.walls.each do |w|
w.sprites = [
- [w.x, w.bottom_height - 720, 100, 720, 'sprites/wall.png', 180],
- [w.x, w.top_y, 100, 720, 'sprites/wallbottom.png', 0]
+ { x: w.x, y: w.bottom_height - 720, w: 100, h: 720, path: 'sprites/wall.png', angle: 180 },
+ { x: w.x, y: w.top_y, w: 100, h: 720, path: 'sprites/wallbottom.png', angle: 0 }
]
end
outputs.sprites << state.walls.map(&:sprites)
@@ -107,15 +119,13 @@ class FlappyDragon
def render_dragon
state.show_death = true if state.countdown == 3.seconds
- render_debug_hitbox false
-
if state.show_death == false || !state.death_at
animation_index = state.flapped_at.frame_index 6, 2, false if state.flapped_at
sprite_name = "sprites/dragon_fly#{animation_index.or(0) + 1}.png"
- state.dragon_sprite = [state.x, state.y, 100, 80, sprite_name, state.dy * 1.2]
+ state.dragon_sprite = { x: state.x, y: state.y, w: 100, h: 80, path: sprite_name, angle: state.dy * 1.2 }
else
sprite_name = "sprites/dragon_die.png"
- state.dragon_sprite = [state.x, state.y, 100, 80, sprite_name, state.dy * 1.2]
+ state.dragon_sprite = { x: state.x, y: state.y, w: 100, h: 80, path: sprite_name, angle: state.dy * 1.2 }
sprite_changed_elapsed = state.death_at.elapsed_time - 1.seconds
state.dragon_sprite.angle += (sprite_changed_elapsed ** 1.3) * state.death_fall_direction * -1
state.dragon_sprite.x += (sprite_changed_elapsed ** 1.2) * state.death_fall_direction
@@ -125,20 +135,12 @@ class FlappyDragon
outputs.sprites << state.dragon_sprite
end
- def render_debug_hitbox show
- return unless show
- outputs.borders << [dragon_collision_box.rect, 255, 0, 0] if state.dragon_sprite
- outputs.borders << state.walls.flat_map do |w|
- w.sprites.map { |s| [s.rect, 255, 0, 0] }
- end
- end
-
def render_flash
return unless state.flash_at
- outputs.primitives << [grid.rect,
- white,
- 255 * state.flash_at.ease(20, :flip)].solid
+ outputs.primitives << { **grid.rect.to_hash,
+ **white,
+ a: 255 * state.flash_at.ease(20, :flip) }.solid!
state.flash_at = 0 if state.flash_at.elapsed_time > 20
end
@@ -258,19 +260,12 @@ class FlappyDragon
end
end
- def scrolling_background at, path, rate, y = 0
- [
- [ 0 - at.*(rate) % 1440, y, 1440, 720, path],
- [1440 - at.*(rate) % 1440, y, 1440, 720, path]
- ]
- end
-
def white
- [255, 255, 255]
+ { r: 255, g: 255, b: 255 }
end
def large_white_typeset
- [5, 0, 255, 255, 255]
+ { size_enum: 5, alignment_enum: 0, r: 255, g: 255, b: 255 }
end
def at_beginning?
@@ -279,9 +274,9 @@ class FlappyDragon
def dragon_collision_box
state.dragon_sprite
- .scale_rect(1.0 - collision_forgiveness, 0.5, 0.5)
- .rect_shift_right(10)
- .rect_shift_up(state.dy * 2)
+ .scale_rect(1.0 - collision_forgiveness, 0.5, 0.5)
+ .rect_shift_right(10)
+ .rect_shift_up(state.dy * 2)
end
def game_over?
@@ -290,7 +285,7 @@ class FlappyDragon
state.walls
.flat_map { |w| w.sprites }
.any? do |s|
- s.intersect_rect?(dragon_collision_box)
+ s && s.intersect_rect?(dragon_collision_box)
end
end
diff --git a/samples/99_genre_arcade/twinstick/replay.txt b/samples/99_genre_arcade/twinstick/replay.txt
new file mode 100644
index 0000000..e05480f
--- /dev/null
+++ b/samples/99_genre_arcade/twinstick/replay.txt
@@ -0,0 +1,174 @@
+replay_version 2.0
+stopped_at 819
+seed 100
+recorded_at 2021-11-20 11:29:24 -0600
+[:mouse_button_up, 1, 0, 1, 1, 3]
+[:key_down_raw, 1073741903, 0, 2, 2, 89]
+[:key_down_raw, 1073741903, 0, 2, 3, 104]
+[:key_down_raw, 1073741903, 0, 2, 4, 106]
+[:key_down_raw, 1073741903, 0, 2, 5, 108]
+[:key_down_raw, 1073741903, 0, 2, 6, 110]
+[:key_down_raw, 1073741903, 0, 2, 7, 112]
+[:key_down_raw, 1073741903, 0, 2, 8, 114]
+[:key_down_raw, 1073741903, 0, 2, 9, 116]
+[:key_up_raw, 1073741903, 0, 2, 10, 117]
+[:key_down_raw, 115, 0, 2, 11, 121]
+[:key_down_raw, 1073741905, 0, 2, 12, 133]
+[:key_down_raw, 1073741905, 0, 2, 13, 148]
+[:key_down_raw, 1073741905, 0, 2, 14, 150]
+[:key_down_raw, 1073741905, 0, 2, 15, 152]
+[:key_down_raw, 1073741904, 0, 2, 16, 152]
+[:key_up_raw, 1073741904, 0, 2, 17, 158]
+[:key_up_raw, 1073741905, 0, 2, 18, 159]
+[:key_down_raw, 1073741906, 0, 2, 19, 163]
+[:key_down_raw, 1073741903, 0, 2, 20, 178]
+[:key_up_raw, 1073741903, 0, 2, 21, 185]
+[:key_down_raw, 100, 0, 2, 22, 195]
+[:key_up_raw, 1073741906, 0, 2, 23, 195]
+[:key_up_raw, 115, 0, 2, 24, 195]
+[:key_down_raw, 1073741904, 0, 2, 25, 209]
+[:key_down_raw, 1073741904, 0, 2, 26, 224]
+[:key_down_raw, 1073741904, 0, 2, 27, 226]
+[:key_down_raw, 1073741904, 0, 2, 28, 228]
+[:key_down_raw, 1073741904, 0, 2, 29, 230]
+[:key_down_raw, 119, 0, 2, 30, 230]
+[:key_down_raw, 1073741906, 0, 2, 31, 237]
+[:key_up_raw, 100, 0, 2, 32, 251]
+[:key_down_raw, 1073741906, 0, 2, 33, 252]
+[:key_down_raw, 1073741906, 0, 2, 34, 254]
+[:key_down_raw, 1073741906, 0, 2, 35, 256]
+[:key_down_raw, 1073741906, 0, 2, 36, 258]
+[:key_down_raw, 97, 0, 2, 37, 259]
+[:key_up_raw, 119, 0, 2, 38, 267]
+[:key_up_raw, 1073741906, 0, 2, 39, 268]
+[:key_down_raw, 1073741903, 0, 2, 40, 269]
+[:key_up_raw, 1073741904, 0, 2, 41, 270]
+[:key_down_raw, 1073741903, 0, 2, 42, 284]
+[:key_down_raw, 1073741903, 0, 2, 43, 286]
+[:key_down_raw, 1073741903, 0, 2, 44, 288]
+[:key_down_raw, 1073741903, 0, 2, 45, 290]
+[:key_down_raw, 1073741903, 0, 2, 46, 292]
+[:key_down_raw, 1073741903, 0, 2, 47, 294]
+[:key_down_raw, 1073741903, 0, 2, 48, 296]
+[:key_down_raw, 1073741903, 0, 2, 49, 298]
+[:key_down_raw, 1073741903, 0, 2, 50, 300]
+[:key_down_raw, 1073741903, 0, 2, 51, 302]
+[:key_down_raw, 1073741903, 0, 2, 52, 304]
+[:key_down_raw, 119, 0, 2, 53, 304]
+[:key_down_raw, 1073741906, 0, 2, 54, 311]
+[:key_down_raw, 1073741906, 0, 2, 55, 326]
+[:key_down_raw, 1073741906, 0, 2, 56, 328]
+[:key_down_raw, 1073741906, 0, 2, 57, 330]
+[:key_down_raw, 1073741906, 0, 2, 58, 332]
+[:key_down_raw, 1073741906, 0, 2, 59, 334]
+[:key_down_raw, 1073741906, 0, 2, 60, 336]
+[:key_up_raw, 1073741903, 0, 2, 61, 336]
+[:key_down_raw, 1073741906, 0, 2, 62, 338]
+[:key_down_raw, 1073741906, 0, 2, 63, 340]
+[:key_down_raw, 1073741906, 0, 2, 64, 342]
+[:key_down_raw, 1073741906, 0, 2, 65, 344]
+[:key_up_raw, 119, 0, 2, 66, 344]
+[:key_down_raw, 1073741906, 0, 2, 67, 346]
+[:key_up_raw, 1073741906, 0, 2, 68, 347]
+[:key_down_raw, 1073741903, 0, 2, 69, 347]
+[:key_down_raw, 115, 0, 2, 70, 353]
+[:key_down_raw, 1073741906, 0, 2, 71, 355]
+[:key_up_raw, 97, 0, 2, 72, 356]
+[:key_up_raw, 1073741903, 0, 2, 73, 360]
+[:key_down_raw, 1073741906, 0, 2, 74, 370]
+[:key_down_raw, 1073741906, 0, 2, 75, 372]
+[:key_down_raw, 1073741906, 0, 2, 76, 374]
+[:key_down_raw, 1073741906, 0, 2, 77, 376]
+[:key_down_raw, 1073741906, 0, 2, 78, 378]
+[:key_down_raw, 1073741906, 0, 2, 79, 380]
+[:key_down_raw, 97, 0, 2, 80, 381]
+[:key_up_raw, 115, 0, 2, 81, 385]
+[:key_down_raw, 1073741903, 0, 2, 82, 386]
+[:key_up_raw, 1073741906, 0, 2, 83, 391]
+[:key_down_raw, 1073741903, 0, 2, 84, 401]
+[:key_down_raw, 1073741903, 0, 2, 85, 403]
+[:key_down_raw, 1073741903, 0, 2, 86, 405]
+[:key_down_raw, 1073741903, 0, 2, 87, 407]
+[:key_down_raw, 1073741903, 0, 2, 88, 409]
+[:key_down_raw, 1073741903, 0, 2, 89, 411]
+[:key_down_raw, 1073741903, 0, 2, 90, 413]
+[:key_down_raw, 1073741903, 0, 2, 91, 415]
+[:key_down_raw, 1073741903, 0, 2, 92, 417]
+[:key_down_raw, 1073741903, 0, 2, 93, 419]
+[:key_down_raw, 1073741903, 0, 2, 94, 421]
+[:key_down_raw, 1073741903, 0, 2, 95, 423]
+[:key_down_raw, 1073741903, 0, 2, 96, 425]
+[:key_down_raw, 1073741903, 0, 2, 97, 428]
+[:key_down_raw, 1073741903, 0, 2, 98, 430]
+[:key_up_raw, 97, 0, 2, 99, 430]
+[:key_down_raw, 1073741903, 0, 2, 100, 432]
+[:key_down_raw, 1073741903, 0, 2, 101, 434]
+[:key_down_raw, 1073741903, 0, 2, 102, 436]
+[:key_up_raw, 1073741903, 0, 2, 103, 436]
+[:key_down_raw, 100, 0, 2, 104, 447]
+[:key_down_raw, 1073741904, 0, 2, 105, 447]
+[:key_down_raw, 1073741904, 0, 2, 106, 462]
+[:key_down_raw, 1073741904, 0, 2, 107, 464]
+[:key_down_raw, 1073741904, 0, 2, 108, 466]
+[:key_down_raw, 1073741904, 0, 2, 109, 468]
+[:key_down_raw, 1073741904, 0, 2, 110, 470]
+[:key_down_raw, 1073741904, 0, 2, 111, 472]
+[:key_down_raw, 1073741904, 0, 2, 112, 474]
+[:key_down_raw, 1073741904, 0, 2, 113, 476]
+[:key_down_raw, 1073741904, 0, 2, 114, 478]
+[:key_down_raw, 1073741904, 0, 2, 115, 480]
+[:key_down_raw, 1073741904, 0, 2, 116, 482]
+[:key_down_raw, 1073741904, 0, 2, 117, 484]
+[:key_down_raw, 1073741904, 0, 2, 118, 486]
+[:key_down_raw, 1073741904, 0, 2, 119, 488]
+[:key_down_raw, 1073741904, 0, 2, 120, 490]
+[:key_down_raw, 1073741904, 0, 2, 121, 492]
+[:key_down_raw, 1073741904, 0, 2, 122, 494]
+[:key_down_raw, 1073741904, 0, 2, 123, 496]
+[:key_down_raw, 1073741904, 0, 2, 124, 498]
+[:key_down_raw, 1073741904, 0, 2, 125, 500]
+[:key_down_raw, 1073741904, 0, 2, 126, 502]
+[:key_down_raw, 1073741904, 0, 2, 127, 504]
+[:key_down_raw, 1073741904, 0, 2, 128, 506]
+[:key_down_raw, 1073741904, 0, 2, 129, 508]
+[:key_up_raw, 100, 0, 2, 130, 508]
+[:key_down_raw, 1073741904, 0, 2, 131, 510]
+[:key_down_raw, 1073741904, 0, 2, 132, 512]
+[:key_up_raw, 1073741904, 0, 2, 133, 513]
+[:key_down_raw, 1073741906, 0, 2, 134, 569]
+[:key_down_raw, 1073741903, 0, 2, 135, 570]
+[:key_down_raw, 1073741903, 0, 2, 136, 585]
+[:key_down_raw, 1073741903, 0, 2, 137, 587]
+[:key_up_raw, 1073741903, 0, 2, 138, 588]
+[:key_down_raw, 1073741903, 0, 2, 139, 597]
+[:key_up_raw, 1073741906, 0, 2, 140, 600]
+[:key_up_raw, 1073741903, 0, 2, 141, 608]
+[:key_down_raw, 1073741906, 0, 2, 142, 610]
+[:key_up_raw, 1073741906, 0, 2, 143, 615]
+[:key_down_raw, 1073741906, 0, 2, 144, 619]
+[:key_down_raw, 119, 0, 2, 145, 621]
+[:key_up_raw, 1073741906, 0, 2, 146, 623]
+[:key_down_raw, 119, 0, 2, 147, 636]
+[:key_down_raw, 119, 0, 2, 148, 638]
+[:key_down_raw, 119, 0, 2, 149, 640]
+[:key_down_raw, 119, 0, 2, 150, 642]
+[:key_up_raw, 119, 0, 2, 151, 642]
+[:key_down_raw, 100, 0, 2, 152, 653]
+[:key_down_raw, 100, 0, 2, 153, 668]
+[:key_down_raw, 100, 0, 2, 154, 670]
+[:key_down_raw, 100, 0, 2, 155, 672]
+[:key_down_raw, 100, 0, 2, 156, 674]
+[:key_down_raw, 100, 0, 2, 157, 676]
+[:key_down_raw, 100, 0, 2, 158, 678]
+[:key_down_raw, 100, 0, 2, 159, 680]
+[:key_down_raw, 100, 0, 2, 160, 682]
+[:key_down_raw, 100, 0, 2, 161, 684]
+[:key_down_raw, 100, 0, 2, 162, 686]
+[:key_down_raw, 115, 0, 2, 163, 686]
+[:key_up_raw, 100, 0, 2, 164, 697]
+[:key_down_raw, 97, 0, 2, 165, 699]
+[:key_up_raw, 115, 0, 2, 166, 704]
+[:key_up_raw, 97, 0, 2, 167, 714]
+[:key_down_raw, 96, 0, 2, 168, 769]
+[:key_up_raw, 96, 0, 2, 169, 774]
+[:key_down_raw, 13, 0, 2, 170, 819]
diff --git a/samples/99_genre_crafting/farming_game_starting_point/app/main.rb b/samples/99_genre_crafting/farming_game_starting_point/app/main.rb
new file mode 100644
index 0000000..4c7dd61
--- /dev/null
+++ b/samples/99_genre_crafting/farming_game_starting_point/app/main.rb
@@ -0,0 +1,84 @@
+def tick args
+ args.state.tile_size = 80
+ args.state.player_speed = 4
+ args.state.player ||= tile(args, 7, 3, 0, 128, 180)
+ generate_map args
+ #press j to plant a green onion
+ if args.inputs.keyboard.j
+ #change this part you can change what you want to plant
+ args.state.walls << tile(args, ((args.state.player.x+80)/args.state.tile_size), ((args.state.player.y)/args.state.tile_size), 255, 255, 255)
+ args.state.plants << tile(args, ((args.state.player.x+80)/args.state.tile_size), ((args.state.player.y+80)/args.state.tile_size), 0, 160, 0)
+ end
+ # Adds walls, background, and player to args.outputs.solids so they appear on screen
+ args.outputs.solids << [0,0,1280,720, 237,189,101]
+ args.outputs.sprites << [0, 0, 1280, 720, 'sprites/background.png']
+ args.outputs.solids << args.state.walls
+ args.outputs.solids << args.state.player
+ args.outputs.solids << args.state.plants
+ args.outputs.labels << [320, 640, "press J to plant", 3, 1, 255, 0, 0, 200]
+
+ move_player args, -1, 0 if args.inputs.keyboard.left # x position decreases by 1 if left key is pressed
+ move_player args, 1, 0 if args.inputs.keyboard.right # x position increases by 1 if right key is pressed
+ move_player args, 0, 1 if args.inputs.keyboard.up # y position increases by 1 if up is pressed
+ move_player args, 0, -1 if args.inputs.keyboard.down # y position decreases by 1 if down is pressed
+end
+
+# Sets position, size, and color of the tile
+def tile args, x, y, *color
+ [x * args.state.tile_size, # sets definition for array using method parameters
+ y * args.state.tile_size, # multiplying by tile_size sets x and y to correct position using pixel values
+ args.state.tile_size,
+ args.state.tile_size,
+ *color]
+end
+
+# Creates map by adding tiles to the wall, as well as a goal (that the player needs to reach)
+def generate_map args
+ return if args.state.area
+
+ # Creates the area of the map. There are 9 rows running horizontally across the screen
+ # and 16 columns running vertically on the screen. Any spot with a "1" is not
+ # open for the player to move into (and is green), and any spot with a "0" is available
+ # for the player to move in.
+ args.state.area = [
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
+ [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,],
+ [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,],
+ [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,],
+ [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,],
+ [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,],
+ [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,],
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
+ ].reverse # reverses the order of the area collection
+
+ # By reversing the order, the way that the area appears above is how it appears
+ # on the screen in the game. If we did not reverse, the map would appear inverted.
+
+ #The wall starts off with no tiles.
+ args.state.walls = []
+ args.state.plants = []
+
+ # If v is 1, a green tile is added to args.state.walls.
+ # If v is 2, a black tile is created as the goal.
+ args.state.area.map_2d do |y, x, v|
+ if v == 1
+ args.state.walls << tile(args, x, y, 255, 160, 156) # green tile
+ end
+ end
+end
+
+# Allows the player to move their box around the screen
+def move_player args, *vector
+ box = args.state.player.shift_rect(vector) # box is able to move at an angle
+
+ # If the player's box hits a wall, it is not able to move further in that direction
+ return if args.state.walls
+ .any_intersect_rect?(box)
+
+ # Player's box is able to move at angles (not just the four general directions) fast
+ args.state.player =
+ args.state.player
+ .shift_rect(vector.x * args.state.player_speed, # if we don't multiply by speed, then
+ vector.y * args.state.player_speed) # the box will move extremely slow
+end
diff --git a/samples/99_genre_crafting/farming_game_starting_point/app/repl.rb b/samples/99_genre_crafting/farming_game_starting_point/app/repl.rb
new file mode 100644
index 0000000..f4c8292
--- /dev/null
+++ b/samples/99_genre_crafting/farming_game_starting_point/app/repl.rb
@@ -0,0 +1,307 @@
+# ===============================================================
+# Welcome to repl.rb
+# ===============================================================
+# You can experiement with code within this file. Code in this
+# file is only executed when you save (and only excecuted ONCE).
+# ===============================================================
+
+# ===============================================================
+# REMOVE the "x" from the word "xrepl" and save the file to RUN
+# the code in between the do/end block delimiters.
+# ===============================================================
+
+# ===============================================================
+# ADD the "x" to the word "repl" (make it xrepl) and save the
+# file to IGNORE the code in between the do/end block delimiters.
+# ===============================================================
+
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ puts "The result of 1 + 2 is: #{1 + 2}"
+end
+
+# ====================================================================================
+# Ruby Crash Course:
+# Strings, Numeric, Booleans, Conditionals, Looping, Enumerables, Arrays
+# ====================================================================================
+
+# ====================================================================================
+# Strings
+# ====================================================================================
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ message = "Hello World"
+ puts "The value of message is: " + message
+ puts "Any value can be interpolated within a string using \#{}."
+ puts "Interpolated message: #{message}."
+ puts 'This #{message} is not interpolated because the string uses single quotes.'
+end
+
+# ====================================================================================
+# Numerics
+# ====================================================================================
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ a = 10
+ puts "The value of a is: #{a}"
+ puts "a + 1 is: #{a + 1}"
+ puts "a / 3 is: #{a / 3}"
+end
+
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ b = 10.12
+ puts "The value of b is: #{b}"
+ puts "b + 1 is: #{b + 1}"
+ puts "b as an integer is: #{b.to_i}"
+ puts ''
+end
+
+# ====================================================================================
+# Booleans
+# ====================================================================================
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ c = 30
+ puts "The value of c is #{c}."
+
+ if c
+ puts "This if statement ran because c is truthy."
+ end
+end
+
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ d = false
+ puts "The value of d is #{d}."
+
+ if !d
+ puts "This if statement ran because d is falsey, using the not operator (!) makes d evaluate to true."
+ end
+
+ e = nil
+ puts "Nil is also considered falsey. The value of e is: #{e}."
+
+ if !e
+ puts "This if statement ran because e is nil (a falsey value)."
+ end
+end
+
+# ====================================================================================
+# Conditionals
+# ====================================================================================
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ i_am_true = true
+ i_am_nil = nil
+ i_am_false = false
+ i_am_hi = "hi"
+
+ puts "======== if statement"
+ i_am_one = 1
+ if i_am_one
+ puts "This was printed because i_am_one is truthy."
+ end
+
+ puts "======== if/else statement"
+ if i_am_false
+ puts "This will NOT get printed because i_am_false is false."
+ else
+ puts "This was printed because i_am_false is false."
+ end
+
+ puts "======== if/elsif/else statement"
+ if i_am_false
+ puts "This will NOT get printed because i_am_false is false."
+ elsif i_am_true
+ puts "This was printed because i_am_true is true."
+ else
+ puts "This will NOT get printed i_am_true was true."
+ end
+
+ puts "======== case statement "
+ i_am_one = 1
+ case i_am_one
+ when 10
+ puts "case equaled: 10"
+ when 9
+ puts "case equaled: 9"
+ when 5
+ puts "case equaled: 5"
+ when 1
+ puts "case equaled: 1"
+ else
+ puts "Value wasn't cased."
+ end
+
+ puts "======== different types of comparisons"
+ if 4 == 4
+ puts "equal (4 == 4)"
+ end
+
+ if 4 != 3
+ puts "not equal (4 != 3)"
+ end
+
+ if 3 < 4
+ puts "less than (3 < 4)"
+ end
+
+ if 4 > 3
+ puts "greater than (4 > 3)"
+ end
+
+ if ((4 > 3) || (3 < 4) || false)
+ puts "or statement ((4 > 3) || (3 < 4) || false)"
+ end
+
+ if ((4 > 3) && (3 < 4))
+ puts "and statement ((4 > 3) && (3 < 4))"
+ end
+end
+
+# ====================================================================================
+# Looping
+# ====================================================================================
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ puts "======== times block"
+ 3.times do |i|
+ puts i
+ end
+ puts "======== range block exclusive"
+ (0...3).each do |i|
+ puts i
+ end
+ puts "======== range block inclusive"
+ (0..3).each do |i|
+ puts i
+ end
+end
+
+# ====================================================================================
+# Enumerables
+# ====================================================================================
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ puts "======== array each"
+ colors = ["red", "blue", "yellow"]
+ colors.each do |color|
+ puts color
+ end
+
+ puts '======== array each_with_index'
+ colors = ["red", "blue", "yellow"]
+ colors.each_with_index do |color, i|
+ puts "#{color} at index #{i}"
+ end
+end
+
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ puts "======== single parameter function"
+ def add_one_to n
+ n + 5
+ end
+
+ puts add_one_to(3)
+
+ puts "======== function with default value"
+ def function_with_default_value v = 10
+ v * 10
+ end
+
+ puts "passing three: #{function_with_default_value(3)}"
+ puts "passing nil: #{function_with_default_value}"
+
+ puts "======== Or Equal (||=) operator for nil values"
+ def function_with_nil_default_with_local a = nil
+ result = a
+ result ||= "or equal operator was exected and set a default value"
+ end
+
+ puts "passing 'hi': #{function_with_nil_default_with_local 'hi'}"
+ puts "passing nil: #{function_with_nil_default_with_local}"
+end
+
+# ====================================================================================
+# Arrays
+# ====================================================================================
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ puts "======== Create an array with the numbers 1 to 10."
+ one_to_ten = (1..10).to_a
+ puts one_to_ten
+
+ puts "======== Create a new array that only contains even numbers from the previous array."
+ one_to_ten = (1..10).to_a
+ evens = one_to_ten.find_all do |number|
+ number % 2 == 0
+ end
+ puts evens
+
+ puts "======== Create a new array that rejects odd numbers."
+ one_to_ten = (1..10).to_a
+ also_even = one_to_ten.reject do |number|
+ number % 2 != 0
+ end
+ puts also_even
+
+ puts "======== Create an array that doubles every number."
+ one_to_ten = (1..10).to_a
+ doubled = one_to_ten.map do |number|
+ number * 2
+ end
+ puts doubled
+
+ puts "======== Create an array that selects only odd numbers and then multiply those by 10."
+ one_to_ten = (1..10).to_a
+ odd_doubled = one_to_ten.find_all do |number|
+ number % 2 != 0
+ end.map do |odd_number|
+ odd_number * 10
+ end
+ puts odd_doubled
+
+ puts "======== All combination of numbers 1 to 10."
+ one_to_ten = (1..10).to_a
+ all_combinations = one_to_ten.product(one_to_ten)
+ puts all_combinations
+
+ puts "======== All uniq combinations of numbers. For example: [1, 2] is the same as [2, 1]."
+ one_to_ten = (1..10).to_a
+ uniq_combinations =
+ one_to_ten.product(one_to_ten)
+ .map do |unsorted_number|
+ unsorted_number.sort
+ end.uniq
+ puts uniq_combinations
+end
+
+# ====================================================================================
+# Advanced Arrays
+# ====================================================================================
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ puts "======== All unique Pythagorean Triples between 1 and 40 sorted by area of the triangle."
+
+ one_to_hundred = (1..40).to_a
+ triples =
+ one_to_hundred.product(one_to_hundred).map do |width, height|
+ [width, height, Math.sqrt(width ** 2 + height ** 2)]
+ end.find_all do |_, _, hypotenuse|
+ hypotenuse.to_i == hypotenuse
+ end.map do |triangle|
+ triangle.map(&:to_i)
+ end.uniq do |triangle|
+ triangle.sort
+ end.map do |width, height, hypotenuse|
+ [width, height, hypotenuse, (width * height) / 2]
+ end.sort_by do |_, _, _, area|
+ area
+ end
+
+ triples.each do |width, height, hypotenuse, area|
+ puts "(#{width}, #{height}, #{hypotenuse}) = #{area}"
+ end
+end
diff --git a/samples/99_genre_crafting/farming_game_starting_point/app/tests.rb b/samples/99_genre_crafting/farming_game_starting_point/app/tests.rb
new file mode 100644
index 0000000..458bc18
--- /dev/null
+++ b/samples/99_genre_crafting/farming_game_starting_point/app/tests.rb
@@ -0,0 +1,29 @@
+# For advanced users:
+# You can put some quick verification tests here, any method
+# that starts with the `test_` will be run when you save this file.
+
+# Here is an example test and game
+
+# To run the test: ./dragonruby mygame --eval app/tests.rb --no-tick
+
+class MySuperHappyFunGame
+ attr_gtk
+
+ def tick
+ outputs.solids << [100, 100, 300, 300]
+ end
+end
+
+def test_universe args, assert
+ game = MySuperHappyFunGame.new
+ game.args = args
+ game.tick
+ assert.true! args.outputs.solids.length == 1, "failure: a solid was not added after tick"
+ assert.false! 1 == 2, "failure: some how, 1 equals 2, the world is ending"
+ puts "test_universe completed successfully"
+end
+
+puts "running tests"
+$gtk.reset 100
+$gtk.log_level = :off
+$gtk.tests.start
diff --git a/samples/99_genre_crafting/farming_game_starting_point/replay.txt b/samples/99_genre_crafting/farming_game_starting_point/replay.txt
new file mode 100644
index 0000000..740810d
--- /dev/null
+++ b/samples/99_genre_crafting/farming_game_starting_point/replay.txt
@@ -0,0 +1,170 @@
+replay_version 2.0
+stopped_at 851
+seed 100
+recorded_at 2021-11-20 11:30:20 -0600
+[:mouse_button_up, 1, 0, 1, 1, 4]
+[:key_down_raw, 1073741904, 0, 2, 2, 69]
+[:key_down_raw, 1073741904, 0, 2, 3, 83]
+[:key_up_raw, 1073741904, 0, 2, 4, 84]
+[:key_down_raw, 1073741906, 0, 2, 5, 89]
+[:key_down_raw, 1073741903, 0, 2, 6, 95]
+[:key_up_raw, 1073741906, 0, 2, 7, 103]
+[:key_down_raw, 1073741903, 0, 2, 8, 110]
+[:key_down_raw, 1073741903, 0, 2, 9, 112]
+[:key_down_raw, 1073741903, 0, 2, 10, 114]
+[:key_down_raw, 1073741903, 0, 2, 11, 116]
+[:key_down_raw, 1073741903, 0, 2, 12, 118]
+[:key_down_raw, 1073741903, 0, 2, 13, 120]
+[:key_down_raw, 1073741903, 0, 2, 14, 122]
+[:key_down_raw, 1073741903, 0, 2, 15, 124]
+[:key_up_raw, 1073741903, 0, 2, 16, 125]
+[:key_down_raw, 106, 0, 2, 17, 147]
+[:key_up_raw, 106, 0, 2, 18, 156]
+[:key_down_raw, 1073741904, 0, 2, 19, 180]
+[:key_down_raw, 1073741904, 0, 2, 20, 195]
+[:key_down_raw, 1073741904, 0, 2, 21, 197]
+[:key_down_raw, 1073741904, 0, 2, 22, 199]
+[:key_down_raw, 1073741904, 0, 2, 23, 201]
+[:key_down_raw, 1073741904, 0, 2, 24, 203]
+[:key_down_raw, 1073741904, 0, 2, 25, 205]
+[:key_up_raw, 1073741904, 0, 2, 26, 207]
+[:key_down_raw, 1073741903, 0, 2, 27, 208]
+[:key_down_raw, 1073741903, 0, 2, 28, 223]
+[:key_down_raw, 1073741903, 0, 2, 29, 225]
+[:key_down_raw, 1073741903, 0, 2, 30, 227]
+[:key_down_raw, 1073741903, 0, 2, 31, 229]
+[:key_down_raw, 1073741903, 0, 2, 32, 231]
+[:key_down_raw, 1073741903, 0, 2, 33, 233]
+[:key_down_raw, 1073741903, 0, 2, 34, 235]
+[:key_down_raw, 1073741903, 0, 2, 35, 237]
+[:key_down_raw, 1073741903, 0, 2, 36, 239]
+[:key_down_raw, 1073741903, 0, 2, 37, 241]
+[:key_down_raw, 1073741903, 0, 2, 38, 243]
+[:key_down_raw, 1073741903, 0, 2, 39, 245]
+[:key_down_raw, 1073741903, 0, 2, 40, 247]
+[:key_down_raw, 1073741903, 0, 2, 41, 249]
+[:key_down_raw, 1073741903, 0, 2, 42, 251]
+[:key_down_raw, 1073741903, 0, 2, 43, 253]
+[:key_down_raw, 1073741903, 0, 2, 44, 255]
+[:key_down_raw, 1073741906, 0, 2, 45, 257]
+[:key_up_raw, 1073741903, 0, 2, 46, 258]
+[:key_down_raw, 1073741906, 0, 2, 47, 271]
+[:key_down_raw, 1073741906, 0, 2, 48, 274]
+[:key_down_raw, 1073741906, 0, 2, 49, 276]
+[:key_down_raw, 1073741906, 0, 2, 50, 278]
+[:key_down_raw, 1073741906, 0, 2, 51, 280]
+[:key_up_raw, 1073741906, 0, 2, 52, 280]
+[:key_down_raw, 1073741903, 0, 2, 53, 280]
+[:key_down_raw, 1073741903, 0, 2, 54, 296]
+[:key_down_raw, 1073741903, 0, 2, 55, 298]
+[:key_down_raw, 1073741905, 0, 2, 56, 298]
+[:key_up_raw, 1073741903, 0, 2, 57, 300]
+[:key_down_raw, 1073741905, 0, 2, 58, 313]
+[:key_down_raw, 1073741905, 0, 2, 59, 315]
+[:key_down_raw, 1073741905, 0, 2, 60, 317]
+[:key_down_raw, 1073741905, 0, 2, 61, 319]
+[:key_down_raw, 1073741905, 0, 2, 62, 321]
+[:key_down_raw, 1073741905, 0, 2, 63, 323]
+[:key_down_raw, 1073741905, 0, 2, 64, 325]
+[:key_down_raw, 1073741905, 0, 2, 65, 327]
+[:key_down_raw, 1073741905, 0, 2, 66, 329]
+[:key_down_raw, 1073741904, 0, 2, 67, 330]
+[:key_up_raw, 1073741905, 0, 2, 68, 332]
+[:key_down_raw, 1073741904, 0, 2, 69, 345]
+[:key_down_raw, 1073741904, 0, 2, 70, 347]
+[:key_down_raw, 1073741904, 0, 2, 71, 349]
+[:key_down_raw, 1073741904, 0, 2, 72, 351]
+[:key_up_raw, 1073741904, 0, 2, 73, 353]
+[:key_down_raw, 1073741903, 0, 2, 74, 354]
+[:key_down_raw, 1073741903, 0, 2, 75, 369]
+[:key_down_raw, 1073741903, 0, 2, 76, 371]
+[:key_down_raw, 1073741903, 0, 2, 77, 373]
+[:key_down_raw, 1073741903, 0, 2, 78, 375]
+[:key_down_raw, 1073741903, 0, 2, 79, 377]
+[:key_down_raw, 1073741903, 0, 2, 80, 379]
+[:key_down_raw, 1073741903, 0, 2, 81, 382]
+[:key_down_raw, 1073741903, 0, 2, 82, 383]
+[:key_down_raw, 1073741903, 0, 2, 83, 385]
+[:key_down_raw, 1073741903, 0, 2, 84, 387]
+[:key_down_raw, 1073741903, 0, 2, 85, 390]
+[:key_down_raw, 1073741903, 0, 2, 86, 392]
+[:key_down_raw, 1073741903, 0, 2, 87, 394]
+[:key_down_raw, 1073741905, 0, 2, 88, 395]
+[:key_up_raw, 1073741903, 0, 2, 89, 400]
+[:key_down_raw, 1073741904, 0, 2, 90, 405]
+[:key_up_raw, 1073741905, 0, 2, 91, 416]
+[:key_down_raw, 1073741904, 0, 2, 92, 420]
+[:key_down_raw, 1073741904, 0, 2, 93, 422]
+[:key_down_raw, 1073741904, 0, 2, 94, 424]
+[:key_down_raw, 1073741904, 0, 2, 95, 426]
+[:key_down_raw, 1073741904, 0, 2, 96, 428]
+[:key_down_raw, 1073741904, 0, 2, 97, 430]
+[:key_down_raw, 1073741904, 0, 2, 98, 432]
+[:key_down_raw, 1073741904, 0, 2, 99, 434]
+[:key_down_raw, 1073741904, 0, 2, 100, 436]
+[:key_down_raw, 1073741904, 0, 2, 101, 438]
+[:key_down_raw, 1073741904, 0, 2, 102, 440]
+[:key_down_raw, 1073741904, 0, 2, 103, 442]
+[:key_down_raw, 1073741904, 0, 2, 104, 444]
+[:key_up_raw, 1073741904, 0, 2, 105, 444]
+[:key_down_raw, 1073741906, 0, 2, 106, 445]
+[:key_up_raw, 1073741906, 0, 2, 107, 448]
+[:key_down_raw, 1073741905, 0, 2, 108, 452]
+[:key_down_raw, 1073741905, 0, 2, 109, 467]
+[:key_down_raw, 1073741905, 0, 2, 110, 469]
+[:key_up_raw, 1073741905, 0, 2, 111, 470]
+[:key_down_raw, 1073741906, 0, 2, 112, 484]
+[:key_up_raw, 1073741906, 0, 2, 113, 496]
+[:key_down_raw, 32, 0, 2, 114, 499]
+[:key_up_raw, 32, 0, 2, 115, 505]
+[:key_down_raw, 1073741903, 0, 2, 116, 538]
+[:key_up_raw, 1073741903, 0, 2, 117, 553]
+[:key_down_raw, 106, 0, 2, 118, 604]
+[:key_up_raw, 106, 0, 2, 119, 608]
+[:key_down_raw, 1073741903, 0, 2, 120, 640]
+[:key_down_raw, 1073741906, 0, 2, 121, 654]
+[:key_up_raw, 1073741903, 0, 2, 122, 654]
+[:key_down_raw, 1073741906, 0, 2, 123, 669]
+[:key_down_raw, 1073741906, 0, 2, 124, 671]
+[:key_down_raw, 1073741906, 0, 2, 125, 673]
+[:key_down_raw, 1073741906, 0, 2, 126, 675]
+[:key_up_raw, 1073741906, 0, 2, 127, 677]
+[:key_down_raw, 1073741903, 0, 2, 128, 677]
+[:key_down_raw, 1073741903, 0, 2, 129, 692]
+[:key_down_raw, 1073741903, 0, 2, 130, 694]
+[:key_down_raw, 1073741905, 0, 2, 131, 694]
+[:key_up_raw, 1073741903, 0, 2, 132, 696]
+[:key_down_raw, 1073741905, 0, 2, 133, 709]
+[:key_down_raw, 1073741905, 0, 2, 134, 711]
+[:key_down_raw, 1073741905, 0, 2, 135, 713]
+[:key_down_raw, 1073741905, 0, 2, 136, 715]
+[:key_down_raw, 1073741905, 0, 2, 137, 717]
+[:key_down_raw, 1073741904, 0, 2, 138, 719]
+[:key_up_raw, 1073741905, 0, 2, 139, 721]
+[:key_down_raw, 1073741904, 0, 2, 140, 734]
+[:key_down_raw, 1073741904, 0, 2, 141, 736]
+[:key_down_raw, 1073741904, 0, 2, 142, 738]
+[:key_down_raw, 1073741904, 0, 2, 143, 740]
+[:key_down_raw, 1073741904, 0, 2, 144, 742]
+[:key_down_raw, 1073741904, 0, 2, 145, 744]
+[:key_down_raw, 1073741904, 0, 2, 146, 746]
+[:key_down_raw, 1073741904, 0, 2, 147, 748]
+[:key_up_raw, 1073741904, 0, 2, 148, 748]
+[:key_down_raw, 96, 0, 2, 149, 778]
+[:key_up_raw, 96, 0, 2, 150, 782]
+[:mouse_move, 782, 86, 2, 151, 822]
+[:mouse_move, 774, 93, 2, 152, 823]
+[:mouse_move, 764, 101, 2, 153, 824]
+[:mouse_move, 752, 113, 2, 154, 825]
+[:mouse_move, 732, 126, 2, 155, 826]
+[:mouse_move, 716, 141, 2, 156, 827]
+[:mouse_move, 705, 152, 2, 157, 828]
+[:mouse_move, 699, 162, 2, 158, 829]
+[:mouse_move, 693, 172, 2, 159, 830]
+[:mouse_move, 690, 177, 2, 160, 831]
+[:mouse_move, 690, 176, 2, 161, 839]
+[:mouse_move, 691, 175, 2, 162, 840]
+[:mouse_move, 693, 173, 2, 163, 841]
+[:mouse_move, 695, 173, 2, 164, 842]
+[:mouse_move, 695, 172, 2, 165, 844]
+[:key_down_raw, 13, 0, 2, 166, 851]
diff --git a/samples/99_genre_crafting/farming_game_starting_point/sprites/background.png b/samples/99_genre_crafting/farming_game_starting_point/sprites/background.png
new file mode 100644
index 0000000..dbda37e
--- /dev/null
+++ b/samples/99_genre_crafting/farming_game_starting_point/sprites/background.png
Binary files differ
diff --git a/samples/99_genre_crafting/replay.txt b/samples/99_genre_crafting/replay.txt
new file mode 100644
index 0000000..740810d
--- /dev/null
+++ b/samples/99_genre_crafting/replay.txt
@@ -0,0 +1,170 @@
+replay_version 2.0
+stopped_at 851
+seed 100
+recorded_at 2021-11-20 11:30:20 -0600
+[:mouse_button_up, 1, 0, 1, 1, 4]
+[:key_down_raw, 1073741904, 0, 2, 2, 69]
+[:key_down_raw, 1073741904, 0, 2, 3, 83]
+[:key_up_raw, 1073741904, 0, 2, 4, 84]
+[:key_down_raw, 1073741906, 0, 2, 5, 89]
+[:key_down_raw, 1073741903, 0, 2, 6, 95]
+[:key_up_raw, 1073741906, 0, 2, 7, 103]
+[:key_down_raw, 1073741903, 0, 2, 8, 110]
+[:key_down_raw, 1073741903, 0, 2, 9, 112]
+[:key_down_raw, 1073741903, 0, 2, 10, 114]
+[:key_down_raw, 1073741903, 0, 2, 11, 116]
+[:key_down_raw, 1073741903, 0, 2, 12, 118]
+[:key_down_raw, 1073741903, 0, 2, 13, 120]
+[:key_down_raw, 1073741903, 0, 2, 14, 122]
+[:key_down_raw, 1073741903, 0, 2, 15, 124]
+[:key_up_raw, 1073741903, 0, 2, 16, 125]
+[:key_down_raw, 106, 0, 2, 17, 147]
+[:key_up_raw, 106, 0, 2, 18, 156]
+[:key_down_raw, 1073741904, 0, 2, 19, 180]
+[:key_down_raw, 1073741904, 0, 2, 20, 195]
+[:key_down_raw, 1073741904, 0, 2, 21, 197]
+[:key_down_raw, 1073741904, 0, 2, 22, 199]
+[:key_down_raw, 1073741904, 0, 2, 23, 201]
+[:key_down_raw, 1073741904, 0, 2, 24, 203]
+[:key_down_raw, 1073741904, 0, 2, 25, 205]
+[:key_up_raw, 1073741904, 0, 2, 26, 207]
+[:key_down_raw, 1073741903, 0, 2, 27, 208]
+[:key_down_raw, 1073741903, 0, 2, 28, 223]
+[:key_down_raw, 1073741903, 0, 2, 29, 225]
+[:key_down_raw, 1073741903, 0, 2, 30, 227]
+[:key_down_raw, 1073741903, 0, 2, 31, 229]
+[:key_down_raw, 1073741903, 0, 2, 32, 231]
+[:key_down_raw, 1073741903, 0, 2, 33, 233]
+[:key_down_raw, 1073741903, 0, 2, 34, 235]
+[:key_down_raw, 1073741903, 0, 2, 35, 237]
+[:key_down_raw, 1073741903, 0, 2, 36, 239]
+[:key_down_raw, 1073741903, 0, 2, 37, 241]
+[:key_down_raw, 1073741903, 0, 2, 38, 243]
+[:key_down_raw, 1073741903, 0, 2, 39, 245]
+[:key_down_raw, 1073741903, 0, 2, 40, 247]
+[:key_down_raw, 1073741903, 0, 2, 41, 249]
+[:key_down_raw, 1073741903, 0, 2, 42, 251]
+[:key_down_raw, 1073741903, 0, 2, 43, 253]
+[:key_down_raw, 1073741903, 0, 2, 44, 255]
+[:key_down_raw, 1073741906, 0, 2, 45, 257]
+[:key_up_raw, 1073741903, 0, 2, 46, 258]
+[:key_down_raw, 1073741906, 0, 2, 47, 271]
+[:key_down_raw, 1073741906, 0, 2, 48, 274]
+[:key_down_raw, 1073741906, 0, 2, 49, 276]
+[:key_down_raw, 1073741906, 0, 2, 50, 278]
+[:key_down_raw, 1073741906, 0, 2, 51, 280]
+[:key_up_raw, 1073741906, 0, 2, 52, 280]
+[:key_down_raw, 1073741903, 0, 2, 53, 280]
+[:key_down_raw, 1073741903, 0, 2, 54, 296]
+[:key_down_raw, 1073741903, 0, 2, 55, 298]
+[:key_down_raw, 1073741905, 0, 2, 56, 298]
+[:key_up_raw, 1073741903, 0, 2, 57, 300]
+[:key_down_raw, 1073741905, 0, 2, 58, 313]
+[:key_down_raw, 1073741905, 0, 2, 59, 315]
+[:key_down_raw, 1073741905, 0, 2, 60, 317]
+[:key_down_raw, 1073741905, 0, 2, 61, 319]
+[:key_down_raw, 1073741905, 0, 2, 62, 321]
+[:key_down_raw, 1073741905, 0, 2, 63, 323]
+[:key_down_raw, 1073741905, 0, 2, 64, 325]
+[:key_down_raw, 1073741905, 0, 2, 65, 327]
+[:key_down_raw, 1073741905, 0, 2, 66, 329]
+[:key_down_raw, 1073741904, 0, 2, 67, 330]
+[:key_up_raw, 1073741905, 0, 2, 68, 332]
+[:key_down_raw, 1073741904, 0, 2, 69, 345]
+[:key_down_raw, 1073741904, 0, 2, 70, 347]
+[:key_down_raw, 1073741904, 0, 2, 71, 349]
+[:key_down_raw, 1073741904, 0, 2, 72, 351]
+[:key_up_raw, 1073741904, 0, 2, 73, 353]
+[:key_down_raw, 1073741903, 0, 2, 74, 354]
+[:key_down_raw, 1073741903, 0, 2, 75, 369]
+[:key_down_raw, 1073741903, 0, 2, 76, 371]
+[:key_down_raw, 1073741903, 0, 2, 77, 373]
+[:key_down_raw, 1073741903, 0, 2, 78, 375]
+[:key_down_raw, 1073741903, 0, 2, 79, 377]
+[:key_down_raw, 1073741903, 0, 2, 80, 379]
+[:key_down_raw, 1073741903, 0, 2, 81, 382]
+[:key_down_raw, 1073741903, 0, 2, 82, 383]
+[:key_down_raw, 1073741903, 0, 2, 83, 385]
+[:key_down_raw, 1073741903, 0, 2, 84, 387]
+[:key_down_raw, 1073741903, 0, 2, 85, 390]
+[:key_down_raw, 1073741903, 0, 2, 86, 392]
+[:key_down_raw, 1073741903, 0, 2, 87, 394]
+[:key_down_raw, 1073741905, 0, 2, 88, 395]
+[:key_up_raw, 1073741903, 0, 2, 89, 400]
+[:key_down_raw, 1073741904, 0, 2, 90, 405]
+[:key_up_raw, 1073741905, 0, 2, 91, 416]
+[:key_down_raw, 1073741904, 0, 2, 92, 420]
+[:key_down_raw, 1073741904, 0, 2, 93, 422]
+[:key_down_raw, 1073741904, 0, 2, 94, 424]
+[:key_down_raw, 1073741904, 0, 2, 95, 426]
+[:key_down_raw, 1073741904, 0, 2, 96, 428]
+[:key_down_raw, 1073741904, 0, 2, 97, 430]
+[:key_down_raw, 1073741904, 0, 2, 98, 432]
+[:key_down_raw, 1073741904, 0, 2, 99, 434]
+[:key_down_raw, 1073741904, 0, 2, 100, 436]
+[:key_down_raw, 1073741904, 0, 2, 101, 438]
+[:key_down_raw, 1073741904, 0, 2, 102, 440]
+[:key_down_raw, 1073741904, 0, 2, 103, 442]
+[:key_down_raw, 1073741904, 0, 2, 104, 444]
+[:key_up_raw, 1073741904, 0, 2, 105, 444]
+[:key_down_raw, 1073741906, 0, 2, 106, 445]
+[:key_up_raw, 1073741906, 0, 2, 107, 448]
+[:key_down_raw, 1073741905, 0, 2, 108, 452]
+[:key_down_raw, 1073741905, 0, 2, 109, 467]
+[:key_down_raw, 1073741905, 0, 2, 110, 469]
+[:key_up_raw, 1073741905, 0, 2, 111, 470]
+[:key_down_raw, 1073741906, 0, 2, 112, 484]
+[:key_up_raw, 1073741906, 0, 2, 113, 496]
+[:key_down_raw, 32, 0, 2, 114, 499]
+[:key_up_raw, 32, 0, 2, 115, 505]
+[:key_down_raw, 1073741903, 0, 2, 116, 538]
+[:key_up_raw, 1073741903, 0, 2, 117, 553]
+[:key_down_raw, 106, 0, 2, 118, 604]
+[:key_up_raw, 106, 0, 2, 119, 608]
+[:key_down_raw, 1073741903, 0, 2, 120, 640]
+[:key_down_raw, 1073741906, 0, 2, 121, 654]
+[:key_up_raw, 1073741903, 0, 2, 122, 654]
+[:key_down_raw, 1073741906, 0, 2, 123, 669]
+[:key_down_raw, 1073741906, 0, 2, 124, 671]
+[:key_down_raw, 1073741906, 0, 2, 125, 673]
+[:key_down_raw, 1073741906, 0, 2, 126, 675]
+[:key_up_raw, 1073741906, 0, 2, 127, 677]
+[:key_down_raw, 1073741903, 0, 2, 128, 677]
+[:key_down_raw, 1073741903, 0, 2, 129, 692]
+[:key_down_raw, 1073741903, 0, 2, 130, 694]
+[:key_down_raw, 1073741905, 0, 2, 131, 694]
+[:key_up_raw, 1073741903, 0, 2, 132, 696]
+[:key_down_raw, 1073741905, 0, 2, 133, 709]
+[:key_down_raw, 1073741905, 0, 2, 134, 711]
+[:key_down_raw, 1073741905, 0, 2, 135, 713]
+[:key_down_raw, 1073741905, 0, 2, 136, 715]
+[:key_down_raw, 1073741905, 0, 2, 137, 717]
+[:key_down_raw, 1073741904, 0, 2, 138, 719]
+[:key_up_raw, 1073741905, 0, 2, 139, 721]
+[:key_down_raw, 1073741904, 0, 2, 140, 734]
+[:key_down_raw, 1073741904, 0, 2, 141, 736]
+[:key_down_raw, 1073741904, 0, 2, 142, 738]
+[:key_down_raw, 1073741904, 0, 2, 143, 740]
+[:key_down_raw, 1073741904, 0, 2, 144, 742]
+[:key_down_raw, 1073741904, 0, 2, 145, 744]
+[:key_down_raw, 1073741904, 0, 2, 146, 746]
+[:key_down_raw, 1073741904, 0, 2, 147, 748]
+[:key_up_raw, 1073741904, 0, 2, 148, 748]
+[:key_down_raw, 96, 0, 2, 149, 778]
+[:key_up_raw, 96, 0, 2, 150, 782]
+[:mouse_move, 782, 86, 2, 151, 822]
+[:mouse_move, 774, 93, 2, 152, 823]
+[:mouse_move, 764, 101, 2, 153, 824]
+[:mouse_move, 752, 113, 2, 154, 825]
+[:mouse_move, 732, 126, 2, 155, 826]
+[:mouse_move, 716, 141, 2, 156, 827]
+[:mouse_move, 705, 152, 2, 157, 828]
+[:mouse_move, 699, 162, 2, 158, 829]
+[:mouse_move, 693, 172, 2, 159, 830]
+[:mouse_move, 690, 177, 2, 160, 831]
+[:mouse_move, 690, 176, 2, 161, 839]
+[:mouse_move, 691, 175, 2, 162, 840]
+[:mouse_move, 693, 173, 2, 163, 841]
+[:mouse_move, 695, 173, 2, 164, 842]
+[:mouse_move, 695, 172, 2, 165, 844]
+[:key_down_raw, 13, 0, 2, 166, 851]
diff --git a/samples/99_genre_dev_tools/animation_creator_starting_point/app/main.rb b/samples/99_genre_dev_tools/animation_creator_starting_point/app/main.rb
index 14456e3..b80e4b8 100644
--- a/samples/99_genre_dev_tools/animation_creator_starting_point/app/main.rb
+++ b/samples/99_genre_dev_tools/animation_creator_starting_point/app/main.rb
@@ -72,24 +72,22 @@ class OneBitLowrezPaint
end
def render_instructions
- instructions = <<-S
-* Instructions:
-- All data is stored in the ~canvas~ directory.
-- Hold ~d~ to set the edit mode to erase.
-- Release ~d~ to set the edit mode drawing.
-- Press ~a~ to added a frame to the end.
-- Press ~b~ to select the previous frame.
-- Press ~f~ to select the next frame.
-- Press ~c~ to copy a frame.
-- Press ~v~ to paste a copied frame into the selected frame.
-- Press ~x~ to delete the currently selected frame.
-- Press ~w~ to save the canvas and export all sprites.
-- Press ~l~ to load the canvas.
-S
-
- instructions.strip.each_line.with_index do |l, i|
+ instructions = [
+ "* Hotkeys:",
+ "- d: hold to erase, release to draw.",
+ "- a: add frame.",
+ "- c: copy frame.",
+ "- v: paste frame.",
+ "- x: delete frame.",
+ "- b: go to previous frame.",
+ "- f: go to next frame.",
+ "- w: save to ./canvas directory.",
+ "- l: load from ./canvas."
+ ]
+
+ instructions.each.with_index do |l, i|
outputs.labels << { x: 840, y: 500 - (i * 20), text: "#{l}",
- r: 180, g: 180, b: 180, size_enum: -3 }
+ r: 180, g: 180, b: 180, size_enum: 0 }
end
end
@@ -103,12 +101,12 @@ S
label = { x: b.x + state.buttons_frame_selection.size.half,
y: b.y,
text: "#{i + 1}", r: 180, g: 180, b: 180,
- size_enum: -4, alignment_enum: 1 }.label
+ size_enum: -4, alignment_enum: 1 }.label!
- selection_border = b.merge(r: 40, g: 40, b: 40).border
+ selection_border = b.merge(r: 40, g: 40, b: 40).border!
if i == state.animation_frames_selected_index
- selection_border = b.merge(r: 40, g: 230, b: 200).border
+ selection_border = b.merge(r: 40, g: 230, b: 200).border!
end
[selection_border, label]
diff --git a/samples/99_genre_dev_tools/tile_editor_starting_point/app/main.rb b/samples/99_genre_dev_tools/tile_editor_starting_point/app/main.rb
index 4238fcd..95ccfdf 100644
--- a/samples/99_genre_dev_tools/tile_editor_starting_point/app/main.rb
+++ b/samples/99_genre_dev_tools/tile_editor_starting_point/app/main.rb
@@ -17,15 +17,19 @@
- args.outputs.labels: An array. The values generate a label.
The parameters are [X, Y, TEXT, SIZE, ALIGNMENT, RED, GREEN, BLUE, ALPHA, FONT STYLE]
+ For more information about labels, go to mygame/documentation/02-labels.md.
- args.outputs.sprites: An array. The values generate a sprite.
The parameters are [X, Y, WIDTH, HEIGHT, IMAGE PATH]
+ For more information about sprites, go to mygame/documentation/05-sprites.md.
- args.outputs.solids: An array. The values generate a solid.
The parameters are [X, Y, WIDTH, HEIGHT, RED, GREEN, BLUE]
+ For more information about solids, go to mygame/documentation/03-solids-and-borders.md.
- args.outputs.lines: An array. The values generate a line.
The parameters are [X1, Y1, X2, Y2, RED, GREEN, BLUE]
+ For more information about lines, go to mygame/documentation/04-lines.md.
- args.state.new_entity: Used when we want to create a new object, like a sprite or button.
In this sample app, new_entity is used to create a new button that clears the grid.
diff --git a/samples/99_genre_dungeon_crawl/classics_jam/app/main.rb b/samples/99_genre_dungeon_crawl/classics_jam/app/main.rb
new file mode 100644
index 0000000..d14b50e
--- /dev/null
+++ b/samples/99_genre_dungeon_crawl/classics_jam/app/main.rb
@@ -0,0 +1,213 @@
+class Game
+ attr_gtk
+
+ def tick
+ defaults
+ render
+ input
+ calc
+ end
+
+ def defaults
+ player.x ||= 640
+ player.y ||= 360
+ player.w ||= 16
+ player.h ||= 16
+ player.attacked_at ||= -1
+ player.angle ||= 0
+ player.future_player ||= future_player_position 0, 0
+ player.projectiles ||= []
+ player.damage ||= 0
+ state.level ||= create_level level_one_template
+ end
+
+ def render
+ outputs.sprites << level.walls.map do |w|
+ w.merge(path: 'sprites/square/gray.png')
+ end
+
+ outputs.sprites << level.spawn_locations.map do |s|
+ s.merge(path: 'sprites/square/blue.png')
+ end
+
+ outputs.sprites << player.projectiles.map do |p|
+ p.merge(path: 'sprites/square/blue.png')
+ end
+
+ outputs.sprites << level.enemies.map do |e|
+ e.merge(path: 'sprites/square/red.png')
+ end
+
+ outputs.sprites << player.merge(path: 'sprites/circle/green.png', angle: player.angle)
+
+ outputs.labels << { x: 30, y: 30.from_top, text: "damage: #{player.damage || 0}" }
+ end
+
+ def input
+ player.angle = inputs.directional_angle || player.angle
+ if inputs.controller_one.key_down.a || inputs.keyboard.key_down.space
+ player.attacked_at = state.tick_count
+ end
+ end
+
+ def calc
+ calc_player
+ calc_projectiles
+ calc_enemies
+ calc_spawn_locations
+ end
+
+ def calc_player
+ if player.attacked_at == state.tick_count
+ player.projectiles << { at: state.tick_count,
+ x: player.x,
+ y: player.y,
+ angle: player.angle,
+ w: 4,
+ h: 4 }.center_inside_rect(player)
+ end
+
+ if player.attacked_at.elapsed_time > 5
+ future_player = future_player_position inputs.left_right * 2, inputs.up_down * 2
+ future_player_collision = future_collision player, future_player, level.walls
+ player.x = future_player_collision.x if !future_player_collision.dx_collision
+ player.y = future_player_collision.y if !future_player_collision.dy_collision
+ end
+ end
+
+ def calc_projectile_collisions entities
+ entities.each do |e|
+ e.damage ||= 0
+ player.projectiles.each do |p|
+ if !p.collided && (p.intersect_rect? e)
+ p.collided = true
+ e.damage += 1
+ end
+ end
+ end
+ end
+
+ def calc_projectiles
+ player.projectiles.map! do |p|
+ dx, dy = p.angle.vector 10
+ p.merge(x: p.x + dx, y: p.y + dy)
+ end
+
+ calc_projectile_collisions level.walls + level.enemies + level.spawn_locations
+ player.projectiles.reject! { |p| p.at.elapsed_time > 10000 }
+ player.projectiles.reject! { |p| p.collided }
+ level.enemies.reject! { |e| e.damage > e.hp }
+ level.spawn_locations.reject! { |s| s.damage > s.hp }
+ end
+
+ def calc_enemies
+ level.enemies.map! do |e|
+ dx = 0
+ dx = 1 if e.x < player.x
+ dx = -1 if e.x > player.x
+ dy = 0
+ dy = 1 if e.y < player.y
+ dy = -1 if e.y > player.y
+ future_e = future_entity_position dx, dy, e
+ future_e_collision = future_collision e, future_e, level.enemies + level.walls
+ e.next_x = e.x
+ e.next_y = e.y
+ e.next_x = future_e_collision.x if !future_e_collision.dx_collision
+ e.next_y = future_e_collision.y if !future_e_collision.dy_collision
+ e
+ end
+
+ level.enemies.map! do |e|
+ e.x = e.next_x
+ e.y = e.next_y
+ e
+ end
+
+ level.enemies.each do |e|
+ player.damage += 1 if e.intersect_rect? player
+ end
+ end
+
+ def calc_spawn_locations
+ level.spawn_locations.map! do |s|
+ s.merge(countdown: s.countdown - 1)
+ end
+ level.spawn_locations
+ .find_all { |s| s.countdown.neg? }
+ .each do |s|
+ s.countdown = s.rate
+ s.merge(countdown: s.rate)
+ new_enemy = create_enemy s
+ if !(level.enemies.find { |e| e.intersect_rect? new_enemy })
+ level.enemies << new_enemy
+ end
+ end
+ end
+
+ def create_enemy spawn_location
+ to_cell(spawn_location.ordinal_x, spawn_location.ordinal_y).merge hp: 2
+ end
+
+ def create_level level_template
+ {
+ walls: level_template.walls.map { |w| to_cell(w.ordinal_x, w.ordinal_y).merge(w) },
+ enemies: [],
+ spawn_locations: level_template.spawn_locations.map { |s| to_cell(s.ordinal_x, s.ordinal_y).merge(s) }
+ }
+ end
+
+ def level_one_template
+ {
+ walls: [{ ordinal_x: 25, ordinal_y: 20},
+ { ordinal_x: 25, ordinal_y: 21},
+ { ordinal_x: 25, ordinal_y: 22},
+ { ordinal_x: 25, ordinal_y: 23}],
+ spawn_locations: [{ ordinal_x: 10, ordinal_y: 10, rate: 120, countdown: 0, hp: 5 }]
+ }
+ end
+
+ def player
+ state.player ||= {}
+ end
+
+ def level
+ state.level ||= {}
+ end
+
+ def future_collision entity, future_entity, others
+ dx_collision = others.find { |o| o != entity && (o.intersect_rect? future_entity.dx) }
+ dy_collision = others.find { |o| o != entity && (o.intersect_rect? future_entity.dy) }
+
+ {
+ dx_collision: dx_collision,
+ x: future_entity.dx.x,
+ dy_collision: dy_collision,
+ y: future_entity.dy.y
+ }
+ end
+
+ def future_entity_position dx, dy, entity
+ {
+ dx: entity.merge(x: entity.x + dx),
+ dy: entity.merge(y: entity.y + dy),
+ both: entity.merge(x: entity.x + dx, y: entity.y + dy)
+ }
+ end
+
+ def future_player_position dx, dy
+ future_entity_position dx, dy, player
+ end
+
+ def to_cell ordinal_x, ordinal_y
+ { x: ordinal_x * 16, y: ordinal_y * 16, w: 16, h: 16 }
+ end
+end
+
+def tick args
+ $game ||= Game.new
+ $game.args = args
+ $game.tick
+end
+
+$gtk.reset
+$game = nil
diff --git a/samples/99_genre_dungeon_crawl/classics_jam/replay.txt b/samples/99_genre_dungeon_crawl/classics_jam/replay.txt
new file mode 100644
index 0000000..eab6ec5
--- /dev/null
+++ b/samples/99_genre_dungeon_crawl/classics_jam/replay.txt
@@ -0,0 +1,197 @@
+replay_version 2.0
+stopped_at 873
+seed 100
+recorded_at 2021-11-20 11:38:43 -0600
+[:mouse_button_up, 1, 0, 1, 1, 4]
+[:key_down_raw, 1073741905, 0, 2, 2, 99]
+[:key_down_raw, 1073741905, 0, 2, 3, 113]
+[:key_down_raw, 1073741905, 0, 2, 4, 115]
+[:key_down_raw, 1073741905, 0, 2, 5, 117]
+[:key_down_raw, 1073741905, 0, 2, 6, 119]
+[:key_down_raw, 1073741905, 0, 2, 7, 121]
+[:key_down_raw, 1073741905, 0, 2, 8, 123]
+[:key_down_raw, 1073741905, 0, 2, 9, 125]
+[:key_down_raw, 1073741905, 0, 2, 10, 127]
+[:key_down_raw, 1073741905, 0, 2, 11, 129]
+[:key_down_raw, 1073741905, 0, 2, 12, 131]
+[:key_down_raw, 1073741905, 0, 2, 13, 133]
+[:key_down_raw, 1073741905, 0, 2, 14, 135]
+[:key_down_raw, 1073741905, 0, 2, 15, 137]
+[:key_down_raw, 1073741905, 0, 2, 16, 139]
+[:key_down_raw, 1073741905, 0, 2, 17, 141]
+[:key_down_raw, 1073741905, 0, 2, 18, 143]
+[:key_down_raw, 1073741905, 0, 2, 19, 145]
+[:key_down_raw, 1073741905, 0, 2, 20, 147]
+[:key_down_raw, 1073741905, 0, 2, 21, 149]
+[:key_down_raw, 1073741905, 0, 2, 22, 151]
+[:key_down_raw, 1073741905, 0, 2, 23, 153]
+[:key_down_raw, 1073741905, 0, 2, 24, 155]
+[:key_down_raw, 1073741905, 0, 2, 25, 157]
+[:key_down_raw, 1073741905, 0, 2, 26, 159]
+[:key_down_raw, 1073741905, 0, 2, 27, 161]
+[:key_down_raw, 1073741905, 0, 2, 28, 163]
+[:key_down_raw, 1073741905, 0, 2, 29, 165]
+[:key_down_raw, 1073741905, 0, 2, 30, 167]
+[:key_down_raw, 1073741905, 0, 2, 31, 169]
+[:key_down_raw, 1073741905, 0, 2, 32, 171]
+[:key_down_raw, 1073741905, 0, 2, 33, 173]
+[:key_down_raw, 1073741905, 0, 2, 34, 175]
+[:key_down_raw, 1073741905, 0, 2, 35, 177]
+[:key_down_raw, 1073741905, 0, 2, 36, 179]
+[:key_down_raw, 1073741905, 0, 2, 37, 181]
+[:key_down_raw, 1073741905, 0, 2, 38, 183]
+[:key_down_raw, 1073741905, 0, 2, 39, 185]
+[:key_down_raw, 1073741905, 0, 2, 40, 187]
+[:key_down_raw, 1073741905, 0, 2, 41, 189]
+[:key_down_raw, 1073741905, 0, 2, 42, 191]
+[:key_down_raw, 1073741905, 0, 2, 43, 193]
+[:key_down_raw, 1073741905, 0, 2, 44, 195]
+[:key_down_raw, 1073741904, 0, 2, 45, 196]
+[:key_up_raw, 1073741905, 0, 2, 46, 196]
+[:key_up_raw, 1073741904, 0, 2, 47, 205]
+[:key_down_raw, 32, 0, 2, 48, 206]
+[:key_up_raw, 32, 0, 2, 49, 212]
+[:key_down_raw, 32, 0, 2, 50, 217]
+[:key_up_raw, 32, 0, 2, 51, 222]
+[:key_down_raw, 32, 0, 2, 52, 227]
+[:key_up_raw, 32, 0, 2, 53, 233]
+[:key_down_raw, 32, 0, 2, 54, 237]
+[:key_up_raw, 32, 0, 2, 55, 243]
+[:key_down_raw, 32, 0, 2, 56, 266]
+[:key_up_raw, 32, 0, 2, 57, 271]
+[:key_down_raw, 32, 0, 2, 58, 276]
+[:key_up_raw, 32, 0, 2, 59, 282]
+[:key_down_raw, 32, 0, 2, 60, 294]
+[:key_up_raw, 32, 0, 2, 61, 300]
+[:key_down_raw, 32, 0, 2, 62, 305]
+[:key_down_raw, 1073741904, 0, 2, 63, 306]
+[:key_up_raw, 32, 0, 2, 64, 310]
+[:key_down_raw, 1073741904, 0, 2, 65, 322]
+[:key_down_raw, 1073741904, 0, 2, 66, 324]
+[:key_down_raw, 1073741904, 0, 2, 67, 326]
+[:key_down_raw, 1073741904, 0, 2, 68, 328]
+[:key_down_raw, 1073741904, 0, 2, 69, 330]
+[:key_down_raw, 1073741904, 0, 2, 70, 332]
+[:key_down_raw, 1073741904, 0, 2, 71, 334]
+[:key_down_raw, 1073741904, 0, 2, 72, 336]
+[:key_down_raw, 1073741904, 0, 2, 73, 338]
+[:key_down_raw, 1073741904, 0, 2, 74, 340]
+[:key_down_raw, 1073741904, 0, 2, 75, 342]
+[:key_down_raw, 1073741904, 0, 2, 76, 344]
+[:key_down_raw, 1073741904, 0, 2, 77, 346]
+[:key_down_raw, 1073741904, 0, 2, 78, 348]
+[:key_down_raw, 1073741904, 0, 2, 79, 350]
+[:key_down_raw, 1073741904, 0, 2, 80, 352]
+[:key_down_raw, 1073741904, 0, 2, 81, 354]
+[:key_down_raw, 1073741904, 0, 2, 82, 356]
+[:key_down_raw, 1073741904, 0, 2, 83, 358]
+[:key_down_raw, 1073741904, 0, 2, 84, 360]
+[:key_down_raw, 1073741904, 0, 2, 85, 362]
+[:key_down_raw, 1073741904, 0, 2, 86, 364]
+[:key_down_raw, 1073741904, 0, 2, 87, 366]
+[:key_down_raw, 1073741904, 0, 2, 88, 368]
+[:key_down_raw, 1073741904, 0, 2, 89, 370]
+[:key_down_raw, 1073741904, 0, 2, 90, 372]
+[:key_down_raw, 1073741904, 0, 2, 91, 374]
+[:key_down_raw, 1073741904, 0, 2, 92, 376]
+[:key_down_raw, 1073741904, 0, 2, 93, 378]
+[:key_down_raw, 1073741904, 0, 2, 94, 380]
+[:key_down_raw, 1073741904, 0, 2, 95, 382]
+[:key_down_raw, 1073741904, 0, 2, 96, 384]
+[:key_down_raw, 1073741904, 0, 2, 97, 386]
+[:key_down_raw, 1073741904, 0, 2, 98, 388]
+[:key_down_raw, 1073741904, 0, 2, 99, 390]
+[:key_down_raw, 1073741904, 0, 2, 100, 392]
+[:key_down_raw, 1073741904, 0, 2, 101, 394]
+[:key_down_raw, 1073741904, 0, 2, 102, 396]
+[:key_down_raw, 1073741904, 0, 2, 103, 398]
+[:key_down_raw, 1073741904, 0, 2, 104, 400]
+[:key_down_raw, 1073741904, 0, 2, 105, 402]
+[:key_down_raw, 1073741904, 0, 2, 106, 404]
+[:key_down_raw, 1073741904, 0, 2, 107, 406]
+[:key_down_raw, 1073741904, 0, 2, 108, 408]
+[:key_down_raw, 1073741904, 0, 2, 109, 410]
+[:key_down_raw, 1073741904, 0, 2, 110, 412]
+[:key_down_raw, 1073741904, 0, 2, 111, 414]
+[:key_down_raw, 1073741904, 0, 2, 112, 416]
+[:key_down_raw, 1073741904, 0, 2, 113, 418]
+[:key_down_raw, 1073741904, 0, 2, 114, 420]
+[:key_down_raw, 1073741904, 0, 2, 115, 422]
+[:key_down_raw, 1073741904, 0, 2, 116, 424]
+[:key_down_raw, 1073741904, 0, 2, 117, 426]
+[:key_down_raw, 1073741904, 0, 2, 118, 428]
+[:key_down_raw, 1073741904, 0, 2, 119, 430]
+[:key_down_raw, 1073741904, 0, 2, 120, 432]
+[:key_down_raw, 1073741904, 0, 2, 121, 434]
+[:key_down_raw, 1073741904, 0, 2, 122, 436]
+[:key_down_raw, 1073741904, 0, 2, 123, 438]
+[:key_down_raw, 1073741904, 0, 2, 124, 440]
+[:key_up_raw, 1073741904, 0, 2, 125, 442]
+[:key_down_raw, 1073741903, 0, 2, 126, 461]
+[:key_down_raw, 1073741903, 0, 2, 127, 476]
+[:key_down_raw, 1073741903, 0, 2, 128, 478]
+[:key_down_raw, 1073741903, 0, 2, 129, 480]
+[:key_down_raw, 1073741903, 0, 2, 130, 482]
+[:key_down_raw, 1073741903, 0, 2, 131, 484]
+[:key_down_raw, 1073741903, 0, 2, 132, 486]
+[:key_down_raw, 1073741903, 0, 2, 133, 488]
+[:key_down_raw, 1073741903, 0, 2, 134, 490]
+[:key_down_raw, 1073741903, 0, 2, 135, 492]
+[:key_down_raw, 1073741903, 0, 2, 136, 494]
+[:key_down_raw, 1073741903, 0, 2, 137, 496]
+[:key_down_raw, 1073741903, 0, 2, 138, 498]
+[:key_down_raw, 1073741903, 0, 2, 139, 500]
+[:key_down_raw, 1073741903, 0, 2, 140, 502]
+[:key_down_raw, 1073741903, 0, 2, 141, 504]
+[:key_down_raw, 1073741903, 0, 2, 142, 506]
+[:key_down_raw, 1073741903, 0, 2, 143, 508]
+[:key_down_raw, 1073741903, 0, 2, 144, 510]
+[:key_down_raw, 1073741903, 0, 2, 145, 512]
+[:key_down_raw, 1073741903, 0, 2, 146, 514]
+[:key_down_raw, 1073741903, 0, 2, 147, 516]
+[:key_down_raw, 1073741903, 0, 2, 148, 518]
+[:key_down_raw, 1073741903, 0, 2, 149, 520]
+[:key_down_raw, 1073741903, 0, 2, 150, 522]
+[:key_down_raw, 1073741903, 0, 2, 151, 524]
+[:key_down_raw, 1073741903, 0, 2, 152, 526]
+[:key_down_raw, 1073741903, 0, 2, 153, 528]
+[:key_down_raw, 1073741904, 0, 2, 154, 528]
+[:key_up_raw, 1073741903, 0, 2, 155, 528]
+[:key_down_raw, 32, 0, 2, 156, 534]
+[:key_up_raw, 32, 0, 2, 157, 539]
+[:key_down_raw, 32, 0, 2, 158, 545]
+[:key_up_raw, 32, 0, 2, 159, 549]
+[:key_down_raw, 32, 0, 2, 160, 554]
+[:key_up_raw, 32, 0, 2, 161, 560]
+[:key_down_raw, 32, 0, 2, 162, 564]
+[:key_up_raw, 32, 0, 2, 163, 570]
+[:key_down_raw, 32, 0, 2, 164, 575]
+[:key_up_raw, 32, 0, 2, 165, 581]
+[:key_down_raw, 32, 0, 2, 166, 585]
+[:key_up_raw, 32, 0, 2, 167, 590]
+[:key_down_raw, 32, 0, 2, 168, 594]
+[:key_up_raw, 32, 0, 2, 169, 600]
+[:key_down_raw, 32, 0, 2, 170, 605]
+[:key_up_raw, 32, 0, 2, 171, 610]
+[:key_down_raw, 32, 0, 2, 172, 615]
+[:key_up_raw, 32, 0, 2, 173, 620]
+[:key_down_raw, 32, 0, 2, 174, 624]
+[:key_up_raw, 32, 0, 2, 175, 630]
+[:key_up_raw, 1073741904, 0, 2, 176, 631]
+[:key_down_raw, 32, 0, 2, 177, 634]
+[:key_up_raw, 32, 0, 2, 178, 639]
+[:key_down_raw, 32, 0, 2, 179, 644]
+[:key_up_raw, 32, 0, 2, 180, 649]
+[:key_down_raw, 32, 0, 2, 181, 654]
+[:key_up_raw, 32, 0, 2, 182, 659]
+[:key_down_raw, 32, 0, 2, 183, 664]
+[:key_up_raw, 32, 0, 2, 184, 669]
+[:key_down_raw, 32, 0, 2, 185, 674]
+[:key_up_raw, 32, 0, 2, 186, 679]
+[:key_down_raw, 32, 0, 2, 187, 684]
+[:key_up_raw, 32, 0, 2, 188, 689]
+[:key_down_raw, 32, 0, 2, 189, 694]
+[:key_up_raw, 32, 0, 2, 190, 699]
+[:key_down_raw, 96, 0, 2, 191, 823]
+[:key_up_raw, 96, 0, 2, 192, 828]
+[:key_down_raw, 13, 0, 2, 193, 873]
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-green.png b/samples/99_genre_dungeon_crawl/classics_jam/sprites/circle/green.png
index 43cf7ee..43cf7ee 100644
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-green.png
+++ b/samples/99_genre_dungeon_crawl/classics_jam/sprites/circle/green.png
Binary files differ
diff --git a/samples/99_genre_3d/3d_cube/sprites/square-blue.png b/samples/99_genre_dungeon_crawl/classics_jam/sprites/square/blue.png
index b840849..b840849 100644
--- a/samples/99_genre_3d/3d_cube/sprites/square-blue.png
+++ b/samples/99_genre_dungeon_crawl/classics_jam/sprites/square/blue.png
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-gray.png b/samples/99_genre_dungeon_crawl/classics_jam/sprites/square/gray.png
index 2142b30..2142b30 100644
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-gray.png
+++ b/samples/99_genre_dungeon_crawl/classics_jam/sprites/square/gray.png
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-red.png b/samples/99_genre_dungeon_crawl/classics_jam/sprites/square/red.png
index 3ed5f13..3ed5f13 100644
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-red.png
+++ b/samples/99_genre_dungeon_crawl/classics_jam/sprites/square/red.png
Binary files differ
diff --git a/samples/99_genre_fighting/01_special_move_inputs/app/main.rb b/samples/99_genre_fighting/01_special_move_inputs/app/main.rb
new file mode 100644
index 0000000..5db1951
--- /dev/null
+++ b/samples/99_genre_fighting/01_special_move_inputs/app/main.rb
@@ -0,0 +1,297 @@
+def tick args
+ #tick_instructions args, "Use LEFT and RIGHT arrow keys to move and SPACE to jump."
+ defaults args
+ render args
+ input args
+ calc args
+end
+
+# sets default values and creates empty collections
+# initialization only happens in the first frame
+def defaults args
+ fiddle args
+
+ args.state.tick_count = args.state.tick_count
+ args.state.bridge_top = 128
+ args.state.player.x ||= 0 # initializes player's properties
+ args.state.player.y ||= args.state.bridge_top
+ args.state.player.w ||= 64
+ args.state.player.h ||= 64
+ args.state.player.dy ||= 0
+ args.state.player.dx ||= 0
+ args.state.player.r ||= 0
+ args.state.game_over_at ||= 0
+ args.state.animation_time ||=0
+
+ args.state.timeleft ||=0
+ args.state.timeright ||=0
+ args.state.lastpush ||=0
+
+ args.state.inputlist ||= ["j","k","l"]
+end
+
+# sets enemy, player, hammer values
+def fiddle args
+ args.state.gravity = -0.5
+ args.state.player_jump_power = 10 # sets player values
+ args.state.player_jump_power_duration = 5
+ args.state.player_max_run_speed = 20
+ args.state.player_speed_slowdown_rate = 0.9
+ args.state.player_acceleration = 0.9
+end
+
+# outputs objects onto the screen
+def render args
+ if (args.state.player.dx < 0.01) && (args.state.player.dx > -0.01)
+ args.state.player.dx = 0
+ end
+
+ #move list
+ (args.layout.rect_group row: 0, col_from_right: 8, drow: 0.3,
+ merge: { vertical_alignment_enum: 0, size_enum: -2 },
+ group: [
+ { text: "move: WASD" },
+ { text: "jump: Space" },
+ { text: "attack forwards: J (while on ground" },
+ { text: "attack upwards: K (while on groud)" },
+ { text: "attack backwards: J (while on ground and holding A)" },
+ { text: "attack downwards: K (while in air)" },
+ { text: "dash attack: J, K in quick succession." },
+ { text: "shield: hold J, K at the same time." },
+ { text: "dash backwards: A, A in quick succession." },
+ ]).into args.outputs.labels
+
+ # registered moves
+ args.outputs.labels << { x: 0.to_layout_col,
+ y: 0.to_layout_row,
+ text: "input history",
+ size_enum: -2,
+ vertical_alignment_enum: 0 }
+
+ (args.state.inputlist.take(5)).map do |s|
+ { text: s, size_enum: -2, vertical_alignment_enum: 0 }
+ end.yield_self do |group|
+ (args.layout.rect_group row: 0.3, col: 0, drow: 0.3, group: group).into args.outputs.labels
+ end
+
+
+ #sprites
+ player = [args.state.player.x, args.state.player.y,
+ args.state.player.w, args.state.player.h,
+ "sprites/square/white.png",
+ args.state.player.r]
+
+ playershield = [args.state.player.x - 20, args.state.player.y - 10,
+ args.state.player.w + 20, args.state.player.h + 20,
+ "sprites/square/blue.png",
+ args.state.player.r,
+ 0]
+
+ playerjab = [args.state.player.x + 32, args.state.player.y,
+ args.state.player.w, args.state.player.h,
+ "sprites/isometric/indigo.png",
+ args.state.player.r,
+ 0]
+
+ playerupper = [args.state.player.x, args.state.player.y + 32,
+ args.state.player.w, args.state.player.h,
+ "sprites/isometric/indigo.png",
+ args.state.player.r+90,
+ 0]
+
+ if ((args.state.tick_count - args.state.lastpush) <= 15)
+ if (args.state.inputlist[0] == "<<")
+ player = [args.state.player.x, args.state.player.y,
+ args.state.player.w, args.state.player.h,
+ "sprites/square/yellow.png", args.state.player.r]
+ end
+
+ if (args.state.inputlist[0] == "shield")
+ player = [args.state.player.x, args.state.player.y,
+ args.state.player.w, args.state.player.h,
+ "sprites/square/indigo.png", args.state.player.r]
+
+ playershield = [args.state.player.x - 10, args.state.player.y - 10,
+ args.state.player.w + 20, args.state.player.h + 20,
+ "sprites/square/blue.png", args.state.player.r, 50]
+ end
+
+ if (args.state.inputlist[0] == "back-attack")
+ playerjab = [args.state.player.x - 20, args.state.player.y,
+ args.state.player.w - 10, args.state.player.h,
+ "sprites/isometric/indigo.png", args.state.player.r, 255]
+ end
+
+ if (args.state.inputlist[0] == "forward-attack")
+ playerjab = [args.state.player.x + 32, args.state.player.y,
+ args.state.player.w, args.state.player.h,
+ "sprites/isometric/indigo.png", args.state.player.r, 255]
+ end
+
+ if (args.state.inputlist[0] == "up-attack")
+ playerupper = [args.state.player.x, args.state.player.y + 32,
+ args.state.player.w, args.state.player.h,
+ "sprites/isometric/indigo.png", args.state.player.r + 90, 255]
+ end
+
+ if (args.state.inputlist[0] == "dair")
+ playerupper = [args.state.player.x, args.state.player.y - 32,
+ args.state.player.w, args.state.player.h,
+ "sprites/isometric/indigo.png", args.state.player.r + 90, 255]
+ end
+
+ if (args.state.inputlist[0] == "dash-attack")
+ playerupper = [args.state.player.x, args.state.player.y + 32,
+ args.state.player.w, args.state.player.h,
+ "sprites/isometric/violet.png", args.state.player.r + 90, 255]
+
+ playerjab = [args.state.player.x + 32, args.state.player.y,
+ args.state.player.w, args.state.player.h,
+ "sprites/isometric/violet.png", args.state.player.r, 255]
+ end
+ end
+
+ args.outputs.sprites << playerjab
+ args.outputs.sprites << playerupper
+ args.outputs.sprites << player
+ args.outputs.sprites << playershield
+
+ args.outputs.solids << 20.map_with_index do |i| # uses 20 squares to form bridge
+ [i * 64, args.state.bridge_top - 64, 64, 64]
+ end
+end
+
+# Performs calculations to move objects on the screen
+def calc args
+ # Since velocity is the change in position, the change in x increases by dx. Same with y and dy.
+ args.state.player.x += args.state.player.dx
+ args.state.player.y += args.state.player.dy
+
+ # Since acceleration is the change in velocity, the change in y (dy) increases every frame
+ args.state.player.dy += args.state.gravity
+
+ # player's y position is either current y position or y position of top of
+ # bridge, whichever has a greater value
+ # ensures that the player never goes below the bridge
+ args.state.player.y = args.state.player.y.greater(args.state.bridge_top)
+
+ # player's x position is either the current x position or 0, whichever has a greater value
+ # ensures that the player doesn't go too far left (out of the screen's scope)
+ args.state.player.x = args.state.player.x.greater(0)
+
+ # player is not falling if it is located on the top of the bridge
+ args.state.player.falling = false if args.state.player.y == args.state.bridge_top
+ #args.state.player.rect = [args.state.player.x, args.state.player.y, args.state.player.h, args.state.player.w] # sets definition for player
+end
+
+# Resets the player by changing its properties back to the values they had at initialization
+def reset_player args
+ args.state.player.x = 0
+ args.state.player.y = args.state.bridge_top
+ args.state.player.dy = 0
+ args.state.player.dx = 0
+ args.state.enemy.hammers.clear # empties hammer collection
+ args.state.enemy.hammer_queue.clear # empties hammer_queue
+ args.state.game_over_at = args.state.tick_count # game_over_at set to current frame (or passage of time)
+end
+
+# Processes input from the user to move the player
+def input args
+ if args.state.inputlist.length > 5
+ args.state.inputlist.pop
+ end
+
+ should_process_special_move = (args.inputs.keyboard.key_down.j) ||
+ (args.inputs.keyboard.key_down.k) ||
+ (args.inputs.keyboard.key_down.a) ||
+ (args.inputs.keyboard.key_down.d) ||
+ (args.inputs.controller_one.key_down.y) ||
+ (args.inputs.controller_one.key_down.x) ||
+ (args.inputs.controller_one.key_down.left) ||
+ (args.inputs.controller_one.key_down.right)
+
+ if (should_process_special_move)
+ if (args.inputs.keyboard.key_down.j && args.inputs.keyboard.key_down.k) ||
+ (args.inputs.controller_one.key_down.x && args.inputs.controller_one.key_down.y)
+ args.state.inputlist.unshift("shield")
+ elsif (args.inputs.keyboard.key_down.k || args.inputs.controller_one.key_down.y) &&
+ (args.state.inputlist[0] == "forward-attack") && ((args.state.tick_count - args.state.lastpush) <= 15)
+ args.state.inputlist.unshift("dash-attack")
+ args.state.player.dx = 20
+ elsif (args.inputs.keyboard.key_down.j && args.inputs.keyboard.a) ||
+ (args.inputs.controller_one.key_down.x && args.inputs.controller_one.key_down.left)
+ args.state.inputlist.unshift("back-attack")
+ elsif ( args.inputs.controller_one.key_down.x || args.inputs.keyboard.key_down.j)
+ args.state.inputlist.unshift("forward-attack")
+ elsif (args.inputs.keyboard.key_down.k || args.inputs.controller_one.key_down.y) &&
+ (args.state.player.y > 128)
+ args.state.inputlist.unshift("dair")
+ elsif (args.inputs.keyboard.key_down.k || args.inputs.controller_one.key_down.y)
+ args.state.inputlist.unshift("up-attack")
+ elsif (args.inputs.controller_one.key_down.left || args.inputs.keyboard.key_down.a) &&
+ (args.state.inputlist[0] == "<") &&
+ ((args.state.tick_count - args.state.lastpush) <= 10)
+ args.state.inputlist.unshift("<<")
+ args.state.player.dx = -15
+ elsif (args.inputs.controller_one.key_down.left || args.inputs.keyboard.key_down.a)
+ args.state.inputlist.unshift("<")
+ args.state.timeleft = args.state.tick_count
+ elsif (args.inputs.controller_one.key_down.right || args.inputs.keyboard.key_down.d)
+ args.state.inputlist.unshift(">")
+ end
+
+ args.state.lastpush = args.state.tick_count
+ end
+
+ if args.inputs.keyboard.space || args.inputs.controller_one.r2 # if the user presses the space bar
+ args.state.player.jumped_at ||= args.state.tick_count # jumped_at is set to current frame
+
+ # if the time that has passed since the jump is less than the player's jump duration and
+ # the player is not falling
+ if args.state.player.jumped_at.elapsed_time < args.state.player_jump_power_duration && !args.state.player.falling
+ args.state.player.dy = args.state.player_jump_power # change in y is set to power of player's jump
+ end
+ end
+
+ # if the space bar is in the "up" state (or not being pressed down)
+ if args.inputs.keyboard.key_up.space || args.inputs.controller_one.key_up.r2
+ args.state.player.jumped_at = nil # jumped_at is empty
+ args.state.player.falling = true # the player is falling
+ end
+
+ if args.inputs.left # if left key is pressed
+ if args.state.player.dx < -5
+ args.state.player.dx = args.state.player.dx
+ else
+ args.state.player.dx = -5
+ end
+
+ elsif args.inputs.right # if right key is pressed
+ if args.state.player.dx > 5
+ args.state.player.dx = args.state.player.dx
+ else
+ args.state.player.dx = 5
+ end
+ else
+ args.state.player.dx *= args.state.player_speed_slowdown_rate # dx is scaled down
+ end
+
+ if ((args.state.player.dx).abs > 5) #&& ((args.state.tick_count - args.state.lastpush) <= 10)
+ args.state.player.dx *= 0.95
+ end
+end
+
+def tick_instructions args, text, y = 715
+ return if args.state.key_event_occurred
+ if args.inputs.mouse.click ||
+ args.inputs.keyboard.directional_vector ||
+ args.inputs.keyboard.key_down.enter ||
+ args.inputs.keyboard.key_down.space ||
+ args.inputs.keyboard.key_down.escape
+ args.state.key_event_occurred = true
+ end
+
+ args.outputs.debug << [0, y - 50, 1280, 60].solid
+ args.outputs.debug << [640, y, text, 1, 1, 255, 255, 255].label
+ args.outputs.debug << [640, y - 25, "(click to dismiss instructions)" , -2, 1, 255, 255, 255].label
+end
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-indigo.png b/samples/99_genre_fighting/01_special_move_inputs/sprites/isometric/indigo.png
index e6be50c..e6be50c 100644
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-indigo.png
+++ b/samples/99_genre_fighting/01_special_move_inputs/sprites/isometric/indigo.png
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-violet.png b/samples/99_genre_fighting/01_special_move_inputs/sprites/isometric/violet.png
index f09bf21..f09bf21 100644
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-violet.png
+++ b/samples/99_genre_fighting/01_special_move_inputs/sprites/isometric/violet.png
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-blue.png b/samples/99_genre_fighting/01_special_move_inputs/sprites/square/blue.png
index b840849..b840849 100644
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-blue.png
+++ b/samples/99_genre_fighting/01_special_move_inputs/sprites/square/blue.png
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-indigo.png b/samples/99_genre_fighting/01_special_move_inputs/sprites/square/indigo.png
index 2384108..2384108 100644
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-indigo.png
+++ b/samples/99_genre_fighting/01_special_move_inputs/sprites/square/indigo.png
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-white.png b/samples/99_genre_fighting/01_special_move_inputs/sprites/square/white.png
index 378c565..378c565 100644
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-white.png
+++ b/samples/99_genre_fighting/01_special_move_inputs/sprites/square/white.png
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-yellow.png b/samples/99_genre_fighting/01_special_move_inputs/sprites/square/yellow.png
index 0edeeec..0edeeec 100644
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-yellow.png
+++ b/samples/99_genre_fighting/01_special_move_inputs/sprites/square/yellow.png
Binary files differ
diff --git a/samples/99_genre_lowrez/nokia_3310/app/main.rb b/samples/99_genre_lowrez/nokia_3310/app/main.rb
index d275ada..7aa6ba5 100644
--- a/samples/99_genre_lowrez/nokia_3310/app/main.rb
+++ b/samples/99_genre_lowrez/nokia_3310/app/main.rb
@@ -605,7 +605,7 @@ def render_debug args
text: text,
size_enum: -1.5,
r: 255, g: 255, b: 255
- }.label
+ }.label!
end
args.outputs.debug << {
@@ -615,7 +615,7 @@ def render_debug args
size_enum: -0.5,
alignment_enum: 1,
r: 255, g: 255, b: 255
- }.label
+ }.label!
end
def snake_demo args
diff --git a/samples/99_genre_lowrez/nokia_3310/app/nokia.rb b/samples/99_genre_lowrez/nokia_3310/app/nokia.rb
index 077e36f..7bcb5b1 100644
--- a/samples/99_genre_lowrez/nokia_3310/app/nokia.rb
+++ b/samples/99_genre_lowrez/nokia_3310/app/nokia.rb
@@ -236,7 +236,7 @@ module GTK
g: 240,
b: 216,
a: 100
- }.line
+ }.line!
end
(NOKIA_WIDTH + 1).map_with_index do |i|
@@ -249,7 +249,7 @@ module GTK
g: 240,
b: 216,
a: 100
- }.line
+ }.line!
end
@args.state.overlay_rendered = true
diff --git a/samples/99_genre_lowrez/resolution_64x64/app/main.rb b/samples/99_genre_lowrez/resolution_64x64/app/main.rb
index a30d75a..4b1614d 100644
--- a/samples/99_genre_lowrez/resolution_64x64/app/main.rb
+++ b/samples/99_genre_lowrez/resolution_64x64/app/main.rb
@@ -560,7 +560,7 @@ def render_debug args
g: 128,
b: 128,
a: 80
- }.line
+ }.line!
args.outputs.static_debug << {
x: LOWREZ_X_OFFSET + (i * 10),
@@ -571,7 +571,7 @@ def render_debug args
g: 128,
b: 128,
a: 80
- }.line
+ }.line!
end
end
@@ -598,7 +598,7 @@ def render_debug args
y: 720 - (i * 20),
text: text,
size_enum: -1.5
- }.label
+ }.label!
end
args.outputs.debug << {
@@ -607,7 +607,7 @@ def render_debug args
text: "INFO: dev mode is currently enabled. Comment out the invocation of ~render_debug~ within the ~tick~ method to hide the debug layer.",
size_enum: -0.5,
alignment_enum: 1
- }.label
+ }.label!
end
$gtk.reset
diff --git a/samples/99_genre_mario/01_jumping/app/main.rb b/samples/99_genre_mario/01_jumping/app/main.rb
new file mode 100644
index 0000000..2d12a22
--- /dev/null
+++ b/samples/99_genre_mario/01_jumping/app/main.rb
@@ -0,0 +1,78 @@
+def tick args
+ defaults args
+ render args
+ input args
+ calc args
+end
+
+def defaults args
+ args.state.player.x ||= args.grid.w.half
+ args.state.player.y ||= 0
+ args.state.player.size ||= 100
+ args.state.player.dy ||= 0
+ args.state.player.action ||= :jumping
+ args.state.jump.power = 20
+ args.state.jump.increase_frames = 10
+ args.state.jump.increase_power = 1
+ args.state.gravity = -1
+end
+
+def render args
+ args.outputs.sprites << {
+ x: args.state.player.x -
+ args.state.player.size.half,
+ y: args.state.player.y,
+ w: args.state.player.size,
+ h: args.state.player.size,
+ path: 'sprites/square/red.png'
+ }
+end
+
+def input args
+ if args.inputs.keyboard.key_down.space
+ if args.state.player.action == :standing
+ args.state.player.action = :jumping
+ args.state.player.dy = args.state.jump.power
+
+ # record when the action took place
+ current_frame = args.state.tick_count
+ args.state.player.action_at = current_frame
+ end
+ end
+
+ # if the space bar is being held
+ if args.inputs.keyboard.key_held.space
+ # is the player jumping
+ is_jumping = args.state.player.action == :jumping
+
+ # when was the jump performed
+ time_of_jump = args.state.player.action_at
+
+ # how much time has passed since the jump
+ jump_elapsed_time = time_of_jump.elapsed_time
+
+ # how much time is allowed for increasing power
+ time_allowed = args.state.jump.increase_frames
+
+ # if the player is jumping
+ # and the elapsed time is less than
+ # the allowed time
+ if is_jumping && jump_elapsed_time < time_allowed
+ # increase the dy by the increase power
+ power_to_add = args.state.jump.increase_power
+ args.state.player.dy += power_to_add
+ end
+ end
+end
+
+def calc args
+ if args.state.player.action == :jumping
+ args.state.player.y += args.state.player.dy
+ args.state.player.dy += args.state.gravity
+ end
+
+ if args.state.player.y < 0
+ args.state.player.y = 0
+ args.state.player.action = :standing
+ end
+end
diff --git a/samples/99_genre_mario/01_jumping/replay.txt b/samples/99_genre_mario/01_jumping/replay.txt
new file mode 100644
index 0000000..d56d585
--- /dev/null
+++ b/samples/99_genre_mario/01_jumping/replay.txt
@@ -0,0 +1,52 @@
+replay_version 2.0
+stopped_at 574
+seed 100
+recorded_at 2021-11-20 16:44:37 -0600
+[:mouse_button_up, 1, 0, 1, 1, 3]
+[:key_down_raw, 32, 0, 2, 2, 89]
+[:key_up_raw, 32, 0, 2, 3, 92]
+[:key_down_raw, 32, 0, 2, 4, 193]
+[:key_up_raw, 32, 0, 2, 5, 195]
+[:key_down_raw, 32, 0, 2, 6, 258]
+[:key_down_raw, 32, 0, 2, 7, 273]
+[:key_down_raw, 32, 0, 2, 8, 275]
+[:key_down_raw, 32, 0, 2, 9, 277]
+[:key_down_raw, 32, 0, 2, 10, 279]
+[:key_down_raw, 32, 0, 2, 11, 281]
+[:key_down_raw, 32, 0, 2, 12, 283]
+[:key_down_raw, 32, 0, 2, 13, 285]
+[:key_down_raw, 32, 0, 2, 14, 287]
+[:key_down_raw, 32, 0, 2, 15, 289]
+[:key_down_raw, 32, 0, 2, 16, 291]
+[:key_down_raw, 32, 0, 2, 17, 293]
+[:key_down_raw, 32, 0, 2, 18, 295]
+[:key_down_raw, 32, 0, 2, 19, 297]
+[:key_down_raw, 32, 0, 2, 20, 299]
+[:key_down_raw, 32, 0, 2, 21, 301]
+[:key_down_raw, 32, 0, 2, 22, 303]
+[:key_down_raw, 32, 0, 2, 23, 305]
+[:key_down_raw, 32, 0, 2, 24, 307]
+[:key_up_raw, 32, 0, 2, 25, 307]
+[:key_down_raw, 32, 0, 2, 26, 336]
+[:key_up_raw, 32, 0, 2, 27, 339]
+[:key_down_raw, 32, 0, 2, 28, 389]
+[:key_up_raw, 32, 0, 2, 29, 392]
+[:key_down_raw, 32, 0, 2, 30, 444]
+[:key_down_raw, 32, 0, 2, 31, 459]
+[:key_down_raw, 32, 0, 2, 32, 461]
+[:key_down_raw, 32, 0, 2, 33, 463]
+[:key_down_raw, 32, 0, 2, 34, 465]
+[:key_down_raw, 32, 0, 2, 35, 467]
+[:key_down_raw, 32, 0, 2, 36, 469]
+[:key_down_raw, 32, 0, 2, 37, 471]
+[:key_down_raw, 32, 0, 2, 38, 473]
+[:key_down_raw, 32, 0, 2, 39, 475]
+[:key_down_raw, 32, 0, 2, 40, 477]
+[:key_down_raw, 32, 0, 2, 41, 479]
+[:key_down_raw, 32, 0, 2, 42, 481]
+[:key_down_raw, 32, 0, 2, 43, 483]
+[:key_down_raw, 32, 0, 2, 44, 485]
+[:key_up_raw, 32, 0, 2, 45, 485]
+[:key_down_raw, 96, 0, 2, 46, 509]
+[:key_up_raw, 96, 0, 2, 47, 512]
+[:key_down_raw, 13, 0, 2, 48, 574]
diff --git a/samples/99_genre_mario/01_jumping/sprites/square/red.png b/samples/99_genre_mario/01_jumping/sprites/square/red.png
new file mode 100644
index 0000000..a59443e
--- /dev/null
+++ b/samples/99_genre_mario/01_jumping/sprites/square/red.png
Binary files differ
diff --git a/samples/99_genre_mario/02_jumping_and_collisions/app/main.rb b/samples/99_genre_mario/02_jumping_and_collisions/app/main.rb
new file mode 100644
index 0000000..52d9135
--- /dev/null
+++ b/samples/99_genre_mario/02_jumping_and_collisions/app/main.rb
@@ -0,0 +1,281 @@
+class Game
+ attr_gtk
+
+ def tick
+ defaults
+ render
+ input
+ calc
+ end
+
+ def defaults
+ return if state.tick_count != 0
+
+ player.x = 64
+ player.y = 800
+ player.size = 50
+ player.dx = 0
+ player.dy = 0
+ player.action = :falling
+
+ player.max_speed = 20
+ player.jump_power = 15
+ player.jump_air_time = 15
+ player.jump_increase_power = 1
+
+ state.gravity = -1
+ state.drag = 0.001
+ state.tile_size = 64
+ state.tiles ||= [
+ { ordinal_x: 0, ordinal_y: 0 },
+ { ordinal_x: 1, ordinal_y: 0 },
+ { ordinal_x: 2, ordinal_y: 0 },
+ { ordinal_x: 3, ordinal_y: 0 },
+ { ordinal_x: 4, ordinal_y: 0 },
+ { ordinal_x: 5, ordinal_y: 0 },
+ { ordinal_x: 6, ordinal_y: 0 },
+ { ordinal_x: 7, ordinal_y: 0 },
+ { ordinal_x: 8, ordinal_y: 0 },
+ { ordinal_x: 9, ordinal_y: 0 },
+ { ordinal_x: 10, ordinal_y: 0 },
+ { ordinal_x: 11, ordinal_y: 0 },
+ { ordinal_x: 12, ordinal_y: 0 },
+
+ { ordinal_x: 9, ordinal_y: 3 },
+ { ordinal_x: 10, ordinal_y: 3 },
+ { ordinal_x: 11, ordinal_y: 3 },
+ ]
+
+ tiles.each do |t|
+ t.rect = { x: t.ordinal_x * 64,
+ y: t.ordinal_y * 64,
+ w: 64,
+ h: 64 }
+ end
+ end
+
+ def render
+ render_player
+ render_tiles
+ # render_grid
+ end
+
+ def input
+ input_jump
+ input_move
+ end
+
+ def calc
+ calc_player_rect
+ calc_left
+ calc_right
+ calc_below
+ calc_above
+ calc_player_dy
+ calc_player_dx
+ calc_game_over
+ end
+
+ def render_player
+ outputs.sprites << {
+ x: player.x,
+ y: player.y,
+ w: player.size,
+ h: player.size,
+ path: 'sprites/square/red.png'
+ }
+ end
+
+ def render_tiles
+ outputs.sprites << state.tiles.map do |t|
+ t.merge path: 'sprites/square/white.png',
+ x: t.ordinal_x * 64,
+ y: t.ordinal_y * 64,
+ w: 64,
+ h: 64
+ end
+ end
+
+ def render_grid
+ if state.tick_count == 0
+ outputs[:grid].background_color = [0, 0, 0, 0]
+ outputs[:grid].borders << available_brick_locations
+ outputs[:grid].labels << available_brick_locations.map do |b|
+ [
+ b.merge(text: "#{b.ordinal_x},#{b.ordinal_y}",
+ x: b.x + 2,
+ y: b.y + 2,
+ size_enum: -3,
+ vertical_alignment_enum: 0,
+ blendmode_enum: 0),
+ b.merge(text: "#{b.x},#{b.y}",
+ x: b.x + 2,
+ y: b.y + 2 + 20,
+ size_enum: -3,
+ vertical_alignment_enum: 0,
+ blendmode_enum: 0)
+ ]
+ end
+ end
+
+ outputs.sprites << { x: 0, y: 0, w: 1280, h: 720, path: :grid }
+ end
+
+ def input_jump
+ if inputs.keyboard.key_down.space
+ player_jump
+ end
+
+ if inputs.keyboard.key_held.space
+ player_jump_increase_air_time
+ end
+ end
+
+ def input_move
+ if player.dx.abs < 20
+ if inputs.keyboard.left
+ player.dx -= 2
+ elsif inputs.keyboard.right
+ player.dx += 2
+ end
+ end
+ end
+
+ def calc_game_over
+ if player.y < -64
+ player.x = 64
+ player.y = 800
+ player.dx = 0
+ player.dy = 0
+ end
+ end
+
+ def calc_player_rect
+ player.rect = player_current_rect
+ player.next_rect = player_next_rect
+ player.prev_rect = player_prev_rect
+ end
+
+ def calc_player_dx
+ player.dx = player_next_dx
+ player.x += player.dx
+ end
+
+ def calc_player_dy
+ player.y += player.dy
+ player.dy = player_next_dy
+ end
+
+ def calc_below
+ return unless player.dy < 0
+ tiles_below = tiles_find { |t| t.rect.top <= player.prev_rect.y }
+ collision = tiles_find_colliding tiles_below, (player.rect.merge y: player.next_rect.y)
+ if collision
+ player.y = collision.rect.y + state.tile_size
+ player.dy = 0
+ player.action = :standing
+ else
+ player.action = :falling
+ end
+ end
+
+ def calc_left
+ return unless player.dx < 0 && player_next_dx < 0
+ tiles_left = tiles_find { |t| t.rect.right <= player.prev_rect.left }
+ collision = tiles_find_colliding tiles_left, (player.rect.merge x: player.next_rect.x)
+ return unless collision
+ player.x = collision.rect.right
+ player.dx = 0
+ end
+
+ def calc_right
+ return unless player.dx > 0 && player_next_dx > 0
+ tiles_right = tiles_find { |t| t.rect.left >= player.prev_rect.right }
+ collision = tiles_find_colliding tiles_right, (player.rect.merge x: player.next_rect.x)
+ return unless collision
+ player.x = collision.rect.left - player.rect.w
+ player.dx = 0
+ end
+
+ def calc_above
+ return unless player.dy > 0
+ tiles_above = tiles_find { |t| t.rect.y >= player.prev_rect.y }
+ collision = tiles_find_colliding tiles_above, (player.rect.merge y: player.next_rect.y)
+ return unless collision
+ player.dy = 0
+ player.y = collision.rect.bottom - player.rect.h
+ end
+
+ def player_current_rect
+ { x: player.x, y: player.y, w: player.size, h: player.size }
+ end
+
+ def available_brick_locations
+ (0..19).to_a
+ .product(0..11)
+ .map do |(ordinal_x, ordinal_y)|
+ { ordinal_x: ordinal_x,
+ ordinal_y: ordinal_y,
+ x: ordinal_x * 64,
+ y: ordinal_y * 64,
+ w: 64,
+ h: 64 }
+ end
+ end
+
+ def player
+ state.player ||= args.state.new_entity :player
+ end
+
+ def player_next_dy
+ player.dy + state.gravity + state.drag ** 2 * -1
+ end
+
+ def player_next_dx
+ player.dx * 0.8
+ end
+
+ def player_next_rect
+ player.rect.merge x: player.x + player_next_dx,
+ y: player.y + player_next_dy
+ end
+
+ def player_prev_rect
+ player.rect.merge x: player.x - player.dx,
+ y: player.y - player.dy
+ end
+
+ def player_jump
+ return if player.action != :standing
+ player.action = :jumping
+ player.dy = state.player.jump_power
+ current_frame = state.tick_count
+ player.action_at = current_frame
+ end
+
+ def player_jump_increase_air_time
+ return if player.action != :jumping
+ return if player.action_at.elapsed_time >= player.jump_air_time
+ player.dy += player.jump_increase_power
+ end
+
+ def tiles
+ state.tiles
+ end
+
+ def tiles_find_colliding tiles, target
+ tiles.find { |t| t.rect.intersect_rect? target }
+ end
+
+ def tiles_find &block
+ tiles.find_all(&block)
+ end
+end
+
+def tick args
+ $game ||= Game.new
+ $game.args = args
+ $game.tick
+end
+
+$gtk.reset
diff --git a/samples/99_genre_mario/02_jumping_and_collisions/replay.txt b/samples/99_genre_mario/02_jumping_and_collisions/replay.txt
new file mode 100644
index 0000000..17e610f
--- /dev/null
+++ b/samples/99_genre_mario/02_jumping_and_collisions/replay.txt
@@ -0,0 +1,159 @@
+replay_version 2.0
+stopped_at 913
+seed 100
+recorded_at 2021-11-20 17:04:30 -0600
+[:mouse_move, 784, 90, 2, 1, 1]
+[:mouse_button_up, 1, 0, 1, 2, 4]
+[:mouse_move, 785, 90, 2, 3, 7]
+[:key_down_raw, 1073741903, 0, 2, 4, 63]
+[:key_down_raw, 1073741903, 0, 2, 5, 78]
+[:key_down_raw, 1073741903, 0, 2, 6, 81]
+[:key_down_raw, 1073741903, 0, 2, 7, 83]
+[:key_down_raw, 1073741903, 0, 2, 8, 85]
+[:key_down_raw, 1073741903, 0, 2, 9, 87]
+[:key_down_raw, 1073741903, 0, 2, 10, 89]
+[:key_down_raw, 1073741903, 0, 2, 11, 91]
+[:key_down_raw, 1073741903, 0, 2, 12, 93]
+[:key_down_raw, 1073741903, 0, 2, 13, 95]
+[:key_down_raw, 1073741903, 0, 2, 14, 97]
+[:key_down_raw, 1073741903, 0, 2, 15, 99]
+[:key_down_raw, 1073741903, 0, 2, 16, 101]
+[:key_down_raw, 1073741903, 0, 2, 17, 103]
+[:key_down_raw, 1073741903, 0, 2, 18, 105]
+[:key_down_raw, 1073741903, 0, 2, 19, 107]
+[:key_down_raw, 1073741903, 0, 2, 20, 109]
+[:key_down_raw, 1073741903, 0, 2, 21, 111]
+[:key_down_raw, 1073741903, 0, 2, 22, 113]
+[:key_down_raw, 1073741903, 0, 2, 23, 115]
+[:key_down_raw, 1073741903, 0, 2, 24, 117]
+[:key_down_raw, 1073741903, 0, 2, 25, 119]
+[:key_down_raw, 1073741903, 0, 2, 26, 121]
+[:key_up_raw, 1073741903, 0, 2, 27, 121]
+[:key_down_raw, 1073741904, 0, 2, 28, 155]
+[:key_up_raw, 1073741904, 0, 2, 29, 159]
+[:key_down_raw, 32, 0, 2, 30, 170]
+[:key_up_raw, 32, 0, 2, 31, 176]
+[:key_down_raw, 1073741903, 0, 2, 32, 189]
+[:key_up_raw, 1073741903, 0, 2, 33, 199]
+[:key_down_raw, 1073741904, 0, 2, 34, 235]
+[:key_up_raw, 1073741904, 0, 2, 35, 249]
+[:key_down_raw, 32, 0, 2, 36, 258]
+[:key_down_raw, 1073741903, 0, 2, 37, 262]
+[:key_down_raw, 1073741903, 0, 2, 38, 277]
+[:key_down_raw, 1073741903, 0, 2, 39, 279]
+[:key_down_raw, 1073741903, 0, 2, 40, 281]
+[:key_down_raw, 1073741903, 0, 2, 41, 283]
+[:key_down_raw, 1073741903, 0, 2, 42, 285]
+[:key_down_raw, 1073741903, 0, 2, 43, 287]
+[:key_up_raw, 32, 0, 2, 44, 288]
+[:key_down_raw, 1073741903, 0, 2, 45, 289]
+[:key_up_raw, 1073741903, 0, 2, 46, 290]
+[:key_down_raw, 1073741904, 0, 2, 47, 309]
+[:key_down_raw, 32, 0, 2, 48, 320]
+[:key_up_raw, 32, 0, 2, 49, 330]
+[:key_down_raw, 32, 0, 2, 50, 335]
+[:key_up_raw, 32, 0, 2, 51, 339]
+[:key_up_raw, 1073741904, 0, 2, 52, 355]
+[:key_down_raw, 1073741903, 0, 2, 53, 361]
+[:key_down_raw, 1073741903, 0, 2, 54, 376]
+[:key_down_raw, 1073741903, 0, 2, 55, 378]
+[:key_down_raw, 1073741903, 0, 2, 56, 380]
+[:key_down_raw, 1073741903, 0, 2, 57, 382]
+[:key_down_raw, 1073741903, 0, 2, 58, 384]
+[:key_down_raw, 1073741903, 0, 2, 59, 386]
+[:key_down_raw, 1073741903, 0, 2, 60, 388]
+[:key_down_raw, 1073741903, 0, 2, 61, 390]
+[:key_down_raw, 1073741903, 0, 2, 62, 392]
+[:key_down_raw, 1073741903, 0, 2, 63, 394]
+[:key_down_raw, 1073741903, 0, 2, 64, 396]
+[:key_down_raw, 1073741903, 0, 2, 65, 398]
+[:key_down_raw, 1073741903, 0, 2, 66, 400]
+[:key_down_raw, 1073741903, 0, 2, 67, 402]
+[:key_up_raw, 1073741903, 0, 2, 68, 403]
+[:key_down_raw, 32, 0, 2, 69, 408]
+[:key_up_raw, 32, 0, 2, 70, 415]
+[:key_down_raw, 32, 0, 2, 71, 435]
+[:key_up_raw, 32, 0, 2, 72, 450]
+[:key_down_raw, 32, 0, 2, 73, 461]
+[:key_up_raw, 32, 0, 2, 74, 473]
+[:key_down_raw, 1073741903, 0, 2, 75, 480]
+[:key_up_raw, 1073741903, 0, 2, 76, 491]
+[:key_down_raw, 32, 0, 2, 77, 495]
+[:key_down_raw, 32, 0, 2, 78, 509]
+[:key_down_raw, 32, 0, 2, 79, 511]
+[:key_down_raw, 32, 0, 2, 80, 515]
+[:key_down_raw, 32, 0, 2, 81, 515]
+[:key_down_raw, 32, 0, 2, 82, 517]
+[:key_up_raw, 32, 0, 2, 83, 519]
+[:key_down_raw, 1073741903, 0, 2, 84, 525]
+[:key_down_raw, 32, 0, 2, 85, 537]
+[:key_up_raw, 1073741903, 0, 2, 86, 539]
+[:key_up_raw, 32, 0, 2, 87, 549]
+[:key_down_raw, 1073741904, 0, 2, 88, 567]
+[:key_down_raw, 1073741904, 0, 2, 89, 582]
+[:key_down_raw, 1073741904, 0, 2, 90, 584]
+[:key_down_raw, 1073741904, 0, 2, 91, 586]
+[:key_down_raw, 1073741904, 0, 2, 92, 588]
+[:key_down_raw, 1073741904, 0, 2, 93, 591]
+[:key_down_raw, 1073741904, 0, 2, 94, 593]
+[:key_down_raw, 1073741904, 0, 2, 95, 594]
+[:key_up_raw, 1073741904, 0, 2, 96, 595]
+[:key_down_raw, 1073741904, 0, 2, 97, 623]
+[:key_down_raw, 1073741904, 0, 2, 98, 640]
+[:key_down_raw, 1073741904, 0, 2, 99, 640]
+[:key_down_raw, 1073741904, 0, 2, 100, 642]
+[:key_down_raw, 1073741904, 0, 2, 101, 645]
+[:key_down_raw, 1073741904, 0, 2, 102, 647]
+[:key_down_raw, 1073741904, 0, 2, 103, 649]
+[:key_down_raw, 1073741904, 0, 2, 104, 651]
+[:key_up_raw, 1073741904, 0, 2, 105, 652]
+[:key_down_raw, 1073741903, 0, 2, 106, 683]
+[:key_down_raw, 1073741903, 0, 2, 107, 698]
+[:key_down_raw, 1073741903, 0, 2, 108, 700]
+[:key_down_raw, 1073741903, 0, 2, 109, 702]
+[:key_down_raw, 1073741903, 0, 2, 110, 704]
+[:key_down_raw, 1073741903, 0, 2, 111, 706]
+[:key_down_raw, 1073741903, 0, 2, 112, 708]
+[:key_down_raw, 1073741903, 0, 2, 113, 710]
+[:key_down_raw, 1073741903, 0, 2, 114, 712]
+[:key_down_raw, 1073741903, 0, 2, 115, 714]
+[:key_down_raw, 1073741903, 0, 2, 116, 716]
+[:key_down_raw, 1073741903, 0, 2, 117, 718]
+[:key_down_raw, 1073741903, 0, 2, 118, 720]
+[:key_down_raw, 1073741903, 0, 2, 119, 722]
+[:key_down_raw, 1073741903, 0, 2, 120, 724]
+[:key_down_raw, 1073741903, 0, 2, 121, 726]
+[:key_down_raw, 1073741903, 0, 2, 122, 728]
+[:key_down_raw, 1073741903, 0, 2, 123, 730]
+[:key_down_raw, 1073741903, 0, 2, 124, 732]
+[:key_down_raw, 1073741903, 0, 2, 125, 734]
+[:key_down_raw, 1073741903, 0, 2, 126, 736]
+[:key_down_raw, 1073741903, 0, 2, 127, 738]
+[:key_down_raw, 1073741903, 0, 2, 128, 740]
+[:key_down_raw, 1073741903, 0, 2, 129, 742]
+[:key_down_raw, 1073741903, 0, 2, 130, 744]
+[:key_down_raw, 1073741903, 0, 2, 131, 746]
+[:key_down_raw, 1073741903, 0, 2, 132, 748]
+[:key_down_raw, 32, 0, 2, 133, 748]
+[:key_down_raw, 32, 0, 2, 134, 763]
+[:key_down_raw, 32, 0, 2, 135, 765]
+[:key_down_raw, 32, 0, 2, 136, 767]
+[:key_down_raw, 32, 0, 2, 137, 769]
+[:key_down_raw, 32, 0, 2, 138, 771]
+[:key_up_raw, 32, 0, 2, 139, 773]
+[:key_down_raw, 1073741904, 0, 2, 140, 775]
+[:key_up_raw, 1073741903, 0, 2, 141, 776]
+[:key_down_raw, 1073741904, 0, 2, 142, 790]
+[:key_down_raw, 1073741904, 0, 2, 143, 792]
+[:key_down_raw, 1073741904, 0, 2, 144, 794]
+[:key_down_raw, 1073741904, 0, 2, 145, 796]
+[:key_down_raw, 1073741904, 0, 2, 146, 798]
+[:key_down_raw, 1073741904, 0, 2, 147, 801]
+[:key_down_raw, 1073741904, 0, 2, 148, 803]
+[:key_down_raw, 1073741904, 0, 2, 149, 804]
+[:key_down_raw, 1073741904, 0, 2, 150, 807]
+[:key_down_raw, 1073741904, 0, 2, 151, 809]
+[:key_up_raw, 1073741904, 0, 2, 152, 810]
+[:key_down_raw, 96, 0, 2, 153, 854]
+[:key_up_raw, 96, 0, 2, 154, 858]
+[:key_down_raw, 13, 0, 2, 155, 913]
diff --git a/samples/99_genre_mario/02_jumping_and_collisions/sprites/square/red.png b/samples/99_genre_mario/02_jumping_and_collisions/sprites/square/red.png
new file mode 100644
index 0000000..a59443e
--- /dev/null
+++ b/samples/99_genre_mario/02_jumping_and_collisions/sprites/square/red.png
Binary files differ
diff --git a/samples/99_genre_mario/02_jumping_and_collisions/sprites/square/white.png b/samples/99_genre_mario/02_jumping_and_collisions/sprites/square/white.png
new file mode 100644
index 0000000..7a233ea
--- /dev/null
+++ b/samples/99_genre_mario/02_jumping_and_collisions/sprites/square/white.png
Binary files differ
diff --git a/samples/99_genre_platformer/clepto_frog/app/main.rb b/samples/99_genre_platformer/clepto_frog/app/main.rb
index a4eb069..a3a237e 100644
--- a/samples/99_genre_platformer/clepto_frog/app/main.rb
+++ b/samples/99_genre_platformer/clepto_frog/app/main.rb
@@ -1,4 +1,4 @@
-MAP_FILE_PATH = 'app/map.txt'
+MAP_FILE_PATH = 'map.txt'
require 'app/map.rb'
@@ -53,35 +53,7 @@ class CleptoFrog
def render_intro
outputs.labels << [640, 700, "Clepto Frog", 4, 1]
- if state.tick_count >= 120
- outputs.labels << [640, 620, "\"Uh... your office has a pet frog?\" - New Guy",
- 4, 1, 0, 0, 0, 255 * 120.ease(60)]
- end
-
- if state.tick_count >= 240
- outputs.labels << [640, 580, "\"Yep! His name is Clepto.\" - Jim",
- 4, 1, 0, 0, 0, 255 * 240.ease(60)]
- end
-
- if state.tick_count >= 360
- outputs.labels << [640, 540, "\"Uh...\" - New Guy",
- 4, 1, 0, 0, 0, 255 * 360.ease(60)]
- end
-
- if state.tick_count >= 480
- outputs.labels << [640, 500, "\"He steals mugs while we're away...\" - Jim",
- 4, 1, 0, 0, 0, 255 * 480.ease(60)]
- end
-
- if state.tick_count >= 600
- outputs.labels << [640, 460, "\"It's not a big deal, we take them back in the morning.\" - Jim",
- 4, 1, 0, 0, 0, 255 * 600.ease(60)]
- end
-
- outputs.sprites << [640 - 50, 360 - 50, 100, 100,
- "sprites/square-green.png"]
-
- if state.tick_count == 800
+ if state.tick_count == 120
state.scene = :game
state.game_start_at = state.tick_count
end
@@ -89,7 +61,7 @@ class CleptoFrog
def tick
defaults
- if state.scene == :intro && state.tick_count <= 800
+ if state.scene == :intro && state.tick_count <= 120
render_intro
elsif state.scene == :ending
render_ending
@@ -192,15 +164,15 @@ class CleptoFrog
if state.god_mode
# SHOW HIDE COLLISIONS
- outputs.sprites << state.world.map do |x, y, w, h|
- x = vx(x)
- y = vy(y)
+ outputs.sprites << state.world.map do |rect|
+ x = vx(rect.x)
+ y = vy(rect.y)
if x > -80 && x < 1280 && y > -80 && y < 720
{
x: x,
y: y,
- w: vw(w || state.tile_size),
- h: vh(h || state.tile_size),
+ w: vw(rect.w || state.tile_size),
+ h: vh(rect.h || state.tile_size),
path: 'sprites/square-gray.png',
a: 128
}
@@ -223,8 +195,10 @@ class CleptoFrog
# Creates sprite following mouse to help indicate which sprite you have selected
- outputs.primitives << [inputs.mouse.position.x, inputs.mouse.position.y,
- state.tile_size, state.tile_size, 'sprites/square-indigo.png', 0, 100].sprite
+ outputs.primitives << [inputs.mouse.position.x - 32 * state.camera_scale,
+ inputs.mouse.position.y - 32 * state.camera_scale,
+ state.tile_size * state.camera_scale,
+ state.tile_size * state.camera_scale, 'sprites/square-indigo.png', 0, 100].sprite
end
render_mini_map
@@ -305,6 +279,29 @@ class CleptoFrog
set_camera_scale 1
end
+ if inputs.mouse.click
+ state.id_seed += 1
+ id = state.id_seed
+ x = state.camera_x + (inputs.mouse.click.x.fdiv(state.camera_scale) - 32)
+ y = state.camera_y + (inputs.mouse.click.y.fdiv(state.camera_scale) - 32)
+ x = ((x + 2).idiv 4) * 4
+ y = ((y + 2).idiv 4) * 4
+ w = 64
+ h = 64
+ candidate_rect = { id: id, x: x, y: y, w: w, h: h }
+ scaled_candidate_rect = { x: x + 30, y: y + 30, w: w - 60, h: h - 60 }
+ to_remove = state.world.find { |r| r.intersect_rect? scaled_candidate_rect }
+ if to_remove && args.inputs.keyboard.x
+ state.world.reject! { |r| r.id == to_remove.id }
+ else
+ state.world << candidate_rect
+ end
+ export_map
+ state.world_lookup = {}
+ state.world_collision_rects = nil
+ calc_world_lookup
+ end
+
if input_up?
state.y += 10
state.dy = 0
@@ -326,12 +323,6 @@ class CleptoFrog
if state.scene == :game
process_inputs_player_movement
process_inputs_god_mode
- elsif state.scene == :intro
- if args.inputs.keyboard.key_down.enter || args.inputs.keyboard.key_down.space
- if Kernel.tick_count < 600
- Kernel.tick_count = 600
- end
- end
end
end
@@ -429,17 +420,6 @@ class CleptoFrog
end
end
- def add_floors
- # floors
- state.world += [
- [0, 0, 10000, 40],
- [0, 1670, 3250, 60],
- [6691, 1653, 3290, 60],
- [1521, 3792, 7370, 60],
- [0, 5137, 3290, 60]
- ]
- end
-
def attempt_load_world_from_file
return if state.world
# exported_world = gtk.read_file(MAP_FILE_PATH)
@@ -447,26 +427,11 @@ class CleptoFrog
state.objects = []
if $collisions
- $collisions.map do |x, y, w, h|
- state.world << [x, y, w, h]
+ state.id_seed ||= 0
+ $collisions.each do |x, y, w, h|
+ state.id_seed += 1
+ state.world << { id: state.id_seed, x: x, y: y, w: w, h: h }
end
-
- add_floors
- # elsif exported_world
- # exported_world.each_line.map do |l|
- # tokens = l.strip.split(',')
- # x = tokens[0].to_i
- # y = tokens[1].to_i
- # type = tokens[2].to_i
- # if type == 1
- # state.world << [x, y, state.tile_size, state.tile_size]
- # elsif type == 2
- # w, h, path = tokens[3..-1]
- # state.objects << [x, y, w.to_i, h.to_i, path]
- # end
- # end
-
- # add_floors
end
if $mugs
@@ -487,23 +452,24 @@ class CleptoFrog
# Searches through the world and finds the cordinates that exist
state.world_lookup = {}
- state.world.each do |x, y, w, h|
- state.world_lookup[[x, y, w || state.tile_size, h || state.tile_size]] = true
+ state.world.each do |rect|
+ state.world_lookup[rect.id] = rect
end
# Assigns collision rects for every sprite drawn
state.world_collision_rects =
state.world_lookup
.keys
- .map do |x, y, w, h|
+ .map do |key|
+ rect = state.world_lookup[key]
s = state.tile_size
- w ||= s
- h ||= s
+ rect.w ||= s
+ rect.h ||= s
{
- args: [x, y, w, h],
- left_right: [x, y + 4, w, h - 6],
- top: [x + 4, y + 6, w - 8, h - 6],
- bottom: [x + 1, y - 1, w - 2, h - 8],
+ args: rect,
+ left_right: { x: rect.x, y: rect.y + 4, w: rect.w, h: rect.h - 6 },
+ top: { x: rect.x + 4, y: rect.y + 6, w: rect.w - 8, h: rect.h - 6 },
+ bottom: { x: rect.x + 1, y: rect.y - 1, w: rect.w - 2, h: rect.h - 8 },
}
end
@@ -559,12 +525,21 @@ class CleptoFrog
def end_of_tongue
p = state.tongue_angle.vector(state.tongue_length)
- [start_of_tongue.x + p.x, start_of_tongue.y + p.y]
+ { x: start_of_tongue.x + p.x, y: start_of_tongue.y + p.y }
end
def calc_shooting
+ calc_shooting_increment
+ calc_shooting_increment
+ calc_shooting_increment
+ calc_shooting_increment
+ calc_shooting_increment
+ calc_shooting_increment
+ end
+
+ def calc_shooting_increment
return unless state.action == :shooting
- state.tongue_length += 30
+ state.tongue_length += 5
potential_anchor = end_of_tongue
if potential_anchor.x <= 0
state.anchor_point = potential_anchor
@@ -583,9 +558,9 @@ class CleptoFrog
state.action = :anchored
outputs.sounds << 'sounds/attached.wav'
else
- anchor_rect = [potential_anchor.x - 5, potential_anchor.y - 5, 10, 10]
+ anchor_rect = { x: potential_anchor.x - 5, y: potential_anchor.y - 5, w: 10, h: 10 }
collision = state.world_collision_rects.find_all do |v|
- [v[:args].x, v[:args].y, v[:args].w, v[:args].h].intersect_rect?(anchor_rect)
+ v[:args].intersect_rect?(anchor_rect)
end.first
if collision
state.anchor_point = potential_anchor
@@ -681,7 +656,7 @@ class CleptoFrog
.first
return unless left_side_collisions
- state.x = left_side_collisions[:left_right].right
+ state.x = left_side_collisions[:left_right].right + 1
state.dx = state.dy.abs * 0.8
state.collision_on_x = true
end
@@ -696,7 +671,7 @@ class CleptoFrog
.first
return unless right_side_collisions
- state.x = right_side_collisions[:left_right].left - state.tile_size
+ state.x = right_side_collisions[:left_right].left - state.tile_size - 1
state.dx = state.dx.abs * 0.8 * -1
state.collision_on_x = true
end
@@ -712,7 +687,7 @@ class CleptoFrog
.first
return unless ceil_collisions
- state.y = ceil_collisions[:bottom].y - state.tile_size
+ state.y = ceil_collisions[:bottom].y - state.tile_size - 1
state.dy = state.dy.abs * 0.8 * -1
state.collision_on_y = true
end
@@ -725,13 +700,17 @@ class CleptoFrog
end
def export_map
- export_string = state.world.map do |x, y|
- "#{x},#{y},1"
- end
+ export_string = "$collisions = [\n"
+ export_string += state.world.map do |rect|
+ "[#{rect.x},#{rect.y},#{rect.w},#{rect.h}],"
+ end.join "\n"
+ export_string += "\n]\n\n"
+ export_string += "$mugs = [\n"
export_string += state.objects.map do |x, y, w, h, path|
- "#{x},#{y},2,#{w},#{h},#{path}"
- end
- gtk.write_file(MAP_FILE_PATH, export_string.join("\n"))
+ "[#{x},#{y},#{w},#{h},'#{path}'],"
+ end.join "\n"
+ export_string += "\n]\n\n"
+ gtk.write_file(MAP_FILE_PATH, export_string)
state.map_saved_at = state.tick_count
end
diff --git a/samples/99_genre_platformer/clepto_frog/app/map.rb b/samples/99_genre_platformer/clepto_frog/app/map.rb
index c048c82..a504ff9 100644
--- a/samples/99_genre_platformer/clepto_frog/app/map.rb
+++ b/samples/99_genre_platformer/clepto_frog/app/map.rb
@@ -989,6 +989,11 @@ $collisions = [
[4459, 3997, 64, 64],
[76, 5215, 64, 64],
[39, 5217, 64, 64],
+ [0, 0, 10000, 40],
+ [0, 1670, 3250, 60],
+ [6691, 1653, 3290, 60],
+ [1521, 3792, 7370, 60],
+ [0, 5137, 3290, 60]
]
$mugs = [
diff --git a/samples/99_genre_platformer/clepto_frog/replay.txt b/samples/99_genre_platformer/clepto_frog/replay.txt
new file mode 100644
index 0000000..8662d31
--- /dev/null
+++ b/samples/99_genre_platformer/clepto_frog/replay.txt
@@ -0,0 +1,249 @@
+replay_version 2.0
+stopped_at 1097
+seed 100
+recorded_at 2021-11-20 11:32:38 -0600
+[:mouse_button_up, 1, 0, 1, 1, 4]
+[:key_down_raw, 1073741903, 0, 2, 2, 157]
+[:key_down_raw, 1073741903, 0, 2, 3, 171]
+[:key_down_raw, 1073741903, 0, 2, 4, 174]
+[:key_down_raw, 1073741903, 0, 2, 5, 176]
+[:key_down_raw, 1073741903, 0, 2, 6, 177]
+[:key_down_raw, 1073741903, 0, 2, 7, 179]
+[:key_down_raw, 1073741903, 0, 2, 8, 181]
+[:key_down_raw, 1073741903, 0, 2, 9, 182]
+[:key_down_raw, 1073741903, 0, 2, 10, 185]
+[:key_up_raw, 1073741903, 0, 2, 11, 185]
+[:key_down_raw, 32, 0, 2, 12, 187]
+[:key_up_raw, 32, 0, 2, 13, 190]
+[:key_down_raw, 1073741906, 0, 2, 14, 231]
+[:key_down_raw, 1073741903, 0, 2, 15, 239]
+[:key_down_raw, 1073741903, 0, 2, 16, 252]
+[:key_down_raw, 1073741903, 0, 2, 17, 254]
+[:key_down_raw, 1073741903, 0, 2, 18, 256]
+[:key_down_raw, 1073741903, 0, 2, 19, 258]
+[:key_down_raw, 1073741903, 0, 2, 20, 259]
+[:key_down_raw, 1073741903, 0, 2, 21, 261]
+[:key_down_raw, 1073741903, 0, 2, 22, 263]
+[:key_down_raw, 1073741903, 0, 2, 23, 265]
+[:key_down_raw, 1073741903, 0, 2, 24, 267]
+[:key_down_raw, 1073741903, 0, 2, 25, 269]
+[:key_down_raw, 1073741903, 0, 2, 26, 271]
+[:key_down_raw, 1073741903, 0, 2, 27, 273]
+[:key_down_raw, 1073741903, 0, 2, 28, 274]
+[:key_down_raw, 1073741903, 0, 2, 29, 276]
+[:key_down_raw, 1073741903, 0, 2, 30, 278]
+[:key_down_raw, 1073741903, 0, 2, 31, 280]
+[:key_down_raw, 1073741903, 0, 2, 32, 282]
+[:key_down_raw, 1073741903, 0, 2, 33, 284]
+[:key_down_raw, 1073741903, 0, 2, 34, 286]
+[:key_down_raw, 1073741903, 0, 2, 35, 287]
+[:key_down_raw, 1073741903, 0, 2, 36, 289]
+[:key_down_raw, 1073741903, 0, 2, 37, 291]
+[:key_down_raw, 1073741903, 0, 2, 38, 293]
+[:key_down_raw, 1073741903, 0, 2, 39, 295]
+[:key_down_raw, 1073741903, 0, 2, 40, 296]
+[:key_down_raw, 1073741903, 0, 2, 41, 298]
+[:key_down_raw, 1073741903, 0, 2, 42, 300]
+[:key_down_raw, 1073741903, 0, 2, 43, 302]
+[:key_down_raw, 1073741903, 0, 2, 44, 303]
+[:key_down_raw, 1073741903, 0, 2, 45, 305]
+[:key_down_raw, 1073741903, 0, 2, 46, 307]
+[:key_down_raw, 1073741903, 0, 2, 47, 309]
+[:key_down_raw, 1073741903, 0, 2, 48, 310]
+[:key_down_raw, 1073741903, 0, 2, 49, 312]
+[:key_down_raw, 1073741903, 0, 2, 50, 314]
+[:key_down_raw, 1073741903, 0, 2, 51, 316]
+[:key_down_raw, 1073741903, 0, 2, 52, 318]
+[:key_down_raw, 1073741903, 0, 2, 53, 320]
+[:key_down_raw, 1073741903, 0, 2, 54, 322]
+[:key_down_raw, 1073741903, 0, 2, 55, 324]
+[:key_down_raw, 1073741903, 0, 2, 56, 326]
+[:key_down_raw, 1073741903, 0, 2, 57, 328]
+[:key_down_raw, 1073741903, 0, 2, 58, 330]
+[:key_down_raw, 1073741903, 0, 2, 59, 332]
+[:key_down_raw, 1073741903, 0, 2, 60, 334]
+[:key_down_raw, 1073741903, 0, 2, 61, 336]
+[:key_down_raw, 1073741903, 0, 2, 62, 338]
+[:key_down_raw, 1073741903, 0, 2, 63, 340]
+[:key_down_raw, 1073741903, 0, 2, 64, 342]
+[:key_down_raw, 1073741903, 0, 2, 65, 344]
+[:key_down_raw, 1073741903, 0, 2, 66, 345]
+[:key_down_raw, 1073741903, 0, 2, 67, 347]
+[:key_down_raw, 1073741903, 0, 2, 68, 349]
+[:key_up_raw, 1073741906, 0, 2, 69, 351]
+[:key_down_raw, 1073741903, 0, 2, 70, 351]
+[:key_down_raw, 1073741903, 0, 2, 71, 353]
+[:key_down_raw, 1073741903, 0, 2, 72, 355]
+[:key_down_raw, 1073741903, 0, 2, 73, 357]
+[:key_down_raw, 1073741903, 0, 2, 74, 359]
+[:key_down_raw, 1073741903, 0, 2, 75, 361]
+[:key_down_raw, 1073741903, 0, 2, 76, 363]
+[:key_down_raw, 1073741903, 0, 2, 77, 365]
+[:key_down_raw, 1073741903, 0, 2, 78, 367]
+[:key_down_raw, 1073741903, 0, 2, 79, 369]
+[:key_down_raw, 1073741903, 0, 2, 80, 371]
+[:key_down_raw, 1073741903, 0, 2, 81, 373]
+[:key_down_raw, 1073741903, 0, 2, 82, 375]
+[:key_down_raw, 1073741903, 0, 2, 83, 376]
+[:key_down_raw, 1073741903, 0, 2, 84, 378]
+[:key_down_raw, 1073741903, 0, 2, 85, 380]
+[:key_down_raw, 1073741903, 0, 2, 86, 382]
+[:key_down_raw, 1073741903, 0, 2, 87, 384]
+[:key_down_raw, 1073741903, 0, 2, 88, 386]
+[:key_down_raw, 1073741906, 0, 2, 89, 386]
+[:key_down_raw, 1073741906, 0, 2, 90, 400]
+[:key_down_raw, 1073741906, 0, 2, 91, 402]
+[:key_down_raw, 1073741906, 0, 2, 92, 404]
+[:key_down_raw, 1073741906, 0, 2, 93, 405]
+[:key_down_raw, 1073741906, 0, 2, 94, 407]
+[:key_down_raw, 1073741906, 0, 2, 95, 409]
+[:key_down_raw, 1073741906, 0, 2, 96, 411]
+[:key_down_raw, 1073741906, 0, 2, 97, 413]
+[:key_down_raw, 1073741906, 0, 2, 98, 415]
+[:key_down_raw, 1073741906, 0, 2, 99, 417]
+[:key_down_raw, 1073741906, 0, 2, 100, 419]
+[:key_down_raw, 1073741906, 0, 2, 101, 421]
+[:key_down_raw, 1073741906, 0, 2, 102, 422]
+[:key_down_raw, 1073741906, 0, 2, 103, 424]
+[:key_down_raw, 1073741906, 0, 2, 104, 426]
+[:key_down_raw, 1073741906, 0, 2, 105, 428]
+[:key_down_raw, 1073741906, 0, 2, 106, 430]
+[:key_down_raw, 1073741906, 0, 2, 107, 432]
+[:key_down_raw, 1073741906, 0, 2, 108, 434]
+[:key_down_raw, 32, 0, 2, 109, 434]
+[:key_up_raw, 32, 0, 2, 110, 442]
+[:key_up_raw, 1073741906, 0, 2, 111, 460]
+[:key_up_raw, 1073741903, 0, 2, 112, 576]
+[:key_down_raw, 1073741903, 0, 2, 113, 588]
+[:key_down_raw, 1073741903, 0, 2, 114, 602]
+[:key_down_raw, 1073741903, 0, 2, 115, 604]
+[:key_down_raw, 1073741903, 0, 2, 116, 606]
+[:key_down_raw, 1073741903, 0, 2, 117, 608]
+[:key_down_raw, 1073741903, 0, 2, 118, 610]
+[:key_down_raw, 1073741903, 0, 2, 119, 612]
+[:key_down_raw, 1073741903, 0, 2, 120, 614]
+[:key_down_raw, 1073741903, 0, 2, 121, 616]
+[:key_down_raw, 1073741903, 0, 2, 122, 617]
+[:key_down_raw, 1073741903, 0, 2, 123, 619]
+[:key_down_raw, 1073741903, 0, 2, 124, 621]
+[:key_down_raw, 1073741903, 0, 2, 125, 623]
+[:key_down_raw, 1073741903, 0, 2, 126, 624]
+[:key_down_raw, 1073741903, 0, 2, 127, 626]
+[:key_down_raw, 1073741903, 0, 2, 128, 628]
+[:key_down_raw, 1073741903, 0, 2, 129, 630]
+[:key_down_raw, 1073741903, 0, 2, 130, 632]
+[:key_down_raw, 1073741903, 0, 2, 131, 634]
+[:key_down_raw, 1073741903, 0, 2, 132, 636]
+[:key_down_raw, 1073741903, 0, 2, 133, 638]
+[:key_down_raw, 1073741903, 0, 2, 134, 640]
+[:key_down_raw, 1073741903, 0, 2, 135, 641]
+[:key_down_raw, 1073741903, 0, 2, 136, 643]
+[:key_down_raw, 1073741903, 0, 2, 137, 645]
+[:key_down_raw, 1073741903, 0, 2, 138, 647]
+[:key_down_raw, 1073741903, 0, 2, 139, 649]
+[:key_down_raw, 1073741903, 0, 2, 140, 651]
+[:key_down_raw, 1073741903, 0, 2, 141, 653]
+[:key_down_raw, 1073741903, 0, 2, 142, 655]
+[:key_down_raw, 1073741903, 0, 2, 143, 656]
+[:key_down_raw, 1073741903, 0, 2, 144, 658]
+[:key_down_raw, 1073741903, 0, 2, 145, 660]
+[:key_down_raw, 1073741903, 0, 2, 146, 662]
+[:key_down_raw, 1073741903, 0, 2, 147, 664]
+[:key_down_raw, 1073741903, 0, 2, 148, 666]
+[:key_down_raw, 1073741903, 0, 2, 149, 668]
+[:key_down_raw, 1073741903, 0, 2, 150, 670]
+[:key_down_raw, 1073741903, 0, 2, 151, 672]
+[:key_down_raw, 1073741903, 0, 2, 152, 674]
+[:key_down_raw, 1073741903, 0, 2, 153, 676]
+[:key_down_raw, 1073741903, 0, 2, 154, 678]
+[:key_down_raw, 1073741903, 0, 2, 155, 680]
+[:key_down_raw, 1073741903, 0, 2, 156, 681]
+[:key_down_raw, 1073741903, 0, 2, 157, 683]
+[:key_down_raw, 32, 0, 2, 158, 684]
+[:key_up_raw, 1073741903, 0, 2, 159, 686]
+[:key_up_raw, 32, 0, 2, 160, 689]
+[:key_down_raw, 1073741904, 0, 2, 161, 692]
+[:key_down_raw, 1073741904, 0, 2, 162, 704]
+[:key_down_raw, 1073741904, 0, 2, 163, 706]
+[:key_down_raw, 1073741904, 0, 2, 164, 707]
+[:key_down_raw, 1073741904, 0, 2, 165, 709]
+[:key_down_raw, 1073741904, 0, 2, 166, 711]
+[:key_down_raw, 1073741904, 0, 2, 167, 713]
+[:key_down_raw, 1073741904, 0, 2, 168, 715]
+[:key_up_raw, 1073741904, 0, 2, 169, 717]
+[:key_down_raw, 32, 0, 2, 170, 769]
+[:key_up_raw, 32, 0, 2, 171, 775]
+[:key_down_raw, 1073741904, 0, 2, 172, 785]
+[:key_down_raw, 1073741904, 0, 2, 173, 799]
+[:key_down_raw, 1073741904, 0, 2, 174, 801]
+[:key_down_raw, 1073741904, 0, 2, 175, 803]
+[:key_down_raw, 1073741904, 0, 2, 176, 805]
+[:key_down_raw, 1073741904, 0, 2, 177, 807]
+[:key_down_raw, 1073741904, 0, 2, 178, 810]
+[:key_down_raw, 1073741904, 0, 2, 179, 812]
+[:key_down_raw, 1073741904, 0, 2, 180, 814]
+[:key_down_raw, 1073741904, 0, 2, 181, 816]
+[:key_down_raw, 1073741904, 0, 2, 182, 818]
+[:key_down_raw, 1073741904, 0, 2, 183, 820]
+[:key_down_raw, 1073741904, 0, 2, 184, 822]
+[:key_down_raw, 1073741904, 0, 2, 185, 824]
+[:key_down_raw, 1073741904, 0, 2, 186, 826]
+[:key_down_raw, 1073741904, 0, 2, 187, 828]
+[:key_down_raw, 1073741904, 0, 2, 188, 830]
+[:key_down_raw, 1073741904, 0, 2, 189, 832]
+[:key_down_raw, 1073741904, 0, 2, 190, 834]
+[:key_down_raw, 1073741904, 0, 2, 191, 836]
+[:key_down_raw, 1073741904, 0, 2, 192, 838]
+[:key_down_raw, 1073741904, 0, 2, 193, 840]
+[:key_down_raw, 1073741904, 0, 2, 194, 841]
+[:key_down_raw, 1073741904, 0, 2, 195, 843]
+[:key_down_raw, 1073741904, 0, 2, 196, 845]
+[:key_down_raw, 1073741904, 0, 2, 197, 847]
+[:key_down_raw, 1073741904, 0, 2, 198, 849]
+[:key_down_raw, 1073741904, 0, 2, 199, 851]
+[:key_down_raw, 1073741904, 0, 2, 200, 853]
+[:key_down_raw, 1073741904, 0, 2, 201, 855]
+[:key_down_raw, 1073741904, 0, 2, 202, 857]
+[:key_down_raw, 1073741904, 0, 2, 203, 859]
+[:key_down_raw, 1073741904, 0, 2, 204, 861]
+[:key_down_raw, 1073741904, 0, 2, 205, 863]
+[:key_down_raw, 1073741904, 0, 2, 206, 864]
+[:key_down_raw, 1073741904, 0, 2, 207, 866]
+[:key_down_raw, 1073741904, 0, 2, 208, 868]
+[:key_down_raw, 1073741904, 0, 2, 209, 870]
+[:key_down_raw, 1073741904, 0, 2, 210, 872]
+[:key_down_raw, 1073741904, 0, 2, 211, 874]
+[:key_down_raw, 1073741904, 0, 2, 212, 876]
+[:key_down_raw, 1073741904, 0, 2, 213, 878]
+[:key_down_raw, 1073741904, 0, 2, 214, 880]
+[:key_down_raw, 1073741904, 0, 2, 215, 882]
+[:key_down_raw, 1073741904, 0, 2, 216, 884]
+[:key_down_raw, 1073741904, 0, 2, 217, 886]
+[:key_down_raw, 1073741904, 0, 2, 218, 887]
+[:key_down_raw, 1073741904, 0, 2, 219, 889]
+[:key_down_raw, 1073741904, 0, 2, 220, 891]
+[:key_down_raw, 1073741904, 0, 2, 221, 893]
+[:key_down_raw, 1073741904, 0, 2, 222, 895]
+[:key_down_raw, 1073741904, 0, 2, 223, 897]
+[:key_down_raw, 1073741904, 0, 2, 224, 899]
+[:key_down_raw, 1073741904, 0, 2, 225, 901]
+[:key_down_raw, 1073741904, 0, 2, 226, 903]
+[:key_down_raw, 1073741904, 0, 2, 227, 905]
+[:key_down_raw, 1073741904, 0, 2, 228, 907]
+[:key_down_raw, 1073741904, 0, 2, 229, 909]
+[:key_down_raw, 1073741904, 0, 2, 230, 911]
+[:key_down_raw, 1073741904, 0, 2, 231, 913]
+[:key_down_raw, 1073741904, 0, 2, 232, 915]
+[:key_down_raw, 1073741904, 0, 2, 233, 917]
+[:key_down_raw, 1073741904, 0, 2, 234, 919]
+[:key_down_raw, 1073741904, 0, 2, 235, 921]
+[:key_down_raw, 1073741904, 0, 2, 236, 923]
+[:key_down_raw, 1073741904, 0, 2, 237, 925]
+[:key_down_raw, 1073741904, 0, 2, 238, 927]
+[:key_down_raw, 1073741904, 0, 2, 239, 929]
+[:key_up_raw, 1073741904, 0, 2, 240, 930]
+[:key_down_raw, 1073741904, 0, 2, 241, 1024]
+[:key_up_raw, 1073741904, 0, 2, 242, 1036]
+[:key_down_raw, 96, 0, 2, 243, 1046]
+[:key_up_raw, 96, 0, 2, 244, 1050]
+[:key_down_raw, 13, 0, 2, 245, 1097]
diff --git a/samples/99_genre_platformer/gorillas_basic/app/repl.rb b/samples/99_genre_platformer/gorillas_basic/app/repl.rb
deleted file mode 100644
index 4428c4b..0000000
--- a/samples/99_genre_platformer/gorillas_basic/app/repl.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-begin
- if $gtk.args.state.current_turn == :player_1_angle
- $gtk.args.state.player_1_angle = "#{60 + 10.randomize(:ratio).to_i}"
- $you_so_basic_gorillas.input_execute_turn
- $gtk.args.state.player_1_velocity = "#{30 + 20.randomize(:ratio).to_i}"
- $you_so_basic_gorillas.input_execute_turn
- elsif $gtk.args.state.current_turn == :player_2_angle
- $gtk.args.state.player_2_angle = "#{60 + 10.randomize(:ratio).to_i}"
- $you_so_basic_gorillas.input_execute_turn
- $gtk.args.state.player_2_velocity = "#{30 + 20.randomize(:ratio).to_i}"
- $you_so_basic_gorillas.input_execute_turn
- else
- $you_so_basic_gorillas.input_execute_turn
- end
-rescue Exception => e
- puts e
-end
diff --git a/samples/99_genre_platformer/the_little_probe/app/main.rb b/samples/99_genre_platformer/the_little_probe/app/main.rb
index 8fcf279..9d43ce6 100644
--- a/samples/99_genre_platformer/the_little_probe/app/main.rb
+++ b/samples/99_genre_platformer/the_little_probe/app/main.rb
@@ -394,6 +394,7 @@ class FallingCircle
end
def load_lines file
+ return unless state.snaps
data = gtk.read_file(file) || ""
data.each_line
.reject { |l| l.strip.length == 0 }
@@ -452,10 +453,10 @@ class FallingCircle
results[:point] = { x: x, y: y }
results[:rect] = { x: x - radius, y: y - radius, w: radius * 2, h: radius * 2 }
results[:trajectory] = trajectory(results)
- results[:impacts] = terrain.find_all { |t| line_near_rect? results[:rect], t }.map do |t|
+ results[:impacts] = terrain.find_all { |t| t && (line_near_rect? results[:rect], t) }.map do |t|
{
terrain: t,
- point: geometry.line_intersect(results[:trajectory], t),
+ point: geometry.line_intersect(results[:trajectory], t, replace_infinity: 1000),
type: :terrain
}
end.reject { |t| !point_within_line? t[:point], t[:terrain] }
@@ -463,10 +464,10 @@ class FallingCircle
results[:impacts] += lava.find_all { |t| line_near_rect? results[:rect], t }.map do |t|
{
terrain: t,
- point: geometry.line_intersect(results[:trajectory], t),
+ point: geometry.line_intersect(results[:trajectory], t, replace_infinity: 1000),
type: :lava
}
- end.reject { |t| !point_within_line? t[:point], t[:terrain] }
+ end.reject { |t| !t || (!point_within_line? t[:point], t[:terrain]) }
results
end
@@ -479,6 +480,7 @@ class FallingCircle
end
def calc_terrains_to_monitor
+ return unless circle.impacts
circle.impact = nil
circle.impacts.each do |i|
circle.terrains_to_monitor[i[:terrain]] ||= {
diff --git a/samples/99_genre_platformer/the_little_probe/bug-replay.txt b/samples/99_genre_platformer/the_little_probe/bug-replay.txt
new file mode 100644
index 0000000..378d3c3
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/bug-replay.txt
@@ -0,0 +1,205 @@
+replay_version 2.0
+stopped_at 2085
+seed 100
+recorded_at 2021-11-20 11:34:07 -0600
+[:mouse_button_up, 1, 0, 1, 1, 1]
+[:mouse_move, 803, 93, 2, 2, 31]
+[:mouse_move, 811, 93, 2, 3, 32]
+[:key_down_raw, 1073741903, 0, 2, 4, 123]
+[:key_down_raw, 1073741903, 0, 2, 5, 137]
+[:key_down_raw, 1073741903, 0, 2, 6, 139]
+[:key_down_raw, 1073741903, 0, 2, 7, 141]
+[:key_down_raw, 1073741903, 0, 2, 8, 143]
+[:key_down_raw, 1073741903, 0, 2, 9, 145]
+[:key_down_raw, 1073741903, 0, 2, 10, 147]
+[:key_down_raw, 1073741903, 0, 2, 11, 149]
+[:key_up_raw, 1073741903, 0, 2, 12, 150]
+[:key_down_raw, 32, 0, 2, 13, 171]
+[:key_down_raw, 32, 0, 2, 14, 186]
+[:key_down_raw, 32, 0, 2, 15, 189]
+[:key_down_raw, 32, 0, 2, 16, 190]
+[:key_down_raw, 32, 0, 2, 17, 192]
+[:key_down_raw, 32, 0, 2, 18, 194]
+[:key_down_raw, 32, 0, 2, 19, 196]
+[:key_down_raw, 32, 0, 2, 20, 198]
+[:key_down_raw, 32, 0, 2, 21, 200]
+[:key_down_raw, 32, 0, 2, 22, 202]
+[:key_down_raw, 32, 0, 2, 23, 204]
+[:key_down_raw, 32, 0, 2, 24, 206]
+[:key_down_raw, 32, 0, 2, 25, 208]
+[:key_down_raw, 32, 0, 2, 26, 210]
+[:key_down_raw, 32, 0, 2, 27, 212]
+[:key_down_raw, 32, 0, 2, 28, 214]
+[:key_down_raw, 32, 0, 2, 29, 216]
+[:key_down_raw, 32, 0, 2, 30, 218]
+[:key_down_raw, 32, 0, 2, 31, 221]
+[:key_down_raw, 32, 0, 2, 32, 222]
+[:key_down_raw, 32, 0, 2, 33, 224]
+[:key_down_raw, 32, 0, 2, 34, 227]
+[:key_down_raw, 32, 0, 2, 35, 229]
+[:key_down_raw, 32, 0, 2, 36, 231]
+[:key_down_raw, 32, 0, 2, 37, 233]
+[:key_down_raw, 32, 0, 2, 38, 235]
+[:key_down_raw, 32, 0, 2, 39, 237]
+[:key_down_raw, 32, 0, 2, 40, 239]
+[:key_down_raw, 32, 0, 2, 41, 241]
+[:key_down_raw, 32, 0, 2, 42, 243]
+[:key_down_raw, 32, 0, 2, 43, 245]
+[:key_down_raw, 32, 0, 2, 44, 247]
+[:key_down_raw, 32, 0, 2, 45, 249]
+[:key_down_raw, 32, 0, 2, 46, 251]
+[:key_down_raw, 32, 0, 2, 47, 253]
+[:key_down_raw, 32, 0, 2, 48, 255]
+[:key_down_raw, 32, 0, 2, 49, 257]
+[:key_down_raw, 32, 0, 2, 50, 259]
+[:key_down_raw, 32, 0, 2, 51, 261]
+[:key_down_raw, 32, 0, 2, 52, 263]
+[:key_down_raw, 32, 0, 2, 53, 265]
+[:key_down_raw, 32, 0, 2, 54, 267]
+[:key_down_raw, 32, 0, 2, 55, 269]
+[:key_down_raw, 32, 0, 2, 56, 271]
+[:key_down_raw, 1073741903, 0, 2, 57, 272]
+[:key_up_raw, 1073741903, 0, 2, 58, 284]
+[:key_up_raw, 32, 0, 2, 59, 350]
+[:key_down_raw, 1073741904, 0, 2, 60, 611]
+[:key_down_raw, 1073741904, 0, 2, 61, 626]
+[:key_down_raw, 1073741904, 0, 2, 62, 628]
+[:key_down_raw, 1073741904, 0, 2, 63, 630]
+[:key_down_raw, 1073741904, 0, 2, 64, 632]
+[:key_down_raw, 1073741904, 0, 2, 65, 634]
+[:key_down_raw, 1073741904, 0, 2, 66, 636]
+[:key_up_raw, 1073741904, 0, 2, 67, 636]
+[:key_down_raw, 32, 0, 2, 68, 640]
+[:key_down_raw, 32, 0, 2, 69, 655]
+[:key_down_raw, 32, 0, 2, 70, 657]
+[:key_down_raw, 32, 0, 2, 71, 659]
+[:key_down_raw, 32, 0, 2, 72, 661]
+[:key_down_raw, 32, 0, 2, 73, 663]
+[:key_down_raw, 32, 0, 2, 74, 665]
+[:key_down_raw, 1073741903, 0, 2, 75, 666]
+[:key_up_raw, 1073741903, 0, 2, 76, 672]
+[:key_down_raw, 1073741903, 0, 2, 77, 703]
+[:key_down_raw, 1073741903, 0, 2, 78, 717]
+[:key_up_raw, 1073741903, 0, 2, 79, 717]
+[:key_down_raw, 1073741903, 0, 2, 80, 736]
+[:key_up_raw, 1073741903, 0, 2, 81, 741]
+[:key_up_raw, 32, 0, 2, 82, 798]
+[:key_down_raw, 1073741903, 0, 2, 83, 861]
+[:key_down_raw, 1073741903, 0, 2, 84, 876]
+[:key_down_raw, 1073741903, 0, 2, 85, 878]
+[:key_down_raw, 1073741903, 0, 2, 86, 880]
+[:key_down_raw, 1073741903, 0, 2, 87, 882]
+[:key_down_raw, 1073741903, 0, 2, 88, 884]
+[:key_up_raw, 1073741903, 0, 2, 89, 886]
+[:key_down_raw, 1073741903, 0, 2, 90, 1063]
+[:key_down_raw, 1073741903, 0, 2, 91, 1079]
+[:key_down_raw, 1073741903, 0, 2, 92, 1081]
+[:key_down_raw, 1073741903, 0, 2, 93, 1083]
+[:key_down_raw, 1073741903, 0, 2, 94, 1085]
+[:key_down_raw, 1073741903, 0, 2, 95, 1086]
+[:key_down_raw, 1073741903, 0, 2, 96, 1088]
+[:key_down_raw, 1073741903, 0, 2, 97, 1090]
+[:key_down_raw, 1073741903, 0, 2, 98, 1092]
+[:key_down_raw, 1073741903, 0, 2, 99, 1094]
+[:key_down_raw, 1073741903, 0, 2, 100, 1096]
+[:key_down_raw, 1073741903, 0, 2, 101, 1098]
+[:key_down_raw, 1073741903, 0, 2, 102, 1100]
+[:key_down_raw, 1073741903, 0, 2, 103, 1102]
+[:key_down_raw, 1073741903, 0, 2, 104, 1104]
+[:key_down_raw, 1073741903, 0, 2, 105, 1106]
+[:key_down_raw, 1073741903, 0, 2, 106, 1109]
+[:key_down_raw, 1073741903, 0, 2, 107, 1111]
+[:key_down_raw, 1073741903, 0, 2, 108, 1113]
+[:key_down_raw, 1073741903, 0, 2, 109, 1115]
+[:key_down_raw, 1073741903, 0, 2, 110, 1117]
+[:key_down_raw, 1073741903, 0, 2, 111, 1119]
+[:key_down_raw, 1073741903, 0, 2, 112, 1121]
+[:key_down_raw, 1073741903, 0, 2, 113, 1122]
+[:key_down_raw, 1073741903, 0, 2, 114, 1125]
+[:key_down_raw, 1073741903, 0, 2, 115, 1127]
+[:key_down_raw, 1073741903, 0, 2, 116, 1128]
+[:key_down_raw, 1073741903, 0, 2, 117, 1131]
+[:key_down_raw, 1073741903, 0, 2, 118, 1132]
+[:key_down_raw, 1073741903, 0, 2, 119, 1134]
+[:key_down_raw, 1073741903, 0, 2, 120, 1136]
+[:key_down_raw, 1073741903, 0, 2, 121, 1138]
+[:key_down_raw, 1073741903, 0, 2, 122, 1140]
+[:key_down_raw, 1073741903, 0, 2, 123, 1142]
+[:key_up_raw, 1073741903, 0, 2, 124, 1142]
+[:key_down_raw, 32, 0, 2, 125, 1208]
+[:key_down_raw, 32, 0, 2, 126, 1223]
+[:key_down_raw, 32, 0, 2, 127, 1225]
+[:key_down_raw, 1073741903, 0, 2, 128, 1226]
+[:key_up_raw, 1073741903, 0, 2, 129, 1236]
+[:key_down_raw, 1073741904, 0, 2, 130, 1253]
+[:key_up_raw, 1073741904, 0, 2, 131, 1266]
+[:key_down_raw, 1073741903, 0, 2, 132, 1324]
+[:key_up_raw, 1073741903, 0, 2, 133, 1330]
+[:key_down_raw, 1073741903, 0, 2, 134, 1414]
+[:key_up_raw, 1073741903, 0, 2, 135, 1417]
+[:key_up_raw, 32, 0, 2, 136, 1441]
+[:mouse_move, 812, 92, 2, 137, 1607]
+[:mouse_move, 818, 92, 2, 138, 1608]
+[:mouse_move, 818, 91, 2, 139, 1614]
+[:mouse_move, 818, 90, 2, 140, 1622]
+[:mouse_move, 813, 89, 2, 141, 1623]
+[:mouse_move, 801, 86, 2, 142, 1624]
+[:mouse_move, 786, 83, 2, 143, 1625]
+[:mouse_move, 770, 82, 2, 144, 1626]
+[:mouse_move, 756, 82, 2, 145, 1627]
+[:mouse_move, 745, 82, 2, 146, 1628]
+[:mouse_move, 738, 82, 2, 147, 1629]
+[:mouse_move, 731, 83, 2, 148, 1630]
+[:mouse_move, 724, 84, 2, 149, 1631]
+[:mouse_move, 712, 85, 2, 150, 1632]
+[:mouse_move, 707, 87, 2, 151, 1633]
+[:mouse_move, 702, 89, 2, 152, 1634]
+[:mouse_move, 699, 95, 2, 153, 1635]
+[:mouse_move, 693, 102, 2, 154, 1636]
+[:mouse_move, 687, 110, 2, 155, 1637]
+[:mouse_move, 680, 118, 2, 156, 1638]
+[:mouse_move, 671, 125, 2, 157, 1639]
+[:mouse_move, 659, 132, 2, 158, 1640]
+[:mouse_move, 645, 142, 2, 159, 1641]
+[:mouse_move, 632, 153, 2, 160, 1642]
+[:mouse_move, 616, 164, 2, 161, 1643]
+[:mouse_move, 583, 184, 2, 162, 1644]
+[:mouse_move, 554, 198, 2, 163, 1645]
+[:mouse_move, 519, 212, 2, 164, 1646]
+[:mouse_move, 480, 224, 2, 165, 1647]
+[:mouse_move, 445, 234, 2, 166, 1648]
+[:mouse_move, 414, 246, 2, 167, 1649]
+[:mouse_move, 393, 265, 2, 168, 1650]
+[:mouse_move, 388, 276, 2, 169, 1651]
+[:mouse_move, 386, 272, 2, 170, 1665]
+[:mouse_move, 380, 272, 2, 171, 1666]
+[:mouse_move, 366, 272, 2, 172, 1667]
+[:mouse_move, 336, 266, 2, 173, 1668]
+[:mouse_move, 313, 262, 2, 174, 1669]
+[:mouse_move, 294, 258, 2, 175, 1670]
+[:mouse_move, 278, 255, 2, 176, 1671]
+[:mouse_move, 268, 254, 2, 177, 1672]
+[:mouse_move, 263, 253, 2, 178, 1673]
+[:mouse_move, 261, 252, 2, 179, 1674]
+[:mouse_move, 260, 251, 2, 180, 1675]
+[:mouse_move, 258, 250, 2, 181, 1676]
+[:mouse_move, 256, 249, 2, 182, 1677]
+[:mouse_move, 252, 249, 2, 183, 1678]
+[:mouse_move, 251, 249, 2, 184, 1679]
+[:mouse_move, 248, 249, 2, 185, 1680]
+[:mouse_move, 246, 248, 2, 186, 1681]
+[:mouse_move, 242, 247, 2, 187, 1682]
+[:mouse_move, 234, 247, 2, 188, 1683]
+[:mouse_move, 231, 247, 2, 189, 1684]
+[:mouse_move, 230, 247, 2, 190, 1685]
+[:mouse_move, 230, 246, 2, 191, 1688]
+[:mouse_move, 229, 246, 2, 192, 1691]
+[:mouse_move, 228, 246, 2, 193, 1692]
+[:mouse_move, 227, 246, 2, 194, 1702]
+[:mouse_move, 228, 246, 2, 195, 1834]
+[:mouse_move, 229, 246, 2, 196, 1898]
+[:mouse_move, 229, 245, 2, 197, 1968]
+[:key_down_raw, 96, 0, 2, 198, 2024]
+[:mouse_move, 230, 245, 2, 199, 2027]
+[:key_up_raw, 96, 0, 2, 200, 2028]
+[:key_down_raw, 13, 0, 2, 201, 2085]
diff --git a/samples/99_genre_rpg_narrative/choose_your_own_adventure/app/main.rb b/samples/99_genre_rpg_narrative/choose_your_own_adventure/app/main.rb
index 9da0f38..22faad1 100644
--- a/samples/99_genre_rpg_narrative/choose_your_own_adventure/app/main.rb
+++ b/samples/99_genre_rpg_narrative/choose_your_own_adventure/app/main.rb
@@ -14,8 +14,10 @@
- args.outputs.labels: An array. The values generate a label.
The parameters are [X, Y, TEXT, SIZE, ALIGNMENT, RED, GREEN, BLUE, ALPHA, FONT STYLE]
-
+ For more information about labels, go to mygame/documentation/02-labels.md.
+
- args.keyboard.key_down.KEY: Determines if a key is in the down state or pressed down.
+ For more information about the keyboard, go to mygame/documentation/06-keyboard.md.
- String interpolation: uses #{} syntax; everything between the #{ and the } is evaluated
as Ruby code, and the placeholder is replaced with its corresponding value or result.
diff --git a/samples/99_genre_rpg_narrative/return_of_serenity/app/repl.rb b/samples/99_genre_rpg_narrative/return_of_serenity/app/repl.rb
deleted file mode 100644
index a59baf5..0000000
--- a/samples/99_genre_rpg_narrative/return_of_serenity/app/repl.rb
+++ /dev/null
@@ -1 +0,0 @@
-puts $gtk.args.state.current_scene
diff --git a/samples/99_genre_rpg_roguelike/01_roguelike_starting_point/replay.txt b/samples/99_genre_rpg_roguelike/01_roguelike_starting_point/replay.txt
new file mode 100644
index 0000000..d75d454
--- /dev/null
+++ b/samples/99_genre_rpg_roguelike/01_roguelike_starting_point/replay.txt
@@ -0,0 +1,196 @@
+replay_version 2.0
+stopped_at 697
+seed 100
+recorded_at 2021-11-20 11:36:12 -0600
+[:mouse_button_up, 1, 0, 1, 1, 4]
+[:mouse_move, 793, 90, 2, 2, 24]
+[:mouse_move, 799, 95, 2, 3, 25]
+[:mouse_move, 809, 104, 2, 4, 26]
+[:mouse_move, 818, 111, 2, 5, 27]
+[:mouse_move, 832, 118, 2, 6, 28]
+[:mouse_move, 843, 123, 2, 7, 29]
+[:mouse_move, 849, 126, 2, 8, 30]
+[:key_down_raw, 1073741903, 0, 2, 9, 89]
+[:key_up_raw, 1073741903, 0, 2, 10, 94]
+[:key_down_raw, 1073741903, 0, 2, 11, 98]
+[:key_up_raw, 1073741903, 0, 2, 12, 105]
+[:key_down_raw, 1073741903, 0, 2, 13, 108]
+[:key_down_raw, 1073741906, 0, 2, 14, 116]
+[:key_up_raw, 1073741903, 0, 2, 15, 117]
+[:key_up_raw, 1073741906, 0, 2, 16, 121]
+[:key_down_raw, 1073741906, 0, 2, 17, 126]
+[:key_up_raw, 1073741906, 0, 2, 18, 128]
+[:key_down_raw, 1073741906, 0, 2, 19, 135]
+[:key_up_raw, 1073741906, 0, 2, 20, 138]
+[:key_down_raw, 1073741906, 0, 2, 21, 143]
+[:key_up_raw, 1073741906, 0, 2, 22, 147]
+[:key_down_raw, 1073741906, 0, 2, 23, 152]
+[:key_up_raw, 1073741906, 0, 2, 24, 156]
+[:key_down_raw, 1073741906, 0, 2, 25, 162]
+[:key_up_raw, 1073741906, 0, 2, 26, 167]
+[:key_down_raw, 1073741903, 0, 2, 27, 171]
+[:key_up_raw, 1073741903, 0, 2, 28, 177]
+[:key_down_raw, 1073741903, 0, 2, 29, 181]
+[:key_up_raw, 1073741903, 0, 2, 30, 187]
+[:key_down_raw, 1073741903, 0, 2, 31, 190]
+[:key_up_raw, 1073741903, 0, 2, 32, 197]
+[:key_down_raw, 1073741903, 0, 2, 33, 200]
+[:key_up_raw, 1073741903, 0, 2, 34, 212]
+[:key_down_raw, 1073741906, 0, 2, 35, 214]
+[:key_up_raw, 1073741906, 0, 2, 36, 218]
+[:key_down_raw, 1073741906, 0, 2, 37, 224]
+[:key_up_raw, 1073741906, 0, 2, 38, 227]
+[:key_down_raw, 1073741906, 0, 2, 39, 233]
+[:key_up_raw, 1073741906, 0, 2, 40, 238]
+[:key_down_raw, 1073741906, 0, 2, 41, 243]
+[:key_up_raw, 1073741906, 0, 2, 42, 247]
+[:key_down_raw, 1073741903, 0, 2, 43, 252]
+[:key_up_raw, 1073741903, 0, 2, 44, 259]
+[:key_down_raw, 1073741903, 0, 2, 45, 264]
+[:key_up_raw, 1073741903, 0, 2, 46, 269]
+[:key_down_raw, 1073741903, 0, 2, 47, 274]
+[:key_up_raw, 1073741903, 0, 2, 48, 279]
+[:key_down_raw, 1073741903, 0, 2, 49, 283]
+[:key_up_raw, 1073741903, 0, 2, 50, 289]
+[:key_down_raw, 1073741903, 0, 2, 51, 294]
+[:key_up_raw, 1073741903, 0, 2, 52, 300]
+[:key_down_raw, 1073741905, 0, 2, 53, 308]
+[:key_up_raw, 1073741905, 0, 2, 54, 313]
+[:key_down_raw, 1073741903, 0, 2, 55, 323]
+[:key_up_raw, 1073741903, 0, 2, 56, 333]
+[:key_down_raw, 1073741906, 0, 2, 57, 360]
+[:key_up_raw, 1073741906, 0, 2, 58, 364]
+[:key_down_raw, 1073741906, 0, 2, 59, 369]
+[:key_up_raw, 1073741906, 0, 2, 60, 374]
+[:key_down_raw, 1073741906, 0, 2, 61, 379]
+[:key_up_raw, 1073741906, 0, 2, 62, 383]
+[:mouse_move, 868, 122, 2, 63, 418]
+[:mouse_move, 879, 121, 2, 64, 419]
+[:mouse_move, 882, 120, 2, 65, 420]
+[:mouse_move, 876, 120, 2, 66, 426]
+[:mouse_move, 853, 119, 2, 67, 427]
+[:mouse_move, 830, 117, 2, 68, 428]
+[:mouse_move, 799, 112, 2, 69, 429]
+[:mouse_move, 750, 105, 2, 70, 430]
+[:mouse_move, 659, 100, 2, 71, 431]
+[:mouse_move, 544, 100, 2, 72, 432]
+[:mouse_move, 447, 100, 2, 73, 433]
+[:mouse_move, 383, 100, 2, 74, 434]
+[:mouse_move, 336, 100, 2, 75, 435]
+[:mouse_move, 290, 100, 2, 76, 436]
+[:mouse_move, 251, 100, 2, 77, 437]
+[:mouse_move, 205, 100, 2, 78, 438]
+[:mouse_move, 181, 100, 2, 79, 439]
+[:mouse_move, 159, 102, 2, 80, 440]
+[:mouse_move, 137, 106, 2, 81, 441]
+[:mouse_move, 124, 111, 2, 82, 442]
+[:mouse_move, 120, 113, 2, 83, 443]
+[:mouse_move, 134, 117, 2, 84, 446]
+[:mouse_move, 167, 127, 2, 85, 447]
+[:mouse_move, 208, 137, 2, 86, 448]
+[:mouse_move, 255, 142, 2, 87, 449]
+[:mouse_move, 356, 155, 2, 88, 450]
+[:mouse_move, 439, 159, 2, 89, 451]
+[:mouse_move, 522, 159, 2, 90, 452]
+[:mouse_move, 576, 151, 2, 91, 453]
+[:mouse_move, 606, 139, 2, 92, 454]
+[:mouse_move, 622, 128, 2, 93, 455]
+[:mouse_move, 630, 120, 2, 94, 456]
+[:mouse_move, 630, 117, 2, 95, 457]
+[:mouse_move, 620, 104, 2, 96, 458]
+[:mouse_move, 592, 85, 2, 97, 459]
+[:mouse_move, 544, 64, 2, 98, 460]
+[:mouse_move, 465, 35, 2, 99, 461]
+[:mouse_move, 377, 15, 2, 100, 462]
+[:mouse_move, 209, 0, 2, 101, 463]
+[:mouse_move, 10, 66, 2, 102, 473]
+[:mouse_move, 39, 76, 2, 103, 474]
+[:mouse_move, 66, 80, 2, 104, 475]
+[:mouse_move, 96, 81, 2, 105, 476]
+[:mouse_move, 125, 81, 2, 106, 477]
+[:mouse_move, 149, 80, 2, 107, 478]
+[:mouse_move, 173, 76, 2, 108, 479]
+[:mouse_move, 192, 74, 2, 109, 480]
+[:mouse_move, 209, 71, 2, 110, 481]
+[:mouse_move, 213, 71, 2, 111, 482]
+[:mouse_move, 212, 72, 2, 112, 486]
+[:mouse_move, 212, 75, 2, 113, 487]
+[:mouse_move, 217, 79, 2, 114, 488]
+[:mouse_move, 218, 80, 2, 115, 489]
+[:key_down_raw, 1073741905, 0, 2, 116, 517]
+[:key_up_raw, 1073741905, 0, 2, 117, 522]
+[:key_down_raw, 1073741905, 0, 2, 118, 526]
+[:key_up_raw, 1073741905, 0, 2, 119, 530]
+[:key_down_raw, 1073741905, 0, 2, 120, 535]
+[:key_up_raw, 1073741905, 0, 2, 121, 539]
+[:key_down_raw, 1073741905, 0, 2, 122, 544]
+[:key_up_raw, 1073741905, 0, 2, 123, 549]
+[:mouse_move, 217, 80, 2, 124, 582]
+[:mouse_move, 214, 80, 2, 125, 583]
+[:mouse_move, 205, 80, 2, 126, 584]
+[:mouse_move, 190, 80, 2, 127, 585]
+[:mouse_move, 168, 80, 2, 128, 586]
+[:mouse_move, 145, 80, 2, 129, 587]
+[:mouse_move, 123, 80, 2, 130, 588]
+[:mouse_move, 95, 80, 2, 131, 589]
+[:mouse_move, 64, 80, 2, 132, 590]
+[:mouse_move, 43, 82, 2, 133, 591]
+[:mouse_move, 29, 82, 2, 134, 592]
+[:mouse_move, 22, 83, 2, 135, 593]
+[:mouse_move, 19, 83, 2, 136, 594]
+[:mouse_move, 19, 85, 2, 137, 596]
+[:mouse_move, 22, 98, 2, 138, 597]
+[:mouse_move, 35, 116, 2, 139, 598]
+[:mouse_move, 55, 135, 2, 140, 599]
+[:mouse_move, 79, 147, 2, 141, 600]
+[:mouse_move, 106, 152, 2, 142, 601]
+[:mouse_move, 140, 153, 2, 143, 602]
+[:mouse_move, 182, 151, 2, 144, 603]
+[:mouse_move, 220, 141, 2, 145, 604]
+[:mouse_move, 247, 127, 2, 146, 605]
+[:mouse_move, 272, 103, 2, 147, 606]
+[:mouse_move, 274, 90, 2, 148, 607]
+[:mouse_move, 271, 77, 2, 149, 608]
+[:mouse_move, 254, 64, 2, 150, 609]
+[:mouse_move, 222, 50, 2, 151, 610]
+[:mouse_move, 181, 37, 2, 152, 611]
+[:mouse_move, 141, 32, 2, 153, 612]
+[:mouse_move, 102, 30, 2, 154, 613]
+[:mouse_move, 69, 30, 2, 155, 614]
+[:mouse_move, 40, 34, 2, 156, 615]
+[:mouse_move, 20, 43, 2, 157, 616]
+[:mouse_move, 5, 54, 2, 158, 617]
+[:mouse_move, 0, 77, 2, 159, 618]
+[:mouse_move, 6, 99, 2, 160, 619]
+[:mouse_move, 25, 120, 2, 161, 620]
+[:mouse_move, 51, 134, 2, 162, 621]
+[:mouse_move, 83, 139, 2, 163, 622]
+[:mouse_move, 119, 142, 2, 164, 623]
+[:mouse_move, 156, 142, 2, 165, 624]
+[:mouse_move, 189, 142, 2, 166, 625]
+[:mouse_move, 209, 138, 2, 167, 626]
+[:mouse_move, 222, 132, 2, 168, 627]
+[:mouse_move, 227, 126, 2, 169, 628]
+[:mouse_move, 229, 120, 2, 170, 629]
+[:mouse_move, 231, 113, 2, 171, 630]
+[:mouse_move, 232, 113, 2, 172, 631]
+[:mouse_move, 235, 113, 2, 173, 651]
+[:mouse_move, 236, 113, 2, 174, 652]
+[:mouse_move, 237, 113, 2, 175, 653]
+[:mouse_move, 242, 113, 2, 176, 654]
+[:mouse_move, 252, 115, 2, 177, 655]
+[:mouse_move, 277, 116, 2, 178, 656]
+[:key_down_raw, 96, 0, 2, 179, 656]
+[:mouse_move, 316, 116, 2, 180, 657]
+[:mouse_move, 372, 116, 2, 181, 658]
+[:mouse_move, 445, 117, 2, 182, 659]
+[:mouse_move, 513, 123, 2, 183, 660]
+[:key_up_raw, 96, 0, 2, 184, 661]
+[:mouse_move, 572, 131, 2, 185, 661]
+[:mouse_move, 622, 135, 2, 186, 662]
+[:mouse_move, 669, 135, 2, 187, 663]
+[:mouse_move, 704, 135, 2, 188, 664]
+[:mouse_move, 724, 135, 2, 189, 665]
+[:mouse_move, 728, 135, 2, 190, 666]
+[:mouse_move, 727, 135, 2, 191, 670]
+[:key_down_raw, 13, 0, 2, 192, 697]
diff --git a/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/app/constants.rb b/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/app/constants.rb
deleted file mode 100644
index 37dd493..0000000
--- a/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/app/constants.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-SHOW_LEGEND = true
-SOURCE_TILE_SIZE = 16
-DESTINATION_TILE_SIZE = 16
-TILE_SHEET_SIZE = 256
-TILE_R = 0
-TILE_G = 0
-TILE_B = 0
-TILE_A = 255
diff --git a/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/app/legend.rb b/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/app/legend.rb
deleted file mode 100644
index 4d07b79..0000000
--- a/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/app/legend.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-def tick_legend args
- return unless SHOW_LEGEND
-
- legend_padding = 16
- legend_x = 1280 - TILE_SHEET_SIZE - legend_padding
- legend_y = 720 - TILE_SHEET_SIZE - legend_padding
- tile_sheet_sprite = [legend_x,
- legend_y,
- TILE_SHEET_SIZE,
- TILE_SHEET_SIZE,
- 'sprites/simple-mood-16x16.png', 0,
- TILE_A,
- TILE_R,
- TILE_G,
- TILE_B]
-
- if args.inputs.mouse.point.inside_rect? tile_sheet_sprite
- mouse_row = args.inputs.mouse.point.y.idiv(SOURCE_TILE_SIZE)
- tile_row = 15 - (mouse_row - legend_y.idiv(SOURCE_TILE_SIZE))
-
- mouse_col = args.inputs.mouse.point.x.idiv(SOURCE_TILE_SIZE)
- tile_col = (mouse_col - legend_x.idiv(SOURCE_TILE_SIZE))
-
- args.outputs.primitives << [legend_x - legend_padding * 2,
- mouse_row * SOURCE_TILE_SIZE, 256 + legend_padding * 2, 16, 128, 128, 128, 64].solid
-
- args.outputs.primitives << [mouse_col * SOURCE_TILE_SIZE,
- legend_y - legend_padding * 2, 16, 256 + legend_padding * 2, 128, 128, 128, 64].solid
-
- sprite_key = sprite_lookup.find { |k, v| v == [tile_row, tile_col] }
- if sprite_key
- member_name, _ = sprite_key
- member_name = member_name_as_code member_name
- args.outputs.labels << [660, 70, "# CODE SAMPLE (place in the tick_game method located in main.rb)", -1, 0]
- args.outputs.labels << [660, 50, "# GRID_X, GRID_Y, TILE_KEY", -1, 0]
- args.outputs.labels << [660, 30, "args.outputs.sprites << tile_in_game( 5, 6, #{member_name} )", -1, 0]
- else
- args.outputs.labels << [660, 50, "Tile [#{tile_row}, #{tile_col}] not found. Add a key and value to app/sprite_lookup.rb:", -1, 0]
- args.outputs.labels << [660, 30, "{ \"some_string\" => [#{tile_row}, #{tile_col}] } OR { some_symbol: [#{tile_row}, #{tile_col}] }.", -1, 0]
- end
-
- end
-
- # render the sprite in the top right with a padding to the top and right so it's
- # not flush against the edge
- args.outputs.sprites << tile_sheet_sprite
-
- # carefully place some ascii arrows to show the legend labels
- args.outputs.labels << [895, 707, "ROW --->"]
- args.outputs.labels << [943, 412, " ^"]
- args.outputs.labels << [943, 412, " |"]
- args.outputs.labels << [943, 394, "COL ---+"]
-
- # use the tile sheet to print out row and column numbers
- args.outputs.sprites << 16.map_with_index do |i|
- sprite_key = i % 10
- [
- tile(1280 - TILE_SHEET_SIZE - legend_padding * 2 - SOURCE_TILE_SIZE,
- 720 - legend_padding * 2 - (SOURCE_TILE_SIZE * i),
- sprite(sprite_key)),
- tile(1280 - TILE_SHEET_SIZE - SOURCE_TILE_SIZE + (SOURCE_TILE_SIZE * i),
- 720 - TILE_SHEET_SIZE - legend_padding * 3, sprite(sprite_key))
- ]
- end
-end
diff --git a/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/app/main.rb b/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/app/main.rb
deleted file mode 100644
index bd5f521..0000000
--- a/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/app/main.rb
+++ /dev/null
@@ -1,97 +0,0 @@
-require 'app/constants.rb'
-require 'app/sprite_lookup.rb'
-require 'app/legend.rb'
-
-def tick args
- tick_game args
- tick_legend args
-end
-
-def tick_game args
- # setup the grid
- args.state.grid.padding = 104
- args.state.grid.size = 512
-
- # set up your game
- # initialize the game/game defaults. ||= means that you only initialize it if
- # the value isn't alread initialized
- args.state.player.x ||= 0
- args.state.player.y ||= 0
-
- args.state.enemies ||= [
- { x: 10, y: 10, type: :goblin, tile_key: :G },
- { x: 15, y: 30, type: :rat, tile_key: :R }
- ]
-
- args.state.info_message ||= "Use arrow keys to move around."
-
- # handle keyboard input
- # keyboard input (arrow keys to move player)
- new_player_x = args.state.player.x
- new_player_y = args.state.player.y
- player_direction = ""
- player_moved = false
- if args.inputs.keyboard.key_down.up
- new_player_y += 1
- player_direction = "north"
- player_moved = true
- elsif args.inputs.keyboard.key_down.down
- new_player_y -= 1
- player_direction = "south"
- player_moved = true
- elsif args.inputs.keyboard.key_down.right
- new_player_x += 1
- player_direction = "east"
- player_moved = true
- elsif args.inputs.keyboard.key_down.left
- new_player_x -= 1
- player_direction = "west"
- player_moved = true
- end
-
- #handle game logic
- # determine if there is an enemy on that square,
- # if so, don't let the player move there
- if player_moved
- found_enemy = args.state.enemies.find do |e|
- e[:x] == new_player_x && e[:y] == new_player_y
- end
-
- if !found_enemy
- args.state.player.x = new_player_x
- args.state.player.y = new_player_y
- args.state.info_message = "You moved #{player_direction}."
- else
- args.state.info_message = "You cannot move into a square an enemy occupies."
- end
- end
-
- args.outputs.sprites << tile_in_game(args.state.player.x,
- args.state.player.y, '@')
-
- # render game
- # render enemies at locations
- args.outputs.sprites << args.state.enemies.map do |e|
- tile_in_game(e[:x], e[:y], e[:tile_key])
- end
-
- # render the border
- border_x = args.state.grid.padding - DESTINATION_TILE_SIZE
- border_y = args.state.grid.padding - DESTINATION_TILE_SIZE
- border_size = args.state.grid.size + DESTINATION_TILE_SIZE * 2
-
- args.outputs.borders << [border_x,
- border_y,
- border_size,
- border_size]
-
- # render label stuff
- args.outputs.labels << [border_x, border_y - 10, "Current player location is: #{args.state.player.x}, #{args.state.player.y}"]
- args.outputs.labels << [border_x, border_y + 25 + border_size, args.state.info_message]
-end
-
-def tile_in_game x, y, tile_key
- tile($gtk.args.state.grid.padding + x * DESTINATION_TILE_SIZE,
- $gtk.args.state.grid.padding + y * DESTINATION_TILE_SIZE,
- tile_key)
-end
diff --git a/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/app/sprite_lookup.rb b/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/app/sprite_lookup.rb
deleted file mode 100644
index f129e25..0000000
--- a/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/app/sprite_lookup.rb
+++ /dev/null
@@ -1,124 +0,0 @@
-def sprite_lookup
- {
- 0 => [3, 0],
- 1 => [3, 1],
- 2 => [3, 2],
- 3 => [3, 3],
- 4 => [3, 4],
- 5 => [3, 5],
- 6 => [3, 6],
- 7 => [3, 7],
- 8 => [3, 8],
- 9 => [3, 9],
- '@' => [4, 0],
- A: [ 4, 1],
- B: [ 4, 2],
- C: [ 4, 3],
- D: [ 4, 4],
- E: [ 4, 5],
- F: [ 4, 6],
- G: [ 4, 7],
- H: [ 4, 8],
- I: [ 4, 9],
- J: [ 4, 10],
- K: [ 4, 11],
- L: [ 4, 12],
- M: [ 4, 13],
- N: [ 4, 14],
- O: [ 4, 15],
- P: [ 5, 0],
- Q: [ 5, 1],
- R: [ 5, 2],
- S: [ 5, 3],
- T: [ 5, 4],
- U: [ 5, 5],
- V: [ 5, 6],
- W: [ 5, 7],
- X: [ 5, 8],
- Y: [ 5, 9],
- Z: [ 5, 10],
- a: [ 6, 1],
- b: [ 6, 2],
- c: [ 6, 3],
- d: [ 6, 4],
- e: [ 6, 5],
- f: [ 6, 6],
- g: [ 6, 7],
- h: [ 6, 8],
- i: [ 6, 9],
- j: [ 6, 10],
- k: [ 6, 11],
- l: [ 6, 12],
- m: [ 6, 13],
- n: [ 6, 14],
- o: [ 6, 15],
- p: [ 7, 0],
- q: [ 7, 1],
- r: [ 7, 2],
- s: [ 7, 3],
- t: [ 7, 4],
- u: [ 7, 5],
- v: [ 7, 6],
- w: [ 7, 7],
- x: [ 7, 8],
- y: [ 7, 9],
- z: [ 7, 10],
- '|' => [ 7, 12]
- }
-end
-
-def sprite key
- $gtk.args.state.reserved.sprite_lookup[key]
-end
-
-def member_name_as_code raw_member_name
- if raw_member_name.is_a? Symbol
- ":#{raw_member_name}"
- elsif raw_member_name.is_a? String
- "'#{raw_member_name}'"
- elsif raw_member_name.is_a? Fixnum
- "#{raw_member_name}"
- else
- "UNKNOWN: #{raw_member_name}"
- end
-end
-
-def tile x, y, tile_row_column_or_key
- tile_extended x, y, DESTINATION_TILE_SIZE, DESTINATION_TILE_SIZE, TILE_R, TILE_G, TILE_B, TILE_A, tile_row_column_or_key
-end
-
-def tile_extended x, y, w, h, r, g, b, a, tile_row_column_or_key
- row_or_key, column = tile_row_column_or_key
- if !column
- row, column = sprite row_or_key
- else
- row, column = row_or_key, column
- end
-
- if !row
- member_name = member_name_as_code tile_row_column_or_key
- raise "Unabled to find a sprite for #{member_name}. Make sure the value exists in app/sprite_lookup.rb."
- end
-
- # Sprite provided by Rogue Yun
- # http://www.bay12forums.com/smf/index.php?topic=144897.0
- # License: Public Domain
-
- {
- x: x,
- y: y,
- w: w,
- h: h,
- tile_x: column * 16,
- tile_y: (row * 16),
- tile_w: 16,
- tile_h: 16,
- r: r,
- g: g,
- b: b,
- a: a,
- path: 'sprites/simple-mood-16x16.png'
- }
-end
-
-$gtk.args.state.reserved.sprite_lookup = sprite_lookup
diff --git a/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/sprites/simple-mood-16x16.png b/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/sprites/simple-mood-16x16.png
deleted file mode 100644
index 0eca11e..0000000
--- a/samples/99_genre_rpg_roguelike/roguelike_line_of_sight/sprites/simple-mood-16x16.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_roguelike/roguelike_starting_point/app/main.rb b/samples/99_genre_rpg_roguelike/roguelike_starting_point/app/main.rb
deleted file mode 100644
index 7ed8d60..0000000
--- a/samples/99_genre_rpg_roguelike/roguelike_starting_point/app/main.rb
+++ /dev/null
@@ -1,438 +0,0 @@
-=begin
-
- APIs listing that haven't been encountered in previous sample apps:
-
- - lambda: A way to define a block and its parameters with special syntax.
- For example, the syntax of lambda looks like this:
- my_lambda = -> { puts "This is my lambda" }
-
- Reminders:
- - args.outputs.labels: An array. The values generate a label.
- The parameters are [X, Y, TEXT, SIZE, ALIGNMENT, RED, GREEN, BLUE, ALPHA, FONT STYLE]
-
- - ARRAY#inside_rect?: Returns whether or not the point is inside a rect.
-
- - product: Returns an array of all combinations of elements from all arrays.
-
- - find: Finds all elements of a collection that meet requirements.
-
- - abs: Returns the absolute value.
-
-=end
-
-# This sample app allows the player to move around in the dungeon, which becomes more or less visible
-# depending on the player's location, and also has enemies.
-
-class Game
- attr_accessor :args, :state, :inputs, :outputs, :grid
-
- # Calls all the methods needed for the game to run properly.
- def tick
- defaults
- render_canvas
- render_dungeon
- render_player
- render_enemies
- print_cell_coordinates
- calc_canvas
- input_move
- input_click_map
- end
-
- # Sets default values and initializes variables
- def defaults
- outputs.background_color = [0, 0, 0] # black background
-
- # Initializes empty canvas, dungeon, and enemies collections.
- state.canvas ||= []
- state.dungeon ||= []
- state.enemies ||= []
-
- # If state.area doesn't have value, load_area_one and derive_dungeon_from_area methods are called
- if !state.area
- load_area_one
- derive_dungeon_from_area
-
- # Changing these values will change the position of player
- state.x = 7
- state.y = 5
-
- # Creates new enemies, sets their values, and adds them to the enemies collection.
- state.enemies << state.new_entity(:enemy) do |e| # declares each enemy as new entity
- e.x = 13 # position
- e.y = 5
- e.previous_hp = 3
- e.hp = 3
- e.max_hp = 3
- e.is_dead = false # the enemy is alive
- end
-
- update_line_of_sight # updates line of sight by adding newly visible cells
- end
- end
-
- # Adds elements into the state.area collection
- # The dungeon is derived using the coordinates of this collection
- def load_area_one
- state.area ||= []
- state.area << [8, 6]
- state.area << [7, 6]
- state.area << [7, 7]
- state.area << [8, 9]
- state.area << [7, 8]
- state.area << [7, 9]
- state.area << [6, 4]
- state.area << [7, 3]
- state.area << [7, 4]
- state.area << [6, 5]
- state.area << [7, 5]
- state.area << [8, 5]
- state.area << [8, 4]
- state.area << [1, 1]
- state.area << [0, 1]
- state.area << [0, 2]
- state.area << [1, 2]
- state.area << [2, 2]
- state.area << [2, 1]
- state.area << [2, 3]
- state.area << [1, 3]
- state.area << [1, 4]
- state.area << [2, 4]
- state.area << [2, 5]
- state.area << [1, 5]
- state.area << [2, 6]
- state.area << [3, 6]
- state.area << [4, 6]
- state.area << [4, 7]
- state.area << [4, 8]
- state.area << [5, 8]
- state.area << [5, 9]
- state.area << [6, 9]
- state.area << [7, 10]
- state.area << [7, 11]
- state.area << [7, 12]
- state.area << [7, 12]
- state.area << [7, 13]
- state.area << [8, 13]
- state.area << [9, 13]
- state.area << [10, 13]
- state.area << [11, 13]
- state.area << [12, 13]
- state.area << [12, 12]
- state.area << [8, 12]
- state.area << [9, 12]
- state.area << [10, 12]
- state.area << [11, 12]
- state.area << [12, 11]
- state.area << [13, 11]
- state.area << [13, 10]
- state.area << [13, 9]
- state.area << [13, 8]
- state.area << [13, 7]
- state.area << [13, 6]
- state.area << [12, 6]
- state.area << [14, 6]
- state.area << [14, 5]
- state.area << [13, 5]
- state.area << [12, 5]
- state.area << [12, 4]
- state.area << [13, 4]
- state.area << [14, 4]
- state.area << [1, 6]
- state.area << [6, 6]
- end
-
- # Starts with an empty dungeon collection, and adds dungeon cells into it.
- def derive_dungeon_from_area
- state.dungeon = [] # starts as empty collection
-
- state.area.each do |a| # for each element of the area collection
- state.dungeon << state.new_entity(:dungeon_cell) do |d| # declares each dungeon cell as new entity
- d.x = a.x # dungeon cell position using coordinates from area
- d.y = a.y
- d.is_visible = false # cell is not visible
- d.alpha = 0 # not transparent at all
- d.border = [left_margin + a.x * grid_size,
- bottom_margin + a.y * grid_size,
- grid_size,
- grid_size,
- *blue,
- 255] # sets border definition for dungeon cell
- d # returns dungeon cell
- end
- end
- end
-
- def left_margin
- 40 # sets left margin
- end
-
- def bottom_margin
- 60 # sets bottom margin
- end
-
- def grid_size
- 40 # sets size of grid square
- end
-
- # Updates the line of sight by calling the thick_line_of_sight method and
- # adding dungeon cells to the newly_visible collection
- def update_line_of_sight
- variations = [-1, 0, 1]
- # creates collection of newly visible dungeon cells
- newly_visible = variations.product(variations).flat_map do |rise, run| # combo of all elements
- thick_line_of_sight state.x, state.y, rise, run, 15, # calls thick_line_of_sight method
- lambda { |x, y| dungeon_cell_exists? x, y } # checks whether or not cell exists
- end.uniq# removes duplicates
-
- state.dungeon.each do |d| # perform action on each element of dungeons collection
- d.is_visible = newly_visible.find { |v| v.x == d.x && v.y == d.y } # finds match inside newly_visible collection
- end
- end
-
- #Returns a boolean value
- def dungeon_cell_exists? x, y
- # Finds cell coordinates inside dungeon collection to determine if dungeon cell exists
- state.dungeon.find { |d| d.x == x && d.y == y }
- end
-
- # Calls line_of_sight method to add elements to result collection
- def thick_line_of_sight start_x, start_y, rise, run, distance, cell_exists_lambda
- result = []
- result += line_of_sight start_x, start_y, rise, run, distance, cell_exists_lambda
- result += line_of_sight start_x - 1, start_y, rise, run, distance, cell_exists_lambda # one left
- result += line_of_sight start_x + 1, start_y, rise, run, distance, cell_exists_lambda # one right
- result
- end
-
- # Adds points to the result collection to create the player's line of sight
- def line_of_sight start_x, start_y, rise, run, distance, cell_exists_lambda
- result = [] # starts as empty collection
- points = points_on_line start_x, start_y, rise, run, distance # calls points_on_line method
- points.each do |p| # for each point in collection
- if cell_exists_lambda.call(p.x, p.y) # if the cell exists
- result << p # add it to result collection
- else # if cell does not exist
- return result # return result collection as it is
- end
- end
-
- result # return result collection
- end
-
- # Finds the coordinates of the points on the line by performing calculations
- def points_on_line start_x, start_y, rise, run, distance
- distance.times.map do |i| # perform an action
- [start_x + run * i, start_y + rise * i] # definition of point
- end
- end
-
- def render_canvas
- return
- outputs.borders << state.canvas.map do |c| # on each element of canvas collection
- c.border # outputs border
- end
- end
-
- # Outputs the dungeon cells.
- def render_dungeon
- outputs.solids << [0, 0, grid.w, grid.h] # outputs black background for grid
-
- # Sets the alpha value (opacity) for each dungeon cell and calls the cell_border method.
- outputs.borders << state.dungeon.map do |d| # for each element in dungeon collection
- d.alpha += if d.is_visible # if cell is visible
- 255.fdiv(30) # increment opacity (transparency)
- else # if cell is not visible
- 255.fdiv(600) * -1 # decrease opacity
- end
- d.alpha = d.alpha.cap_min_max(0, 255)
- cell_border d.x, d.y, [*blue, d.alpha] # sets blue border using alpha value
- end.reject_nil
- end
-
- # Sets definition of a cell border using the parameters
- def cell_border x, y, color = nil
- [left_margin + x * grid_size,
- bottom_margin + y * grid_size,
- grid_size,
- grid_size,
- *color]
- end
-
- # Sets the values for the player and outputs it as a label
- def render_player
- outputs.labels << [grid_x(state.x) + 20, # positions "@" text in center of grid square
- grid_y(state.y) + 35,
- "@", # player is represented by a white "@" character
- 1, 1, *white]
- end
-
- def grid_x x
- left_margin + x * grid_size # positions horizontally on grid
- end
-
- def grid_y y
- bottom_margin + y * grid_size # positions vertically on grid
- end
-
- # Outputs enemies onto the screen.
- def render_enemies
- state.enemies.map do |e| # for each enemy in the collection
- alpha = 255 # set opacity (full transparency)
-
- # Outputs an enemy using a label.
- outputs.labels << [
- left_margin + 20 + e.x * grid_size, # positions enemy's "r" text in center of grid square
- bottom_margin + 35 + e.y * grid_size,
- "r", # enemy's text
- 1, 1, *white, alpha]
-
- # Creates a red border around an enemy.
- outputs.borders << [grid_x(e.x), grid_y(e.y), grid_size, grid_size, *red]
- end
- end
-
- #White labels are output for the cell coordinates of each element in the dungeon collection.
- def print_cell_coordinates
- return unless state.debug
- state.dungeon.each do |d|
- outputs.labels << [grid_x(d.x) + 2,
- grid_y(d.y) - 2,
- "#{d.x},#{d.y}",
- -2, 0, *white]
- end
- end
-
- # Adds new elements into the canvas collection and sets their values.
- def calc_canvas
- return if state.canvas.length > 0 # return if canvas collection has at least one element
- 15.times do |x| # 15 times perform an action
- 15.times do |y|
- state.canvas << state.new_entity(:canvas) do |c| # declare canvas element as new entity
- c.x = x # set position
- c.y = y
- c.border = [left_margin + x * grid_size,
- bottom_margin + y * grid_size,
- grid_size,
- grid_size,
- *white, 30] # sets border definition
- end
- end
- end
- end
-
- # Updates x and y values of the player, and updates player's line of sight
- def input_move
- x, y, x_diff, y_diff = input_target_cell
-
- return unless dungeon_cell_exists? x, y # player can't move there if a dungeon cell doesn't exist in that location
- return if enemy_at x, y # player can't move there if there is an enemy in that location
-
- state.x += x_diff # increments x by x_diff (so player moves left or right)
- state.y += y_diff # same with y and y_diff ( so player moves up or down)
- update_line_of_sight # updates visible cells
- end
-
- def enemy_at x, y
- # Finds if coordinates exist in enemies collection and enemy is not dead
- state.enemies.find { |e| e.x == x && e.y == y && !e.is_dead }
- end
-
- #M oves the user based on their keyboard input and sets values for target cell
- def input_target_cell
- if inputs.keyboard.key_down.up # if "up" key is in "down" state
- [state.x, state.y + 1, 0, 1] # user moves up
- elsif inputs.keyboard.key_down.down # if "down" key is pressed
- [state.x, state.y - 1, 0, -1] # user moves down
- elsif inputs.keyboard.key_down.left # if "left" key is pressed
- [state.x - 1, state.y, -1, 0] # user moves left
- elsif inputs.keyboard.key_down.right # if "right" key is pressed
- [state.x + 1, state.y, 1, 0] # user moves right
- else
- nil # otherwise, empty
- end
- end
-
- # Goes through the canvas collection to find if the mouse was clicked inside of the borders of an element.
- def input_click_map
- return unless inputs.mouse.click # return unless the mouse is clicked
- canvas_entry = state.canvas.find do |c| # find element from canvas collection that meets requirements
- inputs.mouse.click.inside_rect? c.border # find border that mouse was clicked inside of
- end
- puts canvas_entry # prints canvas_entry value
- end
-
- # Sets the definition of a label using the parameters.
- def label text, x, y, color = nil
- color ||= white # color is initialized to white
- [x, y, text, 1, 1, *color] # sets label definition
- end
-
- def green
- [60, 200, 100] # sets color saturation to shade of green
- end
-
- def blue
- [50, 50, 210] # sets color saturation to shade of blue
- end
-
- def white
- [255, 255, 255] # sets color saturation to white
- end
-
- def red
- [230, 80, 80] # sets color saturation to shade of red
- end
-
- def orange
- [255, 80, 60] # sets color saturation to shade of orange
- end
-
- def pink
- [255, 0, 200] # sets color saturation to shade of pink
- end
-
- def gray
- [75, 75, 75] # sets color saturation to shade of gray
- end
-
- # Recolors the border using the parameters.
- def recolor_border border, r, g, b
- border[4] = r
- border[5] = g
- border[6] = b
- border
- end
-
- # Returns a boolean value.
- def visible? cell
- # finds cell's coordinates inside visible_cells collections to determine if cell is visible
- state.visible_cells.find { |c| c.x == cell.x && c.y == cell.y}
- end
-
- # Exports dungeon by printing dungeon cell coordinates
- def export_dungeon
- state.dungeon.each do |d| # on each element of dungeon collection
- puts "state.dungeon << [#{d.x}, #{d.y}]" # prints cell coordinates
- end
- end
-
- def distance_to_cell cell
- distance_to state.x, cell.x, state.y, cell.y # calls distance_to method
- end
-
- def distance_to from_x, x, from_y, y
- (from_x - x).abs + (from_y - y).abs # finds distance between two cells using coordinates
- end
-end
-
-$game = Game.new
-
-def tick args
- $game.args = args
- $game.state = args.state
- $game.inputs = args.inputs
- $game.outputs = args.outputs
- $game.grid = args.grid
- $game.tick
-end
diff --git a/samples/99_genre_rpg_roguelike/roguelike_starting_point/replay.txt b/samples/99_genre_rpg_roguelike/roguelike_starting_point/replay.txt
deleted file mode 100644
index a2b4c52..0000000
--- a/samples/99_genre_rpg_roguelike/roguelike_starting_point/replay.txt
+++ /dev/null
@@ -1,555 +0,0 @@
-replay_version 2.0
-stopped_at 1731
-seed 100
-recorded_at Sun Sep 29 22:38:52 2019
-[:mouse_move, 785, 468, 2, 1, 114]
-[:mouse_move, 756, 468, 2, 2, 115]
-[:mouse_move, 745, 468, 2, 3, 117]
-[:mouse_move, 718, 470, 2, 4, 118]
-[:mouse_move, 705, 472, 2, 5, 119]
-[:mouse_move, 680, 476, 2, 6, 120]
-[:mouse_move, 668, 478, 2, 7, 121]
-[:mouse_move, 606, 492, 2, 8, 122]
-[:mouse_move, 581, 499, 2, 9, 123]
-[:mouse_move, 523, 511, 2, 10, 124]
-[:mouse_move, 417, 527, 2, 11, 125]
-[:mouse_move, 387, 528, 2, 12, 126]
-[:mouse_move, 344, 528, 2, 13, 127]
-[:mouse_move, 324, 526, 2, 14, 128]
-[:mouse_move, 295, 520, 2, 15, 129]
-[:mouse_move, 285, 518, 2, 16, 130]
-[:mouse_move, 276, 515, 2, 17, 131]
-[:mouse_move, 255, 512, 2, 18, 132]
-[:mouse_move, 244, 511, 2, 19, 133]
-[:mouse_move, 228, 511, 2, 20, 134]
-[:mouse_move, 213, 513, 2, 21, 135]
-[:mouse_move, 194, 523, 2, 22, 136]
-[:mouse_move, 190, 526, 2, 23, 137]
-[:mouse_move, 183, 532, 2, 24, 138]
-[:mouse_move, 180, 533, 2, 25, 139]
-[:mouse_move, 177, 536, 2, 26, 140]
-[:mouse_move, 177, 537, 2, 27, 141]
-[:mouse_move, 193, 537, 2, 28, 142]
-[:mouse_move, 208, 536, 2, 29, 143]
-[:mouse_move, 222, 536, 2, 30, 144]
-[:mouse_move, 232, 535, 2, 31, 145]
-[:mouse_move, 241, 535, 2, 32, 146]
-[:mouse_move, 245, 535, 2, 33, 147]
-[:mouse_move, 249, 535, 2, 34, 148]
-[:mouse_move, 250, 535, 2, 35, 149]
-[:mouse_move, 251, 535, 2, 36, 150]
-[:mouse_move, 252, 534, 2, 37, 151]
-[:mouse_move, 256, 531, 2, 38, 152]
-[:mouse_move, 259, 527, 2, 39, 153]
-[:mouse_move, 265, 520, 2, 40, 154]
-[:mouse_move, 270, 515, 2, 41, 155]
-[:mouse_move, 274, 511, 2, 42, 156]
-[:mouse_move, 282, 501, 2, 43, 157]
-[:mouse_move, 293, 490, 2, 44, 159]
-[:mouse_move, 295, 489, 2, 45, 160]
-[:mouse_move, 299, 487, 2, 46, 161]
-[:mouse_move, 301, 485, 2, 47, 162]
-[:mouse_move, 303, 484, 2, 48, 163]
-[:mouse_move, 304, 484, 2, 49, 164]
-[:mouse_move, 306, 484, 2, 50, 165]
-[:mouse_move, 307, 484, 2, 51, 166]
-[:mouse_move, 308, 484, 2, 52, 167]
-[:mouse_move, 310, 484, 2, 53, 168]
-[:mouse_move, 314, 484, 2, 54, 169]
-[:mouse_move, 316, 484, 2, 55, 170]
-[:mouse_move, 317, 484, 2, 56, 171]
-[:mouse_move, 318, 484, 2, 57, 172]
-[:mouse_move, 319, 484, 2, 58, 173]
-[:key_down_raw, 1073741906, 0, 2, 59, 232]
-[:key_up_raw, 1073741906, 0, 2, 60, 237]
-[:key_down_raw, 1073741906, 0, 2, 61, 243]
-[:key_up_raw, 1073741906, 0, 2, 62, 247]
-[:key_down_raw, 1073741906, 0, 2, 63, 254]
-[:key_up_raw, 1073741906, 0, 2, 64, 257]
-[:key_down_raw, 1073741906, 0, 2, 65, 266]
-[:key_up_raw, 1073741906, 0, 2, 66, 272]
-[:key_down_raw, 1073741906, 0, 2, 67, 279]
-[:key_up_raw, 1073741906, 0, 2, 68, 284]
-[:key_down_raw, 1073741905, 0, 2, 69, 326]
-[:key_up_raw, 1073741905, 0, 2, 70, 334]
-[:key_down_raw, 1073741904, 0, 2, 71, 421]
-[:key_up_raw, 1073741904, 0, 2, 72, 428]
-[:key_down_raw, 1073741904, 0, 2, 73, 438]
-[:key_up_raw, 1073741904, 0, 2, 74, 445]
-[:key_down_raw, 1073741905, 0, 2, 75, 459]
-[:key_up_raw, 1073741905, 0, 2, 76, 466]
-[:key_down_raw, 1073741904, 0, 2, 77, 480]
-[:key_up_raw, 1073741904, 0, 2, 78, 488]
-[:key_down_raw, 1073741905, 0, 2, 79, 499]
-[:key_up_raw, 1073741905, 0, 2, 80, 507]
-[:mouse_move, 289, 484, 2, 81, 545]
-[:mouse_move, 274, 484, 2, 82, 546]
-[:mouse_move, 244, 484, 2, 83, 547]
-[:mouse_move, 231, 485, 2, 84, 548]
-[:mouse_move, 208, 485, 2, 85, 549]
-[:mouse_move, 199, 485, 2, 86, 550]
-[:mouse_move, 178, 485, 2, 87, 551]
-[:mouse_move, 174, 485, 2, 88, 552]
-[:mouse_move, 162, 483, 2, 89, 553]
-[:mouse_move, 159, 482, 2, 90, 554]
-[:mouse_move, 157, 477, 2, 91, 555]
-[:mouse_move, 157, 473, 2, 92, 556]
-[:mouse_move, 161, 465, 2, 93, 557]
-[:mouse_move, 165, 459, 2, 94, 558]
-[:mouse_move, 174, 449, 2, 95, 559]
-[:mouse_move, 179, 443, 2, 96, 560]
-[:mouse_move, 191, 431, 2, 97, 561]
-[:mouse_move, 196, 425, 2, 98, 562]
-[:mouse_move, 205, 413, 2, 99, 563]
-[:mouse_move, 210, 408, 2, 100, 564]
-[:mouse_move, 212, 406, 2, 101, 565]
-[:mouse_move, 219, 397, 2, 102, 566]
-[:mouse_move, 223, 395, 2, 103, 567]
-[:mouse_move, 228, 390, 2, 104, 568]
-[:mouse_move, 230, 388, 2, 105, 569]
-[:mouse_move, 233, 386, 2, 106, 570]
-[:mouse_move, 234, 385, 2, 107, 571]
-[:mouse_move, 235, 384, 2, 108, 573]
-[:mouse_move, 234, 384, 2, 109, 580]
-[:mouse_move, 234, 382, 2, 110, 622]
-[:mouse_move, 234, 379, 2, 111, 623]
-[:mouse_move, 236, 374, 2, 112, 624]
-[:mouse_move, 237, 371, 2, 113, 625]
-[:mouse_move, 240, 366, 2, 114, 626]
-[:mouse_move, 241, 364, 2, 115, 627]
-[:mouse_move, 243, 362, 2, 116, 628]
-[:mouse_move, 243, 361, 2, 117, 629]
-[:mouse_move, 242, 361, 2, 118, 632]
-[:mouse_move, 239, 361, 2, 119, 633]
-[:mouse_move, 229, 367, 2, 120, 634]
-[:mouse_move, 223, 372, 2, 121, 635]
-[:mouse_move, 208, 385, 2, 122, 636]
-[:mouse_move, 198, 393, 2, 123, 637]
-[:mouse_move, 179, 410, 2, 124, 638]
-[:mouse_move, 169, 421, 2, 125, 639]
-[:mouse_move, 149, 440, 2, 126, 640]
-[:mouse_move, 139, 451, 2, 127, 641]
-[:mouse_move, 127, 465, 2, 128, 642]
-[:mouse_move, 119, 473, 2, 129, 643]
-[:mouse_move, 108, 486, 2, 130, 644]
-[:mouse_move, 103, 491, 2, 131, 645]
-[:mouse_move, 98, 496, 2, 132, 646]
-[:mouse_move, 96, 498, 2, 133, 647]
-[:mouse_move, 94, 500, 2, 134, 648]
-[:mouse_move, 92, 501, 2, 135, 649]
-[:mouse_move, 91, 502, 2, 136, 650]
-[:mouse_move, 92, 500, 2, 137, 653]
-[:mouse_move, 95, 498, 2, 138, 654]
-[:mouse_move, 105, 488, 2, 139, 655]
-[:mouse_move, 112, 482, 2, 140, 656]
-[:mouse_move, 128, 463, 2, 141, 657]
-[:mouse_move, 138, 450, 2, 142, 658]
-[:mouse_move, 159, 419, 2, 143, 659]
-[:mouse_move, 168, 403, 2, 144, 660]
-[:mouse_move, 182, 382, 2, 145, 661]
-[:mouse_move, 188, 370, 2, 146, 662]
-[:mouse_move, 200, 354, 2, 147, 663]
-[:mouse_move, 205, 348, 2, 148, 664]
-[:mouse_move, 214, 338, 2, 149, 665]
-[:mouse_move, 218, 335, 2, 150, 666]
-[:mouse_move, 222, 331, 2, 151, 667]
-[:mouse_move, 224, 330, 2, 152, 668]
-[:mouse_move, 226, 328, 2, 153, 669]
-[:mouse_move, 227, 328, 2, 154, 670]
-[:mouse_move, 222, 329, 2, 155, 674]
-[:mouse_move, 219, 332, 2, 156, 675]
-[:mouse_move, 207, 342, 2, 157, 676]
-[:mouse_move, 201, 350, 2, 158, 677]
-[:mouse_move, 184, 370, 2, 159, 678]
-[:mouse_move, 173, 384, 2, 160, 679]
-[:mouse_move, 151, 415, 2, 161, 680]
-[:mouse_move, 140, 431, 2, 162, 681]
-[:mouse_move, 119, 458, 2, 163, 682]
-[:mouse_move, 114, 463, 2, 164, 683]
-[:mouse_move, 99, 478, 2, 165, 684]
-[:mouse_move, 97, 480, 2, 166, 685]
-[:mouse_move, 88, 490, 2, 167, 686]
-[:mouse_move, 85, 493, 2, 168, 687]
-[:mouse_move, 82, 496, 2, 169, 688]
-[:mouse_move, 81, 497, 2, 170, 689]
-[:mouse_move, 82, 497, 2, 171, 692]
-[:mouse_move, 84, 496, 2, 172, 693]
-[:mouse_move, 94, 489, 2, 173, 694]
-[:mouse_move, 101, 482, 2, 174, 695]
-[:mouse_move, 119, 463, 2, 175, 696]
-[:mouse_move, 129, 451, 2, 176, 697]
-[:mouse_move, 151, 426, 2, 177, 698]
-[:mouse_move, 155, 420, 2, 178, 699]
-[:mouse_move, 172, 401, 2, 179, 700]
-[:mouse_move, 178, 393, 2, 180, 701]
-[:mouse_move, 185, 387, 2, 181, 702]
-[:mouse_move, 197, 376, 2, 182, 703]
-[:mouse_move, 202, 371, 2, 183, 704]
-[:mouse_move, 209, 365, 2, 184, 705]
-[:mouse_move, 215, 360, 2, 185, 706]
-[:mouse_move, 218, 357, 2, 186, 707]
-[:mouse_move, 222, 353, 2, 187, 708]
-[:mouse_move, 225, 351, 2, 188, 709]
-[:mouse_move, 226, 350, 2, 189, 710]
-[:mouse_move, 227, 348, 2, 190, 711]
-[:mouse_move, 228, 348, 2, 191, 712]
-[:mouse_move, 229, 347, 2, 192, 713]
-[:mouse_move, 229, 346, 2, 193, 715]
-[:mouse_move, 225, 352, 2, 194, 721]
-[:mouse_move, 219, 361, 2, 195, 722]
-[:mouse_move, 201, 385, 2, 196, 723]
-[:mouse_move, 193, 393, 2, 197, 724]
-[:mouse_move, 165, 424, 2, 198, 725]
-[:mouse_move, 151, 439, 2, 199, 726]
-[:mouse_move, 127, 468, 2, 200, 727]
-[:mouse_move, 116, 480, 2, 201, 728]
-[:mouse_move, 106, 490, 2, 202, 729]
-[:mouse_move, 92, 504, 2, 203, 730]
-[:mouse_move, 84, 512, 2, 204, 731]
-[:mouse_move, 77, 519, 2, 205, 732]
-[:mouse_move, 73, 523, 2, 206, 733]
-[:mouse_move, 69, 527, 2, 207, 734]
-[:mouse_move, 68, 527, 2, 208, 735]
-[:mouse_move, 68, 528, 2, 209, 736]
-[:mouse_move, 70, 525, 2, 210, 738]
-[:mouse_move, 73, 522, 2, 211, 739]
-[:mouse_move, 86, 511, 2, 212, 740]
-[:mouse_move, 93, 503, 2, 213, 741]
-[:mouse_move, 117, 477, 2, 214, 742]
-[:mouse_move, 123, 469, 2, 215, 743]
-[:mouse_move, 156, 427, 2, 216, 744]
-[:mouse_move, 169, 407, 2, 217, 745]
-[:mouse_move, 187, 376, 2, 218, 746]
-[:mouse_move, 199, 356, 2, 219, 747]
-[:mouse_move, 221, 318, 2, 220, 748]
-[:mouse_move, 231, 302, 2, 221, 749]
-[:mouse_move, 250, 276, 2, 222, 750]
-[:mouse_move, 260, 266, 2, 223, 751]
-[:mouse_move, 267, 259, 2, 224, 752]
-[:mouse_move, 272, 254, 2, 225, 753]
-[:mouse_move, 279, 247, 2, 226, 754]
-[:mouse_move, 281, 245, 2, 227, 755]
-[:mouse_move, 282, 245, 2, 228, 756]
-[:mouse_move, 283, 244, 2, 229, 757]
-[:key_down_raw, 1073741906, 0, 2, 230, 813]
-[:key_up_raw, 1073741906, 0, 2, 231, 820]
-[:key_down_raw, 1073741903, 0, 2, 232, 833]
-[:key_up_raw, 1073741903, 0, 2, 233, 840]
-[:key_down_raw, 1073741903, 0, 2, 234, 848]
-[:key_up_raw, 1073741903, 0, 2, 235, 855]
-[:key_down_raw, 1073741906, 0, 2, 236, 862]
-[:key_up_raw, 1073741906, 0, 2, 237, 870]
-[:key_down_raw, 1073741903, 0, 2, 238, 880]
-[:key_up_raw, 1073741903, 0, 2, 239, 901]
-[:key_down_raw, 1073741903, 0, 2, 240, 917]
-[:key_up_raw, 1073741903, 0, 2, 241, 924]
-[:key_down_raw, 1073741905, 0, 2, 242, 943]
-[:key_up_raw, 1073741905, 0, 2, 243, 948]
-[:key_down_raw, 1073741905, 0, 2, 244, 952]
-[:key_up_raw, 1073741905, 0, 2, 245, 956]
-[:key_down_raw, 1073741905, 0, 2, 246, 960]
-[:key_up_raw, 1073741905, 0, 2, 247, 963]
-[:key_down_raw, 1073741905, 0, 2, 248, 967]
-[:key_up_raw, 1073741905, 0, 2, 249, 972]
-[:mouse_move, 244, 247, 2, 250, 997]
-[:mouse_move, 229, 253, 2, 251, 998]
-[:mouse_move, 174, 283, 2, 252, 999]
-[:mouse_move, 152, 299, 2, 253, 1000]
-[:mouse_move, 133, 313, 2, 254, 1001]
-[:mouse_move, 63, 372, 2, 255, 1002]
-[:mouse_move, 53, 384, 2, 256, 1003]
-[:mouse_move, 40, 399, 2, 257, 1004]
-[:mouse_move, 20, 424, 2, 258, 1005]
-[:mouse_move, 13, 440, 2, 259, 1006]
-[:mouse_move, 12, 445, 2, 260, 1007]
-[:mouse_move, 12, 450, 2, 261, 1008]
-[:mouse_move, 12, 451, 2, 262, 1009]
-[:mouse_move, 13, 454, 2, 263, 1010]
-[:mouse_move, 14, 454, 2, 264, 1011]
-[:mouse_move, 15, 455, 2, 265, 1012]
-[:mouse_move, 15, 454, 2, 266, 1014]
-[:mouse_move, 15, 452, 2, 267, 1015]
-[:mouse_move, 15, 447, 2, 268, 1016]
-[:mouse_move, 15, 443, 2, 269, 1017]
-[:mouse_move, 16, 438, 2, 270, 1018]
-[:mouse_move, 17, 435, 2, 271, 1019]
-[:mouse_move, 19, 431, 2, 272, 1020]
-[:mouse_move, 20, 430, 2, 273, 1021]
-[:mouse_move, 22, 428, 2, 274, 1022]
-[:mouse_move, 23, 427, 2, 275, 1023]
-[:mouse_move, 25, 426, 2, 276, 1024]
-[:mouse_move, 26, 426, 2, 277, 1025]
-[:mouse_move, 29, 426, 2, 278, 1026]
-[:mouse_move, 30, 426, 2, 279, 1028]
-[:mouse_move, 31, 427, 2, 280, 1029]
-[:mouse_move, 32, 428, 2, 281, 1030]
-[:mouse_move, 33, 431, 2, 282, 1031]
-[:mouse_move, 34, 432, 2, 283, 1032]
-[:mouse_move, 35, 437, 2, 284, 1033]
-[:mouse_move, 36, 439, 2, 285, 1034]
-[:mouse_move, 37, 444, 2, 286, 1035]
-[:mouse_move, 39, 449, 2, 287, 1036]
-[:mouse_move, 44, 460, 2, 288, 1037]
-[:mouse_move, 45, 464, 2, 289, 1038]
-[:mouse_move, 52, 475, 2, 290, 1039]
-[:mouse_move, 55, 479, 2, 291, 1040]
-[:mouse_move, 62, 485, 2, 292, 1041]
-[:mouse_move, 66, 487, 2, 293, 1042]
-[:mouse_move, 74, 488, 2, 294, 1043]
-[:mouse_move, 79, 488, 2, 295, 1044]
-[:mouse_move, 89, 484, 2, 296, 1045]
-[:mouse_move, 95, 480, 2, 297, 1046]
-[:mouse_move, 111, 468, 2, 298, 1047]
-[:mouse_move, 115, 466, 2, 299, 1048]
-[:mouse_move, 134, 453, 2, 300, 1049]
-[:mouse_move, 142, 447, 2, 301, 1050]
-[:mouse_move, 160, 437, 2, 302, 1051]
-[:mouse_move, 170, 431, 2, 303, 1052]
-[:mouse_move, 179, 425, 2, 304, 1053]
-[:mouse_move, 192, 417, 2, 305, 1054]
-[:mouse_move, 200, 411, 2, 306, 1055]
-[:mouse_move, 213, 401, 2, 307, 1056]
-[:mouse_move, 219, 396, 2, 308, 1057]
-[:mouse_move, 230, 386, 2, 309, 1058]
-[:mouse_move, 238, 375, 2, 310, 1059]
-[:mouse_move, 244, 363, 2, 311, 1060]
-[:mouse_move, 247, 355, 2, 312, 1061]
-[:mouse_move, 253, 341, 2, 313, 1062]
-[:mouse_move, 255, 335, 2, 314, 1063]
-[:mouse_move, 257, 321, 2, 315, 1064]
-[:mouse_move, 258, 309, 2, 316, 1065]
-[:mouse_move, 257, 298, 2, 317, 1066]
-[:mouse_move, 255, 291, 2, 318, 1067]
-[:mouse_move, 249, 281, 2, 319, 1068]
-[:mouse_move, 242, 271, 2, 320, 1069]
-[:mouse_move, 233, 264, 2, 321, 1070]
-[:mouse_move, 226, 260, 2, 322, 1071]
-[:mouse_move, 207, 252, 2, 323, 1072]
-[:mouse_move, 203, 251, 2, 324, 1073]
-[:mouse_move, 185, 249, 2, 325, 1074]
-[:mouse_move, 178, 249, 2, 326, 1075]
-[:mouse_move, 161, 249, 2, 327, 1076]
-[:mouse_move, 153, 250, 2, 328, 1077]
-[:mouse_move, 139, 256, 2, 329, 1078]
-[:mouse_move, 132, 259, 2, 330, 1079]
-[:mouse_move, 120, 269, 2, 331, 1080]
-[:mouse_move, 110, 279, 2, 332, 1081]
-[:mouse_move, 104, 287, 2, 333, 1082]
-[:mouse_move, 93, 304, 2, 334, 1083]
-[:mouse_move, 87, 313, 2, 335, 1084]
-[:mouse_move, 80, 326, 2, 336, 1085]
-[:mouse_move, 75, 335, 2, 337, 1086]
-[:mouse_move, 69, 351, 2, 338, 1087]
-[:mouse_move, 67, 359, 2, 339, 1088]
-[:mouse_move, 64, 376, 2, 340, 1089]
-[:mouse_move, 64, 383, 2, 341, 1090]
-[:mouse_move, 62, 399, 2, 342, 1091]
-[:mouse_move, 62, 406, 2, 343, 1092]
-[:mouse_move, 62, 418, 2, 344, 1093]
-[:mouse_move, 62, 423, 2, 345, 1094]
-[:mouse_move, 66, 433, 2, 346, 1095]
-[:mouse_move, 69, 437, 2, 347, 1096]
-[:mouse_move, 78, 444, 2, 348, 1097]
-[:mouse_move, 86, 450, 2, 349, 1098]
-[:mouse_move, 102, 457, 2, 350, 1099]
-[:mouse_move, 112, 458, 2, 351, 1100]
-[:mouse_move, 136, 461, 2, 352, 1101]
-[:mouse_move, 142, 461, 2, 353, 1102]
-[:mouse_move, 162, 460, 2, 354, 1103]
-[:mouse_move, 172, 459, 2, 355, 1104]
-[:mouse_move, 188, 454, 2, 356, 1105]
-[:mouse_move, 195, 451, 2, 357, 1106]
-[:mouse_move, 211, 443, 2, 358, 1107]
-[:mouse_move, 214, 440, 2, 359, 1108]
-[:mouse_move, 222, 432, 2, 360, 1109]
-[:mouse_move, 233, 412, 2, 361, 1110]
-[:mouse_move, 238, 400, 2, 362, 1111]
-[:mouse_move, 248, 375, 2, 363, 1112]
-[:mouse_move, 250, 370, 2, 364, 1113]
-[:mouse_move, 258, 351, 2, 365, 1114]
-[:mouse_move, 261, 343, 2, 366, 1115]
-[:mouse_move, 264, 328, 2, 367, 1116]
-[:mouse_move, 264, 321, 2, 368, 1117]
-[:mouse_move, 265, 307, 2, 369, 1118]
-[:mouse_move, 265, 305, 2, 370, 1119]
-[:mouse_move, 264, 296, 2, 371, 1120]
-[:mouse_move, 262, 289, 2, 372, 1121]
-[:mouse_move, 257, 282, 2, 373, 1122]
-[:mouse_move, 252, 277, 2, 374, 1123]
-[:mouse_move, 237, 271, 2, 375, 1124]
-[:mouse_move, 227, 269, 2, 376, 1125]
-[:mouse_move, 211, 268, 2, 377, 1126]
-[:mouse_move, 201, 268, 2, 378, 1127]
-[:mouse_move, 177, 268, 2, 379, 1128]
-[:mouse_move, 168, 269, 2, 380, 1129]
-[:mouse_move, 149, 274, 2, 381, 1130]
-[:mouse_move, 137, 279, 2, 382, 1131]
-[:mouse_move, 124, 288, 2, 383, 1132]
-[:mouse_move, 116, 294, 2, 384, 1133]
-[:mouse_move, 102, 307, 2, 385, 1134]
-[:mouse_move, 91, 319, 2, 386, 1135]
-[:mouse_move, 88, 323, 2, 387, 1136]
-[:mouse_move, 73, 344, 2, 388, 1137]
-[:mouse_move, 68, 353, 2, 389, 1138]
-[:mouse_move, 57, 374, 2, 390, 1139]
-[:mouse_move, 52, 386, 2, 391, 1140]
-[:mouse_move, 44, 412, 2, 392, 1141]
-[:mouse_move, 42, 418, 2, 393, 1142]
-[:mouse_move, 36, 437, 2, 394, 1143]
-[:mouse_move, 34, 445, 2, 395, 1144]
-[:mouse_move, 33, 453, 2, 396, 1145]
-[:mouse_move, 32, 457, 2, 397, 1146]
-[:mouse_move, 32, 466, 2, 398, 1147]
-[:mouse_move, 33, 468, 2, 399, 1148]
-[:mouse_move, 38, 475, 2, 400, 1149]
-[:mouse_move, 44, 482, 2, 401, 1150]
-[:mouse_move, 56, 492, 2, 402, 1151]
-[:mouse_move, 64, 496, 2, 403, 1152]
-[:mouse_move, 81, 503, 2, 404, 1153]
-[:mouse_move, 92, 503, 2, 405, 1154]
-[:mouse_move, 106, 503, 2, 406, 1155]
-[:mouse_move, 115, 501, 2, 407, 1156]
-[:mouse_move, 134, 492, 2, 408, 1157]
-[:mouse_move, 147, 485, 2, 409, 1158]
-[:mouse_move, 163, 471, 2, 410, 1159]
-[:mouse_move, 171, 463, 2, 411, 1160]
-[:mouse_move, 183, 451, 2, 412, 1161]
-[:mouse_move, 202, 425, 2, 413, 1163]
-[:mouse_move, 215, 401, 2, 414, 1164]
-[:mouse_move, 217, 395, 2, 415, 1165]
-[:mouse_move, 226, 373, 2, 416, 1166]
-[:mouse_move, 234, 357, 2, 417, 1167]
-[:mouse_move, 238, 343, 2, 418, 1168]
-[:mouse_move, 240, 334, 2, 419, 1169]
-[:mouse_move, 247, 310, 2, 420, 1170]
-[:mouse_move, 249, 299, 2, 421, 1171]
-[:mouse_move, 250, 290, 2, 422, 1172]
-[:mouse_move, 251, 283, 2, 423, 1173]
-[:mouse_move, 251, 269, 2, 424, 1174]
-[:mouse_move, 248, 263, 2, 425, 1175]
-[:mouse_move, 237, 256, 2, 426, 1176]
-[:mouse_move, 229, 254, 2, 427, 1177]
-[:mouse_move, 210, 250, 2, 428, 1178]
-[:mouse_move, 199, 249, 2, 429, 1179]
-[:mouse_move, 184, 248, 2, 430, 1180]
-[:mouse_move, 173, 248, 2, 431, 1181]
-[:mouse_move, 153, 248, 2, 432, 1182]
-[:mouse_move, 145, 249, 2, 433, 1183]
-[:mouse_move, 138, 251, 2, 434, 1184]
-[:mouse_move, 125, 257, 2, 435, 1185]
-[:mouse_move, 121, 260, 2, 436, 1186]
-[:mouse_move, 112, 267, 2, 437, 1187]
-[:mouse_move, 101, 280, 2, 438, 1188]
-[:mouse_move, 97, 287, 2, 439, 1189]
-[:mouse_move, 86, 306, 2, 440, 1190]
-[:mouse_move, 81, 316, 2, 441, 1191]
-[:mouse_move, 79, 322, 2, 442, 1192]
-[:mouse_move, 70, 345, 2, 443, 1193]
-[:mouse_move, 63, 365, 2, 444, 1194]
-[:mouse_move, 59, 389, 2, 445, 1195]
-[:mouse_move, 59, 401, 2, 446, 1196]
-[:mouse_move, 59, 416, 2, 447, 1197]
-[:mouse_move, 59, 425, 2, 448, 1198]
-[:mouse_move, 60, 439, 2, 449, 1199]
-[:mouse_move, 60, 442, 2, 450, 1200]
-[:mouse_move, 64, 454, 2, 451, 1201]
-[:mouse_move, 66, 457, 2, 452, 1202]
-[:mouse_move, 70, 462, 2, 453, 1203]
-[:mouse_move, 74, 464, 2, 454, 1204]
-[:mouse_move, 81, 467, 2, 455, 1205]
-[:mouse_move, 85, 468, 2, 456, 1206]
-[:mouse_move, 97, 469, 2, 457, 1207]
-[:mouse_move, 107, 469, 2, 458, 1208]
-[:mouse_move, 124, 471, 2, 459, 1209]
-[:mouse_move, 134, 471, 2, 460, 1210]
-[:mouse_move, 148, 471, 2, 461, 1211]
-[:mouse_move, 161, 468, 2, 462, 1212]
-[:mouse_move, 178, 457, 2, 463, 1213]
-[:mouse_move, 186, 451, 2, 464, 1214]
-[:mouse_move, 202, 434, 2, 465, 1215]
-[:mouse_move, 210, 424, 2, 466, 1216]
-[:mouse_move, 227, 400, 2, 467, 1217]
-[:mouse_move, 234, 388, 2, 468, 1218]
-[:mouse_move, 237, 383, 2, 469, 1219]
-[:mouse_move, 250, 360, 2, 470, 1220]
-[:mouse_move, 254, 351, 2, 471, 1221]
-[:mouse_move, 261, 334, 2, 472, 1222]
-[:mouse_move, 262, 326, 2, 473, 1223]
-[:mouse_move, 264, 312, 2, 474, 1224]
-[:mouse_move, 265, 305, 2, 475, 1225]
-[:mouse_move, 265, 293, 2, 476, 1226]
-[:mouse_move, 265, 287, 2, 477, 1227]
-[:mouse_move, 259, 272, 2, 478, 1228]
-[:mouse_move, 255, 267, 2, 479, 1229]
-[:mouse_move, 246, 260, 2, 480, 1230]
-[:mouse_move, 239, 257, 2, 481, 1231]
-[:mouse_move, 226, 253, 2, 482, 1232]
-[:mouse_move, 213, 251, 2, 483, 1233]
-[:mouse_move, 194, 251, 2, 484, 1234]
-[:mouse_move, 184, 252, 2, 485, 1235]
-[:mouse_move, 163, 259, 2, 486, 1236]
-[:mouse_move, 153, 263, 2, 487, 1237]
-[:mouse_move, 133, 274, 2, 488, 1238]
-[:mouse_move, 128, 278, 2, 489, 1239]
-[:mouse_move, 107, 297, 2, 490, 1240]
-[:mouse_move, 100, 305, 2, 491, 1241]
-[:mouse_move, 86, 324, 2, 492, 1242]
-[:mouse_move, 79, 335, 2, 493, 1243]
-[:mouse_move, 74, 348, 2, 494, 1244]
-[:mouse_move, 66, 388, 2, 495, 1245]
-[:mouse_move, 66, 399, 2, 496, 1246]
-[:mouse_move, 68, 429, 2, 497, 1247]
-[:mouse_move, 73, 441, 2, 498, 1248]
-[:mouse_move, 83, 452, 2, 499, 1249]
-[:mouse_move, 89, 457, 2, 500, 1250]
-[:mouse_move, 97, 462, 2, 501, 1251]
-[:key_down_raw, 1073741906, 0, 2, 502, 1292]
-[:key_up_raw, 1073741906, 0, 2, 503, 1296]
-[:key_down_raw, 1073741906, 0, 2, 504, 1309]
-[:key_up_raw, 1073741906, 0, 2, 505, 1314]
-[:key_down_raw, 1073741906, 0, 2, 506, 1319]
-[:key_up_raw, 1073741906, 0, 2, 507, 1322]
-[:key_down_raw, 1073741906, 0, 2, 508, 1327]
-[:key_up_raw, 1073741906, 0, 2, 509, 1331]
-[:key_down_raw, 1073741906, 0, 2, 510, 1336]
-[:key_up_raw, 1073741906, 0, 2, 511, 1339]
-[:key_down_raw, 1073741906, 0, 2, 512, 1345]
-[:key_up_raw, 1073741906, 0, 2, 513, 1348]
-[:key_down_raw, 1073741906, 0, 2, 514, 1354]
-[:key_up_raw, 1073741906, 0, 2, 515, 1358]
-[:key_down_raw, 1073741906, 0, 2, 516, 1362]
-[:key_up_raw, 1073741906, 0, 2, 517, 1370]
-[:key_down_raw, 1073741903, 0, 2, 518, 1386]
-[:key_up_raw, 1073741903, 0, 2, 519, 1392]
-[:key_down_raw, 1073741903, 0, 2, 520, 1397]
-[:key_up_raw, 1073741903, 0, 2, 521, 1401]
-[:key_down_raw, 1073741903, 0, 2, 522, 1407]
-[:key_up_raw, 1073741903, 0, 2, 523, 1412]
-[:key_down_raw, 1073741903, 0, 2, 524, 1415]
-[:key_up_raw, 1073741903, 0, 2, 525, 1421]
-[:key_down_raw, 1073741903, 0, 2, 526, 1428]
-[:key_up_raw, 1073741903, 0, 2, 527, 1436]
-[:key_down_raw, 1073741905, 0, 2, 528, 1446]
-[:key_up_raw, 1073741905, 0, 2, 529, 1458]
-[:key_down_raw, 1073741905, 0, 2, 530, 1466]
-[:key_up_raw, 1073741905, 0, 2, 531, 1472]
-[:key_down_raw, 1073741903, 0, 2, 532, 1479]
-[:key_up_raw, 1073741903, 0, 2, 533, 1489]
-[:key_down_raw, 1073741905, 0, 2, 534, 1513]
-[:key_up_raw, 1073741905, 0, 2, 535, 1517]
-[:key_down_raw, 1073741905, 0, 2, 536, 1522]
-[:key_up_raw, 1073741905, 0, 2, 537, 1526]
-[:key_down_raw, 1073741905, 0, 2, 538, 1531]
-[:key_up_raw, 1073741905, 0, 2, 539, 1535]
-[:key_down_raw, 1073741905, 0, 2, 540, 1540]
-[:key_up_raw, 1073741905, 0, 2, 541, 1544]
-[:key_down_raw, 1073741905, 0, 2, 542, 1549]
-[:key_up_raw, 1073741905, 0, 2, 543, 1554]
-[:key_down_raw, 1073741905, 0, 2, 544, 1558]
-[:key_up_raw, 1073741905, 0, 2, 545, 1564]
-[:key_down_raw, 1073742051, 1024, 2, 546, 1663]
-[:key_down_raw, 114, 1024, 2, 547, 1664]
-[:key_up_raw, 114, 1024, 2, 548, 1669]
-[:key_up_raw, 1073742051, 0, 2, 549, 1677]
-[:key_down_raw, 1073742051, 1024, 2, 550, 1729]
-[:key_down_raw, 113, 1024, 2, 551, 1730]
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/app/main.rb b/samples/99_genre_rpg_tactical/gameboard_movement/app/main.rb
deleted file mode 100644
index 8eb935e..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/app/main.rb
+++ /dev/null
@@ -1,529 +0,0 @@
-# Size of board is always 1280x720
-
-def tick args
- size = 64
-
- # Draw a checkerboard as a placeholder game board
- i = 0
- j = 0
- while i < 12 do
- while j < 21 do
- args.outputs.solids << [(j*size), (i*size), size, size, 255, 100, 0, ((i+j) % 2 == 0) ? 255 : 0]
- j += 1
- end
- j = 0
- i += 1
- end
- k = 0
- ary = Array.new(220)
- while k < 220
- ary[k] = 1
- if k > 20 and k < 36
- ary[k] = 0
- end
- if k > 40 and k < 56
- ary[k] = 0
- end
- if k > 60 and k < 76
- ary[k] = 0
- end
- if k > 80 and k < 96
- ary[k] = 0
- end
- if k > 100 and k < 116
- ary[k] = 0
- end
- if k > 120 and k < 136
- ary[k] = 0
- end
- if k == 161 and args.state.bot3.hp >= 1
- ary[k] = 0
- end
- if k == 147 and args.state.bot1.hp >= 1
- ary[k] = 0
- end
- if k == 215 and args.state.bot2.hp >= 1
- ary[k] = 0
- end
- k += 1
- end
- ary2 = ary;
- htarget = 161
- target = 160
- targetb = 181
- targetc = 141
- targetd = 162
- target2 = 146
- target2b = 167
- target2c = 148
- htarget2 = 147
- target3 = 214
- target3c = 216
- target3b = 195
- htarget3 = 215
- # player attributes
- args.state.player.x ||= 0
- args.state.player.y ||= 0
- args.state.player.w ||= 64
- args.state.player.h ||= 64
- args.state.player.direction ||= 1
- args.state.player.hp ||= 100
- args.state.player.strength ||= 100
- args.state.player.pos ||= 0
-
- # bot1 attributes
- args.state.bot1.x ||= 448
- args.state.bot1.y ||= 448
- args.state.bot1.w ||= 64
- args.state.bot1.h ||= 64
- args.state.bot1.direction ||= 1
- args.state.bot1.hp ||= 100
- args.state.bot1.strength ||= 5
-
- # bot2 attributes
- args.state.bot2.x ||= 960
- args.state.bot2.y ||= 640
- args.state.bot2.w ||= 64
- args.state.bot2.h ||= 64
- args.state.bot2.direction ||= 1
- args.state.bot2.hp ||= 100
- args.state.bot2.strength ||= 8
-
- # bot3 attributes
- args.state.bot3.x ||= 64
- args.state.bot3.y ||= 512
- args.state.bot3.w ||= 64
- args.state.bot3.h ||= 64
- args.state.bot3.direction ||= 1
- args.state.bot3.hp ||= 100
- args.state.bot3.strength ||= 8
-
- # obstacle attributes
- args.state.obs1.x ||= 64
- args.state.obs1.y ||= 64
- args.state.obs1.w ||= 960
- args.state.obs1.h ||= 384
- args.state.obs1.direction ||= 1
-
-
- @menu_shown ||= :hidden
-
- # display menu
- if @menu_shown == :hidden
- args.state.menu_button ||= new_button :menu, 1081, 650, "Menu"
- args.outputs.primitives << args.state.menu_button[:primitives]
-
- if button_clicked? args, args.state.menu_button
- @menu_shown = :visible
- end
-
- else
- args.state.menu_overlay = [1080, 0, 200, 720, 100, 0, 0, 250]
-
- # first overlay
- if args.state.menu_overlay
- args.outputs.solids << args.state.menu_overlay
-
- # move button
- args.state.move_button ||= new_button :move, 1081, 650, "Move"
- args.outputs.primitives << args.state.move_button[:primitives]
-
- if button_clicked? args, args.state.move_button
- args.gtk.notify! "Move button was clicked!"
- end
-
- # attack button
- args.state.attack_button ||= new_button :attack, 1081, 600, "Attack"
- args.outputs.primitives << args.state.attack_button[:primitives]
-
- if button_clicked? args, args.state.attack_button
-
- if args.state.player.pos+1 == htarget or args.state.player.pos-1 == htarget or args.state.player.pos+20 == htarget or args.state.player.pos-20 == htarget
- damage = rand(100)
- dealt = "#{damage} Damage Dealt!"
- args.gtk.notify! dealt
- args.state.bot3.hp -= damage
-
- end
- if args.state.player.pos+1 == htarget2 or args.state.player.pos-1 == htarget2 or args.state.player.pos+20 == htarget2 or args.state.player.pos-20 == htarget2
- damage = rand(100)
- dealt = "#{damage} Damage Dealt!"
- args.gtk.notify! dealt
-
- args.state.bot1.hp -= damage
-
- end
- if args.state.player.pos+1 == htarget3 or args.state.player.pos-1 == htarget3 or args.state.player.pos+20 == htarget3 or args.state.player.pos-20 == htarget3
- damage = rand(100)
- dealt = "#{damage} Damage Dealt!"
- args.gtk.notify! dealt
- args.state.bot2.hp -= damage
-
- end
- end
-
- # items button
- args.state.items_button ||= new_button :items, 1081, 550, "Items"
- args.outputs.primitives << args.state.items_button[:primitives]
-
- if button_clicked? args, args.state.items_button
- args.state.itemMenu_overlay = [880, 0, 200, 720, 150, 0, 0, 250]
- args.gtk.notify! "Items button was clicked!"
- end
-
- # second overlay
- if args.state.itemMenu_overlay
- args.outputs.solids << args.state.itemMenu_overlay
- args.outputs.labels << [960, 700, "Items"]
-
- # create items
- args.state.potion_button ||= new_button :potion, 881, 600, "Potion"
- args.outputs.primitives << args.state.potion_button[:primitives]
-
- if button_clicked? args, args.state.potion_button
- args.gtk.notify! "Potion Used!"
- end
-
- args.state.elixer_button ||= new_button :potion, 881, 550, "Elixer"
- args.outputs.primitives << args.state.elixer_button[:primitives]
-
- if button_clicked? args, args.state.elixer_button
- args.gtk.notify! "Elixer Used!"
- end
-
- end
-
- # wait button
- args.state.wait_button ||= new_button :wait, 1081, 500, "Wait"
- args.outputs.primitives << args.state.wait_button[:primitives]
-
- if button_clicked? args, args.state.wait_button
- args.gtk.notify! "Wait button was clicked!"
- end
-
- # close button
- args.state.close_button ||= new_button :close, 1081, 450, "Close"
- args.outputs.primitives << args.state.close_button[:primitives]
-
- # hide menu
- if button_clicked? args, args.state.close_button
- @menu_shown = :hidden
- end
-
- end
- end
-
- # left and right movement
- if args.inputs.keyboard.key_down.right and ary[args.state.player.pos+1] == 1 and args.state.player.pos%20 < 19
- args.state.player.direction = 1
- args.state.player.started_running_at = args.state.tick_count
- args.state.player.x += size
- args.state.player.pos += 1
- elsif args.inputs.keyboard.key_down.left and ary[args.state.player.pos-1] == 1 and args.state.player.pos%20 > 0
- args.state.player.direction = -1
- args.state.player.started_running_at = args.state.tick_count
- args.state.player.x -= size
- args.state.player.pos -= 1
- end
-
-
-
-
- # up and down movement
- if args.inputs.keyboard.key_down.up and ary[args.state.player.pos+20] == 1 and args.state.player.pos < 200
- args.state.player.direction = 1
- args.state.player.started_running_at = args.state.tick_count
- args.state.player.y += size
- args.state.player.pos += 20
- elsif args.inputs.keyboard.key_down.down and ary[args.state.player.pos-20] == 1 and args.state.player.pos >= 20
- args.state.player.direction = -1
- args.state.player.started_running_at = args.state.tick_count
- args.state.player.y -= size
- args.state.player.pos -= 20
- end
-
- pigga = args.state.player.intersect_rect? args.state.obs1
- if pigga
- args.gtk.notify! "sprites collide!"
- args.state.player.y -= size
- end
- looping = true
- cangoup = false
- cangoright = false
- cangodown = false
- cangoleft = false
- ftarget = 10000
- hold = 9
- testtarget = args.state.player.pos
- if args.state.bot3.hp > 0
- ftarget = (target-testtarget).abs
- hold = target
- end
- if(ftarget > (targetb-testtarget).abs and args.state.bot3.hp > 0)
- ftarget = (targetb-testtarget).abs
- hold = targetb
- end
- if(ftarget > (targetc-testtarget).abs and args.state.bot3.hp > 0)
- ftarget = (targetc-testtarget).abs
- hold = targetc
- end
- if(ftarget > (targetd-testtarget).abs and args.state.bot3.hp > 0)
- ftarget = (targetd-testtarget).abs
- hold = targetd
- end
- if(ftarget > (target2-testtarget).abs and args.state.bot1.hp > 0)
- ftarget = (target2-testtarget).abs
- hold = target2
- end
- if(ftarget > (target2b-testtarget).abs and args.state.bot1.hp > 0)
- ftarget = (target2b-testtarget).abs
- hold = target2b
- end
- if(ftarget > (target2c-testtarget).abs and args.state.bot1.hp > 0)
- ftarget = (target2c-testtarget).abs
- hold = target2c
- end
- if(ftarget > (target3-testtarget).abs and args.state.bot2.hp > 0)
- ftarget = (target3-testtarget).abs
- hold = target3
- end
- if(ftarget > (target3b-testtarget).abs and args.state.bot2.hp > 0)
- ftarget = (target3b-testtarget).abs
- hold = target3b
- end
- if(ftarget > (target3c-testtarget).abs and args.state.bot2.hp > 0)
- ftarget = (target3c-testtarget).abs
- hold = target3c
- end
- if ftarget == 10000
- looping = false
- end
- if args.inputs.keyboard.key_down.f
- while looping and target != testtarget and targetb != testtarget and targetc != testtarget and targetd != testtarget and target2 != testtarget and target2b != testtarget and target2c != testtarget and target3 != testtarget and target3b != testtarget and target3c != testtarget
- cangoup = false
- cangoright = false
- cangodown = false
- cangoleft = false
-
- if hold-testtarget >= 20 and ary2[args.state.player.pos+20] == 1 and args.state.player.pos < 200
- cangoup = true
- elsif testtarget-hold >= 20 and ary2[args.state.player.pos-20] == 1 and args.state.player.pos > 20
- cangodown = true
- cangoup = false
- elsif hold%20-testtarget%20 > 0 and ary2[args.state.player.pos+1] == 1 and args.state.player.pos%20 < 19
- cangodown = false
- cangoup = false
- cangoright = true
- elsif testtarget%20-hold%20 > 0 and ary2[args.state.player.pos-1] == 1 and args.state.player.pos%20 > 0
- cangodown = false
- cangoup = false
- cangoright = false
- cangoleft = true
- end
- if cangodown == false and cangoup == false and cangoleft == false and cangoright == false
- if ary2[args.state.player.pos+20] == 1 and args.state.player.pos < 200
- cangoup = true
- elsif ary2[args.state.player.pos-20] == 1 and args.state.player.pos > 20
- cangodown = true
- cangoup = false
- elsif ary2[args.state.player.pos+1] == 1 and args.state.player.pos%20 < 19
- cangodown = false
- cangoup = false
- cangoright = true
- elsif ary2[args.state.player.pos-1] == 1 and args.state.player.pos%20 > 0
- cangodown = false
- cangoup = false
- cangoright = false
- cangoleft = true
- end
- end
- if cangodown == true
- args.state.player.direction = -1
- args.state.player.started_running_at = args.state.tick_count
- args.state.player.y -= size
- ary2[args.state.player.pos] = 0
- args.state.player.pos -= 20
- testtarget -= 20
-
- elsif cangoup == true
- args.state.player.direction = 1
- args.state.player.started_running_at = args.state.tick_count
- args.state.player.y += size
- ary2[args.state.player.pos] = 0
- args.state.player.pos += 20
- testtarget+=20
-
- elsif cangoright == true
- args.state.player.direction = 1
- args.state.player.started_running_at = args.state.tick_count
- args.state.player.x += size
- ary2[args.state.player.pos] = 0
- args.state.player.pos += 1
- testtarget += 1
-
- elsif cangoleft == true
- args.state.player.direction = -1
- args.state.player.started_running_at = args.state.tick_count
- args.state.player.x -= size
- ary2[args.state.player.pos] = 0
- args.state.player.pos -= 1
- testtarget -= 1
- end
-
- end
- end
-
-
- #Wrap player around the stage
- if args.state.player.x > 1280
- args.state.player.x = -64
- args.state.player.started_running_at ||= args.state.tick_count
- elsif args.state.player.x < -64
- args.state.player.x = 1280
- args.state.player.started_running_at ||= args.state.tick_count
- end
-
- if args.state.player.y > 720
- args.state.player.y = -64
- args.state.player.started_running_at ||= args.state.tick_count
- elsif args.state.player.y < -64
- args.state.player.y = 720
- args.state.player.started_running_at ||= args.state.tick_count
- end
-
- # Display obstacles
- args.outputs.sprites << display_obs1(args)
-
- #Display the flying dragon and bots
- args.outputs.sprites << display_dragon(args)
- if args.state.bot1.hp >= 1
- args.outputs.sprites << display_bot1(args)
- end
- if args.state.bot2.hp >= 1
- args.outputs.sprites << display_bot2(args)
- end
- if args.state.bot3.hp >= 1
- args.outputs.sprites << display_bot3(args)
- end
- if args.state.bot1.hp <= 0 and args.state.bot3.hp <= 0 and args.state.bot2.hp <= 0
- args.gtk.notify! "You Win!"
- end
-end
-
-# helper method to create a button
-def new_button id, x, y, text
- # create a hash ("entity") that has some metadata
- # about what it represents
- entity =
- {
- id: id,
- rect: { x: x, y: y, w: 200, h: 50 }
- }
-
- # for that entity, define the primitives
- # that form it
- entity[:primitives] =
- [
- { x: x, y: y, w: 200, h: 50 }.border,
- { x: x + 75, y: y + 30, text: text }.label
- ]
-
- entity
-end
-
-# helper method for determining if a button was clicked
-def button_clicked? args, button
- return false unless args.inputs.mouse.click
- return args.inputs.mouse.point.inside_rect? button[:rect]
-end
-
-def display_dragon args
- start_looping_at = 0
- number_of_sprites = 2
- number_of_frames_to_show_each_sprite = 8
- does_sprite_loop = true
- sprite_index = start_looping_at.frame_index number_of_sprites,
- number_of_frames_to_show_each_sprite,
- does_sprite_loop
- {
- pos: args.state.player.pos,
- x: args.state.player.x,
- y: args.state.player.y,
- w: args.state.player.w,
- h: args.state.player.h,
- path: "sprites/roy-#{sprite_index}.png",
- flip_horizontally: args.state.player.direction < 0
- }
-end
-
-def display_bot1 args
- start_looping_at = 0
- number_of_sprites = 6
- number_of_frames_to_show_each_sprite = 4
- does_sprite_loop = true
- sprite_index = start_looping_at.frame_index number_of_sprites,
- number_of_frames_to_show_each_sprite,
- does_sprite_loop
- {
- x: args.state.bot1.x,
- y: args.state.bot1.y,
- w: args.state.bot1.w,
- h: args.state.bot1.h,
- path: "sprites/dragon-#{sprite_index}.png",
- flip_horizontally: args.state.bot1.direction < 0
- }
-end
-
-def display_bot2 args
- start_looping_at = 0
- number_of_sprites = 6
- number_of_frames_to_show_each_sprite = 4
- does_sprite_loop = true
- sprite_index = start_looping_at.frame_index number_of_sprites,
- number_of_frames_to_show_each_sprite,
- does_sprite_loop
- {
- x: args.state.bot2.x,
- y: args.state.bot2.y,
- w: args.state.bot2.w,
- h: args.state.bot2.h,
- path: "sprites/dragon-#{sprite_index}.png",
- flip_horizontally: args.state.bot2.direction < 0
- }
-end
-
-def display_bot3 args
- start_looping_at = 0
- number_of_sprites = 6
- number_of_frames_to_show_each_sprite = 4
- does_sprite_loop = true
- sprite_index = start_looping_at.frame_index number_of_sprites,
- number_of_frames_to_show_each_sprite,
- does_sprite_loop
- {
- x: args.state.bot3.x,
- y: args.state.bot3.y,
- w: args.state.bot3.w,
- h: args.state.bot3.h,
- path: "sprites/dragon-#{sprite_index}.png",
- flip_horizontally: args.state.bot3.direction < 0
- }
-end
-
-def display_obs1 args
- start_looping_at = 0
- number_of_sprites = 1
- number_of_frames_to_show_each_sprite = 8
- does_sprite_loop = true
- sprite_index = start_looping_at.frame_index number_of_sprites,
- number_of_frames_to_show_each_sprite,
- does_sprite_loop
- {
- x: args.state.obs1.x,
- y: args.state.obs1.y,
- w: args.state.obs1.w,
- h: args.state.obs1.h,
- path: "sprites/water-1.png",
- flip_horizontally: args.state.obs1.direction < 0
- }
-end
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/border-black.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/border-black.png
deleted file mode 100644
index c9d0bad..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/border-black.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-black.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-black.png
deleted file mode 100644
index c98e23d..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-black.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-blue.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-blue.png
deleted file mode 100644
index 1726d2a..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-blue.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-gray.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-gray.png
deleted file mode 100644
index 960f191..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-gray.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-indigo.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-indigo.png
deleted file mode 100644
index 598e240..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-indigo.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-orange.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-orange.png
deleted file mode 100644
index 5604a42..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-orange.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-red.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-red.png
deleted file mode 100644
index 7f17ca6..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-red.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-violet.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-violet.png
deleted file mode 100644
index 681d210..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-violet.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-white.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-white.png
deleted file mode 100644
index bd32155..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-white.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-yellow.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-yellow.png
deleted file mode 100644
index 94992eb..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/circle-yellow.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-0.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-0.png
deleted file mode 100644
index fb179af..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-0.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-1.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-1.png
deleted file mode 100644
index 8cfe531..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-1.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-2.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-2.png
deleted file mode 100644
index cb462e1..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-2.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-3.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-3.png
deleted file mode 100644
index 04c4977..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-3.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-4.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-4.png
deleted file mode 100644
index b29fa3d..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-4.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-5.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-5.png
deleted file mode 100644
index 99f4e74..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/dragon-5.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-0.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-0.png
deleted file mode 100644
index f48636f..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-0.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-1.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-1.png
deleted file mode 100644
index b4018d9..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-1.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-2.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-2.png
deleted file mode 100644
index 3abaedd..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-2.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-3.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-3.png
deleted file mode 100644
index fe94a5a..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-3.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-4.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-4.png
deleted file mode 100644
index ed04237..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-4.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-5.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-5.png
deleted file mode 100644
index 2cd8f06..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-5.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-6.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-6.png
deleted file mode 100644
index e55909c..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-6.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-sheet.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-sheet.png
deleted file mode 100644
index 8559a5c..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/explosion-sheet.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-black.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-black.png
deleted file mode 100644
index f50c872..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-black.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-blue.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-blue.png
deleted file mode 100644
index 1696bae..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-blue.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-gray.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-gray.png
deleted file mode 100644
index e8c4c5a..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-gray.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-green.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-green.png
deleted file mode 100644
index a700602..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-green.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-indigo.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-indigo.png
deleted file mode 100644
index 15f6f4f..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-indigo.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-orange.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-orange.png
deleted file mode 100644
index 1587173..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-orange.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-red.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-red.png
deleted file mode 100644
index d442f39..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-red.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-violet.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-violet.png
deleted file mode 100644
index 3be5731..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-violet.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-white.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-white.png
deleted file mode 100644
index c1ad970..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-white.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-yellow.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-yellow.png
deleted file mode 100644
index 63f5f34..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/hexagon-yellow.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-black.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-black.png
deleted file mode 100644
index fa9e463..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-black.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-blue.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-blue.png
deleted file mode 100644
index a3d8524..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-blue.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-gray.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-gray.png
deleted file mode 100644
index 85dcc1d..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-gray.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-green.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-green.png
deleted file mode 100644
index ec2773e..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-green.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-orange.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-orange.png
deleted file mode 100644
index 154d81c..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-orange.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-red.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-red.png
deleted file mode 100644
index 3448c4d..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-red.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-white.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-white.png
deleted file mode 100644
index a45793d..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-white.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-yellow.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-yellow.png
deleted file mode 100644
index 9be20c7..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/isometric-yellow.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/roy-0.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/roy-0.png
deleted file mode 100644
index dd122e1..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/roy-0.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/roy-1.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/roy-1.png
deleted file mode 100644
index d3ac548..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/roy-1.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-black.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-black.png
deleted file mode 100644
index cea7bd7..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-black.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-orange.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-orange.png
deleted file mode 100644
index bb1eee7..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-orange.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-violet.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-violet.png
deleted file mode 100644
index 333540c..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/square-violet.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/star.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/star.png
deleted file mode 100644
index e0ee0f9..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/star.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/water-1.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/water-1.png
deleted file mode 100644
index 527385a..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/water-1.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/water-2.png b/samples/99_genre_rpg_tactical/gameboard_movement/sprites/water-2.png
deleted file mode 100644
index 7f73b1b..0000000
--- a/samples/99_genre_rpg_tactical/gameboard_movement/sprites/water-2.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/taking_turns/app/main.rb b/samples/99_genre_rpg_tactical/taking_turns/app/main.rb
deleted file mode 100644
index aac6de7..0000000
--- a/samples/99_genre_rpg_tactical/taking_turns/app/main.rb
+++ /dev/null
@@ -1,189 +0,0 @@
-def tick args
- args.state.base_columns ||= 10.times.map { |n| 50 * n + 1280 / 2 - 5 * 50 + 5 }
- args.state.base_rows ||= 5.times.map { |n| 50 * n + 720 - 5 * 50 }
- args.state.offset_columns = 10.times.map { |n| (n - 4.5) * Math.sin(Kernel.tick_count.to_radians) * 12 }
- args.state.offset_rows = 5.map { 0 }
- args.state.columns = 10.times.map { |i| args.state.base_columns[i] + args.state.offset_columns[i] }
- args.state.rows = 5.times.map { |i| args.state.base_rows[i] + args.state.offset_rows[i] }
- args.state.explosions ||= []
- args.state.enemies ||= []
- args.state.score ||= 0
- args.state.wave ||= 0
- if args.state.enemies.empty?
- args.state.wave += 1
- args.state.wave_root = Math.sqrt(args.state.wave)
- args.state.enemies = make_enemies
- end
- args.state.player ||= {x: 620, y: 80, w: 40, h: 40, path: 'sprites/circle-gray.png', angle: 90, cooldown: 0, alive: true}
- args.state.enemy_bullets ||= []
- args.state.player_bullets ||= []
- args.state.lives ||= 3
- args.state.missed_shots ||= 0
- args.state.fired_shots ||= 0
-
- update_explosions args
- update_enemy_positions args
-
- if args.inputs.left && args.state.player[:x] > (300 + 5)
- args.state.player[:x] -= 5
- end
- if args.inputs.right && args.state.player[:x] < (1280 - args.state.player[:w] - 300 - 5)
- args.state.player[:x] += 5
- end
-
- args.state.enemy_bullets.each do |bullet|
- bullet[:x] += bullet[:dx]
- bullet[:y] += bullet[:dy]
- end
- args.state.player_bullets.each do |bullet|
- bullet[:x] += bullet[:dx]
- bullet[:y] += bullet[:dy]
- end
-
- args.state.enemy_bullets = args.state.enemy_bullets.find_all { |bullet| bullet[:y].between?(-16, 736) }
- args.state.player_bullets = args.state.player_bullets.find_all do |bullet|
- if bullet[:y].between?(-16, 736)
- true
- else
- args.state.missed_shots += 1
- false
- end
- end
-
- args.state.enemies = args.state.enemies.reject do |enemy|
- if args.state.player[:alive] && 1500 > (args.state.player[:x] - enemy[:x]) ** 2 + (args.state.player[:y] - enemy[:y]) ** 2
- args.state.explosions << {x: enemy[:x] + 4, y: enemy[:y] + 4, w: 32, h: 32, path: 'sprites/explosion-0.png', age: 0}
- args.state.explosions << {x: args.state.player[:x] + 4, y: args.state.player[:y] + 4, w: 32, h: 32, path: 'sprites/explosion-0.png', age: 0}
- args.state.player[:alive] = false
- true
- else
- false
- end
- end
- args.state.enemy_bullets.each do |bullet|
- if args.state.player[:alive] && 400 > (args.state.player[:x] - bullet[:x] + 12) ** 2 + (args.state.player[:y] - bullet[:y] + 12) ** 2
- args.state.explosions << {x: args.state.player[:x] + 4, y: args.state.player[:y] + 4, w: 32, h: 32, path: 'sprites/explosion-0.png', age: 0}
- args.state.player[:alive] = false
- bullet[:despawn] = true
- end
- end
- args.state.enemies = args.state.enemies.reject do |enemy|
- args.state.player_bullets.any? do |bullet|
- if 400 > (enemy[:x] - bullet[:x] + 12) ** 2 + (enemy[:y] - bullet[:y] + 12) ** 2
- args.state.explosions << {x: enemy[:x] + 4, y: enemy[:y] + 4, w: 32, h: 32, path: 'sprites/explosion-0.png', age: 0}
- bullet[:despawn] = true
- args.state.score += 1000 * args.state.wave
- true
- else
- false
- end
- end
- end
-
- args.state.player_bullets = args.state.player_bullets.reject { |bullet| bullet[:despawn] }
- args.state.enemy_bullets = args.state.enemy_bullets.reject { |bullet| bullet[:despawn] }
-
- args.state.player[:cooldown] -= 1
- if args.inputs.keyboard.key_held.space && args.state.player[:cooldown] <= 0 && args.state.player[:alive]
- args.state.player_bullets << {x: args.state.player[:x] + 12, y: args.state.player[:y] + 28, w: 16, h: 16, path: 'sprites/star.png', dx: 0, dy: 8}.sprite
- args.state.fired_shots += 1
- args.state.player[:cooldown] = 10 + 20 / args.state.wave
- end
- args.state.enemies.each do |enemy|
- if Math.rand < 0.0005 + 0.0005 * args.state.wave && args.state.player[:alive] && enemy[:move_state] == :normal
- args.state.enemy_bullets << {x: enemy[:x] + 12, y: enemy[:y] - 8, w: 16, h: 16, path: 'sprites/star.png', dx: 0, dy: -3 - args.state.wave_root}.sprite
- end
- end
-
- args.outputs.background_color = [0, 0, 0]
- args.outputs.primitives << args.state.enemies.map do |enemy|
- [enemy[:x], enemy[:y], 40, 40, enemy[:path], -90].sprite
- end
- args.outputs.primitives << args.state.player if args.state.player[:alive]
- args.outputs.primitives << args.state.explosions
- args.outputs.primitives << args.state.player_bullets
- args.outputs.primitives << args.state.enemy_bullets
- accuracy = args.state.fired_shots.zero? ? 1 : (args.state.fired_shots - args.state.missed_shots) / args.state.fired_shots
- args.outputs.primitives << [
- [0, 0, 300, 720, 96, 0, 0].solid,
- [1280 - 300, 0, 300, 720, 96, 0, 0].solid,
- [1280 - 290, 60, "Wave #{args.state.wave}", 255, 255, 255].label,
- [1280 - 290, 40, "Accuracy #{(accuracy * 100).floor}%", 255, 255, 255].label,
- [1280 - 290, 20, "Score #{(args.state.score * accuracy).floor}", 255, 255, 255].label,
- ]
- args.outputs.primitives << args.state.lives.times.map do |n|
- [1280 - 290 + 50 * n, 80, 40, 40, 'sprites/circle-gray.png', 90].sprite
- end
- #args.outputs.debug << args.gtk.framerate_diagnostics_primitives
-
- if (!args.state.player[:alive]) && args.state.enemy_bullets.empty? && args.state.explosions.empty? && args.state.enemies.all? { |enemy| enemy[:move_state] == :normal }
- args.state.player[:alive] = true
- args.state.player[:x] = 624
- args.state.player[:y] = 80
- args.state.lives -= 1
- if args.state.lives == -1
- args.state.clear!
- end
- end
-end
-
-def make_enemies
- enemies = []
- enemies += 10.times.map { |n| {x: Math.rand * 1280 * 2 - 640, y: Math.rand * 720 * 2 + 720, row: 0, col: n, path: 'sprites/circle-orange.png', move_state: :retreat} }
- enemies += 10.times.map { |n| {x: Math.rand * 1280 * 2 - 640, y: Math.rand * 720 * 2 + 720, row: 1, col: n, path: 'sprites/circle-orange.png', move_state: :retreat} }
- enemies += 8.times.map { |n| {x: Math.rand * 1280 * 2 - 640, y: Math.rand * 720 * 2 + 720, row: 2, col: n + 1, path: 'sprites/circle-blue.png', move_state: :retreat} }
- enemies += 8.times.map { |n| {x: Math.rand * 1280 * 2 - 640, y: Math.rand * 720 * 2 + 720, row: 3, col: n + 1, path: 'sprites/circle-blue.png', move_state: :retreat} }
- enemies += 4.times.map { |n| {x: Math.rand * 1280 * 2 - 640, y: Math.rand * 720 * 2 + 720, row: 4, col: n + 3, path: 'sprites/circle-green.png', move_state: :retreat} }
- enemies
-end
-
-def update_explosions args
- args.state.explosions.each do |explosion|
- explosion[:age] += 0.5
- explosion[:path] = "sprites/explosion-#{explosion[:age].floor}.png"
- end
- args.state.explosions = args.state.explosions.reject { |explosion| explosion[:age] >= 7 }
-end
-
-def update_enemy_positions args
- args.state.enemies.each do |enemy|
- if enemy[:move_state] == :normal
- enemy[:x] = args.state.columns[enemy[:col]]
- enemy[:y] = args.state.rows[enemy[:row]]
- enemy[:move_state] = :dive if Math.rand < 0.0002 + 0.00005 * args.state.wave && args.state.player[:alive]
- elsif enemy[:move_state] == :dive
- enemy[:target_x] ||= args.state.player[:x]
- enemy[:target_y] ||= args.state.player[:y]
- dx = enemy[:target_x] - enemy[:x]
- dy = enemy[:target_y] - enemy[:y]
- vel = Math.sqrt(dx * dx + dy * dy)
- speed_limit = 2 + args.state.wave_root
- if vel > speed_limit
- dx /= vel / speed_limit
- dy /= vel / speed_limit
- end
- if vel < 1 || !args.state.player[:alive]
- enemy[:move_state] = :retreat
- end
- enemy[:x] += dx
- enemy[:y] += dy
- elsif enemy[:move_state] == :retreat
- enemy[:target_x] = args.state.columns[enemy[:col]]
- enemy[:target_y] = args.state.rows[enemy[:row]]
- dx = enemy[:target_x] - enemy[:x]
- dy = enemy[:target_y] - enemy[:y]
- vel = Math.sqrt(dx * dx + dy * dy)
- speed_limit = 2 + args.state.wave_root
- if vel > speed_limit
- dx /= vel / speed_limit
- dy /= vel / speed_limit
- elsif vel < 1
- enemy[:move_state] = :normal
- enemy[:target_x] = nil
- enemy[:target_y] = nil
- end
- enemy[:x] += dx
- enemy[:y] += dy
- end
- end
-end
diff --git a/samples/99_genre_rpg_tactical/taking_turns/run.bat b/samples/99_genre_rpg_tactical/taking_turns/run.bat
deleted file mode 100644
index 36335e3..0000000
--- a/samples/99_genre_rpg_tactical/taking_turns/run.bat
+++ /dev/null
@@ -1,6 +0,0 @@
-cd /d %~dp0
-
-cd ..
-cd ..
-cd ..
-dragonruby samples/99_genre_arcade/dragalaga
diff --git a/samples/99_genre_rpg_tactical/taking_turns/sprites/circle-blue.png b/samples/99_genre_rpg_tactical/taking_turns/sprites/circle-blue.png
deleted file mode 100644
index 1726d2a..0000000
--- a/samples/99_genre_rpg_tactical/taking_turns/sprites/circle-blue.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/taking_turns/sprites/circle-gray.png b/samples/99_genre_rpg_tactical/taking_turns/sprites/circle-gray.png
deleted file mode 100644
index 960f191..0000000
--- a/samples/99_genre_rpg_tactical/taking_turns/sprites/circle-gray.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/taking_turns/sprites/circle-green.png b/samples/99_genre_rpg_tactical/taking_turns/sprites/circle-green.png
deleted file mode 100644
index 43cf7ee..0000000
--- a/samples/99_genre_rpg_tactical/taking_turns/sprites/circle-green.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/taking_turns/sprites/circle-orange.png b/samples/99_genre_rpg_tactical/taking_turns/sprites/circle-orange.png
deleted file mode 100644
index 5604a42..0000000
--- a/samples/99_genre_rpg_tactical/taking_turns/sprites/circle-orange.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-0.png b/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-0.png
deleted file mode 100644
index f48636f..0000000
--- a/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-0.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-1.png b/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-1.png
deleted file mode 100644
index b4018d9..0000000
--- a/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-1.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-2.png b/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-2.png
deleted file mode 100644
index 3abaedd..0000000
--- a/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-2.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-3.png b/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-3.png
deleted file mode 100644
index fe94a5a..0000000
--- a/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-3.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-4.png b/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-4.png
deleted file mode 100644
index ed04237..0000000
--- a/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-4.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-5.png b/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-5.png
deleted file mode 100644
index 2cd8f06..0000000
--- a/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-5.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-6.png b/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-6.png
deleted file mode 100644
index e55909c..0000000
--- a/samples/99_genre_rpg_tactical/taking_turns/sprites/explosion-6.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_tactical/taking_turns/sprites/star.png b/samples/99_genre_rpg_tactical/taking_turns/sprites/star.png
deleted file mode 100644
index e0ee0f9..0000000
--- a/samples/99_genre_rpg_tactical/taking_turns/sprites/star.png
+++ /dev/null
Binary files differ
diff --git a/samples/99_genre_rpg_topdown/topdown_casino/app/main.rb b/samples/99_genre_rpg_topdown/topdown_casino/app/main.rb
new file mode 100644
index 0000000..eccf744
--- /dev/null
+++ b/samples/99_genre_rpg_topdown/topdown_casino/app/main.rb
@@ -0,0 +1,139 @@
+$gtk.reset
+
+def coinflip
+ rand < 0.5
+end
+
+class Game
+ attr_accessor :args
+
+ def text_font
+ return nil #"rpg.ttf"
+ end
+
+ def text_color
+ [ 255, 255, 255, 255 ]
+ end
+
+ def set_gem_values
+ @args.state.gem0 = ((coinflip) ? 100 : 20)
+ @args.state.gem1 = ((coinflip) ? -10 : -50)
+ @args.state.gem2 = ((coinflip) ? -10 : -30)
+ if coinflip
+ tmp = @args.state.gem0
+ @args.state.gem0 = @args.state.gem1
+ @args.state.gem1 = tmp
+ end
+ if coinflip
+ tmp = @args.state.gem1
+ @args.state.gem1 = @args.state.gem2
+ @args.state.gem2 = tmp
+ end
+ if coinflip
+ tmp = @args.state.gem0
+ @args.state.gem0 = @args.state.gem2
+ @args.state.gem2 = tmp
+ end
+ end
+
+ def initialize args
+ @args = args
+ @args.state.animticks = 0
+ @args.state.score = 0
+ @args.state.gem_chosen = false
+ @args.state.round_finished = false
+ @args.state.gem0_x = 197
+ @args.state.gem0_y = 720-274
+ @args.state.gem1_x = 623
+ @args.state.gem1_y = 720-274
+ @args.state.gem2_x = 1049
+ @args.state.gem2_y = 720-274
+ @args.state.hero_sprite = "sprites/herodown100.png"
+ @args.state.hero_x = 608
+ @args.state.hero_y = 720-656
+ set_gem_values
+ end
+
+ def render_gem_value x, y, gem
+ if @args.state.gem_chosen
+ @args.outputs.labels << [ x, y + 96, gem.to_s, 1, 1, *text_color, text_font ]
+ end
+ end
+
+ def render
+ gemsprite = ((@args.state.animticks % 400) < 200) ? 'sprites/gem200.png' : 'sprites/gem400.png'
+ @args.outputs.background_color = [ 0, 0, 0, 255 ]
+ @args.outputs.sprites << [608, 720-150, 64, 64, 'sprites/oldman.png']
+ @args.outputs.sprites << [300, 720-150, 64, 64, 'sprites/fire.png']
+ @args.outputs.sprites << [900, 720-150, 64, 64, 'sprites/fire.png']
+ @args.outputs.sprites << [@args.state.gem0_x, @args.state.gem0_y, 32, 64, gemsprite]
+ @args.outputs.sprites << [@args.state.gem1_x, @args.state.gem1_y, 32, 64, gemsprite]
+ @args.outputs.sprites << [@args.state.gem2_x, @args.state.gem2_y, 32, 64, gemsprite]
+ @args.outputs.sprites << [@args.state.hero_x, @args.state.hero_y, 64, 64, @args.state.hero_sprite]
+
+ @args.outputs.labels << [ 630, 720-30, "IT'S A SECRET TO EVERYONE.", 1, 1, *text_color, text_font ]
+ @args.outputs.labels << [ 50, 720-85, @args.state.score.to_s, 1, 1, *text_color, text_font ]
+ render_gem_value @args.state.gem0_x, @args.state.gem0_y, @args.state.gem0
+ render_gem_value @args.state.gem1_x, @args.state.gem1_y, @args.state.gem1
+ render_gem_value @args.state.gem2_x, @args.state.gem2_y, @args.state.gem2
+ end
+
+ def calc
+ @args.state.animticks += 16
+
+ return unless @args.state.gem_chosen
+ @args.state.round_finished_debounce ||= 60 * 3
+ @args.state.round_finished_debounce -= 1
+ return if @args.state.round_finished_debounce > 0
+
+ @args.state.gem_chosen = false
+ @args.state.hero.sprite[0] = 'sprites/herodown100.png'
+ @args.state.hero.sprite[1] = 608
+ @args.state.hero.sprite[2] = 656
+ @args.state.round_finished_debounce = nil
+ set_gem_values
+ end
+
+ def walk xdir, ydir, anim
+ @args.state.hero_sprite = "sprites/#{anim}#{(((@args.state.animticks % 200) < 100) ? '100' : '200')}.png"
+ @args.state.hero_x += 5 * xdir
+ @args.state.hero_y += 5 * ydir
+ end
+
+ def check_gem_touching gem_x, gem_y, gem
+ return if @args.state.gem_chosen
+ herorect = [ @args.state.hero_x, @args.state.hero_y, 64, 64 ]
+ return if !herorect.intersect_rect?([gem_x, gem_y, 32, 64])
+ @args.state.gem_chosen = true
+ @args.state.score += gem
+ @args.outputs.sounds << ((gem < 0) ? 'sounds/lose.wav' : 'sounds/win.wav')
+ end
+
+ def input
+ if @args.inputs.keyboard.key_held.left
+ walk(-1.0, 0.0, 'heroleft')
+ elsif @args.inputs.keyboard.key_held.right
+ walk(1.0, 0.0, 'heroright')
+ elsif @args.inputs.keyboard.key_held.up
+ walk(0.0, 1.0, 'heroup')
+ elsif @args.inputs.keyboard.key_held.down
+ walk(0.0, -1.0, 'herodown')
+ end
+
+ check_gem_touching(@args.state.gem0_x, @args.state.gem0_y, @args.state.gem0)
+ check_gem_touching(@args.state.gem1_x, @args.state.gem1_y, @args.state.gem1)
+ check_gem_touching(@args.state.gem2_x, @args.state.gem2_y, @args.state.gem2)
+ end
+
+ def tick
+ input
+ calc
+ render
+ end
+end
+
+def tick args
+ args.state.game ||= Game.new args
+ args.state.game.args = args
+ args.state.game.tick
+end
diff --git a/samples/99_genre_rpg_topdown/topdown_casino/license-for-sample.txt b/samples/99_genre_rpg_topdown/topdown_casino/license-for-sample.txt
new file mode 100644
index 0000000..c25563f
--- /dev/null
+++ b/samples/99_genre_rpg_topdown/topdown_casino/license-for-sample.txt
@@ -0,0 +1,9 @@
+Copyright 2019 DragonRuby LLC (code), Nick Culbertson @mobypixel (art/music)
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/samples/99_genre_rpg_topdown/topdown_casino/replay.txt b/samples/99_genre_rpg_topdown/topdown_casino/replay.txt
new file mode 100644
index 0000000..e4d52d7
--- /dev/null
+++ b/samples/99_genre_rpg_topdown/topdown_casino/replay.txt
@@ -0,0 +1,123 @@
+replay_version 2.0
+stopped_at 871
+seed 100
+recorded_at 2021-11-20 11:37:50 -0600
+[:mouse_button_up, 1, 0, 1, 1, 4]
+[:mouse_move, 802, 86, 2, 2, 21]
+[:key_down_raw, 1073741906, 0, 2, 3, 105]
+[:key_down_raw, 1073741906, 0, 2, 4, 119]
+[:key_down_raw, 1073741906, 0, 2, 5, 121]
+[:key_down_raw, 1073741906, 0, 2, 6, 123]
+[:key_down_raw, 1073741906, 0, 2, 7, 125]
+[:key_down_raw, 1073741906, 0, 2, 8, 127]
+[:key_down_raw, 1073741906, 0, 2, 9, 129]
+[:key_down_raw, 1073741906, 0, 2, 10, 131]
+[:key_down_raw, 1073741906, 0, 2, 11, 133]
+[:key_down_raw, 1073741906, 0, 2, 12, 135]
+[:key_down_raw, 1073741906, 0, 2, 13, 137]
+[:key_down_raw, 1073741906, 0, 2, 14, 139]
+[:key_up_raw, 1073741906, 0, 2, 15, 140]
+[:key_down_raw, 1073741903, 0, 2, 16, 141]
+[:key_down_raw, 1073741906, 0, 2, 17, 153]
+[:key_up_raw, 1073741903, 0, 2, 18, 160]
+[:key_down_raw, 1073741906, 0, 2, 19, 168]
+[:key_down_raw, 1073741906, 0, 2, 20, 170]
+[:key_down_raw, 1073741906, 0, 2, 21, 172]
+[:key_down_raw, 1073741906, 0, 2, 22, 174]
+[:key_down_raw, 1073741906, 0, 2, 23, 176]
+[:key_down_raw, 1073741906, 0, 2, 24, 178]
+[:key_down_raw, 1073741906, 0, 2, 25, 180]
+[:key_down_raw, 1073741906, 0, 2, 26, 182]
+[:key_down_raw, 1073741906, 0, 2, 27, 184]
+[:key_down_raw, 1073741906, 0, 2, 28, 186]
+[:key_down_raw, 1073741906, 0, 2, 29, 188]
+[:key_down_raw, 1073741906, 0, 2, 30, 190]
+[:key_down_raw, 1073741906, 0, 2, 31, 192]
+[:key_down_raw, 1073741906, 0, 2, 32, 194]
+[:key_down_raw, 1073741906, 0, 2, 33, 196]
+[:key_up_raw, 1073741906, 0, 2, 34, 196]
+[:key_down_raw, 1073741904, 0, 2, 35, 225]
+[:key_down_raw, 1073741904, 0, 2, 36, 240]
+[:key_down_raw, 1073741904, 0, 2, 37, 242]
+[:key_down_raw, 1073741904, 0, 2, 38, 244]
+[:key_up_raw, 1073741904, 0, 2, 39, 244]
+[:key_down_raw, 1073741905, 0, 2, 40, 297]
+[:key_down_raw, 1073741905, 0, 2, 41, 312]
+[:key_down_raw, 1073741905, 0, 2, 42, 314]
+[:key_down_raw, 1073741905, 0, 2, 43, 316]
+[:key_down_raw, 1073741905, 0, 2, 44, 318]
+[:key_down_raw, 1073741905, 0, 2, 45, 320]
+[:key_down_raw, 1073741905, 0, 2, 46, 322]
+[:key_down_raw, 1073741905, 0, 2, 47, 324]
+[:key_up_raw, 1073741905, 0, 2, 48, 326]
+[:key_down_raw, 1073741904, 0, 2, 49, 355]
+[:key_down_raw, 1073741904, 0, 2, 50, 370]
+[:key_down_raw, 1073741904, 0, 2, 51, 372]
+[:key_down_raw, 1073741904, 0, 2, 52, 374]
+[:key_down_raw, 1073741904, 0, 2, 53, 376]
+[:key_down_raw, 1073741904, 0, 2, 54, 378]
+[:key_up_raw, 1073741904, 0, 2, 55, 379]
+[:key_down_raw, 1073741906, 0, 2, 56, 393]
+[:key_down_raw, 1073741906, 0, 2, 57, 408]
+[:key_down_raw, 1073741906, 0, 2, 58, 410]
+[:key_down_raw, 1073741906, 0, 2, 59, 412]
+[:key_down_raw, 1073741906, 0, 2, 60, 414]
+[:key_down_raw, 1073741906, 0, 2, 61, 416]
+[:key_down_raw, 1073741906, 0, 2, 62, 418]
+[:key_down_raw, 1073741906, 0, 2, 63, 421]
+[:key_up_raw, 1073741906, 0, 2, 64, 421]
+[:key_down_raw, 1073741906, 0, 2, 65, 454]
+[:key_down_raw, 1073741906, 0, 2, 66, 468]
+[:key_down_raw, 1073741906, 0, 2, 67, 470]
+[:key_down_raw, 1073741906, 0, 2, 68, 472]
+[:key_down_raw, 1073741906, 0, 2, 69, 474]
+[:key_up_raw, 1073741906, 0, 2, 70, 475]
+[:key_down_raw, 1073741904, 0, 2, 71, 476]
+[:key_down_raw, 1073741904, 0, 2, 72, 491]
+[:key_down_raw, 1073741904, 0, 2, 73, 493]
+[:key_down_raw, 1073741904, 0, 2, 74, 495]
+[:key_down_raw, 1073741906, 0, 2, 75, 496]
+[:key_down_raw, 1073741906, 0, 2, 76, 511]
+[:key_down_raw, 1073741906, 0, 2, 77, 513]
+[:key_down_raw, 1073741906, 0, 2, 78, 515]
+[:key_up_raw, 1073741906, 0, 2, 79, 515]
+[:key_down_raw, 1073741905, 0, 2, 80, 524]
+[:key_up_raw, 1073741904, 0, 2, 81, 526]
+[:key_up_raw, 1073741905, 0, 2, 82, 532]
+[:key_down_raw, 1073741906, 0, 2, 83, 570]
+[:key_down_raw, 1073741906, 0, 2, 84, 585]
+[:key_up_raw, 1073741906, 0, 2, 85, 586]
+[:key_down_raw, 1073741903, 0, 2, 86, 591]
+[:key_up_raw, 1073741903, 0, 2, 87, 605]
+[:key_down_raw, 1073741905, 0, 2, 88, 608]
+[:key_down_raw, 1073741905, 0, 2, 89, 623]
+[:key_down_raw, 1073741904, 0, 2, 90, 625]
+[:key_up_raw, 1073741905, 0, 2, 91, 627]
+[:key_down_raw, 1073741904, 0, 2, 92, 640]
+[:key_down_raw, 1073741904, 0, 2, 93, 642]
+[:key_down_raw, 1073741904, 0, 2, 94, 644]
+[:key_down_raw, 1073741904, 0, 2, 95, 646]
+[:key_down_raw, 1073741904, 0, 2, 96, 648]
+[:key_up_raw, 1073741904, 0, 2, 97, 650]
+[:key_down_raw, 1073741903, 0, 2, 98, 705]
+[:key_down_raw, 1073741903, 0, 2, 99, 720]
+[:key_down_raw, 1073741903, 0, 2, 100, 722]
+[:key_down_raw, 1073741903, 0, 2, 101, 724]
+[:key_down_raw, 1073741903, 0, 2, 102, 726]
+[:key_down_raw, 1073741903, 0, 2, 103, 729]
+[:key_down_raw, 1073741903, 0, 2, 104, 731]
+[:key_down_raw, 1073741903, 0, 2, 105, 733]
+[:key_down_raw, 1073741903, 0, 2, 106, 735]
+[:key_down_raw, 1073741903, 0, 2, 107, 737]
+[:key_down_raw, 1073741903, 0, 2, 108, 739]
+[:key_down_raw, 1073741903, 0, 2, 109, 741]
+[:key_down_raw, 1073741903, 0, 2, 110, 743]
+[:key_down_raw, 1073741903, 0, 2, 111, 745]
+[:key_down_raw, 1073741903, 0, 2, 112, 747]
+[:key_down_raw, 1073741903, 0, 2, 113, 749]
+[:key_down_raw, 1073741903, 0, 2, 114, 751]
+[:key_down_raw, 1073741903, 0, 2, 115, 753]
+[:key_up_raw, 1073741903, 0, 2, 116, 753]
+[:key_down_raw, 96, 0, 2, 117, 818]
+[:key_up_raw, 96, 0, 2, 118, 823]
+[:key_down_raw, 13, 0, 2, 119, 871]
diff --git a/samples/99_genre_rpg_topdown/topdown_casino/sprites/fire.png b/samples/99_genre_rpg_topdown/topdown_casino/sprites/fire.png
new file mode 100644
index 0000000..ed4b2f0
--- /dev/null
+++ b/samples/99_genre_rpg_topdown/topdown_casino/sprites/fire.png
Binary files differ
diff --git a/samples/99_genre_rpg_topdown/topdown_casino/sprites/gem200.png b/samples/99_genre_rpg_topdown/topdown_casino/sprites/gem200.png
new file mode 100644
index 0000000..f643db9
--- /dev/null
+++ b/samples/99_genre_rpg_topdown/topdown_casino/sprites/gem200.png
Binary files differ
diff --git a/samples/99_genre_rpg_topdown/topdown_casino/sprites/gem400.png b/samples/99_genre_rpg_topdown/topdown_casino/sprites/gem400.png
new file mode 100644
index 0000000..f872e06
--- /dev/null
+++ b/samples/99_genre_rpg_topdown/topdown_casino/sprites/gem400.png
Binary files differ
diff --git a/samples/99_genre_rpg_topdown/topdown_casino/sprites/herodown100.png b/samples/99_genre_rpg_topdown/topdown_casino/sprites/herodown100.png
new file mode 100644
index 0000000..116d406
--- /dev/null
+++ b/samples/99_genre_rpg_topdown/topdown_casino/sprites/herodown100.png
Binary files differ
diff --git a/samples/99_genre_rpg_topdown/topdown_casino/sprites/herodown200.png b/samples/99_genre_rpg_topdown/topdown_casino/sprites/herodown200.png
new file mode 100644
index 0000000..116d406
--- /dev/null
+++ b/samples/99_genre_rpg_topdown/topdown_casino/sprites/herodown200.png
Binary files differ
diff --git a/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroleft100.png b/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroleft100.png
new file mode 100644
index 0000000..116d406
--- /dev/null
+++ b/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroleft100.png
Binary files differ
diff --git a/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroleft200.png b/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroleft200.png
new file mode 100644
index 0000000..116d406
--- /dev/null
+++ b/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroleft200.png
Binary files differ
diff --git a/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroright100.png b/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroright100.png
new file mode 100644
index 0000000..116d406
--- /dev/null
+++ b/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroright100.png
Binary files differ
diff --git a/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroright200.png b/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroright200.png
new file mode 100644
index 0000000..116d406
--- /dev/null
+++ b/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroright200.png
Binary files differ
diff --git a/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroup100.png b/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroup100.png
new file mode 100644
index 0000000..116d406
--- /dev/null
+++ b/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroup100.png
Binary files differ
diff --git a/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroup200.png b/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroup200.png
new file mode 100644
index 0000000..116d406
--- /dev/null
+++ b/samples/99_genre_rpg_topdown/topdown_casino/sprites/heroup200.png
Binary files differ
diff --git a/samples/99_genre_rpg_topdown/topdown_casino/sprites/oldman.png b/samples/99_genre_rpg_topdown/topdown_casino/sprites/oldman.png
new file mode 100644
index 0000000..a9bb758
--- /dev/null
+++ b/samples/99_genre_rpg_topdown/topdown_casino/sprites/oldman.png
Binary files differ
diff --git a/samples/99_genre_rpg_topdown/topdown_starting_point/app/main.rb b/samples/99_genre_rpg_topdown/topdown_starting_point/app/main.rb
index 33228a6..c447940 100644
--- a/samples/99_genre_rpg_topdown/topdown_starting_point/app/main.rb
+++ b/samples/99_genre_rpg_topdown/topdown_starting_point/app/main.rb
@@ -15,6 +15,7 @@
- args.outputs.labels: An array. The values generate a label.
The parameters are [X, Y, TEXT, SIZE, ALIGNMENT, RED, GREEN, BLUE, ALPHA, FONT STYLE]
+ For more information about labels, go to mygame/documentation/02-labels.md.
=end
diff --git a/samples/99_genre_teenytiny/app/main.rb b/samples/99_genre_teenytiny/app/main.rb
new file mode 100644
index 0000000..a542a93
--- /dev/null
+++ b/samples/99_genre_teenytiny/app/main.rb
@@ -0,0 +1,162 @@
+# full documenation is at http://docs.dragonruby.org
+# be sure to come to the discord if you hit any snags: http://discord.dragonruby.org
+def tick args
+ # ====================================================
+ # initialize default variables
+ # ====================================================
+
+ # ruby has an operator called ||= which means "only initialize this if it's nil"
+ args.state.count_down ||= 20 * 60 # set the count down to 20 seconds
+ # set the initial position of the target
+ args.state.target ||= { x: args.grid.w.half,
+ y: args.grid.h.half,
+ w: 20,
+ h: 20 }
+
+ # set the initial position of the player
+ args.state.player ||= { x: 50,
+ y: 50,
+ w: 20,
+ h: 20 }
+
+ # set the player movement speed
+ args.state.player_speed ||= 5
+
+ # set the score
+ args.state.score ||= 0
+ args.state.teleports ||= 3
+
+ # set the instructions
+ args.state.instructions ||= "Get to the red goal! Use arrow keys to move. Spacebar to teleport (use them carefully)!"
+
+ # ====================================================
+ # render the game
+ # ====================================================
+ args.outputs.labels << { x: args.grid.w.half, y: args.grid.h - 10,
+ text: args.state.instructions,
+ alignment_enum: 1 }
+
+ # check if it's game over. if so, then render game over
+ # otherwise render the current time left
+ if game_over? args
+ args.outputs.labels << { x: args.grid.w.half,
+ y: args.grid.h - 40,
+ text: "game over! (press r to start over)",
+ alignment_enum: 1 }
+ else
+ args.outputs.labels << { x: args.grid.w.half,
+ y: args.grid.h - 40,
+ text: "time left: #{(args.state.count_down.idiv 60) + 1}",
+ alignment_enum: 1 }
+ end
+
+ # render the score
+ args.outputs.labels << { x: args.grid.w.half,
+ y: args.grid.h - 70,
+ text: "score: #{args.state.score}",
+ alignment_enum: 1 }
+
+ # render the player with teleport count
+ args.outputs.sprites << { x: args.state.player.x,
+ y: args.state.player.y,
+ w: args.state.player.w,
+ h: args.state.player.h,
+ path: 'sprites/square-green.png' }
+
+ args.outputs.labels << { x: args.state.player.x + 10,
+ y: args.state.player.y + 40,
+ text: "teleports: #{args.state.teleports}",
+ alignment_enum: 1, size_enum: -2 }
+
+ # render the target
+ args.outputs.sprites << { x: args.state.target.x,
+ y: args.state.target.y,
+ w: args.state.target.w,
+ h: args.state.target.h,
+ path: 'sprites/square-red.png' }
+
+ # ====================================================
+ # run simulation
+ # ====================================================
+
+ # count down calculation
+ args.state.count_down -= 1
+ args.state.count_down = -1 if args.state.count_down < -1
+
+ # ====================================================
+ # process player input
+ # ====================================================
+ # if it isn't game over let them move
+ if !game_over? args
+ dir_y = 0
+ dir_x = 0
+
+ # determine the change horizontally
+ if args.inputs.keyboard.up
+ dir_y += args.state.player_speed
+ elsif args.inputs.keyboard.down
+ dir_y -= args.state.player_speed
+ end
+
+ # determine the change vertically
+ if args.inputs.keyboard.left
+ dir_x -= args.state.player_speed
+ elsif args.inputs.keyboard.right
+ dir_x += args.state.player_speed
+ end
+
+ # determine if teleport can be used
+ if args.inputs.keyboard.key_down.space && args.state.teleports > 0
+ args.state.teleports -= 1
+ dir_x *= 20
+ dir_y *= 20
+ end
+
+ # apply change to player
+ args.state.player.x += dir_x
+ args.state.player.y += dir_y
+ else
+ # if r is pressed, reset the game
+ if args.inputs.keyboard.key_down.r
+ $gtk.reset
+ return
+ end
+ end
+
+ # ====================================================
+ # determine score
+ # ====================================================
+
+ # calculate new score if the player is at goal
+ if !game_over? args
+
+ # if the player is at the goal, then move the goal
+ if args.state.player.intersect_rect? args.state.target
+ # increment the goal
+ args.state.score += 1
+
+ # move the goal to a random location
+ args.state.target = { x: (rand args.grid.w), y: (rand args.grid.h), w: 20, h: 20 }
+
+ # make sure the goal is inside the view area
+ if args.state.target.x < 0
+ args.state.target.x += 20
+ elsif args.state.target.x > 1280
+ args.state.target.x -= 20
+ end
+
+ # make sure the goal is inside the view area
+ if args.state.target.y < 0
+ args.state.target.y += 20
+ elsif args.state.target.y > 720
+ args.state.target.y -= 20
+ end
+ end
+ end
+end
+
+def game_over? args
+ args.state.count_down < 0
+end
+
+$gtk.reset
diff --git a/samples/99_genre_teenytiny/license.txt b/samples/99_genre_teenytiny/license.txt
new file mode 100644
index 0000000..100dcec
--- /dev/null
+++ b/samples/99_genre_teenytiny/license.txt
@@ -0,0 +1,9 @@
+Copyright 2019 DragonRuby LLC
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/samples/99_genre_teenytiny/metadata/game_metadata.txt b/samples/99_genre_teenytiny/metadata/game_metadata.txt
new file mode 100644
index 0000000..1b03500
--- /dev/null
+++ b/samples/99_genre_teenytiny/metadata/game_metadata.txt
@@ -0,0 +1,6 @@
+#devid=myname
+#devtitle=My Name
+#gameid=mygame
+#gametitle=My Game
+#version=0.1
+#icon=metadata/icon.png
diff --git a/samples/99_genre_teenytiny/metadata/icon.png b/samples/99_genre_teenytiny/metadata/icon.png
new file mode 100644
index 0000000..e20e8c2
--- /dev/null
+++ b/samples/99_genre_teenytiny/metadata/icon.png
Binary files differ
diff --git a/samples/99_genre_teenytiny/sprites/square-green.png b/samples/99_genre_teenytiny/sprites/square-green.png
new file mode 100644
index 0000000..5ef7f75
--- /dev/null
+++ b/samples/99_genre_teenytiny/sprites/square-green.png
Binary files differ
diff --git a/samples/99_genre_teenytiny/sprites/square-red.png b/samples/99_genre_teenytiny/sprites/square-red.png
new file mode 100644
index 0000000..3ed5f13
--- /dev/null
+++ b/samples/99_genre_teenytiny/sprites/square-red.png
Binary files differ
diff --git a/samples/99_genre_teenytiny/teenytiny_starting_point/app/main.rb b/samples/99_genre_teenytiny/teenytiny_starting_point/app/main.rb
new file mode 100644
index 0000000..a542a93
--- /dev/null
+++ b/samples/99_genre_teenytiny/teenytiny_starting_point/app/main.rb
@@ -0,0 +1,162 @@
+# full documenation is at http://docs.dragonruby.org
+# be sure to come to the discord if you hit any snags: http://discord.dragonruby.org
+def tick args
+ # ====================================================
+ # initialize default variables
+ # ====================================================
+
+ # ruby has an operator called ||= which means "only initialize this if it's nil"
+ args.state.count_down ||= 20 * 60 # set the count down to 20 seconds
+ # set the initial position of the target
+ args.state.target ||= { x: args.grid.w.half,
+ y: args.grid.h.half,
+ w: 20,
+ h: 20 }
+
+ # set the initial position of the player
+ args.state.player ||= { x: 50,
+ y: 50,
+ w: 20,
+ h: 20 }
+
+ # set the player movement speed
+ args.state.player_speed ||= 5
+
+ # set the score
+ args.state.score ||= 0
+ args.state.teleports ||= 3
+
+ # set the instructions
+ args.state.instructions ||= "Get to the red goal! Use arrow keys to move. Spacebar to teleport (use them carefully)!"
+
+ # ====================================================
+ # render the game
+ # ====================================================
+ args.outputs.labels << { x: args.grid.w.half, y: args.grid.h - 10,
+ text: args.state.instructions,
+ alignment_enum: 1 }
+
+ # check if it's game over. if so, then render game over
+ # otherwise render the current time left
+ if game_over? args
+ args.outputs.labels << { x: args.grid.w.half,
+ y: args.grid.h - 40,
+ text: "game over! (press r to start over)",
+ alignment_enum: 1 }
+ else
+ args.outputs.labels << { x: args.grid.w.half,
+ y: args.grid.h - 40,
+ text: "time left: #{(args.state.count_down.idiv 60) + 1}",
+ alignment_enum: 1 }
+ end
+
+ # render the score
+ args.outputs.labels << { x: args.grid.w.half,
+ y: args.grid.h - 70,
+ text: "score: #{args.state.score}",
+ alignment_enum: 1 }
+
+ # render the player with teleport count
+ args.outputs.sprites << { x: args.state.player.x,
+ y: args.state.player.y,
+ w: args.state.player.w,
+ h: args.state.player.h,
+ path: 'sprites/square-green.png' }
+
+ args.outputs.labels << { x: args.state.player.x + 10,
+ y: args.state.player.y + 40,
+ text: "teleports: #{args.state.teleports}",
+ alignment_enum: 1, size_enum: -2 }
+
+ # render the target
+ args.outputs.sprites << { x: args.state.target.x,
+ y: args.state.target.y,
+ w: args.state.target.w,
+ h: args.state.target.h,
+ path: 'sprites/square-red.png' }
+
+ # ====================================================
+ # run simulation
+ # ====================================================
+
+ # count down calculation
+ args.state.count_down -= 1
+ args.state.count_down = -1 if args.state.count_down < -1
+
+ # ====================================================
+ # process player input
+ # ====================================================
+ # if it isn't game over let them move
+ if !game_over? args
+ dir_y = 0
+ dir_x = 0
+
+ # determine the change horizontally
+ if args.inputs.keyboard.up
+ dir_y += args.state.player_speed
+ elsif args.inputs.keyboard.down
+ dir_y -= args.state.player_speed
+ end
+
+ # determine the change vertically
+ if args.inputs.keyboard.left
+ dir_x -= args.state.player_speed
+ elsif args.inputs.keyboard.right
+ dir_x += args.state.player_speed
+ end
+
+ # determine if teleport can be used
+ if args.inputs.keyboard.key_down.space && args.state.teleports > 0
+ args.state.teleports -= 1
+ dir_x *= 20
+ dir_y *= 20
+ end
+
+ # apply change to player
+ args.state.player.x += dir_x
+ args.state.player.y += dir_y
+ else
+ # if r is pressed, reset the game
+ if args.inputs.keyboard.key_down.r
+ $gtk.reset
+ return
+ end
+ end
+
+ # ====================================================
+ # determine score
+ # ====================================================
+
+ # calculate new score if the player is at goal
+ if !game_over? args
+
+ # if the player is at the goal, then move the goal
+ if args.state.player.intersect_rect? args.state.target
+ # increment the goal
+ args.state.score += 1
+
+ # move the goal to a random location
+ args.state.target = { x: (rand args.grid.w), y: (rand args.grid.h), w: 20, h: 20 }
+
+ # make sure the goal is inside the view area
+ if args.state.target.x < 0
+ args.state.target.x += 20
+ elsif args.state.target.x > 1280
+ args.state.target.x -= 20
+ end
+
+ # make sure the goal is inside the view area
+ if args.state.target.y < 0
+ args.state.target.y += 20
+ elsif args.state.target.y > 720
+ args.state.target.y -= 20
+ end
+ end
+ end
+end
+
+def game_over? args
+ args.state.count_down < 0
+end
+
+$gtk.reset
diff --git a/samples/99_genre_teenytiny/teenytiny_starting_point/license.txt b/samples/99_genre_teenytiny/teenytiny_starting_point/license.txt
new file mode 100644
index 0000000..100dcec
--- /dev/null
+++ b/samples/99_genre_teenytiny/teenytiny_starting_point/license.txt
@@ -0,0 +1,9 @@
+Copyright 2019 DragonRuby LLC
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/samples/99_genre_teenytiny/teenytiny_starting_point/sprites/square-green.png b/samples/99_genre_teenytiny/teenytiny_starting_point/sprites/square-green.png
new file mode 100644
index 0000000..5ef7f75
--- /dev/null
+++ b/samples/99_genre_teenytiny/teenytiny_starting_point/sprites/square-green.png
Binary files differ
diff --git a/samples/99_genre_teenytiny/teenytiny_starting_point/sprites/square-red.png b/samples/99_genre_teenytiny/teenytiny_starting_point/sprites/square-red.png
new file mode 100644
index 0000000..3ed5f13
--- /dev/null
+++ b/samples/99_genre_teenytiny/teenytiny_starting_point/sprites/square-red.png
Binary files differ