last_light/game/state/playing_state.go

144 lines
3 KiB
Go

package state
import (
"mvvasilev/last_light/game/model"
"mvvasilev/last_light/render"
"mvvasilev/last_light/util"
"github.com/gdamore/tcell/v2"
"github.com/gdamore/tcell/v2/views"
)
type PlayingState struct {
player *model.Player
level *model.MultilevelMap
viewport *render.Viewport
movePlayerDirection model.Direction
pauseGame bool
openInventory bool
}
func BeginPlayingState() *PlayingState {
s := new(PlayingState)
mapSize := util.SizeOf(128, 128)
s.player = model.CreatePlayer(40, 12)
s.level = model.CreateMultilevelMap(
model.CreateFlatGroundDungeonLevel(mapSize.WH()),
model.CreateEmptyDungeonLevel(mapSize.WH()),
)
s.level.SetTileAtHeight(40, 12, 1, s.player)
s.viewport = render.CreateViewport(
util.PositionAt(0, 0),
util.PositionAt(40, 12),
util.SizeOf(80, 24),
tcell.StyleDefault,
)
return s
}
func (ps *PlayingState) Pause() {
ps.pauseGame = true
}
func (ps *PlayingState) Unpause() {
ps.pauseGame = false
}
func (ps *PlayingState) SetPaused(paused bool) {
ps.pauseGame = paused
}
func (ps *PlayingState) MovePlayer() {
if ps.movePlayerDirection == model.DirectionNone {
return
}
newPlayerPos := ps.player.Position().WithOffset(model.MovementDirectionOffset(ps.movePlayerDirection))
tileAtMovePos := ps.level.TileAt(newPlayerPos.XY())
if tileAtMovePos.Passable() {
ps.level.SetTileAtHeight(ps.player.Position().X(), ps.player.Position().Y(), 1, nil)
ps.player.Move(ps.movePlayerDirection)
ps.viewport.SetCenter(ps.player.Position())
ps.level.SetTileAtHeight(ps.player.Position().X(), ps.player.Position().Y(), 1, ps.player)
}
ps.movePlayerDirection = model.DirectionNone
}
func (ps *PlayingState) OnInput(e *tcell.EventKey) {
ps.player.Input(e)
if e.Key() == tcell.KeyEsc {
ps.pauseGame = true
return
}
if e.Key() == tcell.KeyRune && e.Rune() == 'i' {
ps.openInventory = true
return
}
switch e.Key() {
case tcell.KeyUp:
ps.movePlayerDirection = model.DirectionUp
case tcell.KeyDown:
ps.movePlayerDirection = model.DirectionDown
case tcell.KeyLeft:
ps.movePlayerDirection = model.DirectionLeft
case tcell.KeyRight:
ps.movePlayerDirection = model.DirectionRight
case tcell.KeyRune:
switch e.Rune() {
case 'w':
ps.movePlayerDirection = model.DirectionUp
case 'a':
ps.movePlayerDirection = model.DirectionLeft
case 's':
ps.movePlayerDirection = model.DirectionDown
case 'd':
ps.movePlayerDirection = model.DirectionRight
}
}
}
func (ps *PlayingState) OnTick(dt int64) GameState {
ps.player.Tick(dt)
if ps.pauseGame {
return PauseGame(ps)
}
if ps.openInventory {
return CreateInventoryScreenState(ps.player, ps)
}
if ps.movePlayerDirection != model.DirectionNone {
ps.MovePlayer()
}
return ps
}
func (ps *PlayingState) CollectDrawables() []render.Drawable {
return render.Multidraw(render.CreateDrawingInstructions(func(v views.View) {
ps.viewport.DrawFromProvider(v, func(x, y int) rune {
tile := ps.level.TileAt(x, y)
if tile != nil {
return tile.Presentation()
}
return ' '
})
}))
}