From a195e335eb55f31dc270bb8fd9e7f5d4d20bb9c9 Mon Sep 17 00:00:00 2001 From: "anton.gurov" Date: Tue, 5 Nov 2019 17:55:38 +0300 Subject: [PATCH] working prototype with ecs --- cmd/game/main.go | 30 ++++++++++++++++---- engine/gamestate/gamestate.go | 5 +++- engine/mob/mob.go | 18 ------------ engine/mob/movement/movement.go | 50 +++++++++++++++++++++++++++++++++ engine/mob/player.go | 5 ---- engine/screens/game.go | 33 ++++++++++++++++------ ui/mainwindow/viewport.go | 31 ++++++++++---------- 7 files changed, 120 insertions(+), 52 deletions(-) create mode 100644 engine/mob/movement/movement.go delete mode 100644 engine/mob/player.go diff --git a/cmd/game/main.go b/cmd/game/main.go index d18fb8d..baebb51 100644 --- a/cmd/game/main.go +++ b/cmd/game/main.go @@ -9,6 +9,7 @@ import ( "lab.zaar.be/thefish/alchemyst-go/engine/gamemap/mapgens" "lab.zaar.be/thefish/alchemyst-go/engine/gamestate" "lab.zaar.be/thefish/alchemyst-go/engine/mob" + "lab.zaar.be/thefish/alchemyst-go/engine/mob/movement" "lab.zaar.be/thefish/alchemyst-go/engine/screens" "lab.zaar.be/thefish/alchemyst-go/engine/types" "lab.zaar.be/thefish/alchemyst-go/ui" @@ -56,18 +57,29 @@ func main() { var logLevels = map[string]zerolog.Level{"debug": zerolog.DebugLevel, "info": zerolog.InfoLevel, "warn": zerolog.WarnLevel} var logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}).Level(logLevels[config.Verbosity]) + // set up context mainCtx := util.NewClientContext(config, &logger) + + //set up main window mw := mainwindow.Init(mainCtx) defer mw.Close() setupLayers(mw) - //fixme + //set up input decoder + go decodeInput(mainCtx, mw.GetLayer("base")) + + + //fixme set up (load / generate) level level, rooms := mapgens.DefaultGen(gamemap.NewLevel(mainCtx, "test", 1)) State.Level = level - vp := mainwindow.NewViewPort(30, 0, 70, 47, mw.GetLayer("base")) + //Set up viewport + vp := mainwindow.NewViewPort(30, 0, 70, 47, mw.GetLayer("base")) + go vp.Listen(State) + + //Set up Screen Manager screenMgr := types.NewScreenManager(mainCtx) screenMgr.AddScreen("title", &screens.TitleScreen{}) screenMgr.AddScreen("game", screens.NewGameScreen(mw, &State, vp)) @@ -92,15 +104,21 @@ func main() { //vp.PlayerCoords = player.Coords //vp.Render(&State) - go decodeInput(mainCtx, mw.GetLayer("base")) - go vp.Listen(State) + //set up controller controller := ecs.NewController() controller.MapComponentClass("coords", types.Coords{}) controller.MapComponentClass("appearance", types.Appearance{}) controller.MapComponentClass("mob", mob.Mob{}) + controller.MapComponentClass("moveable", movement.Moveable{}) + moveable := movement.Moveable{ + Controller: controller, + Level: level, + } + + //fixme set up (load / generate) player player := controller.CreateEntity([]ecs.Component{}) controller.AddComponent(player, &types.Appearance{ @@ -111,13 +129,15 @@ func main() { }) controller.AddComponent(player, rooms[0].Center) //implicit Coords + controller.AddComponent(player, moveable) render := systems.MobRenderSystem{EntityController: controller} controller.AddSystem(render, 1) - level.Player = player + State.Player = player + State.Controller = controller //but every call to bearlibterminal must be wrapped to closure and passed to mainfunc var exit = false diff --git a/engine/gamestate/gamestate.go b/engine/gamestate/gamestate.go index 4f75a2d..aec40fc 100644 --- a/engine/gamestate/gamestate.go +++ b/engine/gamestate/gamestate.go @@ -1,6 +1,7 @@ package gamestate import ( + "lab.zaar.be/thefish/alchemyst-go/engine/ecs" "lab.zaar.be/thefish/alchemyst-go/engine/gamemap" ) @@ -10,8 +11,10 @@ type GameState struct { Input chan string RawInput chan int FovRecompute chan struct{} - Redraw chan struct{} + Redraw chan struct{} + Player ecs.Entity Level *gamemap.Level + Controller *ecs.Controller } // do runs f on the main thread. diff --git a/engine/mob/mob.go b/engine/mob/mob.go index ba70a70..ec9892f 100644 --- a/engine/mob/mob.go +++ b/engine/mob/mob.go @@ -1,8 +1,6 @@ package mob import ( - "fmt" - "lab.zaar.be/thefish/alchemyst-go/engine/gamemap" "lab.zaar.be/thefish/alchemyst-go/engine/types" "reflect" ) @@ -13,26 +11,10 @@ type Mob struct { BlocksPass bool } -func (m *Mob) Walk(level *gamemap.Level, dx, dy int) { - newCoords := types.Coords{m.X + dx, m.Y + dy} - if level.GetTile(newCoords).BlocksPass { - return - } - //fixme - //if level.Objects.At(newCoords).HasComponent("block_pass") { - // - //} - fmt.Printf("new coords: %d, %d\n", m.Coords.X, m.Coords.Y) -} - func (m *Mob) Render() { } -func (m *Mob) MoveToCoords(c types.Coords) { - -} - func (mob Mob) TypeOf() reflect.Type { return reflect.TypeOf(mob) } \ No newline at end of file diff --git a/engine/mob/movement/movement.go b/engine/mob/movement/movement.go new file mode 100644 index 0000000..9662857 --- /dev/null +++ b/engine/mob/movement/movement.go @@ -0,0 +1,50 @@ +package movement + +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/mob" + "lab.zaar.be/thefish/alchemyst-go/engine/types" + "reflect" +) + +type Moveable struct { + Controller *ecs.Controller + Level *gamemap.Level +} + + +func (mov Moveable) Walk() { + +} + +func (mov Moveable) IsBlocked(c types.Coords) bool { + if mov.Level.GetTile(c).BlocksPass == true { + return true + } + list := mov.Controller.GetEntitiesWithComponent(mob.Mob{}.TypeOf()) + for idx, _ := range list { + coords := mov.Controller.GetComponent(list[idx], types.Coords{}.TypeOf()) + if coords == nil { + continue + } + coords = coords.(types.Coords) + if coords != c { + continue + } + m := mov.Controller.GetComponent(list[idx], mob.Mob{}.TypeOf()) + if m == nil { + continue + } + if m.(mob.Mob).BlocksPass { + return true + } + } + fmt.Printf("\nCoords %v do not block pass!", c) + return false +} + +func (mov Moveable) TypeOf() reflect.Type { + return reflect.TypeOf(mov) +} diff --git a/engine/mob/player.go b/engine/mob/player.go deleted file mode 100644 index c1b8920..0000000 --- a/engine/mob/player.go +++ /dev/null @@ -1,5 +0,0 @@ -package mob - -type Player struct { - Mob -} diff --git a/engine/screens/game.go b/engine/screens/game.go index b8c6886..0a6b285 100644 --- a/engine/screens/game.go +++ b/engine/screens/game.go @@ -2,6 +2,8 @@ package screens import ( "lab.zaar.be/thefish/alchemyst-go/engine/gamestate" + "lab.zaar.be/thefish/alchemyst-go/engine/mob/movement" + "lab.zaar.be/thefish/alchemyst-go/engine/types" "lab.zaar.be/thefish/alchemyst-go/ui/mainwindow" ) @@ -21,28 +23,28 @@ func (ts *GameScreen) HandleInput(input string) { //ts.state.Do(func(){ switch input { case "Up", "k", "8": - ts.state.Player.Walk(ts.state.Level, 0, -1) + ts.walk(ts.state, 0, -1) break case "Down", "j", "2": - ts.state.Player.Walk(ts.state.Level,0, 1) + ts.walk(ts.state,0, 1) break case "Left", "h", "4": - ts.state.Player.Walk(ts.state.Level,-1, 0) + ts.walk(ts.state,-1, 0) break case "Right", "l", "6": - ts.state.Player.Walk(ts.state.Level,1, 0) + ts.walk(ts.state,1, 0) break case "y", "7": - ts.state.Player.Walk(ts.state.Level,-1, -1) + ts.walk(ts.state,-1, -1) break case "u", "9": - ts.state.Player.Walk(ts.state.Level,1, -1) + ts.walk(ts.state,1, -1) break case "b", "1": - ts.state.Player.Walk(ts.state.Level,-1, 1) + ts.walk(ts.state,-1, 1) break case "n", "3": - ts.state.Player.Walk(ts.state.Level,1, 1) + ts.walk(ts.state,1, 1) break default: ts.mw.GetLayer("base").ClearArea(0, 3, 40, 1) @@ -56,3 +58,18 @@ func (ts *GameScreen) Exit() {} func (ts *GameScreen) Render() { ts.vp.Render(ts.state) } + + +func (ts *GameScreen) walk(state *gamestate.GameState, dx, dy int) { + controller := state.Controller + coords := controller.GetComponent(state.Player, types.Coords{}.TypeOf()).(types.Coords) + newCoords := types.Coords{coords.X + dx, coords.Y + dy} + movable := controller.GetComponent(state.Player, movement.Moveable{}.TypeOf()).(movement.Moveable) + + if !movable.IsBlocked(newCoords) { + controller.UpdateComponent(state.Player, types.Coords{}.TypeOf(), newCoords) + } + + state.Redraw <- struct{}{} + state.FovRecompute <- struct{}{} +} \ No newline at end of file diff --git a/ui/mainwindow/viewport.go b/ui/mainwindow/viewport.go index afe4ab7..e43ad92 100644 --- a/ui/mainwindow/viewport.go +++ b/ui/mainwindow/viewport.go @@ -6,7 +6,6 @@ import ( "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/mob" "lab.zaar.be/thefish/alchemyst-go/engine/types" "time" ) @@ -18,7 +17,6 @@ type ViewPort struct { cameraCoords types.Coords layer *Layer Fov fov.Fov - Player mob.Player TorchRadius int animateTiles *time.Ticker } @@ -44,12 +42,10 @@ func (vp *ViewPort) Close() { vp.animateTiles = nil //free pointer to ticker } -func (vp *ViewPort) Move(state *gamestate.GameState) { +func (vp *ViewPort) Move(state *gamestate.GameState, newCoords types.Coords) { - c := &state.Level.Player.HasComponent(types.Coords{}).Coords - - x := c.X - vp.Rect.W/2 - y := c.Y - vp.Rect.H/2 + x := newCoords.X - vp.Rect.W/2 + y := newCoords.Y - vp.Rect.H/2 if x < 0 { x = 0 @@ -98,16 +94,22 @@ func (vp *ViewPort) Listen(state gamestate.GameState) { func (vp *ViewPort) Render(state *gamestate.GameState) { - vp.Move(state) + playerCoords := state.Controller.GetComponent(state.Player, types.Coords{}.TypeOf()).(types.Coords) + + vp.Move(state, playerCoords) if fovRecompute { vp.layer.ClearRect(vp.Rect) - fovRecompute = true + fovRecompute = false redraw = true - vp.Fov.ComputeFov(state.Level, state.Level.Player.Coords, vp.TorchRadius) + vp.Fov.ComputeFov(state.Level, playerCoords, vp.TorchRadius) } - //if redraw { + vp.layer.ClearArea(0, 7, 40, 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++ { @@ -122,7 +124,7 @@ func (vp *ViewPort) Render(state *gamestate.GameState) { } } //mobs - pc, err := vp.ToVPCoords(state.Level.Player.Coords) + pc, err := vp.ToVPCoords(playerCoords) _ = pc if err != nil { fmt.Println("error on getting player position") @@ -133,8 +135,7 @@ func (vp *ViewPort) Render(state *gamestate.GameState) { } //redraw = true - //redraw = false - - //} + redraw = false + } }