Using a temp free online sprite for now to test sprites
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user