Apply physics calculations using map rects
This commit is contained in:
parent
843c254cec
commit
383cfdc182
4 changed files with 70 additions and 16 deletions
|
@ -40,6 +40,12 @@ const (
|
|||
PlayerWidth = 16
|
||||
)
|
||||
|
||||
func RectTouches(r1 image.Rectangle, r2 image.Rectangle) bool {
|
||||
return !r1.Empty() && !r2.Empty() &&
|
||||
r1.Min.X <= r2.Max.X && r2.Min.X <= r1.Max.X &&
|
||||
r1.Min.Y <= r2.Max.Y && r2.Min.Y <= r1.Max.Y
|
||||
}
|
||||
|
||||
// stdHit returns FrameData using a standard hitbox and the provided sprite.
|
||||
func stdHit(sprite *ebiten.Image) FrameData {
|
||||
return FrameData{
|
||||
|
|
71
game/game.go
71
game/game.go
|
@ -2,6 +2,7 @@ package game
|
|||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"image"
|
||||
"image/color"
|
||||
"log"
|
||||
"math"
|
||||
|
@ -204,6 +205,10 @@ func (g *Game) ReadInputs() InputBits {
|
|||
return in
|
||||
}
|
||||
|
||||
var physicsRects = []image.Rectangle{
|
||||
image.Rect(-world.GroundWidth/2, 0, world.GroundWidth/2, -world.GroundHeight),
|
||||
}
|
||||
|
||||
func (g *Game) applyPhysics() {
|
||||
for i := 0; i < 2; i++ {
|
||||
opp := 0
|
||||
|
@ -213,21 +218,68 @@ func (g *Game) applyPhysics() {
|
|||
p := &g.Players[i]
|
||||
o := &g.Players[opp]
|
||||
|
||||
// Apply gravity.
|
||||
if p.VY > -world.Gravity {
|
||||
playerRect := world.FloatRect(g.Players[i].X, g.Players[i].Y, g.Players[i].X+float64(component.PlayerSize), g.Players[i].Y+float64(component.PlayerSize))
|
||||
oppRect := world.FloatRect(g.Players[opp].X, g.Players[opp].Y, g.Players[opp].X+float64(component.PlayerSize), g.Players[opp].Y+float64(component.PlayerSize))
|
||||
|
||||
isGrounded := func() (r image.Rectangle, ok bool) {
|
||||
for _, physRect := range physicsRects {
|
||||
if component.RectTouches(playerRect, physRect) {
|
||||
return physRect, true
|
||||
}
|
||||
}
|
||||
return image.Rectangle{}, false
|
||||
}
|
||||
|
||||
// Apply velocity.
|
||||
p.X, p.Y = p.X+p.VX, p.Y+p.VY
|
||||
|
||||
// Apply ground collision.
|
||||
groundRect, grounded := isGrounded()
|
||||
if grounded {
|
||||
// Min is left, Max is right
|
||||
collideX := p.X+component.PlayerWidth >= float64(groundRect.Min.X) && p.X <= float64(groundRect.Max.X)
|
||||
|
||||
// Min is bottom, Max is top
|
||||
collideY := p.Y-component.PlayerHeight >= float64(groundRect.Min.Y) && p.Y <= float64(groundRect.Max.Y)
|
||||
|
||||
log.Println(world.CurrentPlayer, collideX, collideY)
|
||||
if collideY {
|
||||
/*if collideX {
|
||||
if p.X+component.PlayerWidth >= float64(groundRect.Min.X) {
|
||||
p.X = float64(groundRect.Min.X) - component.PlayerWidth
|
||||
} else {
|
||||
p.X = float64(groundRect.Max.X)
|
||||
}
|
||||
}*/
|
||||
if collideY {
|
||||
topDist := p.Y - float64(groundRect.Max.Y)
|
||||
bottomDist := p.Y - component.PlayerHeight - float64(groundRect.Min.Y)
|
||||
|
||||
if math.Abs(topDist) < math.Abs(bottomDist) { // Closer to top.
|
||||
p.Y = float64(groundRect.Max.Y)
|
||||
} else { // Closer to bottom.
|
||||
p.Y = float64(groundRect.Min.Y) + component.PlayerHeight
|
||||
}
|
||||
p.VY = 0
|
||||
}
|
||||
}
|
||||
} else if p.VY > -world.Gravity { // Apply gravity.
|
||||
p.VY -= math.Max(math.Abs(p.VY/2.5), 0.1)
|
||||
if p.VY < -world.Gravity {
|
||||
p.VY = -world.Gravity
|
||||
}
|
||||
}
|
||||
|
||||
// Apply velocity.
|
||||
p.X, p.Y = p.X+p.VX, p.Y+p.VY
|
||||
if p.VY != 0 {
|
||||
log.Println("VY", world.CurrentPlayer, p.VY)
|
||||
}
|
||||
|
||||
/*if grounded {
|
||||
log.Println("grounded")
|
||||
p.VY = 0 // TODO
|
||||
}*/
|
||||
|
||||
// Apply player collision.
|
||||
playerRect := world.FloatRect(g.Players[i].X, g.Players[i].Y, g.Players[i].X+float64(component.PlayerSize), g.Players[i].Y+float64(component.PlayerSize))
|
||||
oppRect := world.FloatRect(g.Players[opp].X, g.Players[opp].Y, g.Players[opp].X+float64(component.PlayerSize), g.Players[opp].Y+float64(component.PlayerSize))
|
||||
|
||||
if playerRect.Overlaps(oppRect) {
|
||||
if playerRect.Min.X < oppRect.Min.X {
|
||||
p.X = o.X - component.PlayerSize
|
||||
|
@ -235,11 +287,6 @@ func (g *Game) applyPhysics() {
|
|||
p.X = o.X + component.PlayerSize
|
||||
}
|
||||
}
|
||||
|
||||
// Apply ground collision.
|
||||
if p.Y < 0 {
|
||||
p.Y = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,13 +41,13 @@ func (s *MapSystem) Draw(e gohan.Entity, screen *ebiten.Image) error {
|
|||
|
||||
groundColor := color.RGBA{50, 50, 50, 255}
|
||||
|
||||
r := image.Rect(-world.ScreenWidth*2, -world.ScreenHeight, world.ScreenWidth*2, 0)
|
||||
r := image.Rect(-world.GroundWidth/2, -world.ScreenHeight, world.GroundWidth/2, 0)
|
||||
screen.SubImage(world.GameRectToScreen(r)).(*ebiten.Image).Fill(groundColor)
|
||||
|
||||
const groundTopHeight = 10
|
||||
groundTopColor := color.RGBA{100, 100, 100, 255}
|
||||
|
||||
r = image.Rect(-world.ScreenWidth*2, -groundTopHeight, world.ScreenWidth*2, 0)
|
||||
r = image.Rect(-world.GroundWidth/2, -groundTopHeight, world.GroundWidth/2, 0)
|
||||
screen.SubImage(world.GameRectToScreen(r)).(*ebiten.Image).Fill(groundTopColor)
|
||||
|
||||
return nil
|
||||
|
|
|
@ -19,11 +19,12 @@ const (
|
|||
|
||||
JumpVelocity = 30
|
||||
|
||||
GroundHeight = 100
|
||||
|
||||
MaxDebug = 2
|
||||
|
||||
FloatValueThreshold = 0.00000001
|
||||
|
||||
GroundWidth = 600
|
||||
GroundHeight = 100
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
Loading…
Reference in a new issue