Added menu and sprinting

This commit is contained in:
2025-11-19 08:50:39 -07:00
parent bd33e7e123
commit c5a3bcb3f4
5 changed files with 494 additions and 59 deletions

View File

@@ -5,10 +5,12 @@ import (
"time"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/inpututil"
"github.com/atridad/BigFeelings/internal/hero"
"github.com/atridad/BigFeelings/internal/status"
"github.com/atridad/BigFeelings/internal/ui/hud"
"github.com/atridad/BigFeelings/internal/ui/menu"
)
const (
@@ -23,19 +25,28 @@ var (
backgroundColor = color.NRGBA{R: 0, G: 0, B: 0, A: 255}
)
type gameState int
const (
statePlaying gameState = iota
statePaused
)
type controls struct {
Left bool
Right bool
Up bool
Down bool
Left bool
Right bool
Up bool
Down bool
Sprint bool
}
func readControls() controls {
return controls{
Left: ebiten.IsKeyPressed(ebiten.KeyArrowLeft) || ebiten.IsKeyPressed(ebiten.KeyA),
Right: ebiten.IsKeyPressed(ebiten.KeyArrowRight) || ebiten.IsKeyPressed(ebiten.KeyD),
Up: ebiten.IsKeyPressed(ebiten.KeyArrowUp) || ebiten.IsKeyPressed(ebiten.KeyW),
Down: ebiten.IsKeyPressed(ebiten.KeyArrowDown) || ebiten.IsKeyPressed(ebiten.KeyS),
Left: ebiten.IsKeyPressed(ebiten.KeyArrowLeft) || ebiten.IsKeyPressed(ebiten.KeyA),
Right: ebiten.IsKeyPressed(ebiten.KeyArrowRight) || ebiten.IsKeyPressed(ebiten.KeyD),
Up: ebiten.IsKeyPressed(ebiten.KeyArrowUp) || ebiten.IsKeyPressed(ebiten.KeyW),
Down: ebiten.IsKeyPressed(ebiten.KeyArrowDown) || ebiten.IsKeyPressed(ebiten.KeyS),
Sprint: ebiten.IsKeyPressed(ebiten.KeyShift),
}
}
@@ -48,7 +59,33 @@ func New() *Game {
}
func (g *Game) Update() error {
g.state.update(readControls())
// Handle escape key to toggle pause
if inpututil.IsKeyJustPressed(ebiten.KeyEscape) {
if g.state.gameState == statePlaying {
g.state.gameState = statePaused
g.state.pauseMenu.Reset()
} else if g.state.gameState == statePaused {
g.state.gameState = statePlaying
// Reset lastTick to prevent delta time accumulation while paused
g.state.lastTick = time.Now()
}
}
if g.state.gameState == statePlaying {
g.state.update(readControls())
} else if g.state.gameState == statePaused {
if selectedOption := g.state.pauseMenu.Update(); selectedOption != nil {
switch *selectedOption {
case menu.OptionResume:
g.state.gameState = statePlaying
// Reset lastTick to prevent delta time accumulation while paused
g.state.lastTick = time.Now()
case menu.OptionQuit:
return ebiten.Termination
}
}
}
return nil
}
@@ -61,27 +98,26 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
}
type state struct {
hero *hero.Hero
status *status.Manager
hud hud.Overlay
bounds hero.Bounds
lastTick time.Time
hero *hero.Hero
hud hud.Overlay
bounds hero.Bounds
lastTick time.Time
pauseMenu *menu.PauseMenu
gameState gameState
}
func newState() *state {
now := time.Now()
return &state{
hero: hero.New(hero.Config{
StartX: ScreenWidth / 2,
StartY: ScreenHeight / 2,
Radius: 28,
Speed: 180,
Color: color.NRGBA{R: 210, G: 220, B: 255, A: 255},
}),
status: status.NewManager([]status.Config{
{Label: "Core", Base: 60, Color: color.NRGBA{R: 255, G: 208, B: 0, A: 255}},
{Label: "Drive", Base: 45, Color: color.NRGBA{R: 0, G: 190, B: 255, A: 255}},
{Label: "Flux", Base: 30, Color: color.NRGBA{R: 255, G: 92, B: 120, A: 255}},
StartX: ScreenWidth / 2,
StartY: ScreenHeight / 2,
Radius: 28,
Speed: 180,
Color: color.NRGBA{R: 210, G: 220, B: 255, A: 255},
MaxStamina: 100,
StaminaDrain: 50,
StaminaRegen: 30,
}),
hud: hud.Overlay{
X: ScreenWidth - 220,
@@ -92,7 +128,9 @@ func newState() *state {
Width: ScreenWidth,
Height: ScreenHeight,
},
lastTick: now,
lastTick: now,
pauseMenu: menu.NewPauseMenu(),
gameState: statePlaying,
}
}
@@ -102,17 +140,34 @@ func (s *state) update(input controls) {
s.lastTick = now
s.hero.Update(hero.Input{
Left: input.Left,
Right: input.Right,
Up: input.Up,
Down: input.Down,
Left: input.Left,
Right: input.Right,
Up: input.Up,
Down: input.Down,
Sprint: input.Sprint,
}, dt, s.bounds)
s.status.Update()
}
func (s *state) draw(screen *ebiten.Image) {
screen.Fill(backgroundColor)
s.hero.Draw(screen)
s.hud.Draw(screen, s.status.Meters())
// Create stamina meter from hero's stamina
staminaColor := color.NRGBA{R: 0, G: 255, B: 180, A: 255}
if s.hero.Stamina < s.hero.MaxStamina*0.2 {
staminaColor = color.NRGBA{R: 255, G: 60, B: 60, A: 255}
}
staminaMeter := status.Meter{
Label: "Stamina",
Base: s.hero.MaxStamina,
Level: s.hero.Stamina,
Color: staminaColor,
}
s.hud.Draw(screen, []status.Meter{staminaMeter})
// Draw pause menu if paused
if s.gameState == statePaused {
s.pauseMenu.Draw(screen, ScreenWidth, ScreenHeight)
}
}