Week 1 - Parts 0 and 1
Part 0 - Setting Up
Project Setup
- Acquire a licensed copy of DragonRuby GTK
- Extract to a standard location for development work
- Downloaded dragonruby-pro-linux-amd64.zip
- Opened archive and copied contents to
/home/kehvarl/DragonRuby/RLD_Tutorial_2024
- Deleted
mygame
folder - At a terminal in the newply created
RLD_Tutorial_2024
folder:git clone git@github.com:Kehvarl/roguelikedev-2024-drgtk.git ./mygame
- Install the editor of your choice
- In this instance I am using Pulsar Edit (a fork of Atom)
- Open
mygame
folder as a project in your editor
Part 1 - Drawing the '@' Symbol and Moving it around
Assuming you've followed Part 0 or otherwise set up your DragonRuby development environment, begin by opening the main.rb
file in your mygame
folder in the editor of your choice.
Opening an Empty Window
Replace the contents so what you have looks like this
def tick args args.outputs.primitives << {x:0, y:0, w:1280, h:720, r:0, g:0, b:0}.solid! end
You can run the program like any other DragonRuby program. If you're new to DragonRuby, just run the dragonruby
or dragonruby.exe
executable in the parent directory above mygame
.
You should now see a relatively plain window with a solid black background, and a title that tells you to update a different file to change it.
Open that new file mygame\metadata\game_metadata.txt
in your editor, and replace the top section with something like this:
# devid=myname # devtitle=My Name # gameid=mygame gametitle=RoguLikeDev Tutorial 2024 # version=0.1 # icon=metadata/icon.png
Lines that start with a 'sharp' (#) symbol are comments, and will be ignored in favor of their defaults. In the above example the gametitle
line has been uncommented and a new title added. Save the file and re-run dragonruby
to view the window with the new title.
Drawing to the screen
Before we proceed, what's going on in our current main.rb
?
def tick args args.outputs.primitives << {x:0, y:0, w:1280, h:720, r:0, g:0, b:0}.solid! end
tick
The line def tick args
creates a function named tick
that expects a single parameter names args
. The tick
function is special in DragonRuby, and is the main entrypoint for the engine into your game code. In the background, the engine will try to run everything in the tick
function 60 times per second, performing any drawing every time. This means that as long as your game code can run in 1/60 of a second, you can maintain 60FPS by just letting DragonRuby run.
args
The only line in our tick
function references the args
parameter. If tick
is how DragonRuby runs your code, args
is how your code interacts with DragonRuby. It lets you save and recover game-state information, it provides you with information about what inputs are being provided by your player, it includes some tools for layout, and interaction of on-screen objects, and it lets you output information to the screen. The line args.outputs.primitives << ...
uses the <<
command to append a definition to the outputs.primitives
collection for DragonRuby to draw on screen this tick.
Hashes
The definition in question: {x:0, y:0, w:1280, h:720, r:0, g:0, b:0}.solid!
is a hash (the ruby word for a dictionary or map) with a few parameters:
- x: the x position defining the left side of our rectangle (Nearly everything in DragonRuby is rects at this level)
- y: the y position defining the bottom of our rectangle
- w: The width of our rectangle
- h: The height of our rectangle
- r: , g: , b: the red, green, and blue parameters for the color to use (in this case 0,0,0 or Black)
- .solid! the primitive marker that tells DragonRuby this specific rectangle is to be filled in with the defined color
As you can see we are defining a solid black rectangle starting at the lower-left corner (0,0) that is the size of our window (1280x720), filling it completely. This gives us a black background to draw the rest of our game on top of.
Sprite hashes
In additions to "solid" rectangles, DragonRuby can render an image known as a sprite. For example, we can use the built-in blue square sprite found in the folder mygame/sprites/square/
it's named blue.png
.
A minimal sprite hash definition looks like
{x: x_value, y: y_value, w: draw_width, h: draw_height, path: sprite_path}.sprite!
As with the solid, it expects an x and y position for the lower left corner, then a width and height. Instead of a color, it looks for a path to the image to use. There are several other properties we can work with, but they all have sensible defaults. For more details, refer to the DragonRuby Documentation: API: Outputs: Sprites: Rendering a Sprite Using a Hash
Update the tick
method of your main.rb
file to look like this:
def tick args args.outputs.primitives << {x:0, y:0, w:1280, h:720, r:0, g:0, b:0}.solid! args.outputs.primitives << {x:640, y:360, w:40, h:40, path:'sprites/square/blue.png'}.sprite! end
If you now run your game, you'll see a screen like this:
Working with Sprite Sheets
Instead of drawing an entire image onto the screen, DragonRuby is capable of drawing just part of a larger image. This allows you to store several sprites in a single image file, for example all the animation frames for a specific action, or all the different animation frames for a specific character.
In this case we're going to use the included font-file sprites/mist/simple-mood-16x16.png
. This sprite sheet is a 16x16 grid of 16x16-pixel sprites that make up the simple-mood font. Using this we can easily draw ASCII characters to the screen.
To draw a single item from a sprite sheet, we need to add 4 more properties to our hash:
{x: x_value, y: y_value, w: draw_width, h: draw_height, source_x: sprite-sheet_x_position, source_y:sprite-sheet_y_position, tile_w:width_of_sprite_in_sheet, tileh:height_of_sprite, path: sprite_path}.sprite!
For example, if we adjust our tick
method like so:
def tick args args.outputs.primitives << {x:0, y:0, w:1280, h:720, r:0, g:0, b:0}.solid! args.outputs.primitives << {x:640, y:360, w:40, h:40, tile_x:0, tile_y:64, tile_w:16, tile_h:16, path:'sprites/misc/simple-mood-16x16.png'}.sprite! end
We've replaced our blue square with the "@" symbol from the sprite sheet.
Remembering State
To turn the new "@" sprite into our player representation, we need some way to make it respond to our inputs. Which means we need some way to track the sprite's state, specifically its position on the screen.
In args
there's a collection named state
. Any value stored into this collection will be available to be accessed on any future tick. We will use this to store our entire player hash like so:
def tick args args.state.player ||= {x:640, y:360, w:16, h:16, tile_x:0, tile_y:64, tile_w:16, tile_h:16, path:'sprites/misc/simple-mood-16x16.png'}.sprite! args.outputs.primitives << {x:0, y:0, w:1280, h:720, r:0, g:0, b:0}.solid! args.outputs.primitives << args.state.player end
Every time DragonRuby runs our tick
function, it checks args.state
for a variable named player
. If that variable is not set, then DragonRuby populates it with our player hash. If it was already set in a prior tick, then this line does nothing.
We also updated out output to draw the contents of our player
variable onto the screen. Meaning any update we make will be reflected in our output
Moving a Sprite
Now that we have our player sprite stored in our game state, we can change it and render our changes each tick
Getting Keyboard Input
To get inputs we will use args
again. In this case args.inputs
holds any supported input states, whether from controllers, a mouse, a touchscreen, or a keyboard.
To check for a pressed key we can look at args.inputs.keyboard.<key>
, but this will return true whether the key was just pressed, or if it's currently held down. At 60 ticks per second, that might cause the player to take several turns when they only intend to take one. Instead we'll use args.inputs.keyboard.key_down.<key>
to only move when the key is pressed, then stop and wait for a new keypress.
If we add keypress checking to the tick
method, the result might look like this:
def tick args args.state.player ||= {x:640, y:360, w:16, h:16, tile_x:0, tile_y:64, tile_w:16, tile_h:16, path:'sprites/misc/simple-mood-16x16.png'}.sprite! args.outputs.primitives << {x:0, y:0, w:1280, h:720, r:0, g:0, b:0}.solid! args.outputs.primitives << args.state.player if args.inputs.keyboard.key_down.up args.state.player.y += 16 elsif args.inputs.keyboard.key_down.down args.state.player.y -= 16 elsif args.inputs.keyboard.key_down.left args.state.player.x -= 16 elsif args.inputs.keyboard.key_down.right args.state.player.x += 16 end end
If you now run the game, you can move the player around the screen with the arrow keys
Files
Get RLD2024
RLD2024
/r/RogueLikeDev does the Complete Roguelike Tutorial 2024 -- DragonRuby Edition
Status | In development |
Category | Other |
Author | Kehvarl |
Leave a comment
Log in with itch.io to leave a comment.