-
Notifications
You must be signed in to change notification settings - Fork 3
Tutorial
This tutorial walks you through creating a simple Gosu game window with a single Entity that has a sprite that is drawn to the screen and can be moved with the keyboard.
If you haven't already, you can install Gosu and Baku with bundler by adding them both to your Gemfile
and running bundle
or by simply running:
$ gem install gosu
$ gem install baku
Create an empty Gosu game window in a file called quick_start.rb
by extending Gosu::Window
and overriding the #initialize
, #update
, and #draw
methods:
require 'gosu'
require 'baku'
class QuickStart < Gosu::Window
def initialize
super(640, 480)
self.caption = "Quick Start"
end
def update
end
def draw
end
end
QuickStart.new.show
Before continuing, open your terminal and make sure your empty game window runs by navigating to the folder with quick_start.rb
and running:
$ ruby quick_start.rb
You should see a black 640 x 480 window pop up with the title "Quick Start". If not, make sure you included the require
statements at the top of quick_start.rb
and don't forget to call QuickStart.new.show
at the bottom.
In your game window's #initialize
method, create a Baku::World
instance.
def initialize
...
@world = Baku::World.new
end
Now call @world.update
in your #update
method and @world.draw
in your draw
method:
def update
@world.update(0)
end
def draw
@world.draw
end
Note that normally you would pass the milliseconds that have elapsed since the last frame into World#update
but we don't need to worry about that for now so just pass it 0
. These changes will cause our World to run the Systems we're going to create on every iteration of the #update
and #draw
methods in our game loop.
Now that we have a World object, we can use it to create our first Entity by calling World#create_entity
:
def initialize
...
@world = Baku::World.new
entity = @world.create_entity
end
This is a completely empty Entity object. Right now it has no Components and we have not yet created any Systems to process it. Let's create our Components first.
Components store the data that defines the behavior of an Entity and can be created by extending Baku::Component
. First, create transform_component.rb
to store the position of your Entity in 2D space:
class TransformComponent < Baku::Component
attr_accessor :x, :y
def initialize(x, y)
super()
@x = x
@y = y
end
end
Next, create sprite_component.rb
to store a sprite texture for your Entity so that it can be drawn to the screen:
class SpriteComponent < Baku::Component
attr_accessor :texture
def initialize(texture)
super()
@texture = texture
end
end
Let's go back and add these components to our Entity. Make sure you first require them at the top of quick_start.rb
:
require_relative 'transform_component.rb'
require_relative 'sprite_component.rb'
Use Entity#add_component
to add the TransformComponent
and give our Entity x and y coordinates of (100, 100)
:
def initialize
...
entity = @world.create_entity
entity.add_component(TransformComponent.new(100, 100))
end
We'll need an image to use as our Entity's sprite. Do a quick Google search or find something on OpenGameArt if you don't have anything handy. Once you've found an image, put it in the same folder as quick_start.rb
, then load it with Gosu and use it to create the SpriteComponent
for our Entity. Make sure you update the image filename in the code below to point to your image:
def initialize
...
entity = @world.create_entity
entity.add_component(TransformComponent.new(100, 100))
texture = Gosu::Image.new("my_sprite.png")
entity.add_component(SpriteComponent.new(texture))
end
Now we have an Entity with two components. Instead of being an empty shell, it now represents an object in our game that has a position in 2D space and can be drawn to the screen. Neat!
Next, let's make some Systems that will move our sprite around and draw it to the screen.
Systems contain the logic of our game. Usually you will be creating systems that process entities by extending Baku::ComponentSystem
. On each iteration of the game loop, a ComponentSystem will process any Entities that contain the Components specified in the ComponentSystem constructor.
Let's first create input_system.rb
to move our Entity in response to keyboard input:
class InputSystem < Baku::ComponentSystem
def initialize
super([TransformComponent], :update)
end
def process_entity(entity, transform)
speed = 5
if Gosu.button_down?(Gosu::KB_UP)
transform.y -= speed
elsif Gosu.button_down?(Gosu::KB_DOWN)
transform.y += speed
elsif Gosu.button_down?(Gosu::KB_LEFT)
transform.x -= speed
elsif Gosu.button_down?(Gosu::KB_RIGHT)
transform.x += speed
end
end
end
Note that we must call super
in the constructor and pass it a list of the components that an Entity must possess in order to be processed by this system and also a symbol that specifies to run this system during the update
step of the game loop.
We must also override the System#process_entity
method with entity
as the first parameter and then one parameter for each Component specified in the constructor.
Now let's create a second system that will be responsible for drawing our Entity's sprite to the screen. It will require an Entity to have both a SpriteComponent
and a TransformComponent
and should be run during the draw
step:
class SpriteRenderSystem < Baku::ComponentSystem
def initialize
super([SpriteComponent, TransformComponent], :draw)
end
def process_entity(entity, sprite, transform)
sprite.texture.draw(transform.x, transform.y, 0)
end
end
Now let's add these Systems to our World. Back in quick_start.rb
, require both of the Systems at the top:
require_relative 'input_system.rb'
require_relative 'sprite_render_system.rb'
Then add both Systems to the World just after creating it:
def initialize
...
@world = Baku::World.new
@world.add_system(InputSystem.new)
@world.add_system(SpriteRenderSystem.new)
...
end
These Systems will now be run during the update
and draw
steps of our game.
Start the game again by switching to your terminal and running:
$ ruby quick_start.rb
You should now see your sprite being drawn to the screen and you should be able to move it around with the arrow keys on your keyboard.
That concludes our quick start tutorial. If you would like to see a more complete example, check out this example implementation of Asteroids. Or you can read more about Entity Component System frameworks in the Intro to ECS section.
Otherwise, happy Baku-ing!