-
Notifications
You must be signed in to change notification settings - Fork 0
Macaw basic concepts
To create the game window you will need to Initialize()
Macaw first.
Entities are the objects which will contain an ID, etype (entity type which is a string) and components which will hold the true data of this object.
An Entity must implements an interface (Entitier). You should not be worried with the functions if you are using the EntityManager from Macaw.
To create an entity with the EntityManager all you have to do is the following:
entityManager := &entity.Manager{}
player := em.Create("player")
This will create the "player" entity.
Components are the structures that contain the "true" data of the entity. An Entity can have multiple components. Components cannot have any logic.
Take a look at the PositionComponent
that comes with Macaw:
type PositionComponent struct {
Pos *sdl.Point
}
All it has is a *sdl.Point
variable. To add or remove components from the entity, use the entity manager. Following the previous example we can add the following components to our player:
// Player component
player.AddComponent(&entity.PositionComponent{&sdl.Point{20, 20}})
player.AddComponent(&entity.CollisionComponent{CollisionAreas: []sdl.Rect{sdl.Rect{0, 0, 10, 80}}})
// Let's also add a camera component that is required to the game engine to be run!
camera := em.Create("camera")
camera.AddComponent(&entity.PositionComponent{&sdl.Point{0, 0}})
camera.AddComponent(&entity.CameraComponent{
ViewportSize: sdl.Point{800, 600},
WorldSize: sdl.Point{1145, 600},
})
Macaw comes with built-in systems. At this moment we have render*, physics and collision systems.
You can (and should) add systems to your game to implement logic to your game. The recommended way is to create a package with your system.
A system must implement the Systemer
interface, which means, have a Init()
and Update()
function.
Here is an example of a system that will keep moving the player entity we have been using in this wiki page
import (
"github.com/tubelz/macaw/entity"
)
type MovePlayerSystem struct {
EntityManager *entity.Manager
Name string
}
// Init initialize this system
func (mps *MovePlayerSystem) Init() {}
// Update will move the player to the right
func (mps *MovePlayerSystem) Update() {
var player *entity.Entity
// IterAvailable will loop only through the entities that are being used in our array
it := p.EntityManager.IterAvailable()
for tmpObj, itok := it(); itok; tmpObj, itok = it() {
if tmpObj.GetType() == "player" {
player = tmpObj
break
}
}
// Get the components we are interested in
component, _ := ball.GetComponent("position")
posComponent := component.(*entity.PositionComponent)
posComponent.X++
}
A Scene
is responsible to divide our game logic (systems) and components. You are required to have at least one Scene in your game.
You can move between the scenes using the SceneManager
that is embedded in the Gameloop
.
It is not required to have a name per Scene, but it is highly recommended. Here is also where you define some options that will impact your Game Window like showing/hiding your cursor, background color, and music.
Example of a Scene in our game
// getting the systems we want to add to our Scene...
render := &system.RenderSystem{Name: "render system", Window: macaw.Window, EntityManager: em}
movePlayer := &customsystem.MovePlayerSystem{Name: "move player system", EntityManager: em}
myInitFunc := func() { log.Print("My Awesome Scene!") }
bgColor := sdl.Color{32, 180, 230, 255}
scene := &macaw.Scene{
Name: "SomeName",
InitFunc: myInitFunc,
SceneOptions: macaw.SceneOptions{BgColor: bgColor, HideCursor: true},
}
scene.AddRenderSystem(renderSystem)
scene.AddGameUpdateSystem(movePlayerSystem)
We are almost done!
Our Game loop works in the following way:
It takes care of all of the player's input, it runs all of our game's logic (GameUpdateSystem
) and then after we accomplish what we need in the timeframe given by our minimum FPS, it will render as much as possible! That's it.
The game loop requires at least one scene!
// Initialize the game loop
gameLoop := &macaw.GameLoop{}
gameLoop.AddScene(scene)
// Execute the game loop
gameLoop.Run()