summaryrefslogtreecommitdiffhomepage
path: root/docs/search_results.txt
diff options
context:
space:
mode:
authorAmir Rajan <[email protected]>2020-09-11 02:02:36 -0500
committerAmir Rajan <[email protected]>2020-09-11 02:02:57 -0500
commit5b2311900072cfff9582bb0296140cfb354cb911 (patch)
tree6896c701c1b9355a04cfa8027f6073063497711b /docs/search_results.txt
parente28637fc73295b59181f3e105bb6f3dc753531eb (diff)
downloaddragonruby-game-toolkit-contrib-5b2311900072cfff9582bb0296140cfb354cb911.tar.gz
dragonruby-game-toolkit-contrib-5b2311900072cfff9582bb0296140cfb354cb911.zip
synced docs
Diffstat (limited to 'docs/search_results.txt')
-rw-r--r--docs/search_results.txt667
1 files changed, 630 insertions, 37 deletions
diff --git a/docs/search_results.txt b/docs/search_results.txt
index 50311a3..39ac95e 100644
--- a/docs/search_results.txt
+++ b/docs/search_results.txt
@@ -1,71 +1,664 @@
-* DOCS: ~Numeric#elapsed_time~
-For a given number, the elapsed frames since that number is returned.
-`Kernel.tick_count` is used to determine how many frames have elapsed.
-An optional numeric argument can be passed in which will be used instead
-of `Kernel.tick_count`.
+* Hello World
-Here is an example of how elapsed_time can be used.
+Welcome to DragonRuby Game Toolkit. Take the steps below to get started.
+
+* Join the Discord and Subscribe to the News Letter
+
+Our Discord channel is [[http://discord.dragonruby.org]].
+
+The News Letter will keep you in the loop with regards to current
+DragonRuby Events: [[http://dragonrubydispatch.com]].
+
+Those who use DragonRuby are called Dragon Riders. This identity is
+incredibly important to us. When someone asks you:
+
+#+begin_quote
+What game engine do you use?
+#+end_quote
+
+Reply with:
+
+#+begin_quote
+I am a Dragon Rider.
+#+end_quote
+
+* Watch Some Intro Videos
+
+Each video is only 20 minutes and all of them will fit into a lunch
+break. So please watch them:
+
+1. Beginner Introduction to DragonRuby Game Toolkit: [[https://youtu.be/ixw7TJhU08E]]
+2. Intermediate Introduction to Ruby Syntax: [[https://youtu.be/HG-XRZ5Ppgc]]
+3. Intermediate Introduction to Arrays in Ruby: [[https://youtu.be/N72sEYFRqfo]]
+
+The second and third videos are not required if you are proficient
+with Ruby, but *definitely* watch the first one.
+
+You may also want to try this free course provided at
+[[http://dragonruby.school]].
+
+* Getting Started Tutorial
+
+This is a tutorial written by Ryan C Gordon (a Juggernaut in the
+industry who has contracted to Valve, Epic, Activision, and
+EA... check out his Wikipedia page: [[https://en.wikipedia.org/wiki/Ryan_C._Gordon]]).
+
+** Introduction
+
+Welcome!
+
+Here's just a little push to get you started if you're new to
+programming or game development.
+
+If you want to write a game, it's no different than writing any other
+program for any other framework: there are a few simple rules that
+might be new to you, but more or less programming is programming no
+matter what you are building.
+
+Did you not know that? Did you think you couldn't write a game because
+you're a "web guy" or you're writing Java at a desk job? Stop letting
+people tell you that you can't, because you already have everything
+you need.
+
+Here, we're going to be programming in a language called "Ruby." In
+the interest of full disclosure, I (Ryan Gordon) wrote the C parts of
+this toolkit and Ruby looks a little strange to me (Amir Rajan wrote
+the Ruby parts, discounting the parts I mangled), but I'm going to
+walk you through the basics because we're all learning together, and
+if you mostly think of yourself as someone that writes C (or C++, C#,
+Objective-C), PHP, or Java, then you're only a step behind me right
+now.
+
+** Prerequisites
+
+Here's the most important thing you should know: Ruby lets you do some
+complicated things really easily, and you can learn that stuff
+later. I'm going to show you one or two cool tricks, but that's all.
+
+Do you know what an if statement is? A for-loop? An array? That's all
+you'll need to start.
+
+** The Game Loop
+
+Ok, here are few rules with regards to game development with GTK:
+
+- Your game is all going to happen under one function ...
+- that runs 60 times a second ...
+- and has to tell the computer what to draw each time.
+
+That's an entire video game in one run-on sentence.
+
+Here's that function. You're going to want to put this in
+mygame/app/main.rb, because that's where we'll look for it by
+default. Load it up in your favorite text editor.
+
+#+begin_src ruby
+ def tick args
+ args.outputs.labels << [580, 400, 'Hello World!']
+ end
+#+end_src
+
+Now run ~dragonruby~ ...did you get a window with "Hello World!"
+written in it? Good, you're officially a game developer!
+
+** Breakdown Of The ~tick~ Method
+
+~mygame/app/main.rb~, is where the Ruby source code is located. This
+looks a little strange, so I'll break it down line by line. In Ruby, a
+'#' character starts a single-line comment, so I'll talk about this
+inline.
+
+#+begin_src ruby
+ # This "def"ines a function, named "tick," which takes a single argument
+ # named "args". DragonRuby looks for this function and calls it every
+ # frame, 60 times a second. "args" is a magic structure with lots of
+ # information in it. You can set variables in there for your own game state,
+ # and every frame it will updated if keys are pressed, joysticks moved,
+ # mice clicked, etc.
+ def tick args
+
+ # One of the things in "args" is the "outputs" object that your game uses
+ # to draw things. Afraid of rendering APIs? No problem. In DragonRuby,
+ # you use arrays to draw things and we figure out the details.
+ # If you want to draw text on the screen, you give it an array (the thing
+ # in the [ brackets ]), with an X and Y coordinate and the text to draw.
+ # The "<<" thing says "append this array onto the list of them at
+ # args.outputs.labels)
+ args.outputs.labels << [580, 400, 'Hello World!']
+ end
+#+end_src
+
+Once your ~tick~ function finishes, we look at all the arrays you made
+and figure out how to draw it. You don't need to know about graphics
+APIs. You're just setting up some arrays! DragonRuby clears out these
+arrays every frame, so you just need to add what you need _right now_
+each time.
+
+** Rendering A Sprite
+
+Now let's spice this up a little.
+
+We're going to add some graphics. Each 2D image in DragonRuby is
+called a "sprite," and to use them, you just make sure they exist in a
+reasonable file format (png, jpg, gif, bmp, etc) and specify them by
+filename. The first time you use one, DragonRuby will load it and keep
+it in video memory for fast access in the future. If you use a
+filename that doesn't exist, you get a fun checkerboard pattern!
+
+There's a "dragonruby.png" file included, just to get you
+started. Let's have it draw every frame with our text:
+
+#+begin_src ruby
+ def tick args
+ args.outputs.labels << [580, 400, 'Hello World!']
+ args.outputs.sprites << [576, 100, 128, 101, 'dragonruby.png']
+ end
+#+end_src
+
+(Pro Tip: you don't have to restart DragonRuby to test your changes;
+when you save main.rb, DragonRuby will notice and reload your
+program.)
+
+That ~.sprites~ line says "add a sprite to the list of sprites we're
+drawing, and draw it at position (576, 100) at a size of 128x101
+pixels". You can find the image to draw at dragonruby.png.
+
+** Coordinate System and Virtual Canvas
+
+Quick note about coordinates: (0, 0) is the bottom left corner of the
+screen, and positive numbers go up and to the right. This is more
+"geometrically correct," even if it's not how you remember doing 2D
+graphics, but we chose this for a simpler reason: when you're making
+Super Mario Brothers and you want Mario to jump, you should be able to
+add to Mario's y position as he goes up and subtract as he falls. It
+makes things easier to understand.
+
+Also: your game screen is _always_ 1280x720 pixels. If you resize the
+window, we will scale and letterbox everything appropriately, so you
+never have to worry about different resolutions.
+
+Ok, now we have an image on the screen, let's animate it:
+
+#+begin_src ruby
+ def tick args
+ args.state.rotation ||= 0
+ args.outputs.labels << [580, 400, 'Hello World!' ]
+ args.outputs.sprites << [576, 100, 128, 101, 'dragonruby.png', args.state.rotation]
+ args.state.rotation -= 1
+ end
+#+end_src
+
+Now you can see that this function is getting called a lot!
+
+** Game State
+
+Here's a fun Ruby thing: ~args.state.rotation ||= 0~ is shorthand for
+"if args.state.rotation isn't initialized, set it to zero." It's a
+nice way to embed your initialization code right next to where you
+need the variable.
+
+~args.state~ is a place you can hang your own data and have it survive
+past the life of the function call. In this case, the current rotation
+of our sprite, which is happily spinning at 60 frames per second. If
+you don't specify rotation (or alpha, or color modulation, or a source
+rectangle, etc), DragonRuby picks a reasonable default, and the array
+is ordered by the most likely things you need to tell us: position,
+size, name.
+
+** There Is No Delta Time
+
+One thing we decided to do in DragonRuby is not make you worry about
+delta time: your function runs at 60 frames per second (about 16
+milliseconds) and that's that. Having to worry about framerate is
+something massive triple-AAA games do, but for fun little 2D games?
+You'd have to work really hard to not hit 60fps. All your drawing is
+happening on a GPU designed to run Fortnite quickly; it can definitely
+handle this.
+
+Since we didn't make you worry about delta time, you can just move the
+rotation by 1 every time and it works without you having to keep track
+of time and math. Want it to move faster? Subtract 2.
+
+** Handling User Input
+
+Now, let's move that image around.
#+begin_src ruby
def tick args
- args.state.last_click_at ||= 0
+ args.state.rotation ||= 0
+ args.state.x ||= 576
+ args.state.y ||= 100
- # record when a mouse click occurs
if args.inputs.mouse.click
- args.state.last_click_at = args.state.tick_count
+ args.state.x = args.inputs.mouse.click.point.x - 64
+ args.state.y = args.inputs.mouse.click.point.y - 50
end
- # Use Numeric#elapsed_time to determine how long it's been
- if args.state.last_click_at.elapsed_time > 120
- args.outputs.labels << [10, 710, "It has been over 2 seconds since the mouse was clicked."]
- end
+ args.outputs.labels << [580, 400, 'Hello World!']
+ args.outputs.sprites << [args.state.x,
+ args.state.y,
+ 128,
+ 101,
+ 'dragonruby.png',
+ args.state.rotation]
+
+ args.state.rotation -= 1
end
#+end_src
-And here is an example where the override parameter is passed in:
+Everywhere you click your mouse, the image moves there. We set a
+default location for it with ~args.state.x ||= 576~, and then we
+change those variables when we see the mouse button in action. You can
+get at the keyboard and game controllers in similar ways.
+
+** Coding On A Raspberry Pi
+
+We have only tested DragonRuby on a Raspberry Pi 3, Models B and B+, but we
+believe it _should_ work on any model with comparable specs.
+
+If you're running DragonRuby Game Toolkit on a Raspberry Pi, or trying to run
+a game made with the Toolkit on a Raspberry Pi, and it's really really slow--
+like one frame every few seconds--then there's likely a simple fix.
+
+You're probably running a desktop environment: menus, apps, web browsers,
+etc. This is okay! Launch the terminal app and type:
+
+#+begin_src
+sudo raspi-config
+#+end_src
+
+It'll ask you for your password (if you don't know, try "raspberry"), and then
+give you a menu of options. Find your way to "Advanced Options", then "GL
+Driver", and change this to "GL (Full KMS)" ... not "fake KMS," which is
+also listed there. Save and reboot. In theory, this should fix the problem.
+
+If you're _still_ having problems and have a Raspberry Pi 2 or better, go back
+to raspi-config and head over to "Advanced Options", "Memory split," and give
+the GPU 256 megabytes. You might be able to avoid this for simple games, as
+this takes RAM away from the system and reserves it for graphics. You can
+also try 128 megabytes as a gentler option.
+
+Note that you can also run DragonRuby without X11 at all: if you run it from
+a virtual terminal it will render fullscreen and won't need the "Full KMS"
+option. This might be attractive if you want to use it as a game console
+sort of thing, or develop over ssh, or launch it from RetroPie, etc.
+
+** Conclusion
+
+There is a lot more you can do with DragonRuby, but now you've already
+got just about everything you need to make a simple game. After all,
+even the most fancy games are just creating objects and moving them
+around. Experiment a little. Add a few more things and have them
+interact in small ways. Want something to go away? Just don't add it
+to ~args.output~ anymore.
+
+** IMPORTANT: Go Through All Of The Sample Apps! Study Them Thoroughly!!
+
+Now that you've completed the Hello World tutorial. Head over to the
+`samples` directory. It is very very important that you study the
+sample apps thoroughly! Go through them in order. Here is a short
+description of each sample app.
+
+1. 00_beginner_ruby_primer: This is an interactive tutorial that shows how to render ~solid~s, animated ~sprite~s, ~label~s.
+2. 00_intermediate_ruby_primer: This is a set of sample Ruby snippets that give you a high level introduction to the programming language.
+3. 01_api_01_labels: Various ways to render ~label~s.
+4. 01_api_02_lines: Various ways to render ~line~s.
+5. 01_api_03_rects: Sample app shows various ways to render ~solid~s and ~border~s.
+6. 01_api_04_sprites: Sample app shows various ways to render ~sprite~s.
+7. 01_api_05_keyboard: Hows how to get keyboard input from the user.
+8. 01_api_06_mouse: Hows how to get mouse mouse position.
+9. 01_api_07_point_to_rect: How to get mouse input from the user and shows collision/hit detection.
+10. 01_api_08_rect_to_rect: Hit detection/collision between two rectangles.
+11. 01_api_10_controller: Interaction with a USB/Bluetooth controller.
+12. 01_api_99_tech_demo: All the different render primitives along with using ~render_targets~.
+13. 02_collision_01_simple: Collision detection with dynamically moving bodies.
+14. 02_collision_02_moving_objects: Collision detection between many primitives, simple platformer physics, and keyboard input.
+15. 02_collision_03_entities: Collision with entities and serves as a small introduction to ECS (entity component system).
+16. 02_collision_04_ramp_with_debugging: How ramp trajectory can be calculated.
+17. 02_collision_05_ramp_with_debugging_two: How ramp trajectory can be calculated.
+18. 02_sprite_animation_and_keyboard_input: How to animate a sprite based off of keyboard input.
+19. 03_mouse_click: How to determine what direction/vector a mouse was clicked relative to a player.
+20. 04_sounds: How to play sounds and work with buttons.
+21. 05_mouse_move: How to determine what direction/vector a mouse was clicked relative to a player.
+22. 05_mouse_move_paint_app: Represents a simple paint app.
+23. 05_mouse_move_tile_editor: A starting point for a tile editor.
+24. 06_coordinate_systems: Shows the two origin systems within Game Toolkit where the origin is in the center and where the origin is at the bottom left.
+25. 07_render_targets: Shows a powerful concept called ~render_target~s. You can use this to programatically create sprites (it's also useful for representing parts of a scene as if it was a view port/camera).
+26. 07_render_targets_advanced: Advanced usage of ~render_target~s.
+27. 08_platformer_collisions: Axis aligned collision along with platformer physics.
+28. 08_platformer_collisions_metroidvania: How to save map data and place sprites live within a game.
+29. 08_platformer_jumping_inertia: Jump physics and how inertia affects collision.
+30. 09_controller_analog_usage_advanced_sprites: Extended properties of a ~sprite~ and how to change the rotation anchor point and render a subset/tile of a sprite.
+31. 09_sprite_animation_using_tile_sheet: How to perform sprite animates using a tile sheet.
+32. 10_save_load_game: Save and load game data.
+33. 11_coersion_of_primitives: How primitives of one specific type can be rendered as another primitive type.
+34. 11_hash_primitives: How primitives can be represented using a ~Hash~.
+35. 12_controller_input_sprite_sheet_animations: How to leverage vectors to move a player around the screen.
+36. 12_top_down_area: How to render a top down map and how to manage collision of a player.
+37. 13_01_easing_functions: How to use lerping functions to define animations/movement.
+38. 13_02_cubic_bezier: How to create a bezier curve using lines.
+39. 13_03_easing_using_spline: How a collection of bezier curves can be used to define an animation.
+40. 13_04_parametric_enemy_movement: How to define the movement of enemies and projectiles using lerping/parametric functions.
+41. 14_sprite_limits: Upper limit for how many sprites can be rendered to the screen.
+42. 14_sprite_limits_static_references: Upper limit for how many sprites can be rendered to the screen using ~static~ output collections (which are updated by reference as opposed to by value).
+43. 15_collision_limits: How many collisions can be processed across many primitives.
+44. 18_moddable_game: How you can make a game where content is authored by the player (modding support).
+45. 19_lowrez_jam: How to use ~render_targets~ to create a low resolution game.
+46. 20_roguelike_starting_point: A starting point for a roguelike and explores concepts such as line of sight.
+47. 20_roguelike_starting_point_two: A starting point for a roguelike where sprites are provided from a tile map/tile sheet.
+48. 21_mailbox_usage: How to do interprocess communication.
+49. 22_trace_debugging: Debugging techniques and tracing execution through your game.
+50. 22_trace_debugging_classes: Debugging techniques and tracing execution through your game.
+51. 23_hexagonal_grid: How to make a tactical grid/map made of hexagons.
+52. 23_isometric_grid: How to make a tactical grid/map made of isometric sprites.
+53. 24_http_example: How to make http requests.
+54. 25_3d_experiment_01_square: How to create 3D objects.
+55. 26_jam_craft: Starting point for crafting game. It also shows how to customize the mouse cursor.
+56. 99_sample_game_basic_gorillas: Reference implementation of a full game. Topics covered: physics, keyboard input, collision, sprite animation.
+57. 99_sample_game_clepto_frog: Reference implementation of a full game. Topics covered: camera control, spring/rope physics, scene orchestration.
+58. 99_sample_game_dueling_starships: Reference implementation that shows local multiplayer. Topics covered: vectors, particles, friction, inertia.
+59. 99_sample_game_flappy_dragon: Reference implementation that is a clone of Flappy Bird. Topics covered: scene orchestration, collision, sound, sprite animations, lerping.
+60. 99_sample_game_pong: Reference implementation of pong.
+61. 99_sample_game_return_of_serenity: Reference implementation of low resolution story based game.
+62. 99_sample_game_the_little_probe: Reference implementation of a full game. Topics covered: Arbitrary collision detection, loading map data, bounce/ball physics.
+63. 99_sample_nddnug_workshop: Reference implementation of a full game. Topics covered: vectors, controller input, sound, trig functions.
+64. 99_sample_snakemoji: Shows that Ruby supports coding with emojis.
+65. 99_zz_gtk_unit_tests: A collection of unit tests that exercise parts of DragonRuby's API.
+
+
+* How To Render A Sprite Using An Array
+
+All file paths should use the forward slash ~/~ *not* backslash
+~~. Game Toolkit includes a number of sprites in the ~sprites~
+folder (everything about your game is located in the ~mygame~ directory).
+
+The following code renders a sprite with a ~width~ and ~height~ of
+~100~ in the center of the screen.
+
+~args.outputs.sprites~ is used to render a sprite.
#+begin_src ruby
def tick args
- args.state.last_click_at ||= 0
+ args.outputs.sprites << [
+ 640 - 50, # X
+ 360 - 50, # Y
+ 100, # W
+ 100, # H
+ 'sprites/square-blue.png' # PATH
+ ]
+ end
+#+end_src
- # create a state variable that tracks time at half the speed of args.state.tick_count
- args.state.simulation_tick = args.state.tick_count.idiv 2
+* More Sprite Properties As An Array
- # record when a mouse click occurs
- if args.inputs.mouse.click
- args.state.last_click_at = args.state.simulation_tick
+Here are all the properties you can set on a sprite.
+
+#+begin_src ruby
+ def tick args
+ args.outputs.sprites << [
+ 100, # X
+ 100, # Y
+ 32, # W
+ 64, # H
+ 'sprites/square-blue.png', # PATH
+ 0, # ANGLE
+ 255, # ALPHA
+ 0, # RED_SATURATION
+ 255, # GREEN_SATURATION
+ 0 # BLUE_SATURATION
+ ]
+ end
+#+end_src
+
+* Different Sprite Representations
+
+Using ordinal positioning can get a little unruly given so many
+properties you have control over.
+
+You can represent a sprite as a ~Hash~:
+
+#+begin_src ruby
+ def tick args
+ args.outputs.sprites << {
+ x: 640 - 50,
+ y: 360 - 50,
+ w: 100,
+ h: 100,
+ path: 'sprites/square-blue.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
+ }
+ end
+#+end_src
+
+You can represent a sprite as an ~object~:
+
+#+begin_src 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,
+ :tile_x, :tile_y, :tile_w, :tile_h,
+ :flip_horizontally, :flip_vertically,
+ :angle_anchor_x, :angle_anchor_y
+
+ def primitive_marker
+ :sprite
end
+ end
- # Use Numeric#elapsed_time to determine how long it's been
- if (args.state.last_click_at.elapsed_time args.state.simulation_tick) > 120
- args.outputs.labels << [10, 710, "It has been over 4 seconds since the mouse was clicked."]
+ class BlueSquare < Sprite
+ def initialize opts
+ @x = opts[:x]
+ @y = opts[:y]
+ @w = opts[:w]
+ @h = opts[:h]
+ @path = 'sprites/square-blue.png'
end
end
+
+ def tick args
+ args.outputs.sprites << (BlueSquare.new x: 640 - 50,
+ y: 360 - 50,
+ w: 50,
+ h: 50)
+ end
#+end_src
+* Using ~args.state~ To Store Your Game State
+
+~args.state~ is a open data structure that allows you to define
+properties that are arbitrarily nested. You don't need to define any kind of
+~class~.
-* DOCS: ~Numeric#created?~
-Returns true if ~Numeric#elapsed_time == 0~. Essentially communicating that
-number is equal to the current frame.
+To initialize your game state, use the ~||=~ operator. Any value on
+the right side of ~||=~ will only be assigned _once_.
-Example usage:
+To assign a value every frame, just use the ~=~ operator, but _make
+sure_ you've initialized a default value.
+
+#+begin_src
+ def tick args
+ # initialize your game state ONCE
+ args.player.x ||= 0
+ args.player.y ||= 0
+ args.player.hp ||= 100
+
+ # increment the x position of the character by one every frame
+ args.player.x += 1
+
+ # Render a sprite with a label above the sprite
+ args.outputs.sprites << [
+ args.player.x,
+ args.player.y,
+ 32, 32,
+ "player.png"
+ ]
+
+ args.outputs.labels << [
+ args.player.x,
+ args.player.y - 50,
+ args.player.hp
+ ]
+ end
+#+end_src
+
+* DOCS: ~Array#map~
+
+The function given a block returns a new ~Enumerable~ of values.
+
+Example of using ~Array#map~ in conjunction with ~args.state~ and
+~args.outputs.sprites~ to render sprites to the screen.
+
+#+begin_src
+ def tick args
+ # define the colors of the rainbow in ~args.state~
+ # as an ~Array~ of ~Hash~es with :order and :name.
+ # :order will be used to determine render location
+ # and :name will be used to determine sprite path.
+ args.state.rainbow_colors ||= [
+ { order: 0, name: :red },
+ { order: 1, name: :orange },
+ { order: 2, name: :yellow },
+ { order: 3, name: :green },
+ { order: 4, name: :blue },
+ { order: 5, name: :indigo },
+ { order: 6, name: :violet },
+ ]
+
+ # render sprites diagonally to the screen
+ # with a width and height of 50.
+ args.outputs
+ .sprites << args.state
+ .rainbow_colors
+ .map do |color| # <-- ~Array#map~ usage
+ [
+ color[:order] * 50,
+ color[:order] * 50,
+ 50,
+ 50,
+ "sprites/square-#{color[:name]}.png"
+ ]
+ end
+ end
+#+end_src
+
+
+* DOCS: ~Array#each~
+
+The function, given a block, invokes the block for each item in the
+~Array~. ~Array#each~ is synonymous to foreach constructs in other languages.
+
+Example of using ~Array#each~ in conjunction with ~args.state~ and
+~args.outputs.sprites~ to render sprites to the screen:
+
+#+begin_src
+ def tick args
+ # define the colors of the rainbow in ~args.state~
+ # as an ~Array~ of ~Hash~es with :order and :name.
+ # :order will be used to determine render location
+ # and :name will be used to determine sprite path.
+ args.state.rainbow_colors ||= [
+ { order: 0, name: :red },
+ { order: 1, name: :orange },
+ { order: 2, name: :yellow },
+ { order: 3, name: :green },
+ { order: 4, name: :blue },
+ { order: 5, name: :indigo },
+ { order: 6, name: :violet },
+ ]
+
+ # render sprites diagonally to the screen
+ # with a width and height of 50.
+ args.state
+ .rainbow_colors
+ .map do |color| # <-- ~Array#each~ usage
+ args.outputs.sprites << [
+ color[:order] * 50,
+ color[:order] * 50,
+ 50,
+ 50,
+ "sprites/square-#{color[:name]}.png"
+ ]
+ end
+ end
+#+end_src
+
+
+* DOCS: ~Numeric#frame_index~
+
+This function is helpful for determining the index of frame-by-frame
+ sprite animation. The numeric value ~self~ represents the moment the
+ animation started.
+
+~frame_index~ takes three additional parameters:
+
+- How many frames exist in the sprite animation.
+- How long to hold each animation for.
+- Whether the animation should repeat.
+
+~frame_index~ will return ~nil~ if the time for the animation is out
+of bounds of the parameter specification.
+
+Example using variables:
#+begin_src ruby
def tick args
- args.state.box_queue ||= []
+ start_looping_at = 0
+ number_of_sprites = 6
+ number_of_frames_to_show_each_sprite = 4
+ does_sprite_loop = true
- if args.state.box_queue.empty?
- args.state.box_queue << { name: :red,
- create_at: args.state.tick_count + 60 }
- end
+ sprite_index =
+ start_looping_at.frame_index number_of_sprites,
+ number_of_frames_to_show_each_sprite,
+ does_sprite_loop
- boxes_to_spawn_this_frame = args.state
- .box_queue
- .find_all { |b| b[:create_at].new? }
+ sprite_index ||= 0
- boxes_to_spawn_this_frame.each { |b| puts "box #{b} was new? on #{args.state.tick_count}." }
+ args.outputs.sprites << [
+ 640 - 50,
+ 360 - 50,
+ 100,
+ 100,
+ "sprites/dragon-#{sprite_index}.png"
+ ]
+ end
+#+end_src
+
+Example using named parameters:
- args.state.box_queue -= boxes_to_spawn_this_frame
+#+begin_src ruby
+ def tick args
+ start_looping_at = 0
+
+ sprite_index =
+ start_looping_at.frame_index count: 6,
+ hold_for: 4,
+ repeat: true,
+ tick_count_override: args.state.tick_count
+
+ sprite_index ||= 0
+
+ args.outputs.sprites << [
+ 640 - 50,
+ 360 - 50,
+ 100,
+ 100,
+ "sprites/dragon-#{sprite_index}.png"
+ ]
end
#+end_src
+