summaryrefslogtreecommitdiffhomepage
path: root/samples/04_physics_and_collisions/05_box_collision_2
diff options
context:
space:
mode:
authorAmir Rajan <[email protected]>2020-09-22 06:27:46 -0500
committerAmir Rajan <[email protected]>2020-09-22 06:27:46 -0500
commit20d5b4057b44ffcf92478b2a8e9476ace2fdc0f5 (patch)
treeb4742e4f9acfd5400a04f314164812606a71df9f /samples/04_physics_and_collisions/05_box_collision_2
parent5b2311900072cfff9582bb0296140cfb354cb911 (diff)
downloaddragonruby-game-toolkit-contrib-20d5b4057b44ffcf92478b2a8e9476ace2fdc0f5.tar.gz
dragonruby-game-toolkit-contrib-20d5b4057b44ffcf92478b2a8e9476ace2fdc0f5.zip
synced with 1.22
Diffstat (limited to 'samples/04_physics_and_collisions/05_box_collision_2')
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/app/main.rb470
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/app/map.txt11
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/license-for-sample.txt9
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/replay.txt819
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image1.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image10.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image11.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image12.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image13.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image14.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image15.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image16.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image17.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image18.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image19.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image2.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image20.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image3.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image4.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image5.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image6.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image7.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image8.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/image9.pngbin0 -> 473 bytes
-rw-r--r--samples/04_physics_and_collisions/05_box_collision_2/sprites/player.pngbin0 -> 744 bytes
25 files changed, 1309 insertions, 0 deletions
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/app/main.rb b/samples/04_physics_and_collisions/05_box_collision_2/app/main.rb
new file mode 100644
index 0000000..126759a
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/app/main.rb
@@ -0,0 +1,470 @@
+=begin
+ APIs listing that haven't been encountered in previous sample apps:
+
+ - times: Performs an action a specific number of times.
+ For example, if we said
+ 5.times puts "Hello DragonRuby",
+ then we'd see the words "Hello DragonRuby" printed on the console 5 times.
+
+ - split: Divides a string into substrings based on a delimiter.
+ For example, if we had a command
+ "DragonRuby is awesome".split(" ")
+ then the result would be
+ ["DragonRuby", "is", "awesome"] because the words are separated by a space delimiter.
+
+ - join: Opposite of split; converts each element of array to a string separated by delimiter.
+ For example, if we had a command
+ ["DragonRuby","is","awesome"].join(" ")
+ then the result would be
+ "DragonRuby is awesome".
+
+ Reminders:
+
+ - to_s: Returns a string representation of an object.
+ For example, if we had
+ 500.to_s
+ the string "500" would be returned.
+ Similar to to_i, which returns an integer representation of an object.
+
+ - elapsed_time: How many frames have passed since the click event.
+
+ - args.outputs.labels: An array. Values in the array generate labels on the screen.
+ The parameters are: [X, Y, TEXT, SIZE, ALIGN, RED, GREEN, BLUE, ALPHA, FONT STYLE]
+ For more information about labels, go to mygame/documentation/02-labels.md.
+
+ - inputs.mouse.down: Determines whether or not the mouse is being pressed down.
+ The position of the mouse when it is pressed down can be found using inputs.mouse.down.point.(x|y).
+
+ - first: Returns the first element of the array.
+
+ - num1.idiv(num2): Divides two numbers and returns an integer.
+
+ - find_all: Finds all values that satisfy specific requirements.
+
+ - ARRAY#intersect_rect?: Returns true or false depending on if two rectangles intersect.
+
+ - reject: Removes elements from a collection if they meet certain requirements.
+
+ - String interpolation: Uses #{} syntax; everything between the #{ and the } is evaluated
+ as Ruby code, and the placeholder is replaced with its corresponding value or result.
+
+=end
+
+MAP_FILE_PATH = 'app/map.txt' # the map.txt file in the app folder contains exported map
+
+class MetroidvaniaStarter
+ attr_accessor :grid, :inputs, :state, :outputs, :gtk
+
+ # Calls methods needed to run the game properly.
+ def tick
+ defaults
+ render
+ calc
+ process_inputs
+ end
+
+ # Sets all the default variables.
+ # '||' states that initialization occurs only in the first frame.
+ def defaults
+ state.tile_size = 64
+ state.gravity = -0.2
+ state.player_width = 60
+ state.player_height = 64
+ state.collision_tolerance = 0.0
+ state.previous_tile_size ||= state.tile_size
+ state.x ||= 0
+ state.y ||= 800
+ state.dy ||= 0
+ state.dx ||= 0
+ attempt_load_world_from_file
+ state.world_lookup ||= { }
+ state.world_collision_rects ||= []
+ state.mode ||= :creating # alternates between :creating and :selecting for sprite selection
+ state.select_menu ||= [0, 720, 1280, 720]
+ #=======================================IMPORTANT=======================================#
+ # When adding sprites, please label them "image1.png", "image2.png", image3".png", etc.
+ # Once you have done that, adjust "state.sprite_quantity" to how many sprites you have.
+ #=======================================================================================#
+ state.sprite_quantity ||= 20 # IMPORTANT TO ALTER IF SPRITES ADDED IF YOU ADD MORE SPRITES
+ state.sprite_coords ||= []
+ state.banner_coords ||= [640, 680 + 720]
+ state.sprite_selected ||= 1
+ state.map_saved_at ||= 0
+
+ # Sets all the cordinate values for the sprite selection screen into a grid
+ # Displayed when 's' is pressed by player to access sprites
+ if state.sprite_coords == [] # if sprite_coords is an empty array
+ count = 1
+ temp_x = 165 # sets a starting x and y position for display
+ temp_y = 500 + 720
+ state.sprite_quantity.times do # for the number of sprites you have
+ state.sprite_coords += [[temp_x, temp_y, count]] # add element to sprite_coords array
+ temp_x += 100 # increment temp_x
+ count += 1 # increment count
+ if temp_x > 1280 - (165 + 50) # if exceeding specific horizontal width on screen
+ temp_x = 165 # a new row of sprites starts
+ temp_y -= 75 # new row of sprites starts 75 units lower than the previous row
+ end
+ end
+ end
+ end
+
+ # Places sprites
+ def render
+
+ # Sets the x, y, width, height, and image path for each sprite in the world collection.
+ outputs.sprites << state.world.map do |x, y, sprite|
+ [x * state.tile_size, # multiply by size so grid coordinates; pixel value of location
+ y * state.tile_size,
+ state.tile_size,
+ state.tile_size,
+ 'sprites/image' + sprite.to_s + '.png'] # uses concatenation to create unique image path
+ end
+
+ # Outputs sprite for the player by setting x, y, width, height, and image path
+ outputs.sprites << [state.x,
+ state.y,
+ state.player_width,
+ state.player_height,'sprites/player.png']
+
+ # Outputs labels as primitives in top right of the screen
+ outputs.primitives << [920, 700, 'Press \'s\' to access sprites.', 1, 0].label
+ outputs.primitives << [920, 675, 'Click existing sprite to delete.', 1, 0].label
+
+ outputs.primitives << [920, 640, '<- and -> to move.', 1, 0].label
+ outputs.primitives << [920, 615, 'Press and hold space to jump.', 1, 0].label
+
+ outputs.primitives << [920, 580, 'Press \'e\' to export current map.', 1, 0].label
+
+ # if the map is saved and less than 120 frames have passed, the label is displayed
+ if state.map_saved_at > 0 && state.map_saved_at.elapsed_time < 120
+ outputs.primitives << [920, 555, 'Map has been exported!', 1, 0, 50, 100, 50].label
+ end
+
+ # If player hits 's', following appears
+ if state.mode == :selecting
+ # White background for sprite selection
+ outputs.primitives << [state.select_menu, 255, 255, 255].solid
+
+ # Select tile label at the top of the screen
+ outputs.primitives << [state.banner_coords.x, state.banner_coords.y, "Select Sprite (sprites located in \"sprites\" folder)", 10, 1, 0, 0, 0, 255].label
+
+ # Places sprites in locations calculated in the defaults function
+ outputs.primitives << state.sprite_coords.map do |x, y, order|
+ [x, y, 50, 50, 'sprites/image' + order.to_s + ".png"].sprite
+ end
+ end
+
+ # Creates sprite following mouse to help indicate which sprite you have selected
+ # 10 is subtracted from the mouse's x position so that the sprite is not covered by the mouse icon
+ outputs.primitives << [inputs.mouse.position.x - 10, inputs.mouse.position.y,
+ 10, 10, 'sprites/image' + state.sprite_selected.to_s + ".png"].sprite
+ end
+
+ # Calls methods that perform calculations
+ def calc
+ calc_in_game
+ calc_sprite_selection
+ end
+
+ # Calls methods that perform calculations (if in creating mode)
+ def calc_in_game
+ return unless state.mode == :creating
+ calc_world_lookup
+ calc_player
+ end
+
+ def calc_world_lookup
+ # If the tile size isn't equal to the previous tile size,
+ # the previous tile size is set to the tile size,
+ # and world_lookup hash is set to empty.
+ if state.tile_size != state.previous_tile_size
+ state.previous_tile_size = state.tile_size
+ state.world_lookup = {}
+ end
+
+ # return if world_lookup is not empty or if world is empty
+ return if state.world_lookup.keys.length > 0
+ return unless state.world.length > 0
+
+ # Searches through the world and finds the coordinates that exist
+ state.world_lookup = {}
+ state.world.each { |x, y| state.world_lookup[[x, y]] = true }
+
+ # Assigns collision rects for every sprite drawn
+ state.world_collision_rects =
+ state.world_lookup
+ .keys
+ .map do |coord_x, coord_y|
+ s = state.tile_size
+ # Multiplying by s (the size of a tile) ensures that the rect is
+ # placed exactly where you want it to be placed (causes grid to coordinate)
+ # How many pixels horizontally across and vertically up and down
+ x = s * coord_x
+ y = s * coord_y
+ {
+ args: [coord_x, coord_y],
+ left_right: [x, y + 4, s, s - 6], # hash keys and values
+ top: [x + 4, y + 6, s - 8, s - 6],
+ bottom: [x + 1, y - 1, s - 2, s - 8],
+ }
+ end
+ end
+
+ # Calculates movement of player and calls methods that perform collision calculations
+ def calc_player
+ state.dy += state.gravity # what goes up must come down because of gravity
+ calc_box_collision
+ calc_edge_collision
+ state.y += state.dy # Since velocity is the change in position, the change in y increases by dy
+ state.x += state.dx # Ditto line above but dx and x
+ state.dx *= 0.8 # Scales dx down
+ end
+
+ # Calls methods that determine whether the player collides with any world_collision_rects.
+ def calc_box_collision
+ return unless state.world_lookup.keys.length > 0 # return unless hash has atleast 1 key
+ collision_floor
+ collision_left
+ collision_right
+ collision_ceiling
+ end
+
+ # Finds collisions between the bottom of the player's rect and the top of a world_collision_rect.
+ def collision_floor
+ return unless state.dy <= 0 # return unless player is going down or is as far down as possible
+ player_rect = [state.x, next_y, state.tile_size, state.tile_size] # definition of player
+
+ # Runs through all the sprites on the field and finds all intersections between player's
+ # bottom and the top of a rect.
+ floor_collisions = state.world_collision_rects
+ .find_all { |r| r[:top].intersect_rect?(player_rect, state.collision_tolerance) }
+ .first
+
+ return unless floor_collisions # performs following changes if a collision has occurred
+ state.y = floor_collisions[:top].top # y of player is set to the y of the colliding rect's top
+ state.dy = 0 # no change in y because the player's path is blocked
+ end
+
+ # Finds collisions between the player's left side and the right side of a world_collision_rect.
+ def collision_left
+ return unless state.dx < 0 # return unless player is moving left
+ player_rect = [next_x, state.y, state.tile_size, state.tile_size]
+
+ # Runs through all the sprites on the field and finds all intersections between the player's left side
+ # and the right side of a rect.
+ 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 # return unless collision occurred
+ state.x = left_side_collisions[:left_right].right # sets player's x to the x of the colliding rect's right side
+ state.dx = 0 # no change in x because the player's path is blocked
+ end
+
+ # Finds collisions between the right side of the player and the left side of a world_collision_rect.
+ def collision_right
+ return unless state.dx > 0 # return unless player is moving right
+ player_rect = [next_x, state.y, state.tile_size, state.tile_size]
+
+ # Runs through all the sprites on the field and finds all intersections between the player's
+ # right side and the left side of a rect.
+ 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 # return unless collision occurred
+ state.x = right_side_collisions[:left_right].left - state.tile_size # player's x is set to the x of colliding rect's left side (minus tile size since x is the player's bottom left corner)
+ state.dx = 0 # no change in x because the player's path is blocked
+ end
+
+ # Finds collisions between the top of the player's rect and the bottom of a world_collision_rect.
+ def collision_ceiling
+ return unless state.dy > 0 # return unless player is moving up
+ player_rect = [state.x, next_y, state.player_width, state.player_height]
+
+ # Runs through all the sprites on the field and finds all intersections between the player's top
+ # and the bottom of a rect.
+ ceil_collisions = state.world_collision_rects
+ .find_all { |r| r[:bottom].intersect_rect?(player_rect, state.collision_tolerance) }
+ .first
+
+ return unless ceil_collisions # return unless collision occurred
+ state.y = ceil_collisions[:bottom].y - state.tile_size # player's y is set to the y of the colliding rect's bottom (minus tile size)
+ state.dy = 0 # no change in y because the player's path is blocked
+ end
+
+ # Makes sure the player remains within the screen's dimensions.
+ def calc_edge_collision
+ # Ensures that player doesn't fall below the map
+ if next_y < 0 && state.dy < 0 # if player is moving down and is about to fall (next_y) below the map's scope
+ state.y = 0 # 0 is the lowest the player can be while staying on the screen
+ state.dy = 0
+ # Ensures player doesn't go insanely high
+ elsif next_y > 720 - state.tile_size && state.dy > 0 # if player is moving up, about to exceed map's scope
+ state.y = 720 - state.tile_size # if we don't subtract tile_size, we won't be able to see the player on the screen
+ state.dy = 0
+ end
+
+ # Ensures that player remains in the horizontal range its supposed to
+ if state.x >= 1280 - state.tile_size && state.dx > 0 # if the player is moving too far right
+ state.x = 1280 - state.tile_size # farthest right the player can be while remaining in the screen's scope
+ state.dx = 0
+ elsif state.x <= 0 && state.dx < 0 # if the player is moving too far left
+ state.x = 0 # farthest left the player can be while remaining in the screen's scope
+ state.dx = 0
+ end
+ end
+
+ def calc_sprite_selection
+ # Does the transition to bring down the select sprite screen
+ if state.mode == :selecting && state.select_menu.y != 0
+ state.select_menu.y = 0 # sets y position of select menu (shown when 's' is pressed)
+ state.banner_coords.y = 680 # sets y position of Select Sprite banner
+ state.sprite_coords = state.sprite_coords.map do |x, y, w, h|
+ [x, y - 720, w, h] # sets definition of sprites (change '-' to '+' and the sprites can't be seen)
+ end
+ end
+
+ # Does the transition to leave the select sprite screen
+ if state.mode == :creating && state.select_menu.y != 720
+ state.select_menu.y = 720 # sets y position of select menu (menu is retreated back up)
+ state.banner_coords.y = 1000 # sets y position of Select Sprite banner
+ state.sprite_coords = state.sprite_coords.map do |x, y, w, h|
+ [x, y + 720, w, h] # sets definition of all elements in collection
+ end
+ end
+ end
+
+ def process_inputs
+ # If the state.mode is back and if the menu has retreated back up
+ # call methods that process user inputs
+ if state.mode == :creating
+ process_inputs_player_movement
+ process_inputs_place_tile
+ end
+
+ # For each sprite_coordinate added, check what sprite was selected
+ if state.mode == :selecting
+ state.sprite_coords.map do |x, y, order| # goes through all sprites in collection
+ # checks that a specific sprite was pressed based on x, y position
+ if inputs.mouse.down && # the && (and) sign means ALL statements must be true for the evaluation to be true
+ inputs.mouse.down.point.x >= x && # x is greater than or equal to sprite's x and
+ inputs.mouse.down.point.x <= x + 50 && # x is less than or equal to 50 pixels to the right
+ inputs.mouse.down.point.y >= y && # y is greater than or equal to sprite's y
+ inputs.mouse.down.point.y <= y + 50 # y is less than or equal to 50 pixels up
+ state.sprite_selected = order # sprite is chosen
+ end
+ end
+ end
+
+ inputs_export_stage
+ process_inputs_show_available_sprites
+ end
+
+ # Moves the player based on the keys they press on their keyboard
+ def process_inputs_player_movement
+ # Sets dx to 0 if the player lets go of arrow keys (player won't move left or right)
+ if inputs.keyboard.key_up.right
+ state.dx = 0
+ elsif inputs.keyboard.key_up.left
+ state.dx = 0
+ end
+
+ # Sets dx to 3 in whatever direction the player chooses when they hold down (or press) the left or right keys
+ if inputs.keyboard.key_held.right
+ state.dx = 3
+ elsif inputs.keyboard.key_held.left
+ state.dx = -3
+ end
+
+ # Sets dy to 5 to make the player ~fly~ when they press the space bar on their keyboard
+ if inputs.keyboard.key_held.space
+ state.dy = 5
+ end
+ end
+
+ # Adds tile in the place the user holds down the mouse
+ def process_inputs_place_tile
+ if inputs.mouse.down # if mouse is pressed
+ state.world_lookup = {}
+ x, y = to_coord inputs.mouse.down.point # gets x, y coordinates for the grid
+
+ # Checks if any coordinates duplicate (already exist in world)
+ if state.world.any? { |existing_x, existing_y, n| existing_x == x && existing_y == y }
+ #erases existing tile space by rejecting them from world
+ state.world = state.world.reject do |existing_x, existing_y, n|
+ existing_x == x && existing_y == y
+ end
+ else
+ state.world << [x, y, state.sprite_selected] # If no duplicates, add the sprite
+ end
+ end
+ end
+
+ # Stores/exports world collection's info (coordinates, sprite number) into a file
+ def inputs_export_stage
+ if inputs.keyboard.key_down.e # if "e" is pressed
+ export_string = state.world.map do |x, y, sprite_number| # stores world info in a string
+ "#{x},#{y},#{sprite_number}" # using string interpolation
+ end
+ gtk.write_file(MAP_FILE_PATH, export_string.join("\n")) # writes string into a file
+ state.map_saved_at = state.tick_count # frame number (passage of time) when the map was saved
+ end
+ end
+
+ def process_inputs_show_available_sprites
+ # Based on keyboard input, the entity (:creating and :selecting) switch
+ if inputs.keyboard.key_held.s && state.mode == :creating # if "s" is pressed and currently creating
+ state.mode = :selecting # will change to selecting
+ inputs.keyboard.clear # VERY IMPORTANT! If not present, it'll flicker between on and off
+ elsif inputs.keyboard.key_held.s && state.mode == :selecting # if "s" is pressed and currently selecting
+ state.mode = :creating # will change to creating
+ inputs.keyboard.clear # VERY IMPORTANT! If not present, it'll flicker between on and off
+ end
+ end
+
+ # Loads the world collection by reading from the map.txt file in the app folder
+ def attempt_load_world_from_file
+ return if state.world # return if the world collection is already populated
+ state.world ||= [] # initialized as an empty collection
+ exported_world = gtk.read_file(MAP_FILE_PATH) # reads the file using the path mentioned at top of code
+ return unless exported_world # return unless the file read was successful
+ state.world = exported_world.each_line.map do |l| # perform action on each line of exported_world
+ l.split(',').map(&:to_i) # calls split using ',' as a delimiter, and invokes .map on the collection,
+ # calling to_i (converts to integers) on each element
+ end
+ end
+
+ # Adds the change in y to y to determine the next y position of the player.
+ def next_y
+ state.y + state.dy
+ end
+
+ # Determines next x position of player
+ def next_x
+ if state.dx < 0 # if the player moves left
+ return state.x - (state.tile_size - state.player_width) # subtracts since the change in x is negative (player is moving left)
+ else
+ return state.x + (state.tile_size - state.player_width) # adds since the change in x is positive (player is moving right)
+ end
+ 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
+end
+
+$metroidvania_starter = MetroidvaniaStarter.new
+
+def tick args
+ $metroidvania_starter.grid = args.grid
+ $metroidvania_starter.inputs = args.inputs
+ $metroidvania_starter.state = args.state
+ $metroidvania_starter.outputs = args.outputs
+ $metroidvania_starter.gtk = args.gtk
+ $metroidvania_starter.tick
+end
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/app/map.txt b/samples/04_physics_and_collisions/05_box_collision_2/app/map.txt
new file mode 100644
index 0000000..abbc046
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/app/map.txt
@@ -0,0 +1,11 @@
+5,7,2
+11,7,2
+15,2,2
+6,5,2
+16,5,2
+13,4,2
+7,2,2
+8,5,2
+8,8,2
+4,6,2
+11,3,2 \ No newline at end of file
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/license-for-sample.txt b/samples/04_physics_and_collisions/05_box_collision_2/license-for-sample.txt
new file mode 100644
index 0000000..100dcec
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/license-for-sample.txt
@@ -0,0 +1,9 @@
+Copyright 2019 DragonRuby LLC
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/replay.txt b/samples/04_physics_and_collisions/05_box_collision_2/replay.txt
new file mode 100644
index 0000000..d53870b
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/replay.txt
@@ -0,0 +1,819 @@
+replay_version 2.0
+stopped_at 1897
+seed 100
+recorded_at Sun Sep 29 22:22:11 2019
+[:mouse_move, 40, 523, 2, 1, 129]
+[:mouse_move, 114, 503, 2, 2, 130]
+[:mouse_move, 170, 488, 2, 3, 131]
+[:mouse_move, 299, 454, 2, 4, 132]
+[:mouse_move, 481, 406, 2, 5, 133]
+[:mouse_move, 685, 346, 2, 6, 134]
+[:mouse_move, 812, 302, 2, 7, 135]
+[:mouse_move, 1026, 205, 2, 8, 136]
+[:mouse_move, 1062, 184, 2, 9, 137]
+[:mouse_move, 1112, 150, 2, 10, 138]
+[:mouse_move, 1153, 121, 2, 11, 139]
+[:mouse_move, 1169, 107, 2, 12, 140]
+[:mouse_move, 1182, 95, 2, 13, 141]
+[:mouse_move, 1197, 73, 2, 14, 142]
+[:mouse_move, 1197, 70, 2, 15, 143]
+[:mouse_move, 1192, 63, 2, 16, 144]
+[:mouse_move, 1187, 60, 2, 17, 145]
+[:mouse_move, 1170, 50, 2, 18, 146]
+[:mouse_move, 1161, 45, 2, 19, 147]
+[:mouse_move, 1147, 38, 2, 20, 148]
+[:mouse_move, 1140, 34, 2, 21, 149]
+[:mouse_move, 1126, 28, 2, 22, 150]
+[:mouse_move, 1114, 25, 2, 23, 151]
+[:mouse_move, 1098, 23, 2, 24, 152]
+[:mouse_move, 1088, 23, 2, 25, 153]
+[:mouse_move, 1072, 23, 2, 26, 154]
+[:mouse_move, 1055, 24, 2, 27, 155]
+[:mouse_move, 1044, 26, 2, 28, 156]
+[:mouse_move, 1019, 29, 2, 29, 157]
+[:mouse_move, 994, 31, 2, 30, 158]
+[:mouse_move, 969, 32, 2, 31, 159]
+[:mouse_move, 963, 32, 2, 32, 160]
+[:mouse_move, 948, 32, 2, 33, 161]
+[:mouse_move, 941, 31, 2, 34, 162]
+[:mouse_move, 924, 29, 2, 35, 163]
+[:mouse_move, 918, 27, 2, 36, 164]
+[:mouse_move, 910, 25, 2, 37, 165]
+[:mouse_move, 907, 24, 2, 38, 166]
+[:mouse_move, 902, 23, 2, 39, 167]
+[:mouse_move, 901, 22, 2, 40, 168]
+[:mouse_move, 899, 22, 2, 41, 169]
+[:mouse_move, 898, 22, 2, 42, 170]
+[:mouse_move, 897, 22, 2, 43, 172]
+[:mouse_move, 897, 23, 2, 44, 174]
+[:mouse_move, 897, 30, 2, 45, 175]
+[:mouse_move, 898, 34, 2, 46, 176]
+[:mouse_move, 906, 46, 2, 47, 177]
+[:mouse_move, 912, 52, 2, 48, 178]
+[:mouse_move, 929, 64, 2, 49, 179]
+[:mouse_move, 941, 69, 2, 50, 180]
+[:mouse_move, 963, 74, 2, 51, 181]
+[:mouse_move, 969, 75, 2, 52, 182]
+[:mouse_move, 980, 76, 2, 53, 183]
+[:mouse_move, 1001, 76, 2, 54, 184]
+[:mouse_move, 1009, 76, 2, 55, 185]
+[:mouse_move, 1025, 76, 2, 56, 186]
+[:mouse_move, 1028, 76, 2, 57, 187]
+[:mouse_move, 1041, 75, 2, 58, 188]
+[:mouse_move, 1046, 73, 2, 59, 189]
+[:mouse_move, 1055, 71, 2, 60, 190]
+[:mouse_move, 1061, 69, 2, 61, 191]
+[:mouse_move, 1078, 65, 2, 62, 192]
+[:mouse_move, 1086, 64, 2, 63, 193]
+[:mouse_move, 1104, 62, 2, 64, 194]
+[:mouse_move, 1109, 62, 2, 65, 195]
+[:mouse_move, 1126, 61, 2, 66, 196]
+[:mouse_move, 1141, 61, 2, 67, 197]
+[:mouse_move, 1155, 60, 2, 68, 198]
+[:mouse_move, 1162, 60, 2, 69, 199]
+[:mouse_move, 1170, 59, 2, 70, 200]
+[:mouse_move, 1175, 59, 2, 71, 201]
+[:mouse_move, 1181, 58, 2, 72, 202]
+[:mouse_move, 1183, 57, 2, 73, 203]
+[:mouse_move, 1186, 56, 2, 74, 204]
+[:mouse_move, 1189, 55, 2, 75, 205]
+[:mouse_move, 1191, 53, 2, 76, 206]
+[:mouse_move, 1191, 52, 2, 77, 207]
+[:mouse_move, 1193, 48, 2, 78, 208]
+[:mouse_move, 1193, 45, 2, 79, 209]
+[:mouse_move, 1192, 43, 2, 80, 210]
+[:mouse_move, 1186, 38, 2, 81, 211]
+[:mouse_move, 1181, 35, 2, 82, 212]
+[:mouse_move, 1168, 30, 2, 83, 213]
+[:mouse_move, 1161, 27, 2, 84, 214]
+[:mouse_move, 1140, 23, 2, 85, 215]
+[:mouse_move, 1130, 21, 2, 86, 216]
+[:mouse_move, 1109, 19, 2, 87, 217]
+[:mouse_move, 1104, 19, 2, 88, 218]
+[:mouse_move, 1081, 19, 2, 89, 219]
+[:mouse_move, 1064, 19, 2, 90, 220]
+[:mouse_move, 1048, 19, 2, 91, 221]
+[:mouse_move, 1037, 19, 2, 92, 222]
+[:mouse_move, 1012, 20, 2, 93, 223]
+[:mouse_move, 1007, 21, 2, 94, 224]
+[:mouse_move, 986, 22, 2, 95, 225]
+[:mouse_move, 978, 23, 2, 96, 226]
+[:mouse_move, 957, 26, 2, 97, 227]
+[:mouse_move, 949, 28, 2, 98, 228]
+[:mouse_move, 935, 32, 2, 99, 229]
+[:mouse_move, 930, 34, 2, 100, 230]
+[:mouse_move, 926, 37, 2, 101, 231]
+[:mouse_move, 921, 40, 2, 102, 232]
+[:mouse_move, 918, 46, 2, 103, 233]
+[:mouse_move, 918, 51, 2, 104, 234]
+[:mouse_move, 919, 60, 2, 105, 235]
+[:mouse_move, 923, 67, 2, 106, 236]
+[:mouse_move, 929, 70, 2, 107, 237]
+[:mouse_move, 941, 73, 2, 108, 238]
+[:mouse_move, 948, 74, 2, 109, 239]
+[:mouse_move, 958, 74, 2, 110, 240]
+[:mouse_move, 962, 74, 2, 111, 241]
+[:mouse_move, 968, 74, 2, 112, 242]
+[:mouse_move, 969, 73, 2, 113, 243]
+[:mouse_move, 970, 73, 2, 114, 244]
+[:mouse_move, 968, 73, 2, 115, 256]
+[:mouse_move, 963, 77, 2, 116, 257]
+[:mouse_move, 949, 85, 2, 117, 258]
+[:mouse_move, 944, 88, 2, 118, 259]
+[:mouse_move, 935, 94, 2, 119, 260]
+[:mouse_move, 932, 96, 2, 120, 261]
+[:mouse_move, 925, 101, 2, 121, 262]
+[:mouse_move, 921, 104, 2, 122, 263]
+[:mouse_move, 917, 107, 2, 123, 264]
+[:mouse_move, 915, 107, 2, 124, 265]
+[:mouse_move, 914, 108, 2, 125, 266]
+[:mouse_move, 912, 108, 2, 126, 267]
+[:mouse_move, 912, 109, 2, 127, 268]
+[:mouse_move, 911, 109, 2, 128, 269]
+[:mouse_move, 913, 109, 2, 129, 275]
+[:mouse_move, 915, 109, 2, 130, 276]
+[:mouse_move, 922, 109, 2, 131, 277]
+[:mouse_move, 926, 109, 2, 132, 278]
+[:mouse_move, 937, 108, 2, 133, 279]
+[:mouse_move, 943, 107, 2, 134, 280]
+[:mouse_move, 955, 106, 2, 135, 281]
+[:mouse_move, 961, 106, 2, 136, 282]
+[:mouse_move, 971, 106, 2, 137, 283]
+[:mouse_move, 977, 106, 2, 138, 284]
+[:mouse_move, 987, 106, 2, 139, 285]
+[:mouse_move, 994, 106, 2, 140, 286]
+[:mouse_move, 1012, 108, 2, 141, 287]
+[:mouse_move, 1016, 109, 2, 142, 288]
+[:mouse_move, 1030, 110, 2, 143, 289]
+[:mouse_move, 1036, 111, 2, 144, 290]
+[:mouse_move, 1050, 111, 2, 145, 291]
+[:mouse_move, 1056, 111, 2, 146, 292]
+[:mouse_move, 1062, 111, 2, 147, 293]
+[:mouse_move, 1074, 111, 2, 148, 294]
+[:mouse_move, 1080, 111, 2, 149, 295]
+[:mouse_move, 1086, 111, 2, 150, 296]
+[:mouse_move, 1094, 111, 2, 151, 297]
+[:mouse_move, 1099, 112, 2, 152, 298]
+[:mouse_move, 1101, 112, 2, 153, 299]
+[:mouse_move, 1106, 112, 2, 154, 300]
+[:mouse_move, 1107, 112, 2, 155, 301]
+[:mouse_move, 1109, 112, 2, 156, 302]
+[:mouse_move, 1104, 112, 2, 157, 306]
+[:mouse_move, 1097, 112, 2, 158, 307]
+[:mouse_move, 1079, 112, 2, 159, 308]
+[:mouse_move, 1067, 111, 2, 160, 309]
+[:mouse_move, 1043, 111, 2, 161, 310]
+[:mouse_move, 1038, 111, 2, 162, 311]
+[:mouse_move, 1018, 111, 2, 163, 312]
+[:mouse_move, 1009, 111, 2, 164, 313]
+[:mouse_move, 986, 111, 2, 165, 314]
+[:mouse_move, 978, 111, 2, 166, 315]
+[:mouse_move, 963, 111, 2, 167, 316]
+[:mouse_move, 954, 111, 2, 168, 317]
+[:mouse_move, 940, 111, 2, 169, 318]
+[:mouse_move, 934, 111, 2, 170, 319]
+[:mouse_move, 929, 111, 2, 171, 320]
+[:mouse_move, 920, 110, 2, 172, 321]
+[:mouse_move, 916, 110, 2, 173, 322]
+[:mouse_move, 911, 109, 2, 174, 323]
+[:mouse_move, 909, 109, 2, 175, 324]
+[:mouse_move, 906, 109, 2, 176, 325]
+[:mouse_move, 905, 109, 2, 177, 327]
+[:mouse_move, 904, 109, 2, 178, 328]
+[:mouse_move, 904, 110, 2, 179, 334]
+[:mouse_move, 907, 112, 2, 180, 335]
+[:mouse_move, 910, 113, 2, 181, 336]
+[:mouse_move, 917, 117, 2, 182, 337]
+[:mouse_move, 921, 118, 2, 183, 338]
+[:mouse_move, 931, 122, 2, 184, 339]
+[:mouse_move, 935, 123, 2, 185, 340]
+[:mouse_move, 943, 125, 2, 186, 341]
+[:mouse_move, 945, 125, 2, 187, 342]
+[:mouse_move, 954, 128, 2, 188, 343]
+[:mouse_move, 957, 128, 2, 189, 344]
+[:mouse_move, 963, 129, 2, 190, 345]
+[:mouse_move, 966, 130, 2, 191, 346]
+[:mouse_move, 968, 130, 2, 192, 347]
+[:mouse_move, 976, 131, 2, 193, 348]
+[:mouse_move, 980, 132, 2, 194, 349]
+[:mouse_move, 986, 132, 2, 195, 350]
+[:mouse_move, 991, 133, 2, 196, 351]
+[:mouse_move, 998, 133, 2, 197, 352]
+[:mouse_move, 1002, 133, 2, 198, 353]
+[:mouse_move, 1010, 133, 2, 199, 354]
+[:mouse_move, 1014, 133, 2, 200, 355]
+[:mouse_move, 1024, 133, 2, 201, 356]
+[:mouse_move, 1030, 133, 2, 202, 357]
+[:mouse_move, 1041, 133, 2, 203, 358]
+[:mouse_move, 1047, 134, 2, 204, 359]
+[:mouse_move, 1062, 134, 2, 205, 360]
+[:mouse_move, 1070, 134, 2, 206, 361]
+[:mouse_move, 1083, 135, 2, 207, 362]
+[:mouse_move, 1091, 135, 2, 208, 363]
+[:mouse_move, 1103, 136, 2, 209, 364]
+[:mouse_move, 1110, 136, 2, 210, 365]
+[:mouse_move, 1123, 138, 2, 211, 366]
+[:mouse_move, 1129, 140, 2, 212, 367]
+[:mouse_move, 1140, 141, 2, 213, 368]
+[:mouse_move, 1145, 142, 2, 214, 369]
+[:mouse_move, 1156, 144, 2, 215, 370]
+[:mouse_move, 1161, 144, 2, 216, 371]
+[:mouse_move, 1171, 145, 2, 217, 372]
+[:mouse_move, 1175, 145, 2, 218, 373]
+[:mouse_move, 1180, 145, 2, 219, 374]
+[:mouse_move, 1188, 145, 2, 220, 375]
+[:mouse_move, 1189, 145, 2, 221, 376]
+[:mouse_move, 1196, 146, 2, 222, 377]
+[:mouse_move, 1199, 146, 2, 223, 378]
+[:mouse_move, 1203, 147, 2, 224, 379]
+[:mouse_move, 1205, 148, 2, 225, 380]
+[:mouse_move, 1208, 150, 2, 226, 381]
+[:mouse_move, 1210, 150, 2, 227, 382]
+[:mouse_move, 1211, 151, 2, 228, 383]
+[:mouse_move, 1212, 151, 2, 229, 384]
+[:mouse_move, 1212, 152, 2, 230, 385]
+[:mouse_move, 1213, 152, 2, 231, 386]
+[:mouse_move, 1212, 152, 2, 232, 422]
+[:mouse_move, 1211, 152, 2, 233, 427]
+[:mouse_move, 1209, 152, 2, 234, 428]
+[:mouse_move, 1194, 159, 2, 235, 429]
+[:mouse_move, 1179, 166, 2, 236, 430]
+[:mouse_move, 1135, 186, 2, 237, 431]
+[:mouse_move, 1123, 191, 2, 238, 432]
+[:mouse_move, 1080, 208, 2, 239, 433]
+[:mouse_move, 1073, 211, 2, 240, 434]
+[:mouse_move, 1045, 219, 2, 241, 435]
+[:mouse_move, 1033, 220, 2, 242, 436]
+[:mouse_move, 1021, 221, 2, 243, 437]
+[:mouse_move, 1016, 221, 2, 244, 438]
+[:mouse_move, 1009, 221, 2, 245, 439]
+[:mouse_move, 1007, 220, 2, 246, 440]
+[:mouse_move, 1002, 218, 2, 247, 441]
+[:mouse_move, 999, 216, 2, 248, 442]
+[:mouse_move, 987, 210, 2, 249, 443]
+[:mouse_move, 979, 207, 2, 250, 444]
+[:mouse_move, 958, 199, 2, 251, 445]
+[:mouse_move, 947, 196, 2, 252, 446]
+[:mouse_move, 929, 191, 2, 253, 447]
+[:mouse_move, 920, 189, 2, 254, 448]
+[:mouse_move, 910, 186, 2, 255, 449]
+[:mouse_move, 906, 185, 2, 256, 450]
+[:mouse_move, 901, 184, 2, 257, 451]
+[:mouse_move, 900, 183, 2, 258, 452]
+[:mouse_move, 899, 183, 2, 259, 453]
+[:mouse_move, 898, 183, 2, 260, 457]
+[:mouse_move, 892, 183, 2, 261, 458]
+[:mouse_move, 885, 183, 2, 262, 459]
+[:mouse_move, 864, 183, 2, 263, 460]
+[:mouse_move, 841, 182, 2, 264, 461]
+[:mouse_move, 811, 180, 2, 265, 462]
+[:mouse_move, 775, 178, 2, 266, 463]
+[:mouse_move, 754, 176, 2, 267, 464]
+[:mouse_move, 748, 176, 2, 268, 465]
+[:mouse_move, 728, 175, 2, 269, 466]
+[:mouse_move, 723, 174, 2, 270, 467]
+[:mouse_move, 717, 174, 2, 271, 468]
+[:mouse_move, 716, 174, 2, 272, 469]
+[:mouse_move, 719, 174, 2, 273, 472]
+[:mouse_move, 724, 174, 2, 274, 473]
+[:mouse_move, 734, 176, 2, 275, 474]
+[:mouse_move, 741, 177, 2, 276, 475]
+[:mouse_move, 758, 178, 2, 277, 476]
+[:mouse_move, 772, 179, 2, 278, 477]
+[:mouse_move, 792, 180, 2, 279, 478]
+[:mouse_move, 796, 180, 2, 280, 479]
+[:mouse_move, 813, 181, 2, 281, 480]
+[:mouse_move, 822, 181, 2, 282, 481]
+[:mouse_move, 830, 181, 2, 283, 482]
+[:mouse_move, 854, 182, 2, 284, 483]
+[:mouse_move, 866, 183, 2, 285, 484]
+[:mouse_move, 891, 183, 2, 286, 485]
+[:mouse_move, 905, 184, 2, 287, 486]
+[:mouse_move, 938, 185, 2, 288, 487]
+[:mouse_move, 970, 186, 2, 289, 488]
+[:mouse_move, 1017, 188, 2, 290, 489]
+[:mouse_move, 1042, 189, 2, 291, 490]
+[:mouse_move, 1079, 190, 2, 292, 491]
+[:mouse_move, 1102, 190, 2, 293, 492]
+[:mouse_move, 1128, 190, 2, 294, 493]
+[:mouse_move, 1142, 190, 2, 295, 494]
+[:mouse_move, 1162, 190, 2, 296, 495]
+[:mouse_move, 1165, 190, 2, 297, 496]
+[:mouse_move, 1175, 190, 2, 298, 497]
+[:mouse_move, 1178, 190, 2, 299, 498]
+[:mouse_move, 1183, 189, 2, 300, 499]
+[:mouse_move, 1185, 189, 2, 301, 500]
+[:mouse_move, 1187, 189, 2, 302, 501]
+[:mouse_move, 1188, 189, 2, 303, 502]
+[:mouse_move, 1190, 189, 2, 304, 503]
+[:mouse_move, 1190, 190, 2, 305, 504]
+[:mouse_move, 1192, 190, 2, 306, 505]
+[:mouse_move, 1193, 191, 2, 307, 506]
+[:mouse_move, 1195, 192, 2, 308, 507]
+[:mouse_move, 1197, 193, 2, 309, 509]
+[:mouse_move, 1198, 194, 2, 310, 510]
+[:mouse_move, 1199, 194, 2, 311, 511]
+[:mouse_move, 1201, 195, 2, 312, 512]
+[:mouse_move, 1202, 196, 2, 313, 513]
+[:mouse_move, 1203, 196, 2, 314, 514]
+[:mouse_move, 1203, 197, 2, 315, 515]
+[:mouse_move, 1204, 197, 2, 316, 516]
+[:mouse_move, 1204, 198, 2, 317, 520]
+[:mouse_move, 1203, 198, 2, 318, 523]
+[:mouse_move, 1202, 199, 2, 319, 524]
+[:mouse_move, 1200, 199, 2, 320, 525]
+[:mouse_move, 1192, 203, 2, 321, 526]
+[:mouse_move, 1177, 209, 2, 322, 527]
+[:mouse_move, 1115, 235, 2, 323, 528]
+[:mouse_move, 1071, 251, 2, 324, 529]
+[:mouse_move, 958, 294, 2, 325, 530]
+[:mouse_move, 890, 320, 2, 326, 531]
+[:mouse_move, 758, 368, 2, 327, 532]
+[:mouse_move, 693, 388, 2, 328, 533]
+[:mouse_move, 610, 409, 2, 329, 534]
+[:mouse_move, 564, 421, 2, 330, 535]
+[:mouse_move, 549, 423, 2, 331, 536]
+[:mouse_move, 518, 429, 2, 332, 537]
+[:mouse_move, 512, 429, 2, 333, 538]
+[:mouse_move, 495, 432, 2, 334, 539]
+[:mouse_move, 490, 432, 2, 335, 540]
+[:mouse_move, 487, 433, 2, 336, 541]
+[:mouse_move, 486, 433, 2, 337, 542]
+[:mouse_move, 486, 432, 2, 338, 543]
+[:mouse_move, 486, 430, 2, 339, 545]
+[:mouse_move, 487, 430, 2, 340, 546]
+[:mouse_move, 487, 426, 2, 341, 547]
+[:mouse_move, 486, 424, 2, 342, 548]
+[:mouse_move, 481, 416, 2, 343, 549]
+[:mouse_move, 477, 409, 2, 344, 550]
+[:mouse_move, 471, 401, 2, 345, 551]
+[:mouse_move, 467, 397, 2, 346, 552]
+[:mouse_move, 456, 391, 2, 347, 553]
+[:mouse_move, 451, 391, 2, 348, 554]
+[:mouse_move, 429, 397, 2, 349, 555]
+[:mouse_move, 416, 406, 2, 350, 556]
+[:mouse_move, 383, 429, 2, 351, 557]
+[:mouse_move, 364, 444, 2, 352, 558]
+[:mouse_move, 337, 471, 2, 353, 559]
+[:mouse_move, 322, 487, 2, 354, 560]
+[:mouse_move, 300, 507, 2, 355, 561]
+[:mouse_move, 289, 515, 2, 356, 562]
+[:mouse_move, 285, 518, 2, 357, 563]
+[:mouse_move, 273, 525, 2, 358, 564]
+[:mouse_move, 269, 527, 2, 359, 565]
+[:mouse_move, 266, 528, 2, 360, 566]
+[:mouse_move, 264, 528, 2, 361, 567]
+[:mouse_move, 262, 528, 2, 362, 568]
+[:mouse_move, 261, 528, 2, 363, 569]
+[:mouse_move, 259, 527, 2, 364, 570]
+[:mouse_move, 258, 526, 2, 365, 571]
+[:mouse_move, 257, 526, 2, 366, 572]
+[:key_down_raw, 115, 0, 2, 367, 589]
+[:key_up_raw, 115, 0, 2, 368, 594]
+[:mouse_move, 257, 524, 2, 369, 617]
+[:mouse_move, 259, 521, 2, 370, 618]
+[:mouse_move, 260, 516, 2, 371, 619]
+[:mouse_move, 263, 497, 2, 372, 620]
+[:mouse_move, 263, 484, 2, 373, 621]
+[:mouse_move, 263, 446, 2, 374, 622]
+[:mouse_move, 258, 426, 2, 375, 623]
+[:mouse_move, 250, 389, 2, 376, 624]
+[:mouse_move, 248, 382, 2, 377, 625]
+[:mouse_move, 239, 351, 2, 378, 626]
+[:mouse_move, 235, 339, 2, 379, 627]
+[:mouse_move, 229, 322, 2, 380, 628]
+[:mouse_move, 226, 314, 2, 381, 629]
+[:mouse_move, 222, 305, 2, 382, 630]
+[:mouse_move, 219, 300, 2, 383, 631]
+[:mouse_move, 216, 296, 2, 384, 632]
+[:mouse_move, 215, 293, 2, 385, 633]
+[:mouse_move, 212, 289, 2, 386, 634]
+[:mouse_move, 212, 286, 2, 387, 635]
+[:mouse_move, 209, 280, 2, 388, 636]
+[:mouse_move, 208, 278, 2, 389, 637]
+[:mouse_move, 207, 271, 2, 390, 638]
+[:mouse_move, 206, 269, 2, 391, 639]
+[:mouse_move, 203, 261, 2, 392, 640]
+[:mouse_move, 201, 258, 2, 393, 641]
+[:mouse_move, 198, 252, 2, 394, 642]
+[:mouse_move, 196, 248, 2, 395, 643]
+[:mouse_move, 194, 245, 2, 396, 644]
+[:mouse_move, 192, 242, 2, 397, 645]
+[:mouse_move, 191, 240, 2, 398, 646]
+[:mouse_move, 189, 238, 2, 399, 647]
+[:mouse_move, 189, 237, 2, 400, 648]
+[:mouse_move, 188, 237, 2, 401, 649]
+[:mouse_move, 187, 237, 2, 402, 658]
+[:mouse_move, 187, 236, 2, 403, 659]
+[:mouse_move, 188, 235, 2, 404, 663]
+[:mouse_move, 191, 234, 2, 405, 664]
+[:mouse_move, 215, 232, 2, 406, 665]
+[:mouse_move, 234, 231, 2, 407, 666]
+[:mouse_move, 280, 226, 2, 408, 667]
+[:mouse_move, 305, 224, 2, 409, 668]
+[:mouse_move, 360, 220, 2, 410, 669]
+[:mouse_move, 372, 220, 2, 411, 670]
+[:mouse_move, 417, 219, 2, 412, 671]
+[:mouse_move, 438, 219, 2, 413, 672]
+[:mouse_move, 458, 219, 2, 414, 673]
+[:mouse_move, 493, 220, 2, 415, 674]
+[:mouse_move, 509, 220, 2, 416, 675]
+[:mouse_move, 536, 221, 2, 417, 676]
+[:mouse_move, 548, 222, 2, 418, 677]
+[:mouse_move, 573, 223, 2, 419, 678]
+[:mouse_move, 585, 225, 2, 420, 679]
+[:mouse_move, 610, 226, 2, 421, 680]
+[:mouse_move, 616, 227, 2, 422, 681]
+[:mouse_move, 640, 228, 2, 423, 682]
+[:mouse_move, 659, 228, 2, 424, 683]
+[:mouse_move, 684, 228, 2, 425, 684]
+[:mouse_move, 697, 228, 2, 426, 685]
+[:mouse_move, 730, 228, 2, 427, 686]
+[:mouse_move, 762, 228, 2, 428, 687]
+[:mouse_move, 804, 226, 2, 429, 688]
+[:mouse_move, 827, 224, 2, 430, 689]
+[:mouse_move, 861, 221, 2, 431, 690]
+[:mouse_move, 884, 218, 2, 432, 691]
+[:mouse_move, 923, 213, 2, 433, 692]
+[:mouse_move, 930, 212, 2, 434, 693]
+[:mouse_move, 955, 208, 2, 435, 694]
+[:mouse_move, 966, 206, 2, 436, 695]
+[:mouse_move, 983, 202, 2, 437, 696]
+[:mouse_move, 990, 200, 2, 438, 697]
+[:mouse_move, 1004, 197, 2, 439, 698]
+[:mouse_move, 1009, 197, 2, 440, 699]
+[:mouse_move, 1012, 197, 2, 441, 700]
+[:mouse_move, 1025, 197, 2, 442, 701]
+[:mouse_move, 1028, 197, 2, 443, 702]
+[:mouse_move, 1034, 201, 2, 444, 721]
+[:mouse_move, 1036, 203, 2, 445, 722]
+[:mouse_move, 1041, 208, 2, 446, 723]
+[:mouse_move, 1044, 212, 2, 447, 724]
+[:mouse_move, 1051, 222, 2, 448, 725]
+[:mouse_move, 1054, 229, 2, 449, 726]
+[:mouse_move, 1057, 236, 2, 450, 727]
+[:mouse_move, 1061, 245, 2, 451, 728]
+[:mouse_move, 1064, 254, 2, 452, 729]
+[:mouse_move, 1067, 262, 2, 453, 730]
+[:mouse_move, 1068, 264, 2, 454, 731]
+[:mouse_move, 1070, 270, 2, 455, 732]
+[:mouse_move, 1071, 272, 2, 456, 733]
+[:mouse_move, 1072, 275, 2, 457, 734]
+[:mouse_move, 1072, 277, 2, 458, 735]
+[:mouse_move, 1073, 278, 2, 459, 736]
+[:mouse_move, 1074, 279, 2, 460, 737]
+[:mouse_move, 1075, 280, 2, 461, 738]
+[:mouse_move, 1077, 281, 2, 462, 739]
+[:mouse_move, 1078, 282, 2, 463, 740]
+[:mouse_move, 1080, 282, 2, 464, 741]
+[:mouse_move, 1082, 282, 2, 465, 742]
+[:mouse_move, 1083, 282, 2, 466, 743]
+[:mouse_move, 1084, 282, 2, 467, 744]
+[:mouse_move, 1085, 281, 2, 468, 746]
+[:mouse_move, 1085, 280, 2, 469, 747]
+[:mouse_move, 1086, 280, 2, 470, 748]
+[:mouse_move, 1086, 279, 2, 471, 749]
+[:mouse_move, 1086, 278, 2, 472, 750]
+[:mouse_move, 1087, 278, 2, 473, 751]
+[:mouse_move, 1088, 278, 2, 474, 755]
+[:mouse_move, 1086, 276, 2, 475, 759]
+[:mouse_move, 1082, 273, 2, 476, 760]
+[:mouse_move, 1058, 257, 2, 477, 761]
+[:mouse_move, 1040, 246, 2, 478, 762]
+[:mouse_move, 995, 214, 2, 479, 763]
+[:mouse_move, 968, 195, 2, 480, 764]
+[:mouse_move, 915, 163, 2, 481, 765]
+[:mouse_move, 887, 148, 2, 482, 766]
+[:mouse_move, 853, 131, 2, 483, 767]
+[:mouse_move, 833, 122, 2, 484, 768]
+[:mouse_move, 794, 105, 2, 485, 769]
+[:mouse_move, 776, 99, 2, 486, 770]
+[:mouse_move, 739, 87, 2, 487, 771]
+[:mouse_move, 723, 83, 2, 488, 772]
+[:mouse_move, 690, 76, 2, 489, 773]
+[:mouse_move, 674, 73, 2, 490, 774]
+[:mouse_move, 627, 69, 2, 491, 775]
+[:mouse_move, 607, 69, 2, 492, 776]
+[:mouse_move, 573, 69, 2, 493, 777]
+[:mouse_move, 554, 69, 2, 494, 778]
+[:mouse_move, 519, 69, 2, 495, 779]
+[:mouse_move, 504, 69, 2, 496, 780]
+[:mouse_move, 484, 68, 2, 497, 781]
+[:mouse_move, 473, 67, 2, 498, 782]
+[:mouse_move, 462, 67, 2, 499, 783]
+[:mouse_move, 445, 66, 2, 500, 784]
+[:mouse_move, 430, 66, 2, 501, 785]
+[:mouse_move, 410, 66, 2, 502, 786]
+[:mouse_move, 396, 66, 2, 503, 787]
+[:mouse_move, 367, 68, 2, 504, 788]
+[:mouse_move, 352, 69, 2, 505, 789]
+[:mouse_move, 321, 73, 2, 506, 790]
+[:mouse_move, 307, 75, 2, 507, 791]
+[:mouse_move, 274, 79, 2, 508, 792]
+[:mouse_move, 258, 81, 2, 509, 793]
+[:mouse_move, 248, 82, 2, 510, 794]
+[:mouse_move, 239, 83, 2, 511, 795]
+[:mouse_move, 231, 84, 2, 512, 796]
+[:mouse_move, 228, 84, 2, 513, 797]
+[:mouse_move, 225, 84, 2, 514, 798]
+[:mouse_move, 224, 84, 2, 515, 800]
+[:mouse_move, 221, 85, 2, 516, 802]
+[:mouse_move, 217, 85, 2, 517, 803]
+[:mouse_move, 209, 86, 2, 518, 804]
+[:mouse_move, 204, 86, 2, 519, 805]
+[:mouse_move, 199, 87, 2, 520, 806]
+[:mouse_move, 193, 88, 2, 521, 807]
+[:mouse_move, 186, 88, 2, 522, 808]
+[:mouse_move, 179, 89, 2, 523, 809]
+[:mouse_move, 178, 89, 2, 524, 810]
+[:mouse_move, 173, 89, 2, 525, 811]
+[:mouse_move, 172, 89, 2, 526, 812]
+[:mouse_move, 171, 89, 2, 527, 813]
+[:mouse_move, 170, 89, 2, 528, 814]
+[:mouse_move, 173, 89, 2, 529, 819]
+[:mouse_move, 178, 89, 2, 530, 820]
+[:mouse_move, 184, 89, 2, 531, 821]
+[:mouse_move, 189, 88, 2, 532, 822]
+[:mouse_move, 199, 88, 2, 533, 823]
+[:mouse_move, 209, 88, 2, 534, 824]
+[:mouse_move, 226, 86, 2, 535, 825]
+[:mouse_move, 236, 85, 2, 536, 826]
+[:mouse_move, 261, 84, 2, 537, 827]
+[:mouse_move, 267, 83, 2, 538, 828]
+[:mouse_move, 287, 83, 2, 539, 829]
+[:mouse_move, 296, 83, 2, 540, 830]
+[:mouse_move, 318, 83, 2, 541, 831]
+[:mouse_move, 328, 84, 2, 542, 832]
+[:mouse_move, 341, 85, 2, 543, 833]
+[:mouse_move, 350, 86, 2, 544, 834]
+[:mouse_move, 359, 86, 2, 545, 835]
+[:mouse_move, 368, 87, 2, 546, 836]
+[:mouse_move, 376, 88, 2, 547, 837]
+[:mouse_move, 390, 88, 2, 548, 838]
+[:mouse_move, 394, 88, 2, 549, 839]
+[:mouse_move, 408, 88, 2, 550, 840]
+[:mouse_move, 415, 88, 2, 551, 841]
+[:mouse_move, 428, 87, 2, 552, 842]
+[:mouse_move, 436, 87, 2, 553, 843]
+[:mouse_move, 458, 86, 2, 554, 844]
+[:mouse_move, 468, 85, 2, 555, 845]
+[:mouse_move, 496, 82, 2, 556, 846]
+[:mouse_move, 523, 79, 2, 557, 847]
+[:mouse_move, 539, 77, 2, 558, 848]
+[:mouse_move, 564, 74, 2, 559, 849]
+[:mouse_move, 592, 71, 2, 560, 850]
+[:mouse_move, 605, 70, 2, 561, 851]
+[:mouse_move, 631, 69, 2, 562, 852]
+[:mouse_move, 646, 69, 2, 563, 853]
+[:mouse_move, 672, 69, 2, 564, 854]
+[:mouse_move, 677, 69, 2, 565, 855]
+[:mouse_move, 705, 69, 2, 566, 856]
+[:mouse_move, 709, 69, 2, 567, 857]
+[:mouse_move, 730, 69, 2, 568, 858]
+[:mouse_move, 745, 70, 2, 569, 859]
+[:mouse_move, 769, 71, 2, 570, 860]
+[:mouse_move, 784, 72, 2, 571, 861]
+[:mouse_move, 814, 73, 2, 572, 862]
+[:mouse_move, 830, 73, 2, 573, 863]
+[:mouse_move, 846, 73, 2, 574, 864]
+[:mouse_move, 876, 74, 2, 575, 865]
+[:mouse_move, 892, 74, 2, 576, 866]
+[:mouse_move, 923, 76, 2, 577, 867]
+[:mouse_move, 940, 78, 2, 578, 868]
+[:mouse_move, 972, 81, 2, 579, 869]
+[:mouse_move, 986, 82, 2, 580, 870]
+[:mouse_move, 1014, 85, 2, 581, 871]
+[:mouse_move, 1027, 88, 2, 582, 872]
+[:mouse_move, 1043, 90, 2, 583, 873]
+[:mouse_move, 1053, 92, 2, 584, 874]
+[:mouse_move, 1069, 94, 2, 585, 875]
+[:mouse_move, 1075, 95, 2, 586, 876]
+[:mouse_move, 1083, 96, 2, 587, 877]
+[:mouse_move, 1086, 97, 2, 588, 878]
+[:mouse_move, 1091, 97, 2, 589, 879]
+[:mouse_move, 1092, 97, 2, 590, 880]
+[:mouse_move, 1093, 97, 2, 591, 881]
+[:mouse_move, 1094, 97, 2, 592, 883]
+[:mouse_move, 1094, 106, 2, 593, 898]
+[:mouse_move, 1094, 112, 2, 594, 899]
+[:mouse_move, 1094, 136, 2, 595, 900]
+[:mouse_move, 1094, 142, 2, 596, 901]
+[:mouse_move, 1094, 157, 2, 597, 902]
+[:mouse_move, 1094, 165, 2, 598, 903]
+[:mouse_move, 1094, 182, 2, 599, 904]
+[:mouse_move, 1094, 186, 2, 600, 905]
+[:mouse_move, 1094, 197, 2, 601, 906]
+[:mouse_move, 1093, 200, 2, 602, 907]
+[:mouse_move, 1092, 206, 2, 603, 908]
+[:mouse_move, 1092, 208, 2, 604, 909]
+[:mouse_move, 1092, 210, 2, 605, 910]
+[:mouse_move, 1092, 211, 2, 606, 911]
+[:mouse_move, 1092, 212, 2, 607, 912]
+[:mouse_move, 1092, 213, 2, 608, 913]
+[:mouse_move, 1092, 214, 2, 609, 914]
+[:mouse_move, 1092, 215, 2, 610, 915]
+[:mouse_move, 1092, 220, 2, 611, 916]
+[:mouse_move, 1092, 222, 2, 612, 917]
+[:mouse_move, 1092, 226, 2, 613, 918]
+[:mouse_move, 1092, 236, 2, 614, 919]
+[:mouse_move, 1092, 239, 2, 615, 920]
+[:mouse_move, 1091, 245, 2, 616, 921]
+[:mouse_move, 1091, 248, 2, 617, 922]
+[:mouse_move, 1091, 252, 2, 618, 923]
+[:mouse_move, 1091, 253, 2, 619, 924]
+[:mouse_move, 1091, 255, 2, 620, 925]
+[:mouse_move, 1091, 256, 2, 621, 926]
+[:mouse_move, 1091, 257, 2, 622, 927]
+[:mouse_move, 1091, 258, 2, 623, 928]
+[:mouse_move, 1091, 259, 2, 624, 931]
+[:mouse_move, 1091, 260, 2, 625, 941]
+[:mouse_move, 1091, 261, 2, 626, 942]
+[:mouse_move, 1091, 262, 2, 627, 943]
+[:mouse_move, 1091, 263, 2, 628, 944]
+[:mouse_move, 1091, 264, 2, 629, 945]
+[:mouse_move, 1091, 265, 2, 630, 947]
+[:mouse_move, 1091, 266, 2, 631, 948]
+[:mouse_move, 1091, 267, 2, 632, 949]
+[:mouse_move, 1091, 268, 2, 633, 951]
+[:mouse_button_pressed, 1, 0, 1, 634, 952]
+[:mouse_button_up, 1, 0, 1, 635, 960]
+[:mouse_move, 1090, 268, 2, 636, 1062]
+[:mouse_move, 1089, 269, 2, 637, 1063]
+[:mouse_move, 1084, 271, 2, 638, 1064]
+[:mouse_move, 1079, 272, 2, 639, 1065]
+[:mouse_move, 1070, 277, 2, 640, 1066]
+[:mouse_move, 1065, 279, 2, 641, 1067]
+[:mouse_move, 1060, 282, 2, 642, 1068]
+[:mouse_move, 1057, 283, 2, 643, 1069]
+[:mouse_move, 1053, 286, 2, 644, 1070]
+[:mouse_move, 1052, 286, 2, 645, 1071]
+[:mouse_move, 1052, 287, 2, 646, 1072]
+[:mouse_move, 1051, 287, 2, 647, 1073]
+[:mouse_move, 1051, 288, 2, 648, 1074]
+[:mouse_move, 1051, 289, 2, 649, 1078]
+[:key_down_raw, 115, 0, 2, 650, 1083]
+[:key_up_raw, 115, 0, 2, 651, 1088]
+[:mouse_move, 1050, 289, 2, 652, 1096]
+[:mouse_move, 1042, 294, 2, 653, 1097]
+[:mouse_move, 1032, 300, 2, 654, 1098]
+[:mouse_move, 979, 325, 2, 655, 1099]
+[:mouse_move, 945, 339, 2, 656, 1100]
+[:mouse_move, 803, 383, 2, 657, 1101]
+[:mouse_move, 722, 403, 2, 658, 1102]
+[:mouse_move, 535, 441, 2, 659, 1103]
+[:mouse_move, 441, 454, 2, 660, 1104]
+[:mouse_move, 311, 467, 2, 661, 1105]
+[:mouse_move, 279, 469, 2, 662, 1106]
+[:mouse_move, 214, 470, 2, 663, 1107]
+[:mouse_move, 149, 469, 2, 664, 1108]
+[:mouse_move, 115, 464, 2, 665, 1109]
+[:mouse_move, 98, 459, 2, 666, 1110]
+[:mouse_move, 84, 456, 2, 667, 1111]
+[:mouse_move, 70, 451, 2, 668, 1112]
+[:mouse_move, 67, 449, 2, 669, 1113]
+[:mouse_move, 64, 447, 2, 670, 1114]
+[:mouse_move, 64, 446, 2, 671, 1115]
+[:mouse_move, 63, 446, 2, 672, 1116]
+[:mouse_move, 63, 445, 2, 673, 1117]
+[:mouse_move, 64, 445, 2, 674, 1121]
+[:mouse_move, 71, 445, 2, 675, 1122]
+[:mouse_move, 78, 445, 2, 676, 1123]
+[:mouse_move, 96, 449, 2, 677, 1124]
+[:mouse_move, 101, 451, 2, 678, 1125]
+[:mouse_move, 113, 455, 2, 679, 1126]
+[:mouse_move, 118, 457, 2, 680, 1127]
+[:mouse_move, 124, 460, 2, 681, 1128]
+[:mouse_move, 126, 460, 2, 682, 1129]
+[:mouse_move, 127, 461, 2, 683, 1130]
+[:mouse_move, 128, 461, 2, 684, 1131]
+[:mouse_move, 128, 462, 2, 685, 1132]
+[:mouse_button_pressed, 1, 0, 1, 686, 1137]
+[:mouse_button_up, 1, 0, 1, 687, 1145]
+[:mouse_move, 128, 457, 2, 688, 1155]
+[:mouse_move, 128, 451, 2, 689, 1156]
+[:mouse_move, 128, 420, 2, 690, 1157]
+[:mouse_move, 128, 397, 2, 691, 1158]
+[:mouse_move, 128, 334, 2, 692, 1159]
+[:mouse_move, 128, 298, 2, 693, 1160]
+[:mouse_move, 128, 282, 2, 694, 1161]
+[:mouse_move, 128, 231, 2, 695, 1162]
+[:mouse_move, 128, 222, 2, 696, 1163]
+[:mouse_move, 128, 192, 2, 697, 1164]
+[:mouse_move, 127, 178, 2, 698, 1165]
+[:mouse_move, 126, 172, 2, 699, 1166]
+[:mouse_move, 126, 168, 2, 700, 1167]
+[:mouse_move, 125, 163, 2, 701, 1168]
+[:mouse_move, 125, 162, 2, 702, 1169]
+[:mouse_move, 124, 161, 2, 703, 1170]
+[:mouse_move, 124, 160, 2, 704, 1171]
+[:mouse_move, 123, 160, 2, 705, 1173]
+[:mouse_button_pressed, 1, 0, 1, 706, 1177]
+[:mouse_button_up, 1, 0, 1, 707, 1186]
+[:mouse_move, 126, 160, 2, 708, 1190]
+[:mouse_move, 149, 160, 2, 709, 1191]
+[:mouse_move, 187, 160, 2, 710, 1192]
+[:mouse_move, 240, 156, 2, 711, 1193]
+[:mouse_move, 274, 150, 2, 712, 1194]
+[:mouse_move, 294, 146, 2, 713, 1195]
+[:mouse_move, 311, 141, 2, 714, 1196]
+[:mouse_move, 324, 139, 2, 715, 1197]
+[:mouse_move, 329, 137, 2, 716, 1198]
+[:mouse_move, 335, 136, 2, 717, 1199]
+[:mouse_button_pressed, 1, 0, 1, 718, 1208]
+[:mouse_button_up, 1, 0, 1, 719, 1217]
+[:mouse_move, 331, 149, 2, 720, 1220]
+[:mouse_move, 325, 159, 2, 721, 1221]
+[:mouse_move, 285, 225, 2, 722, 1222]
+[:mouse_move, 238, 300, 2, 723, 1223]
+[:mouse_move, 159, 435, 2, 724, 1224]
+[:mouse_move, 137, 471, 2, 725, 1225]
+[:mouse_move, 82, 563, 2, 726, 1226]
+[:mouse_move, 51, 612, 2, 727, 1227]
+[:mouse_move, 39, 634, 2, 728, 1228]
+[:mouse_move, 28, 654, 2, 729, 1229]
+[:key_down_raw, 1073741903, 0, 2, 730, 1293]
+[:key_down_raw, 1073741903, 0, 2, 731, 1317]
+[:key_down_raw, 1073741903, 0, 2, 732, 1319]
+[:key_down_raw, 1073741903, 0, 2, 733, 1321]
+[:key_down_raw, 1073741903, 0, 2, 734, 1323]
+[:key_down_raw, 1073741903, 0, 2, 735, 1325]
+[:key_down_raw, 1073741903, 0, 2, 736, 1327]
+[:key_down_raw, 1073741903, 0, 2, 737, 1330]
+[:key_down_raw, 1073741903, 0, 2, 738, 1332]
+[:key_down_raw, 1073741903, 0, 2, 739, 1334]
+[:key_down_raw, 1073741903, 0, 2, 740, 1336]
+[:key_down_raw, 1073741903, 0, 2, 741, 1338]
+[:key_down_raw, 1073741903, 0, 2, 742, 1340]
+[:key_up_raw, 1073741903, 0, 2, 743, 1341]
+[:key_down_raw, 1073741904, 0, 2, 744, 1341]
+[:key_down_raw, 1073741903, 0, 2, 745, 1366]
+[:key_up_raw, 1073741904, 0, 2, 746, 1369]
+[:key_down_raw, 1073741903, 0, 2, 747, 1391]
+[:key_down_raw, 1073741903, 0, 2, 748, 1393]
+[:key_down_raw, 1073741903, 0, 2, 749, 1395]
+[:key_down_raw, 1073741904, 0, 2, 750, 1397]
+[:key_up_raw, 1073741903, 0, 2, 751, 1398]
+[:key_down_raw, 32, 0, 2, 752, 1417]
+[:key_down_raw, 1073741903, 0, 2, 753, 1420]
+[:key_up_raw, 1073741904, 0, 2, 754, 1421]
+[:key_down_raw, 1073741904, 0, 2, 755, 1437]
+[:key_up_raw, 1073741903, 0, 2, 756, 1438]
+[:key_down_raw, 1073741904, 0, 2, 757, 1462]
+[:key_down_raw, 1073741904, 0, 2, 758, 1464]
+[:key_down_raw, 1073741904, 0, 2, 759, 1466]
+[:key_down_raw, 1073741904, 0, 2, 760, 1468]
+[:key_down_raw, 1073741904, 0, 2, 761, 1470]
+[:key_down_raw, 1073741904, 0, 2, 762, 1472]
+[:key_down_raw, 1073741904, 0, 2, 763, 1474]
+[:key_down_raw, 1073741903, 0, 2, 764, 1475]
+[:key_up_raw, 1073741904, 0, 2, 765, 1490]
+[:key_down_raw, 1073741903, 0, 2, 766, 1500]
+[:key_down_raw, 1073741903, 0, 2, 767, 1502]
+[:key_down_raw, 1073741903, 0, 2, 768, 1504]
+[:key_down_raw, 1073741903, 0, 2, 769, 1506]
+[:key_down_raw, 1073741903, 0, 2, 770, 1508]
+[:key_down_raw, 1073741903, 0, 2, 771, 1510]
+[:key_down_raw, 1073741903, 0, 2, 772, 1512]
+[:key_up_raw, 32, 0, 2, 773, 1514]
+[:key_down_raw, 1073741903, 0, 2, 774, 1514]
+[:key_down_raw, 1073741903, 0, 2, 775, 1516]
+[:key_up_raw, 1073741903, 0, 2, 776, 1516]
+[:mouse_move, 30, 645, 2, 777, 1626]
+[:mouse_move, 51, 614, 2, 778, 1627]
+[:mouse_move, 61, 599, 2, 779, 1628]
+[:mouse_move, 84, 572, 2, 780, 1629]
+[:mouse_move, 95, 562, 2, 781, 1630]
+[:mouse_move, 110, 552, 2, 782, 1631]
+[:mouse_move, 122, 543, 2, 783, 1632]
+[:mouse_move, 132, 538, 2, 784, 1633]
+[:mouse_move, 137, 536, 2, 785, 1634]
+[:mouse_move, 142, 534, 2, 786, 1635]
+[:mouse_move, 143, 534, 2, 787, 1636]
+[:mouse_move, 144, 534, 2, 788, 1637]
+[:mouse_move, 144, 533, 2, 789, 1641]
+[:mouse_move, 144, 532, 2, 790, 1642]
+[:mouse_move, 145, 527, 2, 791, 1643]
+[:mouse_move, 147, 522, 2, 792, 1644]
+[:mouse_move, 157, 500, 2, 793, 1645]
+[:mouse_move, 160, 493, 2, 794, 1646]
+[:mouse_move, 168, 478, 2, 795, 1647]
+[:mouse_move, 169, 474, 2, 796, 1648]
+[:mouse_move, 175, 463, 2, 797, 1649]
+[:mouse_move, 177, 460, 2, 798, 1650]
+[:mouse_move, 179, 455, 2, 799, 1651]
+[:mouse_move, 179, 453, 2, 800, 1652]
+[:mouse_move, 179, 451, 2, 801, 1653]
+[:mouse_move, 179, 448, 2, 802, 1654]
+[:mouse_move, 179, 447, 2, 803, 1655]
+[:mouse_move, 179, 445, 2, 804, 1656]
+[:mouse_move, 178, 444, 2, 805, 1657]
+[:mouse_move, 177, 443, 2, 806, 1658]
+[:mouse_move, 175, 441, 2, 807, 1660]
+[:mouse_move, 174, 440, 2, 808, 1661]
+[:mouse_move, 173, 438, 2, 809, 1662]
+[:mouse_move, 172, 437, 2, 810, 1664]
+[:mouse_move, 171, 437, 2, 811, 1666]
+[:mouse_button_pressed, 1, 0, 1, 812, 1674]
+[:mouse_button_up, 1, 0, 1, 813, 1681]
+[:key_down_raw, 1073742051, 1024, 2, 814, 1894]
+[:key_down_raw, 113, 1024, 2, 815, 1896]
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image1.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image1.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image1.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image10.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image10.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image10.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image11.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image11.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image11.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image12.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image12.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image12.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image13.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image13.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image13.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image14.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image14.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image14.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image15.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image15.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image15.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image16.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image16.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image16.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image17.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image17.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image17.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image18.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image18.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image18.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image19.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image19.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image19.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image2.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image2.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image2.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image20.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image20.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image20.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image3.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image3.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image3.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image4.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image4.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image4.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image5.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image5.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image5.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image6.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image6.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image6.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image7.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image7.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image7.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image8.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image8.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image8.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/image9.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image9.png
new file mode 100644
index 0000000..b0eb399
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/image9.png
Binary files differ
diff --git a/samples/04_physics_and_collisions/05_box_collision_2/sprites/player.png b/samples/04_physics_and_collisions/05_box_collision_2/sprites/player.png
new file mode 100644
index 0000000..4c733a2
--- /dev/null
+++ b/samples/04_physics_and_collisions/05_box_collision_2/sprites/player.png
Binary files differ