From 085b1078d4b805f5f50a7606be65b7a42604c236 Mon Sep 17 00:00:00 2001 From: gmzar <gmzar@mindfire.games> Date: Wed, 17 Jul 2019 20:05:05 -0700 Subject: [PATCH] Converted to use entity interfaces --- entity/entity.go | 73 +++++++++++++++++++++++++++++++++++--------- interfaces/entity.go | 17 +++++++++++ main.go | 7 +++-- mapping/gamemap.go | 46 ++++++++++++++-------------- render.go | 14 ++++----- 5 files changed, 110 insertions(+), 47 deletions(-) create mode 100644 interfaces/entity.go diff --git a/entity/entity.go b/entity/entity.go index 0a11974..7001eeb 100644 --- a/entity/entity.go +++ b/entity/entity.go @@ -1,25 +1,70 @@ package entity import ( + "steel/interfaces" + "github.com/kettek/goro" ) + // Entity is a type that represents an active entity in the world. type Entity struct { - X, Y int - Rune rune - Style goro.Style + x, y int + rune rune + style goro.Style } + +// NewEntity returns a pointer to a newly created Entity. +func NewEntity(x int, y int, r rune, s goro.Style) interfaces.Entity { + return &Entity{ + x: x, + y: y, + rune: r, + style: s, + } +} + // Move moves the entity by a given amount. func (e *Entity) Move(x, y int) { - e.X += x - e.Y += y + e.x += x + e.y += y +} + +// X returns the entity's X value. +func (e *Entity) X() int { + return e.x +} + +// SetX sets the entity's X value +func (e *Entity) SetX(x int) { + e.x = x +} + +// Y returns the entity's Y value. +func (e *Entity) Y() int { + return e.y +} + +// SetY sets the entity's Y value +func (e *Entity) SetY(y int) { + e.y = y +} + +// Rune returns the entity's rune. +func (e *Entity) Rune() rune { + return e.rune +} + +// SetRune sets the entity's rune. +func (e *Entity) SetRune(r rune) { + e.rune = r +} + +// Style returns the entity's style. +func (e *Entity) Style() goro.Style { + return e.style +} + +// SetStyle sets the entity's style. +func (e *Entity) SetStyle(s goro.Style) { + e.style = s } -// NewEntity returns a pointer to a newly created Entity. -func NewEntity(x int, y int, r rune, s goro.Style) *Entity { - return &Entity{ - X: x, - Y: y, - Rune: r, - Style: s, - } -} \ No newline at end of file diff --git a/interfaces/entity.go b/interfaces/entity.go new file mode 100644 index 0000000..b6afac4 --- /dev/null +++ b/interfaces/entity.go @@ -0,0 +1,17 @@ +package interfaces + +import ( + "github.com/kettek/goro" +) + +type Entity interface { + X() int + SetX(int) + Y() int + SetY(int) + Rune() rune + SetRune(rune) + Style() goro.Style + SetStyle(goro.Style) + Move(int, int) +} diff --git a/main.go b/main.go index 542b046..36c4e22 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "log" "steel/entity" + "steel/interfaces" "steel/mapping" "github.com/kettek/goro" @@ -40,7 +41,7 @@ func main() { player := entity.NewEntity(screen.Columns/2, screen.Rows/2+5, '@', goro.Style{Foreground: goro.ColorWhite}) npc := entity.NewEntity(screen.Columns/2-5, screen.Rows/2, '@', goro.Style{Foreground: goro.ColorYellow}) - entities := []*entity.Entity{ + entities := []interfaces.Entity{ player, npc, } @@ -59,7 +60,7 @@ func main() { for { if fovRecompute { - RecomputeFov(fovMap, player.X, player.Y, fovRadius, fov.Light{}) + RecomputeFov(fovMap, player.X(), player.Y(), fovRadius, fov.Light{}) } // Draw screen. @@ -74,7 +75,7 @@ func main() { case goro.EventKey: switch action := handleKeyEvent(event).(type) { case ActionMove: - if !gameMap.IsBlocked(player.X+action.X, player.Y+action.Y) { + if !gameMap.IsBlocked(player.X()+action.X, player.Y()+action.Y) { player.Move(action.X, action.Y) fovRecompute = true } diff --git a/mapping/gamemap.go b/mapping/gamemap.go index 0a3d108..0500dba 100644 --- a/mapping/gamemap.go +++ b/mapping/gamemap.go @@ -3,13 +3,13 @@ package mapping import ( "github.com/kettek/goro" - "steel/entity" + "steel/interfaces" ) // GameMap is our map data type. type GameMap struct { Width, Height int - Tiles [][]Tile + Tiles [][]Tile } // Initialize initializes a GameMap's Tiles to match its Width and Height. It also sets up some coordinates to block movement and sight. @@ -20,15 +20,15 @@ func (g *GameMap) Initialize() { g.Tiles[x] = make([]Tile, g.Height) for y := range g.Tiles[x] { g.Tiles[x][y] = Tile{ - BlockSight: true, - BlockMovement: true, + BlockSight: true, + BlockMovement: true, } } - } + } } // MakeMap creates a new randomized map. This is built according to the passed arguments. -func (g *GameMap) MakeMap(maxRooms, roomMinSize, roomMaxSize int, player *entity.Entity) { +func (g *GameMap) MakeMap(maxRooms, roomMinSize, roomMaxSize int, player interfaces.Entity) { var rooms []*Rect for r := 0; r < maxRooms; r++ { @@ -40,7 +40,7 @@ func (g *GameMap) MakeMap(maxRooms, roomMinSize, roomMaxSize int, player *entity y := goro.Random.Intn(g.Height - height - 1) // Create a Rect according to our generated sizes. room := NewRect(x, y, width, height) - + // Iterate through our existing rooms to check for intersection with our new room. intersects := false for _, otherRoom := range rooms { @@ -54,22 +54,22 @@ func (g *GameMap) MakeMap(maxRooms, roomMinSize, roomMaxSize int, player *entity g.CreateRoom(room) roomCenterX, roomCenterY := room.Center() - // Always place the player in the center of the first room. - if len(rooms) == 0 { - player.X = roomCenterX - player.Y = roomCenterY - } else { - prevCenterX, prevCenterY := rooms[len(rooms)-1].Center() - - // Flip a coin if we should tunnel horizontally or vertically first. - if goro.Random.Intn(1) == 1 { - g.CreateHTunnel(prevCenterX, roomCenterX, prevCenterY) - g.CreateVTunnel(prevCenterY, roomCenterY, roomCenterX) + // Always place the player in the center of the first room. + if len(rooms) == 0 { + player.SetX(roomCenterX) + player.SetY(roomCenterY) } else { - g.CreateVTunnel(prevCenterY, roomCenterY, prevCenterX) - g.CreateHTunnel(prevCenterX, roomCenterX, roomCenterY) + prevCenterX, prevCenterY := rooms[len(rooms)-1].Center() + + // Flip a coin if we should tunnel horizontally or vertically first. + if goro.Random.Intn(1) == 1 { + g.CreateHTunnel(prevCenterX, roomCenterX, prevCenterY) + g.CreateVTunnel(prevCenterY, roomCenterY, roomCenterX) + } else { + g.CreateVTunnel(prevCenterY, roomCenterY, prevCenterX) + g.CreateHTunnel(prevCenterX, roomCenterX, roomCenterY) + } } - } // Append our new room to our rooms list. rooms = append(rooms, room) } @@ -96,7 +96,7 @@ func (g *GameMap) CreateHTunnel(x1, x2, y int) { } } -// CreateVTunnel creates a vertical tunnel from y1 to/from y2 starting at x. +// CreateVTunnel creates a vertical tunnel from y1 to/from y2 starting at x. func (g *GameMap) CreateVTunnel(y1, y2, x int) { for y := goro.MinInt(y1, y2); y <= goro.MaxInt(y1, y2); y++ { if g.InBounds(x, y) { @@ -115,7 +115,7 @@ func (g *GameMap) IsBlocked(x, y int) bool { } // InBounds returns if the given coordinates are within the map's bounds. -func (g *GameMap) InBounds (x, y int) bool { +func (g *GameMap) InBounds(x, y int) bool { if x < 0 || x >= g.Width || y < 0 || y >= g.Height { return false } diff --git a/render.go b/render.go index b7277fd..7431fa6 100644 --- a/render.go +++ b/render.go @@ -4,12 +4,12 @@ import ( "github.com/kettek/goro" "github.com/kettek/goro/fov" - "steel/entity" + "steel/interfaces" "steel/mapping" ) // DrawAll draws all entities and the gameMap to the screen and flushes it. -func DrawAll(screen *goro.Screen, entities []*entity.Entity, gameMap mapping.GameMap, fovMap fov.Map, fovRecompute bool, colors map[string]goro.Color) { +func DrawAll(screen *goro.Screen, entities []interfaces.Entity, gameMap mapping.GameMap, fovMap fov.Map, fovRecompute bool, colors map[string]goro.Color) { if fovRecompute { // Draw all the riles in the game map. for x, column := range gameMap.Tiles { @@ -41,18 +41,18 @@ func DrawAll(screen *goro.Screen, entities []*entity.Entity, gameMap mapping.Gam } // ClearAll clears all entities from the screen. -func ClearAll(screen *goro.Screen, entities []*entity.Entity) { +func ClearAll(screen *goro.Screen, entities []interfaces.Entity) { for _, entity := range entities { ClearEntity(screen, entity) } } // DrawEntity draws a given entity to the screen. -func DrawEntity(screen *goro.Screen, e *entity.Entity) { - screen.DrawRune(e.X, e.Y, e.Rune, e.Style) +func DrawEntity(screen *goro.Screen, e interfaces.Entity) { + screen.DrawRune(e.X(), e.Y(), e.Rune(), e.Style()) } // ClearEntity clears a given entity from the screen. -func ClearEntity(screen *goro.Screen, e *entity.Entity) { - screen.SetRune(e.X, e.Y, ' ') +func ClearEntity(screen *goro.Screen, e interfaces.Entity) { + screen.SetRune(e.X(), e.Y(), ' ') }