Skip to content

Instantly share code, notes, and snippets.

@svanellewee
Created January 20, 2015 04:05
Show Gist options
  • Select an option

  • Save svanellewee/a5f84513d2fd46d5bf51 to your computer and use it in GitHub Desktop.

Select an option

Save svanellewee/a5f84513d2fd46d5bf51 to your computer and use it in GitHub Desktop.
Component Entity System Golang SDL
package main
import (
"fmt"
"github.com/veandco/go-sdl2/sdl"
"os"
)
type (
AnyType interface{}
EntityId int // just a number
Component interface{
Execute(entityId EntityId, info AnyType)
}
ComponentName string
Entity map[ComponentName]Component
Entities []Entity
)
var (
winTitle string = "Go-SDL2 Events"
winWidth, winHeight int = 800, 600
entityList Entities
entityIndex int
)
const (
MAX_ENTITIES = 10
)
func init() {
entityList = make(Entities,MAX_ENTITIES)
entityIndex = 0
}
func (entityId EntityId) AddComponent(name ComponentName, component Component) {
if int(entityId) > entityIndex {
return
}
if _, exists := entityList[entityId][name]; exists == true {
return
}
entityList[entityId][name] = component
return
}
func (entities Entities) NewEntity() (result EntityId) {
entityId := entityIndex
entities[entityIndex] = make(Entity)
entityIndex += 1
return EntityId(entityId)
}
func (entities Entities) RunSystem(componentName ComponentName, info AnyType) {
for idx, entity := range entities {
if _, keyExists := entity[componentName]; keyExists {
entityId := EntityId(idx)
entity[componentName].Execute(entityId, info)
}
}
return
}
type (
Appearance struct {
X int32
Y int32
Width int32
Height int32
Color []uint8
}
)
func (appearance *Appearance) Execute(entityId EntityId, info AnyType) {
renderer := info.(*sdl.Renderer)
fmt.Println("Execute appearance for id",appearance,renderer)
rect := sdl.Rect{appearance.X, appearance.Y, appearance.Width, appearance.Height}
r,g,b,a := appearance.Color[0],appearance.Color[1],appearance.Color[2],appearance.Color[3]
(*sdl.Renderer).SetDrawColor(renderer, r,g,b,a)
renderer.FillRect(&rect)
}
type (
UserMovement struct {
}
SignalMovement struct {
X int32
Y int32
}
)
func (x *UserMovement) Execute(entityId EntityId,info AnyType) {
appearanceComponent, exists := entityList[entityId]["appearance"]
if !exists {
return
}
appearance, castsOk := appearanceComponent.(*Appearance)
if !castsOk {
return
}
movement, signalCastsOk := info.(SignalMovement)
if !signalCastsOk {
return
}
appearance.X = movement.X + appearance.X
appearance.Y = movement.Y + appearance.Y
entityList[entityId]["appearance"] = appearance
}
type (
PhysicsMovement struct {
X int32
Y int32
}
)
func (movement *PhysicsMovement) Execute(entityId EntityId, info AnyType) {
appearanceComponent, exists := entityList[entityId]["appearance"]
if !exists {
return
}
appearance, castsOk := appearanceComponent.(*Appearance)
if !castsOk {
return
}
appearance.X = movement.X + appearance.X
appearance.Y = movement.Y + appearance.Y
entityList[entityId]["appearance"] = appearance
winHeight32 := int32(winHeight)
winWidth32 := int32(winWidth)
if winHeight32 < (appearance.Y + appearance.Height) || appearance.Y < 0 {
movement.Y = -movement.Y
}
if winWidth32 < (appearance.X + appearance.Width) || appearance.X < 0 {
movement.X = -movement.X
}
}
// system runs over entities
// http://vasir.net/blog/game-development/how-to-build-entity-component-system-in-javascript
// RenderComponent
// MovementComponent
//
func main() {
var window *sdl.Window
var err error
if 0 != sdl.Init(sdl.INIT_EVERYTHING) {
panic(sdl.GetError())
}
defer sdl.Quit()
window,err = sdl.CreateWindow(winTitle, sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, winWidth, winHeight, sdl.WINDOW_SHOWN)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create window: %s\n", err)
os.Exit(1)
}
defer window.Destroy()
var renderer *sdl.Renderer
renderer,err = sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create renderer: %s\n", err)
os.Exit(2)
}
defer renderer.Destroy()
renderer.SetDrawColor(0,0,0,255)
renderer.Clear()
var event sdl.Event
var running bool
// rect := sdl.Rect{0, 0, 200, 50}
rectId := entityList.NewEntity()
rectId.AddComponent("appearance", &Appearance{
X: 0,
Y: 0,
Width: 200,
Height: 50,
Color: []uint8{ 0, 0, 255,255},
})
rectId.AddComponent("movement", &UserMovement{})
ballId := entityList.NewEntity()
ballId.AddComponent("appearance", &Appearance{
X: 0,
Y: 0,
Width: 10,
Height: 10,
Color: []uint8{ 255, 0, 255,255},
})
ballId.AddComponent("physics", &PhysicsMovement{
X: 1,
Y: 1,
})
running = true
for running {
renderer.SetDrawColor(0,0,0,255)
renderer.Clear()
movement := SignalMovement{}
for event = sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
switch t := event.(type) {
case *sdl.QuitEvent:
running = false
case *sdl.KeyDownEvent:
fmt.Printf("[%d ms] Keyboard\ttype:%d\tsym:%c\tmodifiers:%d\tstate:%d\trepeat:%d\n",t.Timestamp, t.Type, t.Keysym.Sym, t.Keysym.Mod, t.State, t.Repeat)
switch t.Keysym.Sym {
case sdl.K_LEFT:
//rect.X-=10
movement.X = -10
case sdl.K_RIGHT:
// rect.X+=10
movement.X = 10
}
}
}
entityList.RunSystem("appearance",renderer)
entityList.RunSystem("movement",movement)
entityList.RunSystem("physics",nil)
renderer.Present()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment