Move some things around

This commit is contained in:
Miroslav Vasilev 2024-05-06 21:19:08 +03:00
parent 5d1416bb07
commit a56e3d3c91
31 changed files with 209 additions and 219 deletions

6
engine/bounding_box.go Normal file
View file

@ -0,0 +1,6 @@
package engine
type BoundingBox struct {
Positioned
Sized
}

View file

@ -1,8 +1,6 @@
package engine package engine
import ( import (
"mvvasilev/last_light/util"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
"github.com/gdamore/tcell/v2/views" "github.com/gdamore/tcell/v2/views"
"github.com/google/uuid" "github.com/google/uuid"
@ -11,10 +9,10 @@ import (
type Grid struct { type Grid struct {
id uuid.UUID id uuid.UUID
internalCellSize util.Size internalCellSize Size
numCellsHorizontal int numCellsHorizontal int
numCellsVertical int numCellsVertical int
position util.Position position Position
style tcell.Style style tcell.Style
highlightStyle tcell.Style highlightStyle tcell.Style
@ -38,7 +36,7 @@ type Grid struct {
crossJunction rune crossJunction rune
isHighlighted bool isHighlighted bool
highlightedGrid util.Position highlightedGrid Position
fillRune rune fillRune rune
} }
@ -79,11 +77,11 @@ func CreateGrid(
) *Grid { ) *Grid {
return &Grid{ return &Grid{
id: uuid.New(), id: uuid.New(),
internalCellSize: util.SizeOf(cellWidth, cellHeight), internalCellSize: SizeOf(cellWidth, cellHeight),
numCellsHorizontal: numCellsHorizontal, numCellsHorizontal: numCellsHorizontal,
numCellsVertical: numCellsVertical, numCellsVertical: numCellsVertical,
isHighlighted: false, isHighlighted: false,
position: util.PositionAt(x, y), position: PositionAt(x, y),
style: style, style: style,
highlightStyle: highlightStyle, highlightStyle: highlightStyle,
northBorder: northBorder, northBorder: northBorder,
@ -110,7 +108,7 @@ func (g *Grid) UniqueId() uuid.UUID {
return g.id return g.id
} }
func (g *Grid) Highlight(highlightedGrid util.Position) { func (g *Grid) Highlight(highlightedGrid Position) {
g.isHighlighted = true g.isHighlighted = true
g.highlightedGrid = highlightedGrid g.highlightedGrid = highlightedGrid
} }
@ -119,7 +117,7 @@ func (g *Grid) Unhighlight() {
g.isHighlighted = false g.isHighlighted = false
} }
func (g *Grid) Position() util.Position { func (g *Grid) Position() Position {
return g.position return g.position
} }

View file

@ -1,8 +1,6 @@
package engine package engine
import ( import (
"mvvasilev/last_light/util"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
"github.com/gdamore/tcell/v2/views" "github.com/gdamore/tcell/v2/views"
"github.com/google/uuid" "github.com/google/uuid"
@ -11,14 +9,14 @@ import (
type Raw struct { type Raw struct {
id uuid.UUID id uuid.UUID
buffer [][]rune buffer [][]rune
position util.Position position Position
style tcell.Style style tcell.Style
} }
func CreateRawDrawable(x, y int, style tcell.Style, buffer ...string) *Raw { func CreateRawDrawable(x, y int, style tcell.Style, buffer ...string) *Raw {
r := new(Raw) r := new(Raw)
r.position = util.PositionAt(x, y) r.position = PositionAt(x, y)
r.buffer = make([][]rune, 0) r.buffer = make([][]rune, 0)
for _, row := range buffer { for _, row := range buffer {
@ -33,7 +31,7 @@ func CreateRawDrawable(x, y int, style tcell.Style, buffer ...string) *Raw {
func CreateRawDrawableFromBuffer(x, y int, style tcell.Style, buffer [][]rune) *Raw { func CreateRawDrawableFromBuffer(x, y int, style tcell.Style, buffer [][]rune) *Raw {
r := new(Raw) r := new(Raw)
r.position = util.PositionAt(x, y) r.position = PositionAt(x, y)
r.buffer = buffer r.buffer = buffer
return r return r

View file

@ -1,8 +1,6 @@
package engine package engine
import ( import (
"mvvasilev/last_light/util"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
"github.com/gdamore/tcell/v2/views" "github.com/gdamore/tcell/v2/views"
"github.com/google/uuid" "github.com/google/uuid"
@ -11,8 +9,8 @@ import (
type Rectangle struct { type Rectangle struct {
id uuid.UUID id uuid.UUID
size util.Size size Size
position util.Position position Position
style tcell.Style style tcell.Style
northBorder rune northBorder rune
@ -103,8 +101,8 @@ func CreateRectangle(
) Rectangle { ) Rectangle {
return Rectangle{ return Rectangle{
id: uuid.New(), id: uuid.New(),
size: util.SizeOf(width, height), size: SizeOf(width, height),
position: util.PositionAt(x, y), position: PositionAt(x, y),
style: style, style: style,
northBorder: northBorder, northBorder: northBorder,
eastBorder: eastBorder, eastBorder: eastBorder,
@ -124,7 +122,7 @@ func (rect Rectangle) UniqueId() uuid.UUID {
return rect.id return rect.id
} }
func (rect Rectangle) Position() util.Position { func (rect Rectangle) Position() Position {
return rect.position return rect.position
} }

View file

@ -1,7 +1,6 @@
package engine package engine
import ( import (
"mvvasilev/last_light/util"
"strings" "strings"
"unicode/utf8" "unicode/utf8"
@ -13,8 +12,8 @@ import (
type Text struct { type Text struct {
id uuid.UUID id uuid.UUID
content []string content []string
position util.Position position Position
size util.Size size Size
style tcell.Style style tcell.Style
} }
@ -29,8 +28,8 @@ func CreateText(
text.id = uuid.New() text.id = uuid.New()
text.content = strings.Split(content, " ") text.content = strings.Split(content, " ")
text.style = style text.style = style
text.size = util.SizeOf(width, height) text.size = SizeOf(width, height)
text.position = util.PositionAt(x, y) text.position = PositionAt(x, y)
return text return text
} }
@ -39,7 +38,7 @@ func (t *Text) UniqueId() uuid.UUID {
return t.id return t.id
} }
func (t *Text) Position() util.Position { func (t *Text) Position() Position {
return t.position return t.position
} }
@ -47,7 +46,7 @@ func (t *Text) Content() string {
return strings.Join(t.content, " ") return strings.Join(t.content, " ")
} }
func (t *Text) Size() util.Size { func (t *Text) Size() Size {
return t.size return t.size
} }

View file

@ -1,4 +1,4 @@
package util package engine
import "math/rand" import "math/rand"
@ -110,8 +110,3 @@ func LimitDecrement(i int, limit int) int {
func RandInt(min, max int) int { func RandInt(min, max int) int {
return min + rand.Intn(max-min) return min + rand.Intn(max-min)
} }
type Room struct {
Positioned
Sized
}

View file

@ -1,8 +1,6 @@
package engine package engine
import ( import (
"mvvasilev/last_light/util"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
"github.com/gdamore/tcell/v2/views" "github.com/gdamore/tcell/v2/views"
"github.com/google/uuid" "github.com/google/uuid"
@ -10,15 +8,15 @@ import (
type Viewport struct { type Viewport struct {
id uuid.UUID id uuid.UUID
screenLocation util.Position screenLocation Position
viewportCenter util.Position viewportCenter Position
viewportSize util.Size viewportSize Size
style tcell.Style style tcell.Style
} }
func CreateViewport(screenLoc, viewportCenter util.Position, size util.Size, style tcell.Style) *Viewport { func CreateViewport(screenLoc, viewportCenter Position, size Size, style tcell.Style) *Viewport {
v := new(Viewport) v := new(Viewport)
v.id = uuid.New() v.id = uuid.New()
@ -34,19 +32,19 @@ func (vp *Viewport) UniqueId() uuid.UUID {
return vp.id return vp.id
} }
func (vp *Viewport) Center() util.Position { func (vp *Viewport) Center() Position {
return vp.viewportCenter return vp.viewportCenter
} }
func (vp *Viewport) SetCenter(pos util.Position) { func (vp *Viewport) SetCenter(pos Position) {
vp.viewportCenter = pos vp.viewportCenter = pos
} }
func (vp *Viewport) Size() util.Size { func (vp *Viewport) Size() Size {
return vp.viewportSize return vp.viewportSize
} }
func (vp *Viewport) ScreenLocation() util.Position { func (vp *Viewport) ScreenLocation() Position {
return vp.screenLocation return vp.screenLocation
} }

View file

@ -1,7 +1,7 @@
package model package model
import ( import (
"mvvasilev/last_light/util" "mvvasilev/last_light/engine"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
"github.com/google/uuid" "github.com/google/uuid"
@ -39,8 +39,8 @@ type Entity interface {
} }
type MovableEntity interface { type MovableEntity interface {
Position() util.Position Position() engine.Position
MoveTo(newPosition util.Position) MoveTo(newPosition engine.Position)
Entity Entity
} }

View file

@ -1,10 +1,10 @@
package model package model
import "mvvasilev/last_light/util" import "mvvasilev/last_light/engine"
type Inventory interface { type Inventory interface {
Items() []*Item Items() []*Item
Shape() util.Size Shape() engine.Size
Push(item Item) bool Push(item Item) bool
Drop(x, y int) *Item Drop(x, y int) *Item
ItemAt(x, y int) *Item ItemAt(x, y int) *Item
@ -12,10 +12,10 @@ type Inventory interface {
type BasicInventory struct { type BasicInventory struct {
contents []*Item contents []*Item
shape util.Size shape engine.Size
} }
func CreateInventory(shape util.Size) *BasicInventory { func CreateInventory(shape engine.Size) *BasicInventory {
inv := new(BasicInventory) inv := new(BasicInventory)
inv.contents = make([]*Item, 0, shape.Height()*shape.Width()) inv.contents = make([]*Item, 0, shape.Height()*shape.Width())
@ -28,7 +28,7 @@ func (i *BasicInventory) Items() (items []*Item) {
return i.contents return i.contents
} }
func (i *BasicInventory) Shape() util.Size { func (i *BasicInventory) Shape() engine.Size {
return i.shape return i.shape
} }

View file

@ -1,8 +1,6 @@
package model package model
import ( import (
"math/rand"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
) )
@ -105,15 +103,3 @@ func ItemTypeKey() *ItemType {
maxStack: 1, maxStack: 1,
} }
} }
func GenerateItemType(genTable map[float32]*ItemType) *ItemType {
num := rand.Float32()
for k, v := range genTable {
if num > k {
return v
}
}
return nil
}

View file

@ -1,7 +1,7 @@
package model package model
import ( import (
"mvvasilev/last_light/util" "mvvasilev/last_light/engine"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
"github.com/google/uuid" "github.com/google/uuid"
@ -9,7 +9,7 @@ import (
type Player struct { type Player struct {
id uuid.UUID id uuid.UUID
position util.Position position engine.Position
inventory *EquippedInventory inventory *EquippedInventory
} }
@ -18,7 +18,7 @@ func CreatePlayer(x, y int) *Player {
p := new(Player) p := new(Player)
p.id = uuid.New() p.id = uuid.New()
p.position = util.PositionAt(x, y) p.position = engine.PositionAt(x, y)
p.inventory = CreatePlayerInventory() p.inventory = CreatePlayerInventory()
return p return p
@ -28,11 +28,11 @@ func (p *Player) UniqueId() uuid.UUID {
return p.id return p.id
} }
func (p *Player) Position() util.Position { func (p *Player) Position() engine.Position {
return p.position return p.position
} }
func (p *Player) MoveTo(newPos util.Position) { func (p *Player) MoveTo(newPos engine.Position) {
p.position = newPos p.position = newPos
} }

View file

@ -1,6 +1,6 @@
package model package model
import "mvvasilev/last_light/util" import "mvvasilev/last_light/engine"
type EquippedSlot int type EquippedSlot int
@ -27,7 +27,7 @@ type EquippedInventory struct {
func CreatePlayerInventory() *EquippedInventory { func CreatePlayerInventory() *EquippedInventory {
return &EquippedInventory{ return &EquippedInventory{
BasicInventory: CreateInventory(util.SizeOf(8, 4)), BasicInventory: CreateInventory(engine.SizeOf(8, 4)),
} }
} }

View file

@ -2,9 +2,9 @@ package state
import ( import (
"mvvasilev/last_light/engine" "mvvasilev/last_light/engine"
engine1 "mvvasilev/last_light/engine"
"mvvasilev/last_light/game/model" "mvvasilev/last_light/game/model"
"mvvasilev/last_light/game/ui/menu" "mvvasilev/last_light/game/ui/menu"
"mvvasilev/last_light/util"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
) )
@ -14,7 +14,7 @@ type InventoryScreenState struct {
exitMenu bool exitMenu bool
inventoryMenu *menu.PlayerInventoryMenu inventoryMenu *menu.PlayerInventoryMenu
selectedInventorySlot util.Position selectedInventorySlot engine1.Position
player *model.Player player *model.Player
@ -27,7 +27,7 @@ func CreateInventoryScreenState(player *model.Player, prevState PausableState) *
iss.prevState = prevState iss.prevState = prevState
iss.player = player iss.player = player
iss.selectedInventorySlot = util.PositionAt(0, 0) iss.selectedInventorySlot = engine1.PositionAt(0, 0)
iss.exitMenu = false iss.exitMenu = false
iss.inventoryMenu = menu.CreatePlayerInventoryMenu(43, 0, player.Inventory(), tcell.StyleDefault, tcell.StyleDefault.Background(tcell.ColorDarkSlateGray)) iss.inventoryMenu = menu.CreatePlayerInventoryMenu(43, 0, player.Inventory(), tcell.StyleDefault, tcell.StyleDefault.Background(tcell.ColorDarkSlateGray))

View file

@ -2,8 +2,8 @@ package state
import ( import (
"mvvasilev/last_light/engine" "mvvasilev/last_light/engine"
engine1 "mvvasilev/last_light/engine"
"mvvasilev/last_light/game/ui" "mvvasilev/last_light/game/ui"
"mvvasilev/last_light/util"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
) )
@ -50,13 +50,13 @@ func NewMainMenuState() *MainMenuState {
func (mms *MainMenuState) OnInput(e *tcell.EventKey) { func (mms *MainMenuState) OnInput(e *tcell.EventKey) {
if e.Key() == tcell.KeyDown { if e.Key() == tcell.KeyDown {
mms.buttons[mms.currButtonSelected].Unhighlight() mms.buttons[mms.currButtonSelected].Unhighlight()
mms.currButtonSelected = util.LimitIncrement(mms.currButtonSelected, 2) mms.currButtonSelected = engine1.LimitIncrement(mms.currButtonSelected, 2)
mms.buttons[mms.currButtonSelected].Highlight() mms.buttons[mms.currButtonSelected].Highlight()
} }
if e.Key() == tcell.KeyUp { if e.Key() == tcell.KeyUp {
mms.buttons[mms.currButtonSelected].Unhighlight() mms.buttons[mms.currButtonSelected].Unhighlight()
mms.currButtonSelected = util.LimitDecrement(mms.currButtonSelected, 0) mms.currButtonSelected = engine1.LimitDecrement(mms.currButtonSelected, 0)
mms.buttons[mms.currButtonSelected].Highlight() mms.buttons[mms.currButtonSelected].Highlight()
} }

View file

@ -2,8 +2,8 @@ package state
import ( import (
"mvvasilev/last_light/engine" "mvvasilev/last_light/engine"
engine1 "mvvasilev/last_light/engine"
"mvvasilev/last_light/game/ui" "mvvasilev/last_light/game/ui"
"mvvasilev/last_light/util"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
) )
@ -68,13 +68,13 @@ func (pg *PauseGameState) OnInput(e *tcell.EventKey) {
if e.Key() == tcell.KeyDown { if e.Key() == tcell.KeyDown {
pg.buttons[pg.currButtonSelected].Unhighlight() pg.buttons[pg.currButtonSelected].Unhighlight()
pg.currButtonSelected = util.LimitIncrement(pg.currButtonSelected, 1) pg.currButtonSelected = engine1.LimitIncrement(pg.currButtonSelected, 1)
pg.buttons[pg.currButtonSelected].Highlight() pg.buttons[pg.currButtonSelected].Highlight()
} }
if e.Key() == tcell.KeyUp { if e.Key() == tcell.KeyUp {
pg.buttons[pg.currButtonSelected].Unhighlight() pg.buttons[pg.currButtonSelected].Unhighlight()
pg.currButtonSelected = util.LimitDecrement(pg.currButtonSelected, 0) pg.currButtonSelected = engine1.LimitDecrement(pg.currButtonSelected, 0)
pg.buttons[pg.currButtonSelected].Highlight() pg.buttons[pg.currButtonSelected].Highlight()
} }

View file

@ -1,11 +1,10 @@
package state package state
import ( import (
"math/rand"
"mvvasilev/last_light/engine" "mvvasilev/last_light/engine"
engine1 "mvvasilev/last_light/engine"
"mvvasilev/last_light/game/model" "mvvasilev/last_light/game/model"
"mvvasilev/last_light/game/world" "mvvasilev/last_light/game/world"
"mvvasilev/last_light/util"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
"github.com/gdamore/tcell/v2/views" "github.com/gdamore/tcell/v2/views"
@ -27,11 +26,18 @@ type PlayingState struct {
func BeginPlayingState() *PlayingState { func BeginPlayingState() *PlayingState {
s := new(PlayingState) s := new(PlayingState)
mapSize := util.SizeOf(128, 128) mapSize := engine1.SizeOf(128, 128)
dungeonLevel := world.CreateBSPDungeonMap(mapSize.Width(), mapSize.Height(), 4) dungeonLevel := world.CreateBSPDungeonMap(mapSize.Width(), mapSize.Height(), 4)
itemTiles := spawnItems(dungeonLevel) genTable := make(map[float32]*model.ItemType, 0)
genTable[0.2] = model.ItemTypeFish()
genTable[0.05] = model.ItemTypeBow()
genTable[0.051] = model.ItemTypeLongsword()
genTable[0.052] = model.ItemTypeKey()
itemTiles := world.SpawnItems(dungeonLevel.Rooms(), 0.025, genTable)
itemLevel := world.CreateEmptyDungeonLevel(mapSize.Width(), mapSize.Height()) itemLevel := world.CreateEmptyDungeonLevel(mapSize.Width(), mapSize.Height())
@ -52,57 +58,15 @@ func BeginPlayingState() *PlayingState {
s.entityMap.AddEntity(s.player, '@', tcell.StyleDefault) s.entityMap.AddEntity(s.player, '@', tcell.StyleDefault)
s.viewport = engine.CreateViewport( s.viewport = engine.CreateViewport(
util.PositionAt(0, 0), engine1.PositionAt(0, 0),
dungeonLevel.PlayerSpawnPoint(), dungeonLevel.PlayerSpawnPoint(),
util.SizeOf(80, 24), engine1.SizeOf(80, 24),
tcell.StyleDefault, tcell.StyleDefault,
) )
return s return s
} }
func spawnItems(level *world.BSPDungeonMap) []world.Tile {
rooms := level.Rooms()
genTable := make(map[float32]*model.ItemType)
genTable[0.2] = model.ItemTypeFish()
genTable[0.05] = model.ItemTypeBow()
genTable[0.051] = model.ItemTypeLongsword()
genTable[0.052] = model.ItemTypeKey()
itemTiles := make([]world.Tile, 0, 10)
for _, r := range rooms {
maxItems := int(0.10 * float64(r.Size().Area()))
if maxItems < 1 {
continue
}
numItems := rand.Intn(maxItems)
for range numItems {
itemType := model.GenerateItemType(genTable)
if itemType == nil {
continue
}
pos := util.PositionAt(
util.RandInt(r.Position().X()+1, r.Position().X()+r.Size().Width()-1),
util.RandInt(r.Position().Y()+1, r.Position().Y()+r.Size().Height()-1),
)
itemTiles = append(itemTiles, world.CreateItemTile(
pos, itemType, 1,
))
}
}
return itemTiles
}
func (ps *PlayingState) Pause() { func (ps *PlayingState) Pause() {
ps.pauseGame = true ps.pauseGame = true
} }

View file

@ -2,7 +2,7 @@ package ui
import ( import (
"mvvasilev/last_light/engine" "mvvasilev/last_light/engine"
"mvvasilev/last_light/util" engine1 "mvvasilev/last_light/engine"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
"github.com/gdamore/tcell/v2/views" "github.com/gdamore/tcell/v2/views"
@ -45,11 +45,11 @@ func (b *UIBorderedButton) MoveTo(x int, y int) {
panic("not implemented") // TODO: Implement panic("not implemented") // TODO: Implement
} }
func (b *UIBorderedButton) Position() util.Position { func (b *UIBorderedButton) Position() engine1.Position {
panic("not implemented") // TODO: Implement panic("not implemented") // TODO: Implement
} }
func (b *UIBorderedButton) Size() util.Size { func (b *UIBorderedButton) Size() engine1.Size {
panic("not implemented") // TODO: Implement panic("not implemented") // TODO: Implement
} }

View file

@ -1,7 +1,7 @@
package ui package ui
import ( import (
"mvvasilev/last_light/util" "mvvasilev/last_light/engine"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
"github.com/gdamore/tcell/v2/views" "github.com/gdamore/tcell/v2/views"
@ -28,8 +28,8 @@ const (
type UIContainer struct { type UIContainer struct {
id uuid.UUID id uuid.UUID
layout UIContainerLayout layout UIContainerLayout
position util.Position position engine.Position
size util.Size size engine.Size
elements []UIElement elements []UIElement
} }
@ -38,8 +38,8 @@ func CreateUIContainer(x, y int, width, height int, layout UIContainerLayout) *U
container.id = uuid.New() container.id = uuid.New()
container.layout = layout container.layout = layout
container.position = util.PositionAt(x, y) container.position = engine.PositionAt(x, y)
container.size = util.SizeOf(width, height) container.size = engine.SizeOf(width, height)
container.elements = make([]UIElement, 0) container.elements = make([]UIElement, 0)
return container return container
@ -58,14 +58,14 @@ func (uic *UIContainer) UniqueId() uuid.UUID {
} }
func (uic *UIContainer) MoveTo(x, y int) { func (uic *UIContainer) MoveTo(x, y int) {
uic.position = util.PositionAt(x, y) uic.position = engine.PositionAt(x, y)
} }
func (uic *UIContainer) Position() util.Position { func (uic *UIContainer) Position() engine.Position {
return uic.position return uic.position
} }
func (uic *UIContainer) Size() util.Size { func (uic *UIContainer) Size() engine.Size {
return uic.size return uic.size
} }

View file

@ -2,7 +2,7 @@ package ui
import ( import (
"mvvasilev/last_light/engine" "mvvasilev/last_light/engine"
"mvvasilev/last_light/util" engine1 "mvvasilev/last_light/engine"
"unicode/utf8" "unicode/utf8"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
@ -41,11 +41,11 @@ func (t *UILabel) MoveTo(x int, y int) {
t.text = engine.CreateText(x, y, int(t.text.Size().Width()), int(t.Size().Height()), t.text.Content(), t.text.Style()) t.text = engine.CreateText(x, y, int(t.text.Size().Width()), int(t.Size().Height()), t.text.Content(), t.text.Style())
} }
func (t *UILabel) Position() util.Position { func (t *UILabel) Position() engine1.Position {
return t.text.Position() return t.text.Position()
} }
func (t *UILabel) Size() util.Size { func (t *UILabel) Size() engine1.Size {
return t.text.Size() return t.text.Size()
} }

View file

@ -3,9 +3,9 @@ package menu
import ( import (
"fmt" "fmt"
"mvvasilev/last_light/engine" "mvvasilev/last_light/engine"
engine1 "mvvasilev/last_light/engine"
"mvvasilev/last_light/game/model" "mvvasilev/last_light/game/model"
"mvvasilev/last_light/game/ui" "mvvasilev/last_light/game/ui"
"mvvasilev/last_light/util"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
"github.com/gdamore/tcell/v2/views" "github.com/gdamore/tcell/v2/views"
@ -27,7 +27,7 @@ type PlayerInventoryMenu struct {
selectedItem *engine.ArbitraryDrawable selectedItem *engine.ArbitraryDrawable
help *ui.UILabel help *ui.UILabel
selectedInventorySlot util.Position selectedInventorySlot engine1.Position
} }
func CreatePlayerInventoryMenu(x, y int, playerInventory *model.EquippedInventory, style tcell.Style, highlightStyle tcell.Style) *PlayerInventoryMenu { func CreatePlayerInventoryMenu(x, y int, playerInventory *model.EquippedInventory, style tcell.Style, highlightStyle tcell.Style) *PlayerInventoryMenu {
@ -138,11 +138,11 @@ func (pim *PlayerInventoryMenu) MoveTo(x int, y int) {
} }
func (pim *PlayerInventoryMenu) Position() util.Position { func (pim *PlayerInventoryMenu) Position() engine1.Position {
return pim.inventoryMenu.Position() return pim.inventoryMenu.Position()
} }
func (pim *PlayerInventoryMenu) Size() util.Size { func (pim *PlayerInventoryMenu) Size() engine1.Size {
return pim.inventoryMenu.Size() return pim.inventoryMenu.Size()
} }
@ -156,7 +156,7 @@ func (pim *PlayerInventoryMenu) UniqueId() uuid.UUID {
func (pim *PlayerInventoryMenu) SelectSlot(x, y int) { func (pim *PlayerInventoryMenu) SelectSlot(x, y int) {
pim.inventoryGrid.Unhighlight() pim.inventoryGrid.Unhighlight()
pim.selectedInventorySlot = util.PositionAt(x, y) pim.selectedInventorySlot = engine1.PositionAt(x, y)
pim.inventoryGrid.Highlight(pim.selectedInventorySlot) pim.inventoryGrid.Highlight(pim.selectedInventorySlot)
} }

View file

@ -2,7 +2,7 @@ package ui
import ( import (
"mvvasilev/last_light/engine" "mvvasilev/last_light/engine"
"mvvasilev/last_light/util" engine1 "mvvasilev/last_light/engine"
"strings" "strings"
"unicode/utf8" "unicode/utf8"
@ -85,11 +85,11 @@ func (sb *UISimpleButton) MoveTo(x int, y int) {
sb.text = engine.CreateText(x, y, int(utf8.RuneCountInString(sb.text.Content())), 1, sb.text.Content(), sb.highlightedStyle) sb.text = engine.CreateText(x, y, int(utf8.RuneCountInString(sb.text.Content())), 1, sb.text.Content(), sb.highlightedStyle)
} }
func (sb *UISimpleButton) Position() util.Position { func (sb *UISimpleButton) Position() engine1.Position {
return sb.text.Position() return sb.text.Position()
} }
func (sb *UISimpleButton) Size() util.Size { func (sb *UISimpleButton) Size() engine1.Size {
return sb.text.Size() return sb.text.Size()
} }

View file

@ -2,15 +2,15 @@ package ui
import ( import (
"mvvasilev/last_light/engine" "mvvasilev/last_light/engine"
"mvvasilev/last_light/util" engine1 "mvvasilev/last_light/engine"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
) )
type UIElement interface { type UIElement interface {
MoveTo(x, y int) MoveTo(x, y int)
Position() util.Position Position() engine1.Position
Size() util.Size Size() engine1.Size
Input(e *tcell.EventKey) Input(e *tcell.EventKey)
engine.Drawable engine.Drawable

View file

@ -2,7 +2,7 @@ package ui
import ( import (
"mvvasilev/last_light/engine" "mvvasilev/last_light/engine"
"mvvasilev/last_light/util" engine1 "mvvasilev/last_light/engine"
"unicode/utf8" "unicode/utf8"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
@ -45,12 +45,12 @@ func (w *UIWindow) MoveTo(x int, y int) {
} }
func (w *UIWindow) Position() util.Position { func (w *UIWindow) Position() engine1.Position {
return w.box.Position() return w.box.Position()
} }
func (w *UIWindow) Size() util.Size { func (w *UIWindow) Size() engine1.Size {
return util.SizeOf(0, 0) return engine1.SizeOf(0, 0)
} }
func (w *UIWindow) Draw(v views.View) { func (w *UIWindow) Draw(v views.View) {

View file

@ -1,21 +1,21 @@
package world package world
import ( import (
"mvvasilev/last_light/util" "mvvasilev/last_light/engine"
) )
type BSPDungeonMap struct { type BSPDungeonMap struct {
level *BasicMap level *BasicMap
playerSpawnPoint util.Position playerSpawnPoint engine.Position
rooms []util.Room rooms []engine.BoundingBox
} }
func (bsp *BSPDungeonMap) PlayerSpawnPoint() util.Position { func (bsp *BSPDungeonMap) PlayerSpawnPoint() engine.Position {
return bsp.playerSpawnPoint return bsp.playerSpawnPoint
} }
func (bsp *BSPDungeonMap) Size() util.Size { func (bsp *BSPDungeonMap) Size() engine.Size {
return bsp.level.Size() return bsp.level.Size()
} }
@ -30,6 +30,6 @@ func (bsp *BSPDungeonMap) TileAt(x int, y int) Tile {
func (bsp *BSPDungeonMap) Tick(dt int64) { func (bsp *BSPDungeonMap) Tick(dt int64) {
} }
func (bsp *BSPDungeonMap) Rooms() []util.Room { func (bsp *BSPDungeonMap) Rooms() []engine.BoundingBox {
return bsp.rooms return bsp.rooms
} }

View file

@ -1,12 +1,12 @@
package world package world
import "mvvasilev/last_light/util" import "mvvasilev/last_light/engine"
type EmptyDungeonMap struct { type EmptyDungeonMap struct {
level *BasicMap level *BasicMap
} }
func (edl *EmptyDungeonMap) Size() util.Size { func (edl *EmptyDungeonMap) Size() engine.Size {
return edl.level.Size() return edl.level.Size()
} }

View file

@ -2,8 +2,8 @@ package world
import ( import (
"maps" "maps"
"mvvasilev/last_light/engine"
"mvvasilev/last_light/game/model" "mvvasilev/last_light/game/model"
"mvvasilev/last_light/util"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
"github.com/google/uuid" "github.com/google/uuid"
@ -12,13 +12,13 @@ import (
type EntityMap struct { type EntityMap struct {
entities map[int]EntityTile entities map[int]EntityTile
util.Sized engine.Sized
} }
func CreateEntityMap(width, height int) *EntityMap { func CreateEntityMap(width, height int) *EntityMap {
return &EntityMap{ return &EntityMap{
entities: make(map[int]EntityTile, 0), entities: make(map[int]EntityTile, 0),
Sized: util.WithSize(util.SizeOf(width, height)), Sized: engine.WithSize(engine.SizeOf(width, height)),
} }
} }
@ -55,11 +55,7 @@ func (em *EntityMap) AddEntity(entity model.MovableEntity, presentation rune, st
func (em *EntityMap) DropEntity(uuid uuid.UUID) { func (em *EntityMap) DropEntity(uuid uuid.UUID) {
maps.DeleteFunc(em.entities, func(i int, et EntityTile) bool { maps.DeleteFunc(em.entities, func(i int, et EntityTile) bool {
if et.Entity().UniqueId() == uuid { return et.Entity().UniqueId() == uuid
return true
}
return false
}) })
} }

View file

@ -2,7 +2,7 @@ package world
import ( import (
"math/rand" "math/rand"
"mvvasilev/last_light/util" "mvvasilev/last_light/engine"
) )
type splitDirection bool type splitDirection bool
@ -13,10 +13,10 @@ const (
) )
type bspNode struct { type bspNode struct {
origin util.Position origin engine.Position
size util.Size size engine.Size
room util.Room room engine.BoundingBox
hasRoom bool hasRoom bool
left *bspNode left *bspNode
@ -28,8 +28,8 @@ type bspNode struct {
func CreateBSPDungeonMap(width, height int, numSplits int) *BSPDungeonMap { func CreateBSPDungeonMap(width, height int, numSplits int) *BSPDungeonMap {
root := new(bspNode) root := new(bspNode)
root.origin = util.PositionAt(0, 0) root.origin = engine.PositionAt(0, 0)
root.size = util.SizeOf(width, height) root.size = engine.SizeOf(width, height)
split(root, numSplits) split(root, numSplits)
@ -39,13 +39,13 @@ func CreateBSPDungeonMap(width, height int, numSplits int) *BSPDungeonMap {
tiles[h] = make([]Tile, width) tiles[h] = make([]Tile, width)
} }
rooms := make([]util.Room, 0, 2^numSplits) rooms := make([]engine.BoundingBox, 0, 2^numSplits)
iterateBspLeaves(root, func(leaf *bspNode) { iterateBspLeaves(root, func(leaf *bspNode) {
x := util.RandInt(leaf.origin.X(), leaf.origin.X()+leaf.size.Width()/4) x := engine.RandInt(leaf.origin.X(), leaf.origin.X()+leaf.size.Width()/4)
y := util.RandInt(leaf.origin.Y(), leaf.origin.Y()+leaf.size.Height()/4) y := engine.RandInt(leaf.origin.Y(), leaf.origin.Y()+leaf.size.Height()/4)
w := util.RandInt(3, leaf.size.Width()-1) w := engine.RandInt(3, leaf.size.Width()-1)
h := util.RandInt(3, leaf.size.Height()-1) h := engine.RandInt(3, leaf.size.Height()-1)
if x+w >= width { if x+w >= width {
w = w - (x + w - width) - 1 w = w - (x + w - width) - 1
@ -55,9 +55,9 @@ func CreateBSPDungeonMap(width, height int, numSplits int) *BSPDungeonMap {
h = h - (y + h - height) - 1 h = h - (y + h - height) - 1
} }
room := util.Room{ room := engine.BoundingBox{
Positioned: util.WithPosition(util.PositionAt(x, y)), Positioned: engine.WithPosition(engine.PositionAt(x, y)),
Sized: util.WithSize(util.SizeOf(w, h)), Sized: engine.WithSize(engine.SizeOf(w, h)),
} }
rooms = append(rooms, room) rooms = append(rooms, room)
@ -74,11 +74,11 @@ func CreateBSPDungeonMap(width, height int, numSplits int) *BSPDungeonMap {
zCorridor( zCorridor(
tiles, tiles,
util.PositionAt( engine.PositionAt(
roomLeft.Position().X()+roomLeft.Size().Width()/2, roomLeft.Position().X()+roomLeft.Size().Width()/2,
roomLeft.Position().Y()+roomLeft.Size().Height()/2, roomLeft.Position().Y()+roomLeft.Size().Height()/2,
), ),
util.PositionAt( engine.PositionAt(
roomRight.Position().X()+roomRight.Size().Width()/2, roomRight.Position().X()+roomRight.Size().Width()/2,
roomRight.Position().Y()+roomRight.Size().Height()/2, roomRight.Position().Y()+roomRight.Size().Height()/2,
), ),
@ -92,7 +92,7 @@ func CreateBSPDungeonMap(width, height int, numSplits int) *BSPDungeonMap {
bsp.rooms = rooms bsp.rooms = rooms
bsp.level = CreateBasicMap(tiles) bsp.level = CreateBasicMap(tiles)
bsp.playerSpawnPoint = util.PositionAt( bsp.playerSpawnPoint = engine.PositionAt(
spawnRoom.Position().X()+spawnRoom.Size().Width()/2, spawnRoom.Position().X()+spawnRoom.Size().Width()/2,
spawnRoom.Position().Y()+spawnRoom.Size().Height()/2, spawnRoom.Position().Y()+spawnRoom.Size().Height()/2,
) )
@ -100,7 +100,7 @@ func CreateBSPDungeonMap(width, height int, numSplits int) *BSPDungeonMap {
return bsp return bsp
} }
func findRoom(parent *bspNode) util.Room { func findRoom(parent *bspNode) engine.BoundingBox {
if parent.hasRoom { if parent.hasRoom {
return parent.room return parent.room
} }
@ -112,7 +112,7 @@ func findRoom(parent *bspNode) util.Room {
} }
} }
func zCorridor(tiles [][]Tile, from util.Position, to util.Position, direction splitDirection) { func zCorridor(tiles [][]Tile, from engine.Position, to engine.Position, direction splitDirection) {
switch direction { switch direction {
case splitDirectionHorizontal: case splitDirectionHorizontal:
xMidPoint := (from.X() + to.X()) / 2 xMidPoint := (from.X() + to.X()) / 2
@ -164,30 +164,30 @@ func split(parent *bspNode, numSplits int) {
// split vertically // split vertically
if parent.size.Width() > parent.size.Height() { if parent.size.Width() > parent.size.Height() {
// New splits will be between 45% and 65% of the parent's width // New splits will be between 45% and 65% of the parent's width
leftSplitWidth := util.RandInt(int(float32(parent.size.Width())*0.45), int(float32(parent.size.Width())*0.65)) leftSplitWidth := engine.RandInt(int(float32(parent.size.Width())*0.45), int(float32(parent.size.Width())*0.65))
parent.splitDir = splitDirectionVertical parent.splitDir = splitDirectionVertical
parent.left = new(bspNode) parent.left = new(bspNode)
parent.left.origin = parent.origin parent.left.origin = parent.origin
parent.left.size = util.SizeOf(leftSplitWidth, parent.size.Height()) parent.left.size = engine.SizeOf(leftSplitWidth, parent.size.Height())
parent.right = new(bspNode) parent.right = new(bspNode)
parent.right.origin = parent.origin.WithOffset(leftSplitWidth, 0) parent.right.origin = parent.origin.WithOffset(leftSplitWidth, 0)
parent.right.size = util.SizeOf(parent.size.Width()-leftSplitWidth, parent.size.Height()) parent.right.size = engine.SizeOf(parent.size.Width()-leftSplitWidth, parent.size.Height())
} else { // split horizontally } else { // split horizontally
// New splits will be between 45% and 65% of the parent's height // New splits will be between 45% and 65% of the parent's height
leftSplitHeight := util.RandInt(int(float32(parent.size.Height())*0.45), int(float32(parent.size.Height())*0.65)) leftSplitHeight := engine.RandInt(int(float32(parent.size.Height())*0.45), int(float32(parent.size.Height())*0.65))
parent.splitDir = splitDirectionHorizontal parent.splitDir = splitDirectionHorizontal
parent.left = new(bspNode) parent.left = new(bspNode)
parent.left.origin = parent.origin parent.left.origin = parent.origin
parent.left.size = util.SizeOf(parent.size.Width(), leftSplitHeight) parent.left.size = engine.SizeOf(parent.size.Width(), leftSplitHeight)
parent.right = new(bspNode) parent.right = new(bspNode)
parent.right.origin = parent.origin.WithOffset(0, leftSplitHeight) parent.right.origin = parent.origin.WithOffset(0, leftSplitHeight)
parent.right.size = util.SizeOf(parent.size.Width(), parent.size.Height()-leftSplitHeight) parent.right.size = engine.SizeOf(parent.size.Width(), parent.size.Height()-leftSplitHeight)
} }
split(parent.left, numSplits-1) split(parent.left, numSplits-1)
@ -256,7 +256,7 @@ func placeWallAtIfNotPassable(tiles [][]Tile, x, y int) {
tiles[y][x] = CreateStaticTile(x, y, TileTypeWall()) tiles[y][x] = CreateStaticTile(x, y, TileTypeWall())
} }
func makeRoom(tiles [][]Tile, room util.Room) { func makeRoom(tiles [][]Tile, room engine.BoundingBox) {
width := room.Size().Width() width := room.Size().Width()
height := room.Size().Height() height := room.Size().Height()
x := room.Position().X() x := room.Position().X()

View file

@ -0,0 +1,52 @@
package world
import (
"math/rand"
"mvvasilev/last_light/engine"
"mvvasilev/last_light/game/model"
)
func SpawnItems(spawnableAreas []engine.BoundingBox, maxItemRatio float32, genTable map[float32]*model.ItemType) []Tile {
rooms := spawnableAreas
itemTiles := make([]Tile, 0, 10)
for _, r := range rooms {
maxItems := int(maxItemRatio * float32(r.Size().Area()))
if maxItems < 1 {
continue
}
numItems := rand.Intn(maxItems)
for range numItems {
itemType := GenerateItemType(genTable)
if itemType == nil {
continue
}
pos := engine.PositionAt(
engine.RandInt(r.Position().X()+1, r.Position().X()+r.Size().Width()-1),
engine.RandInt(r.Position().Y()+1, r.Position().Y()+r.Size().Height()-1),
)
itemTiles = append(itemTiles, CreateItemTile(pos, itemType, 1))
}
}
return itemTiles
}
func GenerateItemType(genTable map[float32]*model.ItemType) *model.ItemType {
num := rand.Float32()
for k, v := range genTable {
if num > k {
return v
}
}
return nil
}

View file

@ -1,23 +1,23 @@
package world package world
import ( import (
"mvvasilev/last_light/util" "mvvasilev/last_light/engine"
) )
type Map interface { type Map interface {
Size() util.Size Size() engine.Size
SetTileAt(x, y int, t Tile) SetTileAt(x, y int, t Tile)
TileAt(x, y int) Tile TileAt(x, y int) Tile
Tick(dt int64) Tick(dt int64)
} }
type WithPlayerSpawnPoint interface { type WithPlayerSpawnPoint interface {
PlayerSpawnPoint() util.Position PlayerSpawnPoint() engine.Position
Map Map
} }
type WithRooms interface { type WithRooms interface {
Rooms() []util.Room Rooms() []engine.BoundingBox
Map Map
} }
@ -36,8 +36,8 @@ func CreateBasicMap(tiles [][]Tile) *BasicMap {
func (bm *BasicMap) Tick() { func (bm *BasicMap) Tick() {
} }
func (bm *BasicMap) Size() util.Size { func (bm *BasicMap) Size() engine.Size {
return util.SizeOf(len(bm.tiles[0]), len(bm.tiles)) return engine.SizeOf(len(bm.tiles[0]), len(bm.tiles))
} }
func (bm *BasicMap) SetTileAt(x int, y int, t Tile) { func (bm *BasicMap) SetTileAt(x int, y int, t Tile) {

View file

@ -1,6 +1,6 @@
package world package world
import "mvvasilev/last_light/util" import "mvvasilev/last_light/engine"
type MultilevelMap struct { type MultilevelMap struct {
layers []Map layers []Map
@ -14,9 +14,9 @@ func CreateMultilevelMap(maps ...Map) *MultilevelMap {
return m return m
} }
func (mm *MultilevelMap) Size() util.Size { func (mm *MultilevelMap) Size() engine.Size {
if len(mm.layers) == 0 { if len(mm.layers) == 0 {
return util.SizeOf(0, 0) return engine.SizeOf(0, 0)
} }
return mm.layers[0].Size() return mm.layers[0].Size()

View file

@ -1,8 +1,8 @@
package world package world
import ( import (
"mvvasilev/last_light/engine"
"mvvasilev/last_light/game/model" "mvvasilev/last_light/game/model"
"mvvasilev/last_light/util"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
) )
@ -98,27 +98,27 @@ func TileTypeOpenDoor() TileType {
} }
type Tile interface { type Tile interface {
Position() util.Position Position() engine.Position
Presentation() (rune, tcell.Style) Presentation() (rune, tcell.Style)
Passable() bool Passable() bool
Transparent() bool Transparent() bool
} }
type StaticTile struct { type StaticTile struct {
position util.Position position engine.Position
t TileType t TileType
} }
func CreateStaticTile(x, y int, t TileType) Tile { func CreateStaticTile(x, y int, t TileType) Tile {
st := new(StaticTile) st := new(StaticTile)
st.position = util.PositionAt(x, y) st.position = engine.PositionAt(x, y)
st.t = t st.t = t
return st return st
} }
func (st *StaticTile) Position() util.Position { func (st *StaticTile) Position() engine.Position {
return st.position return st.position
} }
@ -139,12 +139,12 @@ func (st *StaticTile) Type() TileType {
} }
type ItemTile struct { type ItemTile struct {
position util.Position position engine.Position
itemType *model.ItemType itemType *model.ItemType
quantity int quantity int
} }
func CreateItemTile(position util.Position, itemType *model.ItemType, quantity int) *ItemTile { func CreateItemTile(position engine.Position, itemType *model.ItemType, quantity int) *ItemTile {
it := new(ItemTile) it := new(ItemTile)
it.position = position it.position = position
@ -162,7 +162,7 @@ func (it *ItemTile) Quantity() int {
return it.quantity return it.quantity
} }
func (it *ItemTile) Position() util.Position { func (it *ItemTile) Position() engine.Position {
return it.position return it.position
} }
@ -202,7 +202,7 @@ func (bet *BasicEntityTile) Entity() model.MovableEntity {
return bet.entity return bet.entity
} }
func (bet *BasicEntityTile) Position() util.Position { func (bet *BasicEntityTile) Position() engine.Position {
return bet.entity.Position() return bet.entity.Position()
} }