Skip to content

Instantly share code, notes, and snippets.

@amirrajan
Created March 29, 2026 00:40
Show Gist options
  • Select an option

  • Save amirrajan/204157d47e646ad244bcaaa2044768d9 to your computer and use it in GitHub Desktop.

Select an option

Save amirrajan/204157d47e646ad244bcaaa2044768d9 to your computer and use it in GitHub Desktop.
DragonRuby Fiddle Tutorial Format
<html>
<head>
<title>DragonRuby - Warp Drive Tutorial</title>
</head>
<body>
<h1>DragonRuby Game Toolkit - Warp Drive Tutorial</h1>
<div itemscope="itemscope" itemtype="tutorial-step" data-step-number="1">
<div itemscope="itemscope" itemtype="tutorial-text">
<h1>Traveling at Light Speed</h1>
In this tutorial, we'll be creating a movement effect that makes it look like you're traveling at light speed.
</div>
<div itemscope="itemscope" itemtype="tutorial-code">
<pre>
<code class="language-ruby" itemprop="text">
# entry point to game
def tick args
# set the game's background color
# try changing these numbers and seeing how
# the background color changes
args.outputs.background_color = [40, 44, 52]
end
# reset the game on save
$gtk.reset
</code>
</pre>
</div>
</div>
<div itemscope="itemscope" itemtype="tutorial-step" data-step-number="2">
<div itemscope="itemscope" itemtype="tutorial-text">
<h1>Drawing Crosshairs</h1>
We are going to set our coordinate system to <code>origin_center</code> which means that <code>0, 0</code> is in the center of the screen.
</div>
<div itemscope="itemscope" itemtype="tutorial-code">
<pre>
<code class="language-ruby" itemprop="text">
def tick args
# set the coordinate system to have the
# origin in the center
args.grid.origin_center!
# draw a horizontal and vertical
# line through the origin
# horizontal line
args.outputs.lines << [ args.grid.left, # X
0, # Y
args.grid.right, # X2
0] # Y2
# vertical line
args.outputs.lines << [ 0, # X
args.grid.top, # Y
0, # X2
args.grid.bottom] # Y2
args.outputs.background_color = [40, 44, 52]
end
$gtk.reset
</code>
</pre>
</div>
</div>
<div itemscope="itemscope" itemtype="tutorial-step" data-step-number="3">
<div itemscope="itemscope" itemtype="tutorial-text">
<h1>Initializing State</h1>
We'll use RNG, and DragonRuby Game Toolkit's <code>Numeric#vector_(x|y)</code>
function to create 100 points around the origin.
</div>
<div itemscope="itemscope" itemtype="tutorial-code">
<pre>
<code class="language-ruby" itemprop="text">
def tick args
# set the coordinate system to have the
# origin in the center
args.grid.origin_center!
# set the radius of the warp tunnel
# this area will be void of stars
args.state.warp_tunnel_size = 10;
# set stars to 100 stars by first
args.state.stars ||= 100.map do |i|
# generating 100 random angles between
# 0 and 360
rand(360)
end.map do |random_angle|
# create a Hash with initial
# starting locations, color
# and speed (between 3 and 13 pixels)
{ initial_x: random_angle.vector_x *
args.state.warp_tunnel_size,
initial_y: random_angle.vector_y *
args.state.warp_tunnel_size,
angle: random_angle,
r: 128,
g: rand(128) + 128,
b: rand(128) + 128,
s: rand(13) + 3 }
end.map do |star|
# using the initial hash
# generate the the starting
# position as a pixel
star.merge x: star[:initial_x],
y: star[:initial_y],
w: 1,
h: 1
end
# black background color
args.outputs.background_color = [0, 0, 0]
# render the stars as solid pixels
args.outputs.solids << args.state.stars
end
$gtk.reset
</code>
</pre>
</div>
</div>
<div itemscope="itemscope" itemtype="tutorial-step" data-step-number="4">
<div itemscope="itemscope" itemtype="tutorial-text">
<h1>Moving Things</h1>
Now that we have the stars created. Let's move them (we take this opportunity to refactor
the <code>tick</code> method into multiple parts).
</div>
<div itemscope="itemscope" itemtype="tutorial-code">
<pre>
<code class="language-ruby" itemprop="text">
# refactor the code to seperate
# methods
def tick args
# initialize default values
defaults args
# render the game
render args
# calculate the next step of the game
calc args
end
def calc args
# for each star move it along the
# normal vector denoted by its angle
args.state.stars.each do |star|
star[:x] += star[:angle].vector_x * star[:s]
star[:y] += star[:angle].vector_y * star[:s]
end
end
def render args
args.outputs.background_color = [0, 0, 0]
args.outputs.solids << args.state.stars
end
def defaults args
args.grid.origin_center!
args.state.warp_tunnel_size = 10;
args.state.stars ||= 100.map do |i|
rand(360)
end.map do |random_angle|
{ initial_x: random_angle.vector_x *
args.state.warp_tunnel_size,
initial_y: random_angle.vector_y *
args.state.warp_tunnel_size,
angle: random_angle,
r: 128,
g: rand(128) + 128,
b: rand(128) + 128,
s: 0.1 + rand * 2 }
end.map do |star|
star.merge x: star[:initial_x],
y: star[:initial_y],
w: 1,
h: 1
end
end
$gtk.reset
</code>
</pre>
</div>
</div>
<div itemscope="itemscope" itemtype="tutorial-step" data-step-number="5">
<div itemscope="itemscope" itemtype="tutorial-text">
<h1>Reset Initial Star State</h1>
There was a sudden explosion of movement, and then nothing.
Once a star is off the screen, we'll want to reset its
position back to its starting point.
</div>
<div itemscope="itemscope" itemtype="tutorial-code">
<pre>
<code class="language-ruby" itemprop="text">
def tick args
defaults args
render args
calc args
end
def calc args
args.state.stars.each do |star|
star[:x] += star[:angle].vector_x * star[:s]
star[:y] += star[:angle].vector_y * star[:s]
end
args.state.stars.find_all do |star|
# find all stars that no longer
# intersect the game's render area
!star.intersect_rect? args.grid.rect
end.each do |star|
# for those stars, reset them back to their
# original position
star[:x] = star[:initial_x]
star[:y] = star[:initial_y]
end
end
def render args
args.outputs.background_color = [0, 0, 0]
args.outputs.solids << args.state.stars
end
def defaults args
args.grid.origin_center!
args.state.warp_tunnel_size = 10;
args.state.stars ||= 100.map do |i|
rand(360)
end.map do |random_angle|
{ initial_x: random_angle.vector_x *
args.state.warp_tunnel_size,
initial_y: random_angle.vector_y *
args.state.warp_tunnel_size,
angle: random_angle,
r: 128,
g: rand(128) + 128,
b: rand(128) + 128,
s: 0.1 + rand * 2 }
end.map do |star|
star.merge x: star[:initial_x],
y: star[:initial_y],
w: 1,
h: 1
end
end
$gtk.reset
</code>
</pre>
</div>
</div>
<div itemscope="itemscope" itemtype="tutorial-step" data-step-number="6">
<div itemscope="itemscope" itemtype="tutorial-text">
<h1>3D Effects</h1>
You can give the movement a bit more depth by accelerating the
star and increasing its size over time. This is the final result.
Play around with the properties and see how altering the numbers gives
you different results.
</div>
<div itemscope="itemscope" itemtype="tutorial-code">
<pre>
<code class="language-ruby" itemprop="text">
def tick args
defaults args
render args
calc args
end
def calc args
args.state.stars.each do |star|
star[:x] += star[:angle].vector_x * star[:s]
star[:y] += star[:angle].vector_y * star[:s]
# track the distance the star has moved
star[:d] += star[:s]
# increase the speed of the star by 20%
star[:s] *= 1.2
# change to width and height of the
# star to grow as the distance increases
# as if it's moving towards you
star[:w] = 1 + 15 * star[:d].fdiv(100)
star[:h] = 1 + 15 * star[:d].fdiv(100)
star[:x] += star[:angle].vector_x *
star[:w].fdiv(2)
star[:y] += star[:angle].vector_y *
star[:h].fdiv(2)
end
args.state.stars.find_all do |star|
!star.intersect_rect? args.grid.rect
end.each do |star|
# reset stars, but initialize
# them with a new random speed
star[:x] = star[:initial_x]
star[:y] = star[:initial_y]
star[:s] = 0.1 * rand
star[:d] = 0
star[:w] = 1
star[:h] = 1
end
end
def render args
args.outputs.background_color = [0, 0, 0]
args.outputs.solids << args.state.stars
end
def defaults args
args.grid.origin_center!
args.state.warp_tunnel_size = 10;
args.state.stars ||= 100.map do |i|
rand(360)
end.map do |random_angle|
{ initial_x: random_angle.vector_x *
args.state.warp_tunnel_size,
initial_y: random_angle.vector_y *
args.state.warp_tunnel_size,
angle: random_angle,
r: 128,
g: rand(128) + 128,
b: rand(128) + 128 }
end.map do |star|
star.merge x: star[:initial_x],
y: star[:initial_y],
w: 1, h: 1,
# make the speed a very small
# random number
s: 0.1 * rand,
# initialize a property
# to keep track of distance
# traveled
d: 0
end
end
$gtk.reset
</code>
</pre>
</div>
</div>
<footer id="bottom"></footer>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment