Created
January 20, 2015 04:05
-
-
Save svanellewee/a5f84513d2fd46d5bf51 to your computer and use it in GitHub Desktop.
Component Entity System Golang SDL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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