Using a temp free online sprite for now to test sprites

This commit is contained in:
2025-11-19 09:08:25 -07:00
parent c5a3bcb3f4
commit 8eb5909919
11 changed files with 370 additions and 271 deletions

View File

@@ -13,18 +13,57 @@ import (
"github.com/atridad/BigFeelings/internal/ui/menu"
)
// ============================================================
// CONFIGURATION
// Tweak these values to change game settings
// ============================================================
const (
ScreenWidth = 960
ScreenHeight = 540
TargetTPS = 60
WindowTitle = "Big Feelings"
TargetTPS = 60
WindowTitle = "Big Feelings"
)
var (
backgroundColor = color.NRGBA{R: 0, G: 0, B: 0, A: 255}
)
// Hero configuration
const (
heroStartX = ScreenWidth / 2
heroStartY = ScreenHeight / 2
heroRadius = 28.0
heroSpeed = 180.0
heroMaxStamina = 100.0
heroStaminaDrain = 50.0
heroStaminaRegen = 30.0
)
var (
heroColor = color.NRGBA{R: 210, G: 220, B: 255, A: 255}
)
// HUD configuration
const (
hudX = ScreenWidth - 220
hudY = 20
)
// Stamina bar colors
var (
staminaNormalColor = color.NRGBA{R: 0, G: 255, B: 180, A: 255}
staminaLowColor = color.NRGBA{R: 255, G: 60, B: 60, A: 255}
)
const (
staminaLowThreshold = 0.2
)
// ============================================================
// TYPES
// ============================================================
type gameState int
const (
@@ -40,63 +79,10 @@ type controls struct {
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),
Sprint: ebiten.IsKeyPressed(ebiten.KeyShift),
}
}
type Game struct {
state *state
}
func New() *Game {
return &Game{state: newState()}
}
func (g *Game) Update() error {
// 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
}
func (g *Game) Draw(screen *ebiten.Image) {
g.state.draw(screen)
}
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return ScreenWidth, ScreenHeight
}
type state struct {
hero *hero.Hero
hud hud.Overlay
@@ -106,22 +92,30 @@ type state struct {
gameState gameState
}
// ============================================================
// INITIALIZATION
// ============================================================
func New() *Game {
return &Game{state: newState()}
}
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},
MaxStamina: 100,
StaminaDrain: 50,
StaminaRegen: 30,
StartX: heroStartX,
StartY: heroStartY,
Radius: heroRadius,
Speed: heroSpeed,
Color: heroColor,
MaxStamina: heroMaxStamina,
StaminaDrain: heroStaminaDrain,
StaminaRegen: heroStaminaRegen,
}),
hud: hud.Overlay{
X: ScreenWidth - 220,
Y: 20,
X: hudX,
Y: hudY,
Color: color.White,
},
bounds: hero.Bounds{
@@ -134,6 +128,52 @@ func newState() *state {
}
}
// ============================================================
// INPUT
// ============================================================
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),
Sprint: ebiten.IsKeyPressed(ebiten.KeyShift),
}
}
// ============================================================
// UPDATE
// ============================================================
func (g *Game) Update() error {
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
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
g.state.lastTick = time.Now()
case menu.OptionQuit:
return ebiten.Termination
}
}
}
return nil
}
func (s *state) update(input controls) {
now := time.Now()
dt := now.Sub(s.lastTick).Seconds()
@@ -148,14 +188,21 @@ func (s *state) update(input controls) {
}, dt, s.bounds)
}
// ============================================================
// RENDERING
// ============================================================
func (g *Game) Draw(screen *ebiten.Image) {
g.state.draw(screen)
}
func (s *state) draw(screen *ebiten.Image) {
screen.Fill(backgroundColor)
s.hero.Draw(screen)
// 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}
staminaColor := staminaNormalColor
if s.hero.Stamina < s.hero.MaxStamina*staminaLowThreshold {
staminaColor = staminaLowColor
}
staminaMeter := status.Meter{
@@ -166,8 +213,11 @@ func (s *state) draw(screen *ebiten.Image) {
}
s.hud.Draw(screen, []status.Meter{staminaMeter})
// Draw pause menu if paused
if s.gameState == statePaused {
s.pauseMenu.Draw(screen, ScreenWidth, ScreenHeight)
}
}
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return ScreenWidth, ScreenHeight
}