diff --git a/cmd/game/main.go b/cmd/game/main.go index 5a612b0..85aa656 100644 --- a/cmd/game/main.go +++ b/cmd/game/main.go @@ -165,10 +165,10 @@ func main() { //fixme set up (load / generate) player - move to game / enter or title / exit player := controller.CreateEntity([]ecs.Component{}) - controller.AddComponent(player, &types.Appearance{ - Glyph: &types.PlainGlyphHolder{"@"}, + controller.AddComponent(player, types.Appearance{ + Glyph: types.PlainGlyphHolder{"@"}, ColorSet: types.TileColorSet{ - Fg: &types.PlainColorHolder{255, 255, 255, 255}, + Fg: types.PlainColorHolder{255, 255, 255, 255}, }, }) diff --git a/engine/ecs/component.go b/engine/ecs/component.go index f8c6119..856691b 100644 --- a/engine/ecs/component.go +++ b/engine/ecs/component.go @@ -2,19 +2,33 @@ package ecs // ECS system by jcerise, github.com/jcerise/gogue +const AmmoComponent = "ammo" const AppearanceComponent = "appearance" +const ArmorComponent = "armor" +const ArmsComponent = "arms" +const BackpackComponent = "backpack" +const CarriedComponent = "carried" +const ConsumableComponent = "consumable" const CoordsComponent = "coords" const MobComponent = "mob" const MoveableComponent = "movable" -const CarriedComponent = "carried" +const NamedComponent = "named" +const RangedComponent = "ranged" const UsableComponent = "usable" const WearableComponent = "usable" -const ArmsComponent = "arms" -const RangedComponent = "ranged" -const AmmoComponent = "ammo" -const ArmorComponent = "armor" -const BackpackComponent = "backpack" type Component interface { Type() string -} \ No newline at end of file +} + +type Named struct { + Name string +} + +func (n Named) Type() string { + return NamedComponent +} + +func (n Named) GetName() string { + return n.Name +} diff --git a/engine/ecs/system.go b/engine/ecs/system.go index 410dcb5..b8fbba0 100644 --- a/engine/ecs/system.go +++ b/engine/ecs/system.go @@ -3,6 +3,7 @@ package ecs // ECS system by jcerise, github.com/jcerise/gogue const MobRenderSystem = "mobrender" +const TerrainRenderSystem = "terrainrender" type System interface { Process() diff --git a/engine/ecs/systems/mob_render_system.go b/engine/ecs/systems/mob_render_system.go index 00df355..198f58f 100644 --- a/engine/ecs/systems/mob_render_system.go +++ b/engine/ecs/systems/mob_render_system.go @@ -7,27 +7,34 @@ import ( ) type MobRenderSystem struct { - EntityController *ecs.Controller - Layer *mainwindow.Layer + Controller *ecs.Controller + Layer *mainwindow.Layer + Viewport *mainwindow.ViewPort } func (mrs MobRenderSystem) Process(){ - for e := range mrs.EntityController.GetEntities() { - if mrs.EntityController.HasComponent(e, ecs.CoordsComponent) && - mrs.EntityController.HasComponent(e, ecs.AppearanceComponent) { + for e := range mrs.Controller.GetEntities() { + if mrs.Controller.HasComponent(e, ecs.CoordsComponent) && + mrs.Controller.HasComponent(e, ecs.AppearanceComponent) { - pos := mrs.EntityController.GetComponent(e, ecs.CoordsComponent).(types.Coords) - appearance := mrs.EntityController.GetComponent(e, ecs.AppearanceComponent).(types.Appearance) + pos := mrs.Controller.GetComponent(e, ecs.CoordsComponent).(types.Coords) + appearance := mrs.Controller.GetComponent(e, ecs.AppearanceComponent).(types.Appearance) //fixme + // if vp.Rect.InBounds(pos) { // Clear the cell this entity occupies, so it is the only glyph drawn there - for i := 0; i <= 2; i++ { - mrs.Layer.ClearArea(pos.X, pos.Y,1,1) + + //for i := 0; i <= 2; i++ { + //mrs.Layer.ClearArea(pos.X, pos.Y,1,1) //WHY?! //gogue.ClearArea(pos.X, pos.Y, 1, 1, i) - } + //} + //fixme - mrs.Layer.WithRawColor(appearance.ColorSet.Fg.GetColor()).Put(pos.X, pos.Y, appearance.Glyph) + 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()) //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 new file mode 100644 index 0000000..78edfbf --- /dev/null +++ b/engine/ecs/systems/terrain_render_system.go @@ -0,0 +1,65 @@ +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/types" + "lab.zaar.be/thefish/alchemyst-go/ui/mainwindow" +) + +type TerrainRenderSystem struct { + Viewport mainwindow.ViewPort + Level gamemap.Level +} + +func (trs TerrainRenderSystem) Process() { + 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 + } +} + +func (trs TerrainRenderSystem) Type() string { + return ecs.TerrainRenderSystem +} \ No newline at end of file diff --git a/engine/gamemap/mapgens/common.go b/engine/gamemap/mapgens/common.go index 3585e9e..6410aca 100644 --- a/engine/gamemap/mapgens/common.go +++ b/engine/gamemap/mapgens/common.go @@ -5,6 +5,7 @@ import ( "lab.zaar.be/thefish/alchemyst-go/engine/gamemap" "lab.zaar.be/thefish/alchemyst-go/engine/types" "lab.zaar.be/thefish/alchemyst-go/util" + "lab.zaar.be/thefish/alchemyst-go/util/appctx" ) //fixme move to config @@ -101,6 +102,15 @@ func GetRandomRoomList(ctx context.Context, rng *util.RNG, l *gamemap.Level, max return rooms } +func BlitToLevel (ctx context.Context, l *gamemap.Level, rooms[]gamemap.Room) { + for _, room := range rooms { + err := room.BlitToLevel(ctx, l) + if err != nil { + appctx.Logger(ctx).Err(err) + } + } +} + //delaunay helper funcs func MedianStraight(rng *util.RNG, l *gamemap.Level, rooms []gamemap.Room, centers []types.Coords, edge types.Edge) { //find connected rooms diff --git a/engine/gamemap/mapgens/default.go b/engine/gamemap/mapgens/default.go index 1ec07ff..9845486 100644 --- a/engine/gamemap/mapgens/default.go +++ b/engine/gamemap/mapgens/default.go @@ -1,7 +1,6 @@ package mapgens import ( - "fmt" "lab.zaar.be/thefish/alchemyst-go/engine/gamemap" "lab.zaar.be/thefish/alchemyst-go/util" "lab.zaar.be/thefish/alchemyst-go/util/appctx" @@ -20,12 +19,7 @@ func DefaultGen(ctx appctx.ClientCtx,l *gamemap.Level) (*gamemap.Level, []gamema rooms := GetRandomRoomList(ctx, rng, l, maxrooms, minRoomSize, maxRoomSize) - for _, room := range rooms { - err := room.BlitToLevel(l) - if err != nil { - fmt.Printf("err: %v", err) - } - } + BlitToLevel(ctx, l, rooms) for idx, room := range rooms { if idx > 0 { diff --git a/engine/gamemap/mapgens/delaunay_mst.go b/engine/gamemap/mapgens/delaunay_mst.go index b5622a0..624687c 100644 --- a/engine/gamemap/mapgens/delaunay_mst.go +++ b/engine/gamemap/mapgens/delaunay_mst.go @@ -2,7 +2,6 @@ package mapgens import ( "context" - "fmt" "lab.zaar.be/thefish/alchemyst-go/engine/gamemap" "lab.zaar.be/thefish/alchemyst-go/engine/types" "lab.zaar.be/thefish/alchemyst-go/util" @@ -22,12 +21,7 @@ func DelaunayMstGen(ctx context.Context, l *gamemap.Level) (*gamemap.Level, []ga rooms := GetRandomRoomList(ctx, rng, l, maxrooms, minRoomSize, maxRoomSize) - for _, room := range rooms { - err := room.BlitToLevel(l) - if err != nil { - fmt.Printf("err: %v", err) - } - } + BlitToLevel(ctx, l, rooms) centers := make([]types.Coords, 0) for _, room := range rooms { diff --git a/engine/gamemap/mapgens/delaunay_mst_ext.go b/engine/gamemap/mapgens/delaunay_mst_ext.go index f997f92..fd7fe0c 100644 --- a/engine/gamemap/mapgens/delaunay_mst_ext.go +++ b/engine/gamemap/mapgens/delaunay_mst_ext.go @@ -1,7 +1,6 @@ package mapgens import ( - "fmt" "lab.zaar.be/thefish/alchemyst-go/engine/gamemap" "lab.zaar.be/thefish/alchemyst-go/engine/types" "lab.zaar.be/thefish/alchemyst-go/util" @@ -21,13 +20,7 @@ func DelaunayMstExtGen(ctx appctx.ClientCtx, l *gamemap.Level) (*gamemap.Level, } rooms := GetRandomRoomList(ctx, rng, l, maxrooms, minRoomSize, maxRoomSize) - - for _, room := range rooms { - err := room.BlitToLevel(l) - if err != nil { - fmt.Printf("err: %v", err) - } - } + BlitToLevel(ctx, l, rooms) centers := make([]types.Coords, 0) for _, room := range rooms { diff --git a/engine/gamemap/mapgens/delaunay_pure.go b/engine/gamemap/mapgens/delaunay_pure.go index e6eb652..df1ee84 100644 --- a/engine/gamemap/mapgens/delaunay_pure.go +++ b/engine/gamemap/mapgens/delaunay_pure.go @@ -2,7 +2,6 @@ package mapgens import ( "context" - "fmt" "lab.zaar.be/thefish/alchemyst-go/engine/gamemap" "lab.zaar.be/thefish/alchemyst-go/engine/types" "lab.zaar.be/thefish/alchemyst-go/util" @@ -21,13 +20,7 @@ func DelaunayPureGen(ctx context.Context, l *gamemap.Level) (*gamemap.Level, []g } rooms := GetRandomRoomList(ctx, rng, l, maxrooms, minRoomSize, maxRoomSize) - - for _, room := range rooms { - err := room.BlitToLevel(l) - if err != nil { - fmt.Printf("err: %v", err) - } - } + BlitToLevel(ctx, l, rooms) centers := make([]types.Coords, 0) for _, room := range rooms { diff --git a/engine/gamemap/room.go b/engine/gamemap/room.go index c7384da..9111455 100644 --- a/engine/gamemap/room.go +++ b/engine/gamemap/room.go @@ -1,12 +1,14 @@ package gamemap import ( + "context" "errors" "fmt" "lab.zaar.be/thefish/alchemyst-go/engine/items" "lab.zaar.be/thefish/alchemyst-go/engine/mob" "lab.zaar.be/thefish/alchemyst-go/engine/types" "lab.zaar.be/thefish/alchemyst-go/util" + "lab.zaar.be/thefish/alchemyst-go/util/appctx" "strings" ) @@ -31,7 +33,7 @@ func (r *Room) Put (x, y int, tileFunc interface{}) { } } -func (room *Room) BlitToLevel(l *Level) error { +func (room *Room) BlitToLevel(ctx context.Context, l *Level) error { //copy tiles like this: //https://stackoverflow.com/questions/21011023/copy-pointer-values-a-b-in-golang @@ -49,7 +51,7 @@ func (room *Room) BlitToLevel(l *Level) error { //check underlying tile if underlyingTile == nil || underlyingTile.Name != "Wall" { - fmt.Println("Invalid blit!") + appctx.Logger(ctx).Warn().Msg("Invalid blit!") return invalidBlit } l.Put(mapCoords.X, mapCoords.Y, tileFunc) diff --git a/engine/items/carried.go b/engine/items/carried.go index cf00f35..7e8c9aa 100644 --- a/engine/items/carried.go +++ b/engine/items/carried.go @@ -85,4 +85,16 @@ func (c Carried) GetMass(what ecs.Entity) int { } func (c *Carried) GetBulk(what ecs.Entity) int { return c.Bulk -} \ No newline at end of file +} + +func FindCarriedOnTile(coords types.Coords) []ecs.Entity { + carrieds := Controller.GetEntitiesWithComponent(ecs.CarriedComponent) + result := make([]ecs.Entity, 0) + for _, ent := range carrieds { + car := Controller.GetComponent(ent, ecs.CarriedComponent) + if car == coords { + result = append(result, ent) + } + } + return result +} diff --git a/engine/items/consumable.go b/engine/items/consumable.go new file mode 100644 index 0000000..613e65d --- /dev/null +++ b/engine/items/consumable.go @@ -0,0 +1,10 @@ +package items +import "lab.zaar.be/thefish/alchemyst-go/engine/ecs" + +type Consumable struct { + +} + +func (c Consumable) Type() string { + return ecs.ConsumableComponent +} \ No newline at end of file diff --git a/engine/items/itemprops/damage.go b/engine/items/itemprops/damage.go index 82d8cc1..dbab7e2 100644 --- a/engine/items/itemprops/damage.go +++ b/engine/items/itemprops/damage.go @@ -3,5 +3,5 @@ package itemprops type DamageProfile struct { Pierce int Bash int - Cleave int + Crush int } diff --git a/engine/mob/mob.go b/engine/mob/mob.go index cd4df82..9bfa2b2 100644 --- a/engine/mob/mob.go +++ b/engine/mob/mob.go @@ -6,8 +6,9 @@ import ( ) type Mob struct { - *types.Appearance + types.Appearance types.Coords + ecs.Named BlocksPass bool } diff --git a/engine/screens/game.go b/engine/screens/game.go index f3b970a..187710f 100644 --- a/engine/screens/game.go +++ b/engine/screens/game.go @@ -19,7 +19,7 @@ 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{EntityController: ts.controller} + renderMobs := systems.MobRenderSystem{Controller: ts.controller, Layer: ts.mw.GetLayer("base"), Viewport: ts.vp} ts.controller.AddSystem(renderMobs, 1) return ts } @@ -82,6 +82,5 @@ func (ts *GameScreen) HandleInput(input string) { func (ts *GameScreen) Render() { 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 4f81e24..e9eb6a4 100644 --- a/ui/mainwindow/viewport.go +++ b/ui/mainwindow/viewport.go @@ -2,7 +2,6 @@ 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" @@ -40,7 +39,7 @@ func NewViewPort(x, y, w, h int, layer *Layer) *ViewPort { func (vp *ViewPort) Close() { vp.animateTiles.Stop() - vp.animateTiles = nil //free pointer to ticker + vp.animateTiles = nil //zero pointer to ticker } func (vp *ViewPort) Move(state *gamestate.GameState, newCoords types.Coords) { @@ -124,6 +123,7 @@ func (vp *ViewPort) Render(state *gamestate.GameState) { } } } + /* //mobs pc, err := vp.ToVPCoords(playerCoords) _ = pc @@ -134,6 +134,7 @@ func (vp *ViewPort) Render(state *gamestate.GameState) { //mw.GetLayer("base").WithColor("white").Put(42, 10, "B") //mw.GetLayer("overlay").WithColor("white").Put(59, 10, "O") } + */ //redraw = true redraw = false