summaryrefslogtreecommitdiffhomepage
path: root/docs/todo
diff options
context:
space:
mode:
authorAmir Rajan <[email protected]>2020-07-30 16:45:24 -0500
committerAmir Rajan <[email protected]>2020-07-30 16:58:40 -0500
commiteb8b770e1952af371832f5f31e00dae09d498cf9 (patch)
tree0884e11fedbfa01c7ce9f1e028cb6c43a13d2052 /docs/todo
parent8d000345a3489988e9e86ee9fda9dcc6c70b7012 (diff)
downloaddragonruby-game-toolkit-contrib-eb8b770e1952af371832f5f31e00dae09d498cf9.tar.gz
dragonruby-game-toolkit-contrib-eb8b770e1952af371832f5f31e00dae09d498cf9.zip
OSS synced with 1.12.
Diffstat (limited to 'docs/todo')
-rw-r--r--docs/todo/03-solids-and-borders.md126
-rw-r--r--docs/todo/04-lines.md108
-rw-r--r--docs/todo/05-sprites.md216
-rw-r--r--docs/todo/06-keyboard.md150
-rw-r--r--docs/todo/07-mouse.md48
-rw-r--r--docs/todo/08-controllers.md86
-rw-r--r--docs/todo/09-scaling.md87
-rw-r--r--docs/todo/99-todo.md89
8 files changed, 910 insertions, 0 deletions
diff --git a/docs/todo/03-solids-and-borders.md b/docs/todo/03-solids-and-borders.md
new file mode 100644
index 0000000..0ed2fc9
--- /dev/null
+++ b/docs/todo/03-solids-and-borders.md
@@ -0,0 +1,126 @@
+# Solids and Borders
+
+Solids and Borders are great to use as place holders for sprites.
+
+## Sample Apps Releated to Solid/Borders Usage (ordered by size of codebase increasing)
+
+- 01_api_03_rects
+- 01_api_99_tech_demo (includes recording)
+- 02_collisions
+- 12_top_down_area (includes recording)
+- 99_sample_game_flappy_dragon (includes recording)
+- 08_platformer_collisions
+- 20_roguelike_starting_point
+- 99_sample_game_pong (includes recording)
+
+## Minimum Code
+
+Creates a solid black rectangle located at 100, 100. 160 pixels
+wide and 90 pixels tall.
+
+```ruby
+# X Y WIDTH HEIGHT
+args.outputs.solids << [100, 100, 160, 90]
+```
+
+Creates an unfilled black-bordered rectangle located at 100, 100.
+160 pixels wide and 90 pixels tall.
+
+```ruby
+# X Y WIDTH HEIGHT
+args.outputs.borders << [100, 100, 160, 90]
+```
+
+## RGBA - Colors and Alpha
+
+The value for the color and alpha is an number between `0` and `255`. The
+alpha property is optional and will be set to `255` if not specified.
+
+Creates a green solid rectangle with an opacity of 50%.
+
+```ruby
+# X Y WIDTH HEIGHT RED GREEN BLUE ALPHA
+args.outputs.solids << [100, 100, 160, 90, 0, 255, 0, 128]
+```
+
+Creates an unfilled green-bordered rectangle located at 100, 100.
+160 pixels wide and 90 pixels tall and an opacity of 50%.
+
+```ruby
+# X Y WIDTH HEIGHT RED GREEN BLUE ALPHA
+args.outputs.borders << [100, 100, 160, 90, 0, 255, 0, 128]
+```
+
+Creates a solid gray rectangle that covers the entire scene. Like a background.
+The opacity is excluded because it's 100% opaque (which has a value of 255).
+
+```ruby
+# X Y WIDTH HEIGHT RED GREEN BLUE
+args.outputs.solids << [ 0, 0, 1280, 720, 128, 128, 128]
+```
+
+## Hash (Advanced)
+
+If you want a more readable invocation. You can use the following hash to create a solid.
+Any parameters that are not specified will be given a default value. The keys of the hash can
+be provided in any order.
+
+```ruby
+args.outputs.solids << {
+ x: 0,
+ y: 0,
+ w: 100,
+ h: 100,
+ r: 0,
+ g: 255,
+ b: 0,
+ a: 255
+}
+
+
+args.outputs.borders << {
+ x: 0,
+ y: 0,
+ w: 100,
+ h: 100,
+ r: 0,
+ g: 255,
+ b: 0,
+ a: 255
+}
+```
+
+## Duck Typing (Advanced)
+
+You can also create a class with solid/border properties and render it as a primitive.
+ALL properties must on the class. ADDITIONALLY, a method called `primitive_marker`
+must be defined on the class.
+
+Here is an example:
+
+```ruby
+# Create type with ALL solid/border properties AND primitive_marker
+class Solid (or Border)
+ attr_accessor :x, :y, :w, :h, :r, :g, :b, :a_x
+
+ def primitive_marker
+ :solid (or :border)
+ end
+end
+
+# Inherit from type
+class Square < Solid (or Border)
+ # constructor
+ def initialize x, y, size
+ self.x = x
+ self.y = y
+ self.w = size
+ self.h = size
+ end
+end
+
+# render solid/border
+
+args.outputs.solids << Square.new(10, 10, 32)
+args.outputs.borders << Square.new(10, 10, 32)
+```
diff --git a/docs/todo/04-lines.md b/docs/todo/04-lines.md
new file mode 100644
index 0000000..03c1abc
--- /dev/null
+++ b/docs/todo/04-lines.md
@@ -0,0 +1,108 @@
+# Lines
+
+Lines are 1 pixel wide and can be diagonal.
+
+## Sample Apps Related to Line Usage (ordered by size of codebase increasing)
+
+- 01_api_02_lines
+- 01_api_99_tech_demo (includes recording)
+- 06_coordinate_systems (includes recording)
+- 19_lowrez_jam_01_hello_world
+- 99_sample_game_pong (includes recording)
+
+## Minimum Code
+
+Creates a black line from the bottom left corner to the top right corner.
+
+```ruby
+# X1 Y1 X2 Y2
+args.outputs.lines << [ 0, 0, 1280, 720]
+```
+
+Creates a black vertical line through the center of the scene.
+
+```ruby
+# X1 Y1 X2 Y2
+args.outputs.lines << [ 640, 0, 640, 720]
+```
+
+Creates a black horizontal line through the center of the scene.
+
+```ruby
+# X1 Y1 X2 Y2
+args.outputs.lines << [ 0, 360, 1280, 360]
+```
+
+## RGBA - Colors and Alpha
+
+The value for the color and alpha is an number between `0` and `255`. The
+alpha property is optional and will be set to `255` if not specified.
+
+Creates a green horizontal line through the center of the scene with an opacity of 50%.
+
+```ruby
+# X1 Y1 X2 Y2 RED GREEN BLUE ALPHA
+args.outputs.lines << [ 0, 360, 1280, 360, 0, 255, 0, 128]
+```
+
+Creates a green vertical line through the center of the scene.
+The opacity is excluded because it's 100% opaque (which has a value of 255).
+
+```ruby
+# X1 Y1 X2 Y2 RED GREEN BLUE
+args.outputs.lines << [ 640, 0, 640, 720, 0, 255, 0]
+```
+
+## Hash (Advanced)
+
+If you want a more readable invocation. You can use the following hash to create a line.
+Any parameters that are not specified will be given a default value. The keys of the hash can
+be provided in any order.
+
+```ruby
+args.outputs.lines << {
+ x: 0,
+ y: 0,
+ x2: 1280,
+ y2: 720,
+ r: 0,
+ g: 255,
+ b: 0,
+ a: 255
+}
+```
+
+## Duck Typing (Advanced)
+
+You can also create a class with line properties and render it as a primitive.
+ALL properties must on the class. ADDITIONALLY, a method called `primitive_marker`
+must be defined on the class.
+
+Here is an example:
+
+```ruby
+# Create type with ALL line properties AND primitive_marker
+class Line
+ attr_accessor :x, :y, :x2, :y2, :r, :g, :b, :a
+
+ def primitive_marker
+ :line
+ end
+end
+
+# Inherit from type
+class VerticalLine < Line
+
+ # constructor
+ def initialize x, y, h
+ self.x = x
+ self.y = y
+ self.x2 = x
+ self.y2 = y + h
+ end
+end
+
+# render line
+
+args.outputs.lines << VerticalLine.new(10, 10, 100)
+```
diff --git a/docs/todo/05-sprites.md b/docs/todo/05-sprites.md
new file mode 100644
index 0000000..e8030ab
--- /dev/null
+++ b/docs/todo/05-sprites.md
@@ -0,0 +1,216 @@
+# Sprites
+
+Sprites are the most important visual component of a game.
+
+## Sample Apps Related to Sprite Usage (ordered by size of codebase increasing)
+
+- 01_api_04_sprites
+- 01_api_99_tech_demo (includes recording)
+- 02_sprite_animation_and_keyboard_input (includes recording)
+- 08_platformer_collisions_metroidvania
+- 09_controller_analog_usage_advanced_sprites
+- 99_sample_game_basic_gorillas (includes recording)
+- 99_sample_game_dueling_starships (includes recording)
+- 99_sample_game_flappy_dragon (includes recording)
+- 99_sample_game_return_of_serenity
+
+## Minimum Code
+
+Sprites need to be under the `mygame` directory. It's recommended that you create a `sprites` folder
+to keep things organized. All sprites must be `.png` files
+
+Here is how you create an sprite with located at 100, 100, that is 32 pixels wide and 64 pixels tall.
+In this example the sprite name is `player.png` and is located under a directory `mygame/sprites`.
+
+```ruby
+# X Y WIDTH HEIGHT PATH
+args.outputs.sprites << [100, 100, 32, 64, "sprites/player.png"]
+```
+
+## Rotation / Angle
+
+Unlike `solids` and `borders`, sprites can be rotated. This is how you rotate a sprite 90 degress.
+
+Note: All angles in DragonRuby Game Toolkit are represented in degrees (not radians).
+
+```ruby
+# X Y WIDTH HEIGHT PATH ANGLE
+args.outputs.sprites << [100, 100, 32, 64, "sprites/player.png", 90]
+```
+
+## Alpha
+
+Sprites can also have a transparency associated with them. The transparency value must come after
+the angle value and supports a number between 0 and 255.
+
+This is how you would define a sprite with no rotation, and a 50% transparency.
+
+```ruby
+# X Y WIDTH HEIGHT PATH ANGLE ALPHA
+args.outputs.sprites << [100, 100, 32, 64, "sprites/player.png", 0, 128]
+```
+
+## Color Saturations
+
+A Sprite's color levels can be changed. The color saturations must come after `angle` and
+`alpha` values.
+
+This is a sprite with no rotation, fully opaque, and with a green tint.
+
+```ruby
+args.outputs.sprites << [100, # X
+ 100, # Y
+ 32, # W
+ 64, # H
+ "sprites/player.png", # PATH
+ 0, # ANGLE
+ 255, # ALPHA
+ 0, # RED_SATURATION
+ 255, # GREEN_SATURATION
+ 0] # BLUE_SATURATION
+```
+
+## Sprite Sub Division / Tile
+
+You can render a portion of a sprite (a tile). The sub division of the sprite is denoted as a rectangle
+directly related to the original size of the png.
+
+This is a sprite scaled to 100 pixels where the source rectangle is located at the bottom left corner
+within a 32 pixel square. The angle, opacity, and color levels of the tile are unaltered.
+
+**For these advanced transforms, you should use a `Hash` instead of an `Array`.**
+
+```ruby
+args.outputs.sprites << {
+ x: 100,
+ y: 100,
+ w: 100,
+ h: 100,
+ path: "sprites/player.png",
+ source_x: 0,
+ source_y: 0,
+ source_w: 32,
+ source_h: 32,
+}
+```
+
+## Flipping a Sprite Horizontally and Vertically
+
+A sprite can be flipped horizontally and vertically.
+
+This is a sprite that has been flipped horizontally. The sprites's angle, alpha, color saturations,
+and source rectangls are unaltered.
+
+**For these advanced transforms, you should use a `Hash` instead of an `Array`.**
+
+```ruby
+args.outputs.sprites << {
+ x: 100,
+ y: 100,
+ w: 100,
+ h: 100,
+ path: "sprites/player.png",
+ flip_horizontally: true,
+}
+```
+
+This is a sprite that has been flipped vertically. The sprites's angle, alpha, color saturations,
+and tile subdivision are unaltered.
+
+```ruby
+args.outputs.sprites << {
+ x: 100,
+ y: 100,
+ w: 100,
+ h: 100,
+ path: "sprites/player.png",
+ flip_vertically: true,
+}
+```
+
+## Rotation Center
+
+A sprites center of rotation can be altered.
+
+This is a sprite that has its rotation center set to the top-middle. The sprites's angle, alpha, color saturations,
+source rectangle subdivision, and projections are unaltered.
+
+```ruby
+args.outputs.sprites << {
+ x: 100,
+ y: 100,
+ w: 100,
+ h: 100,
+ path: "sprites/player.png",
+ angle: 0,
+ angle_anchor_x: 0.5,
+ angle_anchor_y: 1.0
+}
+```
+
+## Hash
+
+Here are all of the properites that are available on a sprite Hash.
+Any parameters that are not specified will be given a default value. The keys of the hash can
+be provided in any order.
+
+```ruby
+args.outputs.sprites << {
+ x: 100,
+ y: 100,
+ w: 100,
+ h: 100,
+ path: "sprites/player.png",
+ angle: 0,
+ a, 255,
+ r: 255,
+ g: 255,
+ b: 255,
+ source_x: 0,
+ source_y: 0,
+ source_w: -1,
+ source_h: -1,
+ flip_vertically: false,
+ flip_horizontally: false,
+ angle_anchor_x: 0.5,
+ angle_anchor_y: 1.0
+}
+```
+
+## Duck Typing (Advanced)
+
+You can also create a class with sprite properties and render it as a primitive.
+ALL properties must on the class. ADDITIONALLY, a method called `primitive_marker`
+must be defined on the class.
+
+Here is an example:
+
+```ruby
+# Create type with ALL sprite properties AND primitive_marker
+class Sprite
+ attr_accessor :x, :y, :w, :h, :path, :angle, :a, :r, :g, :b, :source_x,
+ :source_y, :source_w, :source_h, :flip_horizontally,
+ :flip_vertically, :angle_anchor_x, :angle_anchor_y
+
+ def primitive_marker
+ :sprite
+ end
+end
+
+# Inherit from type
+class PlayerSprite < Sprite
+
+ # constructor
+ def initialize x, y, w, h
+ self.x = x
+ self.y = y
+ self.w = w
+ self.h = h
+ self.path = 'sprites/player.png'
+ end
+end
+
+#render player sprite
+
+args.outputs.sprites << PlayerSprite.new(10, 10, 32, 64)
+```
diff --git a/docs/todo/06-keyboard.md b/docs/todo/06-keyboard.md
new file mode 100644
index 0000000..6fbe6d2
--- /dev/null
+++ b/docs/todo/06-keyboard.md
@@ -0,0 +1,150 @@
+# Keyboard
+
+Determining if `a` key is in the down state (pressed). This happens once each time the key is pressed:
+
+```
+if args.inputs.keyboard.key_down.a
+ puts 'The key is pressed'
+end
+```
+
+Determining if a key is being held. This happens every tick while the key is held down:
+
+```
+if args.inputs.keyboard.key_held.a
+ puts 'The key is being held'
+end
+```
+
+Determining if a key is in the down state or is being held:
+
+```
+if args.inputs.keyboard.a
+ puts 'The key is pressed or being held'
+end
+```
+
+Determining if a key is in the up state (released). This happens once each time the key is released:
+
+```
+if args.inputs.keyboard.key_up.a
+ puts 'The key is released'
+end
+```
+
+# Truthy Keys
+
+You can access all triggered keys through `truthy_keys` on `keyboard`, `controller_one`, and `controller_two`.
+
+This is how you would right all keys to a file. The game must be in the foreground and have focus for this data
+to be recorded.
+
+```
+def tick args
+ [
+ [args.inputs.keyboard, :keyboard],
+ [args.inputs.controller_one, :controller_one],
+ [args.inputs.controller_two, :controller_two]
+ ].each do |input, name|
+ if input.key_down.truthy_keys.length > 0
+ args.gtk.write_file("mygame/app/#{name}_key_down_#{args.state.tick_count}", input.key_down.truthy_keys.to_s)
+ end
+ end
+end
+```
+
+# List of keys:
+
+These are the character and associated properities that will
+be set to true.
+
+For example `A => :a, :shift` means that `args.inputs.keyboard.a`
+would be true and so would `args.inputs.keyboard.shift`
+(if both keys were being held or in the down state).
+
+```
+A => :a, :shift
+B => :b, :shift
+C => :c, :shift
+D => :d, :shift
+E => :e, :shift
+F => :f, :shift
+G => :g, :shift
+H => :h, :shift
+I => :i, :shift
+J => :j, :shift
+K => :k, :shift
+L => :l, :shift
+M => :m, :shift
+N => :n, :shift
+O => :o, :shift
+P => :p, :shift
+Q => :q, :shift
+R => :r, :shift
+S => :s, :shift
+T => :t, :shift
+U => :u, :shift
+V => :v, :shift
+W => :w, :shift
+X => :x, :shift
+Y => :y, :shift
+Z => :z, :shift
+! => :exclamation_point
+0 => :zero
+1 => :one
+2 => :two
+3 => :three
+4 => :four
+5 => :five
+6 => :six
+7 => :seven
+8 => :eight
+9 => :nine
+\b => :backspace
+\e => :escape
+\r => :enter
+\t => :tab
+( => :open_round_brace
+) => :close_round_brace
+{ => :open_curly_brace
+} => :close_curly_brace
+[ => :open_square_brace
+] => :close_square_brace
+: => :colon
+; => :semicolon
+= => :equal_sign
+- => :hyphen
+ => :space
+$ => :dollar_sign
+" => :double_quotation_mark
+' => :single_quotation_mark
+` => :backtick
+~ => :tilde
+. => :period
+, => :comma
+| => :pipe
+_ => :underscore
+# => :hash
++ => :plus
+@ => :at
+/ => :forward_slash
+\ => :back_slash
+* => :asterisk
+< => :less_than
+> => :greater_than
+^ => :greater_than
+& => :ampersand
+² => :superscript_two
+§ => :section_sign
+? => :question_mark
+% => :percent_sign
+º => :ordinal_indicator
+right arrow => :right
+left arrow => :left
+down arrow => :down
+up arrow => :up
+delete key => :delete
+control key => :control
+windows key/command key => :meta
+alt key => :alt
+```
diff --git a/docs/todo/07-mouse.md b/docs/todo/07-mouse.md
new file mode 100644
index 0000000..2af8854
--- /dev/null
+++ b/docs/todo/07-mouse.md
@@ -0,0 +1,48 @@
+# Mouse
+
+Determining current position of mouse:
+
+```
+args.inputs.mouse.x
+args.inputs.mouse.y
+```
+
+Determining if the mouse has been clicked, and it's position. Note:
+`click` and `down` are aliases for each other.
+
+```
+if args.inputs.mouse.click
+ puts "click: #{args.inputs.mouse.click}"
+ puts "x: #{args.inputs.mouse.click.point.x}"
+ puts "y: #{args.inputs.mouse.click.point.y}"
+end
+```
+
+Determining if the mouse button has been released:
+
+```
+if args.inputs.mouse.up
+ puts "up: #{args.inputs.mouse.up}"
+ puts "x: #{args.inputs.mouse.up.point.x}"
+ puts "y: #{args.inputs.mouse.up.point.y}"
+end
+```
+
+Determine which mouse button(s) have been clicked (also works for up):
+```
+if args.inputs.mouse.click
+ puts "left: #{args.inputs.mouse.button_left}"
+ puts "middle: #{args.inputs.mouse.button_middle}"
+ puts "right: #{args.inputs.mouse.button_right}"
+ puts "x1: #{args.inputs.mouse.button_x1}"
+ puts "x2: #{args.inputs.mouse.button_x2}"
+end
+```
+
+Determine if the mouse wheel is being used and its values for this tick:
+```
+if args.inputs.mouse.wheel
+ puts "The wheel moved #{args.inputs.mouse.wheel.x} left/right"
+ puts "The wheel moved #{args.inputs.mouse.wheel.y} up/down"
+end
+```
diff --git a/docs/todo/08-controllers.md b/docs/todo/08-controllers.md
new file mode 100644
index 0000000..68bd9c2
--- /dev/null
+++ b/docs/todo/08-controllers.md
@@ -0,0 +1,86 @@
+# Controllers
+
+There are two controllers you have access to:
+
+```
+args.inputs.controller_one
+args.inputs.controller_two
+```
+
+Determining if a key was down:
+
+```
+if args.inputs.controller_one.key_down.a
+ puts 'The key was in the down state'
+end
+```
+
+Determining if a key is being held:
+
+```
+if args.inputs.controller_one.key_held.a
+ puts 'The key is being held'
+end
+```
+
+Determining if a key is released:
+
+```
+if args.inputs.controller_one.key_up.a
+ puts 'The key is being held'
+end
+```
+
+# Truthy Keys
+
+You can access all triggered keys through `thruthy_keys` on `keyboard`, `controller_one`, and `controller_two`.
+
+This is how you would write all keys to a file. The game must be in the foreground and have focus for this data
+to be recorded.
+
+```
+def tick args
+ [
+ [args.inputs.keyboard, :keyboard],
+ [args.inputs.controller_one, :controller_one],
+ [args.inputs.controller_two, :controller_two]
+ ].each do |input, name|
+ if input.key_down.truthy_keys.length > 0
+ args.gtk.write_file("mygame/app/#{name}_key_down_#{args.state.tick_count}", input.key_down.truthy_keys.to_s)
+ end
+ end
+end
+```
+
+# List of keys:
+
+```
+args.inputs.controller_one.key_held.up
+args.inputs.controller_one.key_held.down
+args.inputs.controller_one.key_held.left
+args.inputs.controller_one.key_held.right
+args.inputs.controller_one.key_held.a
+args.inputs.controller_one.key_held.b
+args.inputs.controller_one.x
+args.inputs.controller_one.y
+args.inputs.controller_one.key_held.l1
+args.inputs.controller_one.key_held.r1
+args.inputs.controller_one.key_held.l2
+args.inputs.controller_one.key_held.r2
+args.inputs.controller_one.key_held.l3
+args.inputs.controller_one.key_held.r3
+args.inputs.controller_one.key_held.start
+args.inputs.controller_one.key_held.select
+args.inputs.controller_one.key_held.directional_up
+args.inputs.controller_one.key_held.directional_down
+args.inputs.controller_one.key_held.directional_left
+args.inputs.controller_one.key_held.directional_right
+args.inputs.controller_one.left_analog_x_raw,
+args.inputs.controller_one.left_analog_y_raw,
+args.inputs.controller_one.left_analog_x_perc,
+args.inputs.controller_one.left_analog_y_perc,
+args.inputs.controller_one.right_analog_x_raw,
+args.inputs.controller_one.right_analog_y_raw,
+args.inputs.controller_one.right_analog_x_perc,
+args.inputs.controller_one.right_analog_y_perc
+```
diff --git a/docs/todo/09-scaling.md b/docs/todo/09-scaling.md
new file mode 100644
index 0000000..9f63748
--- /dev/null
+++ b/docs/todo/09-scaling.md
@@ -0,0 +1,87 @@
+# Scaling
+
+The general idea is (for example): You'll have `sprite.png`
+
+- If you are missing `@1080p`, `sprite.png` will be scaled 1.5.
+- If you're missing `@1440p`, `sprite.png`.
+
+And so on. In code, always use `sprite.png` paths withouth the @, and GTK will figure out the right png to use.
+
+```
++------------+-------+------+------+------+------+------+------+------+------+
+| Resolution | @Name | Unit | 720 | 1080 | 1440 | 4K | 5K | 6K | 8K |
++------------+-------+-----:+-----:+-----:+-----:+-----:+-----:+-----:+-----:+
+| 1280x720 | 720p | 2px | 1x | - | - | - | - | - | - |
+| 1920x1080 | 1080p | 3px | 1.5x | 1x | - | - | - | - | - |
+| 2560x1440 | 1440p | 4px | 2x | - | 1x | - | - | - | - |
+| 3840x2160 | 4K | 6px | 3x | 2x | - | 1x | - | - | - |
+| 5120x2880 | 5K | 8px | 4x | - | 2x | - | 1x | - | - |
+| 5760x3240 | 6K | 9px | 4.5x | 3x | - | - | - | 1x | - |
+| 7680x4320 | 8K | 12px | 6x | 4x | 3x | 2x | - | - | 1x |
++------------+-------+------+------+------+------+------+------+------+------+
+| 640x360 | 360p | 2px | 0.5x | - | - | - | - | - | - |
++------------+-------+------+------+------+------+------+------+------+------+
+```
+
+# Layout Theory (work in progress)
+
+Where it gets tricky is mobile. The algorithm there would be to find
+the nearest pixel perfect resolution and then allow for rendering
+outside of the logical canvas, which will be centered in the
+screen. `grid.left` in these cases will be a negative number and will
+exclude "unsafe" areas (which are only applicable to phones with edge
+to edge screens... god help us all if I have to introduce a
+`grid.(left|right|top|bottom)_unsafe`).
+
+## Variables that need to be considered.
+
+- logical pixel of device
+- logical pixels of canvas (720p)
+- physical pixel of device
+
+## Well known aspect ratios
+
+ - 720p
+ - 1080p
+ - 1440p
+ - 4k
+ - 5k
+ - 6k
+ - 8k
+
+## Laws that support Layout Theory
+
+ - Logical pixels is 720p for a game.
+ - The logical pixels for the game is centered in the device.
+ - The logical pixesl is the only safe area for the game.
+
+## Math
+
+ 1. Take the logical widht and height of the iphone, assume the thinner part is the "9" of the "16:9" aspect ratio. Example: 414 / 896 = 720 / x ... x = 1558
+ 2. Determine the scale down from the 720 to the target "9". Example: 720 * x = 414 ... x = .575
+ 3. Determine the "other side" of the 16?? : 9 aspect ratio for the target device (which might not be 16). Example: 1280 / 1558 = x / 896 ... x = 736
+ 4. And then scale that down. Example: 1558.3 * .575 ... x = 896
+ 5. Determine the 16:9 scaled. Example 414 x 736
+ 6. Determine the unsafe area. Example: (896 - 736) / 2 = 65
+ 7. Verify the math and make sure the aspect ratio makes sense. Example: 1558 / (720 / 9) = 19.5
+ 8. Verify result. Example: 9 : 19.5 with 1.75 unsafe on either side = 140 logical pixels on
+ either side To support iPhone 11 Pro, you must render a game where you render -140 to 1420. 720 x 1280 logical.
+
+## Scale Table
+
+The Physical pixels for the iPhone 11 is 1242 X 2688. This is used to determine which texture will be used from the texture atlas.
+
+```
++------------+-------+------+------+------+------+------+------+------+------+
+| Resolution | @Name | Unit | 720 | 1080 | 1440 | 4K | 5K | 6K | 8K |
++------------+-------+-----:+-----:+-----:+-----:+-----:+-----:+-----:+-----:+
+| 1280x720 | - | 2px | 1x | - | - | - | - | - | - |
+| 1920x1080 | 1080p | 3px | 1.5x | 1x | - | - | - | - | - |
+| 2560x1440 | 1440p | 4px | 2x | - | 1x | - | - | - | - |
+| 3840x2160 | 4K | 6px | 3x | 2x | - | 1x | - | - | - |
+| 5120x2880 | 5K | 8px | 4x | - | 2x | - | 1x | - | - |
+| 5760x3240 | 6K | 9px | 4.5x | 3x | - | - | - | 1x | - |
+| 7680x4320 | 8K | 12px | 6x | 4x | 3x | 2x | - | - | 1x |
++------------+-------+------+------+------+------+------+------+------+------+
+```
diff --git a/docs/todo/99-todo.md b/docs/todo/99-todo.md
new file mode 100644
index 0000000..39c542a
--- /dev/null
+++ b/docs/todo/99-todo.md
@@ -0,0 +1,89 @@
+# Documentation That Needs to be Organized
+
+## Class macro gtk_args
+
+Here's how you can use the `gtk_args` class method:
+
+```ruby
+class Game
+ gtk_args
+ attr_accessor :current_scene, :other_custom_attrs
+
+ def tick
+ end
+end
+
+$game = Game.new
+
+def tick args
+ $game.args = args
+ $game.tick
+end
+```
+
+The code above is the similar to:
+
+```ruby
+class Game
+ attr_accessor :args, :grid, :state, :inputs, :outputs, :gtk, :passes,
+ :current_scene, :other_custom_attrs
+
+ def tick
+ end
+end
+
+$game = Game.new
+
+def tick args
+ $game.args = args
+ $game.grid = args.grid
+ $game.state = args.state
+ $game.outputs = args.outputs
+ $game.gtk = args.gtk
+ $game.passes = args.passes
+ $game.tick
+end
+```
+
+## Monkey patching the runtime
+
+You're on your own if you do this :grimacing:
+
+```ruby
+module GTK
+ class Runtime
+ alias_method :__original_tick_core__, :tick_core unless Runtime.instance_methods.include?(:__original_tick_core__)
+
+ def tick_core
+ __original_tick_core__
+ $top_level.oh @args
+ $top_level.god @args
+ $top_level.why @args
+ end
+ end
+end
+
+def tick args
+end
+
+def oh args
+end
+
+def god args
+end
+
+def why args
+end
+```
+
+## MP3's to Wav converstion script:
+
+```ruby
+`ls .`.each_line.to_a.map do |l|
+ l = l.strip
+ if l.end_with? "mp3"
+ `ffmpeg -i #{l} -acodec pcm_s16le -ar 44100 prep-#{l.split(".")[0]}.wav`
+ `ffmpeg -y -i prep-#{l.split(".")[0]}.wav -f wav -bitexact -acodec pcm_s16le -ar 44100 -ac 1 #{l.split(".")[0]}.wav`
+ end
+end
+```