summaryrefslogtreecommitdiffhomepage
path: root/samples/99_genre_crafting
diff options
context:
space:
mode:
Diffstat (limited to 'samples/99_genre_crafting')
-rw-r--r--samples/99_genre_crafting/farming_game_starting_point/app/main.rb84
-rw-r--r--samples/99_genre_crafting/farming_game_starting_point/app/repl.rb307
-rw-r--r--samples/99_genre_crafting/farming_game_starting_point/app/tests.rb29
-rw-r--r--samples/99_genre_crafting/farming_game_starting_point/replay.txt170
-rw-r--r--samples/99_genre_crafting/farming_game_starting_point/sprites/background.pngbin0 -> 29236 bytes
-rw-r--r--samples/99_genre_crafting/replay.txt170
6 files changed, 760 insertions, 0 deletions
diff --git a/samples/99_genre_crafting/farming_game_starting_point/app/main.rb b/samples/99_genre_crafting/farming_game_starting_point/app/main.rb
new file mode 100644
index 0000000..4c7dd61
--- /dev/null
+++ b/samples/99_genre_crafting/farming_game_starting_point/app/main.rb
@@ -0,0 +1,84 @@
+def tick args
+ args.state.tile_size = 80
+ args.state.player_speed = 4
+ args.state.player ||= tile(args, 7, 3, 0, 128, 180)
+ generate_map args
+ #press j to plant a green onion
+ if args.inputs.keyboard.j
+ #change this part you can change what you want to plant
+ args.state.walls << tile(args, ((args.state.player.x+80)/args.state.tile_size), ((args.state.player.y)/args.state.tile_size), 255, 255, 255)
+ args.state.plants << tile(args, ((args.state.player.x+80)/args.state.tile_size), ((args.state.player.y+80)/args.state.tile_size), 0, 160, 0)
+ end
+ # Adds walls, background, and player to args.outputs.solids so they appear on screen
+ args.outputs.solids << [0,0,1280,720, 237,189,101]
+ args.outputs.sprites << [0, 0, 1280, 720, 'sprites/background.png']
+ args.outputs.solids << args.state.walls
+ args.outputs.solids << args.state.player
+ args.outputs.solids << args.state.plants
+ args.outputs.labels << [320, 640, "press J to plant", 3, 1, 255, 0, 0, 200]
+
+ move_player args, -1, 0 if args.inputs.keyboard.left # x position decreases by 1 if left key is pressed
+ move_player args, 1, 0 if args.inputs.keyboard.right # x position increases by 1 if right key is pressed
+ move_player args, 0, 1 if args.inputs.keyboard.up # y position increases by 1 if up is pressed
+ move_player args, 0, -1 if args.inputs.keyboard.down # y position decreases by 1 if down is pressed
+end
+
+# Sets position, size, and color of the tile
+def tile args, x, y, *color
+ [x * args.state.tile_size, # sets definition for array using method parameters
+ y * args.state.tile_size, # multiplying by tile_size sets x and y to correct position using pixel values
+ args.state.tile_size,
+ args.state.tile_size,
+ *color]
+end
+
+# Creates map by adding tiles to the wall, as well as a goal (that the player needs to reach)
+def generate_map args
+ return if args.state.area
+
+ # Creates the area of the map. There are 9 rows running horizontally across the screen
+ # and 16 columns running vertically on the screen. Any spot with a "1" is not
+ # open for the player to move into (and is green), and any spot with a "0" is available
+ # for the player to move in.
+ args.state.area = [
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
+ [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,],
+ [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,],
+ [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,],
+ [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,],
+ [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,],
+ [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,],
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
+ ].reverse # reverses the order of the area collection
+
+ # By reversing the order, the way that the area appears above is how it appears
+ # on the screen in the game. If we did not reverse, the map would appear inverted.
+
+ #The wall starts off with no tiles.
+ args.state.walls = []
+ args.state.plants = []
+
+ # If v is 1, a green tile is added to args.state.walls.
+ # If v is 2, a black tile is created as the goal.
+ args.state.area.map_2d do |y, x, v|
+ if v == 1
+ args.state.walls << tile(args, x, y, 255, 160, 156) # green tile
+ end
+ end
+end
+
+# Allows the player to move their box around the screen
+def move_player args, *vector
+ box = args.state.player.shift_rect(vector) # box is able to move at an angle
+
+ # If the player's box hits a wall, it is not able to move further in that direction
+ return if args.state.walls
+ .any_intersect_rect?(box)
+
+ # Player's box is able to move at angles (not just the four general directions) fast
+ args.state.player =
+ args.state.player
+ .shift_rect(vector.x * args.state.player_speed, # if we don't multiply by speed, then
+ vector.y * args.state.player_speed) # the box will move extremely slow
+end
diff --git a/samples/99_genre_crafting/farming_game_starting_point/app/repl.rb b/samples/99_genre_crafting/farming_game_starting_point/app/repl.rb
new file mode 100644
index 0000000..f4c8292
--- /dev/null
+++ b/samples/99_genre_crafting/farming_game_starting_point/app/repl.rb
@@ -0,0 +1,307 @@
+# ===============================================================
+# Welcome to repl.rb
+# ===============================================================
+# You can experiement with code within this file. Code in this
+# file is only executed when you save (and only excecuted ONCE).
+# ===============================================================
+
+# ===============================================================
+# REMOVE the "x" from the word "xrepl" and save the file to RUN
+# the code in between the do/end block delimiters.
+# ===============================================================
+
+# ===============================================================
+# ADD the "x" to the word "repl" (make it xrepl) and save the
+# file to IGNORE the code in between the do/end block delimiters.
+# ===============================================================
+
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ puts "The result of 1 + 2 is: #{1 + 2}"
+end
+
+# ====================================================================================
+# Ruby Crash Course:
+# Strings, Numeric, Booleans, Conditionals, Looping, Enumerables, Arrays
+# ====================================================================================
+
+# ====================================================================================
+# Strings
+# ====================================================================================
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ message = "Hello World"
+ puts "The value of message is: " + message
+ puts "Any value can be interpolated within a string using \#{}."
+ puts "Interpolated message: #{message}."
+ puts 'This #{message} is not interpolated because the string uses single quotes.'
+end
+
+# ====================================================================================
+# Numerics
+# ====================================================================================
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ a = 10
+ puts "The value of a is: #{a}"
+ puts "a + 1 is: #{a + 1}"
+ puts "a / 3 is: #{a / 3}"
+end
+
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ b = 10.12
+ puts "The value of b is: #{b}"
+ puts "b + 1 is: #{b + 1}"
+ puts "b as an integer is: #{b.to_i}"
+ puts ''
+end
+
+# ====================================================================================
+# Booleans
+# ====================================================================================
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ c = 30
+ puts "The value of c is #{c}."
+
+ if c
+ puts "This if statement ran because c is truthy."
+ end
+end
+
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ d = false
+ puts "The value of d is #{d}."
+
+ if !d
+ puts "This if statement ran because d is falsey, using the not operator (!) makes d evaluate to true."
+ end
+
+ e = nil
+ puts "Nil is also considered falsey. The value of e is: #{e}."
+
+ if !e
+ puts "This if statement ran because e is nil (a falsey value)."
+ end
+end
+
+# ====================================================================================
+# Conditionals
+# ====================================================================================
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ i_am_true = true
+ i_am_nil = nil
+ i_am_false = false
+ i_am_hi = "hi"
+
+ puts "======== if statement"
+ i_am_one = 1
+ if i_am_one
+ puts "This was printed because i_am_one is truthy."
+ end
+
+ puts "======== if/else statement"
+ if i_am_false
+ puts "This will NOT get printed because i_am_false is false."
+ else
+ puts "This was printed because i_am_false is false."
+ end
+
+ puts "======== if/elsif/else statement"
+ if i_am_false
+ puts "This will NOT get printed because i_am_false is false."
+ elsif i_am_true
+ puts "This was printed because i_am_true is true."
+ else
+ puts "This will NOT get printed i_am_true was true."
+ end
+
+ puts "======== case statement "
+ i_am_one = 1
+ case i_am_one
+ when 10
+ puts "case equaled: 10"
+ when 9
+ puts "case equaled: 9"
+ when 5
+ puts "case equaled: 5"
+ when 1
+ puts "case equaled: 1"
+ else
+ puts "Value wasn't cased."
+ end
+
+ puts "======== different types of comparisons"
+ if 4 == 4
+ puts "equal (4 == 4)"
+ end
+
+ if 4 != 3
+ puts "not equal (4 != 3)"
+ end
+
+ if 3 < 4
+ puts "less than (3 < 4)"
+ end
+
+ if 4 > 3
+ puts "greater than (4 > 3)"
+ end
+
+ if ((4 > 3) || (3 < 4) || false)
+ puts "or statement ((4 > 3) || (3 < 4) || false)"
+ end
+
+ if ((4 > 3) && (3 < 4))
+ puts "and statement ((4 > 3) && (3 < 4))"
+ end
+end
+
+# ====================================================================================
+# Looping
+# ====================================================================================
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ puts "======== times block"
+ 3.times do |i|
+ puts i
+ end
+ puts "======== range block exclusive"
+ (0...3).each do |i|
+ puts i
+ end
+ puts "======== range block inclusive"
+ (0..3).each do |i|
+ puts i
+ end
+end
+
+# ====================================================================================
+# Enumerables
+# ====================================================================================
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ puts "======== array each"
+ colors = ["red", "blue", "yellow"]
+ colors.each do |color|
+ puts color
+ end
+
+ puts '======== array each_with_index'
+ colors = ["red", "blue", "yellow"]
+ colors.each_with_index do |color, i|
+ puts "#{color} at index #{i}"
+ end
+end
+
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ puts "======== single parameter function"
+ def add_one_to n
+ n + 5
+ end
+
+ puts add_one_to(3)
+
+ puts "======== function with default value"
+ def function_with_default_value v = 10
+ v * 10
+ end
+
+ puts "passing three: #{function_with_default_value(3)}"
+ puts "passing nil: #{function_with_default_value}"
+
+ puts "======== Or Equal (||=) operator for nil values"
+ def function_with_nil_default_with_local a = nil
+ result = a
+ result ||= "or equal operator was exected and set a default value"
+ end
+
+ puts "passing 'hi': #{function_with_nil_default_with_local 'hi'}"
+ puts "passing nil: #{function_with_nil_default_with_local}"
+end
+
+# ====================================================================================
+# Arrays
+# ====================================================================================
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ puts "======== Create an array with the numbers 1 to 10."
+ one_to_ten = (1..10).to_a
+ puts one_to_ten
+
+ puts "======== Create a new array that only contains even numbers from the previous array."
+ one_to_ten = (1..10).to_a
+ evens = one_to_ten.find_all do |number|
+ number % 2 == 0
+ end
+ puts evens
+
+ puts "======== Create a new array that rejects odd numbers."
+ one_to_ten = (1..10).to_a
+ also_even = one_to_ten.reject do |number|
+ number % 2 != 0
+ end
+ puts also_even
+
+ puts "======== Create an array that doubles every number."
+ one_to_ten = (1..10).to_a
+ doubled = one_to_ten.map do |number|
+ number * 2
+ end
+ puts doubled
+
+ puts "======== Create an array that selects only odd numbers and then multiply those by 10."
+ one_to_ten = (1..10).to_a
+ odd_doubled = one_to_ten.find_all do |number|
+ number % 2 != 0
+ end.map do |odd_number|
+ odd_number * 10
+ end
+ puts odd_doubled
+
+ puts "======== All combination of numbers 1 to 10."
+ one_to_ten = (1..10).to_a
+ all_combinations = one_to_ten.product(one_to_ten)
+ puts all_combinations
+
+ puts "======== All uniq combinations of numbers. For example: [1, 2] is the same as [2, 1]."
+ one_to_ten = (1..10).to_a
+ uniq_combinations =
+ one_to_ten.product(one_to_ten)
+ .map do |unsorted_number|
+ unsorted_number.sort
+ end.uniq
+ puts uniq_combinations
+end
+
+# ====================================================================================
+# Advanced Arrays
+# ====================================================================================
+# Remove the x from xrepl to run the code. Add the x back to ignore to code.
+xrepl do
+ puts "======== All unique Pythagorean Triples between 1 and 40 sorted by area of the triangle."
+
+ one_to_hundred = (1..40).to_a
+ triples =
+ one_to_hundred.product(one_to_hundred).map do |width, height|
+ [width, height, Math.sqrt(width ** 2 + height ** 2)]
+ end.find_all do |_, _, hypotenuse|
+ hypotenuse.to_i == hypotenuse
+ end.map do |triangle|
+ triangle.map(&:to_i)
+ end.uniq do |triangle|
+ triangle.sort
+ end.map do |width, height, hypotenuse|
+ [width, height, hypotenuse, (width * height) / 2]
+ end.sort_by do |_, _, _, area|
+ area
+ end
+
+ triples.each do |width, height, hypotenuse, area|
+ puts "(#{width}, #{height}, #{hypotenuse}) = #{area}"
+ end
+end
diff --git a/samples/99_genre_crafting/farming_game_starting_point/app/tests.rb b/samples/99_genre_crafting/farming_game_starting_point/app/tests.rb
new file mode 100644
index 0000000..458bc18
--- /dev/null
+++ b/samples/99_genre_crafting/farming_game_starting_point/app/tests.rb
@@ -0,0 +1,29 @@
+# For advanced users:
+# You can put some quick verification tests here, any method
+# that starts with the `test_` will be run when you save this file.
+
+# Here is an example test and game
+
+# To run the test: ./dragonruby mygame --eval app/tests.rb --no-tick
+
+class MySuperHappyFunGame
+ attr_gtk
+
+ def tick
+ outputs.solids << [100, 100, 300, 300]
+ end
+end
+
+def test_universe args, assert
+ game = MySuperHappyFunGame.new
+ game.args = args
+ game.tick
+ assert.true! args.outputs.solids.length == 1, "failure: a solid was not added after tick"
+ assert.false! 1 == 2, "failure: some how, 1 equals 2, the world is ending"
+ puts "test_universe completed successfully"
+end
+
+puts "running tests"
+$gtk.reset 100
+$gtk.log_level = :off
+$gtk.tests.start
diff --git a/samples/99_genre_crafting/farming_game_starting_point/replay.txt b/samples/99_genre_crafting/farming_game_starting_point/replay.txt
new file mode 100644
index 0000000..740810d
--- /dev/null
+++ b/samples/99_genre_crafting/farming_game_starting_point/replay.txt
@@ -0,0 +1,170 @@
+replay_version 2.0
+stopped_at 851
+seed 100
+recorded_at 2021-11-20 11:30:20 -0600
+[:mouse_button_up, 1, 0, 1, 1, 4]
+[:key_down_raw, 1073741904, 0, 2, 2, 69]
+[:key_down_raw, 1073741904, 0, 2, 3, 83]
+[:key_up_raw, 1073741904, 0, 2, 4, 84]
+[:key_down_raw, 1073741906, 0, 2, 5, 89]
+[:key_down_raw, 1073741903, 0, 2, 6, 95]
+[:key_up_raw, 1073741906, 0, 2, 7, 103]
+[:key_down_raw, 1073741903, 0, 2, 8, 110]
+[:key_down_raw, 1073741903, 0, 2, 9, 112]
+[:key_down_raw, 1073741903, 0, 2, 10, 114]
+[:key_down_raw, 1073741903, 0, 2, 11, 116]
+[:key_down_raw, 1073741903, 0, 2, 12, 118]
+[:key_down_raw, 1073741903, 0, 2, 13, 120]
+[:key_down_raw, 1073741903, 0, 2, 14, 122]
+[:key_down_raw, 1073741903, 0, 2, 15, 124]
+[:key_up_raw, 1073741903, 0, 2, 16, 125]
+[:key_down_raw, 106, 0, 2, 17, 147]
+[:key_up_raw, 106, 0, 2, 18, 156]
+[:key_down_raw, 1073741904, 0, 2, 19, 180]
+[:key_down_raw, 1073741904, 0, 2, 20, 195]
+[:key_down_raw, 1073741904, 0, 2, 21, 197]
+[:key_down_raw, 1073741904, 0, 2, 22, 199]
+[:key_down_raw, 1073741904, 0, 2, 23, 201]
+[:key_down_raw, 1073741904, 0, 2, 24, 203]
+[:key_down_raw, 1073741904, 0, 2, 25, 205]
+[:key_up_raw, 1073741904, 0, 2, 26, 207]
+[:key_down_raw, 1073741903, 0, 2, 27, 208]
+[:key_down_raw, 1073741903, 0, 2, 28, 223]
+[:key_down_raw, 1073741903, 0, 2, 29, 225]
+[:key_down_raw, 1073741903, 0, 2, 30, 227]
+[:key_down_raw, 1073741903, 0, 2, 31, 229]
+[:key_down_raw, 1073741903, 0, 2, 32, 231]
+[:key_down_raw, 1073741903, 0, 2, 33, 233]
+[:key_down_raw, 1073741903, 0, 2, 34, 235]
+[:key_down_raw, 1073741903, 0, 2, 35, 237]
+[:key_down_raw, 1073741903, 0, 2, 36, 239]
+[:key_down_raw, 1073741903, 0, 2, 37, 241]
+[:key_down_raw, 1073741903, 0, 2, 38, 243]
+[:key_down_raw, 1073741903, 0, 2, 39, 245]
+[:key_down_raw, 1073741903, 0, 2, 40, 247]
+[:key_down_raw, 1073741903, 0, 2, 41, 249]
+[:key_down_raw, 1073741903, 0, 2, 42, 251]
+[:key_down_raw, 1073741903, 0, 2, 43, 253]
+[:key_down_raw, 1073741903, 0, 2, 44, 255]
+[:key_down_raw, 1073741906, 0, 2, 45, 257]
+[:key_up_raw, 1073741903, 0, 2, 46, 258]
+[:key_down_raw, 1073741906, 0, 2, 47, 271]
+[:key_down_raw, 1073741906, 0, 2, 48, 274]
+[:key_down_raw, 1073741906, 0, 2, 49, 276]
+[:key_down_raw, 1073741906, 0, 2, 50, 278]
+[:key_down_raw, 1073741906, 0, 2, 51, 280]
+[:key_up_raw, 1073741906, 0, 2, 52, 280]
+[:key_down_raw, 1073741903, 0, 2, 53, 280]
+[:key_down_raw, 1073741903, 0, 2, 54, 296]
+[:key_down_raw, 1073741903, 0, 2, 55, 298]
+[:key_down_raw, 1073741905, 0, 2, 56, 298]
+[:key_up_raw, 1073741903, 0, 2, 57, 300]
+[:key_down_raw, 1073741905, 0, 2, 58, 313]
+[:key_down_raw, 1073741905, 0, 2, 59, 315]
+[:key_down_raw, 1073741905, 0, 2, 60, 317]
+[:key_down_raw, 1073741905, 0, 2, 61, 319]
+[:key_down_raw, 1073741905, 0, 2, 62, 321]
+[:key_down_raw, 1073741905, 0, 2, 63, 323]
+[:key_down_raw, 1073741905, 0, 2, 64, 325]
+[:key_down_raw, 1073741905, 0, 2, 65, 327]
+[:key_down_raw, 1073741905, 0, 2, 66, 329]
+[:key_down_raw, 1073741904, 0, 2, 67, 330]
+[:key_up_raw, 1073741905, 0, 2, 68, 332]
+[:key_down_raw, 1073741904, 0, 2, 69, 345]
+[:key_down_raw, 1073741904, 0, 2, 70, 347]
+[:key_down_raw, 1073741904, 0, 2, 71, 349]
+[:key_down_raw, 1073741904, 0, 2, 72, 351]
+[:key_up_raw, 1073741904, 0, 2, 73, 353]
+[:key_down_raw, 1073741903, 0, 2, 74, 354]
+[:key_down_raw, 1073741903, 0, 2, 75, 369]
+[:key_down_raw, 1073741903, 0, 2, 76, 371]
+[:key_down_raw, 1073741903, 0, 2, 77, 373]
+[:key_down_raw, 1073741903, 0, 2, 78, 375]
+[:key_down_raw, 1073741903, 0, 2, 79, 377]
+[:key_down_raw, 1073741903, 0, 2, 80, 379]
+[:key_down_raw, 1073741903, 0, 2, 81, 382]
+[:key_down_raw, 1073741903, 0, 2, 82, 383]
+[:key_down_raw, 1073741903, 0, 2, 83, 385]
+[:key_down_raw, 1073741903, 0, 2, 84, 387]
+[:key_down_raw, 1073741903, 0, 2, 85, 390]
+[:key_down_raw, 1073741903, 0, 2, 86, 392]
+[:key_down_raw, 1073741903, 0, 2, 87, 394]
+[:key_down_raw, 1073741905, 0, 2, 88, 395]
+[:key_up_raw, 1073741903, 0, 2, 89, 400]
+[:key_down_raw, 1073741904, 0, 2, 90, 405]
+[:key_up_raw, 1073741905, 0, 2, 91, 416]
+[:key_down_raw, 1073741904, 0, 2, 92, 420]
+[:key_down_raw, 1073741904, 0, 2, 93, 422]
+[:key_down_raw, 1073741904, 0, 2, 94, 424]
+[:key_down_raw, 1073741904, 0, 2, 95, 426]
+[:key_down_raw, 1073741904, 0, 2, 96, 428]
+[:key_down_raw, 1073741904, 0, 2, 97, 430]
+[:key_down_raw, 1073741904, 0, 2, 98, 432]
+[:key_down_raw, 1073741904, 0, 2, 99, 434]
+[:key_down_raw, 1073741904, 0, 2, 100, 436]
+[:key_down_raw, 1073741904, 0, 2, 101, 438]
+[:key_down_raw, 1073741904, 0, 2, 102, 440]
+[:key_down_raw, 1073741904, 0, 2, 103, 442]
+[:key_down_raw, 1073741904, 0, 2, 104, 444]
+[:key_up_raw, 1073741904, 0, 2, 105, 444]
+[:key_down_raw, 1073741906, 0, 2, 106, 445]
+[:key_up_raw, 1073741906, 0, 2, 107, 448]
+[:key_down_raw, 1073741905, 0, 2, 108, 452]
+[:key_down_raw, 1073741905, 0, 2, 109, 467]
+[:key_down_raw, 1073741905, 0, 2, 110, 469]
+[:key_up_raw, 1073741905, 0, 2, 111, 470]
+[:key_down_raw, 1073741906, 0, 2, 112, 484]
+[:key_up_raw, 1073741906, 0, 2, 113, 496]
+[:key_down_raw, 32, 0, 2, 114, 499]
+[:key_up_raw, 32, 0, 2, 115, 505]
+[:key_down_raw, 1073741903, 0, 2, 116, 538]
+[:key_up_raw, 1073741903, 0, 2, 117, 553]
+[:key_down_raw, 106, 0, 2, 118, 604]
+[:key_up_raw, 106, 0, 2, 119, 608]
+[:key_down_raw, 1073741903, 0, 2, 120, 640]
+[:key_down_raw, 1073741906, 0, 2, 121, 654]
+[:key_up_raw, 1073741903, 0, 2, 122, 654]
+[:key_down_raw, 1073741906, 0, 2, 123, 669]
+[:key_down_raw, 1073741906, 0, 2, 124, 671]
+[:key_down_raw, 1073741906, 0, 2, 125, 673]
+[:key_down_raw, 1073741906, 0, 2, 126, 675]
+[:key_up_raw, 1073741906, 0, 2, 127, 677]
+[:key_down_raw, 1073741903, 0, 2, 128, 677]
+[:key_down_raw, 1073741903, 0, 2, 129, 692]
+[:key_down_raw, 1073741903, 0, 2, 130, 694]
+[:key_down_raw, 1073741905, 0, 2, 131, 694]
+[:key_up_raw, 1073741903, 0, 2, 132, 696]
+[:key_down_raw, 1073741905, 0, 2, 133, 709]
+[:key_down_raw, 1073741905, 0, 2, 134, 711]
+[:key_down_raw, 1073741905, 0, 2, 135, 713]
+[:key_down_raw, 1073741905, 0, 2, 136, 715]
+[:key_down_raw, 1073741905, 0, 2, 137, 717]
+[:key_down_raw, 1073741904, 0, 2, 138, 719]
+[:key_up_raw, 1073741905, 0, 2, 139, 721]
+[:key_down_raw, 1073741904, 0, 2, 140, 734]
+[:key_down_raw, 1073741904, 0, 2, 141, 736]
+[:key_down_raw, 1073741904, 0, 2, 142, 738]
+[:key_down_raw, 1073741904, 0, 2, 143, 740]
+[:key_down_raw, 1073741904, 0, 2, 144, 742]
+[:key_down_raw, 1073741904, 0, 2, 145, 744]
+[:key_down_raw, 1073741904, 0, 2, 146, 746]
+[:key_down_raw, 1073741904, 0, 2, 147, 748]
+[:key_up_raw, 1073741904, 0, 2, 148, 748]
+[:key_down_raw, 96, 0, 2, 149, 778]
+[:key_up_raw, 96, 0, 2, 150, 782]
+[:mouse_move, 782, 86, 2, 151, 822]
+[:mouse_move, 774, 93, 2, 152, 823]
+[:mouse_move, 764, 101, 2, 153, 824]
+[:mouse_move, 752, 113, 2, 154, 825]
+[:mouse_move, 732, 126, 2, 155, 826]
+[:mouse_move, 716, 141, 2, 156, 827]
+[:mouse_move, 705, 152, 2, 157, 828]
+[:mouse_move, 699, 162, 2, 158, 829]
+[:mouse_move, 693, 172, 2, 159, 830]
+[:mouse_move, 690, 177, 2, 160, 831]
+[:mouse_move, 690, 176, 2, 161, 839]
+[:mouse_move, 691, 175, 2, 162, 840]
+[:mouse_move, 693, 173, 2, 163, 841]
+[:mouse_move, 695, 173, 2, 164, 842]
+[:mouse_move, 695, 172, 2, 165, 844]
+[:key_down_raw, 13, 0, 2, 166, 851]
diff --git a/samples/99_genre_crafting/farming_game_starting_point/sprites/background.png b/samples/99_genre_crafting/farming_game_starting_point/sprites/background.png
new file mode 100644
index 0000000..dbda37e
--- /dev/null
+++ b/samples/99_genre_crafting/farming_game_starting_point/sprites/background.png
Binary files differ
diff --git a/samples/99_genre_crafting/replay.txt b/samples/99_genre_crafting/replay.txt
new file mode 100644
index 0000000..740810d
--- /dev/null
+++ b/samples/99_genre_crafting/replay.txt
@@ -0,0 +1,170 @@
+replay_version 2.0
+stopped_at 851
+seed 100
+recorded_at 2021-11-20 11:30:20 -0600
+[:mouse_button_up, 1, 0, 1, 1, 4]
+[:key_down_raw, 1073741904, 0, 2, 2, 69]
+[:key_down_raw, 1073741904, 0, 2, 3, 83]
+[:key_up_raw, 1073741904, 0, 2, 4, 84]
+[:key_down_raw, 1073741906, 0, 2, 5, 89]
+[:key_down_raw, 1073741903, 0, 2, 6, 95]
+[:key_up_raw, 1073741906, 0, 2, 7, 103]
+[:key_down_raw, 1073741903, 0, 2, 8, 110]
+[:key_down_raw, 1073741903, 0, 2, 9, 112]
+[:key_down_raw, 1073741903, 0, 2, 10, 114]
+[:key_down_raw, 1073741903, 0, 2, 11, 116]
+[:key_down_raw, 1073741903, 0, 2, 12, 118]
+[:key_down_raw, 1073741903, 0, 2, 13, 120]
+[:key_down_raw, 1073741903, 0, 2, 14, 122]
+[:key_down_raw, 1073741903, 0, 2, 15, 124]
+[:key_up_raw, 1073741903, 0, 2, 16, 125]
+[:key_down_raw, 106, 0, 2, 17, 147]
+[:key_up_raw, 106, 0, 2, 18, 156]
+[:key_down_raw, 1073741904, 0, 2, 19, 180]
+[:key_down_raw, 1073741904, 0, 2, 20, 195]
+[:key_down_raw, 1073741904, 0, 2, 21, 197]
+[:key_down_raw, 1073741904, 0, 2, 22, 199]
+[:key_down_raw, 1073741904, 0, 2, 23, 201]
+[:key_down_raw, 1073741904, 0, 2, 24, 203]
+[:key_down_raw, 1073741904, 0, 2, 25, 205]
+[:key_up_raw, 1073741904, 0, 2, 26, 207]
+[:key_down_raw, 1073741903, 0, 2, 27, 208]
+[:key_down_raw, 1073741903, 0, 2, 28, 223]
+[:key_down_raw, 1073741903, 0, 2, 29, 225]
+[:key_down_raw, 1073741903, 0, 2, 30, 227]
+[:key_down_raw, 1073741903, 0, 2, 31, 229]
+[:key_down_raw, 1073741903, 0, 2, 32, 231]
+[:key_down_raw, 1073741903, 0, 2, 33, 233]
+[:key_down_raw, 1073741903, 0, 2, 34, 235]
+[:key_down_raw, 1073741903, 0, 2, 35, 237]
+[:key_down_raw, 1073741903, 0, 2, 36, 239]
+[:key_down_raw, 1073741903, 0, 2, 37, 241]
+[:key_down_raw, 1073741903, 0, 2, 38, 243]
+[:key_down_raw, 1073741903, 0, 2, 39, 245]
+[:key_down_raw, 1073741903, 0, 2, 40, 247]
+[:key_down_raw, 1073741903, 0, 2, 41, 249]
+[:key_down_raw, 1073741903, 0, 2, 42, 251]
+[:key_down_raw, 1073741903, 0, 2, 43, 253]
+[:key_down_raw, 1073741903, 0, 2, 44, 255]
+[:key_down_raw, 1073741906, 0, 2, 45, 257]
+[:key_up_raw, 1073741903, 0, 2, 46, 258]
+[:key_down_raw, 1073741906, 0, 2, 47, 271]
+[:key_down_raw, 1073741906, 0, 2, 48, 274]
+[:key_down_raw, 1073741906, 0, 2, 49, 276]
+[:key_down_raw, 1073741906, 0, 2, 50, 278]
+[:key_down_raw, 1073741906, 0, 2, 51, 280]
+[:key_up_raw, 1073741906, 0, 2, 52, 280]
+[:key_down_raw, 1073741903, 0, 2, 53, 280]
+[:key_down_raw, 1073741903, 0, 2, 54, 296]
+[:key_down_raw, 1073741903, 0, 2, 55, 298]
+[:key_down_raw, 1073741905, 0, 2, 56, 298]
+[:key_up_raw, 1073741903, 0, 2, 57, 300]
+[:key_down_raw, 1073741905, 0, 2, 58, 313]
+[:key_down_raw, 1073741905, 0, 2, 59, 315]
+[:key_down_raw, 1073741905, 0, 2, 60, 317]
+[:key_down_raw, 1073741905, 0, 2, 61, 319]
+[:key_down_raw, 1073741905, 0, 2, 62, 321]
+[:key_down_raw, 1073741905, 0, 2, 63, 323]
+[:key_down_raw, 1073741905, 0, 2, 64, 325]
+[:key_down_raw, 1073741905, 0, 2, 65, 327]
+[:key_down_raw, 1073741905, 0, 2, 66, 329]
+[:key_down_raw, 1073741904, 0, 2, 67, 330]
+[:key_up_raw, 1073741905, 0, 2, 68, 332]
+[:key_down_raw, 1073741904, 0, 2, 69, 345]
+[:key_down_raw, 1073741904, 0, 2, 70, 347]
+[:key_down_raw, 1073741904, 0, 2, 71, 349]
+[:key_down_raw, 1073741904, 0, 2, 72, 351]
+[:key_up_raw, 1073741904, 0, 2, 73, 353]
+[:key_down_raw, 1073741903, 0, 2, 74, 354]
+[:key_down_raw, 1073741903, 0, 2, 75, 369]
+[:key_down_raw, 1073741903, 0, 2, 76, 371]
+[:key_down_raw, 1073741903, 0, 2, 77, 373]
+[:key_down_raw, 1073741903, 0, 2, 78, 375]
+[:key_down_raw, 1073741903, 0, 2, 79, 377]
+[:key_down_raw, 1073741903, 0, 2, 80, 379]
+[:key_down_raw, 1073741903, 0, 2, 81, 382]
+[:key_down_raw, 1073741903, 0, 2, 82, 383]
+[:key_down_raw, 1073741903, 0, 2, 83, 385]
+[:key_down_raw, 1073741903, 0, 2, 84, 387]
+[:key_down_raw, 1073741903, 0, 2, 85, 390]
+[:key_down_raw, 1073741903, 0, 2, 86, 392]
+[:key_down_raw, 1073741903, 0, 2, 87, 394]
+[:key_down_raw, 1073741905, 0, 2, 88, 395]
+[:key_up_raw, 1073741903, 0, 2, 89, 400]
+[:key_down_raw, 1073741904, 0, 2, 90, 405]
+[:key_up_raw, 1073741905, 0, 2, 91, 416]
+[:key_down_raw, 1073741904, 0, 2, 92, 420]
+[:key_down_raw, 1073741904, 0, 2, 93, 422]
+[:key_down_raw, 1073741904, 0, 2, 94, 424]
+[:key_down_raw, 1073741904, 0, 2, 95, 426]
+[:key_down_raw, 1073741904, 0, 2, 96, 428]
+[:key_down_raw, 1073741904, 0, 2, 97, 430]
+[:key_down_raw, 1073741904, 0, 2, 98, 432]
+[:key_down_raw, 1073741904, 0, 2, 99, 434]
+[:key_down_raw, 1073741904, 0, 2, 100, 436]
+[:key_down_raw, 1073741904, 0, 2, 101, 438]
+[:key_down_raw, 1073741904, 0, 2, 102, 440]
+[:key_down_raw, 1073741904, 0, 2, 103, 442]
+[:key_down_raw, 1073741904, 0, 2, 104, 444]
+[:key_up_raw, 1073741904, 0, 2, 105, 444]
+[:key_down_raw, 1073741906, 0, 2, 106, 445]
+[:key_up_raw, 1073741906, 0, 2, 107, 448]
+[:key_down_raw, 1073741905, 0, 2, 108, 452]
+[:key_down_raw, 1073741905, 0, 2, 109, 467]
+[:key_down_raw, 1073741905, 0, 2, 110, 469]
+[:key_up_raw, 1073741905, 0, 2, 111, 470]
+[:key_down_raw, 1073741906, 0, 2, 112, 484]
+[:key_up_raw, 1073741906, 0, 2, 113, 496]
+[:key_down_raw, 32, 0, 2, 114, 499]
+[:key_up_raw, 32, 0, 2, 115, 505]
+[:key_down_raw, 1073741903, 0, 2, 116, 538]
+[:key_up_raw, 1073741903, 0, 2, 117, 553]
+[:key_down_raw, 106, 0, 2, 118, 604]
+[:key_up_raw, 106, 0, 2, 119, 608]
+[:key_down_raw, 1073741903, 0, 2, 120, 640]
+[:key_down_raw, 1073741906, 0, 2, 121, 654]
+[:key_up_raw, 1073741903, 0, 2, 122, 654]
+[:key_down_raw, 1073741906, 0, 2, 123, 669]
+[:key_down_raw, 1073741906, 0, 2, 124, 671]
+[:key_down_raw, 1073741906, 0, 2, 125, 673]
+[:key_down_raw, 1073741906, 0, 2, 126, 675]
+[:key_up_raw, 1073741906, 0, 2, 127, 677]
+[:key_down_raw, 1073741903, 0, 2, 128, 677]
+[:key_down_raw, 1073741903, 0, 2, 129, 692]
+[:key_down_raw, 1073741903, 0, 2, 130, 694]
+[:key_down_raw, 1073741905, 0, 2, 131, 694]
+[:key_up_raw, 1073741903, 0, 2, 132, 696]
+[:key_down_raw, 1073741905, 0, 2, 133, 709]
+[:key_down_raw, 1073741905, 0, 2, 134, 711]
+[:key_down_raw, 1073741905, 0, 2, 135, 713]
+[:key_down_raw, 1073741905, 0, 2, 136, 715]
+[:key_down_raw, 1073741905, 0, 2, 137, 717]
+[:key_down_raw, 1073741904, 0, 2, 138, 719]
+[:key_up_raw, 1073741905, 0, 2, 139, 721]
+[:key_down_raw, 1073741904, 0, 2, 140, 734]
+[:key_down_raw, 1073741904, 0, 2, 141, 736]
+[:key_down_raw, 1073741904, 0, 2, 142, 738]
+[:key_down_raw, 1073741904, 0, 2, 143, 740]
+[:key_down_raw, 1073741904, 0, 2, 144, 742]
+[:key_down_raw, 1073741904, 0, 2, 145, 744]
+[:key_down_raw, 1073741904, 0, 2, 146, 746]
+[:key_down_raw, 1073741904, 0, 2, 147, 748]
+[:key_up_raw, 1073741904, 0, 2, 148, 748]
+[:key_down_raw, 96, 0, 2, 149, 778]
+[:key_up_raw, 96, 0, 2, 150, 782]
+[:mouse_move, 782, 86, 2, 151, 822]
+[:mouse_move, 774, 93, 2, 152, 823]
+[:mouse_move, 764, 101, 2, 153, 824]
+[:mouse_move, 752, 113, 2, 154, 825]
+[:mouse_move, 732, 126, 2, 155, 826]
+[:mouse_move, 716, 141, 2, 156, 827]
+[:mouse_move, 705, 152, 2, 157, 828]
+[:mouse_move, 699, 162, 2, 158, 829]
+[:mouse_move, 693, 172, 2, 159, 830]
+[:mouse_move, 690, 177, 2, 160, 831]
+[:mouse_move, 690, 176, 2, 161, 839]
+[:mouse_move, 691, 175, 2, 162, 840]
+[:mouse_move, 693, 173, 2, 163, 841]
+[:mouse_move, 695, 173, 2, 164, 842]
+[:mouse_move, 695, 172, 2, 165, 844]
+[:key_down_raw, 13, 0, 2, 166, 851]