summaryrefslogtreecommitdiffhomepage
path: root/samples/99_genre_platformer
diff options
context:
space:
mode:
authorAmir Rajan <[email protected]>2020-09-11 02:02:01 -0500
committerAmir Rajan <[email protected]>2020-09-11 02:02:57 -0500
commit33ec37b141e896b47ed642923fd33b0c658ae9fb (patch)
treea40d3e5d41beeb06508200078f6f26b0ee57d6a4 /samples/99_genre_platformer
parent958cf43779d2bf528869e80511c4c4f2a433b2db (diff)
downloaddragonruby-game-toolkit-contrib-33ec37b141e896b47ed642923fd33b0c658ae9fb.tar.gz
dragonruby-game-toolkit-contrib-33ec37b141e896b47ed642923fd33b0c658ae9fb.zip
synced samples
Diffstat (limited to 'samples/99_genre_platformer')
-rw-r--r--samples/99_genre_platformer/clepto_frog/app/main.rb864
-rw-r--r--samples/99_genre_platformer/clepto_frog/app/map.rb1025
-rw-r--r--samples/99_genre_platformer/clepto_frog/metadata/game_metadata.txt6
-rw-r--r--samples/99_genre_platformer/clepto_frog/sprites/level-map.pngbin0 -> 389333 bytes
-rw-r--r--samples/99_genre_platformer/clepto_frog/sprites/square-black.pngbin0 -> 250 bytes
-rw-r--r--samples/99_genre_platformer/clepto_frog/sprites/square-blue.pngbin0 -> 283 bytes
-rw-r--r--samples/99_genre_platformer/clepto_frog/sprites/square-gray.pngbin0 -> 251 bytes
-rw-r--r--samples/99_genre_platformer/clepto_frog/sprites/square-green.pngbin0 -> 283 bytes
-rw-r--r--samples/99_genre_platformer/clepto_frog/sprites/square-indigo.pngbin0 -> 283 bytes
-rw-r--r--samples/99_genre_platformer/clepto_frog/sprites/square-orange.pngbin0 -> 282 bytes
-rw-r--r--samples/99_genre_platformer/clepto_frog/sprites/square-pink.pngbin0 -> 273 bytes
-rw-r--r--samples/99_genre_platformer/clepto_frog/sprites/square-red.pngbin0 -> 274 bytes
-rw-r--r--samples/99_genre_platformer/clepto_frog/sprites/square-violet.pngbin0 -> 284 bytes
-rw-r--r--samples/99_genre_platformer/clepto_frog/sprites/square-white.pngbin0 -> 279 bytes
-rw-r--r--samples/99_genre_platformer/clepto_frog/sprites/square-yellow.pngbin0 -> 286 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/CREDITS.txt3
-rw-r--r--samples/99_genre_platformer/gorillas_basic/app/main.rb373
-rw-r--r--samples/99_genre_platformer/gorillas_basic/app/repl.rb17
-rw-r--r--samples/99_genre_platformer/gorillas_basic/app/tests.rb4
-rw-r--r--samples/99_genre_platformer/gorillas_basic/app/tests/building_generation_tests.rb15
-rw-r--r--samples/99_genre_platformer/gorillas_basic/license-for-sample.txt9
-rw-r--r--samples/99_genre_platformer/gorillas_basic/metadata/game_metadata.txt6
-rw-r--r--samples/99_genre_platformer/gorillas_basic/replay.txt719
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/banana.pngbin0 -> 4771 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/explosion0.pngbin0 -> 4603 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/explosion1.pngbin0 -> 4585 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/explosion2.pngbin0 -> 4675 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/explosion3.pngbin0 -> 4724 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/explosion4.pngbin0 -> 4773 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/explosion5.pngbin0 -> 4742 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/explosion6.pngbin0 -> 4665 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/hole.pngbin0 -> 3637 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/left-0.pngbin0 -> 6352 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/left-1.pngbin0 -> 6243 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/left-2.pngbin0 -> 6339 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/left-idle.pngbin0 -> 5921 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/right-0.pngbin0 -> 6264 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/right-1.pngbin0 -> 6122 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/right-2.pngbin0 -> 6339 bytes
-rw-r--r--samples/99_genre_platformer/gorillas_basic/sprites/right-idle.pngbin0 -> 5933 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/app/main.rb887
-rw-r--r--samples/99_genre_platformer/the_little_probe/level.txt1481
-rw-r--r--samples/99_genre_platformer/the_little_probe/level_lava.txt235
-rw-r--r--samples/99_genre_platformer/the_little_probe/license-for-sample.txt9
-rw-r--r--samples/99_genre_platformer/the_little_probe/metadata/game_metadata.txt6
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0301.wavbin0 -> 387170 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0302.wavbin0 -> 387170 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0303.wavbin0 -> 387170 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0304.wavbin0 -> 387170 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0305.wavbin0 -> 518498 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0306.wavbin0 -> 387170 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0307.wavbin0 -> 387170 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0308.wavbin0 -> 387170 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0309.wavbin0 -> 387170 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0310.wavbin0 -> 472418 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0311.wavbin0 -> 341090 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0312.wavbin0 -> 341090 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0313.wavbin0 -> 341090 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0314.wavbin0 -> 603746 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0315.wavbin0 -> 472418 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0316.wavbin0 -> 472418 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0317.wavbin0 -> 472418 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0318.wavbin0 -> 472418 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0319.wavbin0 -> 472418 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0320.wavbin0 -> 472418 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/0321.wavbin0 -> 472418 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sounds/bg.oggbin0 -> 1348295 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/area_one.pngbin0 -> 851626 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/circle-black.pngbin0 -> 1882 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/circle-blue.pngbin0 -> 2901 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/circle-gray.pngbin0 -> 3006 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/circle-green.pngbin0 -> 2887 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/circle-indigo.pngbin0 -> 2433 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/circle-orange.pngbin0 -> 2670 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/circle-red.pngbin0 -> 2233 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/circle-violet.pngbin0 -> 2439 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/circle-white.pngbin0 -> 1754 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/circle-yellow.pngbin0 -> 2456 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/jupiter.pngbin0 -> 3240358 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/level.pngbin0 -> 14054321 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/probe.pngbin0 -> 93401 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/square-black.pngbin0 -> 250 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/square-blue.pngbin0 -> 283 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/square-gray.pngbin0 -> 251 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/square-green.pngbin0 -> 283 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/square-indigo.pngbin0 -> 283 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/square-orange.pngbin0 -> 282 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/square-red.pngbin0 -> 274 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/square-violet.pngbin0 -> 284 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/square-white.pngbin0 -> 279 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/square-yellow.pngbin0 -> 286 bytes
-rw-r--r--samples/99_genre_platformer/the_little_probe/sprites/whisp.pngbin0 -> 241 bytes
92 files changed, 5659 insertions, 0 deletions
diff --git a/samples/99_genre_platformer/clepto_frog/app/main.rb b/samples/99_genre_platformer/clepto_frog/app/main.rb
new file mode 100644
index 0000000..a4eb069
--- /dev/null
+++ b/samples/99_genre_platformer/clepto_frog/app/main.rb
@@ -0,0 +1,864 @@
+MAP_FILE_PATH = 'app/map.txt'
+
+require 'app/map.rb'
+
+class CleptoFrog
+ attr_gtk
+
+ def render_ending
+ state.game_over_at ||= state.tick_count
+
+ outputs.labels << [640, 700, "Clepto Frog", 4, 1]
+
+ if state.tick_count >= (state.game_over_at + 120)
+ outputs.labels << [640, 620, "\"I... I.... don't believe it.\" - New Guy",
+ 4, 1, 0, 0, 0, 255 * (state.game_over_at + 120).ease(60)]
+ end
+
+ if state.tick_count >= (state.game_over_at + 240)
+ outputs.labels << [640, 580, "\"He actually stole all the mugs?\" - New Guy",
+ 4, 1, 0, 0, 0, 255 * (state.game_over_at + 240).ease(60)]
+ end
+
+ if state.tick_count >= (state.game_over_at + 360)
+ outputs.labels << [640, 540, "\"Kind of feel bad STARTING HIM WITH NOTHING again.\" - New Guy",
+ 4, 1, 0, 0, 0, 255 * (state.game_over_at + 360).ease(60)]
+ end
+
+ outputs.sprites << [640 - 50, 360 - 50, 100, 100,
+ "sprites/square-green.png"]
+
+ outputs.labels << [640, 300, "Current Time: #{"%.2f" % state.stuff_time}", 4, 1]
+ outputs.labels << [640, 270, "Best Time: #{"%.2f" % state.stuff_best_time}", 4, 1]
+
+ if state.tick_count >= (state.game_over_at + 550)
+ restart_game
+ end
+ end
+
+ def restart_game
+ state.world = nil
+ state.x = nil
+ state.y = nil
+ state.dx = nil
+ state.dy = nil
+ state.stuff_score = 0
+ state.stuff_time = 0
+ state.intro_tick_count = nil
+ defaults
+ state.game_start_at = state.tick_count
+ state.scene = :game
+ state.game_over_at = nil
+ end
+
+ 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
+ state.scene = :game
+ state.game_start_at = state.tick_count
+ end
+ end
+
+ def tick
+ defaults
+ if state.scene == :intro && state.tick_count <= 800
+ render_intro
+ elsif state.scene == :ending
+ render_ending
+ else
+ render
+ end
+ calc
+ process_inputs
+ end
+
+ def defaults
+ state.scene ||= :intro
+ state.stuff_score ||= 0
+ state.stuff_time ||= 0
+ state.stuff_best_time ||= nil
+ state.camera_x ||= 0
+ state.camera_y ||= 0
+ state.target_camera_scale ||= 1
+ state.camera_scale ||= 1
+ state.tongue_length ||= 100
+ state.dev_action ||= :collision_mode
+ state.action ||= :aiming
+ state.tongue_angle ||= 90
+ state.tile_size = 64
+ state.gravity = -0.1
+ state.air = -0.01
+ state.player_width = 60
+ state.player_height = 60
+ state.collision_tolerance = 0.0
+ state.previous_tile_size ||= state.tile_size
+ state.x ||= 2400
+ state.y ||= 200
+ state.dy ||= 0
+ state.dx ||= 0
+ attempt_load_world_from_file
+ state.world_lookup ||= { }
+ state.world_collision_rects ||= []
+ state.mode ||= :creating
+ state.select_menu ||= [0, 720, 1280, 720]
+ state.sprite_quantity ||= 20
+ state.sprite_coords ||= []
+ state.banner_coords ||= [640, 680 + 720]
+ state.sprite_selected ||= 1
+ state.map_saved_at ||= 0
+ state.intro_tick_count ||= state.tick_count
+ if state.sprite_coords == []
+ count = 1
+ temp_x = 165
+ temp_y = 500 + 720
+ state.sprite_quantity.times do
+ state.sprite_coords += [[temp_x, temp_y, count]]
+ temp_x += 100
+ count += 1
+ if temp_x > 1280 - (165 + 50)
+ temp_x = 165
+ temp_y -= 75
+ end
+ end
+ end
+ end
+
+ def start_of_tongue x = nil, y = nil
+ x ||= state.x
+ y ||= state.y
+ [
+ x + state.player_width.half,
+ y + state.player_height.half
+ ]
+ end
+
+ def stage_definition
+ outputs.sprites << [vx(0), vy(0), vw(10000), vw(5875), 'sprites/level-map.png']
+ end
+
+ def render
+ stage_definition
+ start_of_tongue_render = [vx(start_of_tongue.x), vy(start_of_tongue.y)]
+ end_of_tongue_render = [vx(end_of_tongue.x), vy(end_of_tongue.y)]
+
+ if state.anchor_point
+ anchor_point_render = [vx(state.anchor_point.x), vy(state.anchor_point.y)]
+ outputs.sprites << { x: start_of_tongue_render.x,
+ y: start_of_tongue_render.y,
+ w: vw(2),
+ h: args.geometry.distance(start_of_tongue_render, anchor_point_render),
+ path: 'sprites/square-pink.png',
+ angle_anchor_y: 0,
+ angle: state.tongue_angle - 90 }
+ else
+ outputs.sprites << { x: vx(start_of_tongue.x),
+ y: vy(start_of_tongue.y),
+ w: vw(2),
+ h: vh(state.tongue_length),
+ path: 'sprites/square-pink.png',
+ angle_anchor_y: 0,
+ angle: state.tongue_angle - 90 }
+ end
+
+ outputs.sprites << state.objects.map { |o| [vx(o.x), vy(o.y), vw(o.w), vh(o.h), o.path] }
+
+ if state.god_mode
+ # SHOW HIDE COLLISIONS
+ outputs.sprites << state.world.map do |x, y, w, h|
+ x = vx(x)
+ y = vy(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),
+ path: 'sprites/square-gray.png',
+ a: 128
+ }
+ end
+ end
+ end
+
+ render_player
+ outputs.sprites << [vx(2315), vy(45), vw(569), vh(402), 'sprites/square-blue.png', 0, 40]
+
+ # Label in top left of the screen
+ outputs.primitives << [20, 640, 180, 70, 255, 255, 255, 128].solid
+ outputs.primitives << [30, 700, "Stuff: #{state.stuff_score} of #{$mugs.count}", 1].label
+ outputs.primitives << [30, 670, "Time: #{"%.2f" % state.stuff_time}", 1].label
+
+ if state.god_mode
+ if state.map_saved_at > 0 && state.map_saved_at.elapsed_time < 120
+ outputs.primitives << [920, 670, 'Map has been exported!', 1, 0, 50, 100, 50].label
+ end
+
+
+ # 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
+ end
+
+ render_mini_map
+ outputs.primitives << [0, 0, 1280, 720, 255, 255, 255, 255 * state.game_start_at.ease(60, :flip)].solid
+ end
+
+ def render_mini_map
+ x, y = 1170, 10
+ outputs.primitives << [x, y, 100, 58, 0, 0, 0, 200].solid
+ outputs.primitives << [x + args.state.x.fdiv(100) - 1, y + args.state.y.fdiv(100) - 1, 2, 2, 0, 255, 0].solid
+ t_start = start_of_tongue
+ t_end = end_of_tongue
+ outputs.primitives << [
+ x + t_start.x.fdiv(100), y + t_start.y.fdiv(100),
+ x + t_end.x.fdiv(100), y + t_end.y.fdiv(100),
+ 255, 255, 255
+ ].line
+
+ state.objects.each do |o|
+ outputs.primitives << [x + o.x.fdiv(100) - 1, y + o.y.fdiv(100) - 1, 2, 2, 200, 200, 0].solid
+ end
+ end
+
+ def calc_camera percentage_override = nil
+ percentage = percentage_override || (0.2 * state.camera_scale)
+ target_scale = state.target_camera_scale
+ distance_scale = target_scale - state.camera_scale
+ state.camera_scale += distance_scale * percentage
+
+ target_x = state.x * state.target_camera_scale
+ target_y = state.y * state.target_camera_scale
+
+ distance_x = target_x - (state.camera_x + 640)
+ distance_y = target_y - (state.camera_y + 360)
+ state.camera_x += distance_x * percentage if distance_x.abs > 1
+ state.camera_y += distance_y * percentage if distance_y.abs > 1
+ state.camera_x = 0 if state.camera_x < 0
+ state.camera_y = 0 if state.camera_y < 0
+ end
+
+ def vx x
+ (x * state.camera_scale) - state.camera_x
+ end
+
+ def vy y
+ (y * state.camera_scale) - state.camera_y
+ end
+
+ def vw w
+ w * state.camera_scale
+ end
+
+ def vh h
+ h * state.camera_scale
+ end
+
+ def calc
+ calc_camera
+ calc_world_lookup
+ calc_player
+ calc_on_floor
+ calc_score
+ end
+
+ def set_camera_scale v = nil
+ return if v < 0.1
+ state.target_camera_scale = v
+ end
+
+ def process_inputs_god_mode
+ return unless state.god_mode
+
+ if inputs.keyboard.key_down.equal_sign || (inputs.keyboard.equal_sign && state.tick_count.mod_zero?(10))
+ set_camera_scale state.camera_scale + 0.1
+ elsif inputs.keyboard.key_down.hyphen || (inputs.keyboard.hyphen && state.tick_count.mod_zero?(10))
+ set_camera_scale state.camera_scale - 0.1
+ elsif inputs.keyboard.eight || inputs.keyboard.zero
+ set_camera_scale 1
+ end
+
+ if input_up?
+ state.y += 10
+ state.dy = 0
+ elsif input_down?
+ state.y -= 10
+ state.dy = 0
+ end
+
+ if input_left?
+ state.x -= 10
+ state.dx = 0
+ elsif input_right?
+ state.x += 10
+ state.dx = 0
+ end
+ end
+
+ def process_inputs
+ 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
+
+ def input_up?
+ inputs.keyboard.w || inputs.keyboard.up || inputs.keyboard.k
+ end
+
+ def input_up_released?
+ inputs.keyboard.key_up.w ||
+ inputs.keyboard.key_up.up ||
+ inputs.keyboard.key_up.k
+ end
+
+ def input_down?
+ inputs.keyboard.s || inputs.keyboard.down || inputs.keyboard.j
+ end
+
+ def input_down_released?
+ inputs.keyboard.key_up.s ||
+ inputs.keyboard.key_up.down ||
+ inputs.keyboard.key_up.j
+ end
+
+ def input_left?
+ inputs.keyboard.a || inputs.keyboard.left || inputs.keyboard.h
+ end
+
+ def input_right?
+ inputs.keyboard.d || inputs.keyboard.right || inputs.keyboard.l
+ end
+
+ def set_object path, w, h
+ state.object = path
+ state.object_w = w
+ state.object_h = h
+ end
+
+ def collision_mode
+ state.dev_action = :collision_mode
+ end
+
+ def process_inputs_player_movement
+ if inputs.keyboard.key_down.g
+ state.god_mode = !state.god_mode
+ puts state.god_mode
+ end
+
+ if inputs.keyboard.key_down.u && state.dev_action == :collision_mode
+ state.world = state.world[0..-2]
+ state.world_lookup = {}
+ end
+
+ if inputs.keyboard.key_down.space && !state.anchor_point
+ state.tongue_length = 0
+ state.action = :shooting
+ outputs.sounds << 'sounds/shooting.wav'
+ elsif inputs.keyboard.key_down.space
+ state.action = :aiming
+ state.anchor_point = nil
+ state.tongue_length = 100
+ end
+
+ if state.anchor_point
+ if input_up?
+ if state.tongue_length >= 105
+ state.tongue_length -= 5
+ state.dy += 0.8
+ end
+ elsif input_down?
+ state.tongue_length += 5
+ state.dy -= 0.8
+ end
+
+ if input_left? && state.dx > 1
+ state.dx *= 0.98
+ elsif input_left? && state.dx < -1
+ state.dx *= 1.03
+ elsif input_left? && !state.on_floor
+ state.dx -= 3
+ elsif input_right? && state.dx > 1
+ state.dx *= 1.03
+ elsif input_right? && state.dx < -1
+ state.dx *= 0.98
+ elsif input_right? && !state.on_floor
+ state.dx += 3
+ end
+ else
+ if input_left?
+ state.tongue_angle += 1.5
+ state.tongue_angle = state.tongue_angle
+ elsif input_right?
+ state.tongue_angle -= 1.5
+ state.tongue_angle = state.tongue_angle
+ end
+ 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)
+ state.world = []
+ state.objects = []
+
+ if $collisions
+ $collisions.map do |x, y, w, h|
+ state.world << [x, y, w, 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
+ $mugs.map do |x, y, w, h, path|
+ state.objects << [x, y, w, h, path]
+ end
+ end
+ end
+
+ def calc_world_lookup
+ if state.tile_size != state.previous_tile_size
+ state.previous_tile_size = state.tile_size
+ state.world_lookup = {}
+ end
+
+ return if state.world_lookup.keys.length > 0
+ return unless state.world.length > 0
+
+ # 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
+ end
+
+ # Assigns collision rects for every sprite drawn
+ state.world_collision_rects =
+ state.world_lookup
+ .keys
+ .map do |x, y, w, h|
+ s = state.tile_size
+ w ||= s
+ 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],
+ }
+ end
+
+ end
+
+ def calc_pendulum
+ return if !state.anchor_point
+ target_x = state.anchor_point.x - start_of_tongue.x
+ target_y = state.anchor_point.y -
+ state.tongue_length - 5 - 20 - state.player_height
+
+ diff_y = state.y - target_y
+
+ if target_x > 0
+ state.dx += 0.6
+ elsif target_x < 0
+ state.dx -= 0.6
+ end
+
+ if diff_y > 0
+ state.dy -= 0.1
+ elsif diff_y < 0
+ state.dy += 0.1
+ end
+
+ state.dx *= 0.99
+
+ if state.dy.abs < 2
+ state.dy *= 0.8
+ else
+ state.dy *= 0.90
+ end
+
+ if state.tongue_length && state.y
+ state.dy += state.tongue_angle.vector_y state.tongue_length.fdiv(1000)
+ end
+ end
+
+ def calc_tongue_angle
+ return unless state.anchor_point
+ state.tongue_angle = args.geometry.angle_from state.anchor_point, start_of_tongue
+ state.tongue_length = args.geometry.distance(start_of_tongue, state.anchor_point)
+ state.tongue_length = state.tongue_length.greater(100)
+ end
+
+ def player_from_end_of_tongue
+ p = state.tongue_angle.vector(state.tongue_length)
+ derived_start = [state.anchor_point.x - p.x, state.anchor_point.y - p.y]
+ derived_start.x -= state.player_width.half
+ derived_start.y -= state.player_height.half
+ derived_start
+ end
+
+ def end_of_tongue
+ p = state.tongue_angle.vector(state.tongue_length)
+ [start_of_tongue.x + p.x, start_of_tongue.y + p.y]
+ end
+
+ def calc_shooting
+ return unless state.action == :shooting
+ state.tongue_length += 30
+ potential_anchor = end_of_tongue
+ if potential_anchor.x <= 0
+ state.anchor_point = potential_anchor
+ state.action = :anchored
+ outputs.sounds << 'sounds/attached.wav'
+ elsif potential_anchor.x >= 10000
+ state.anchor_point = potential_anchor
+ state.action = :anchored
+ outputs.sounds << 'sounds/attached.wav'
+ elsif potential_anchor.y <= 0
+ state.anchor_point = potential_anchor
+ state.action = :anchored
+ outputs.sounds << 'sounds/attached.wav'
+ elsif potential_anchor.y >= 5875
+ state.anchor_point = potential_anchor
+ state.action = :anchored
+ outputs.sounds << 'sounds/attached.wav'
+ else
+ anchor_rect = [potential_anchor.x - 5, potential_anchor.y - 5, 10, 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)
+ end.first
+ if collision
+ state.anchor_point = potential_anchor
+ state.action = :anchored
+ outputs.sounds << 'sounds/attached.wav'
+ end
+ end
+ end
+
+ def calc_player
+ calc_shooting
+ if !state.god_mode
+ state.dy += state.gravity # Since acceleration is the change in velocity, the change in y (dy) increases every frame
+ state.dx += state.dx * state.air
+ end
+ calc_pendulum
+ calc_box_collision
+ calc_edge_collision
+ if !state.god_mode
+ state.y += state.dy
+ state.x += state.dx
+ end
+ calc_tongue_angle
+ end
+
+ def calc_box_collision
+ return unless state.world_lookup.keys.length > 0
+ collision_floor
+ collision_left
+ collision_right
+ collision_ceiling
+ end
+
+ def calc_edge_collision
+ # Ensures that player doesn't fall below the map
+ if next_y < 0 && state.dy < 0
+ state.y = 0
+ state.dy = state.dy.abs * 0.8
+ state.collision_on_y = true
+ # Ensures player doesn't go insanely high
+ elsif next_y > 5875 - state.tile_size && state.dy > 0
+ state.y = 5875 - state.tile_size
+ state.dy = state.dy.abs * 0.8 * -1
+ state.collision_on_y = true
+ end
+
+ # Ensures that player remains in the horizontal range its supposed to
+ if state.x >= 10000 - state.tile_size && state.dx > 0
+ state.x = 10000 - state.tile_size
+ state.dx = state.dx.abs * 0.8 * -1
+ state.collision_on_x = true
+ elsif state.x <= 0 && state.dx < 0
+ state.x = 0
+ state.dx = state.dx.abs * 0.8
+ state.collision_on_x = true
+ end
+ end
+
+ def next_y
+ state.y + state.dy
+ end
+
+ def next_x
+ if state.dx < 0
+ return (state.x + state.dx) - (state.tile_size - state.player_width)
+ else
+ return (state.x + state.dx) + (state.tile_size - state.player_width)
+ end
+ end
+
+ def collision_floor
+ return unless state.dy <= 0
+
+ player_rect = [state.x, next_y, state.tile_size, state.tile_size]
+
+ # Runs through all the sprites on the field and determines if the player hits the bottom of sprite (hence "-0.1" above)
+ floor_collisions = state.world_collision_rects
+ .find_all { |r| r[:top].intersect_rect?(player_rect, state.collision_tolerance) }
+ .first
+
+ return unless floor_collisions
+ state.y = floor_collisions[:top].top
+ state.dy = state.dy.abs * 0.8
+ end
+
+ def collision_left
+ return unless state.dx < 0
+ player_rect = [next_x, state.y, state.tile_size, state.tile_size]
+
+ # Runs through all the sprites on the field and determines if the player hits the left side of sprite (hence "-0.1" above)
+ left_side_collisions = state.world_collision_rects
+ .find_all { |r| r[:left_right].intersect_rect?(player_rect, state.collision_tolerance) }
+ .first
+
+ return unless left_side_collisions
+ state.x = left_side_collisions[:left_right].right
+ state.dx = state.dy.abs * 0.8
+ state.collision_on_x = true
+ end
+
+ def collision_right
+ return unless state.dx > 0
+
+ player_rect = [next_x, state.y, state.tile_size, state.tile_size]
+ # Runs through all the sprites on the field and determines if the player hits the right side of sprite (hence "-0.1" above)
+ right_side_collisions = state.world_collision_rects
+ .find_all { |r| r[:left_right].intersect_rect?(player_rect, state.collision_tolerance) }
+ .first
+
+ return unless right_side_collisions
+ state.x = right_side_collisions[:left_right].left - state.tile_size
+ state.dx = state.dx.abs * 0.8 * -1
+ state.collision_on_x = true
+ end
+
+ def collision_ceiling
+ return unless state.dy > 0
+
+ player_rect = [state.x, next_y, state.player_width, state.player_height]
+
+ # Runs through all the sprites on the field and determines if the player hits the ceiling of sprite (hence "+0.1" above)
+ ceil_collisions = state.world_collision_rects
+ .find_all { |r| r[:bottom].intersect_rect?(player_rect, state.collision_tolerance) }
+ .first
+
+ return unless ceil_collisions
+ state.y = ceil_collisions[:bottom].y - state.tile_size
+ state.dy = state.dy.abs * 0.8 * -1
+ state.collision_on_y = true
+ end
+
+ def to_coord point
+ # Integer divides (idiv) point.x to turn into grid
+ # Then, you can just multiply each integer by state.tile_size
+ # later and huzzah. Grid coordinates
+ [point.x.idiv(state.tile_size), point.y.idiv(state.tile_size)]
+ end
+
+ def export_map
+ export_string = state.world.map do |x, y|
+ "#{x},#{y},1"
+ end
+ 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"))
+ state.map_saved_at = state.tick_count
+ end
+
+ def inputs_export_stage
+ end
+
+ def calc_score
+ return unless state.scene == :game
+ player = [state.x, state.y, state.player_width, state.player_height]
+ collected = state.objects.find_all { |s| s.intersect_rect? player }
+ state.stuff_score += collected.length
+ if collected.length > 0
+ outputs.sounds << 'sounds/collectable.wav'
+ end
+ state.objects = state.objects.reject { |s| collected.include? s }
+ state.stuff_time += 0.01
+ if state.objects.length == 0
+ if !state.stuff_best_time || state.stuff_time < state.stuff_best_time
+ state.stuff_best_time = state.stuff_time
+ end
+ state.game_over_at = nil
+ state.scene = :ending
+ end
+ end
+
+ def calc_on_floor
+ if state.action == :anchored
+ state.on_floor = false
+ state.on_floor_debounce = 30
+ else
+ state.on_floor_debounce ||= 30
+
+ if state.dy.round != 0
+ state.on_floor_debounce = 30
+ state.on_floor = false
+ else
+ state.on_floor_debounce -= 1
+ end
+
+ if state.on_floor_debounce <= 0
+ state.on_floor_debounce = 0
+ state.on_floor = true
+ end
+ end
+ end
+
+ def render_player
+ path = "sprites/square-green.png"
+ angle = 0
+ # outputs.labels << [vx(state.x), vy(state.y) - 30, "dy: #{state.dy.round}"]
+ if state.action == :idle
+ # outputs.labels << [vx(state.x), vy(state.y), "IDLE"]
+ path = "sprites/square-green.png"
+ elsif state.action == :aiming && !state.on_floor
+ # outputs.labels << [vx(state.x), vy(state.y), "AIMING AIR BORN"]
+ angle = state.tongue_angle - 90
+ path = "sprites/square-green.png"
+ elsif state.action == :aiming # ON THE GROUND
+ # outputs.labels << [vx(state.x), vy(state.y), "AIMING GROUND"]
+ path = "sprites/square-green.png"
+ elsif state.action == :shooting && !state.on_floor
+ # outputs.labels << [vx(state.x), vy(state.y), "SHOOTING AIR BORN"]
+ path = "sprites/square-green.png"
+ angle = state.tongue_angle - 90
+ elsif state.action == :shooting
+ # outputs.labels << [vx(state.x), vy(state.y), "SHOOTING ON GROUND"]
+ path = "sprites/square-green.png"
+ elsif state.action == :anchored
+ # outputs.labels << [vx(state.x), vy(state.y), "SWINGING"]
+ angle = state.tongue_angle - 90
+ path = "sprites/square-green.png"
+ end
+
+ outputs.sprites << [vx(state.x),
+ vy(state.y),
+ vw(state.player_width),
+ vh(state.player_height),
+ path,
+ angle]
+ end
+
+ def render_player_old
+ # Player
+ if state.action == :aiming
+ path = 'sprites\frg\idle\frog_idle.png'
+ if state.dx > 2
+ #directional right sprite was here but i needa redo it
+ path = 'sprites\frg\anchor\frog-anchor-0.png'
+ #directional left sprite was here but i needa redo it
+ elsif state.dx < -2
+ path = 'sprites\frg\anchor\frog-anchor-0.png'
+ end
+ outputs.sprites << [vx(state.x),
+ vy(state.y),
+ vw(state.player_width),
+ vh(state.player_height),
+ path,
+ (state.tongue_angle - 90)]
+ elsif state.action == :anchored || state.action == :shooting
+ outputs.sprites << [vx(state.x),
+ vy(state.y),
+ vw(state.player_width),
+ vw(state.player_height),
+ 'sprites/animations_povfrog/frog_bwah_up.png',
+ (state.tongue_angle - 90)]
+ end
+ end
+end
+
+
+$game = CleptoFrog.new
+
+def tick args
+ if args.state.scene == :game
+ tick_instructions args, "SPACE to SHOOT and RELEASE tongue. LEFT, RIGHT to SWING and BUILD momentum. MINIMAP in bottom right corner.", 360
+ end
+ $game.args = args
+ $game.tick
+end
+
+def tick_instructions args, text, y = 715
+ return if args.state.key_event_occurred
+ if args.inputs.keyboard.directional_vector || args.inputs.keyboard.key_down.space
+ 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, "(SPACE to dismiss instructions)" , -2, 1, 255, 255, 255].label
+end
diff --git a/samples/99_genre_platformer/clepto_frog/app/map.rb b/samples/99_genre_platformer/clepto_frog/app/map.rb
new file mode 100644
index 0000000..c048c82
--- /dev/null
+++ b/samples/99_genre_platformer/clepto_frog/app/map.rb
@@ -0,0 +1,1025 @@
+$collisions = [
+ [326, 463, 64, 64],
+ [274, 462, 64, 64],
+ [326, 413, 64, 64],
+ [275, 412, 64, 64],
+ [124, 651, 64, 64],
+ [72, 651, 64, 64],
+ [124, 600, 64, 64],
+ [69, 599, 64, 64],
+ [501, 997, 64, 64],
+ [476, 995, 64, 64],
+ [3224, 2057, 64, 64],
+ [3224, 1994, 64, 64],
+ [3225, 1932, 64, 64],
+ [3225, 1870, 64, 64],
+ [3226, 1806, 64, 64],
+ [3224, 1744, 64, 64],
+ [3225, 1689, 64, 64],
+ [3226, 1660, 64, 64],
+ [3161, 1658, 64, 64],
+ [3097, 1660, 64, 64],
+ [3033, 1658, 64, 64],
+ [2969, 1658, 64, 64],
+ [2904, 1658, 64, 64],
+ [2839, 1657, 64, 64],
+ [2773, 1657, 64, 64],
+ [2709, 1658, 64, 64],
+ [2643, 1657, 64, 64],
+ [2577, 1657, 64, 64],
+ [2509, 1658, 64, 64],
+ [2440, 1658, 64, 64],
+ [2371, 1658, 64, 64],
+ [2301, 1659, 64, 64],
+ [2230, 1659, 64, 64],
+ [2159, 1659, 64, 64],
+ [2092, 1660, 64, 64],
+ [2025, 1661, 64, 64],
+ [1958, 1660, 64, 64],
+ [1888, 1659, 64, 64],
+ [1817, 1657, 64, 64],
+ [1745, 1656, 64, 64],
+ [1673, 1658, 64, 64],
+ [1605, 1660, 64, 64],
+ [1536, 1658, 64, 64],
+ [1465, 1660, 64, 64],
+ [1386, 1960, 64, 64],
+ [1384, 1908, 64, 64],
+ [1387, 1862, 64, 64],
+ [1326, 1863, 64, 64],
+ [1302, 1862, 64, 64],
+ [1119, 1906, 64, 64],
+ [1057, 1905, 64, 64],
+ [994, 1905, 64, 64],
+ [937, 1904, 64, 64],
+ [896, 1904, 64, 64],
+ [1001, 1845, 64, 64],
+ [1003, 1780, 64, 64],
+ [1003, 1718, 64, 64],
+ [692, 1958, 64, 64],
+ [691, 1900, 64, 64],
+ [774, 1861, 64, 64],
+ [712, 1861, 64, 64],
+ [691, 1863, 64, 64],
+ [325, 2133, 64, 64],
+ [275, 2134, 64, 64],
+ [326, 2082, 64, 64],
+ [275, 2082, 64, 64],
+ [124, 2321, 64, 64],
+ [71, 2320, 64, 64],
+ [123, 2267, 64, 64],
+ [71, 2268, 64, 64],
+ [2354, 1859, 64, 64],
+ [2292, 1859, 64, 64],
+ [2231, 1857, 64, 64],
+ [2198, 1858, 64, 64],
+ [2353, 1802, 64, 64],
+ [2296, 1798, 64, 64],
+ [2233, 1797, 64, 64],
+ [2200, 1797, 64, 64],
+ [2352, 1742, 64, 64],
+ [2288, 1741, 64, 64],
+ [2230, 1743, 64, 64],
+ [2196, 1743, 64, 64],
+ [1736, 460, 64, 64],
+ [1735, 400, 64, 64],
+ [1736, 339, 64, 64],
+ [1736, 275, 64, 64],
+ [1738, 210, 64, 64],
+ [1735, 145, 64, 64],
+ [1735, 87, 64, 64],
+ [1736, 51, 64, 64],
+ [539, 289, 64, 64],
+ [541, 228, 64, 64],
+ [626, 191, 64, 64],
+ [572, 192, 64, 64],
+ [540, 193, 64, 64],
+ [965, 233, 64, 64],
+ [904, 234, 64, 64],
+ [840, 234, 64, 64],
+ [779, 234, 64, 64],
+ [745, 236, 64, 64],
+ [851, 169, 64, 64],
+ [849, 108, 64, 64],
+ [852, 50, 64, 64],
+ [1237, 289, 64, 64],
+ [1236, 228, 64, 64],
+ [1238, 197, 64, 64],
+ [1181, 192, 64, 64],
+ [1152, 192, 64, 64],
+ [1443, 605, 64, 64],
+ [1419, 606, 64, 64],
+ [1069, 925, 64, 64],
+ [1068, 902, 64, 64],
+ [1024, 927, 64, 64],
+ [1017, 897, 64, 64],
+ [963, 926, 64, 64],
+ [958, 898, 64, 64],
+ [911, 928, 64, 64],
+ [911, 896, 64, 64],
+ [2132, 803, 64, 64],
+ [2081, 803, 64, 64],
+ [2131, 752, 64, 64],
+ [2077, 751, 64, 64],
+ [2615, 649, 64, 64],
+ [2564, 651, 64, 64],
+ [2533, 650, 64, 64],
+ [2027, 156, 64, 64],
+ [1968, 155, 64, 64],
+ [1907, 153, 64, 64],
+ [1873, 155, 64, 64],
+ [2025, 95, 64, 64],
+ [1953, 98, 64, 64],
+ [1894, 100, 64, 64],
+ [1870, 100, 64, 64],
+ [2029, 45, 64, 64],
+ [1971, 48, 64, 64],
+ [1915, 47, 64, 64],
+ [1873, 47, 64, 64],
+ [3956, 288, 64, 64],
+ [3954, 234, 64, 64],
+ [4042, 190, 64, 64],
+ [3990, 190, 64, 64],
+ [3958, 195, 64, 64],
+ [3422, 709, 64, 64],
+ [3425, 686, 64, 64],
+ [3368, 709, 64, 64],
+ [3364, 683, 64, 64],
+ [3312, 711, 64, 64],
+ [3307, 684, 64, 64],
+ [3266, 712, 64, 64],
+ [3269, 681, 64, 64],
+ [4384, 236, 64, 64],
+ [4320, 234, 64, 64],
+ [4257, 235, 64, 64],
+ [4192, 234, 64, 64],
+ [4162, 234, 64, 64],
+ [4269, 171, 64, 64],
+ [4267, 111, 64, 64],
+ [4266, 52, 64, 64],
+ [4580, 458, 64, 64],
+ [4582, 396, 64, 64],
+ [4582, 335, 64, 64],
+ [4581, 275, 64, 64],
+ [4581, 215, 64, 64],
+ [4581, 152, 64, 64],
+ [4582, 89, 64, 64],
+ [4583, 51, 64, 64],
+ [4810, 289, 64, 64],
+ [4810, 227, 64, 64],
+ [4895, 189, 64, 64],
+ [4844, 191, 64, 64],
+ [4809, 191, 64, 64],
+ [5235, 233, 64, 64],
+ [5176, 232, 64, 64],
+ [5118, 230, 64, 64],
+ [5060, 232, 64, 64],
+ [5015, 237, 64, 64],
+ [5123, 171, 64, 64],
+ [5123, 114, 64, 64],
+ [5121, 51, 64, 64],
+ [5523, 461, 64, 64],
+ [5123, 42, 64, 64],
+ [5525, 401, 64, 64],
+ [5525, 340, 64, 64],
+ [5526, 273, 64, 64],
+ [5527, 211, 64, 64],
+ [5525, 150, 64, 64],
+ [5527, 84, 64, 64],
+ [5524, 44, 64, 64],
+ [5861, 288, 64, 64],
+ [5861, 229, 64, 64],
+ [5945, 193, 64, 64],
+ [5904, 193, 64, 64],
+ [5856, 194, 64, 64],
+ [6542, 234, 64, 64],
+ [6478, 235, 64, 64],
+ [6413, 238, 64, 64],
+ [6348, 235, 64, 64],
+ [6285, 236, 64, 64],
+ [6222, 235, 64, 64],
+ [6160, 235, 64, 64],
+ [6097, 236, 64, 64],
+ [6069, 237, 64, 64],
+ [6321, 174, 64, 64],
+ [6318, 111, 64, 64],
+ [6320, 49, 64, 64],
+ [6753, 291, 64, 64],
+ [6752, 227, 64, 64],
+ [6753, 192, 64, 64],
+ [6692, 191, 64, 64],
+ [6668, 193, 64, 64],
+ [6336, 604, 64, 64],
+ [6309, 603, 64, 64],
+ [7264, 461, 64, 64],
+ [7264, 395, 64, 64],
+ [7264, 333, 64, 64],
+ [7264, 270, 64, 64],
+ [7265, 207, 64, 64],
+ [7266, 138, 64, 64],
+ [7264, 78, 64, 64],
+ [7266, 48, 64, 64],
+ [7582, 149, 64, 64],
+ [7524, 147, 64, 64],
+ [7461, 146, 64, 64],
+ [7425, 148, 64, 64],
+ [7580, 86, 64, 64],
+ [7582, 41, 64, 64],
+ [7519, 41, 64, 64],
+ [7460, 40, 64, 64],
+ [7427, 96, 64, 64],
+ [7427, 41, 64, 64],
+ [8060, 288, 64, 64],
+ [8059, 226, 64, 64],
+ [8145, 194, 64, 64],
+ [8081, 194, 64, 64],
+ [8058, 195, 64, 64],
+ [8485, 234, 64, 64],
+ [8422, 235, 64, 64],
+ [8360, 235, 64, 64],
+ [8296, 235, 64, 64],
+ [8266, 237, 64, 64],
+ [8371, 173, 64, 64],
+ [8370, 117, 64, 64],
+ [8372, 59, 64, 64],
+ [8372, 51, 64, 64],
+ [9147, 192, 64, 64],
+ [9063, 287, 64, 64],
+ [9064, 225, 64, 64],
+ [9085, 193, 64, 64],
+ [9063, 194, 64, 64],
+ [9492, 234, 64, 64],
+ [9428, 234, 64, 64],
+ [9365, 235, 64, 64],
+ [9302, 235, 64, 64],
+ [9270, 237, 64, 64],
+ [9374, 172, 64, 64],
+ [9376, 109, 64, 64],
+ [9377, 48, 64, 64],
+ [9545, 1060, 64, 64],
+ [9482, 1062, 64, 64],
+ [9423, 1062, 64, 64],
+ [9387, 1062, 64, 64],
+ [9541, 999, 64, 64],
+ [9542, 953, 64, 64],
+ [9478, 953, 64, 64],
+ [9388, 999, 64, 64],
+ [9414, 953, 64, 64],
+ [9389, 953, 64, 64],
+ [9294, 1194, 64, 64],
+ [9245, 1195, 64, 64],
+ [9297, 1143, 64, 64],
+ [9245, 1144, 64, 64],
+ [5575, 1781, 64, 64],
+ [5574, 1753, 64, 64],
+ [5522, 1782, 64, 64],
+ [5518, 1753, 64, 64],
+ [5472, 1783, 64, 64],
+ [5471, 1751, 64, 64],
+ [5419, 1781, 64, 64],
+ [5421, 1749, 64, 64],
+ [500, 3207, 64, 64],
+ [477, 3205, 64, 64],
+ [1282, 3214, 64, 64],
+ [1221, 3214, 64, 64],
+ [1188, 3215, 64, 64],
+ [1345, 3103, 64, 64],
+ [1288, 3103, 64, 64],
+ [1231, 3104, 64, 64],
+ [1190, 3153, 64, 64],
+ [1189, 3105, 64, 64],
+ [2255, 3508, 64, 64],
+ [2206, 3510, 64, 64],
+ [2254, 3458, 64, 64],
+ [2202, 3458, 64, 64],
+ [2754, 2930, 64, 64],
+ [2726, 2932, 64, 64],
+ [3408, 2874, 64, 64],
+ [3407, 2849, 64, 64],
+ [3345, 2872, 64, 64],
+ [3342, 2847, 64, 64],
+ [3284, 2874, 64, 64],
+ [3284, 2848, 64, 64],
+ [3248, 2878, 64, 64],
+ [3252, 2848, 64, 64],
+ [3953, 3274, 64, 64],
+ [3899, 3277, 64, 64],
+ [3951, 3222, 64, 64],
+ [3900, 3222, 64, 64],
+ [4310, 2968, 64, 64],
+ [4246, 2969, 64, 64],
+ [4183, 2965, 64, 64],
+ [4153, 2967, 64, 64],
+ [4311, 2910, 64, 64],
+ [4308, 2856, 64, 64],
+ [4251, 2855, 64, 64],
+ [4197, 2857, 64, 64],
+ [5466, 3184, 64, 64],
+ [5466, 3158, 64, 64],
+ [5404, 3184, 64, 64],
+ [5404, 3156, 64, 64],
+ [5343, 3185, 64, 64],
+ [5342, 3156, 64, 64],
+ [5308, 3185, 64, 64],
+ [5307, 3154, 64, 64],
+ [6163, 2950, 64, 64],
+ [6111, 2952, 64, 64],
+ [6164, 2898, 64, 64],
+ [6113, 2897, 64, 64],
+ [7725, 3156, 64, 64],
+ [7661, 3157, 64, 64],
+ [7598, 3157, 64, 64],
+ [7533, 3156, 64, 64],
+ [7468, 3156, 64, 64],
+ [7401, 3156, 64, 64],
+ [7335, 3157, 64, 64],
+ [7270, 3157, 64, 64],
+ [7208, 3157, 64, 64],
+ [7146, 3157, 64, 64],
+ [7134, 3159, 64, 64],
+ [6685, 3726, 64, 64],
+ [6685, 3663, 64, 64],
+ [6683, 3602, 64, 64],
+ [6679, 3538, 64, 64],
+ [6680, 3474, 64, 64],
+ [6682, 3413, 64, 64],
+ [6681, 3347, 64, 64],
+ [6681, 3287, 64, 64],
+ [6682, 3223, 64, 64],
+ [6683, 3161, 64, 64],
+ [6682, 3102, 64, 64],
+ [6684, 3042, 64, 64],
+ [6685, 2980, 64, 64],
+ [6685, 2920, 64, 64],
+ [6683, 2859, 64, 64],
+ [6684, 2801, 64, 64],
+ [6686, 2743, 64, 64],
+ [6683, 2683, 64, 64],
+ [6681, 2622, 64, 64],
+ [6682, 2559, 64, 64],
+ [6683, 2498, 64, 64],
+ [6685, 2434, 64, 64],
+ [6683, 2371, 64, 64],
+ [6683, 2306, 64, 64],
+ [6684, 2242, 64, 64],
+ [6683, 2177, 64, 64],
+ [6683, 2112, 64, 64],
+ [6683, 2049, 64, 64],
+ [6683, 1985, 64, 64],
+ [6682, 1923, 64, 64],
+ [6683, 1860, 64, 64],
+ [6685, 1797, 64, 64],
+ [6684, 1735, 64, 64],
+ [6685, 1724, 64, 64],
+ [7088, 1967, 64, 64],
+ [7026, 1966, 64, 64],
+ [6964, 1967, 64, 64],
+ [6900, 1965, 64, 64],
+ [6869, 1969, 64, 64],
+ [6972, 1904, 64, 64],
+ [6974, 1840, 64, 64],
+ [6971, 1776, 64, 64],
+ [6971, 1716, 64, 64],
+ [7168, 1979, 64, 64],
+ [7170, 1919, 64, 64],
+ [7169, 1882, 64, 64],
+ [7115, 1880, 64, 64],
+ [7086, 1881, 64, 64],
+ [7725, 1837, 64, 64],
+ [7724, 1776, 64, 64],
+ [7724, 1728, 64, 64],
+ [7661, 1727, 64, 64],
+ [7603, 1728, 64, 64],
+ [7571, 1837, 64, 64],
+ [7570, 1774, 64, 64],
+ [7572, 1725, 64, 64],
+ [7859, 2134, 64, 64],
+ [7858, 2070, 64, 64],
+ [7858, 2008, 64, 64],
+ [7860, 1942, 64, 64],
+ [7856, 1878, 64, 64],
+ [7860, 1813, 64, 64],
+ [7859, 1750, 64, 64],
+ [7856, 1724, 64, 64],
+ [8155, 1837, 64, 64],
+ [8092, 1839, 64, 64],
+ [8032, 1838, 64, 64],
+ [7999, 1839, 64, 64],
+ [8153, 1773, 64, 64],
+ [8154, 1731, 64, 64],
+ [8090, 1730, 64, 64],
+ [8035, 1732, 64, 64],
+ [8003, 1776, 64, 64],
+ [8003, 1730, 64, 64],
+ [8421, 1978, 64, 64],
+ [8420, 1917, 64, 64],
+ [8505, 1878, 64, 64],
+ [8443, 1881, 64, 64],
+ [8420, 1882, 64, 64],
+ [8847, 1908, 64, 64],
+ [8783, 1908, 64, 64],
+ [8718, 1910, 64, 64],
+ [8654, 1910, 64, 64],
+ [8628, 1911, 64, 64],
+ [8729, 1847, 64, 64],
+ [8731, 1781, 64, 64],
+ [8731, 1721, 64, 64],
+ [9058, 2135, 64, 64],
+ [9056, 2073, 64, 64],
+ [9058, 2006, 64, 64],
+ [9057, 1939, 64, 64],
+ [9058, 1876, 64, 64],
+ [9056, 1810, 64, 64],
+ [9059, 1745, 64, 64],
+ [9060, 1722, 64, 64],
+ [9273, 1977, 64, 64],
+ [9273, 1912, 64, 64],
+ [9358, 1883, 64, 64],
+ [9298, 1881, 64, 64],
+ [9270, 1883, 64, 64],
+ [9699, 1910, 64, 64],
+ [9637, 1910, 64, 64],
+ [9576, 1910, 64, 64],
+ [9512, 1911, 64, 64],
+ [9477, 1912, 64, 64],
+ [9584, 1846, 64, 64],
+ [9585, 1783, 64, 64],
+ [9586, 1719, 64, 64],
+ [8320, 2788, 64, 64],
+ [8256, 2789, 64, 64],
+ [8192, 2789, 64, 64],
+ [8180, 2789, 64, 64],
+ [8319, 2730, 64, 64],
+ [8319, 2671, 64, 64],
+ [8319, 2639, 64, 64],
+ [8259, 2639, 64, 64],
+ [8202, 2639, 64, 64],
+ [8179, 2727, 64, 64],
+ [8178, 2665, 64, 64],
+ [8177, 2636, 64, 64],
+ [9360, 3138, 64, 64],
+ [9296, 3137, 64, 64],
+ [9235, 3139, 64, 64],
+ [9174, 3139, 64, 64],
+ [9113, 3138, 64, 64],
+ [9050, 3138, 64, 64],
+ [8988, 3138, 64, 64],
+ [8925, 3138, 64, 64],
+ [8860, 3136, 64, 64],
+ [8797, 3136, 64, 64],
+ [8770, 3138, 64, 64],
+ [8827, 4171, 64, 64],
+ [8827, 4107, 64, 64],
+ [8827, 4043, 64, 64],
+ [8827, 3978, 64, 64],
+ [8825, 3914, 64, 64],
+ [8824, 3858, 64, 64],
+ [9635, 4234, 64, 64],
+ [9584, 4235, 64, 64],
+ [9634, 4187, 64, 64],
+ [9582, 4183, 64, 64],
+ [9402, 5114, 64, 64],
+ [9402, 5087, 64, 64],
+ [9347, 5113, 64, 64],
+ [9345, 5086, 64, 64],
+ [9287, 5114, 64, 64],
+ [9285, 5085, 64, 64],
+ [9245, 5114, 64, 64],
+ [9244, 5086, 64, 64],
+ [9336, 5445, 64, 64],
+ [9285, 5445, 64, 64],
+ [9337, 5395, 64, 64],
+ [9283, 5393, 64, 64],
+ [8884, 4968, 64, 64],
+ [8884, 4939, 64, 64],
+ [8822, 4967, 64, 64],
+ [8823, 4940, 64, 64],
+ [8765, 4967, 64, 64],
+ [8762, 4937, 64, 64],
+ [8726, 4969, 64, 64],
+ [8727, 4939, 64, 64],
+ [7946, 5248, 64, 64],
+ [7945, 5220, 64, 64],
+ [7887, 5248, 64, 64],
+ [7886, 5219, 64, 64],
+ [7830, 5248, 64, 64],
+ [7827, 5218, 64, 64],
+ [7781, 5248, 64, 64],
+ [7781, 5216, 64, 64],
+ [6648, 4762, 64, 64],
+ [6621, 4761, 64, 64],
+ [5011, 4446, 64, 64],
+ [4982, 4444, 64, 64],
+ [4146, 4641, 64, 64],
+ [4092, 4643, 64, 64],
+ [4145, 4589, 64, 64],
+ [4091, 4590, 64, 64],
+ [4139, 4497, 64, 64],
+ [4135, 4437, 64, 64],
+ [4135, 4383, 64, 64],
+ [4078, 4495, 64, 64],
+ [4014, 4494, 64, 64],
+ [3979, 4496, 64, 64],
+ [4074, 4384, 64, 64],
+ [4015, 4381, 64, 64],
+ [3980, 4433, 64, 64],
+ [3981, 4384, 64, 64],
+ [3276, 4279, 64, 64],
+ [3275, 4218, 64, 64],
+ [3276, 4170, 64, 64],
+ [3211, 4164, 64, 64],
+ [3213, 4280, 64, 64],
+ [3156, 4278, 64, 64],
+ [3120, 4278, 64, 64],
+ [3151, 4163, 64, 64],
+ [3120, 4216, 64, 64],
+ [3120, 4161, 64, 64],
+ [1536, 4171, 64, 64],
+ [1536, 4110, 64, 64],
+ [1535, 4051, 64, 64],
+ [1536, 3991, 64, 64],
+ [1536, 3928, 64, 64],
+ [1536, 3863, 64, 64],
+ [1078, 4605, 64, 64],
+ [1076, 4577, 64, 64],
+ [1018, 4604, 64, 64],
+ [1018, 4575, 64, 64],
+ [957, 4606, 64, 64],
+ [960, 4575, 64, 64],
+ [918, 4602, 64, 64],
+ [918, 4580, 64, 64],
+ [394, 4164, 64, 64],
+ [335, 4163, 64, 64],
+ [274, 4161, 64, 64],
+ [236, 4163, 64, 64],
+ [394, 4140, 64, 64],
+ [329, 4139, 64, 64],
+ [268, 4139, 64, 64],
+ [239, 4139, 64, 64],
+ [4326, 5073, 64, 64],
+ [4324, 5042, 64, 64],
+ [4265, 5074, 64, 64],
+ [4263, 5042, 64, 64],
+ [4214, 5072, 64, 64],
+ [4211, 5043, 64, 64],
+ [4166, 5073, 64, 64],
+ [4164, 5041, 64, 64],
+ [4844, 5216, 64, 64],
+ [4844, 5189, 64, 64],
+ [4785, 5217, 64, 64],
+ [4790, 5187, 64, 64],
+ [4726, 5219, 64, 64],
+ [4728, 5185, 64, 64],
+ [4681, 5218, 64, 64],
+ [4684, 5186, 64, 64],
+ [4789, 4926, 64, 64],
+ [4734, 4928, 64, 64],
+ [4787, 4876, 64, 64],
+ [4738, 4874, 64, 64],
+ [4775, 5548, 64, 64],
+ [4775, 5495, 64, 64],
+ [4723, 5550, 64, 64],
+ [4725, 5494, 64, 64],
+ [1360, 5269, 64, 64],
+ [1362, 5218, 64, 64],
+ [1315, 5266, 64, 64],
+ [1282, 5266, 64, 64],
+ [1246, 5311, 64, 64],
+ [1190, 5312, 64, 64],
+ [1136, 5310, 64, 64],
+ [1121, 5427, 64, 64],
+ [1121, 5370, 64, 64],
+ [1074, 5427, 64, 64],
+ [1064, 5423, 64, 64],
+ [1052, 5417, 64, 64],
+ [1050, 5368, 64, 64],
+ [1008, 5314, 64, 64],
+ [997, 5307, 64, 64],
+ [977, 5299, 64, 64],
+ [976, 5248, 64, 64],
+ [825, 5267, 64, 64],
+ [826, 5213, 64, 64],
+ [776, 5267, 64, 64],
+ [768, 5261, 64, 64],
+ [755, 5256, 64, 64],
+ [753, 5209, 64, 64],
+ [1299, 5206, 64, 64],
+ [1238, 5204, 64, 64],
+ [1178, 5203, 64, 64],
+ [1124, 5204, 64, 64],
+ [1065, 5206, 64, 64],
+ [1008, 5203, 64, 64],
+ [977, 5214, 64, 64],
+ [410, 5313, 64, 64],
+ [407, 5249, 64, 64],
+ [411, 5225, 64, 64],
+ [397, 5217, 64, 64],
+ [378, 5209, 64, 64],
+ [358, 5312, 64, 64],
+ [287, 5427, 64, 64],
+ [286, 5364, 64, 64],
+ [300, 5313, 64, 64],
+ [242, 5427, 64, 64],
+ [229, 5420, 64, 64],
+ [217, 5416, 64, 64],
+ [215, 5364, 64, 64],
+ [174, 5311, 64, 64],
+ [165, 5308, 64, 64],
+ [139, 5300, 64, 64],
+ [141, 5236, 64, 64],
+ [141, 5211, 64, 64],
+ [315, 5208, 64, 64],
+ [251, 5208, 64, 64],
+ [211, 5211, 64, 64],
+ [8050, 4060, 64, 64],
+ [7992, 4060, 64, 64],
+ [7929, 4060, 64, 64],
+ [7866, 4061, 64, 64],
+ [7828, 4063, 64, 64],
+ [7934, 4001, 64, 64],
+ [7935, 3936, 64, 64],
+ [7935, 3875, 64, 64],
+ [7622, 4111, 64, 64],
+ [7623, 4049, 64, 64],
+ [7707, 4018, 64, 64],
+ [7663, 4019, 64, 64],
+ [7623, 4017, 64, 64],
+ [7193, 4060, 64, 64],
+ [7131, 4059, 64, 64],
+ [7070, 4057, 64, 64],
+ [7008, 4060, 64, 64],
+ [6977, 4060, 64, 64],
+ [7080, 3998, 64, 64],
+ [7081, 3935, 64, 64],
+ [7080, 3873, 64, 64],
+ [6855, 4019, 64, 64],
+ [6790, 4018, 64, 64],
+ [6770, 4114, 64, 64],
+ [6770, 4060, 64, 64],
+ [6768, 4013, 64, 64],
+ [6345, 4060, 64, 64],
+ [6284, 4062, 64, 64],
+ [6222, 4061, 64, 64],
+ [6166, 4061, 64, 64],
+ [6124, 4066, 64, 64],
+ [6226, 3995, 64, 64],
+ [6226, 3933, 64, 64],
+ [6228, 3868, 64, 64],
+ [5916, 4113, 64, 64],
+ [5918, 4052, 64, 64],
+ [6001, 4018, 64, 64],
+ [5941, 4019, 64, 64],
+ [5918, 4020, 64, 64],
+ [5501, 4059, 64, 64],
+ [5439, 4061, 64, 64],
+ [5376, 4059, 64, 64],
+ [5312, 4058, 64, 64],
+ [5285, 4062, 64, 64],
+ [5388, 3999, 64, 64],
+ [5385, 3941, 64, 64],
+ [5384, 3874, 64, 64],
+ [5075, 4112, 64, 64],
+ [5074, 4051, 64, 64],
+ [5158, 4018, 64, 64],
+ [5095, 4020, 64, 64],
+ [5073, 4018, 64, 64],
+ [4549, 3998, 64, 64],
+ [4393, 3996, 64, 64],
+ [4547, 3938, 64, 64],
+ [4547, 3886, 64, 64],
+ [4488, 3885, 64, 64],
+ [4427, 3885, 64, 64],
+ [4395, 3938, 64, 64],
+ [4395, 3885, 64, 64],
+ [0, 0, 64, 64],
+ [0, 1670, 64, 64],
+ [6691, 1653, 64, 64],
+ [1521, 3792, 64, 64],
+ [0, 5137, 64, 64],
+ [0, 0, 64, 64],
+ [0, 1670, 64, 64],
+ [6691, 1653, 64, 64],
+ [1521, 3792, 64, 64],
+ [0, 5137, 64, 64],
+ [1215, 2421, 64, 64],
+ [1214, 2360, 64, 64],
+ [1211, 2300, 64, 64],
+ [1211, 2291, 64, 64],
+ [1158, 2420, 64, 64],
+ [1156, 2358, 64, 64],
+ [1149, 2291, 64, 64],
+ [1095, 2420, 64, 64],
+ [1030, 2418, 64, 64],
+ [966, 2419, 64, 64],
+ [903, 2419, 64, 64],
+ [852, 2419, 64, 64],
+ [1087, 2291, 64, 64],
+ [1023, 2291, 64, 64],
+ [960, 2291, 64, 64],
+ [896, 2292, 64, 64],
+ [854, 2355, 64, 64],
+ [854, 2292, 64, 64],
+ [675, 3017, 64, 64],
+ [622, 3017, 64, 64],
+ [676, 2965, 64, 64],
+ [622, 2965, 64, 64],
+ [1560, 3212, 64, 64],
+ [1496, 3212, 64, 64],
+ [1430, 3211, 64, 64],
+ [1346, 3214, 64, 64],
+ [1410, 3213, 64, 64],
+ [1560, 3147, 64, 64],
+ [1559, 3105, 64, 64],
+ [1496, 3105, 64, 64],
+ [1442, 3105, 64, 64],
+ [1412, 3106, 64, 64],
+ [918, 4163, 64, 64],
+ [854, 4161, 64, 64],
+ [792, 4160, 64, 64],
+ [729, 4159, 64, 64],
+ [666, 4158, 64, 64],
+ [601, 4158, 64, 64],
+ [537, 4156, 64, 64],
+ [918, 4137, 64, 64],
+ [854, 4137, 64, 64],
+ [789, 4136, 64, 64],
+ [726, 4137, 64, 64],
+ [661, 4137, 64, 64],
+ [599, 4139, 64, 64],
+ [538, 4137, 64, 64],
+ [5378, 4254, 64, 64],
+ [5440, 4204, 64, 64],
+ [5405, 4214, 64, 64],
+ [5350, 4254, 64, 64],
+ [5439, 4177, 64, 64],
+ [5413, 4173, 64, 64],
+ [5399, 4128, 64, 64],
+ [5352, 4200, 64, 64],
+ [5352, 4158, 64, 64],
+ [5392, 4130, 64, 64],
+ [6216, 4251, 64, 64],
+ [6190, 4251, 64, 64],
+ [6279, 4200, 64, 64],
+ [6262, 4205, 64, 64],
+ [6233, 4214, 64, 64],
+ [6280, 4172, 64, 64],
+ [6256, 4169, 64, 64],
+ [6239, 4128, 64, 64],
+ [6231, 4128, 64, 64],
+ [6191, 4195, 64, 64],
+ [6190, 4158, 64, 64],
+ [7072, 4250, 64, 64],
+ [7046, 4250, 64, 64],
+ [7133, 4202, 64, 64],
+ [7107, 4209, 64, 64],
+ [7086, 4214, 64, 64],
+ [7133, 4173, 64, 64],
+ [7108, 4169, 64, 64],
+ [7092, 4127, 64, 64],
+ [7084, 4128, 64, 64],
+ [7047, 4191, 64, 64],
+ [7047, 4156, 64, 64],
+ [7926, 4252, 64, 64],
+ [7900, 4253, 64, 64],
+ [7987, 4202, 64, 64],
+ [7965, 4209, 64, 64],
+ [7942, 4216, 64, 64],
+ [7989, 4174, 64, 64],
+ [7970, 4170, 64, 64],
+ [7949, 4126, 64, 64],
+ [7901, 4196, 64, 64],
+ [7900, 4159, 64, 64],
+ [7941, 4130, 64, 64],
+ [2847, 379, 64, 64],
+ [2825, 380, 64, 64],
+ [2845, 317, 64, 64],
+ [2829, 316, 64, 64],
+ [2845, 255, 64, 64],
+ [2830, 257, 64, 64],
+ [2845, 202, 64, 64],
+ [2829, 198, 64, 64],
+ [2770, 169, 64, 64],
+ [2708, 170, 64, 64],
+ [2646, 171, 64, 64],
+ [2582, 171, 64, 64],
+ [2518, 171, 64, 64],
+ [2454, 171, 64, 64],
+ [2391, 172, 64, 64],
+ [2332, 379, 64, 64],
+ [2315, 379, 64, 64],
+ [2334, 316, 64, 64],
+ [2315, 317, 64, 64],
+ [2332, 254, 64, 64],
+ [2314, 254, 64, 64],
+ [2335, 192, 64, 64],
+ [2311, 192, 64, 64],
+ [2846, 142, 64, 64],
+ [2784, 140, 64, 64],
+ [2846, 79, 64, 64],
+ [2847, 41, 64, 64],
+ [2783, 80, 64, 64],
+ [2790, 39, 64, 64],
+ [2727, 41, 64, 64],
+ [2665, 43, 64, 64],
+ [2605, 43, 64, 64],
+ [2543, 44, 64, 64],
+ [2480, 45, 64, 64],
+ [2419, 45, 64, 64],
+ [2357, 44, 64, 64],
+ [2313, 129, 64, 64],
+ [2313, 70, 64, 64],
+ [2314, 40, 64, 64],
+ [2517, 2385, 64, 64],
+ [2452, 2385, 64, 64],
+ [2390, 2386, 64, 64],
+ [2328, 2386, 64, 64],
+ [2264, 2386, 64, 64],
+ [2200, 2386, 64, 64],
+ [2137, 2387, 64, 64],
+ [2071, 2385, 64, 64],
+ [2016, 2389, 64, 64],
+ [2517, 2341, 64, 64],
+ [2518, 2316, 64, 64],
+ [2456, 2316, 64, 64],
+ [2393, 2316, 64, 64],
+ [2328, 2317, 64, 64],
+ [2264, 2316, 64, 64],
+ [2207, 2318, 64, 64],
+ [2144, 2317, 64, 64],
+ [2081, 2316, 64, 64],
+ [2015, 2342, 64, 64],
+ [2016, 2315, 64, 64],
+ [869, 3709, 64, 64],
+ [819, 3710, 64, 64],
+ [869, 3658, 64, 64],
+ [820, 3658, 64, 64],
+ [0, 0, 64, 64],
+ [0, 1670, 64, 64],
+ [6691, 1653, 64, 64],
+ [1521, 3792, 64, 64],
+ [0, 5137, 64, 64],
+ [3898, 2400, 64, 64],
+ [3835, 2400, 64, 64],
+ [3771, 2400, 64, 64],
+ [3708, 2401, 64, 64],
+ [3646, 2401, 64, 64],
+ [3587, 2401, 64, 64],
+ [3530, 2401, 64, 64],
+ [3897, 2340, 64, 64],
+ [3897, 2295, 64, 64],
+ [3834, 2296, 64, 64],
+ [3773, 2295, 64, 64],
+ [3710, 2296, 64, 64],
+ [3656, 2295, 64, 64],
+ [3593, 2294, 64, 64],
+ [3527, 2339, 64, 64],
+ [3531, 2293, 64, 64],
+ [4152, 2903, 64, 64],
+ [4155, 2858, 64, 64],
+ [3942, 1306, 64, 64],
+ [3942, 1279, 64, 64],
+ [3879, 1306, 64, 64],
+ [3881, 1278, 64, 64],
+ [3819, 1305, 64, 64],
+ [3819, 1277, 64, 64],
+ [3756, 1306, 64, 64],
+ [3756, 1277, 64, 64],
+ [3694, 1306, 64, 64],
+ [3695, 1277, 64, 64],
+ [3631, 1306, 64, 64],
+ [3632, 1278, 64, 64],
+ [3565, 1306, 64, 64],
+ [3567, 1279, 64, 64],
+ [4432, 1165, 64, 64],
+ [4408, 1163, 64, 64],
+ [5123, 1003, 64, 64],
+ [5065, 1002, 64, 64],
+ [5042, 1002, 64, 64],
+ [6020, 1780, 64, 64],
+ [6020, 1756, 64, 64],
+ [5959, 1780, 64, 64],
+ [5959, 1752, 64, 64],
+ [5897, 1779, 64, 64],
+ [5899, 1752, 64, 64],
+ [5836, 1779, 64, 64],
+ [5836, 1751, 64, 64],
+ [5776, 1780, 64, 64],
+ [5776, 1754, 64, 64],
+ [5717, 1780, 64, 64],
+ [5716, 1752, 64, 64],
+ [5658, 1781, 64, 64],
+ [5658, 1755, 64, 64],
+ [5640, 1781, 64, 64],
+ [5640, 1754, 64, 64],
+ [5832, 2095, 64, 64],
+ [5782, 2093, 64, 64],
+ [5832, 2044, 64, 64],
+ [5777, 2043, 64, 64],
+ [4847, 2577, 64, 64],
+ [4795, 2577, 64, 64],
+ [4846, 2526, 64, 64],
+ [4794, 2526, 64, 64],
+ [8390, 923, 64, 64],
+ [8363, 922, 64, 64],
+ [7585, 1084, 64, 64],
+ [7582, 1058, 64, 64],
+ [7525, 1084, 64, 64],
+ [7524, 1056, 64, 64],
+ [7478, 1085, 64, 64],
+ [7476, 1055, 64, 64],
+ [7421, 1086, 64, 64],
+ [7421, 1052, 64, 64],
+ [7362, 1085, 64, 64],
+ [7361, 1053, 64, 64],
+ [7307, 1087, 64, 64],
+ [7307, 1054, 64, 64],
+ [7258, 1086, 64, 64],
+ [7255, 1058, 64, 64],
+ [7203, 1083, 64, 64],
+ [7203, 1055, 64, 64],
+ [7161, 1085, 64, 64],
+ [7158, 1057, 64, 64],
+ [7100, 1083, 64, 64],
+ [7099, 1058, 64, 64],
+ [7038, 1082, 64, 64],
+ [7038, 1058, 64, 64],
+ [6982, 1083, 64, 64],
+ [6984, 1057, 64, 64],
+ [0, 0, 64, 64],
+ [0, 1670, 64, 64],
+ [6691, 1653, 64, 64],
+ [1521, 3792, 64, 64],
+ [0, 5137, 64, 64],
+ [0, 0, 64, 64],
+ [0, 1670, 64, 64],
+ [6691, 1653, 64, 64],
+ [1521, 3792, 64, 64],
+ [0, 5137, 64, 64],
+ [0, 0, 64, 64],
+ [0, 1670, 64, 64],
+ [6691, 1653, 64, 64],
+ [1521, 3792, 64, 64],
+ [0, 5137, 64, 64],
+ [8346, 424, 64, 64],
+ [8407, 376, 64, 64],
+ [8375, 386, 64, 64],
+ [8407, 347, 64, 64],
+ [8388, 343, 64, 64],
+ [8320, 423, 64, 64],
+ [8319, 363, 64, 64],
+ [8368, 303, 64, 64],
+ [8359, 303, 64, 64],
+ [8318, 330, 64, 64],
+ [9369, 425, 64, 64],
+ [9340, 425, 64, 64],
+ [9431, 376, 64, 64],
+ [9414, 382, 64, 64],
+ [9387, 391, 64, 64],
+ [9431, 349, 64, 64],
+ [9412, 344, 64, 64],
+ [9392, 305, 64, 64],
+ [9339, 365, 64, 64],
+ [9341, 333, 64, 64],
+ [9384, 301, 64, 64],
+ [7673, 1896, 64, 64],
+ [7642, 1834, 64, 64],
+ [7646, 1901, 64, 64],
+ [4500, 4054, 64, 64],
+ [4476, 4055, 64, 64],
+ [4459, 3997, 64, 64],
+ [76, 5215, 64, 64],
+ [39, 5217, 64, 64],
+]
+
+$mugs = [
+ [85, 87, 39, 43, "sprites/square-orange.png"],
+ [958, 1967, 39, 43, "sprites/square-orange.png"],
+ [2537, 1734, 39, 43, "sprites/square-orange.png"],
+ [3755, 2464, 39, 43, "sprites/square-orange.png"],
+ [1548, 3273, 39, 43, "sprites/square-orange.png"],
+ [2050, 220, 39, 43, "sprites/square-orange.png"],
+ [854, 297, 39, 43, "sprites/square-orange.png"],
+ [343, 526, 39, 43, "sprites/square-orange.png"],
+ [3454, 772, 39, 43, "sprites/square-orange.png"],
+ [5041, 298, 39, 43, "sprites/square-orange.png"],
+ [6089, 300, 39, 43, "sprites/square-orange.png"],
+ [6518, 295, 39, 43, "sprites/square-orange.png"],
+ [7661, 47, 39, 43, "sprites/square-orange.png"],
+ [9392, 1125, 39, 43, "sprites/square-orange.png"],
+ [7298, 1152, 39, 43, "sprites/square-orange.png"],
+ [5816, 1843, 39, 43, "sprites/square-orange.png"],
+ [876, 3772, 39, 43, "sprites/square-orange.png"],
+ [1029, 4667, 39, 43, "sprites/square-orange.png"],
+ [823, 5324, 39, 43, "sprites/square-orange.png"],
+ [3251, 5220, 39, 43, "sprites/square-orange.png"],
+ [4747, 5282, 39, 43, "sprites/square-orange.png"],
+ [9325, 5178, 39, 43, "sprites/square-orange.png"],
+ [9635, 4298, 39, 43, "sprites/square-orange.png"],
+ [7837, 4127, 39, 43, "sprites/square-orange.png"],
+ [8651, 1971, 39, 43, "sprites/square-orange.png"],
+ [6892, 2031, 39, 43, "sprites/square-orange.png"],
+ [4626, 3882, 39, 43, "sprites/square-orange.png"],
+ [4024, 4554, 39, 43, "sprites/square-orange.png"],
+ [3925, 3337, 39, 43, "sprites/square-orange.png"],
+ [5064, 1064, 39, 43, "sprites/square-orange.png"]
+]
diff --git a/samples/99_genre_platformer/clepto_frog/metadata/game_metadata.txt b/samples/99_genre_platformer/clepto_frog/metadata/game_metadata.txt
new file mode 100644
index 0000000..7b3f61e
--- /dev/null
+++ b/samples/99_genre_platformer/clepto_frog/metadata/game_metadata.txt
@@ -0,0 +1,6 @@
+devid=amirrajan
+devtitle=Amir Rajan
+gameid=clepto-frog
+gametitle=Clepto Frog
+version=1.0
+icon=sprites/square-green.png
diff --git a/samples/99_genre_platformer/clepto_frog/sprites/level-map.png b/samples/99_genre_platformer/clepto_frog/sprites/level-map.png
new file mode 100644
index 0000000..f590be4
--- /dev/null
+++ b/samples/99_genre_platformer/clepto_frog/sprites/level-map.png
Binary files differ
diff --git a/samples/99_genre_platformer/clepto_frog/sprites/square-black.png b/samples/99_genre_platformer/clepto_frog/sprites/square-black.png
new file mode 100644
index 0000000..cea7bd7
--- /dev/null
+++ b/samples/99_genre_platformer/clepto_frog/sprites/square-black.png
Binary files differ
diff --git a/samples/99_genre_platformer/clepto_frog/sprites/square-blue.png b/samples/99_genre_platformer/clepto_frog/sprites/square-blue.png
new file mode 100644
index 0000000..b840849
--- /dev/null
+++ b/samples/99_genre_platformer/clepto_frog/sprites/square-blue.png
Binary files differ
diff --git a/samples/99_genre_platformer/clepto_frog/sprites/square-gray.png b/samples/99_genre_platformer/clepto_frog/sprites/square-gray.png
new file mode 100644
index 0000000..2142b30
--- /dev/null
+++ b/samples/99_genre_platformer/clepto_frog/sprites/square-gray.png
Binary files differ
diff --git a/samples/99_genre_platformer/clepto_frog/sprites/square-green.png b/samples/99_genre_platformer/clepto_frog/sprites/square-green.png
new file mode 100644
index 0000000..5ef7f75
--- /dev/null
+++ b/samples/99_genre_platformer/clepto_frog/sprites/square-green.png
Binary files differ
diff --git a/samples/99_genre_platformer/clepto_frog/sprites/square-indigo.png b/samples/99_genre_platformer/clepto_frog/sprites/square-indigo.png
new file mode 100644
index 0000000..2384108
--- /dev/null
+++ b/samples/99_genre_platformer/clepto_frog/sprites/square-indigo.png
Binary files differ
diff --git a/samples/99_genre_platformer/clepto_frog/sprites/square-orange.png b/samples/99_genre_platformer/clepto_frog/sprites/square-orange.png
new file mode 100644
index 0000000..bb1eee7
--- /dev/null
+++ b/samples/99_genre_platformer/clepto_frog/sprites/square-orange.png
Binary files differ
diff --git a/samples/99_genre_platformer/clepto_frog/sprites/square-pink.png b/samples/99_genre_platformer/clepto_frog/sprites/square-pink.png
new file mode 100644
index 0000000..3bbb63a
--- /dev/null
+++ b/samples/99_genre_platformer/clepto_frog/sprites/square-pink.png
Binary files differ
diff --git a/samples/99_genre_platformer/clepto_frog/sprites/square-red.png b/samples/99_genre_platformer/clepto_frog/sprites/square-red.png
new file mode 100644
index 0000000..3ed5f13
--- /dev/null
+++ b/samples/99_genre_platformer/clepto_frog/sprites/square-red.png
Binary files differ
diff --git a/samples/99_genre_platformer/clepto_frog/sprites/square-violet.png b/samples/99_genre_platformer/clepto_frog/sprites/square-violet.png
new file mode 100644
index 0000000..333540c
--- /dev/null
+++ b/samples/99_genre_platformer/clepto_frog/sprites/square-violet.png
Binary files differ
diff --git a/samples/99_genre_platformer/clepto_frog/sprites/square-white.png b/samples/99_genre_platformer/clepto_frog/sprites/square-white.png
new file mode 100644
index 0000000..378c565
--- /dev/null
+++ b/samples/99_genre_platformer/clepto_frog/sprites/square-white.png
Binary files differ
diff --git a/samples/99_genre_platformer/clepto_frog/sprites/square-yellow.png b/samples/99_genre_platformer/clepto_frog/sprites/square-yellow.png
new file mode 100644
index 0000000..0edeeec
--- /dev/null
+++ b/samples/99_genre_platformer/clepto_frog/sprites/square-yellow.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/CREDITS.txt b/samples/99_genre_platformer/gorillas_basic/CREDITS.txt
new file mode 100644
index 0000000..7503a2a
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/CREDITS.txt
@@ -0,0 +1,3 @@
+code: Amir Rajan, https://twitter.com/amirrajan
+graphics: Nick Culbertson, https://twitter.com/MobyPixel
+
diff --git a/samples/99_genre_platformer/gorillas_basic/app/main.rb b/samples/99_genre_platformer/gorillas_basic/app/main.rb
new file mode 100644
index 0000000..53f9a4f
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/app/main.rb
@@ -0,0 +1,373 @@
+class YouSoBasicGorillas
+ attr_accessor :outputs, :grid, :state, :inputs
+
+ def tick
+ defaults
+ render
+ calc
+ process_inputs
+ end
+
+ def defaults
+ outputs.background_color = [33, 32, 87]
+ state.building_spacing = 1
+ state.building_room_spacing = 15
+ state.building_room_width = 10
+ state.building_room_height = 15
+ state.building_heights = [4, 4, 6, 8, 15, 20, 18]
+ state.building_room_sizes = [5, 4, 6, 7]
+ state.gravity = 0.25
+ state.first_strike ||= :player_1
+ state.buildings ||= []
+ state.holes ||= []
+ state.player_1_score ||= 0
+ state.player_2_score ||= 0
+ state.wind ||= 0
+ end
+
+ def render
+ render_stage
+ render_value_insertion
+ render_gorillas
+ render_holes
+ render_banana
+ render_game_over
+ render_score
+ render_wind
+ end
+
+ def render_score
+ outputs.primitives << [0, 0, 1280, 31, fancy_white].solid
+ outputs.primitives << [1, 1, 1279, 29].solid
+ outputs.labels << [ 10, 25, "Score: #{state.player_1_score}", 0, 0, fancy_white]
+ outputs.labels << [1270, 25, "Score: #{state.player_2_score}", 0, 2, fancy_white]
+ end
+
+ def render_wind
+ outputs.primitives << [640, 12, state.wind * 500 + state.wind * 10 * rand, 4, 35, 136, 162].solid
+ outputs.lines << [640, 30, 640, 0, fancy_white]
+ end
+
+ def render_game_over
+ return unless state.over
+ outputs.primitives << [grid.rect, 0, 0, 0, 200].solid
+ outputs.primitives << [640, 370, "Game Over!!", 5, 1, fancy_white].label
+ if state.winner == :player_1
+ outputs.primitives << [640, 340, "Player 1 Wins!!", 5, 1, fancy_white].label
+ else
+ outputs.primitives << [640, 340, "Player 2 Wins!!", 5, 1, fancy_white].label
+ end
+ end
+
+ def render_stage
+ return unless state.stage_generated
+ return if state.stage_rendered
+
+ outputs.static_solids << [grid.rect, 33, 32, 87]
+ outputs.static_solids << state.buildings.map(&:solids)
+ state.stage_rendered = true
+ end
+
+ def render_gorilla gorilla, id
+ return unless gorilla
+ if state.banana && state.banana.owner == gorilla
+ animation_index = state.banana.created_at.frame_index(3, 5, false)
+ end
+ if !animation_index
+ outputs.sprites << [gorilla.solid, "sprites/#{id}-idle.png"]
+ else
+ outputs.sprites << [gorilla.solid, "sprites/#{id}-#{animation_index}.png"]
+ end
+ end
+
+ def render_gorillas
+ render_gorilla state.player_1, :left
+ render_gorilla state.player_2, :right
+ end
+
+ def render_value_insertion
+ return if state.banana
+ return if state.over
+
+ if state.current_turn == :player_1_angle
+ outputs.labels << [ 10, 710, "Angle: #{state.player_1_angle}_", fancy_white]
+ elsif state.current_turn == :player_1_velocity
+ outputs.labels << [ 10, 710, "Angle: #{state.player_1_angle}", fancy_white]
+ outputs.labels << [ 10, 690, "Velocity: #{state.player_1_velocity}_", fancy_white]
+ elsif state.current_turn == :player_2_angle
+ outputs.labels << [1120, 710, "Angle: #{state.player_2_angle}_", fancy_white]
+ elsif state.current_turn == :player_2_velocity
+ outputs.labels << [1120, 710, "Angle: #{state.player_2_angle}", fancy_white]
+ outputs.labels << [1120, 690, "Velocity: #{state.player_2_velocity}_", fancy_white]
+ end
+ end
+
+ def render_banana
+ return unless state.banana
+ rotation = state.tick_count.%(360) * 20
+ rotation *= -1 if state.banana.dx > 0
+ outputs.sprites << [state.banana.x, state.banana.y, 15, 15, 'sprites/banana.png', rotation]
+ end
+
+ def render_holes
+ outputs.sprites << state.holes.map do |s|
+ animation_index = s.created_at.frame_index(7, 3, false)
+ if animation_index
+ [s.sprite, [s.sprite.rect, "sprites/explosion#{animation_index}.png" ]]
+ else
+ s.sprite
+ end
+ end
+ end
+
+ def calc
+ calc_generate_stage
+ calc_current_turn
+ calc_banana
+ end
+
+ def calc_current_turn
+ return if state.current_turn
+
+ state.current_turn = :player_1_angle
+ state.current_turn = :player_2_angle if state.first_strike == :player_2
+ end
+
+ def calc_generate_stage
+ return if state.stage_generated
+
+ state.buildings << building_prefab(state.building_spacing + -20, *random_building_size)
+ 8.numbers.inject(state.buildings) do |buildings, i|
+ buildings <<
+ building_prefab(state.building_spacing +
+ state.buildings.last.right,
+ *random_building_size)
+ end
+
+ building_two = state.buildings[1]
+ state.player_1 = new_player(building_two.x + building_two.w.fdiv(2),
+ building_two.h)
+
+ building_nine = state.buildings[-3]
+ state.player_2 = new_player(building_nine.x + building_nine.w.fdiv(2),
+ building_nine.h)
+ state.stage_generated = true
+ state.wind = 1.randomize(:ratio, :sign)
+ end
+
+ def new_player x, y
+ state.new_entity(:gorilla) do |p|
+ p.x = x - 25
+ p.y = y
+ p.solid = [p.x, p.y, 50, 50]
+ end
+ end
+
+ def calc_banana
+ return unless state.banana
+
+ state.banana.x += state.banana.dx
+ state.banana.dx += state.wind.fdiv(50)
+ state.banana.y += state.banana.dy
+ state.banana.dy -= state.gravity
+ banana_collision = [state.banana.x, state.banana.y, 10, 10]
+
+ if state.player_1 && banana_collision.intersect_rect?(state.player_1.solid)
+ state.over = true
+ if state.banana.owner == state.player_2
+ state.winner = :player_2
+ else
+ state.winner = :player_1
+ end
+
+ state.player_2_score += 1
+ elsif state.player_2 && banana_collision.intersect_rect?(state.player_2.solid)
+ state.over = true
+ if state.banana.owner == state.player_2
+ state.winner = :player_1
+ else
+ state.winner = :player_2
+ end
+ state.player_1_score += 1
+ end
+
+ if state.over
+ place_hole
+ return
+ end
+
+ return if state.holes.any? do |h|
+ h.sprite.scale_rect(0.8, 0.5, 0.5).intersect_rect? [state.banana.x, state.banana.y, 10, 10]
+ end
+
+ return unless state.banana.y < 0 || state.buildings.any? do |b|
+ b.rect.intersect_rect? [state.banana.x, state.banana.y, 1, 1]
+ end
+
+ place_hole
+ end
+
+ def place_hole
+ return unless state.banana
+
+ state.holes << state.new_entity(:banana) do |b|
+ b.sprite = [state.banana.x - 20, state.banana.y - 20, 40, 40, 'sprites/hole.png']
+ end
+
+ state.banana = nil
+ end
+
+ def process_inputs_main
+ return if state.banana
+ return if state.over
+
+ if inputs.keyboard.key_down.enter
+ input_execute_turn
+ elsif inputs.keyboard.key_down.backspace
+ state.as_hash[state.current_turn] ||= ""
+ state.as_hash[state.current_turn] = state.as_hash[state.current_turn][0..-2]
+ elsif inputs.keyboard.key_down.char
+ state.as_hash[state.current_turn] ||= ""
+ state.as_hash[state.current_turn] += inputs.keyboard.key_down.char
+ end
+ end
+
+ def process_inputs_game_over
+ return unless state.over
+ return unless inputs.keyboard.key_down.truthy_keys.any?
+ state.over = false
+ outputs.static_solids.clear
+ state.buildings.clear
+ state.holes.clear
+ state.stage_generated = false
+ state.stage_rendered = false
+ if state.first_strike == :player_1
+ state.first_strike = :player_2
+ else
+ state.first_strike = :player_1
+ end
+ end
+
+ def process_inputs
+ process_inputs_main
+ process_inputs_game_over
+ end
+
+ def input_execute_turn
+ return if state.banana
+
+ if state.current_turn == :player_1_angle && parse_or_clear!(:player_1_angle)
+ state.current_turn = :player_1_velocity
+ elsif state.current_turn == :player_1_velocity && parse_or_clear!(:player_1_velocity)
+ state.current_turn = :player_2_angle
+ state.banana =
+ new_banana(state.player_1,
+ state.player_1.x + 25,
+ state.player_1.y + 60,
+ state.player_1_angle,
+ state.player_1_velocity)
+ elsif state.current_turn == :player_2_angle && parse_or_clear!(:player_2_angle)
+ state.current_turn = :player_2_velocity
+ elsif state.current_turn == :player_2_velocity && parse_or_clear!(:player_2_velocity)
+ state.current_turn = :player_1_angle
+ state.banana =
+ new_banana(state.player_2,
+ state.player_2.x + 25,
+ state.player_2.y + 60,
+ 180 - state.player_2_angle,
+ state.player_2_velocity)
+ end
+
+ if state.banana
+ state.player_1_angle = nil
+ state.player_1_velocity = nil
+ state.player_2_angle = nil
+ state.player_2_velocity = nil
+ end
+ end
+
+ def random_building_size
+ [state.building_heights.sample, state.building_room_sizes.sample]
+ end
+
+ def int? v
+ v.to_i.to_s == v.to_s
+ end
+
+ def random_building_color
+ [[ 99, 0, 107],
+ [ 35, 64, 124],
+ [ 35, 136, 162],
+ ].sample
+ end
+
+ def random_window_color
+ [[ 88, 62, 104],
+ [253, 224, 187]].sample
+ end
+
+ def windows_for_building starting_x, floors, rooms
+ floors.-(1).combinations(rooms - 1).map do |floor, room|
+ [starting_x +
+ state.building_room_width.*(room) +
+ state.building_room_spacing.*(room + 1),
+ state.building_room_height.*(floor) +
+ state.building_room_spacing.*(floor + 1),
+ state.building_room_width,
+ state.building_room_height,
+ random_window_color]
+ end
+ end
+
+ def building_prefab starting_x, floors, rooms
+ state.new_entity(:building) do |b|
+ b.x = starting_x
+ b.y = 0
+ b.w = state.building_room_width.*(rooms) +
+ state.building_room_spacing.*(rooms + 1)
+ b.h = state.building_room_height.*(floors) +
+ state.building_room_spacing.*(floors + 1)
+ b.right = b.x + b.w
+ b.rect = [b.x, b.y, b.w, b.h]
+ b.solids = [[b.x - 1, b.y, b.w + 2, b.h + 1, fancy_white],
+ [b.x, b.y, b.w, b.h, random_building_color],
+ windows_for_building(b.x, floors, rooms)]
+ end
+ end
+
+ def parse_or_clear! game_prop
+ if int? state.as_hash[game_prop]
+ state.as_hash[game_prop] = state.as_hash[game_prop].to_i
+ return true
+ end
+
+ state.as_hash[game_prop] = nil
+ return false
+ end
+
+ def new_banana owner, x, y, angle, velocity
+ state.new_entity(:banana) do |b|
+ b.owner = owner
+ b.x = x
+ b.y = y
+ b.angle = angle % 360
+ b.velocity = velocity / 5
+ b.dx = b.angle.vector_x(b.velocity)
+ b.dy = b.angle.vector_y(b.velocity)
+ end
+ end
+
+ def fancy_white
+ [253, 252, 253]
+ end
+end
+
+$you_so_basic_gorillas = YouSoBasicGorillas.new
+
+def tick args
+ $you_so_basic_gorillas.outputs = args.outputs
+ $you_so_basic_gorillas.grid = args.grid
+ $you_so_basic_gorillas.state = args.state
+ $you_so_basic_gorillas.inputs = args.inputs
+ $you_so_basic_gorillas.tick
+end
diff --git a/samples/99_genre_platformer/gorillas_basic/app/repl.rb b/samples/99_genre_platformer/gorillas_basic/app/repl.rb
new file mode 100644
index 0000000..4428c4b
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/app/repl.rb
@@ -0,0 +1,17 @@
+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/gorillas_basic/app/tests.rb b/samples/99_genre_platformer/gorillas_basic/app/tests.rb
new file mode 100644
index 0000000..e108574
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/app/tests.rb
@@ -0,0 +1,4 @@
+$gtk.reset 100
+$gtk.supress_framerate_warning = true
+$gtk.require 'app/tests/building_generation_tests.rb'
+$gtk.tests.start
diff --git a/samples/99_genre_platformer/gorillas_basic/app/tests/building_generation_tests.rb b/samples/99_genre_platformer/gorillas_basic/app/tests/building_generation_tests.rb
new file mode 100644
index 0000000..bbad57a
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/app/tests/building_generation_tests.rb
@@ -0,0 +1,15 @@
+def test_solids args, assert
+ game = YouSoBasicGorillas.new
+ game.outputs = args.outputs
+ game.grid = args.grid
+ game.state = args.state
+ game.inputs = args.inputs
+ game.tick
+ assert.true! args.state.stage_generated, "stage wasn't generated but it should have been"
+ game.tick
+ assert.true! args.outputs.static_solids.length > 0, "stage wasn't rendered"
+ number_of_building_components = (args.state.buildings.map { |b| 2 + b.solids[2].length }.inject do |sum, v| (sum || 0) + v end)
+ the_only_background = 1
+ static_solids = args.outputs.static_solids.length
+ assert.true! static_solids == the_only_background.+(number_of_building_components), "not all parts of the buildings and background were rendered"
+end
diff --git a/samples/99_genre_platformer/gorillas_basic/license-for-sample.txt b/samples/99_genre_platformer/gorillas_basic/license-for-sample.txt
new file mode 100644
index 0000000..8fa4d42
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/license-for-sample.txt
@@ -0,0 +1,9 @@
+Copyright 2019 DragonRuby LLC (code), Nick Culbertson @mobypixel (art)
+
+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_platformer/gorillas_basic/metadata/game_metadata.txt b/samples/99_genre_platformer/gorillas_basic/metadata/game_metadata.txt
new file mode 100644
index 0000000..38d9894
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/metadata/game_metadata.txt
@@ -0,0 +1,6 @@
+devid=dragonruby
+devtitle=DragonRuby LLC
+gameid=basicgorillas
+gametitle=Basic Gorillas
+version=1.1
+icon=sprites/left-0.png
diff --git a/samples/99_genre_platformer/gorillas_basic/replay.txt b/samples/99_genre_platformer/gorillas_basic/replay.txt
new file mode 100644
index 0000000..a1d4eab
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/replay.txt
@@ -0,0 +1,719 @@
+replay_version 2.0
+stopped_at 1814
+seed 100
+recorded_at Sun Sep 29 23:27:50 2019
+[:mouse_move, 20, 450, 2, 1, 32]
+[:mouse_move, 61, 422, 2, 2, 33]
+[:mouse_move, 64, 417, 2, 3, 34]
+[:mouse_move, 67, 413, 2, 4, 35]
+[:mouse_move, 77, 402, 2, 5, 36]
+[:mouse_move, 78, 397, 2, 6, 37]
+[:mouse_move, 79, 393, 2, 7, 38]
+[:mouse_move, 79, 392, 2, 8, 39]
+[:mouse_move, 79, 401, 2, 9, 41]
+[:mouse_move, 80, 426, 2, 10, 42]
+[:mouse_move, 85, 444, 2, 11, 43]
+[:mouse_move, 97, 477, 2, 12, 44]
+[:mouse_move, 100, 482, 2, 13, 45]
+[:mouse_move, 113, 496, 2, 14, 46]
+[:mouse_move, 118, 498, 2, 15, 47]
+[:mouse_move, 123, 499, 2, 16, 48]
+[:mouse_move, 131, 493, 2, 17, 49]
+[:mouse_move, 132, 485, 2, 18, 50]
+[:mouse_move, 133, 462, 2, 19, 51]
+[:mouse_move, 133, 448, 2, 20, 52]
+[:mouse_move, 125, 402, 2, 21, 53]
+[:mouse_move, 120, 380, 2, 22, 54]
+[:mouse_move, 106, 336, 2, 23, 55]
+[:mouse_move, 97, 310, 2, 24, 56]
+[:mouse_move, 72, 250, 2, 25, 57]
+[:mouse_move, 58, 216, 2, 26, 58]
+[:mouse_move, 48, 188, 2, 27, 59]
+[:mouse_move, 39, 166, 2, 28, 60]
+[:mouse_move, 35, 156, 2, 29, 61]
+[:mouse_move, 33, 150, 2, 30, 62]
+[:mouse_move, 33, 145, 2, 31, 75]
+[:mouse_move, 33, 128, 2, 32, 76]
+[:mouse_move, 33, 119, 2, 33, 77]
+[:mouse_move, 33, 106, 2, 34, 78]
+[:mouse_move, 33, 101, 2, 35, 79]
+[:mouse_move, 33, 90, 2, 36, 80]
+[:mouse_move, 33, 83, 2, 37, 81]
+[:mouse_move, 31, 74, 2, 38, 82]
+[:mouse_move, 29, 68, 2, 39, 83]
+[:mouse_move, 26, 60, 2, 40, 84]
+[:mouse_move, 25, 59, 2, 41, 85]
+[:mouse_move, 23, 53, 2, 42, 86]
+[:mouse_move, 22, 51, 2, 43, 87]
+[:mouse_move, 21, 50, 2, 44, 88]
+[:mouse_move, 21, 49, 2, 45, 89]
+[:mouse_move, 19, 48, 2, 46, 90]
+[:mouse_move, 15, 46, 2, 47, 92]
+[:mouse_move, 12, 44, 2, 48, 93]
+[:mouse_move, 11, 43, 2, 49, 94]
+[:mouse_move, 9, 42, 2, 50, 95]
+[:mouse_move, 9, 41, 2, 51, 96]
+[:mouse_move, 8, 41, 2, 52, 97]
+[:mouse_move, 9, 41, 2, 53, 104]
+[:mouse_move, 12, 42, 2, 54, 105]
+[:mouse_move, 17, 44, 2, 55, 106]
+[:mouse_move, 21, 44, 2, 56, 107]
+[:mouse_move, 25, 45, 2, 57, 108]
+[:mouse_move, 34, 46, 2, 58, 109]
+[:mouse_move, 43, 46, 2, 59, 110]
+[:mouse_move, 48, 47, 2, 60, 111]
+[:mouse_move, 53, 47, 2, 61, 112]
+[:mouse_move, 61, 48, 2, 62, 113]
+[:mouse_move, 66, 48, 2, 63, 114]
+[:mouse_move, 74, 49, 2, 64, 115]
+[:mouse_move, 84, 51, 2, 65, 116]
+[:mouse_move, 88, 51, 2, 66, 117]
+[:mouse_move, 95, 52, 2, 67, 118]
+[:mouse_move, 98, 52, 2, 68, 119]
+[:mouse_move, 104, 52, 2, 69, 120]
+[:mouse_move, 108, 52, 2, 70, 121]
+[:mouse_move, 111, 52, 2, 71, 122]
+[:mouse_move, 115, 51, 2, 72, 123]
+[:mouse_move, 116, 50, 2, 73, 124]
+[:mouse_move, 118, 49, 2, 74, 125]
+[:mouse_move, 119, 49, 2, 75, 126]
+[:mouse_move, 120, 49, 2, 76, 127]
+[:mouse_move, 121, 48, 2, 77, 128]
+[:mouse_move, 122, 48, 2, 78, 130]
+[:mouse_move, 123, 48, 2, 79, 132]
+[:mouse_move, 124, 48, 2, 80, 133]
+[:mouse_move, 125, 48, 2, 81, 136]
+[:mouse_move, 125, 49, 2, 82, 141]
+[:mouse_move, 115, 67, 2, 83, 152]
+[:mouse_move, 109, 101, 2, 84, 153]
+[:mouse_move, 93, 189, 2, 85, 154]
+[:mouse_move, 81, 254, 2, 86, 155]
+[:mouse_move, 67, 327, 2, 87, 156]
+[:mouse_move, 40, 469, 2, 88, 157]
+[:mouse_move, 35, 496, 2, 89, 158]
+[:mouse_move, 24, 556, 2, 90, 159]
+[:mouse_move, 23, 566, 2, 91, 160]
+[:mouse_move, 20, 586, 2, 92, 161]
+[:mouse_move, 19, 595, 2, 93, 162]
+[:mouse_move, 18, 603, 2, 94, 163]
+[:mouse_move, 18, 605, 2, 95, 164]
+[:mouse_move, 18, 606, 2, 96, 165]
+[:mouse_move, 19, 606, 2, 97, 166]
+[:mouse_move, 20, 606, 2, 98, 168]
+[:mouse_move, 21, 606, 2, 99, 169]
+[:mouse_move, 21, 607, 2, 100, 170]
+[:mouse_move, 24, 608, 2, 101, 171]
+[:mouse_move, 27, 609, 2, 102, 172]
+[:mouse_move, 37, 616, 2, 103, 173]
+[:mouse_move, 45, 621, 2, 104, 174]
+[:mouse_move, 67, 631, 2, 105, 175]
+[:mouse_move, 81, 636, 2, 106, 176]
+[:mouse_move, 114, 645, 2, 107, 177]
+[:mouse_move, 129, 647, 2, 108, 178]
+[:mouse_move, 151, 646, 2, 109, 179]
+[:mouse_move, 176, 635, 2, 110, 180]
+[:mouse_move, 179, 630, 2, 111, 181]
+[:mouse_move, 190, 605, 2, 112, 182]
+[:mouse_move, 193, 582, 2, 113, 183]
+[:mouse_move, 193, 572, 2, 114, 184]
+[:mouse_move, 193, 556, 2, 115, 185]
+[:mouse_move, 190, 535, 2, 116, 186]
+[:mouse_move, 187, 523, 2, 117, 187]
+[:mouse_move, 179, 509, 2, 118, 188]
+[:mouse_move, 172, 502, 2, 119, 189]
+[:mouse_move, 159, 500, 2, 120, 190]
+[:mouse_move, 152, 500, 2, 121, 191]
+[:mouse_move, 142, 507, 2, 122, 192]
+[:mouse_move, 137, 513, 2, 123, 193]
+[:mouse_move, 129, 527, 2, 124, 194]
+[:mouse_move, 125, 540, 2, 125, 195]
+[:mouse_move, 125, 558, 2, 126, 196]
+[:mouse_move, 127, 566, 2, 127, 197]
+[:mouse_move, 135, 578, 2, 128, 198]
+[:mouse_move, 144, 590, 2, 129, 199]
+[:mouse_move, 159, 597, 2, 130, 200]
+[:mouse_move, 171, 599, 2, 131, 201]
+[:mouse_move, 179, 599, 2, 132, 202]
+[:mouse_move, 185, 599, 2, 133, 203]
+[:mouse_move, 200, 590, 2, 134, 204]
+[:mouse_move, 206, 579, 2, 135, 205]
+[:mouse_move, 206, 565, 2, 136, 206]
+[:mouse_move, 206, 558, 2, 137, 207]
+[:mouse_move, 197, 541, 2, 138, 208]
+[:mouse_move, 191, 537, 2, 139, 209]
+[:mouse_move, 183, 535, 2, 140, 210]
+[:mouse_move, 166, 535, 2, 141, 211]
+[:mouse_move, 155, 541, 2, 142, 212]
+[:mouse_move, 133, 569, 2, 143, 213]
+[:mouse_move, 127, 585, 2, 144, 214]
+[:mouse_move, 127, 602, 2, 145, 215]
+[:mouse_move, 132, 626, 2, 146, 216]
+[:mouse_move, 138, 630, 2, 147, 217]
+[:mouse_move, 144, 631, 2, 148, 218]
+[:mouse_move, 162, 627, 2, 149, 219]
+[:mouse_move, 180, 609, 2, 150, 220]
+[:mouse_move, 212, 530, 2, 151, 221]
+[:mouse_move, 221, 476, 2, 152, 222]
+[:mouse_move, 227, 388, 2, 153, 223]
+[:mouse_move, 227, 336, 2, 154, 224]
+[:mouse_move, 219, 256, 2, 155, 225]
+[:mouse_move, 209, 225, 2, 156, 226]
+[:mouse_move, 183, 173, 2, 157, 227]
+[:mouse_move, 175, 163, 2, 158, 228]
+[:mouse_move, 161, 140, 2, 159, 229]
+[:mouse_move, 158, 136, 2, 160, 230]
+[:mouse_move, 147, 121, 2, 161, 231]
+[:mouse_move, 144, 116, 2, 162, 232]
+[:mouse_move, 138, 107, 2, 163, 233]
+[:mouse_move, 136, 104, 2, 164, 234]
+[:mouse_move, 132, 99, 2, 165, 235]
+[:mouse_move, 130, 96, 2, 166, 236]
+[:mouse_move, 128, 95, 2, 167, 237]
+[:mouse_move, 124, 90, 2, 168, 238]
+[:mouse_move, 122, 89, 2, 169, 239]
+[:mouse_move, 120, 87, 2, 170, 240]
+[:mouse_move, 119, 86, 2, 171, 241]
+[:mouse_move, 117, 86, 2, 172, 242]
+[:mouse_move, 117, 85, 2, 173, 243]
+[:mouse_move, 114, 84, 2, 174, 244]
+[:mouse_move, 112, 83, 2, 175, 245]
+[:mouse_move, 109, 82, 2, 176, 246]
+[:key_down_raw, 56, 0, 2, 177, 299]
+[:key_up_raw, 56, 0, 2, 178, 304]
+[:key_down_raw, 48, 0, 2, 179, 309]
+[:key_up_raw, 48, 0, 2, 180, 314]
+[:key_down_raw, 13, 0, 2, 181, 346]
+[:key_up_raw, 13, 0, 2, 182, 353]
+[:key_down_raw, 49, 0, 2, 183, 390]
+[:key_up_raw, 49, 0, 2, 184, 393]
+[:key_down_raw, 49, 0, 2, 185, 398]
+[:key_up_raw, 49, 0, 2, 186, 404]
+[:key_down_raw, 53, 0, 2, 187, 410]
+[:key_up_raw, 53, 0, 2, 188, 415]
+[:key_down_raw, 13, 0, 2, 189, 478]
+[:key_up_raw, 13, 0, 2, 190, 484]
+[:mouse_move, 128, 84, 2, 191, 539]
+[:mouse_move, 153, 89, 2, 192, 540]
+[:mouse_move, 181, 97, 2, 193, 541]
+[:mouse_move, 216, 107, 2, 194, 542]
+[:mouse_move, 292, 129, 2, 195, 543]
+[:mouse_move, 367, 151, 2, 196, 544]
+[:mouse_move, 465, 178, 2, 197, 545]
+[:mouse_move, 520, 193, 2, 198, 546]
+[:mouse_move, 572, 207, 2, 199, 547]
+[:mouse_move, 581, 209, 2, 200, 548]
+[:mouse_move, 600, 215, 2, 201, 549]
+[:mouse_move, 607, 217, 2, 202, 550]
+[:mouse_move, 614, 220, 2, 203, 551]
+[:mouse_move, 614, 221, 2, 204, 684]
+[:mouse_move, 617, 223, 2, 205, 686]
+[:mouse_move, 619, 224, 2, 206, 687]
+[:mouse_move, 629, 230, 2, 207, 688]
+[:mouse_move, 641, 234, 2, 208, 689]
+[:mouse_move, 676, 242, 2, 209, 690]
+[:mouse_move, 718, 248, 2, 210, 691]
+[:mouse_move, 797, 251, 2, 211, 692]
+[:mouse_move, 817, 251, 2, 212, 693]
+[:mouse_move, 888, 236, 2, 213, 694]
+[:mouse_move, 916, 224, 2, 214, 695]
+[:mouse_move, 933, 210, 2, 215, 696]
+[:mouse_move, 957, 191, 2, 216, 697]
+[:mouse_move, 960, 189, 2, 217, 713]
+[:mouse_move, 965, 186, 2, 218, 714]
+[:mouse_move, 975, 180, 2, 219, 715]
+[:mouse_move, 988, 174, 2, 220, 716]
+[:mouse_move, 1021, 161, 2, 221, 717]
+[:mouse_move, 1051, 148, 2, 222, 718]
+[:mouse_move, 1079, 136, 2, 223, 719]
+[:mouse_move, 1096, 127, 2, 224, 720]
+[:mouse_move, 1126, 109, 2, 225, 721]
+[:mouse_move, 1131, 106, 2, 226, 722]
+[:mouse_move, 1149, 90, 2, 227, 723]
+[:mouse_move, 1155, 85, 2, 228, 724]
+[:mouse_move, 1161, 79, 2, 229, 725]
+[:mouse_move, 1164, 76, 2, 230, 726]
+[:mouse_move, 1166, 75, 2, 231, 727]
+[:mouse_move, 1168, 73, 2, 232, 728]
+[:mouse_move, 1169, 72, 2, 233, 729]
+[:mouse_move, 1171, 71, 2, 234, 730]
+[:mouse_move, 1172, 71, 2, 235, 731]
+[:mouse_move, 1172, 70, 2, 236, 733]
+[:mouse_move, 1173, 70, 2, 237, 734]
+[:mouse_move, 1173, 69, 2, 238, 741]
+[:mouse_move, 1175, 67, 2, 239, 742]
+[:mouse_move, 1177, 64, 2, 240, 743]
+[:mouse_move, 1183, 58, 2, 241, 744]
+[:mouse_move, 1187, 53, 2, 242, 745]
+[:mouse_move, 1195, 44, 2, 243, 746]
+[:mouse_move, 1197, 42, 2, 244, 747]
+[:mouse_move, 1202, 37, 2, 245, 748]
+[:mouse_move, 1204, 35, 2, 246, 749]
+[:mouse_move, 1205, 34, 2, 247, 750]
+[:mouse_move, 1205, 33, 2, 248, 751]
+[:mouse_move, 1199, 33, 2, 249, 752]
+[:mouse_move, 1185, 33, 2, 250, 753]
+[:mouse_move, 1168, 33, 2, 251, 754]
+[:mouse_move, 1123, 34, 2, 252, 755]
+[:mouse_move, 1096, 35, 2, 253, 756]
+[:mouse_move, 1074, 37, 2, 254, 757]
+[:mouse_move, 1057, 37, 2, 255, 758]
+[:mouse_move, 1043, 39, 2, 256, 759]
+[:mouse_move, 1037, 39, 2, 257, 760]
+[:mouse_move, 1031, 40, 2, 258, 761]
+[:mouse_move, 1030, 40, 2, 259, 762]
+[:mouse_move, 1029, 41, 2, 260, 763]
+[:mouse_move, 1029, 44, 2, 261, 764]
+[:mouse_move, 1033, 56, 2, 262, 765]
+[:mouse_move, 1044, 72, 2, 263, 766]
+[:mouse_move, 1064, 90, 2, 264, 767]
+[:mouse_move, 1078, 100, 2, 265, 768]
+[:mouse_move, 1109, 113, 2, 266, 769]
+[:mouse_move, 1125, 113, 2, 267, 770]
+[:mouse_move, 1154, 107, 2, 268, 771]
+[:mouse_move, 1168, 98, 2, 269, 772]
+[:mouse_move, 1184, 83, 2, 270, 773]
+[:mouse_move, 1194, 74, 2, 271, 774]
+[:mouse_move, 1202, 65, 2, 272, 775]
+[:mouse_move, 1206, 59, 2, 273, 776]
+[:mouse_move, 1210, 49, 2, 274, 777]
+[:mouse_move, 1210, 44, 2, 275, 778]
+[:mouse_move, 1203, 38, 2, 276, 779]
+[:mouse_move, 1198, 36, 2, 277, 780]
+[:mouse_move, 1191, 32, 2, 278, 781]
+[:mouse_move, 1178, 27, 2, 279, 782]
+[:mouse_move, 1172, 24, 2, 280, 783]
+[:mouse_move, 1160, 20, 2, 281, 784]
+[:mouse_move, 1154, 18, 2, 282, 785]
+[:mouse_move, 1141, 18, 2, 283, 786]
+[:mouse_move, 1133, 18, 2, 284, 787]
+[:mouse_move, 1117, 23, 2, 285, 788]
+[:mouse_move, 1110, 28, 2, 286, 789]
+[:mouse_move, 1099, 44, 2, 287, 790]
+[:mouse_move, 1097, 49, 2, 288, 791]
+[:mouse_move, 1093, 59, 2, 289, 792]
+[:mouse_move, 1091, 65, 2, 290, 793]
+[:mouse_move, 1091, 79, 2, 291, 794]
+[:mouse_move, 1095, 82, 2, 292, 795]
+[:mouse_move, 1121, 91, 2, 293, 796]
+[:mouse_move, 1140, 93, 2, 294, 797]
+[:mouse_move, 1172, 97, 2, 295, 798]
+[:mouse_move, 1194, 97, 2, 296, 799]
+[:mouse_move, 1230, 89, 2, 297, 800]
+[:mouse_move, 1237, 84, 2, 298, 801]
+[:mouse_move, 1255, 69, 2, 299, 802]
+[:mouse_move, 1260, 63, 2, 300, 803]
+[:mouse_move, 1264, 44, 2, 301, 804]
+[:mouse_move, 1262, 36, 2, 302, 805]
+[:mouse_move, 1246, 19, 2, 303, 806]
+[:mouse_move, 1235, 12, 2, 304, 807]
+[:mouse_move, 1210, 1, 2, 305, 808]
+[:mouse_move, 1197, 0, 2, 306, 809]
+[:mouse_move, 1153, 0, 2, 307, 812]
+[:mouse_move, 1143, 4, 2, 308, 812]
+[:mouse_move, 1134, 11, 2, 309, 813]
+[:mouse_move, 1126, 19, 2, 310, 814]
+[:mouse_move, 1117, 30, 2, 311, 814]
+[:mouse_move, 1109, 42, 2, 312, 815]
+[:mouse_move, 1101, 56, 2, 313, 816]
+[:mouse_move, 1094, 71, 2, 314, 816]
+[:mouse_move, 1088, 85, 2, 315, 817]
+[:mouse_move, 1085, 98, 2, 316, 818]
+[:mouse_move, 1083, 125, 2, 317, 819]
+[:mouse_move, 1082, 126, 2, 318, 831]
+[:mouse_move, 1074, 136, 2, 319, 832]
+[:mouse_move, 1049, 174, 2, 320, 833]
+[:mouse_move, 1023, 217, 2, 321, 834]
+[:mouse_move, 958, 326, 2, 322, 835]
+[:mouse_move, 945, 350, 2, 323, 836]
+[:mouse_move, 918, 398, 2, 324, 837]
+[:mouse_move, 894, 443, 2, 325, 838]
+[:mouse_move, 890, 451, 2, 326, 839]
+[:mouse_move, 878, 481, 2, 327, 840]
+[:mouse_move, 877, 490, 2, 328, 841]
+[:mouse_move, 877, 497, 2, 329, 842]
+[:mouse_move, 880, 499, 2, 330, 843]
+[:mouse_move, 886, 500, 2, 331, 844]
+[:mouse_move, 888, 500, 2, 332, 845]
+[:mouse_move, 892, 498, 2, 333, 846]
+[:mouse_move, 894, 498, 2, 334, 847]
+[:mouse_move, 903, 498, 2, 335, 848]
+[:mouse_move, 909, 506, 2, 336, 849]
+[:mouse_move, 923, 524, 2, 337, 850]
+[:mouse_move, 934, 534, 2, 338, 851]
+[:mouse_move, 958, 551, 2, 339, 852]
+[:mouse_move, 970, 555, 2, 340, 853]
+[:mouse_move, 995, 555, 2, 341, 854]
+[:mouse_move, 1007, 551, 2, 342, 855]
+[:mouse_move, 1036, 525, 2, 343, 856]
+[:mouse_move, 1039, 515, 2, 344, 857]
+[:mouse_move, 1052, 467, 2, 345, 858]
+[:mouse_move, 1052, 456, 2, 346, 859]
+[:mouse_move, 1049, 426, 2, 347, 860]
+[:mouse_move, 1041, 415, 2, 348, 861]
+[:mouse_move, 1017, 399, 2, 349, 862]
+[:mouse_move, 994, 394, 2, 350, 863]
+[:mouse_move, 984, 394, 2, 351, 864]
+[:mouse_move, 954, 403, 2, 352, 865]
+[:mouse_move, 937, 413, 2, 353, 866]
+[:mouse_move, 903, 453, 2, 354, 867]
+[:mouse_move, 897, 472, 2, 355, 868]
+[:mouse_move, 893, 501, 2, 356, 869]
+[:mouse_move, 893, 520, 2, 357, 870]
+[:mouse_move, 901, 547, 2, 358, 871]
+[:mouse_move, 909, 557, 2, 359, 872]
+[:mouse_move, 929, 567, 2, 360, 873]
+[:mouse_move, 943, 569, 2, 361, 874]
+[:mouse_move, 982, 565, 2, 362, 875]
+[:mouse_move, 990, 560, 2, 363, 876]
+[:mouse_move, 1034, 532, 2, 364, 877]
+[:mouse_move, 1039, 524, 2, 365, 878]
+[:mouse_move, 1073, 474, 2, 366, 879]
+[:mouse_move, 1088, 424, 2, 367, 880]
+[:mouse_move, 1094, 334, 2, 368, 881]
+[:mouse_move, 1095, 309, 2, 369, 882]
+[:mouse_move, 1098, 220, 2, 370, 883]
+[:mouse_move, 1103, 182, 2, 371, 884]
+[:mouse_move, 1115, 135, 2, 372, 885]
+[:mouse_move, 1124, 111, 2, 373, 886]
+[:mouse_move, 1136, 83, 2, 374, 887]
+[:mouse_move, 1144, 70, 2, 375, 888]
+[:mouse_move, 1151, 58, 2, 376, 889]
+[:mouse_move, 1154, 52, 2, 377, 890]
+[:mouse_move, 1158, 48, 2, 378, 891]
+[:mouse_move, 1161, 43, 2, 379, 892]
+[:mouse_move, 1162, 41, 2, 380, 893]
+[:mouse_move, 1164, 39, 2, 381, 894]
+[:mouse_move, 1165, 38, 2, 382, 895]
+[:mouse_move, 1166, 37, 2, 383, 896]
+[:mouse_move, 1167, 36, 2, 384, 897]
+[:mouse_move, 1167, 35, 2, 385, 898]
+[:mouse_move, 1168, 35, 2, 386, 899]
+[:mouse_move, 1169, 35, 2, 387, 900]
+[:key_down_raw, 56, 0, 2, 388, 940]
+[:key_up_raw, 56, 0, 2, 389, 945]
+[:key_down_raw, 48, 0, 2, 390, 952]
+[:key_up_raw, 48, 0, 2, 391, 957]
+[:key_down_raw, 13, 0, 2, 392, 1001]
+[:key_up_raw, 13, 0, 2, 393, 1006]
+[:key_down_raw, 49, 0, 2, 394, 1030]
+[:key_up_raw, 49, 0, 2, 395, 1035]
+[:key_down_raw, 49, 0, 2, 396, 1041]
+[:key_up_raw, 49, 0, 2, 397, 1045]
+[:key_down_raw, 53, 0, 2, 398, 1098]
+[:key_up_raw, 53, 0, 2, 399, 1101]
+[:mouse_move, 1193, 38, 2, 400, 1121]
+[:mouse_move, 1236, 52, 2, 401, 1122]
+[:mouse_move, 1279, 63, 2, 402, 1123]
+[:mouse_move, 1279, 69, 2, 403, 1124]
+[:mouse_move, 1277, 36, 2, 404, 1134]
+[:mouse_move, 1271, 36, 2, 405, 1135]
+[:mouse_move, 1259, 35, 2, 406, 1136]
+[:mouse_move, 1250, 35, 2, 407, 1136]
+[:mouse_move, 1242, 35, 2, 408, 1137]
+[:mouse_move, 1239, 35, 2, 409, 1138]
+[:mouse_move, 1230, 36, 2, 410, 1138]
+[:mouse_move, 1225, 37, 2, 411, 1139]
+[:mouse_move, 1222, 38, 2, 412, 1140]
+[:mouse_move, 1220, 38, 2, 413, 1140]
+[:mouse_move, 1217, 38, 2, 414, 1141]
+[:mouse_move, 1215, 39, 2, 415, 1142]
+[:mouse_move, 1213, 39, 2, 416, 1142]
+[:mouse_move, 1211, 39, 2, 417, 1143]
+[:mouse_move, 1210, 40, 2, 418, 1144]
+[:mouse_move, 1208, 41, 2, 419, 1145]
+[:mouse_move, 1207, 42, 2, 420, 1146]
+[:mouse_move, 1206, 44, 2, 421, 1147]
+[:mouse_move, 1205, 44, 2, 422, 1148]
+[:mouse_move, 1204, 47, 2, 423, 1149]
+[:mouse_move, 1203, 49, 2, 424, 1150]
+[:mouse_move, 1202, 51, 2, 425, 1151]
+[:mouse_move, 1202, 52, 2, 426, 1152]
+[:mouse_move, 1202, 53, 2, 427, 1153]
+[:mouse_move, 1202, 54, 2, 428, 1154]
+[:mouse_move, 1207, 54, 2, 429, 1155]
+[:mouse_move, 1212, 55, 2, 430, 1156]
+[:mouse_move, 1223, 56, 2, 431, 1157]
+[:mouse_move, 1229, 57, 2, 432, 1158]
+[:mouse_move, 1236, 57, 2, 433, 1159]
+[:mouse_move, 1240, 57, 2, 434, 1160]
+[:mouse_move, 1245, 57, 2, 435, 1161]
+[:mouse_move, 1247, 57, 2, 436, 1162]
+[:mouse_move, 1249, 57, 2, 437, 1163]
+[:mouse_move, 1250, 57, 2, 438, 1163]
+[:mouse_move, 1251, 57, 2, 439, 1164]
+[:mouse_move, 1252, 57, 2, 440, 1165]
+[:mouse_move, 1253, 57, 2, 441, 1165]
+[:mouse_move, 1254, 57, 2, 442, 1166]
+[:mouse_move, 1255, 57, 2, 443, 1167]
+[:mouse_move, 1256, 57, 2, 444, 1168]
+[:mouse_move, 1257, 57, 2, 445, 1169]
+[:mouse_move, 1258, 57, 2, 446, 1171]
+[:mouse_move, 1259, 57, 2, 447, 1171]
+[:mouse_move, 1260, 57, 2, 448, 1173]
+[:mouse_move, 1259, 57, 2, 449, 1177]
+[:mouse_move, 1251, 56, 2, 450, 1178]
+[:mouse_move, 1244, 56, 2, 451, 1179]
+[:mouse_move, 1234, 56, 2, 452, 1180]
+[:mouse_move, 1231, 56, 2, 453, 1181]
+[:mouse_move, 1223, 56, 2, 454, 1182]
+[:mouse_move, 1220, 56, 2, 455, 1183]
+[:mouse_move, 1217, 57, 2, 456, 1184]
+[:mouse_move, 1219, 57, 2, 457, 1187]
+[:mouse_move, 1227, 58, 2, 458, 1188]
+[:mouse_move, 1231, 59, 2, 459, 1189]
+[:mouse_move, 1233, 59, 2, 460, 1190]
+[:mouse_move, 1236, 59, 2, 461, 1190]
+[:mouse_move, 1239, 59, 2, 462, 1191]
+[:mouse_move, 1240, 60, 2, 463, 1192]
+[:mouse_move, 1241, 60, 2, 464, 1192]
+[:mouse_move, 1242, 60, 2, 465, 1193]
+[:mouse_move, 1232, 65, 2, 466, 1205]
+[:mouse_move, 1219, 74, 2, 467, 1206]
+[:mouse_move, 1163, 105, 2, 468, 1207]
+[:mouse_move, 1078, 154, 2, 469, 1208]
+[:mouse_move, 931, 239, 2, 470, 1209]
+[:mouse_move, 896, 263, 2, 471, 1210]
+[:mouse_move, 763, 366, 2, 472, 1211]
+[:mouse_move, 742, 388, 2, 473, 1212]
+[:mouse_move, 667, 471, 2, 474, 1213]
+[:mouse_move, 642, 509, 2, 475, 1214]
+[:mouse_move, 613, 575, 2, 476, 1215]
+[:mouse_move, 611, 588, 2, 477, 1216]
+[:mouse_move, 588, 612, 2, 478, 1230]
+[:mouse_move, 577, 624, 2, 479, 1231]
+[:mouse_move, 532, 667, 2, 480, 1232]
+[:mouse_move, 523, 676, 2, 481, 1233]
+[:mouse_move, 516, 682, 2, 482, 1234]
+[:mouse_move, 511, 686, 2, 483, 1235]
+[:mouse_move, 492, 703, 2, 484, 1236]
+[:mouse_move, 490, 705, 2, 485, 1237]
+[:mouse_move, 489, 706, 2, 486, 1238]
+[:mouse_move, 488, 706, 2, 487, 1239]
+[:mouse_move, 488, 707, 2, 488, 1240]
+[:mouse_move, 488, 708, 2, 489, 1246]
+[:mouse_move, 487, 709, 2, 490, 1247]
+[:mouse_move, 487, 710, 2, 491, 1248]
+[:mouse_move, 488, 710, 2, 492, 1252]
+[:mouse_move, 489, 710, 2, 493, 1252]
+[:mouse_move, 490, 710, 2, 494, 1253]
+[:mouse_move, 492, 709, 2, 495, 1253]
+[:mouse_move, 495, 709, 2, 496, 1254]
+[:mouse_move, 499, 708, 2, 497, 1255]
+[:mouse_move, 501, 708, 2, 498, 1256]
+[:mouse_move, 504, 707, 2, 499, 1257]
+[:mouse_move, 507, 707, 2, 500, 1258]
+[:mouse_move, 509, 707, 2, 501, 1259]
+[:mouse_move, 511, 707, 2, 502, 1260]
+[:mouse_move, 513, 707, 2, 503, 1261]
+[:mouse_move, 515, 707, 2, 504, 1262]
+[:mouse_move, 516, 708, 2, 505, 1263]
+[:mouse_move, 518, 708, 2, 506, 1264]
+[:mouse_move, 520, 708, 2, 507, 1265]
+[:mouse_move, 521, 708, 2, 508, 1266]
+[:mouse_move, 523, 708, 2, 509, 1267]
+[:mouse_move, 525, 708, 2, 510, 1268]
+[:mouse_move, 526, 709, 2, 511, 1269]
+[:mouse_move, 527, 709, 2, 512, 1269]
+[:mouse_move, 528, 709, 2, 513, 1270]
+[:mouse_move, 529, 710, 2, 514, 1271]
+[:mouse_move, 530, 710, 2, 515, 1272]
+[:mouse_move, 531, 711, 2, 516, 1274]
+[:mouse_move, 532, 711, 2, 517, 1275]
+[:mouse_move, 533, 711, 2, 518, 1275]
+[:mouse_move, 536, 712, 2, 519, 1276]
+[:mouse_move, 540, 713, 2, 520, 1278]
+[:mouse_move, 541, 714, 2, 521, 1279]
+[:mouse_move, 543, 714, 2, 522, 1279]
+[:mouse_move, 544, 715, 2, 523, 1280]
+[:mouse_move, 546, 715, 2, 524, 1281]
+[:mouse_move, 548, 715, 2, 525, 1281]
+[:mouse_move, 550, 716, 2, 526, 1282]
+[:mouse_move, 551, 716, 2, 527, 1283]
+[:mouse_move, 555, 716, 2, 528, 1284]
+[:mouse_move, 557, 716, 2, 529, 1285]
+[:mouse_move, 561, 716, 2, 530, 1286]
+[:mouse_move, 563, 716, 2, 531, 1287]
+[:mouse_move, 567, 716, 2, 532, 1288]
+[:mouse_move, 569, 715, 2, 533, 1289]
+[:mouse_move, 572, 715, 2, 534, 1290]
+[:mouse_move, 575, 714, 2, 535, 1291]
+[:mouse_move, 578, 714, 2, 536, 1292]
+[:mouse_move, 580, 714, 2, 537, 1293]
+[:mouse_move, 585, 714, 2, 538, 1294]
+[:mouse_move, 586, 714, 2, 539, 1295]
+[:mouse_move, 588, 714, 2, 540, 1296]
+[:mouse_move, 591, 714, 2, 541, 1296]
+[:mouse_move, 594, 714, 2, 542, 1297]
+[:mouse_move, 596, 714, 2, 543, 1298]
+[:mouse_move, 598, 714, 2, 544, 1298]
+[:mouse_move, 600, 714, 2, 545, 1299]
+[:mouse_move, 602, 714, 2, 546, 1300]
+[:mouse_move, 606, 714, 2, 547, 1300]
+[:mouse_move, 607, 714, 2, 548, 1301]
+[:mouse_move, 611, 714, 2, 549, 1302]
+[:mouse_move, 614, 715, 2, 550, 1302]
+[:mouse_move, 615, 715, 2, 551, 1303]
+[:mouse_move, 619, 716, 2, 552, 1304]
+[:mouse_move, 622, 716, 2, 553, 1304]
+[:mouse_move, 623, 716, 2, 554, 1305]
+[:mouse_move, 628, 717, 2, 555, 1306]
+[:mouse_move, 631, 717, 2, 556, 1306]
+[:mouse_move, 634, 717, 2, 557, 1307]
+[:mouse_move, 637, 717, 2, 558, 1308]
+[:mouse_move, 641, 717, 2, 559, 1308]
+[:mouse_move, 643, 717, 2, 560, 1309]
+[:mouse_move, 647, 717, 2, 561, 1310]
+[:mouse_move, 652, 716, 2, 562, 1311]
+[:mouse_move, 656, 715, 2, 563, 1312]
+[:mouse_move, 660, 713, 2, 564, 1313]
+[:mouse_move, 663, 712, 2, 565, 1314]
+[:mouse_move, 667, 710, 2, 566, 1315]
+[:mouse_move, 669, 709, 2, 567, 1316]
+[:mouse_move, 670, 706, 2, 568, 1317]
+[:mouse_move, 670, 705, 2, 569, 1318]
+[:mouse_move, 669, 702, 2, 570, 1319]
+[:mouse_move, 666, 700, 2, 571, 1320]
+[:mouse_move, 660, 696, 2, 572, 1321]
+[:mouse_move, 656, 695, 2, 573, 1322]
+[:mouse_move, 643, 691, 2, 574, 1323]
+[:mouse_move, 637, 691, 2, 575, 1324]
+[:mouse_move, 628, 690, 2, 576, 1325]
+[:mouse_move, 617, 690, 2, 577, 1325]
+[:mouse_move, 606, 690, 2, 578, 1326]
+[:mouse_move, 596, 690, 2, 579, 1327]
+[:mouse_move, 590, 690, 2, 580, 1327]
+[:mouse_move, 579, 690, 2, 581, 1328]
+[:mouse_move, 569, 691, 2, 582, 1329]
+[:mouse_move, 561, 692, 2, 583, 1329]
+[:mouse_move, 554, 693, 2, 584, 1330]
+[:mouse_move, 546, 693, 2, 585, 1331]
+[:mouse_move, 539, 694, 2, 586, 1331]
+[:mouse_move, 533, 694, 2, 587, 1332]
+[:mouse_move, 527, 695, 2, 588, 1333]
+[:mouse_move, 522, 695, 2, 589, 1333]
+[:mouse_move, 520, 696, 2, 590, 1334]
+[:mouse_move, 516, 696, 2, 591, 1335]
+[:mouse_move, 513, 697, 2, 592, 1335]
+[:mouse_move, 509, 697, 2, 593, 1336]
+[:mouse_move, 507, 698, 2, 594, 1337]
+[:mouse_move, 502, 698, 2, 595, 1338]
+[:mouse_move, 501, 698, 2, 596, 1339]
+[:mouse_move, 500, 699, 2, 597, 1340]
+[:mouse_move, 499, 699, 2, 598, 1341]
+[:mouse_move, 498, 699, 2, 599, 1342]
+[:mouse_move, 498, 700, 2, 600, 1343]
+[:mouse_move, 498, 701, 2, 601, 1344]
+[:mouse_move, 498, 702, 2, 602, 1345]
+[:mouse_move, 503, 704, 2, 603, 1346]
+[:mouse_move, 506, 705, 2, 604, 1347]
+[:mouse_move, 516, 707, 2, 605, 1348]
+[:mouse_move, 521, 708, 2, 606, 1349]
+[:mouse_move, 533, 709, 2, 607, 1350]
+[:mouse_move, 540, 709, 2, 608, 1351]
+[:mouse_move, 555, 710, 2, 609, 1352]
+[:mouse_move, 567, 710, 2, 610, 1353]
+[:mouse_move, 574, 710, 2, 611, 1354]
+[:mouse_move, 583, 710, 2, 612, 1354]
+[:mouse_move, 588, 710, 2, 613, 1355]
+[:mouse_move, 603, 708, 2, 614, 1356]
+[:mouse_move, 611, 707, 2, 615, 1356]
+[:mouse_move, 621, 703, 2, 616, 1357]
+[:mouse_move, 631, 699, 2, 617, 1358]
+[:mouse_move, 642, 694, 2, 618, 1358]
+[:mouse_move, 653, 686, 2, 619, 1359]
+[:mouse_move, 665, 677, 2, 620, 1360]
+[:mouse_move, 686, 659, 2, 621, 1360]
+[:mouse_move, 700, 643, 2, 622, 1361]
+[:mouse_move, 717, 622, 2, 623, 1362]
+[:mouse_move, 765, 543, 2, 624, 1363]
+[:mouse_move, 785, 502, 2, 625, 1364]
+[:mouse_move, 816, 431, 2, 626, 1365]
+[:mouse_move, 835, 388, 2, 627, 1366]
+[:mouse_move, 869, 313, 2, 628, 1367]
+[:mouse_move, 875, 301, 2, 629, 1368]
+[:mouse_move, 906, 233, 2, 630, 1369]
+[:mouse_move, 916, 209, 2, 631, 1370]
+[:mouse_move, 948, 131, 2, 632, 1371]
+[:mouse_move, 962, 87, 2, 633, 1372]
+[:mouse_move, 973, 47, 2, 634, 1373]
+[:mouse_move, 975, 38, 2, 635, 1374]
+[:mouse_move, 979, 9, 2, 636, 1375]
+[:mouse_move, 978, 9, 2, 637, 1391]
+[:mouse_move, 968, 25, 2, 638, 1392]
+[:mouse_move, 959, 37, 2, 639, 1393]
+[:mouse_move, 942, 67, 2, 640, 1394]
+[:mouse_move, 934, 84, 2, 641, 1395]
+[:mouse_move, 912, 130, 2, 642, 1396]
+[:mouse_move, 902, 157, 2, 643, 1397]
+[:mouse_move, 891, 190, 2, 644, 1398]
+[:key_down_raw, 13, 0, 2, 645, 1443]
+[:key_up_raw, 13, 0, 2, 646, 1448]
+[:mouse_move, 890, 190, 2, 647, 1681]
+[:mouse_move, 889, 190, 2, 648, 1682]
+[:mouse_move, 887, 190, 2, 649, 1682]
+[:mouse_move, 884, 191, 2, 650, 1683]
+[:mouse_move, 877, 193, 2, 651, 1684]
+[:mouse_move, 868, 195, 2, 652, 1684]
+[:mouse_move, 852, 199, 2, 653, 1685]
+[:mouse_move, 837, 203, 2, 654, 1686]
+[:mouse_move, 815, 207, 2, 655, 1686]
+[:mouse_move, 790, 212, 2, 656, 1687]
+[:mouse_move, 763, 218, 2, 657, 1688]
+[:mouse_move, 733, 223, 2, 658, 1688]
+[:mouse_move, 705, 229, 2, 659, 1689]
+[:mouse_move, 692, 232, 2, 660, 1690]
+[:mouse_move, 647, 243, 2, 661, 1691]
+[:mouse_move, 639, 244, 2, 662, 1692]
+[:mouse_move, 611, 252, 2, 663, 1693]
+[:mouse_move, 601, 255, 2, 664, 1694]
+[:mouse_move, 589, 259, 2, 665, 1695]
+[:mouse_move, 584, 261, 2, 666, 1696]
+[:mouse_move, 576, 265, 2, 667, 1697]
+[:mouse_move, 572, 267, 2, 668, 1698]
+[:mouse_move, 567, 271, 2, 669, 1699]
+[:mouse_move, 565, 273, 2, 670, 1700]
+[:mouse_move, 561, 280, 2, 671, 1701]
+[:mouse_move, 559, 285, 2, 672, 1702]
+[:mouse_move, 556, 297, 2, 673, 1703]
+[:mouse_move, 555, 304, 2, 674, 1704]
+[:mouse_move, 552, 327, 2, 675, 1705]
+[:mouse_move, 552, 338, 2, 676, 1706]
+[:mouse_move, 552, 350, 2, 677, 1707]
+[:mouse_move, 552, 366, 2, 678, 1707]
+[:mouse_move, 554, 380, 2, 679, 1708]
+[:mouse_move, 559, 397, 2, 680, 1709]
+[:mouse_move, 566, 411, 2, 681, 1709]
+[:mouse_move, 575, 426, 2, 682, 1710]
+[:mouse_move, 594, 450, 2, 683, 1711]
+[:mouse_move, 611, 462, 2, 684, 1711]
+[:mouse_move, 631, 472, 2, 685, 1712]
+[:mouse_move, 713, 494, 2, 686, 1714]
+[:mouse_move, 745, 495, 2, 687, 1715]
+[:mouse_move, 777, 495, 2, 688, 1716]
+[:mouse_move, 808, 490, 2, 689, 1717]
+[:mouse_move, 818, 484, 2, 690, 1717]
+[:mouse_move, 825, 480, 2, 691, 1718]
+[:mouse_move, 856, 454, 2, 692, 1719]
+[:mouse_move, 860, 443, 2, 693, 1719]
+[:mouse_move, 861, 431, 2, 694, 1720]
+[:mouse_move, 858, 408, 2, 695, 1721]
+[:mouse_move, 813, 347, 2, 696, 1722]
+[:mouse_move, 798, 334, 2, 697, 1723]
+[:mouse_move, 731, 285, 2, 698, 1724]
+[:mouse_move, 696, 269, 2, 699, 1725]
+[:mouse_move, 629, 253, 2, 700, 1726]
+[:mouse_move, 597, 251, 2, 701, 1727]
+[:mouse_move, 540, 256, 2, 702, 1728]
+[:mouse_move, 516, 267, 2, 703, 1729]
+[:mouse_move, 474, 299, 2, 704, 1730]
+[:mouse_move, 468, 309, 2, 705, 1731]
+[:mouse_move, 441, 353, 2, 706, 1732]
+[:mouse_move, 434, 372, 2, 707, 1733]
+[:mouse_move, 430, 391, 2, 708, 1734]
+[:mouse_move, 430, 397, 2, 709, 1734]
+[:mouse_move, 430, 421, 2, 710, 1735]
+[:mouse_move, 434, 438, 2, 711, 1736]
+[:mouse_move, 447, 447, 2, 712, 1736]
+[:mouse_move, 462, 454, 2, 713, 1737]
+[:key_down_raw, 1073742051, 1024, 2, 714, 1812]
+[:key_down_raw, 113, 1024, 2, 715, 1813]
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/banana.png b/samples/99_genre_platformer/gorillas_basic/sprites/banana.png
new file mode 100644
index 0000000..b0f4134
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/banana.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/explosion0.png b/samples/99_genre_platformer/gorillas_basic/sprites/explosion0.png
new file mode 100644
index 0000000..e94c644
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/explosion0.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/explosion1.png b/samples/99_genre_platformer/gorillas_basic/sprites/explosion1.png
new file mode 100644
index 0000000..b4018d9
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/explosion1.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/explosion2.png b/samples/99_genre_platformer/gorillas_basic/sprites/explosion2.png
new file mode 100644
index 0000000..3abaedd
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/explosion2.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/explosion3.png b/samples/99_genre_platformer/gorillas_basic/sprites/explosion3.png
new file mode 100644
index 0000000..fe94a5a
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/explosion3.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/explosion4.png b/samples/99_genre_platformer/gorillas_basic/sprites/explosion4.png
new file mode 100644
index 0000000..ed04237
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/explosion4.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/explosion5.png b/samples/99_genre_platformer/gorillas_basic/sprites/explosion5.png
new file mode 100644
index 0000000..2cd8f06
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/explosion5.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/explosion6.png b/samples/99_genre_platformer/gorillas_basic/sprites/explosion6.png
new file mode 100644
index 0000000..e55909c
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/explosion6.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/hole.png b/samples/99_genre_platformer/gorillas_basic/sprites/hole.png
new file mode 100644
index 0000000..cb4e8b3
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/hole.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/left-0.png b/samples/99_genre_platformer/gorillas_basic/sprites/left-0.png
new file mode 100644
index 0000000..096d19c
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/left-0.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/left-1.png b/samples/99_genre_platformer/gorillas_basic/sprites/left-1.png
new file mode 100644
index 0000000..5944578
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/left-1.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/left-2.png b/samples/99_genre_platformer/gorillas_basic/sprites/left-2.png
new file mode 100644
index 0000000..a64f3d8
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/left-2.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/left-idle.png b/samples/99_genre_platformer/gorillas_basic/sprites/left-idle.png
new file mode 100644
index 0000000..21a71dc
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/left-idle.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/right-0.png b/samples/99_genre_platformer/gorillas_basic/sprites/right-0.png
new file mode 100644
index 0000000..57ffd46
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/right-0.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/right-1.png b/samples/99_genre_platformer/gorillas_basic/sprites/right-1.png
new file mode 100644
index 0000000..a921560
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/right-1.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/right-2.png b/samples/99_genre_platformer/gorillas_basic/sprites/right-2.png
new file mode 100644
index 0000000..fc97c90
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/right-2.png
Binary files differ
diff --git a/samples/99_genre_platformer/gorillas_basic/sprites/right-idle.png b/samples/99_genre_platformer/gorillas_basic/sprites/right-idle.png
new file mode 100644
index 0000000..2838588
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/sprites/right-idle.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/app/main.rb b/samples/99_genre_platformer/the_little_probe/app/main.rb
new file mode 100644
index 0000000..1c90218
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/app/main.rb
@@ -0,0 +1,887 @@
+class FallingCircle
+ attr_gtk
+
+ def tick
+ fiddle
+ defaults
+ render
+ input
+ calc
+ end
+
+ def fiddle
+ state.gravity = -0.02
+ circle.radius = 15
+ circle.elasticity = 0.4
+ camera.follow_speed = 0.4 * 0.4
+ end
+
+ def render
+ render_stage_editor
+ render_debug
+ render_game
+ end
+
+ def defaults
+ if state.tick_count == 0
+ outputs.sounds << "sounds/bg.ogg"
+ end
+
+ state.storyline ||= [
+ { text: "<- -> to aim, hold space to charge", distance_gate: 0 },
+ { text: "the little probe - by @amirrajan, made with DragonRuby Game Toolkit", distance_gate: 0 },
+ { text: "mission control, this is sasha. landing on europa successful.", distance_gate: 0 },
+ { text: "operation \"find earth 2.0\", initiated at 8-29-2036 14:00.", distance_gate: 0 },
+ { text: "jupiter's sure is beautiful...", distance_gate: 4000 },
+ { text: "hmm, it seems there's some kind of anomoly in the sky", distance_gate: 7000 },
+ { text: "dancing lights, i'll call them whisps.", distance_gate: 8000 },
+ { text: "#todo... look i ran out of time -_-", distance_gate: 9000 },
+ { text: "there's never enough time", distance_gate: 9000 },
+ { text: "the game jam was fun though ^_^", distance_gate: 10000 },
+ ]
+
+ load_level force: args.state.tick_count == 0
+ state.line_mode ||= :terrain
+
+ state.sound_index ||= 1
+ circle.potential_lift ||= 0
+ circle.angle ||= 90
+ circle.check_point_at ||= -1000
+ circle.game_over_at ||= -1000
+ circle.x ||= -485
+ circle.y ||= 12226
+ circle.check_point_x ||= circle.x
+ circle.check_point_y ||= circle.y
+ circle.dy ||= 0
+ circle.dx ||= 0
+ circle.previous_dy ||= 0
+ circle.previous_dx ||= 0
+ circle.angle ||= 0
+ circle.after_images ||= []
+ circle.terrains_to_monitor ||= {}
+ circle.impact_history ||= []
+
+ camera.x ||= 0
+ camera.y ||= 0
+ camera.target_x ||= 0
+ camera.target_y ||= 0
+ state.snaps ||= { }
+ state.snap_number = 10
+
+ args.state.storyline_x ||= -1000
+ args.state.storyline_y ||= -1000
+ end
+
+ def render_game
+ outputs.background_color = [0, 0, 0]
+ outputs.sprites << [-circle.x + 1100,
+ -circle.y - 100,
+ 2416 * 4,
+ 3574 * 4,
+ 'sprites/jupiter.png']
+ outputs.sprites << [-circle.x,
+ -circle.y,
+ 2416 * 4,
+ 3574 * 4,
+ 'sprites/level.png']
+ outputs.sprites << state.whisp_queue
+ render_aiming_retical
+ render_circle
+ render_notification
+ end
+
+ def render_notification
+ toast_length = 500
+ if circle.game_over_at.elapsed_time < toast_length
+ label_text = "..."
+ elsif circle.check_point_at.elapsed_time > toast_length
+ args.state.current_storyline = nil
+ return
+ end
+ if circle.check_point_at &&
+ circle.check_point_at.elapsed_time == 1 &&
+ !args.state.current_storyline
+ if args.state.storyline.length > 0 && args.state.distance_traveled > args.state.storyline[0][:distance_gate]
+ args.state.current_storyline = args.state.storyline.shift[:text]
+ args.state.distance_traveled ||= 0
+ args.state.storyline_x = circle.x
+ args.state.storyline_y = circle.y
+ end
+ return unless args.state.current_storyline
+ end
+ label_text = args.state.current_storyline
+ return unless label_text
+ x = circle.x + camera.x
+ y = circle.y + camera.y - 40
+ w = 900
+ h = 30
+ outputs.primitives << [x - w.idiv(2), y - h, w, h, 255, 255, 255, 255].solid
+ outputs.primitives << [x - w.idiv(2), y - h, w, h, 0, 0, 0, 255].border
+ outputs.labels << [x, y - 4, label_text, 1, 1, 0, 0, 0, 255]
+ end
+
+ def render_aiming_retical
+ outputs.sprites << [state.camera.x + circle.x + circle.angle.vector_x(circle.potential_lift * 10) - 5,
+ state.camera.y + circle.y + circle.angle.vector_y(circle.potential_lift * 10) - 5,
+ 10, 10, 'sprites/circle-orange.png']
+ outputs.sprites << [state.camera.x + circle.x + circle.angle.vector_x(circle.radius * 3) - 5,
+ state.camera.y + circle.y + circle.angle.vector_y(circle.radius * 3) - 5,
+ 10, 10, 'sprites/circle-orange.png', 0, 128]
+ if rand > 0.9
+ outputs.sprites << [state.camera.x + circle.x + circle.angle.vector_x(circle.radius * 3) - 5,
+ state.camera.y + circle.y + circle.angle.vector_y(circle.radius * 3) - 5,
+ 10, 10, 'sprites/circle-white.png', 0, 128]
+ end
+ end
+
+ def render_circle
+ outputs.sprites << circle.after_images.map do |ai|
+ ai.merge(x: ai.x + state.camera.x - circle.radius,
+ y: ai.y + state.camera.y - circle.radius,
+ w: circle.radius * 2,
+ h: circle.radius * 2,
+ path: 'sprites/circle-white.png')
+ end
+
+ outputs.sprites << [(circle.x - circle.radius) + state.camera.x,
+ (circle.y - circle.radius) + state.camera.y,
+ circle.radius * 2,
+ circle.radius * 2,
+ 'sprites/probe.png']
+ end
+
+ def render_debug
+ return unless state.debug_mode
+
+ outputs.labels << [10, 30, state.line_mode, 0, 0, 0, 0, 0]
+ outputs.labels << [12, 32, state.line_mode, 0, 0, 255, 255, 255]
+
+ args.outputs.lines << trajectory(circle).line.to_hash.tap do |h|
+ h[:x] += state.camera.x
+ h[:y] += state.camera.y
+ h[:x2] += state.camera.x
+ h[:y2] += state.camera.y
+ end
+
+ outputs.primitives << state.terrain.find_all do |t|
+ circle.x.between?(t.x - 640, t.x2 + 640) || circle.y.between?(t.y - 360, t.y2 + 360)
+ end.map do |t|
+ [
+ t.line.associate(r: 0, g: 255, b: 0) do |h|
+ h.x += state.camera.x
+ h.y += state.camera.y
+ h.x2 += state.camera.x
+ h.y2 += state.camera.y
+ if circle.rect.intersect_rect? t[:rect]
+ h[:r] = 255
+ h[:g] = 0
+ end
+ h
+ end,
+ t[:rect].border.associate(r: 255, g: 0, b: 0) do |h|
+ h.x += state.camera.x
+ h.y += state.camera.y
+ h.b = 255 if line_near_rect? circle.rect, t
+ h
+ end
+ ]
+ end
+
+ outputs.primitives << state.lava.find_all do |t|
+ circle.x.between?(t.x - 640, t.x2 + 640) || circle.y.between?(t.y - 360, t.y2 + 360)
+ end.map do |t|
+ [
+ t.line.associate(r: 0, g: 0, b: 255) do |h|
+ h.x += state.camera.x
+ h.y += state.camera.y
+ h.x2 += state.camera.x
+ h.y2 += state.camera.y
+ if circle.rect.intersect_rect? t[:rect]
+ h[:r] = 255
+ h[:b] = 0
+ end
+ h
+ end,
+ t[:rect].border.associate(r: 255, g: 0, b: 0) do |h|
+ h.x += state.camera.x
+ h.y += state.camera.y
+ h.b = 255 if line_near_rect? circle.rect, t
+ h
+ end
+ ]
+ end
+
+ if state.god_mode
+ border = circle.rect.merge(x: circle.rect.x + state.camera.x,
+ y: circle.rect.y + state.camera.y,
+ g: 255)
+ else
+ border = circle.rect.merge(x: circle.rect.x + state.camera.x,
+ y: circle.rect.y + state.camera.y,
+ b: 255)
+ end
+
+ outputs.borders << border
+
+ overlapping ||= {}
+
+ circle.impact_history.each do |h|
+ label_mod = 300
+ x = (h[:body][:x].-(150).idiv(label_mod)) * label_mod + camera.x
+ y = (h[:body][:y].+(150).idiv(label_mod)) * label_mod + camera.y
+ 10.times do
+ if overlapping[x] && overlapping[x][y]
+ y -= 52
+ else
+ break
+ end
+ end
+
+ overlapping[x] ||= {}
+ overlapping[x][y] ||= true
+ outputs.primitives << [x, y - 25, 300, 50, 0, 0, 0, 128].solid
+ outputs.labels << [x + 10, y + 24, "dy: %.2f" % h[:body][:new_dy], -2, 0, 255, 255, 255]
+ outputs.labels << [x + 10, y + 9, "dx: %.2f" % h[:body][:new_dx], -2, 0, 255, 255, 255]
+ outputs.labels << [x + 10, y - 5, " ?: #{h[:body][:new_reason]}", -2, 0, 255, 255, 255]
+
+ outputs.labels << [x + 100, y + 24, "angle: %.2f" % h[:impact][:angle], -2, 0, 255, 255, 255]
+ outputs.labels << [x + 100, y + 9, "m(l): %.2f" % h[:terrain][:slope], -2, 0, 255, 255, 255]
+ outputs.labels << [x + 100, y - 5, "m(c): %.2f" % h[:body][:slope], -2, 0, 255, 255, 255]
+
+ outputs.labels << [x + 200, y + 24, "ray: #{h[:impact][:ray]}", -2, 0, 255, 255, 255]
+ outputs.labels << [x + 200, y + 9, "nxt: #{h[:impact][:ray_next]}", -2, 0, 255, 255, 255]
+ outputs.labels << [x + 200, y - 5, "typ: #{h[:impact][:type]}", -2, 0, 255, 255, 255]
+ end
+
+ if circle.floor
+ outputs.labels << [circle.x + camera.x + 30, circle.y + camera.y + 100, "point: #{circle.floor_point.slice(:x, :y).values}", -2, 0]
+ outputs.labels << [circle.x + camera.x + 31, circle.y + camera.y + 101, "point: #{circle.floor_point.slice(:x, :y).values}", -2, 0, 255, 255, 255]
+ outputs.labels << [circle.x + camera.x + 30, circle.y + camera.y + 85, "circle: #{circle.hash.slice(:x, :y).values}", -2, 0]
+ outputs.labels << [circle.x + camera.x + 31, circle.y + camera.y + 86, "circle: #{circle.hash.slice(:x, :y).values}", -2, 0, 255, 255, 255]
+ outputs.labels << [circle.x + camera.x + 30, circle.y + camera.y + 70, "rel: #{circle.floor_relative_x} #{circle.floor_relative_y}", -2, 0]
+ outputs.labels << [circle.x + camera.x + 31, circle.y + camera.y + 71, "rel: #{circle.floor_relative_x} #{circle.floor_relative_y}", -2, 0, 255, 255, 255]
+ end
+ end
+
+ def render_stage_editor
+ return unless state.god_mode
+ return unless state.point_one
+ args.lines << [state.point_one, inputs.mouse.point, 0, 255, 255]
+ end
+
+ def trajectory body
+ [body.x + body.dx,
+ body.y + body.dy,
+ body.x + body.dx * 1000,
+ body.y + body.dy * 1000,
+ 0, 255, 255]
+ end
+
+ def lengthen_line line, num
+ line = normalize_line(line)
+ slope = geometry.line_slope(line, replace_infinity: 10).abs
+ if slope < 2
+ [line.x - num, line.y, line.x2 + num, line.y2].line.to_hash
+ else
+ [line.x, line.y, line.x2, line.y2].line.to_hash
+ end
+ end
+
+ def normalize_line line
+ if line.x > line.x2
+ x = line.x2
+ y = line.y2
+ x2 = line.x
+ y2 = line.y
+ else
+ x = line.x
+ y = line.y
+ x2 = line.x2
+ y2 = line.y2
+ end
+ [x, y, x2, y2]
+ end
+
+ def rect_for_line line
+ if line.x > line.x2
+ x = line.x2
+ y = line.y2
+ x2 = line.x
+ y2 = line.y
+ else
+ x = line.x
+ y = line.y
+ x2 = line.x2
+ y2 = line.y2
+ end
+
+ w = x2 - x
+ h = y2 - y
+
+ if h < 0
+ y += h
+ h = h.abs
+ end
+
+ if w < circle.radius
+ x -= circle.radius
+ w = circle.radius * 2
+ end
+
+ if h < circle.radius
+ y -= circle.radius
+ h = circle.radius * 2
+ end
+
+ { x: x, y: y, w: w, h: h }
+ end
+
+ def snap_to_grid x, y, snaps
+ snap_number = 10
+ x = x.to_i
+ y = y.to_i
+
+ x_floor = x.idiv(snap_number) * snap_number
+ x_mod = x % snap_number
+ x_ceil = (x.idiv(snap_number) + 1) * snap_number
+
+ y_floor = y.idiv(snap_number) * snap_number
+ y_mod = y % snap_number
+ y_ceil = (y.idiv(snap_number) + 1) * snap_number
+
+ if snaps[x_floor]
+ x_result = x_floor
+ elsif snaps[x_ceil]
+ x_result = x_ceil
+ elsif x_mod < snap_number.idiv(2)
+ x_result = x_floor
+ else
+ x_result = x_ceil
+ end
+
+ snaps[x_result] ||= {}
+
+ if snaps[x_result][y_floor]
+ y_result = y_floor
+ elsif snaps[x_result][y_ceil]
+ y_result = y_ceil
+ elsif y_mod < snap_number.idiv(2)
+ y_result = y_floor
+ else
+ y_result = y_ceil
+ end
+
+ snaps[x_result][y_result] = true
+ return [x_result, y_result]
+
+ end
+
+ def snap_line line
+ x, y, x2, y2 = line
+ end
+
+ def string_to_line s
+ x, y, x2, y2 = s.split(',').map(&:to_f)
+
+ if x > x2
+ x2, x = x, x2
+ y2, y = y, y2
+ end
+
+ x, y = snap_to_grid x, y, state.snaps
+ x2, y2 = snap_to_grid x2, y2, state.snaps
+ [x, y, x2, y2].line.to_hash
+ end
+
+ def load_lines file
+ data = gtk.read_file(file) || ""
+ data.each_line
+ .reject { |l| l.strip.length == 0 }
+ .map { |l| string_to_line l }
+ .map { |h| h.merge(rect: rect_for_line(h)) }
+ end
+
+ def load_terrain
+ load_lines 'level.txt'
+ end
+
+ def load_lava
+ load_lines 'level_lava.txt'
+ end
+
+ def load_level force: false
+ if force
+ state.snaps = {}
+ state.terrain = load_terrain
+ state.lava = load_lava
+ else
+ state.terrain ||= load_terrain
+ state.lava ||= load_lava
+ end
+ end
+
+ def save_lines lines, file
+ s = lines.map do |l|
+ "#{l.x1},#{l.y1},#{l.x2},#{l.y2}"
+ end.join("\n")
+ gtk.write_file(file, s)
+ end
+
+ def save_level
+ save_lines(state.terrain, 'level.txt')
+ save_lines(state.lava, 'level_lava.txt')
+ load_level force: true
+ end
+
+ def line_near_rect? rect, terrain
+ geometry.intersect_rect?(rect, terrain[:rect])
+ end
+
+ def point_within_line? point, line
+ return false if !point
+ return false if !line
+ return true
+ end
+
+ def calc_impacts x, dx, y, dy, radius
+ results = { }
+ results[:x] = x
+ results[:y] = y
+ results[:dx] = x
+ results[:dy] = y
+ 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|
+ {
+ terrain: t,
+ point: geometry.line_intersect(results[:trajectory], t),
+ type: :terrain
+ }
+ end.reject { |t| !point_within_line? t[:point], t[:terrain] }
+
+ results[:impacts] += lava.find_all { |t| line_near_rect? results[:rect], t }.map do |t|
+ {
+ terrain: t,
+ point: geometry.line_intersect(results[:trajectory], t),
+ type: :lava
+ }
+ end.reject { |t| !point_within_line? t[:point], t[:terrain] }
+
+ results
+ end
+
+ def calc_potential_impacts
+ impact_results = calc_impacts circle.x, circle.dx, circle.y, circle.dy, circle.radius
+ circle.rect = impact_results[:rect]
+ circle.trajectory = impact_results[:trajectory]
+ circle.impacts = impact_results[:impacts]
+ end
+
+ def calc_terrains_to_monitor
+ circle.impact = nil
+ circle.impacts.each do |i|
+ circle.terrains_to_monitor[i[:terrain]] ||= {
+ ray_start: geometry.ray_test(circle, i[:terrain]),
+ }
+
+ circle.terrains_to_monitor[i[:terrain]][:ray_current] = geometry.ray_test(circle, i[:terrain])
+ if circle.terrains_to_monitor[i[:terrain]][:ray_start] != circle.terrains_to_monitor[i[:terrain]][:ray_current]
+ if circle.x.between?(i[:terrain].x, i[:terrain].x2) || circle.y.between?(i[:terrain].y, i[:terrain].y2)
+ circle.impact = i
+ circle.ray_current = circle.terrains_to_monitor[i[:terrain]][:ray_current]
+ end
+ end
+ end
+ end
+
+ def impact_result body, impact
+ infinity_alias = 1000
+ r = {
+ body: {},
+ terrain: {},
+ impact: {}
+ }
+
+ r[:body][:line] = body.trajectory.dup
+ r[:body][:slope] = geometry.line_slope(body.trajectory, replace_infinity: infinity_alias)
+ r[:body][:slope_sign] = r[:body][:slope].sign
+ r[:body][:x] = body.x
+ r[:body][:y] = body.y
+ r[:body][:dy] = body.dy
+ r[:body][:dx] = body.dx
+
+ r[:terrain][:line] = impact[:terrain].dup
+ r[:terrain][:slope] = geometry.line_slope(impact[:terrain], replace_infinity: infinity_alias)
+ r[:terrain][:slope_sign] = r[:terrain][:slope].sign
+
+ r[:impact][:angle] = geometry.angle_between_lines(body.trajectory, impact[:terrain], replace_infinity: infinity_alias)
+ r[:impact][:point] = { x: impact[:point].x, y: impact[:point].y }
+ r[:impact][:same_slope_sign] = r[:body][:slope_sign] == r[:terrain][:slope_sign]
+ r[:impact][:ray] = body.ray_current
+ r[:body][:new_on_floor] = body.on_floor
+ r[:body][:new_floor] = r[:terrain][:line]
+
+ if r[:impact][:angle].abs < 90 && r[:terrain][:slope].abs < 3
+ play_sound
+ r[:body][:new_dy] = r[:body][:dy] * circle.elasticity * -1
+ r[:body][:new_dx] = r[:body][:dx] * circle.elasticity
+ r[:impact][:type] = :horizontal
+ r[:body][:new_reason] = "-"
+ elsif r[:impact][:angle].abs < 90 && r[:terrain][:slope].abs > 3
+ play_sound
+ r[:body][:new_dy] = r[:body][:dy] * 1.1
+ r[:body][:new_dx] = r[:body][:dx] * -circle.elasticity
+ r[:impact][:type] = :vertical
+ r[:body][:new_reason] = "|"
+ else
+ play_sound
+ r[:body][:new_dx] = r[:body][:dx] * -circle.elasticity
+ r[:body][:new_dy] = r[:body][:dy] * -circle.elasticity
+ r[:impact][:type] = :slanted
+ r[:body][:new_reason] = "/"
+ end
+
+ r[:impact][:energy] = r[:body][:new_dx].abs + r[:body][:new_dy].abs
+
+ if r[:impact][:energy] <= 0.3 && r[:terrain][:slope].abs < 4
+ r[:body][:new_dx] = 0
+ r[:body][:new_dy] = 0
+ r[:impact][:energy] = 0
+ r[:body][:new_on_floor] = true
+ r[:body][:new_floor] = r[:terrain][:line]
+ r[:body][:new_reason] = "0"
+ end
+
+ r[:impact][:ray_next] = geometry.ray_test({ x: r[:body][:x] - (r[:body][:dx] * 1.1) + r[:body][:new_dx],
+ y: r[:body][:y] - (r[:body][:dy] * 1.1) + r[:body][:new_dy] + state.gravity },
+ r[:terrain][:line])
+
+ if r[:impact][:ray_next] == r[:impact][:ray]
+ r[:body][:new_dx] *= -1
+ r[:body][:new_dy] *= -1
+ r[:body][:new_reason] = "clip"
+ end
+
+ r
+ end
+
+ def game_over!
+ circle.x = circle.check_point_x
+ circle.y = circle.check_point_y
+ circle.dx = 0
+ circle.dy = 0
+ circle.game_over_at = state.tick_count
+ end
+
+ def not_game_over!
+ impact_history_entry = impact_result circle, circle.impact
+ circle.impact_history << impact_history_entry
+ circle.x -= circle.dx * 1.1
+ circle.y -= circle.dy * 1.1
+ circle.dx = impact_history_entry[:body][:new_dx]
+ circle.dy = impact_history_entry[:body][:new_dy]
+ circle.on_floor = impact_history_entry[:body][:new_on_floor]
+
+ if circle.on_floor
+ circle.check_point_at = state.tick_count
+ circle.check_point_x = circle.x
+ circle.check_point_y = circle.y
+ end
+
+ circle.previous_floor = circle.floor || {}
+ circle.floor = impact_history_entry[:body][:new_floor] || {}
+ circle.floor_point = impact_history_entry[:impact][:point]
+ if circle.floor.slice(:x, :y, :x2, :y2) != circle.previous_floor.slice(:x, :y, :x2, :y2)
+ new_relative_x = if circle.dx > 0
+ :right
+ elsif circle.dx < 0
+ :left
+ else
+ nil
+ end
+
+ new_relative_y = if circle.dy > 0
+ :above
+ elsif circle.dy < 0
+ :below
+ else
+ nil
+ end
+
+ circle.floor_relative_x = new_relative_x
+ circle.floor_relative_y = new_relative_y
+ end
+
+ circle.impact = nil
+ circle.terrains_to_monitor.clear
+ end
+
+ def calc_physics
+ if args.state.god_mode
+ calc_potential_impacts
+ calc_terrains_to_monitor
+ return
+ end
+
+ if circle.y < -700
+ game_over
+ return
+ end
+
+ return if state.game_over
+ return if circle.on_floor
+ circle.previous_dy = circle.dy
+ circle.previous_dx = circle.dx
+ circle.x += circle.dx
+ circle.y += circle.dy
+ args.state.distance_traveled ||= 0
+ args.state.distance_traveled += circle.dx.abs + circle.dy.abs
+ circle.dy += state.gravity
+ calc_potential_impacts
+ calc_terrains_to_monitor
+ return unless circle.impact
+ if circle.impact && circle.impact[:type] == :lava
+ game_over!
+ else
+ not_game_over!
+ end
+ end
+
+ def input_god_mode
+ state.debug_mode = !state.debug_mode if inputs.keyboard.key_down.forward_slash
+
+ # toggle god mode
+ if inputs.keyboard.key_down.g
+ state.god_mode = !state.god_mode
+ state.potential_lift = 0
+ circle.floor = nil
+ circle.floor_point = nil
+ circle.floor_relative_x = nil
+ circle.floor_relative_y = nil
+ circle.impact = nil
+ circle.terrains_to_monitor.clear
+ return
+ end
+
+ return unless state.god_mode
+
+ circle.x = circle.x.to_i
+ circle.y = circle.y.to_i
+
+ # move god circle
+ if inputs.keyboard.left || inputs.keyboard.a
+ circle.x -= 20
+ elsif inputs.keyboard.right || inputs.keyboard.d || inputs.keyboard.f
+ circle.x += 20
+ end
+
+ if inputs.keyboard.up || inputs.keyboard.w
+ circle.y += 20
+ elsif inputs.keyboard.down || inputs.keyboard.s
+ circle.y -= 20
+ end
+
+ # delete terrain
+ if inputs.keyboard.key_down.x
+ calc_terrains_to_monitor
+ state.terrain = state.terrain.reject do |t|
+ t[:rect].intersect_rect? circle.rect
+ end
+
+ state.lava = state.lava.reject do |t|
+ t[:rect].intersect_rect? circle.rect
+ end
+
+ calc_potential_impacts
+ save_level
+ end
+
+ # change terrain type
+ if inputs.keyboard.key_down.l
+ if state.line_mode == :terrain
+ state.line_mode = :lava
+ else
+ state.line_mode = :terrain
+ end
+ end
+
+ if inputs.mouse.click && !state.point_one
+ state.point_one = inputs.mouse.click.point
+ elsif inputs.mouse.click && state.point_one
+ l = [*state.point_one, *inputs.mouse.click.point]
+ l = [l.x - state.camera.x,
+ l.y - state.camera.y,
+ l.x2 - state.camera.x,
+ l.y2 - state.camera.y].line.to_hash
+ l[:rect] = rect_for_line l
+ if state.line_mode == :terrain
+ state.terrain << l
+ else
+ state.lava << l
+ end
+ save_level
+ next_x = inputs.mouse.click.point.x - 640
+ next_y = inputs.mouse.click.point.y - 360
+ circle.x += next_x
+ circle.y += next_y
+ state.point_one = nil
+ elsif inputs.keyboard.one
+ state.point_one = [circle.x + camera.x, circle.y+ camera.y]
+ end
+
+ # cancel chain lines
+ if inputs.keyboard.key_down.nine || inputs.keyboard.key_down.escape || inputs.keyboard.key_up.six || inputs.keyboard.key_up.one
+ state.point_one = nil
+ end
+ end
+
+ def play_sound
+ return if state.sound_debounce > 0
+ state.sound_debounce = 5
+ outputs.sounds << "sounds/03#{"%02d" % state.sound_index}.wav"
+ state.sound_index += 1
+ if state.sound_index > 21
+ state.sound_index = 1
+ end
+ end
+
+ def input_game
+ if inputs.keyboard.down || inputs.keyboard.space
+ circle.potential_lift += 0.03
+ circle.potential_lift = circle.potential_lift.lesser(10)
+ elsif inputs.keyboard.key_up.down || inputs.keyboard.key_up.space
+ play_sound
+ circle.dy += circle.angle.vector_y circle.potential_lift
+ circle.dx += circle.angle.vector_x circle.potential_lift
+
+ if circle.on_floor
+ if circle.floor_relative_y == :above
+ circle.y += circle.potential_lift.abs * 2
+ elsif circle.floor_relative_y == :below
+ circle.y -= circle.potential_lift.abs * 2
+ end
+ end
+
+ circle.on_floor = false
+ circle.potential_lift = 0
+ circle.terrains_to_monitor.clear
+ circle.impact_history.clear
+ circle.impact = nil
+ calc_physics
+ end
+
+ # aim probe
+ if inputs.keyboard.right || inputs.keyboard.a
+ circle.angle -= 2
+ elsif inputs.keyboard.left || inputs.keyboard.d
+ circle.angle += 2
+ end
+ end
+
+ def input
+ input_god_mode
+ input_game
+ end
+
+ def calc_camera
+ state.camera.target_x = 640 - circle.x
+ state.camera.target_y = 360 - circle.y
+ xdiff = state.camera.target_x - state.camera.x
+ ydiff = state.camera.target_y - state.camera.y
+ state.camera.x += xdiff * camera.follow_speed
+ state.camera.y += ydiff * camera.follow_speed
+ end
+
+ def calc
+ state.sound_debounce ||= 0
+ state.sound_debounce -= 1
+ state.sound_debounce = 0 if state.sound_debounce < 0
+ if state.god_mode
+ circle.dy *= 0.1
+ circle.dx *= 0.1
+ end
+ calc_camera
+ state.whisp_queue ||= []
+ if state.tick_count.mod_zero?(4)
+ state.whisp_queue << {
+ x: -300,
+ y: 1400 * rand,
+ speed: 2.randomize(:ratio) + 3,
+ w: 20,
+ h: 20, path: 'sprites/whisp.png',
+ a: 0,
+ created_at: state.tick_count,
+ angle: 0,
+ r: 100,
+ g: 128 + 128 * rand,
+ b: 128 + 128 * rand
+ }
+ end
+
+ state.whisp_queue.each do |w|
+ w.x += w[:speed] * 2
+ w.x -= circle.dx * 0.3
+ w.y -= w[:speed]
+ w.y -= circle.dy * 0.3
+ w.angle += w[:speed]
+ w.a = w[:created_at].ease(30) * 255
+ end
+
+ state.whisp_queue = state.whisp_queue.reject { |w| w[:x] > 1280 }
+
+ if state.tick_count.mod_zero?(2) && (circle.dx != 0 || circle.dy != 0)
+ circle.after_images << {
+ x: circle.x,
+ y: circle.y,
+ w: circle.radius,
+ h: circle.radius,
+ a: 255,
+ created_at: state.tick_count
+ }
+ end
+
+ circle.after_images.each do |ai|
+ ai.a = ai[:created_at].ease(10, :flip) * 255
+ end
+
+ circle.after_images = circle.after_images.reject { |ai| ai[:created_at].elapsed_time > 10 }
+ calc_physics
+ end
+
+ def circle
+ state.circle
+ end
+
+ def camera
+ state.camera
+ end
+
+ def terrain
+ state.terrain
+ end
+
+ def lava
+ state.lava
+ end
+end
+
+# $gtk.reset
+
+def tick args
+ args.outputs.background_color = [0, 0, 0]
+ if args.inputs.keyboard.r
+ args.gtk.reset
+ return
+ end
+ # uncomment the line below to slow down the game so you
+ # can see each tick as it passes
+ # args.gtk.slowmo! 30
+ $game ||= FallingCircle.new
+ $game.args = args
+ $game.tick
+end
+
+def reset
+ $game = nil
+end
diff --git a/samples/99_genre_platformer/the_little_probe/level.txt b/samples/99_genre_platformer/the_little_probe/level.txt
new file mode 100644
index 0000000..62caf2d
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/level.txt
@@ -0,0 +1,1481 @@
+640,8840,1180,8840
+-60,10220,0,9960
+-60,10220,0,10500
+0,10500,0,10780
+0,10780,40,10900
+500,10920,760,10960
+300,10560,820,10600
+420,10320,700,10300
+820,10600,1500,10600
+1500,10600,1940,10600
+1940,10600,2380,10580
+2380,10580,2800,10620
+2240,11080,2480,11020
+2000,11120,2240,11080
+1760,11180,2000,11120
+1620,11180,1760,11180
+1500,11220,1620,11180
+1180,11280,1340,11220
+1040,11240,1180,11280
+840,11280,1040,11240
+640,11280,840,11280
+500,11220,640,11280
+420,11140,500,11220
+240,11100,420,11140
+100,11120,240,11100
+0,11180,100,11120
+-160,11220,0,11180
+-260,11240,-160,11220
+1340,11220,1500,11220
+960,13300,1280,13060
+1280,13060,1540,12860
+1540,12860,1820,12700
+1820,12700,2080,12520
+2080,12520,2240,12400
+2240,12400,2240,12240
+2240,12240,2400,12080
+2400,12080,2560,11920
+2560,11920,2640,11740
+2640,11740,2740,11580
+2740,11580,2800,11400
+2800,11400,2800,11240
+2740,11140,2800,11240
+2700,11040,2740,11140
+2700,11040,2740,10960
+2740,10960,2740,10920
+2700,10900,2740,10920
+2380,10900,2700,10900
+2040,10920,2380,10900
+1720,10940,2040,10920
+1380,11000,1720,10940
+1180,10980,1380,11000
+900,10980,1180,10980
+760,10960,900,10980
+240,10960,500,10920
+40,10900,240,10960
+0,9700,0,9960
+-60,9500,0,9700
+-60,9420,-60,9500
+-60,9420,-60,9340
+-60,9340,-60,9280
+-60,9120,-60,9280
+-60,8940,-60,9120
+-60,8940,-60,8780
+-60,8780,0,8700
+0,8700,40,8680
+40,8680,240,8700
+240,8700,360,8780
+360,8780,640,8840
+1420,8400,1540,8480
+1540,8480,1680,8500
+1680,8500,1940,8460
+1180,8840,1280,8880
+1280,8880,1340,8860
+1340,8860,1720,8860
+1720,8860,1820,8920
+1820,8920,1820,9140
+1820,9140,1820,9280
+1820,9460,1820,9280
+1760,9480,1820,9460
+1640,9480,1760,9480
+1540,9500,1640,9480
+1340,9500,1540,9500
+1100,9500,1340,9500
+1040,9540,1100,9500
+960,9540,1040,9540
+300,9420,360,9460
+240,9440,300,9420
+180,9600,240,9440
+120,9660,180,9600
+100,9820,120,9660
+100,9820,120,9860
+120,9860,140,9900
+140,9900,140,10000
+140,10440,180,10540
+100,10080,140,10000
+100,10080,140,10100
+140,10100,140,10440
+180,10540,300,10560
+2140,9560,2140,9640
+2140,9720,2140,9640
+1880,9780,2140,9720
+1720,9780,1880,9780
+1620,9740,1720,9780
+1500,9780,1620,9740
+1380,9780,1500,9780
+1340,9820,1380,9780
+1200,9820,1340,9820
+1100,9780,1200,9820
+900,9780,1100,9780
+820,9720,900,9780
+540,9720,820,9720
+360,9840,540,9720
+360,9840,360,9960
+360,9960,360,10080
+360,10140,360,10080
+360,10140,360,10240
+360,10240,420,10320
+700,10300,820,10280
+820,10280,820,10280
+820,10280,900,10320
+900,10320,1040,10300
+1040,10300,1200,10320
+1200,10320,1380,10280
+1380,10280,1500,10300
+1500,10300,1760,10300
+2800,10620,2840,10600
+2840,10600,2900,10600
+2900,10600,3000,10620
+3000,10620,3080,10620
+3080,10620,3140,10600
+3140,10540,3140,10600
+3140,10540,3140,10460
+3140,10460,3140,10360
+3140,10360,3140,10260
+3140,10260,3140,10140
+3140,10140,3140,10000
+3140,10000,3140,9860
+3140,9860,3160,9720
+3160,9720,3160,9580
+3160,9580,3160,9440
+3160,9300,3160,9440
+3160,9300,3160,9140
+3160,9140,3160,8980
+3160,8980,3160,8820
+3160,8820,3160,8680
+3160,8680,3160,8520
+1760,10300,1880,10300
+660,9500,960,9540
+640,9460,660,9500
+360,9460,640,9460
+-480,10760,-440,10880
+-480,11020,-440,10880
+-480,11160,-260,11240
+-480,11020,-480,11160
+-600,11420,-380,11320
+-380,11320,-200,11340
+-200,11340,0,11340
+0,11340,180,11340
+960,13420,960,13300
+960,13420,960,13520
+960,13520,1000,13560
+1000,13560,1040,13540
+1040,13540,1200,13440
+1200,13440,1380,13380
+1380,13380,1620,13300
+1620,13300,1820,13220
+1820,13220,2000,13200
+2000,13200,2240,13200
+2240,13200,2440,13160
+2440,13160,2640,13040
+-480,10760,-440,10620
+-440,10620,-360,10560
+-380,10460,-360,10560
+-380,10460,-360,10300
+-380,10140,-360,10300
+-380,10140,-380,10040
+-380,9880,-380,10040
+-380,9720,-380,9880
+-380,9720,-380,9540
+-380,9360,-380,9540
+-380,9180,-380,9360
+-380,9180,-380,9000
+-380,8840,-380,9000
+-380,8840,-380,8760
+-380,8760,-380,8620
+-380,8620,-380,8520
+-380,8520,-360,8400
+-360,8400,-100,8400
+-100,8400,-60,8420
+-60,8420,240,8440
+240,8440,240,8380
+240,8380,500,8440
+500,8440,760,8460
+760,8460,1000,8400
+1000,8400,1180,8420
+1180,8420,1420,8400
+1940,8460,2140,8420
+2140,8420,2200,8520
+2200,8680,2200,8520
+2140,8840,2200,8680
+2140,8840,2140,9020
+2140,9100,2140,9020
+2140,9200,2140,9100
+2140,9200,2200,9320
+2200,9320,2200,9440
+2140,9560,2200,9440
+1880,10300,2200,10280
+2200,10280,2480,10260
+2480,10260,2700,10240
+2700,10240,2840,10180
+2840,10180,2900,10060
+2900,9860,2900,10060
+2900,9640,2900,9860
+2900,9640,2900,9500
+2900,9460,2900,9500
+2740,9460,2900,9460
+2700,9460,2740,9460
+2700,9360,2700,9460
+2700,9320,2700,9360
+2600,9320,2700,9320
+2600,9260,2600,9320
+2600,9200,2600,9260
+2480,9120,2600,9200
+2440,9080,2480,9120
+2380,9080,2440,9080
+2320,9060,2380,9080
+2320,8860,2320,9060
+2320,8860,2380,8840
+2380,8840,2480,8860
+2480,8860,2600,8840
+2600,8840,2740,8840
+2740,8840,2840,8800
+2840,8800,2900,8700
+2900,8600,2900,8700
+2900,8480,2900,8600
+2900,8380,2900,8480
+2900,8380,2900,8260
+2900,8260,2900,8140
+2900,8140,2900,8020
+2900,8020,2900,7900
+2900,7820,2900,7900
+2900,7820,2900,7740
+2900,7660,2900,7740
+2900,7560,2900,7660
+2900,7460,2900,7560
+2900,7460,2900,7360
+2900,7260,2900,7360
+2840,7160,2900,7260
+2800,7080,2840,7160
+2700,7100,2800,7080
+2560,7120,2700,7100
+2400,7100,2560,7120
+2320,7100,2400,7100
+2140,7100,2320,7100
+2040,7080,2140,7100
+1940,7080,2040,7080
+1820,7140,1940,7080
+1680,7140,1820,7140
+1540,7140,1680,7140
+1420,7220,1540,7140
+1280,7220,1380,7220
+1140,7200,1280,7220
+1000,7220,1140,7200
+760,7280,900,7320
+540,7220,760,7280
+300,7180,540,7220
+180,7120,180,7160
+40,7140,180,7120
+-60,7160,40,7140
+-200,7120,-60,7160
+180,7160,300,7180
+-260,7060,-200,7120
+-260,6980,-260,7060
+-260,6880,-260,6980
+-260,6880,-260,6820
+-260,6820,-200,6760
+-200,6760,-100,6740
+-100,6740,-60,6740
+-60,6740,40,6740
+40,6740,300,6800
+300,6800,420,6760
+420,6760,500,6740
+500,6740,540,6760
+540,6760,540,6760
+540,6760,640,6780
+640,6660,640,6780
+580,6580,640,6660
+580,6440,580,6580
+580,6440,640,6320
+640,6320,640,6180
+580,6080,640,6180
+580,6080,640,5960
+640,5960,640,5840
+640,5840,640,5700
+640,5700,660,5560
+660,5560,660,5440
+660,5440,660,5300
+660,5140,660,5300
+660,5140,660,5000
+660,5000,660,4880
+660,4880,820,4860
+820,4860,1000,4840
+1000,4840,1100,4860
+1100,4860,1280,4860
+1280,4860,1420,4840
+1420,4840,1580,4860
+1580,4860,1720,4820
+1720,4820,1880,4860
+1880,4860,2000,4840
+2000,4840,2140,4840
+2140,4840,2320,4860
+2320,4860,2440,4880
+2440,4880,2600,4880
+2600,4880,2800,4880
+2800,4880,2900,4880
+2900,4880,2900,4820
+2900,4740,2900,4820
+2800,4700,2900,4740
+2520,4680,2800,4700
+2240,4660,2520,4680
+1940,4620,2240,4660
+1820,4580,1940,4620
+1820,4500,1820,4580
+1820,4500,1880,4420
+1880,4420,2000,4420
+2000,4420,2200,4420
+2200,4420,2400,4440
+2400,4440,2600,4440
+2600,4440,2840,4440
+2840,4440,2900,4400
+2740,4260,2900,4280
+2600,4240,2740,4260
+2480,4280,2600,4240
+2320,4240,2480,4280
+2140,4220,2320,4240
+1940,4220,2140,4220
+1880,4160,1940,4220
+1880,4160,1880,4080
+1880,4080,2040,4040
+2040,4040,2240,4060
+2240,4060,2400,4040
+2400,4040,2600,4060
+2600,4060,2740,4020
+2740,4020,2840,3940
+2840,3780,2840,3940
+2740,3660,2840,3780
+2700,3680,2740,3660
+2520,3700,2700,3680
+2380,3700,2520,3700
+2200,3720,2380,3700
+2040,3720,2200,3720
+1880,3700,2040,3720
+1820,3680,1880,3700
+1760,3600,1820,3680
+1760,3600,1820,3480
+1820,3480,1880,3440
+1880,3440,1960,3460
+1960,3460,2140,3460
+2140,3460,2380,3460
+2380,3460,2640,3440
+2640,3440,2900,3380
+2840,3280,2900,3380
+2840,3280,2900,3200
+2900,3200,2900,3140
+2840,3020,2900,3140
+2800,2960,2840,3020
+2700,3000,2800,2960
+2600,2980,2700,3000
+2380,3000,2600,2980
+2140,3000,2380,3000
+1880,3000,2140,3000
+1720,3040,1880,3000
+1640,2960,1720,3040
+1500,2940,1640,2960
+1340,3000,1500,2940
+1240,3000,1340,3000
+1140,3020,1240,3000
+1040,3000,1140,3020
+960,2960,1040,3000
+900,2960,960,2960
+840,2840,900,2960
+700,2820,840,2840
+540,2820,700,2820
+420,2820,540,2820
+180,2800,420,2820
+60,2780,180,2800
+-60,2800,60,2780
+-160,2760,-60,2800
+-260,2740,-160,2760
+-300,2640,-260,2740
+-360,2560,-300,2640
+-380,2460,-360,2560
+-380,2460,-300,2380
+-300,2300,-300,2380
+-300,2300,-300,2220
+-300,2100,-300,2220
+-300,2100,-300,2040
+-300,2040,-160,2040
+-160,2040,-60,2040
+-60,2040,60,2040
+60,2040,180,2040
+180,2040,360,2040
+360,2040,540,2040
+540,2040,700,2080
+660,2160,700,2080
+660,2160,700,2260
+660,2380,700,2260
+500,2340,660,2380
+360,2340,500,2340
+240,2340,360,2340
+40,2320,240,2340
+-60,2320,40,2320
+-100,2380,-60,2320
+-100,2380,-100,2460
+-100,2460,-100,2540
+-100,2540,0,2560
+0,2560,140,2600
+140,2600,300,2600
+300,2600,460,2600
+460,2600,640,2600
+640,2600,760,2580
+760,2580,820,2560
+820,2560,820,2500
+820,2500,820,2400
+820,2400,840,2320
+840,2320,840,2240
+820,2120,840,2240
+820,2020,820,2120
+820,1900,820,2020
+760,1840,820,1900
+640,1840,760,1840
+500,1840,640,1840
+300,1860,420,1880
+180,1840,300,1860
+420,1880,500,1840
+0,1840,180,1840
+-60,1860,0,1840
+-160,1840,-60,1860
+-200,1800,-160,1840
+-260,1760,-200,1800
+-260,1680,-260,1760
+-260,1620,-260,1680
+-260,1540,-260,1620
+-260,1540,-260,1460
+-300,1420,-260,1460
+-300,1420,-300,1340
+-300,1340,-260,1260
+-260,1260,-260,1160
+-260,1060,-260,1160
+-260,1060,-260,960
+-260,880,-260,960
+-260,880,-260,780
+-260,780,-260,680
+-300,580,-260,680
+-300,580,-300,480
+-300,480,-260,400
+-300,320,-260,400
+-300,320,-300,240
+-300,240,-200,220
+-200,220,-200,160
+-200,160,-100,140
+-100,140,0,120
+0,120,60,120
+60,120,180,120
+180,120,300,120
+300,120,420,140
+420,140,580,180
+580,180,760,180
+760,180,900,180
+960,180,1100,180
+1100,180,1340,200
+1340,200,1580,200
+1580,200,1720,180
+1720,180,2000,140
+2000,140,2240,140
+2240,140,2480,140
+2520,140,2800,160
+2800,160,3000,160
+3000,160,3140,160
+3140,260,3140,160
+3140,260,3140,380
+3080,500,3140,380
+3080,620,3080,500
+3080,620,3080,740
+3080,740,3080,840
+3080,960,3080,840
+3080,1080,3080,960
+3080,1080,3080,1200
+3080,1200,3080,1340
+3080,1340,3080,1460
+3080,1580,3080,1460
+3080,1700,3080,1580
+3080,1700,3080,1760
+3080,1760,3200,1760
+3200,1760,3320,1760
+3320,1760,3520,1760
+3520,1760,3680,1740
+3680,1740,3780,1700
+3780,1700,3840,1620
+3840,1620,3840,1520
+3840,1520,3840,1420
+3840,1320,3840,1420
+3840,1120,3840,1320
+3840,1120,3840,940
+3840,940,3840,760
+3780,600,3840,760
+3780,600,3780,440
+3780,320,3780,440
+3780,320,3780,160
+3780,60,3780,160
+3780,60,4020,60
+4020,60,4260,40
+4260,40,4500,40
+4500,40,4740,40
+4740,40,4840,20
+4840,20,4880,80
+4880,80,5080,40
+5080,40,5280,20
+5280,20,5500,0
+5500,0,5720,0
+5720,0,5940,60
+5940,60,6240,60
+6240,60,6540,20
+6540,20,6840,20
+6840,20,7040,0
+7040,0,7140,0
+7140,0,7400,20
+7400,20,7680,0
+7680,0,7940,0
+7940,0,8200,-20
+8200,-20,8360,20
+8360,20,8560,-40
+8560,-40,8760,0
+8760,0,8880,40
+8880,120,8880,40
+8840,220,8840,120
+8620,240,8840,220
+8420,260,8620,240
+8200,280,8420,260
+7940,280,8200,280
+7760,240,7940,280
+7560,220,7760,240
+7360,280,7560,220
+7140,260,7360,280
+6940,240,7140,260
+6720,220,6940,240
+6480,220,6720,220
+6360,300,6480,220
+6240,300,6360,300
+6200,500,6240,300
+6200,500,6360,540
+6360,540,6540,520
+6540,520,6720,480
+6720,480,6880,460
+6880,460,7080,500
+7080,500,7320,500
+7320,500,7680,500
+7680,620,7680,500
+7520,640,7680,620
+7360,640,7520,640
+7200,640,7360,640
+7040,660,7200,640
+6880,720,7040,660
+6720,700,6880,720
+6540,700,6720,700
+6420,760,6540,700
+6280,740,6420,760
+6240,760,6280,740
+6200,920,6240,760
+6200,920,6360,960
+6360,960,6540,960
+6540,960,6720,960
+6720,960,6760,980
+6760,980,6880,940
+6880,940,7080,940
+7080,940,7280,940
+7280,940,7520,920
+7520,920,7760,900
+7760,900,7980,860
+7980,860,8100,880
+8100,880,8280,900
+8280,900,8500,820
+8500,820,8700,820
+8700,820,8760,840
+8760,960,8760,840
+8700,1040,8760,960
+8560,1060,8700,1040
+8460,1080,8560,1060
+8360,1040,8460,1080
+8280,1080,8360,1040
+8160,1120,8280,1080
+8040,1120,8160,1120
+7940,1100,8040,1120
+7800,1120,7940,1100
+7680,1120,7800,1120
+7520,1100,7680,1120
+7360,1100,7520,1100
+7200,1120,7360,1100
+7040,1180,7200,1120
+6880,1160,7040,1180
+6720,1160,6880,1160
+6540,1160,6720,1160
+6360,1160,6540,1160
+6200,1160,6360,1160
+6040,1220,6200,1160
+6040,1220,6040,1400
+6040,1400,6200,1440
+6200,1440,6320,1440
+6320,1440,6440,1440
+6600,1440,6760,1440
+6760,1440,6940,1420
+6440,1440,6600,1440
+6940,1420,7280,1400
+7280,1400,7560,1400
+7560,1400,7760,1400
+7760,1400,7940,1360
+7940,1360,8100,1380
+8100,1380,8280,1340
+8280,1340,8460,1320
+8660,1300,8760,1360
+8460,1320,8660,1300
+8760,1360,8800,1500
+8800,1660,8800,1500
+8800,1660,8800,1820
+8700,1840,8800,1820
+8620,1860,8700,1840
+8560,1800,8620,1860
+8560,1800,8620,1680
+8500,1640,8620,1680
+8420,1680,8500,1640
+8280,1680,8420,1680
+8160,1680,8280,1680
+7900,1680,8160,1680
+7680,1680,7900,1680
+7400,1660,7680,1680
+7140,1680,7400,1660
+6880,1640,7140,1680
+6040,1820,6320,1780
+5900,1840,6040,1820
+6640,1700,6880,1640
+6320,1780,6640,1700
+5840,2040,5900,1840
+5840,2040,5840,2220
+5840,2220,5840,2320
+5840,2460,5840,2320
+5840,2560,5840,2460
+5840,2560,5960,2620
+5960,2620,6200,2620
+6200,2620,6380,2600
+6380,2600,6600,2580
+6600,2580,6800,2600
+6800,2600,7040,2580
+7040,2580,7280,2580
+7280,2580,7480,2560
+7760,2540,7980,2520
+7980,2520,8160,2500
+7480,2560,7760,2540
+8160,2500,8160,2420
+8160,2420,8160,2320
+8160,2180,8160,2320
+7980,2160,8160,2180
+7800,2180,7980,2160
+7600,2200,7800,2180
+7400,2200,7600,2200
+6960,2200,7200,2200
+7200,2200,7400,2200
+6720,2200,6960,2200
+6540,2180,6720,2200
+6320,2200,6540,2180
+6240,2160,6320,2200
+6240,2160,6240,2040
+6240,2040,6240,1940
+6240,1940,6440,1940
+6440,1940,6720,1940
+6720,1940,6940,1920
+7520,1920,7760,1920
+6940,1920,7280,1920
+7280,1920,7520,1920
+7760,1920,8100,1900
+8100,1900,8420,1900
+8420,1900,8460,1940
+8460,2120,8460,1940
+8460,2280,8460,2120
+8460,2280,8560,2420
+8560,2420,8660,2380
+8660,2380,8800,2340
+8800,2340,8840,2400
+8840,2520,8840,2400
+8800,2620,8840,2520
+8800,2740,8800,2620
+8800,2860,8800,2740
+8800,2940,8800,2860
+8760,2980,8800,2940
+8660,2980,8760,2980
+8620,2960,8660,2980
+8560,2880,8620,2960
+8560,2880,8560,2780
+8500,2740,8560,2780
+8420,2760,8500,2740
+8420,2840,8420,2760
+8420,2840,8420,2940
+8420,3040,8420,2940
+8420,3160,8420,3040
+8420,3280,8420,3380
+8420,3280,8420,3160
+8420,3380,8620,3460
+8620,3460,8760,3460
+8760,3460,8840,3400
+8840,3400,8960,3400
+8960,3400,9000,3500
+9000,3700,9000,3500
+9000,3900,9000,3700
+9000,4080,9000,3900
+9000,4280,9000,4080
+9000,4500,9000,4280
+9000,4620,9000,4500
+9000,4780,9000,4620
+9000,4780,9000,4960
+9000,5120,9000,4960
+9000,5120,9000,5300
+8960,5460,9000,5300
+8920,5620,8960,5460
+8920,5620,8920,5800
+8920,5800,8920,5960
+8920,5960,8920,6120
+8920,6120,8960,6300
+8960,6300,8960,6480
+8960,6660,8960,6480
+8960,6860,8960,6660
+8960,7040,8960,6860
+8920,7420,8920,7220
+8920,7420,8960,7620
+8960,7620,8960,7800
+8960,7800,8960,8000
+8960,8000,8960,8180
+8960,8180,8960,8380
+8960,8580,8960,8380
+8920,8800,8960,8580
+8880,9000,8920,8800
+8840,9180,8880,9000
+8800,9220,8840,9180
+8800,9220,8840,9340
+8760,9380,8840,9340
+8560,9340,8760,9380
+8360,9360,8560,9340
+8160,9360,8360,9360
+8040,9340,8160,9360
+7860,9360,8040,9340
+7680,9360,7860,9360
+7520,9360,7680,9360
+7420,9260,7520,9360
+7400,9080,7420,9260
+7400,9080,7420,8860
+7420,8860,7440,8720
+7440,8720,7480,8660
+7480,8660,7520,8540
+7520,8540,7600,8460
+7600,8460,7800,8480
+7800,8480,8040,8480
+8040,8480,8280,8480
+8280,8480,8500,8460
+8500,8460,8620,8440
+8620,8440,8660,8340
+8660,8340,8660,8220
+8660,8220,8700,8080
+8700,8080,8700,7920
+8700,7920,8700,7760
+8700,7760,8700,7620
+8700,7480,8700,7620
+8700,7480,8700,7320
+8700,7160,8700,7320
+8920,7220,8960,7040
+8660,7040,8700,7160
+8660,7040,8700,6880
+8660,6700,8700,6880
+8660,6700,8700,6580
+8700,6460,8700,6580
+8700,6460,8700,6320
+8700,6160,8700,6320
+8700,6160,8760,6020
+8760,6020,8760,5860
+8760,5860,8760,5700
+8760,5700,8760,5540
+8760,5540,8760,5360
+8760,5360,8760,5180
+8760,5000,8760,5180
+8700,4820,8760,5000
+8560,4740,8700,4820
+8420,4700,8560,4740
+8280,4700,8420,4700
+8100,4700,8280,4700
+7980,4700,8100,4700
+7820,4740,7980,4700
+7800,4920,7820,4740
+7800,4920,7900,4960
+7900,4960,8060,4980
+8060,4980,8220,5000
+8220,5000,8420,5040
+8420,5040,8460,5120
+8460,5180,8460,5120
+8360,5200,8460,5180
+8360,5280,8360,5200
+8160,5300,8360,5280
+8040,5260,8160,5300
+7860,5220,8040,5260
+7720,5160,7860,5220
+7640,5120,7720,5160
+7480,5120,7640,5120
+7240,5120,7480,5120
+7000,5120,7240,5120
+6800,5160,7000,5120
+6640,5220,6800,5160
+6600,5360,6640,5220
+6600,5460,6600,5360
+6480,5520,6600,5460
+6240,5540,6480,5520
+5980,5540,6240,5540
+5740,5540,5980,5540
+5500,5520,5740,5540
+5400,5520,5500,5520
+5280,5540,5400,5520
+5080,5540,5280,5540
+4940,5540,5080,5540
+4760,5540,4940,5540
+4600,5540,4760,5540
+4440,5560,4600,5540
+4040,5580,4120,5520
+4260,5540,4440,5560
+4120,5520,4260,5540
+4020,5720,4040,5580
+4020,5840,4020,5720
+4020,5840,4080,5940
+4080,5940,4120,6040
+4120,6040,4200,6080
+4200,6080,4340,6080
+4340,6080,4500,6060
+4500,6060,4700,6060
+4700,6060,4880,6060
+4880,6060,5080,6060
+5080,6060,5280,6080
+5280,6080,5440,6100
+5440,6100,5660,6100
+5660,6100,5900,6080
+5900,6080,6120,6080
+6120,6080,6360,6080
+6360,6080,6480,6100
+6480,6100,6540,6060
+6540,6060,6720,6060
+6720,6060,6940,6060
+6940,6060,7140,6060
+7400,6060,7600,6060
+7140,6060,7400,6060
+7600,6060,7800,6060
+7800,6060,7860,6080
+7860,6080,8060,6080
+8060,6080,8220,6080
+8220,6080,8320,6140
+8320,6140,8360,6300
+8320,6460,8360,6300
+8320,6620,8320,6460
+8320,6800,8320,6620
+8320,6960,8320,6800
+8320,6960,8360,7120
+8320,7280,8360,7120
+8320,7440,8320,7280
+8320,7600,8320,7440
+8100,7580,8220,7600
+8220,7600,8320,7600
+7900,7560,8100,7580
+7680,7560,7900,7560
+7480,7580,7680,7560
+7280,7580,7480,7580
+7080,7580,7280,7580
+7000,7600,7080,7580
+6880,7600,7000,7600
+6800,7580,6880,7600
+6640,7580,6800,7580
+6540,7580,6640,7580
+6380,7600,6540,7580
+6280,7620,6380,7600
+6240,7700,6280,7620
+6240,7700,6240,7800
+6240,7840,6240,7800
+6080,7840,6240,7840
+5960,7820,6080,7840
+5660,7840,5800,7840
+5500,7800,5660,7840
+5440,7700,5500,7800
+5800,7840,5960,7820
+5440,7540,5440,7700
+5440,7440,5440,7540
+5440,7320,5440,7440
+5400,7320,5440,7320
+5340,7400,5400,7320
+5340,7400,5340,7500
+5340,7600,5340,7500
+5340,7600,5340,7720
+5340,7720,5340,7860
+5340,7860,5340,7960
+5340,7960,5440,8020
+5440,8020,5560,8020
+5560,8020,5720,8040
+5720,8040,5900,8060
+5900,8060,6080,8060
+6080,8060,6240,8060
+6720,8040,6840,8060
+6240,8060,6480,8040
+6480,8040,6720,8040
+6840,8060,6940,8060
+6940,8060,7080,8120
+7080,8120,7140,8180
+7140,8460,7140,8320
+7140,8620,7140,8460
+7140,8620,7140,8740
+7140,8860,7140,8740
+7140,8960,7140,8860
+7140,8960,7200,9080
+7140,9200,7200,9080
+7140,9200,7200,9320
+7200,9320,7200,9460
+7200,9760,7200,9900
+7200,9620,7200,9460
+7200,9620,7200,9760
+7200,9900,7200,10060
+7200,10220,7200,10060
+7200,10360,7200,10220
+7140,10400,7200,10360
+6880,10400,7140,10400
+6640,10360,6880,10400
+6420,10360,6640,10360
+6160,10380,6420,10360
+5940,10340,6160,10380
+5720,10320,5940,10340
+5500,10340,5720,10320
+5280,10300,5500,10340
+5080,10300,5280,10300
+4840,10280,5080,10300
+4700,10280,4840,10280
+4540,10280,4700,10280
+4360,10280,4540,10280
+4200,10300,4360,10280
+4040,10380,4200,10300
+4020,10500,4040,10380
+3980,10640,4020,10500
+3980,10640,3980,10760
+3980,10760,4020,10920
+4020,10920,4080,11000
+4080,11000,4340,11020
+4340,11020,4600,11060
+4600,11060,4840,11040
+4840,11040,4880,10960
+4880,10740,4880,10960
+4880,10740,4880,10600
+4880,10600,5080,10560
+5080,10560,5340,10620
+5340,10620,5660,10620
+5660,10620,6040,10600
+6040,10600,6120,10620
+6120,10620,6240,10720
+6240,10720,6420,10740
+6420,10740,6640,10760
+6640,10760,6880,10780
+7140,10780,7400,10780
+6880,10780,7140,10780
+7400,10780,7680,10780
+7680,10780,8100,10760
+8100,10760,8460,10740
+8460,10740,8700,10760
+8800,10840,8800,10980
+8700,10760,8800,10840
+8760,11200,8800,10980
+8760,11200,8760,11380
+8760,11380,8800,11560
+8760,11680,8800,11560
+8760,11760,8760,11680
+8760,11760,8760,11920
+8760,11920,8800,12080
+8800,12200,8800,12080
+8700,12240,8800,12200
+8560,12220,8700,12240
+8360,12220,8560,12220
+8160,12240,8360,12220
+7720,12220,7980,12220
+7980,12220,8160,12240
+7400,12200,7720,12220
+7200,12180,7400,12200
+7000,12160,7200,12180
+6800,12160,7000,12160
+6280,12140,6380,12180
+6120,12180,6280,12140
+6540,12180,6800,12160
+6380,12180,6540,12180
+5900,12200,6120,12180
+5620,12180,5900,12200
+5340,12120,5620,12180
+5140,12100,5340,12120
+4980,12120,5140,12100
+4840,12120,4980,12120
+4700,12200,4840,12120
+4700,12380,4700,12200
+4740,12480,4940,12520
+4700,12380,4740,12480
+4940,12520,5160,12560
+5160,12560,5340,12600
+5340,12600,5400,12600
+5400,12600,5500,12600
+5500,12600,5620,12600
+5620,12600,5720,12560
+5720,12560,5800,12440
+5800,12440,5900,12380
+5900,12380,6120,12420
+6120,12420,6380,12440
+6380,12440,6600,12460
+6720,12460,6840,12520
+6840,12520,6960,12520
+6600,12460,6720,12460
+6960,12520,7040,12500
+7040,12500,7140,12440
+7200,12440,7360,12500
+7360,12500,7600,12560
+7600,12560,7860,12600
+7860,12600,8060,12500
+8100,12500,8200,12340
+8200,12340,8360,12360
+8360,12360,8560,12400
+8560,12400,8660,12420
+8660,12420,8840,12400
+8840,12400,9000,12360
+9000,12360,9000,12360
+2900,4400,2900,4280
+900,7320,1000,7220
+2640,13040,2900,12920
+2900,12920,3160,12840
+3480,12760,3780,12620
+3780,12620,4020,12460
+4300,12360,4440,12260
+4020,12460,4300,12360
+3160,12840,3480,12760
+4440,12080,4440,12260
+4440,12080,4440,11880
+4440,11880,4440,11720
+4440,11720,4600,11720
+4600,11720,4760,11740
+4760,11740,4980,11760
+4980,11760,5160,11760
+5160,11760,5340,11780
+6000,11860,6120,11820
+5340,11780,5620,11820
+5620,11820,6000,11860
+6120,11820,6360,11820
+6360,11820,6640,11860
+6940,11920,7240,11940
+7240,11940,7520,11960
+7520,11960,7860,11960
+7860,11960,8100,11920
+8100,11920,8420,11940
+8420,11940,8460,11960
+8460,11960,8500,11860
+8460,11760,8500,11860
+8320,11720,8460,11760
+8160,11720,8320,11720
+7940,11720,8160,11720
+7720,11700,7940,11720
+7520,11680,7720,11700
+7320,11680,7520,11680
+7200,11620,7320,11680
+7200,11620,7200,11500
+7200,11500,7280,11440
+7280,11440,7420,11440
+7420,11440,7600,11440
+7600,11440,7980,11460
+7980,11460,8160,11460
+8160,11460,8360,11460
+8360,11460,8460,11400
+8420,11060,8500,11200
+8280,11040,8420,11060
+8100,11060,8280,11040
+8460,11400,8500,11200
+7800,11060,8100,11060
+7520,11060,7800,11060
+7240,11060,7520,11060
+6940,11040,7240,11060
+6640,11000,6940,11040
+6420,10980,6640,11000
+6360,11060,6420,10980
+6360,11180,6360,11060
+6200,11280,6360,11180
+5960,11300,6200,11280
+5720,11280,5960,11300
+5500,11280,5720,11280
+4940,11300,5200,11280
+4660,11260,4940,11300
+4440,11280,4660,11260
+4260,11280,4440,11280
+4220,11220,4260,11280
+4080,11280,4220,11220
+3980,11420,4080,11280
+3980,11420,4040,11620
+4040,11620,4040,11820
+3980,11960,4040,11820
+3840,12000,3980,11960
+3720,11940,3840,12000
+3680,11800,3720,11940
+3680,11580,3680,11800
+3680,11360,3680,11580
+3680,11360,3680,11260
+3680,11080,3680,11260
+3680,11080,3680,10880
+3680,10700,3680,10880
+3680,10700,3680,10620
+3680,10480,3680,10620
+3680,10480,3680,10300
+3680,10300,3680,10100
+3680,10100,3680,9940
+3680,9940,3720,9860
+3720,9860,3920,9900
+3920,9900,4220,9880
+4980,9940,5340,9960
+4220,9880,4540,9900
+4540,9900,4980,9940
+5340,9960,5620,9960
+5620,9960,5900,9960
+5900,9960,6160,10000
+6160,10000,6480,10000
+6480,10000,6720,10000
+6720,10000,6880,9860
+6880,9860,6880,9520
+6880,9520,6940,9340
+6940,9120,6940,9340
+6940,9120,6940,8920
+6940,8700,6940,8920
+6880,8500,6940,8700
+6880,8320,6880,8500
+7140,8320,7140,8180
+6760,8260,6880,8320
+6540,8240,6760,8260
+6420,8180,6540,8240
+6280,8240,6420,8180
+6160,8300,6280,8240
+6120,8400,6160,8300
+6080,8520,6120,8400
+5840,8480,6080,8520
+5620,8500,5840,8480
+5500,8500,5620,8500
+5340,8560,5500,8500
+5160,8540,5340,8560
+4620,8520,4880,8520
+4360,8480,4620,8520
+4880,8520,5160,8540
+4140,8440,4360,8480
+3920,8460,4140,8440
+3720,8380,3920,8460
+3680,8160,3720,8380
+3680,8160,3720,7940
+3720,7720,3720,7940
+3680,7580,3720,7720
+3680,7580,3720,7440
+3720,7440,3720,7300
+3720,7160,3720,7300
+3720,7160,3720,7020
+3720,7020,3780,6900
+3780,6900,4080,6940
+4080,6940,4340,6980
+4340,6980,4600,6980
+4600,6980,4880,6980
+4880,6980,5160,6980
+5160,6980,5400,7000
+5400,7000,5560,7020
+5560,7020,5660,7080
+5660,7080,5660,7280
+5660,7280,5660,7440
+5660,7440,5740,7520
+5740,7520,5740,7600
+5740,7600,5900,7600
+5900,7600,6040,7540
+6040,7540,6040,7320
+6040,7320,6120,7200
+6120,7200,6120,7040
+6120,7040,6240,7000
+6240,7000,6480,7060
+6480,7060,6800,7060
+6800,7060,7080,7080
+7080,7080,7320,7100
+7940,7100,7980,6920
+7860,6860,7980,6920
+7640,6860,7860,6860
+7400,6840,7640,6860
+7320,7100,7560,7120
+7560,7120,7760,7120
+7760,7120,7940,7100
+7200,6820,7400,6840
+7040,6820,7200,6820
+6600,6840,6840,6840
+6380,6800,6600,6840
+6120,6800,6380,6800
+5900,6840,6120,6800
+5620,6820,5900,6840
+5400,6800,5620,6820
+5140,6800,5400,6800
+4880,6780,5140,6800
+4600,6760,4880,6780
+4340,6760,4600,6760
+4080,6760,4340,6760
+3840,6740,4080,6760
+3680,6720,3840,6740
+3680,6720,3680,6560
+3680,6560,3720,6400
+3720,6400,3720,6200
+3720,6200,3780,6000
+3720,5780,3780,6000
+3720,5580,3720,5780
+3720,5360,3720,5580
+3720,5360,3840,5240
+3840,5240,4200,5260
+4200,5260,4600,5280
+4600,5280,4880,5280
+4880,5280,5140,5200
+5140,5200,5220,5100
+5220,5100,5280,4900
+5280,4900,5340,4840
+5340,4840,5720,4880
+6120,4880,6480,4860
+6880,4840,7200,4860
+6480,4860,6880,4840
+7200,4860,7320,4860
+7320,4860,7360,4740
+7360,4600,7440,4520
+7360,4600,7360,4740
+7440,4520,7640,4520
+7640,4520,7800,4480
+7800,4480,7800,4280
+7800,4280,7800,4040
+7800,4040,7800,3780
+7800,3560,7800,3780
+7800,3560,7860,3440
+7860,3440,8060,3460
+8060,3460,8160,3340
+8160,3340,8160,3140
+8160,3140,8160,2960
+8000,2900,8160,2960
+7860,2900,8000,2900
+7640,2940,7860,2900
+7400,2980,7640,2940
+7100,2980,7400,2980
+6840,3000,7100,2980
+5620,2980,5840,2980
+5840,2980,6500,3000
+6500,3000,6840,3000
+5560,2780,5620,2980
+5560,2780,5560,2580
+5560,2580,5560,2380
+5560,2140,5560,2380
+5560,2140,5560,1900
+5560,1900,5620,1660
+5620,1660,5660,1460
+5660,1460,5660,1300
+5500,1260,5660,1300
+5340,1260,5500,1260
+4600,1220,4840,1240
+4440,1220,4600,1220
+4440,1080,4440,1220
+4440,1080,4600,1020
+5080,1260,5340,1260
+4840,1240,5080,1260
+4600,1020,4940,1020
+4940,1020,5220,1020
+5220,1020,5560,960
+5560,960,5660,860
+5660,740,5660,860
+5280,740,5660,740
+4940,780,5280,740
+4660,760,4940,780
+4500,700,4660,760
+4500,520,4500,700
+4500,520,4700,460
+4700,460,5080,440
+5440,420,5740,420
+5080,440,5440,420
+5740,420,5840,360
+5800,280,5840,360
+5560,280,5800,280
+4980,300,5280,320
+4360,320,4660,300
+4200,360,4360,320
+5280,320,5560,280
+4660,300,4980,300
+4140,480,4200,360
+4140,480,4140,640
+4140,640,4200,780
+4200,780,4200,980
+4200,980,4220,1180
+4220,1400,4220,1180
+4220,1400,4260,1540
+4260,1540,4500,1540
+4500,1540,4700,1520
+4700,1520,4980,1540
+5280,1560,5400,1560
+4980,1540,5280,1560
+5400,1560,5400,1700
+5400,1780,5400,1700
+5340,1900,5400,1780
+5340,2020,5340,1900
+5340,2220,5340,2020
+5340,2220,5340,2420
+5340,2420,5340,2520
+5080,2600,5220,2580
+5220,2580,5340,2520
+4900,2580,5080,2600
+4700,2540,4900,2580
+4500,2540,4700,2540
+4220,2580,4340,2540
+4200,2700,4220,2580
+4340,2540,4500,2540
+3980,2740,4200,2700
+3840,2740,3980,2740
+3780,2640,3840,2740
+3780,2640,3780,2460
+3780,2280,3780,2460
+3620,2020,3780,2100
+3780,2280,3780,2100
+3360,2040,3620,2020
+3080,2040,3360,2040
+2840,2020,3080,2040
+2740,1940,2840,2020
+2740,1940,2800,1800
+2800,1640,2800,1800
+2800,1640,2800,1460
+2800,1300,2800,1460
+2700,1180,2800,1300
+2480,1140,2700,1180
+1580,1200,1720,1200
+2240,1180,2480,1140
+1960,1180,2240,1180
+1720,1200,1960,1180
+1500,1320,1580,1200
+1500,1440,1500,1320
+1500,1440,1760,1480
+1760,1480,1940,1480
+1940,1480,2140,1500
+2140,1500,2320,1520
+2400,1560,2400,1700
+2280,1820,2380,1780
+2320,1520,2400,1560
+2380,1780,2400,1700
+2080,1840,2280,1820
+1720,1820,2080,1840
+1420,1800,1720,1820
+1280,1800,1420,1800
+1240,1720,1280,1800
+1240,1720,1240,1600
+1240,1600,1280,1480
+1280,1340,1280,1480
+1180,1280,1280,1340
+1000,1280,1180,1280
+760,1280,1000,1280
+360,1240,540,1260
+180,1220,360,1240
+540,1260,760,1280
+180,1080,180,1220
+180,1080,180,1000
+180,1000,360,940
+360,940,540,960
+540,960,820,980
+1100,980,1200,920
+820,980,1100,980
+6640,11860,6940,11920
+5200,11280,5500,11280
+4120,7330,4120,7230
+4120,7230,4660,7250
+4660,7250,4940,7250
+4940,7250,5050,7340
+5010,7400,5050,7340
+4680,7380,5010,7400
+4380,7370,4680,7380
+4120,7330,4360,7370
+4120,7670,4120,7760
+4120,7670,4280,7650
+4280,7650,4540,7660
+4550,7660,4820,7680
+4820,7680,4900,7730
+4880,7800,4900,7730
+4620,7820,4880,7800
+4360,7790,4620,7820
+4120,7760,4360,7790
+6840,6840,7040,6820
+5720,4880,6120,4880
+1200,920,1340,810
+1340,810,1520,790
+1520,790,1770,800
+2400,790,2600,750
+2600,750,2640,520
+2520,470,2640,520
+2140,470,2520,470
+1760,800,2090,800
+2080,800,2400,790
+1760,450,2140,470
+1420,450,1760,450
+1180,440,1420,450
+900,480,1180,440
+640,450,900,480
+360,440,620,450
+120,430,360,440
+0,520,120,430
+-20,780,0,520
+-20,780,-20,1020
+-20,1020,-20,1150
+-20,1150,0,1300
+0,1470,60,1530
+0,1300,0,1470
+60,1530,360,1530
+360,1530,660,1520
+660,1520,980,1520
+980,1520,1040,1520
+1040,1520,1070,1560
+1070,1770,1070,1560
+1070,1770,1100,2010
+1070,2230,1100,2010
+1070,2240,1180,2340
+1180,2340,1580,2340
+1580,2340,1940,2350
+1940,2350,2440,2350
+2440,2350,2560,2380
+2560,2380,2600,2540
+2810,2640,3140,2680
+2600,2540,2810,2640
+3140,2680,3230,2780
+3230,2780,3260,2970
+3230,3220,3260,2970
+3200,3470,3230,3220
+3200,3480,3210,3760
+3210,3760,3210,4040
+3200,4040,3230,4310
+3210,4530,3230,4310
+3210,4530,3230,4730
+3230,4960,3230,4730
+3230,4960,3260,5190
+3170,5330,3260,5190
+2920,5330,3170,5330
+2660,5360,2920,5330
+2420,5330,2660,5360
+2200,5280,2400,5330
+2020,5280,2200,5280
+1840,5260,2020,5280
+1660,5280,1840,5260
+1500,5300,1660,5280
+1360,5270,1500,5300
+1200,5290,1340,5270
+1070,5400,1200,5290
+1040,5630,1070,5400
+1000,5900,1040,5630
+980,6170,1000,5900
+980,6280,980,6170
+980,6540,980,6280
+980,6540,1040,6720
+1040,6720,1360,6730
+1360,6730,1760,6710
+2110,6720,2420,6730
+1760,6710,2110,6720
+2420,6730,2640,6720
+2640,6720,2970,6720
+2970,6720,3160,6700
+3160,6700,3240,6710
+3240,6710,3260,6890
+3260,7020,3260,6890
+3230,7180,3260,7020
+3230,7350,3230,7180
+3210,7510,3230,7350
+3210,7510,3210,7690
+3210,7870,3210,7690
+3210,7870,3210,7980
+3200,8120,3210,7980
+3200,8330,3200,8120
+3160,8520,3200,8330
+2460,11100,2480,11020
+2200,11180,2460,11100
+1260,11350,1600,11320
+600,11430,930,11400
+180,11340,620,11430
+1600,11320,1910,11280
+1910,11280,2200,11180
+923.0029599285435,11398.99893503157,1264.002959928544,11351.99893503157 \ No newline at end of file
diff --git a/samples/99_genre_platformer/the_little_probe/level_lava.txt b/samples/99_genre_platformer/the_little_probe/level_lava.txt
new file mode 100644
index 0000000..e2bc2bd
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/level_lava.txt
@@ -0,0 +1,235 @@
+100,10740,500,10780
+500,10780,960,10760
+960,10760,1340,10760
+1380,10760,1820,10780
+1820,10780,2240,10780
+2280,10780,2740,10740
+2740,10740,3000,10780
+3000,10780,3140,11020
+-520,8820,-480,9160
+-520,8480,-520,8820
+-520,8480,-480,8180
+-480,8180,-200,8120
+-200,8120,100,8220
+100,8220,420,8240
+420,8240,760,8260
+760,8260,1140,8280
+1140,8280,1500,8200
+1500,8200,1880,8240
+1880,8240,2240,8260
+2240,8260,2320,8480
+2320,8480,2380,8680
+2240,8860,2380,8680
+2240,9080,2240,8860
+2240,9080,2320,9260
+2320,9260,2480,9440
+2480,9440,2600,9640
+2480,9840,2600,9640
+2400,10020,2480,9840
+2240,10080,2400,10020
+1960,10080,2240,10080
+1720,10080,1960,10080
+1460,10080,1720,10080
+1180,10080,1420,10080
+900,10080,1180,10080
+640,10080,900,10080
+640,10080,640,9900
+60,10520,100,10740
+40,10240,60,10520
+40,10240,40,9960
+40,9960,40,9680
+40,9680,40,9360
+40,9360,60,9080
+60,9080,100,8860
+100,8860,460,9040
+460,9040,760,9220
+760,9220,1140,9220
+1140,9220,1720,9200
+-660,11580,-600,11420
+-660,11800,-660,11580
+-660,12000,-660,11800
+-660,12000,-600,12220
+-600,12220,-600,12440
+-600,12440,-600,12640
+-600,11240,-260,11280
+-260,11280,100,11240
+9000,12360,9020,12400
+9020,12620,9020,12400
+9020,12840,9020,12620
+9020,13060,9020,12840
+9020,13060,9020,13240
+9020,13240,9020,13420
+9020,13420,9020,13600
+9020,13600,9020,13780
+8880,13900,9020,13780
+8560,13800,8880,13900
+8220,13780,8560,13800
+7860,13760,8220,13780
+7640,13780,7860,13760
+7360,13800,7640,13780
+7100,13800,7360,13800
+6540,13760,6800,13780
+6800,13780,7100,13800
+6280,13760,6540,13760
+5760,13760,6280,13760
+5220,13780,5760,13760
+4700,13760,5220,13780
+4200,13740,4700,13760
+3680,13720,4200,13740
+3140,13700,3680,13720
+2600,13680,3140,13700
+2040,13940,2600,13680
+1640,13940,2040,13940
+1200,13960,1640,13940
+840,14000,1200,13960
+300,13960,840,14000
+-200,13900,300,13960
+-600,12840,-600,12640
+-600,13140,-600,12840
+-600,13140,-600,13420
+-600,13700,-600,13420
+-600,13700,-600,13820
+-600,13820,-200,13900
+-600,11240,-560,11000
+-560,11000,-480,10840
+-520,10660,-480,10840
+-520,10660,-520,10480
+-520,10480,-520,10300
+-520,10260,-480,10080
+-480,9880,-440,10060
+-520,9680,-480,9880
+-520,9680,-480,9400
+-480,9400,-480,9160
+1820,9880,2140,9800
+1540,9880,1820,9880
+1200,9920,1500,9880
+900,9880,1200,9920
+640,9900,840,9880
+2380,8760,2800,8760
+2800,8760,2840,8660
+2840,8660,2840,8420
+2840,8160,2840,8420
+2800,7900,2840,8160
+2800,7900,2800,7720
+2800,7540,2800,7720
+2800,7540,2800,7360
+2700,7220,2800,7360
+2400,7220,2700,7220
+2080,7240,2400,7220
+1760,7320,2080,7240
+1380,7360,1720,7320
+1040,7400,1340,7360
+640,7400,1000,7420
+300,7380,640,7400
+0,7300,240,7380
+-300,7180,-60,7300
+-380,6860,-360,7180
+-380,6880,-360,6700
+-360,6700,-260,6540
+-260,6540,0,6520
+0,6520,240,6640
+240,6640,460,6640
+460,6640,500,6480
+500,6260,500,6480
+460,6060,500,6260
+460,5860,460,6060
+460,5860,500,5640
+500,5640,540,5440
+540,5440,580,5220
+580,5220,580,5000
+580,4960,580,4740
+580,4740,960,4700
+960,4700,1140,4760
+1140,4760,1420,4740
+1420,4740,1720,4700
+1720,4700,2000,4740
+2000,4740,2380,4760
+2380,4760,2700,4800
+1720,4600,1760,4300
+1760,4300,2200,4340
+2200,4340,2560,4340
+2560,4340,2740,4340
+2160,12580,2440,12400
+1820,12840,2160,12580
+1500,13080,1820,12840
+1140,13340,1500,13080
+1140,13340,1580,13220
+2110,13080,2520,13000
+2520,13000,2900,12800
+1580,13220,2110,13080
+2900,12800,3200,12680
+3200,12680,3440,12640
+3440,12640,3720,12460
+3720,12460,4040,12320
+4040,12320,4360,12200
+4360,11940,4380,12180
+4360,11700,4360,11940
+4360,11700,4540,11500
+4540,11500,4880,11540
+6000,11660,6280,11640
+5440,11600,5720,11610
+5720,11610,6000,11660
+6280,11640,6760,11720
+6760,11720,7060,11780
+7060,11780,7360,11810
+7360,11810,7640,11840
+7640,11840,8000,11830
+8000,11830,8320,11850
+8320,11850,8390,11800
+8330,11760,8390,11800
+8160,11760,8330,11760
+7910,11750,8160,11760
+7660,11740,7900,11750
+7400,11730,7660,11740
+7160,11680,7400,11730
+7080,11570,7160,11680
+7080,11570,7100,11350
+7100,11350,7440,11280
+7440,11280,7940,11280
+7960,11280,8360,11280
+5840,11540,6650,11170
+4880,11540,5440,11600
+3410,11830,3420,11300
+3410,11260,3520,10920
+3520,10590,3520,10920
+3520,10590,3540,10260
+3520,9900,3540,10240
+3520,9900,3640,9590
+3640,9570,4120,9590
+4140,9590,4600,9680
+4620,9680,5030,9730
+5120,9750,5520,9800
+5620,9820,6080,9800
+6130,9810,6580,9820
+6640,9820,6800,9700
+6780,9400,6800,9700
+6780,9400,6840,9140
+6820,8860,6840,9120
+6780,8600,6820,8830
+6720,8350,6780,8570
+6480,8340,6720,8320
+6260,8400,6480,8340
+6050,8580,6240,8400
+5760,8630,6040,8590
+5520,8690,5740,8630
+5120,8690,5450,8700
+4570,8670,5080,8690
+4020,8610,4540,8670
+3540,8480,4020,8610
+3520,8230,3520,8480
+3520,7930,3520,8230
+3520,7930,3540,7630
+3480,7320,3540,7610
+3480,7280,3500,7010
+3500,6980,3680,6850
+3680,6850,4220,6840
+4230,6840,4760,6850
+4780,6850,5310,6860
+5310,6860,5720,6940
+5720,6940,5880,7250
+5880,7250,5900,7520
+100,11240,440,11300
+440,11300,760,11330
+1480,11280,1840,11230
+2200,11130,2360,11090
+1840,11230,2200,11130 \ No newline at end of file
diff --git a/samples/99_genre_platformer/the_little_probe/license-for-sample.txt b/samples/99_genre_platformer/the_little_probe/license-for-sample.txt
new file mode 100644
index 0000000..b1005ed
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/license-for-sample.txt
@@ -0,0 +1,9 @@
+Copyright 2019 DragonRuby LLC, Amir Rajan
+
+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_platformer/the_little_probe/metadata/game_metadata.txt b/samples/99_genre_platformer/the_little_probe/metadata/game_metadata.txt
new file mode 100644
index 0000000..cba2788
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/metadata/game_metadata.txt
@@ -0,0 +1,6 @@
+devid=amirrajan
+devtitle=Amir Rajan
+gameid=the-little-probe
+gametitle=The Little Probe
+version=1.0
+icon=sprites/probe.png
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0301.wav b/samples/99_genre_platformer/the_little_probe/sounds/0301.wav
new file mode 100644
index 0000000..13bdf5a
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0301.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0302.wav b/samples/99_genre_platformer/the_little_probe/sounds/0302.wav
new file mode 100644
index 0000000..b3e5849
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0302.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0303.wav b/samples/99_genre_platformer/the_little_probe/sounds/0303.wav
new file mode 100644
index 0000000..0871983
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0303.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0304.wav b/samples/99_genre_platformer/the_little_probe/sounds/0304.wav
new file mode 100644
index 0000000..9ee599e
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0304.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0305.wav b/samples/99_genre_platformer/the_little_probe/sounds/0305.wav
new file mode 100644
index 0000000..d2f919f
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0305.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0306.wav b/samples/99_genre_platformer/the_little_probe/sounds/0306.wav
new file mode 100644
index 0000000..4f15476
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0306.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0307.wav b/samples/99_genre_platformer/the_little_probe/sounds/0307.wav
new file mode 100644
index 0000000..ffb55f9
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0307.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0308.wav b/samples/99_genre_platformer/the_little_probe/sounds/0308.wav
new file mode 100644
index 0000000..86cae87
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0308.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0309.wav b/samples/99_genre_platformer/the_little_probe/sounds/0309.wav
new file mode 100644
index 0000000..1dd2a65
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0309.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0310.wav b/samples/99_genre_platformer/the_little_probe/sounds/0310.wav
new file mode 100644
index 0000000..cc0df6f
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0310.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0311.wav b/samples/99_genre_platformer/the_little_probe/sounds/0311.wav
new file mode 100644
index 0000000..0e85a2d
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0311.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0312.wav b/samples/99_genre_platformer/the_little_probe/sounds/0312.wav
new file mode 100644
index 0000000..0680440
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0312.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0313.wav b/samples/99_genre_platformer/the_little_probe/sounds/0313.wav
new file mode 100644
index 0000000..466851b
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0313.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0314.wav b/samples/99_genre_platformer/the_little_probe/sounds/0314.wav
new file mode 100644
index 0000000..81784c6
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0314.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0315.wav b/samples/99_genre_platformer/the_little_probe/sounds/0315.wav
new file mode 100644
index 0000000..f6d0036
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0315.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0316.wav b/samples/99_genre_platformer/the_little_probe/sounds/0316.wav
new file mode 100644
index 0000000..942c6d3
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0316.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0317.wav b/samples/99_genre_platformer/the_little_probe/sounds/0317.wav
new file mode 100644
index 0000000..75e35ed
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0317.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0318.wav b/samples/99_genre_platformer/the_little_probe/sounds/0318.wav
new file mode 100644
index 0000000..1fff907
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0318.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0319.wav b/samples/99_genre_platformer/the_little_probe/sounds/0319.wav
new file mode 100644
index 0000000..016a76f
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0319.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0320.wav b/samples/99_genre_platformer/the_little_probe/sounds/0320.wav
new file mode 100644
index 0000000..a41bafe
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0320.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/0321.wav b/samples/99_genre_platformer/the_little_probe/sounds/0321.wav
new file mode 100644
index 0000000..dede4f1
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/0321.wav
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sounds/bg.ogg b/samples/99_genre_platformer/the_little_probe/sounds/bg.ogg
new file mode 100644
index 0000000..8a02a75
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sounds/bg.ogg
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/area_one.png b/samples/99_genre_platformer/the_little_probe/sprites/area_one.png
new file mode 100644
index 0000000..afd2f46
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/area_one.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/circle-black.png b/samples/99_genre_platformer/the_little_probe/sprites/circle-black.png
new file mode 100644
index 0000000..c98e23d
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/circle-black.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/circle-blue.png b/samples/99_genre_platformer/the_little_probe/sprites/circle-blue.png
new file mode 100644
index 0000000..1726d2a
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/circle-blue.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/circle-gray.png b/samples/99_genre_platformer/the_little_probe/sprites/circle-gray.png
new file mode 100644
index 0000000..960f191
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/circle-gray.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/circle-green.png b/samples/99_genre_platformer/the_little_probe/sprites/circle-green.png
new file mode 100644
index 0000000..43cf7ee
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/circle-green.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/circle-indigo.png b/samples/99_genre_platformer/the_little_probe/sprites/circle-indigo.png
new file mode 100644
index 0000000..598e240
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/circle-indigo.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/circle-orange.png b/samples/99_genre_platformer/the_little_probe/sprites/circle-orange.png
new file mode 100644
index 0000000..5604a42
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/circle-orange.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/circle-red.png b/samples/99_genre_platformer/the_little_probe/sprites/circle-red.png
new file mode 100644
index 0000000..7f17ca6
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/circle-red.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/circle-violet.png b/samples/99_genre_platformer/the_little_probe/sprites/circle-violet.png
new file mode 100644
index 0000000..681d210
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/circle-violet.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/circle-white.png b/samples/99_genre_platformer/the_little_probe/sprites/circle-white.png
new file mode 100644
index 0000000..bd32155
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/circle-white.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/circle-yellow.png b/samples/99_genre_platformer/the_little_probe/sprites/circle-yellow.png
new file mode 100644
index 0000000..94992eb
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/circle-yellow.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/jupiter.png b/samples/99_genre_platformer/the_little_probe/sprites/jupiter.png
new file mode 100644
index 0000000..7982713
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/jupiter.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/level.png b/samples/99_genre_platformer/the_little_probe/sprites/level.png
new file mode 100644
index 0000000..1ce0f1a
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/level.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/probe.png b/samples/99_genre_platformer/the_little_probe/sprites/probe.png
new file mode 100644
index 0000000..e29b144
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/probe.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/square-black.png b/samples/99_genre_platformer/the_little_probe/sprites/square-black.png
new file mode 100644
index 0000000..cea7bd7
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/square-black.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/square-blue.png b/samples/99_genre_platformer/the_little_probe/sprites/square-blue.png
new file mode 100644
index 0000000..b840849
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/square-blue.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/square-gray.png b/samples/99_genre_platformer/the_little_probe/sprites/square-gray.png
new file mode 100644
index 0000000..2142b30
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/square-gray.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/square-green.png b/samples/99_genre_platformer/the_little_probe/sprites/square-green.png
new file mode 100644
index 0000000..5ef7f75
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/square-green.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/square-indigo.png b/samples/99_genre_platformer/the_little_probe/sprites/square-indigo.png
new file mode 100644
index 0000000..2384108
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/square-indigo.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/square-orange.png b/samples/99_genre_platformer/the_little_probe/sprites/square-orange.png
new file mode 100644
index 0000000..bb1eee7
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/square-orange.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/square-red.png b/samples/99_genre_platformer/the_little_probe/sprites/square-red.png
new file mode 100644
index 0000000..3ed5f13
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/square-red.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/square-violet.png b/samples/99_genre_platformer/the_little_probe/sprites/square-violet.png
new file mode 100644
index 0000000..333540c
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/square-violet.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/square-white.png b/samples/99_genre_platformer/the_little_probe/sprites/square-white.png
new file mode 100644
index 0000000..378c565
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/square-white.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/square-yellow.png b/samples/99_genre_platformer/the_little_probe/sprites/square-yellow.png
new file mode 100644
index 0000000..0edeeec
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/square-yellow.png
Binary files differ
diff --git a/samples/99_genre_platformer/the_little_probe/sprites/whisp.png b/samples/99_genre_platformer/the_little_probe/sprites/whisp.png
new file mode 100644
index 0000000..07154ee
--- /dev/null
+++ b/samples/99_genre_platformer/the_little_probe/sprites/whisp.png
Binary files differ