rendering items, pick up, iventory re-make in progress to aloow item drop/wear/whatever

This commit is contained in:
thefish 2019-11-17 02:09:41 +03:00
parent 685dfeeeb1
commit 0a6c642dc2
12 changed files with 349 additions and 207 deletions

View File

@ -85,7 +85,7 @@ func main() {
//set up controller //set up controller
controller := ecs.NewController() controller := ecs.NewController(mainCtx)
controller.MapComponentClass(ecs.CoordsComponent, types.Coords{}) controller.MapComponentClass(ecs.CoordsComponent, types.Coords{})
controller.MapComponentClass(ecs.AppearanceComponent, types.Appearance{}) controller.MapComponentClass(ecs.AppearanceComponent, types.Appearance{})
@ -93,16 +93,21 @@ func main() {
controller.MapComponentClass(ecs.MoveableComponent, movement.Moveable{}) controller.MapComponentClass(ecs.MoveableComponent, movement.Moveable{})
controller.MapComponentClass(ecs.CarriedComponent, movement.Moveable{}) controller.MapComponentClass(ecs.CarriedComponent, movement.Moveable{})
controller.MapComponentClass(ecs.UsableComponent, movement.Moveable{}) controller.MapComponentClass(ecs.UsableComponent, movement.Moveable{})
controller.MapComponentClass(ecs.BackpackComponent, items.Backpack{})
moveable := movement.Moveable{ moveable := movement.Moveable{
Controller: controller, Controller: controller,
Level: level, Level: level,
} }
items.Init(controller)
bp := items.Backpack{MaxMass:100, MaxBulk:100}
//Set up Screen Manager //Set up Screen Manager
screenMgr := types.NewScreenManager(mainCtx) screenMgr := types.NewScreenManager(mainCtx)
screenMgr.AddScreen("title", screens.NewTitleScreen(mw, screenMgr)) screenMgr.AddScreen("title", screens.NewTitleScreen(mw, screenMgr))
screenMgr.AddScreen("game", screens.NewGameScreen(mw, &State, vp, controller, screenMgr)) screenMgr.AddScreen("game", screens.NewGameScreen(mainCtx, mw, &State, vp, controller, screenMgr))
screenMgr.AddScreen("help", screens.NewMenuScreen( screenMgr.AddScreen("help", screens.NewMenuScreen(
mw, mw,
screenMgr, screenMgr,
@ -128,25 +133,20 @@ func main() {
}).MakeList(), }).MakeList(),
) )
screenMgr.AddScreen("inventory", screens.NewMenuScreen( screenMgr.AddScreen("inventory", screens.InventoryScreen{
mw, MenuScreen: screens.NewMenuScreen(
screenMgr, mw,
"Inventory", screenMgr,
"Items in your backpack:", "Inventory",
//"[color=yellow]Note[/color]: Many of these are not implemented yet", "Items in your backpack:",
"", //"[color=yellow]Note[/color]: Many of these are not implemented yet",
types.NewCenteredRect(mw.Rect, 70, 25), "",
true, ). types.NewCenteredRect(mw.Rect, 70, 25),
SetBgColor("#ef305c70"). true, ).
SetFgColor("white"). SetBgColor("#ef305c70").
SetItems([]interface{}{ SetFgColor("white").
`"Fish-eye" crafty shaded glasses`, SetItems([]interface{}{}).MakeList()
"Xecutor's glowing visor", },
"Kitschy goggles of many pathways",
"Ring of inexistence",
"Orb of omniscience",
"Wand of amnesia",
}).MakeList(),
) )
screenMgr.AddScreen("devmenu", screens.NewDevmenuScreen( screenMgr.AddScreen("devmenu", screens.NewDevmenuScreen(
@ -174,7 +174,9 @@ func main() {
controller.AddComponent(player, rooms[0].Center) //implicit Coords controller.AddComponent(player, rooms[0].Center) //implicit Coords
controller.AddComponent(player, moveable) controller.AddComponent(player, moveable)
controller.AddComponent(player, bp)
//fixme adding items
potion := controller.CreateEntity([]ecs.Component{}) potion := controller.CreateEntity([]ecs.Component{})
controller.AddComponent(potion, types.Appearance{ controller.AddComponent(potion, types.Appearance{
Glyph: types.PlainGlyphHolder{"!"}, Glyph: types.PlainGlyphHolder{"!"},
@ -182,11 +184,24 @@ func main() {
Fg: types.PlainColorHolder{255, 55, 255, 222}, Fg: types.PlainColorHolder{255, 55, 255, 222},
}, },
}) })
controller.AddComponent(potion, rooms[1].Center) //implicit Coords controller.AddComponent(potion, rooms[0].Center) //implicit Coords
controller.AddComponent(potion, items.Carried{}) controller.AddComponent(potion, items.Carried{Mass:5, Bulk:3})
controller.AddComponent(potion, items.Usable{}) controller.AddComponent(potion, items.Usable{})
controller.AddComponent(potion, items.Consumable{}) controller.AddComponent(potion, items.Consumable{})
potion2 := controller.CreateEntity([]ecs.Component{})
controller.AddComponent(potion2, types.Appearance{
Glyph: types.PlainGlyphHolder{"!"},
ColorSet: types.TileColorSet{
Fg: types.PlainColorHolder{255, 222, 255, 55},
},
})
controller.AddComponent(potion2, rooms[1].Center) //implicit Coords
controller.AddComponent(potion2, items.Carried{Mass:5, Bulk:3})
controller.AddComponent(potion2, items.Usable{})
controller.AddComponent(potion2, items.Consumable{})
//fixme end setting up items
State.Player = player State.Player = player
State.Controller = controller State.Controller = controller

View File

@ -3,11 +3,13 @@ package ecs
// ECS system by jcerise, github.com/jcerise/gogue // ECS system by jcerise, github.com/jcerise/gogue
import ( import (
"fmt" "context"
"lab.zaar.be/thefish/alchemyst-go/util/appctx"
"sort" "sort"
) )
type Controller struct { type Controller struct {
ctx context.Context
systems map[string]System systems map[string]System
sortedSystems map[int][]System sortedSystems map[int][]System
priorityKeys []int priorityKeys []int
@ -21,8 +23,8 @@ type Controller struct {
} }
// NewController is a convenience/constructor method to properly initialize a new processor // NewController is a convenience/constructor method to properly initialize a new processor
func NewController() *Controller { func NewController(ctx context.Context) *Controller {
controller := Controller{} controller := Controller{ctx: ctx}
controller.systems = make(map[string]System) controller.systems = make(map[string]System)
controller.sortedSystems = make(map[int][]System) controller.sortedSystems = make(map[int][]System)
controller.priorityKeys = []int{} controller.priorityKeys = []int{}
@ -78,7 +80,7 @@ func (c *Controller) GetMappedComponentClass(componentName string) Component {
return c.componentMap[componentName] return c.componentMap[componentName]
} else { } else {
// TODO: Add better (read: actual) error handling here // TODO: Add better (read: actual) error handling here
fmt.Printf("Component[%s] not registered on Controller.\n", componentName) appctx.Logger(c.ctx).Warn().Msgf("Component[%s] not registered on Controller.\n", componentName)
return nil return nil
} }
} }
@ -206,7 +208,7 @@ func (c *Controller) AddSystem(system System, priority int) {
c.sortedSystems[priority] = append(c.sortedSystems[priority], system) c.sortedSystems[priority] = append(c.sortedSystems[priority], system)
sort.Ints(c.priorityKeys) sort.Ints(c.priorityKeys)
} else { } else {
fmt.Printf("A system of type %v was already added to the controller %v!", systemType, c) appctx.Logger(c.ctx).Warn().Msgf("A system of type %v was already added to the controller %v!", systemType, c)
} }
} }

View File

@ -2,8 +2,7 @@ package ecs
// ECS system by jcerise, github.com/jcerise/gogue // ECS system by jcerise, github.com/jcerise/gogue
const MobRenderSystem = "mobrender" const TerrainRenderSystem = "levelrender"
const TerrainRenderSystem = "terrainrender"
type System interface { type System interface {
Process() Process()

View File

@ -0,0 +1,160 @@
package systems
import (
"lab.zaar.be/thefish/alchemyst-go/engine/ecs"
"lab.zaar.be/thefish/alchemyst-go/engine/fov"
"lab.zaar.be/thefish/alchemyst-go/engine/gamestate"
"lab.zaar.be/thefish/alchemyst-go/engine/types"
"lab.zaar.be/thefish/alchemyst-go/ui/mainwindow"
"sort"
"time"
)
var fovRecompute = true
var redraw = false
type LevelRenderSystem struct {
Viewport *mainwindow.ViewPort
Controller *ecs.Controller
state *gamestate.GameState
layer *mainwindow.Layer
fov fov.Fov
animateTiles *time.Ticker
TorchRadius int
}
func NewLevelRenderSystem(
state *gamestate.GameState,
controller *ecs.Controller,
vp *mainwindow.ViewPort,
layer *mainwindow.Layer,
fov fov.Fov,
) LevelRenderSystem {
trs := LevelRenderSystem{
Viewport: vp,
Controller: controller,
layer: layer,
state: state,
fov: fov,
}
trs.TorchRadius = 12 //fixme move to sight component
trs.animateTiles = time.NewTicker(time.Second / 12)
return trs
}
//fixme add to screens/game Exit()
func (trs LevelRenderSystem) Close() {
trs.animateTiles.Stop()
trs.animateTiles = nil //zero pointer to ticker
}
func (trs LevelRenderSystem) Listen() {
for {
select {
case <-trs.state.FovRecompute:
fovRecompute = true
case <-trs.state.Redraw:
redraw = true
case <-trs.animateTiles.C:
redraw = true
}
}
}
type priorityRenderable struct {
types.Appearance
types.Coords
Priority int //with bigger are rendered last
}
type prioritySorter []priorityRenderable
func (a prioritySorter) Len() int { return len(a) }
func (a prioritySorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a prioritySorter) Less(i, j int) bool { return a[i].Priority < a[j].Priority }
func (trs LevelRenderSystem) Process() {
playerCoords := trs.state.Controller.GetComponent(trs.state.Player, ecs.CoordsComponent).(types.Coords)
trs.Viewport.Move(trs.state, playerCoords)
if fovRecompute {
trs.layer.ClearRect(trs.Viewport.Rect)
trs.fov.ComputeFov(trs.state.Level, playerCoords, trs.TorchRadius)
fovRecompute = false
redraw = true
}
if redraw {
//terrain
for y := 0; y < trs.Viewport.H; y++ {
for x := 0; x < trs.Viewport.W; x++ {
mapCoords := types.Coords{trs.Viewport.CameraCoords.X + x, trs.Viewport.CameraCoords.Y + y}
if trs.state.Level.InBounds(mapCoords) {
tile := trs.state.Level.GetTile(mapCoords)
if tile.Explored || tile.Visible {
trs.layer.PutToBase(
x+trs.Viewport.X,
y+trs.Viewport.Y,
tile.GetChar(),
tile.GetRawColor(),
tile.GetRawBgColor(),
)
}
}
}
}
//mobs
entToRender := make([]priorityRenderable, 0)
for e := range trs.Controller.GetEntities() {
if trs.Controller.HasComponent(e, ecs.CoordsComponent) &&
trs.Controller.HasComponent(e, ecs.AppearanceComponent) {
pos := trs.Controller.GetComponent(e, ecs.CoordsComponent).(types.Coords)
appearance := trs.Controller.GetComponent(e, ecs.AppearanceComponent).(types.Appearance)
//fixme fov check
if !trs.state.Level.GetTile(pos).Visible {
continue
}
vpc, err := trs.Viewport.ToVPCoords(pos)
if err != nil {
continue //we cant see it? no problem.
}
//Костыль для приоритета отрисовки
p := 0
if trs.Controller.HasComponent(e, ecs.CarriedComponent) {
p = 10
}
if trs.Controller.HasComponent(e, ecs.MoveableComponent) {
p = 100
}
entToRender = append(entToRender, priorityRenderable{
Appearance: appearance,
Coords: vpc,
Priority: p,
})
}
}
sort.Sort(prioritySorter(entToRender))
for _, ree := range entToRender {
trs.layer.WithRawColor(ree.Appearance.ColorSet.Fg.GetColor()).
Put(ree.X, ree.Y, ree.Appearance.Glyph.GetGlyph())
}
entToRender = nil
redraw = false
}
}
func (trs LevelRenderSystem) SystemType() string {
return ecs.TerrainRenderSystem
}

View File

@ -1,45 +0,0 @@
package systems
import (
"lab.zaar.be/thefish/alchemyst-go/engine/ecs"
"lab.zaar.be/thefish/alchemyst-go/engine/fov"
"lab.zaar.be/thefish/alchemyst-go/engine/gamemap"
"lab.zaar.be/thefish/alchemyst-go/engine/types"
"lab.zaar.be/thefish/alchemyst-go/ui/mainwindow"
)
type MobRenderSystem struct {
Controller *ecs.Controller
Layer *mainwindow.Layer
Viewport *mainwindow.ViewPort
Fov fov.Fov
*gamemap.Level
}
func (mrs MobRenderSystem) Process() {
//if redraw {
for e := range mrs.Controller.GetEntities() {
if mrs.Controller.HasComponent(e, ecs.CoordsComponent) &&
mrs.Controller.HasComponent(e, ecs.AppearanceComponent) {
pos := mrs.Controller.GetComponent(e, ecs.CoordsComponent).(types.Coords)
appearance := mrs.Controller.GetComponent(e, ecs.AppearanceComponent).(types.Appearance)
//fixme fov check
//if !mrs.Fov.IsInFov(pos) {
// continue
//}
vpc, err := mrs.Viewport.ToVPCoords(pos)
if err != nil {
continue //we cant see it? no problem.
}
mrs.Layer.WithRawColor(appearance.ColorSet.Fg.GetColor()).Put(vpc.X, vpc.Y, appearance.Glyph.GetGlyph())
}
}
//}
}
func (mrs MobRenderSystem) SystemType() string {
return ecs.MobRenderSystem
}

View File

@ -1,104 +0,0 @@
package systems
import (
"lab.zaar.be/thefish/alchemyst-go/engine/ecs"
"lab.zaar.be/thefish/alchemyst-go/engine/fov"
"lab.zaar.be/thefish/alchemyst-go/engine/gamestate"
"lab.zaar.be/thefish/alchemyst-go/engine/types"
"lab.zaar.be/thefish/alchemyst-go/ui/mainwindow"
"time"
)
var fovRecompute = true
var redraw = false
type TerrainRenderSystem struct {
Viewport *mainwindow.ViewPort
state *gamestate.GameState
layer *mainwindow.Layer
fov fov.Fov
animateTiles *time.Ticker
TorchRadius int
}
func NewTerrainRenderSystem(
state *gamestate.GameState,
vp *mainwindow.ViewPort,
layer *mainwindow.Layer,
fov fov.Fov,
) TerrainRenderSystem {
trs := TerrainRenderSystem{
Viewport:vp,
layer: layer,
state: state,
fov: fov,
}
trs.TorchRadius = 12 //fixme move to sight component
trs.animateTiles = time.NewTicker(time.Second / 12)
return trs
}
//fixme add to screens/game Exit()
func (trs TerrainRenderSystem) Close() {
trs.animateTiles.Stop()
trs.animateTiles = nil //zero pointer to ticker
}
func (trs TerrainRenderSystem) Listen() {
for {
select {
case <-trs.state.FovRecompute:
fovRecompute = true
case <-trs.state.Redraw:
redraw = true
case <-trs.animateTiles.C:
redraw = true
}
}
}
func (trs TerrainRenderSystem) Process() {
playerCoords := trs.state.Controller.GetComponent(trs.state.Player, ecs.CoordsComponent).(types.Coords)
trs.Viewport.Move(trs.state, playerCoords)
if fovRecompute {
trs.layer.ClearRect(trs.Viewport.Rect)
trs.fov.ComputeFov(trs.state.Level, playerCoords, trs.TorchRadius)
fovRecompute = false
redraw = true
}
if redraw {
//terrain
for y := 0; y < trs.Viewport.H; y++ {
for x := 0; x < trs.Viewport.W; x++ {
mapCoords := types.Coords{trs.Viewport.CameraCoords.X + x, trs.Viewport.CameraCoords.Y + y}
if trs.state.Level.InBounds(mapCoords) {
tile := trs.state.Level.GetTile(mapCoords)
if tile.Explored || tile.Visible {
trs.layer.PutToBase(
x+trs.Viewport.X,
y+trs.Viewport.Y,
tile.GetChar(),
tile.GetRawColor(),
tile.GetRawBgColor(),
)
}
}
}
}
redraw = false
}
}
func (trs TerrainRenderSystem) SystemType() string {
return ecs.TerrainRenderSystem
}

View File

@ -124,6 +124,7 @@ func (ps *precomputedShade) FindByCoords(c types.Coords) (int, *Cell, error) {
func (ps *precomputedShade) IsInFov(coords types.Coords) bool { func (ps *precomputedShade) IsInFov(coords types.Coords) bool {
rc := ps.fromLevelCoords(coords) rc := ps.fromLevelCoords(coords)
if rc.X == 0 && rc.Y ==0 {return true}
_, cell, err := ps.FindByCoords(rc) _, cell, err := ps.FindByCoords(rc)
if err != nil { if err != nil {
return false return false

View File

@ -30,4 +30,8 @@ func (b *Backpack) HasFreeSpace(Bulk, Mass int) bool {
return false return false
} }
return true return true
}
func (b *Backpack) GetItems() []ecs.Entity {
return b.items
} }

View File

@ -50,6 +50,8 @@ func (c Carried) Pickup(who, what ecs.Entity) {
//remove coords instead (does not exist on map anymore) //remove coords instead (does not exist on map anymore)
Controller.RemoveComponent(what, ecs.CoordsComponent) Controller.RemoveComponent(what, ecs.CoordsComponent)
bp.items = append(bp.items, what) bp.items = append(bp.items, what)
//fuck that, we need to update constantly
Controller.UpdateComponent(who, ecs.BackpackComponent, bp)
} }
func (c Carried) Drop(who, what ecs.Entity) { func (c Carried) Drop(who, what ecs.Entity) {
@ -87,11 +89,12 @@ func (c *Carried) GetBulk(what ecs.Entity) int {
return c.Bulk return c.Bulk
} }
func FindCarriedOnTile(coords types.Coords) []ecs.Entity { func FindCarriedUnder(who ecs.Entity) []ecs.Entity {
coords := Controller.GetComponent(who, ecs.CoordsComponent).(types.Coords)
carrieds := Controller.GetEntitiesWithComponent(ecs.CarriedComponent) carrieds := Controller.GetEntitiesWithComponent(ecs.CarriedComponent)
result := make([]ecs.Entity, 0) result := make([]ecs.Entity, 0)
for _, ent := range carrieds { for _, ent := range carrieds {
car := Controller.GetComponent(ent, ecs.CarriedComponent) car := Controller.GetComponent(ent, ecs.CoordsComponent)
if car == coords { if car == coords {
result = append(result, ent) result = append(result, ent)
} }

View File

@ -2,8 +2,8 @@ package items
import "lab.zaar.be/thefish/alchemyst-go/engine/ecs" import "lab.zaar.be/thefish/alchemyst-go/engine/ecs"
var Controller ecs.Controller var Controller *ecs.Controller
func Init(ctrl ecs.Controller) { func Init(ctrl *ecs.Controller) {
Controller = ctrl Controller = ctrl
} }

View File

@ -1,45 +1,47 @@
package screens package screens
import ( import (
"context"
"lab.zaar.be/thefish/alchemyst-go/engine/ecs" "lab.zaar.be/thefish/alchemyst-go/engine/ecs"
"lab.zaar.be/thefish/alchemyst-go/engine/ecs/systems" "lab.zaar.be/thefish/alchemyst-go/engine/ecs/systems"
"lab.zaar.be/thefish/alchemyst-go/engine/fov" "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/fov/precomputed_shade"
"lab.zaar.be/thefish/alchemyst-go/engine/gamestate" "lab.zaar.be/thefish/alchemyst-go/engine/gamestate"
"lab.zaar.be/thefish/alchemyst-go/engine/items"
"lab.zaar.be/thefish/alchemyst-go/engine/mob/movement" "lab.zaar.be/thefish/alchemyst-go/engine/mob/movement"
"lab.zaar.be/thefish/alchemyst-go/engine/types" "lab.zaar.be/thefish/alchemyst-go/engine/types"
"lab.zaar.be/thefish/alchemyst-go/ui/mainwindow" "lab.zaar.be/thefish/alchemyst-go/ui/mainwindow"
"lab.zaar.be/thefish/alchemyst-go/util/appctx"
) )
type GameScreen struct { type GameScreen struct {
ctx context.Context
mw *mainwindow.MainWindow mw *mainwindow.MainWindow
state *gamestate.GameState state *gamestate.GameState
vp *mainwindow.ViewPort vp *mainwindow.ViewPort
controller *ecs.Controller controller *ecs.Controller
scm *types.ScreenManager scm *types.ScreenManager
fov fov.Fov fov fov.Fov
} }
func NewGameScreen(mw *mainwindow.MainWindow, state *gamestate.GameState, viewPort *mainwindow.ViewPort, controller *ecs.Controller, scm *types.ScreenManager) *GameScreen { func NewGameScreen(ctx context.Context, mw *mainwindow.MainWindow, state *gamestate.GameState, viewPort *mainwindow.ViewPort, controller *ecs.Controller, scm *types.ScreenManager) *GameScreen {
ts := &GameScreen{mw: mw, state: state, vp: viewPort, controller: controller, scm: scm} ts := &GameScreen{
ctx: ctx,
mw: mw,
state: state,
vp: viewPort,
controller: controller,
scm: scm,
}
//fixme move this to fov system //fixme move this to fov system
computedFov := precomputed_shade.NewPrecomputedShade(15) computedFov := precomputed_shade.NewPrecomputedShade(15)
computedFov.Init() computedFov.Init()
ts.fov = computedFov ts.fov = computedFov
renderMobs := systems.MobRenderSystem{ renderLevel := systems.NewLevelRenderSystem(state, ts.controller, viewPort, ts.mw.GetLayer("base"), ts.fov)
Controller: ts.controller, go renderLevel.Listen()
Layer: ts.mw.GetLayer("base"), ts.controller.AddSystem(renderLevel, 50)
Viewport: ts.vp,
Level: state.Level,
Fov: ts.fov,
}
ts.controller.AddSystem(renderMobs, 10)
renderTerrain := systems.NewTerrainRenderSystem(state, viewPort, ts.mw.GetLayer("base"), ts.fov)
go renderTerrain.Listen()
ts.controller.AddSystem(renderTerrain, 5)
return ts return ts
} }
@ -50,8 +52,8 @@ func (ts *GameScreen) Enter() {
Print(1, ts.mw.H-2, "Press [color=white]?[/color] for help") Print(1, ts.mw.H-2, "Press [color=white]?[/color] for help")
} }
func (ts *GameScreen) Exit() { func (ts *GameScreen) Exit() {
//trs := ts.controller.GetSystem(ecs.TerrainRenderSystem) //trs := ts.controller.GetSystem(ecs.LevelRenderSystem)
//trs.(systems.TerrainRenderSystem).Close() //trs.(systems.LevelRenderSystem).Close()
ts.mw.GetLayer("overlay").ClearArea(0, ts.mw.H-3, 30, 3) ts.mw.GetLayer("overlay").ClearArea(0, ts.mw.H-3, 30, 3)
//remove what we dont need //remove what we dont need
} }
@ -90,6 +92,23 @@ func (ts *GameScreen) HandleInput(input string) {
ts.scm.SetScreenByName("devmenu") ts.scm.SetScreenByName("devmenu")
break break
case "g":
//get list of carriables on tile
carrieds := items.FindCarriedUnder(ts.state.Player)
if len(carrieds) == 0 {
break
} //do nothing
//select if there is more than 1
if len(carrieds) > 1 {
appctx.Logger(ts.ctx).Warn().Msg("Passing item list to inventory not implemented yet")
} else {
//call pickup in selected
cc := items.Controller.GetComponent(carrieds[0], ecs.CarriedComponent).(items.Carried)
items.Carried.Pickup(cc, ts.state.Player, carrieds[0])
}
break;
case "i": case "i":
ts.scm.SetScreenByName("inventory") ts.scm.SetScreenByName("inventory")
break break
@ -104,4 +123,4 @@ func (ts *GameScreen) HandleInput(input string) {
func (ts *GameScreen) Render() { func (ts *GameScreen) Render() {
//ts.vp.Render(ts.state) //ts.vp.Render(ts.state)
ts.controller.Process([]string{}) ts.controller.Process([]string{})
} }

View File

@ -1,11 +1,99 @@
package screens package screens
type InventoryScreen struct { import (
"lab.zaar.be/thefish/alchemyst-go/engine/ecs"
"lab.zaar.be/thefish/alchemyst-go/engine/types"
"strings"
)
type InventoryScreen struct {
*MenuScreen
items []ecs.Entity
cursor int
offset int
pageSize int
} }
func (ts *InventoryScreen) UseEcs() bool {return true} func (is *InventoryScreen) MakeInverntory() *InventoryScreen {
func (ts *InventoryScreen) Enter() {} is.drawFunc = is.InventoryRender
func (ts *InventoryScreen) HandleInput(input string) {} is.inputFunc = is.HandleInput
func (ts *InventoryScreen) Exit() {} return is
func (ts *InventoryScreen) Render() {} }
func (is *InventoryScreen) SetItems(items []ecs.Entity) *InventoryScreen {
is.items = items
return is
}
func (is *InventoryScreen) HandleInput(input string) {
switch input {
case "PageUp":
is.offset = is.offset - 1
if is.offset < 0 {
is.offset = 0
}
break
case "PageDown":
is.offset = is.offset + 1
if is.offset > len(is.items)-1 {
is.offset = len(is.items) - 1
}
break
case "enter":
//select current under cursor
break;
case "a","b","c","d","e","f","g","h","i","j","k","l":
//selct by letter
break;
case "Escape":
fallthrough
case "Space":
is.scm.SetScreen(is.scm.PreviousScreen)
break
}
}
func (is *InventoryScreen) InventoryRender() {
menuLayer := is.mw.GetLayer("menu")
menuLayer.ClearRect(is.Rect)
bgLayer := is.mw.GetLayer("menubg")
bgLayer.ClearRect(is.Rect)
bgLayer.WithColor(is.bgColor).NewWindow(is.Rect).Splash()
menuLayer.WithColor(is.fgColor).NewWindow(is.Rect).DoubleBordered(is.title)
menuLayer.Print(is.X+(is.W/2)-7, is.Y+is.H-1, "╡"+"[color=green]Space[/color] to close"+"╞")
footerHeight := 0
if is.footer != "" {
_, footerHeight = menuLayer.PrintInside(is.Rect, is.footer, 9)
footerHeight = footerHeight + 2
}
_, headerHeight := menuLayer.PrintInside(is.Rect, is.header, blt.TK_ALIGN_LEFT)
itemField := types.Rect{is.X, is.Y + headerHeight + 1, is.W, is.H - headerHeight - footerHeight}
_ = itemField
var ilw, ilh int
if (len(is.items) > 0) {
//fixme itemfield object, scroller, inputhandler, current selected item
menuItems := make([]string, 0)
for i := is.offset; i < len(is.items); i++ {
if string(is.items[i].(string)) != "" {
menuItems = append(menuItems, is.items[i].(string))
}
}
ilw, ilh = menuLayer.PrintInside(itemField, strings.Join(menuItems, "\n"), blt.TK_ALIGN_LEFT)
}
if ilh < len(is.items) {
is.drawScrollBar(menuLayer, itemField)
}
if ilw > itemField.W-4 {
fmt.Printf("Excess width of item names found! Need h-scroll of certain names")
}
}
//func (ms *InventoryScreen) UseEcs() bool {return true}
//func (ms *InventoryScreen) Enter() {}
//func (ms *InventoryScreen) Exit() {}
//func (ms *InventoryScreen) Render() {}