Converted to use entity interfaces

This commit is contained in:
Joel M. Southall 2019-07-17 20:05:05 -07:00
parent eea1fa9388
commit 085b1078d4
5 changed files with 110 additions and 47 deletions

View File

@ -1,25 +1,70 @@
package entity package entity
import ( import (
"steel/interfaces"
"github.com/kettek/goro" "github.com/kettek/goro"
) )
// Entity is a type that represents an active entity in the world. // Entity is a type that represents an active entity in the world.
type Entity struct { type Entity struct {
X, Y int x, y int
Rune rune rune rune
Style goro.Style 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. // Move moves the entity by a given amount.
func (e *Entity) Move(x, y int) { func (e *Entity) Move(x, y int) {
e.X += x e.x += x
e.Y += y 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,
}
}

17
interfaces/entity.go Normal file
View File

@ -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)
}

View File

@ -3,6 +3,7 @@ package main
import ( import (
"log" "log"
"steel/entity" "steel/entity"
"steel/interfaces"
"steel/mapping" "steel/mapping"
"github.com/kettek/goro" "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}) 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}) npc := entity.NewEntity(screen.Columns/2-5, screen.Rows/2, '@', goro.Style{Foreground: goro.ColorYellow})
entities := []*entity.Entity{ entities := []interfaces.Entity{
player, player,
npc, npc,
} }
@ -59,7 +60,7 @@ func main() {
for { for {
if fovRecompute { if fovRecompute {
RecomputeFov(fovMap, player.X, player.Y, fovRadius, fov.Light{}) RecomputeFov(fovMap, player.X(), player.Y(), fovRadius, fov.Light{})
} }
// Draw screen. // Draw screen.
@ -74,7 +75,7 @@ func main() {
case goro.EventKey: case goro.EventKey:
switch action := handleKeyEvent(event).(type) { switch action := handleKeyEvent(event).(type) {
case ActionMove: 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) player.Move(action.X, action.Y)
fovRecompute = true fovRecompute = true
} }

View File

@ -3,13 +3,13 @@ package mapping
import ( import (
"github.com/kettek/goro" "github.com/kettek/goro"
"steel/entity" "steel/interfaces"
) )
// GameMap is our map data type. // GameMap is our map data type.
type GameMap struct { type GameMap struct {
Width, Height int 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. // 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) g.Tiles[x] = make([]Tile, g.Height)
for y := range g.Tiles[x] { for y := range g.Tiles[x] {
g.Tiles[x][y] = Tile{ g.Tiles[x][y] = Tile{
BlockSight: true, BlockSight: true,
BlockMovement: true, BlockMovement: true,
} }
} }
} }
} }
// MakeMap creates a new randomized map. This is built according to the passed arguments. // 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 var rooms []*Rect
for r := 0; r < maxRooms; r++ { 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) y := goro.Random.Intn(g.Height - height - 1)
// Create a Rect according to our generated sizes. // Create a Rect according to our generated sizes.
room := NewRect(x, y, width, height) room := NewRect(x, y, width, height)
// Iterate through our existing rooms to check for intersection with our new room. // Iterate through our existing rooms to check for intersection with our new room.
intersects := false intersects := false
for _, otherRoom := range rooms { for _, otherRoom := range rooms {
@ -54,22 +54,22 @@ func (g *GameMap) MakeMap(maxRooms, roomMinSize, roomMaxSize int, player *entity
g.CreateRoom(room) g.CreateRoom(room)
roomCenterX, roomCenterY := room.Center() roomCenterX, roomCenterY := room.Center()
// Always place the player in the center of the first room. // Always place the player in the center of the first room.
if len(rooms) == 0 { if len(rooms) == 0 {
player.X = roomCenterX player.SetX(roomCenterX)
player.Y = roomCenterY player.SetY(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)
} else { } else {
g.CreateVTunnel(prevCenterY, roomCenterY, prevCenterX) prevCenterX, prevCenterY := rooms[len(rooms)-1].Center()
g.CreateHTunnel(prevCenterX, roomCenterX, roomCenterY)
// 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. // Append our new room to our rooms list.
rooms = append(rooms, room) 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) { func (g *GameMap) CreateVTunnel(y1, y2, x int) {
for y := goro.MinInt(y1, y2); y <= goro.MaxInt(y1, y2); y++ { for y := goro.MinInt(y1, y2); y <= goro.MaxInt(y1, y2); y++ {
if g.InBounds(x, 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. // 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 { if x < 0 || x >= g.Width || y < 0 || y >= g.Height {
return false return false
} }

View File

@ -4,12 +4,12 @@ import (
"github.com/kettek/goro" "github.com/kettek/goro"
"github.com/kettek/goro/fov" "github.com/kettek/goro/fov"
"steel/entity" "steel/interfaces"
"steel/mapping" "steel/mapping"
) )
// DrawAll draws all entities and the gameMap to the screen and flushes it. // 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 { if fovRecompute {
// Draw all the riles in the game map. // Draw all the riles in the game map.
for x, column := range gameMap.Tiles { 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. // 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 { for _, entity := range entities {
ClearEntity(screen, entity) ClearEntity(screen, entity)
} }
} }
// DrawEntity draws a given entity to the screen. // DrawEntity draws a given entity to the screen.
func DrawEntity(screen *goro.Screen, e *entity.Entity) { func DrawEntity(screen *goro.Screen, e interfaces.Entity) {
screen.DrawRune(e.X, e.Y, e.Rune, e.Style) screen.DrawRune(e.X(), e.Y(), e.Rune(), e.Style())
} }
// ClearEntity clears a given entity from the screen. // ClearEntity clears a given entity from the screen.
func ClearEntity(screen *goro.Screen, e *entity.Entity) { func ClearEntity(screen *goro.Screen, e interfaces.Entity) {
screen.SetRune(e.X, e.Y, ' ') screen.SetRune(e.X(), e.Y(), ' ')
} }