reflection goes out of the window

This commit is contained in:
thefish 2019-11-10 01:24:45 +03:00
parent bc00262ead
commit f442dc6921
16 changed files with 87 additions and 63 deletions

View File

@ -72,8 +72,10 @@ func main() {
level, rooms := mapgens.DefaultGen(gamemap.NewLevel(mainCtx, "test", 1))
State.Level = level
sidebarWidth := 0
//Set up viewport
vp := mainwindow.NewViewPort(30, 0, (mw.W - 30), (mw.H - 0), mw.GetLayer("base"))
vp := mainwindow.NewViewPort(sidebarWidth, 0, (mw.W - sidebarWidth), (mw.H - 0), mw.GetLayer("base"))
go vp.Listen(State)
//set up controller
@ -126,7 +128,7 @@ func main() {
"Items in your backpack:",
//"[color=yellow]Note[/color]: Many of these are not implemented yet",
"",
types.NewCenteredRect(mw.Rect, 50, 15),
types.NewCenteredRect(mw.Rect, 70, 25),
true, ).
SetBgColor("#ef305c70").
SetFgColor("white").
@ -232,7 +234,7 @@ func decodeInput(ctx util.ClientCtx, baseLayer *mainwindow.Layer) {
return
}
var pressed = ""
var isModifier, _ = util.InArray(keycode, modifiers)
var isModifier, _ = util.IntInSlice(keycode, modifiers)
if !isModifier {
pressed = ui.Scancodemap[keycode]

View File

@ -2,8 +2,13 @@ package ecs
// ECS system by jcerise, github.com/jcerise/gogue
import "reflect"
const AppearanceComponent = "appearance"
const CoordsComponent = "coords"
const MobComponent = "mob"
const MoveableComponent = "movable"
const CarriedComponent = "carried"
const UsableComponent = "usable"
type Component interface {
TypeOf() reflect.Type
Type() string
}

View File

@ -4,17 +4,16 @@ package ecs
import (
"fmt"
"reflect"
"sort"
)
type Controller struct {
systems map[reflect.Type]System
systems map[string]System
sortedSystems map[int][]System
priorityKeys []int
nextEntityID Entity
components map[reflect.Type][]Entity
entities map[Entity]map[reflect.Type]Component
components map[string][]Entity
entities map[Entity]map[string]Component
deadEntities []int
// The component map will keep track of what components are available
@ -24,12 +23,12 @@ type Controller struct {
// NewController is a convenience/constructor method to properly initialize a new processor
func NewController() *Controller {
controller := Controller{}
controller.systems = make(map[reflect.Type]System)
controller.systems = make(map[string]System)
controller.sortedSystems = make(map[int][]System)
controller.priorityKeys = []int{}
controller.nextEntityID = 0
controller.components = make(map[reflect.Type][]Entity)
controller.entities = make(map[Entity]map[reflect.Type]Component)
controller.components = make(map[string][]Entity)
controller.entities = make(map[Entity]map[string]Component)
controller.deadEntities = []int{}
controller.componentMap = make(map[string]Component)
@ -47,7 +46,7 @@ func (c *Controller) CreateEntity(components []Component) Entity {
}
}
c.entities[c.nextEntityID] = make(map[reflect.Type]Component)
c.entities[c.nextEntityID] = make(map[string]Component)
return c.nextEntityID
}
@ -89,7 +88,7 @@ func (c *Controller) GetMappedComponentClass(componentName string) Component {
// as you can check which entites are associated with a component, and vice versa.
func (c *Controller) AddComponent(entity Entity, component Component) {
// First, get the type of the component
componentType := reflect.TypeOf(component)
componentType := component.Type()
// Record that the component type is associated with the entity.
c.components[componentType] = append(c.components[componentType], entity)
@ -97,14 +96,14 @@ func (c *Controller) AddComponent(entity Entity, component Component) {
// Now, check to see if the entity is already tracked in the controller entity list. If it is not, add it, and
// associate the component with it
if _, ok := c.entities[entity]; !ok {
c.entities[entity] = make(map[reflect.Type]Component)
c.entities[entity] = make(map[string]Component)
}
c.entities[entity][componentType] = component
}
// HasComponent checks a given entity to see if it has a given component associated with it
func (c *Controller) HasComponent(entity Entity, componentType reflect.Type) bool {
func (c *Controller) HasComponent(entity Entity, componentType string) bool {
if _, ok := c.entities[entity][componentType]; ok {
return true
} else {
@ -113,7 +112,7 @@ func (c *Controller) HasComponent(entity Entity, componentType reflect.Type) boo
}
// GetComponent returns the component instance for a component type, if one exists for the provided entity
func (c *Controller) GetComponent(entity Entity, componentType reflect.Type) Component {
func (c *Controller) GetComponent(entity Entity, componentType string) Component {
// Check the given entity has the provided component
if c.HasComponent(entity, componentType) {
return c.entities[entity][componentType]
@ -123,7 +122,7 @@ func (c *Controller) GetComponent(entity Entity, componentType reflect.Type) Com
}
// GetEntity gets a specific entity, and all of its component instances
func (c *Controller) GetEntity(entity Entity) map[reflect.Type]Component {
func (c *Controller) GetEntity(entity Entity) map[string]Component {
for i, _ := range c.entities {
if i == entity {
return c.entities[entity]
@ -134,13 +133,13 @@ func (c *Controller) GetEntity(entity Entity) map[reflect.Type]Component {
}
// GetEntities returns a map of all entities and their component instances
func (c *Controller) GetEntities() map[Entity]map[reflect.Type]Component {
func (c *Controller) GetEntities() map[Entity]map[string]Component {
return c.entities
}
// GetEntitiesWithComponent returns a list of all entities with a given component attached
// TODO: Allow for passing a list of components
func (c *Controller) GetEntitiesWithComponent(componentType reflect.Type) []Entity {
func (c *Controller) GetEntitiesWithComponent(componentType string) []Entity {
entitiesWithComponent := make([]Entity, 0)
for entity := range c.entities {
if c.HasComponent(entity, componentType) {
@ -152,7 +151,7 @@ func (c *Controller) GetEntitiesWithComponent(componentType reflect.Type) []Enti
}
// UpdateComponent updates a component on an entity with a new version of the same component
func (c *Controller) UpdateComponent(entity Entity, componentType reflect.Type, newComponent Component) Entity {
func (c *Controller) UpdateComponent(entity Entity, componentType string, newComponent Component) Entity {
// First, remove the component in question (Don't actually update things, but rather remove and replace)
c.RemoveComponent(entity, componentType)
@ -165,7 +164,7 @@ func (c *Controller) UpdateComponent(entity Entity, componentType reflect.Type,
// DeleteComponent will delete a component instance from an entity, based on component type. It will also remove the
// association between the component and the entity, and remove the component from the processor completely if no
// other entities are using it.
func (c *Controller) RemoveComponent(entity Entity, componentType reflect.Type) Entity {
func (c *Controller) RemoveComponent(entity Entity, componentType string) Entity {
// Find the index of the entity to operate on in the components slice
index := -1
for i, v := range c.components[componentType] {
@ -194,7 +193,7 @@ func (c *Controller) RemoveComponent(entity Entity, componentType reflect.Type)
// numeric order, low to high. If multiple systems are registered as the same priority, they will be randomly run within
// that priority group.
func (c *Controller) AddSystem(system System, priority int) {
systemType := reflect.TypeOf(system)
systemType := system.SystemType()
if _, ok := c.systems[systemType]; !ok {
// A system of this type has not been added yet, so add it to the systems list
@ -214,10 +213,10 @@ func (c *Controller) AddSystem(system System, priority int) {
// Process kicks off system processing for all systems attached to the controller. Systems will be processed in the
// order they are found, or if they have a priority, in priority order. If there is a mix of systems with priority and
// without, systems with priority will be processed first (in order).
func (c *Controller) Process(excludedSystems []reflect.Type) {
func (c *Controller) Process(excludedSystems []string) {
for _, key := range c.priorityKeys {
for _, system := range c.sortedSystems[key] {
systemType := reflect.TypeOf(system)
systemType := system.SystemType()
// Check if the current system type was marked as excluded on this call. If it was, not process it.
if !TypeInSlice(systemType, excludedSystems) {
@ -228,7 +227,7 @@ func (c *Controller) Process(excludedSystems []reflect.Type) {
}
// HasSystem checks the controller to see if it has a given system associated with it
func (c *Controller) HasSystem(systemType reflect.Type) bool {
func (c *Controller) HasSystem(systemType string) bool {
if _, ok := c.systems[systemType]; ok {
return true
} else {
@ -237,7 +236,7 @@ func (c *Controller) HasSystem(systemType reflect.Type) bool {
}
// ProcessSystem allows for on demand processing of individual systems, rather than processing all at once via Process
func (c *Controller) ProcessSystem(systemType reflect.Type) {
func (c *Controller) ProcessSystem(systemType string) {
if c.HasSystem(systemType) {
system := c.systems[systemType]
system.Process()

View File

@ -2,6 +2,9 @@ package ecs
// ECS system by jcerise, github.com/jcerise/gogue
const MobRenderSystem = "mobrender"
type System interface {
Process()
SystemType() string
}

View File

@ -13,11 +13,11 @@ type MobRenderSystem struct {
func (mrs MobRenderSystem) Process(){
for e := range mrs.EntityController.GetEntities() {
if mrs.EntityController.HasComponent(e, types.Coords{}.TypeOf()) &&
mrs.EntityController.HasComponent(e, types.Appearance{}.TypeOf()) {
if mrs.EntityController.HasComponent(e, ecs.CoordsComponent) &&
mrs.EntityController.HasComponent(e, ecs.AppearanceComponent) {
pos := mrs.EntityController.GetComponent(e, types.Coords{}.TypeOf()).(types.Coords)
appearance := mrs.EntityController.GetComponent(e, types.Appearance{}.TypeOf()).(types.Appearance)
pos := mrs.EntityController.GetComponent(e, ecs.CoordsComponent).(types.Coords)
appearance := mrs.EntityController.GetComponent(e, ecs.AppearanceComponent).(types.Appearance)
//fixme
// Clear the cell this entity occupies, so it is the only glyph drawn there
@ -30,4 +30,8 @@ func (mrs MobRenderSystem) Process(){
//gogue.PrintGlyph(pos.X, pos.Y, appearance.Glyph, "", appearance.Layer)
}
}
}
func (mrs MobRenderSystem) SystemType() string {
return ecs.MobRenderSystem
}

View File

@ -2,8 +2,6 @@ package ecs
// ECS system by jcerise, github.com/jcerise/gogue
import "reflect"
// IntInSlice will return true if the integer value provided is present in the slice provided, false otherwise.
func IntInSlice(a int, list []int) bool {
for _, b := range list {
@ -15,7 +13,7 @@ func IntInSlice(a int, list []int) bool {
}
// TypeInSlice will return true if the reflect.Type provided is present in the slice provided, false otherwise.
func TypeInSlice(a reflect.Type, list []reflect.Type) bool {
func TypeInSlice(a string, list []string) bool {
for _, b := range list {
if b == a {
return true

View File

@ -8,7 +8,7 @@ import (
//fixme move to config
var minRoomSize = 3
var maxRoomSize = 22
var maxrooms = 30
var maxrooms = 50
//fixme make closure to stack them
func DefaultGen(l *gamemap.Level) (*gamemap.Level, []*gamemap.Room) {

View File

@ -1,8 +1,8 @@
package mob
import (
"lab.zaar.be/thefish/alchemyst-go/engine/ecs"
"lab.zaar.be/thefish/alchemyst-go/engine/types"
"reflect"
)
type Mob struct {
@ -15,6 +15,6 @@ func (m *Mob) Render() {
}
func (mob Mob) TypeOf() reflect.Type {
return reflect.TypeOf(mob)
func (mob Mob) Type() string {
return ecs.MobComponent
}

View File

@ -5,7 +5,6 @@ import (
"lab.zaar.be/thefish/alchemyst-go/engine/gamemap"
"lab.zaar.be/thefish/alchemyst-go/engine/mob"
"lab.zaar.be/thefish/alchemyst-go/engine/types"
"reflect"
)
type Moveable struct {
@ -13,6 +12,9 @@ type Moveable struct {
Level *gamemap.Level
}
func (mov Moveable) Type() string {
return ecs.MoveableComponent
}
func (mov Moveable) Walk() {
@ -23,9 +25,9 @@ func (mov Moveable) IsBlocked(c types.Coords) bool {
if mov.Level.GetTile(c).BlocksPass == true {
return true
}
list := mov.Controller.GetEntitiesWithComponent(mob.Mob{}.TypeOf())
list := mov.Controller.GetEntitiesWithComponent(ecs.MobComponent)
for idx, _ := range list {
coords := mov.Controller.GetComponent(list[idx], types.Coords{}.TypeOf())
coords := mov.Controller.GetComponent(list[idx], ecs.CoordsComponent)
if coords == nil {
continue
}
@ -33,7 +35,7 @@ func (mov Moveable) IsBlocked(c types.Coords) bool {
if coords != c {
continue
}
m := mov.Controller.GetComponent(list[idx], mob.Mob{}.TypeOf())
m := mov.Controller.GetComponent(list[idx], ecs.MobComponent)
if m == nil {
continue
}
@ -43,7 +45,3 @@ func (mov Moveable) IsBlocked(c types.Coords) bool {
}
return false
}
func (mov Moveable) TypeOf() reflect.Type {
return reflect.TypeOf(mov)
}

View File

@ -83,12 +83,12 @@ func (ts *GameScreen) Render() {
func (ts *GameScreen) walk(state *gamestate.GameState, dx, dy int) {
controller := state.Controller
coords := controller.GetComponent(state.Player, types.Coords{}.TypeOf()).(types.Coords)
coords := controller.GetComponent(state.Player, ecs.CoordsComponent).(types.Coords)
newCoords := types.Coords{coords.X + dx, coords.Y + dy}
movable := controller.GetComponent(state.Player, movement.Moveable{}.TypeOf()).(movement.Moveable)
movable := controller.GetComponent(state.Player, ecs.MoveableComponent).(movement.Moveable)
if !movable.IsBlocked(newCoords) {
controller.UpdateComponent(state.Player, types.Coords{}.TypeOf(), newCoords)
controller.UpdateComponent(state.Player, ecs.CoordsComponent, newCoords)
}
state.Redraw <- struct{}{}

View File

@ -29,7 +29,9 @@ func (ts *TitleScreen) Exit() {
blt.Clear()
}
func (ts *TitleScreen) Render() {
blt.PrintExt(0, 0, ts.mw.W, ts.mw.H, 15, logo)
blt.PrintExt(0, 2, ts.mw.W, ts.mw.H, blt.TK_ALIGN_CENTER, logo)
blt.PrintExt(0, 19, ts.mw.W, ts.mw.H, blt.TK_ALIGN_CENTER, menu)
blt.PrintExt(0, 35, ts.mw.W, ts.mw.H, 3, credits)
}
var logo = `
@ -45,8 +47,9 @@ var logo = `
;k. .Ox Ok..'.,l ;Kk:;dk cKl lX: dKc,;oc kx kk OO dKl;lk: .0O
l; ,o .kK0KKK; :Ok; c; l: .oxc. x: Ol xl .dk: .o
`
var menu = `
Alchemyst (c) 2011-2014 thefish <thefish@zaar.be>
@ -55,9 +58,9 @@ Alchemyst (c) 2011-2014 thefish <thefish@zaar.be>
[color=green]L[/color]oad saved game
Read [color=green]h[/color]elp file
Highest [color=green]S[/color]cores
`
var credits = `
Roguebasin Libtcod Tutorial (c) 2010-2011, Jotaf Henriques
Brogue 1.3 (c) 2010 Brian Walker
Madness (c) 2010 hmp <humpolec@gmail.com>

View File

@ -2,8 +2,8 @@ package types
import (
"github.com/gammazero/deque"
"lab.zaar.be/thefish/alchemyst-go/engine/ecs"
"lab.zaar.be/thefish/alchemyst-go/util"
"reflect"
)
import blt "lab.zaar.be/thefish/bearlibterminal"
@ -106,6 +106,6 @@ func FillColorRing(colorValue uint8, minGlow, maxGlow, step int) *cdeque {
return c
}
func (app Appearance) TypeOf() reflect.Type {
return reflect.TypeOf(app)
func (app Appearance) Type() string {
return ecs.AppearanceComponent
}

View File

@ -1,16 +1,16 @@
package types
import (
"lab.zaar.be/thefish/alchemyst-go/engine/ecs"
"math"
"reflect"
)
type Coords struct {
X, Y int
}
func (сс Coords) TypeOf() reflect.Type {
return reflect.TypeOf(сс)
func (сс Coords) Type() string {
return ecs.CoordsComponent
}
func (c *Coords) Get() (int, int) {

View File

@ -13,7 +13,7 @@ func ReadKey() (string, int) {
}
var key = blt.Read()
var pressed = ""
var isModifier, _ = util.InArray(key, modifiers)
var isModifier, _ = util.IntInSlice(key, modifiers)
if !isModifier {
pressed = Scancodemap[key]
@ -38,5 +38,4 @@ func ReadKeyCode() int {
return blt.TK_NONE
}
return blt.Read()
}

View File

@ -3,6 +3,7 @@ package mainwindow
import (
"errors"
"fmt"
"lab.zaar.be/thefish/alchemyst-go/engine/ecs"
"lab.zaar.be/thefish/alchemyst-go/engine/fov"
"lab.zaar.be/thefish/alchemyst-go/engine/fov/precomputed_shade"
"lab.zaar.be/thefish/alchemyst-go/engine/gamestate"
@ -94,7 +95,7 @@ func (vp *ViewPort) Listen(state gamestate.GameState) {
func (vp *ViewPort) Render(state *gamestate.GameState) {
playerCoords := state.Controller.GetComponent(state.Player, types.Coords{}.TypeOf()).(types.Coords)
playerCoords := state.Controller.GetComponent(state.Player, ecs.CoordsComponent).(types.Coords)
vp.Move(state, playerCoords)

View File

@ -4,6 +4,18 @@ import (
"reflect"
)
func IntInSlice(needle int, haystack[]int) (exists bool, index int) {
exists = false
index = -1
for i := 0; i < len(haystack); i++ {
if haystack[i] == needle {
return true, i
}
}
return exists, index
}
//left here for historical reasons
func InArray(val interface{}, array interface{}) (exists bool, index int) {
exists = false
index = -1
@ -21,4 +33,4 @@ func InArray(val interface{}, array interface{}) (exists bool, index int) {
}
}
return
}
}