Added proper taggins for gravity

This commit is contained in:
2025-11-26 00:27:28 -07:00
parent a9b2a3b7ff
commit c70f85abe5
4 changed files with 118 additions and 24 deletions

View File

@@ -13,10 +13,10 @@ const (
// Physics // Physics
const ( const (
Gravity = 1400.0 Gravity = 1400.0
JumpStrength = -480.0 JumpStrength = -580.0
MaxFallSpeed = 900.0 MaxFallSpeed = 900.0
GroundFriction = 0.82 GroundFriction = 0.82
AirFriction = 0.96 AirFriction = 0.86
) )
// Gameplay // Gameplay

View File

@@ -7,6 +7,7 @@ import (
"github.com/atridad/LilGuy/internal/config" "github.com/atridad/LilGuy/internal/config"
"github.com/atridad/LilGuy/internal/projectile" "github.com/atridad/LilGuy/internal/projectile"
"github.com/atridad/LilGuy/internal/world"
) )
const ( const (
@@ -49,6 +50,14 @@ const (
DirRight DirRight
) )
// Tags
type Tag int
const (
TagGravity Tag = iota
)
// Hero state // Hero state
type Hero struct { type Hero struct {
@@ -63,6 +72,8 @@ type Hero struct {
Color color.NRGBA Color color.NRGBA
Tags map[Tag]bool
Stamina float64 Stamina float64
MaxStamina float64 MaxStamina float64
StaminaDrain float64 StaminaDrain float64
@@ -118,6 +129,7 @@ func New(cfg Config) *Hero {
Radius: cfg.Radius, Radius: cfg.Radius,
Speed: cfg.Speed, Speed: cfg.Speed,
Color: cfg.Color, Color: cfg.Color,
Tags: map[Tag]bool{TagGravity: true},
Stamina: cfg.MaxStamina, Stamina: cfg.MaxStamina,
MaxStamina: cfg.MaxStamina, MaxStamina: cfg.MaxStamina,
StaminaDrain: cfg.StaminaDrain, StaminaDrain: cfg.StaminaDrain,
@@ -136,42 +148,69 @@ func New(cfg Config) *Hero {
} }
} }
func (h *Hero) Update(input Input, dt float64, bounds Bounds) { func (h *Hero) Update(input Input, dt float64, bounds Bounds, w *world.World) {
if dt > 0.1 { if dt > 0.1 {
dt = 0.1 dt = 0.1
} }
h.updateMovement(input, dt, bounds) h.updateMovement(input, dt, bounds, w)
h.updateStamina(input, dt) h.updateStamina(input, dt)
h.updateAnimation(dt) h.updateAnimation(dt)
} }
// Movement and physics // Movement and physics
func (h *Hero) updateMovement(input Input, dt float64, bounds Bounds) { func (h *Hero) updateMovement(input Input, dt float64, bounds Bounds, w *world.World) {
// apply gravity if h.HasTag(TagGravity) {
h.VelocityY += config.Gravity * dt h.VelocityY += config.Gravity * dt
}
if h.VelocityY > config.MaxFallSpeed { if h.VelocityY > config.MaxFallSpeed {
h.VelocityY = config.MaxFallSpeed h.VelocityY = config.MaxFallSpeed
} }
newY := h.Y + h.VelocityY*dt newY := h.Y + h.VelocityY*dt
wasGrounded := h.isGrounded h.isGrounded = false
if newY >= bounds.Ground {
h.Y = bounds.Ground if w != nil && h.VelocityY >= 0 {
h.VelocityY = 0 feetX := h.X
h.isGrounded = true var landedSurface *world.Surface
} else {
h.Y = newY for _, s := range w.Surfaces {
h.isGrounded = false if !s.IsWalkable() {
continue
}
if feetX >= s.X && feetX <= s.X+s.Width {
if h.Y <= s.Y && newY >= s.Y {
if landedSurface == nil || s.Y < landedSurface.Y {
landedSurface = s
}
}
}
}
if landedSurface != nil {
newY = landedSurface.Y
h.VelocityY = 0
h.isGrounded = true
}
} }
if input.Jump && (h.isGrounded || (!wasGrounded && h.isGrounded)) { if !h.isGrounded {
if newY >= bounds.Ground {
newY = bounds.Ground
h.VelocityY = 0
h.isGrounded = true
}
}
h.Y = newY
if input.Jump && h.isGrounded {
h.VelocityY = config.JumpStrength h.VelocityY = config.JumpStrength
h.isGrounded = false h.isGrounded = false
} }
// horizontal input
targetVelocityX := 0.0 targetVelocityX := 0.0
if input.Left { if input.Left {
targetVelocityX -= h.Speed targetVelocityX -= h.Speed
@@ -184,7 +223,6 @@ func (h *Hero) updateMovement(input Input, dt float64, bounds Bounds) {
h.isMoving = targetVelocityX != 0 h.isMoving = targetVelocityX != 0
// sprinting
h.isSprinting = input.Sprint && h.canSprint && h.Stamina > 0 && h.isMoving h.isSprinting = input.Sprint && h.canSprint && h.Stamina > 0 && h.isMoving
if h.isSprinting { if h.isSprinting {
targetVelocityX *= config.SprintSpeedMultiplier targetVelocityX *= config.SprintSpeedMultiplier
@@ -329,6 +367,27 @@ func (h *Hero) getCurrentSprite() *ebiten.Image {
return getKnightSprite(h.direction, h.isMoving, h.animFrame) return getKnightSprite(h.direction, h.isMoving, h.animFrame)
} }
func (h *Hero) AddTag(tag Tag) {
if h.Tags == nil {
h.Tags = make(map[Tag]bool)
}
h.Tags[tag] = true
}
func (h *Hero) RemoveTag(tag Tag) {
if h.Tags == nil {
return
}
delete(h.Tags, tag)
}
func (h *Hero) HasTag(tag Tag) bool {
if h.Tags == nil {
return false
}
return h.Tags[tag]
}
func (h *Hero) GetDirection() Direction { func (h *Hero) GetDirection() Direction {
return h.direction return h.direction
} }

View File

@@ -13,13 +13,48 @@ func CreatePlains(screenWidth, screenHeight float64) *Map {
m.BackgroundColor = color.NRGBA{R: 135, G: 206, B: 235, A: 255} m.BackgroundColor = color.NRGBA{R: 135, G: 206, B: 235, A: 255}
// ground surface // ground surface
groundColor := color.NRGBA{R: 34, G: 139, B: 34, A: 255}
m.World.AddSurface(&world.Surface{ m.World.AddSurface(&world.Surface{
X: 0, X: 0,
Y: screenHeight - config.GroundHeight, Y: screenHeight - config.GroundHeight,
Width: screenWidth, Width: screenWidth,
Height: config.GroundHeight, Height: config.GroundHeight,
Tag: world.TagGround, Tag: world.TagGround,
Color: color.NRGBA{R: 34, G: 139, B: 34, A: 255}, Color: groundColor,
})
// Platforms
// Use ground color by default as requested
platformColor := groundColor
// Platform 1: Low left
m.World.AddSurface(&world.Surface{
X: 100,
Y: screenHeight - 120,
Width: 150,
Height: 20,
Tag: world.TagPlatform,
Color: platformColor,
})
// Platform 2: Mid center
m.World.AddSurface(&world.Surface{
X: 350,
Y: screenHeight - 200,
Width: 200,
Height: 20,
Tag: world.TagPlatform,
Color: platformColor,
})
// Platform 3: High right
m.World.AddSurface(&world.Surface{
X: 650,
Y: screenHeight - 280,
Width: 150,
Height: 20,
Tag: world.TagPlatform,
Color: platformColor,
}) })
// left portal to desert // left portal to desert

View File

@@ -119,7 +119,7 @@ func (g *GameplayScreen) Update(input GameplayInput, delta time.Duration) {
Right: input.Right, Right: input.Right,
Jump: input.Jump, Jump: input.Jump,
Sprint: input.Sprint, Sprint: input.Sprint,
}, dt, g.bounds) }, dt, g.bounds, g.world)
if input.Shoot { if input.Shoot {
direction := 1.0 direction := 1.0