From 0d8649498ce0897dc18239ca8425f82c1fda959f Mon Sep 17 00:00:00 2001 From: thefish Date: Sat, 16 Nov 2019 04:31:57 +0300 Subject: [PATCH] terrain animation broken, mobs rendering right --- cmd/game/main.go | 1 - engine/ecs/controller.go | 7 ++ engine/ecs/systems/mob_render_system.go | 24 +++- engine/ecs/systems/terrain_render_system.go | 115 +++++++++++++------- engine/screens/game.go | 17 ++- ui/mainwindow/viewport.go | 103 ++---------------- 6 files changed, 128 insertions(+), 139 deletions(-) diff --git a/cmd/game/main.go b/cmd/game/main.go index 85aa656..373201e 100644 --- a/cmd/game/main.go +++ b/cmd/game/main.go @@ -81,7 +81,6 @@ func main() { //Set up viewport vp := mainwindow.NewViewPort(sidebarWidth, 0, (mw.W - sidebarWidth), (mw.H - 0), mw.GetLayer("base")) - go vp.Listen(State) //set up controller diff --git a/engine/ecs/controller.go b/engine/ecs/controller.go index cd340af..d736cec 100644 --- a/engine/ecs/controller.go +++ b/engine/ecs/controller.go @@ -210,6 +210,13 @@ func (c *Controller) AddSystem(system System, priority int) { } } +func (c *Controller) GetSystem(systemType string) System { + if system, ok := c.systems[systemType]; ok { + return system + } + return nil +} + // 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). diff --git a/engine/ecs/systems/mob_render_system.go b/engine/ecs/systems/mob_render_system.go index 198f58f..5b05b3d 100644 --- a/engine/ecs/systems/mob_render_system.go +++ b/engine/ecs/systems/mob_render_system.go @@ -1,7 +1,9 @@ package systems import ( + "fmt" "lab.zaar.be/thefish/alchemyst-go/engine/ecs" + "lab.zaar.be/thefish/alchemyst-go/engine/gamemap" "lab.zaar.be/thefish/alchemyst-go/engine/types" "lab.zaar.be/thefish/alchemyst-go/ui/mainwindow" ) @@ -10,6 +12,7 @@ type MobRenderSystem struct { Controller *ecs.Controller Layer *mainwindow.Layer Viewport *mainwindow.ViewPort + *gamemap.Level } func (mrs MobRenderSystem) Process(){ @@ -30,8 +33,25 @@ func (mrs MobRenderSystem) Process(){ //} //fixme - mrs.Layer.WithRawColor(appearance.ColorSet.Fg.GetColor()).Put(pos.X, pos.Y, appearance.Glyph.GetGlyph()) - mrs.Layer.WithRawColor(appearance.ColorSet.Fg.GetColor()).Put(pos.X, pos.Y, appearance.Glyph.GetGlyph()) + //for y := 0; y < mrs.Viewport.H; y++ { + // for x := 0; x < mrs.Viewport.W; x++ { + // mapCoords := types.Coords{mrs.Viewport.CameraCoords.X + x, mrs.Viewport.CameraCoords.Y + y} + // if mrs.Level.InBounds(mapCoords) { + // mrs.Layer.WithRawColor(appearance.ColorSet.Fg.GetColor()).Put( + // x+mrs.Viewport.X, + // y+mrs.Viewport.Y, + // appearance.Glyph.GetGlyph(), + // ) + // } + // } + //} + + vpc, err := mrs.Viewport.ToVPCoords(pos) + if err != nil { + fmt.Printf("Err: " , err) + } + + mrs.Layer.WithRawColor(appearance.ColorSet.Fg.GetColor()).Put(vpc.X, vpc.Y, appearance.Glyph.GetGlyph()) //gogue.PrintGlyph(pos.X, pos.Y, appearance.Glyph, "", appearance.Layer) //} diff --git a/engine/ecs/systems/terrain_render_system.go b/engine/ecs/systems/terrain_render_system.go index 78edfbf..2a267a0 100644 --- a/engine/ecs/systems/terrain_render_system.go +++ b/engine/ecs/systems/terrain_render_system.go @@ -2,64 +2,105 @@ package systems import ( "lab.zaar.be/thefish/alchemyst-go/engine/ecs" - "lab.zaar.be/thefish/alchemyst-go/engine/gamemap" + "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" "lab.zaar.be/thefish/alchemyst-go/engine/types" "lab.zaar.be/thefish/alchemyst-go/ui/mainwindow" + "time" ) type TerrainRenderSystem struct { - Viewport mainwindow.ViewPort - Level gamemap.Level + Viewport *mainwindow.ViewPort + state *gamestate.GameState + layer *mainwindow.Layer + animateTiles *time.Ticker + fov fov.Fov + TorchRadius int + redraw bool + fovRecompute bool +} + +func NewTerrainRenderSystem( + state *gamestate.GameState, + vp *mainwindow.ViewPort, + layer *mainwindow.Layer, +) TerrainRenderSystem { + + trs := TerrainRenderSystem{ + Viewport:vp, + layer: layer, + state: state, + redraw: true, + fovRecompute: true, + } + + computedFov := precomputed_shade.NewPrecomputedShade(15) + computedFov.Init() + trs.TorchRadius = 12 //fixme move to sight component + + trs.animateTiles = time.NewTicker(time.Second / 12) + + trs.fov = computedFov + + 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: + trs.fovRecompute = true + case <-trs.state.Redraw: + trs.redraw = true + case <-trs.animateTiles.C: + trs.redraw = true + } + } } func (trs TerrainRenderSystem) Process() { - playerCoords := state.Controller.GetComponent(state.Player, ecs.CoordsComponent).(types.Coords) + playerCoords := trs.state.Controller.GetComponent(trs.state.Player, ecs.CoordsComponent).(types.Coords) - vp.Move(state, playerCoords) + trs.Viewport.Move(trs.state, playerCoords) - if fovRecompute { - vp.layer.ClearRect(vp.Rect) - fovRecompute = false - redraw = true - vp.Fov.ComputeFov(state.Level, playerCoords, vp.TorchRadius) + if trs.fovRecompute { + trs.layer.ClearRect(trs.Viewport.Rect) + trs.fovRecompute = false + trs.redraw = true + trs.fov.ComputeFov(trs.state.Level, playerCoords, trs.TorchRadius) } - //vp.layer.ClearArea(0, 7, 20, 1) - //vp.layer.Print(0,7, fmt.Sprintf("pcds: %v", playerCoords)) - - - if redraw { + if trs.redraw { //terrain - for y := 0; y < vp.H; y++ { - for x := 0; x < vp.W; x++ { - mapCoords := types.Coords{vp.cameraCoords.X + x, vp.cameraCoords.Y + y} + 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 state.Level.InBounds(mapCoords) { - tile := state.Level.GetTile(mapCoords) + if trs.state.Level.InBounds(mapCoords) { + tile := trs.state.Level.GetTile(mapCoords) if tile.Explored || tile.Visible { - vp.layer.PutToBase(x+vp.X, y+vp.Y, tile.GetChar(), tile.GetRawColor(), tile.GetRawBgColor()) + trs.layer.PutToBase( + x+trs.Viewport.X, + y+trs.Viewport.Y, + tile.GetChar(), + tile.GetRawColor(), + tile.GetRawBgColor(), + ) } } } } - /* - //mobs - pc, err := vp.ToVPCoords(playerCoords) - _ = pc - if err != nil { - fmt.Println("error on getting player position") - } else { - vp.layer.WithColor("white").Put(pc.X+vp.X, pc.Y+vp.Y, "@") - //mw.GetLayer("base").WithColor("white").Put(42, 10, "B") - //mw.GetLayer("overlay").WithColor("white").Put(59, 10, "O") - } - */ - - //redraw = true - redraw = false + trs.redraw = false } } -func (trs TerrainRenderSystem) Type() string { +func (trs TerrainRenderSystem) SystemType() string { return ecs.TerrainRenderSystem } \ No newline at end of file diff --git a/engine/screens/game.go b/engine/screens/game.go index 187710f..05da2ed 100644 --- a/engine/screens/game.go +++ b/engine/screens/game.go @@ -19,8 +19,17 @@ type GameScreen struct { func NewGameScreen(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} - renderMobs := systems.MobRenderSystem{Controller: ts.controller, Layer: ts.mw.GetLayer("base"), Viewport: ts.vp} - ts.controller.AddSystem(renderMobs, 1) + renderMobs := systems.MobRenderSystem{ + Controller: ts.controller, + Layer: ts.mw.GetLayer("base"), + Viewport: ts.vp, + Level: state.Level, + } + ts.controller.AddSystem(renderMobs, 10) + renderTerrain := systems.NewTerrainRenderSystem(state, viewPort, ts.mw.GetLayer("base")) + go renderTerrain.Listen() + ts.controller.AddSystem(renderTerrain, 5) + return ts } @@ -31,6 +40,8 @@ func (ts *GameScreen) Enter() { Print(1, ts.mw.H-2, "Press [color=white]?[/color] for help") } func (ts *GameScreen) Exit() { + //trs := ts.controller.GetSystem(ecs.TerrainRenderSystem) + //trs.(systems.TerrainRenderSystem).Close() ts.mw.GetLayer("overlay").ClearArea(0, ts.mw.H-3, 30, 3) //remove what we dont need } @@ -81,6 +92,6 @@ func (ts *GameScreen) HandleInput(input string) { } func (ts *GameScreen) Render() { - ts.vp.Render(ts.state) + //ts.vp.Render(ts.state) ts.controller.Process([]string{}) } \ No newline at end of file diff --git a/ui/mainwindow/viewport.go b/ui/mainwindow/viewport.go index e9eb6a4..9570540 100644 --- a/ui/mainwindow/viewport.go +++ b/ui/mainwindow/viewport.go @@ -1,47 +1,23 @@ package mainwindow import ( - "errors" - "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" + "fmt" "lab.zaar.be/thefish/alchemyst-go/engine/gamestate" "lab.zaar.be/thefish/alchemyst-go/engine/types" - "time" ) -var NotInViewError = errors.New("not in ViewPort") - type ViewPort struct { types.Rect - cameraCoords types.Coords - layer *Layer - Fov fov.Fov - TorchRadius int - animateTiles *time.Ticker + CameraCoords types.Coords } func NewViewPort(x, y, w, h int, layer *Layer) *ViewPort { - - computedFov := precomputed_shade.NewPrecomputedShade(15) - computedFov.Init() vp := ViewPort{ Rect: types.Rect{x, y, w, h}, - layer: layer, - Fov: computedFov, } - - vp.TorchRadius = 12 - vp.animateTiles = time.NewTicker(time.Second / 12) - return &vp } -func (vp *ViewPort) Close() { - vp.animateTiles.Stop() - vp.animateTiles = nil //zero pointer to ticker -} - func (vp *ViewPort) Move(state *gamestate.GameState, newCoords types.Coords) { x := newCoords.X - vp.Rect.W/2 @@ -59,85 +35,20 @@ func (vp *ViewPort) Move(state *gamestate.GameState, newCoords types.Coords) { if y > state.Level.H-vp.H - 1 { y = state.Level.H - vp.H } - if x != vp.cameraCoords.X || y != vp.cameraCoords.Y { + if x != vp.CameraCoords.X || y != vp.CameraCoords.Y { state.FovRecompute <- struct{}{} } - vp.cameraCoords.X = x - vp.cameraCoords.Y = y + vp.CameraCoords.X = x + vp.CameraCoords.Y = y } func (vp *ViewPort) ToVPCoords(c types.Coords) (newCoords types.Coords, err error) { //coords on map to coords on vp - x, y := c.X-vp.cameraCoords.X, c.Y-vp.cameraCoords.Y + x, y := c.X-vp.CameraCoords.X, c.Y-vp.CameraCoords.Y if x < 0 || y < 0 || x > vp.W || y > vp.H { - return types.Coords{-1, -1}, NotInViewError + return types.Coords{-1, -1}, fmt.Errorf("Not in viewport: {%d, %d}", x, y) } return types.Coords{x, y}, nil } -var redraw = true -var fovRecompute = true - -func (vp *ViewPort) Listen(state gamestate.GameState) { - for { - select { - case <-state.FovRecompute: - fovRecompute = true - case <-state.Redraw: - redraw = true - case <-vp.animateTiles.C: - redraw = true - } - } -} - -func (vp *ViewPort) Render(state *gamestate.GameState) { - - playerCoords := state.Controller.GetComponent(state.Player, ecs.CoordsComponent).(types.Coords) - - vp.Move(state, playerCoords) - - if fovRecompute { - vp.layer.ClearRect(vp.Rect) - fovRecompute = false - redraw = true - vp.Fov.ComputeFov(state.Level, playerCoords, vp.TorchRadius) - } - - //vp.layer.ClearArea(0, 7, 20, 1) - //vp.layer.Print(0,7, fmt.Sprintf("pcds: %v", playerCoords)) - - - if redraw { - //terrain - for y := 0; y < vp.H; y++ { - for x := 0; x < vp.W; x++ { - mapCoords := types.Coords{vp.cameraCoords.X + x, vp.cameraCoords.Y + y} - - if state.Level.InBounds(mapCoords) { - tile := state.Level.GetTile(mapCoords) - if tile.Explored || tile.Visible { - vp.layer.PutToBase(x+vp.X, y+vp.Y, tile.GetChar(), tile.GetRawColor(), tile.GetRawBgColor()) - } - } - } - } - /* - //mobs - pc, err := vp.ToVPCoords(playerCoords) - _ = pc - if err != nil { - fmt.Println("error on getting player position") - } else { - vp.layer.WithColor("white").Put(pc.X+vp.X, pc.Y+vp.Y, "@") - //mw.GetLayer("base").WithColor("white").Put(42, 10, "B") - //mw.GetLayer("overlay").WithColor("white").Put(59, 10, "O") - } - */ - - //redraw = true - redraw = false - } - -}