From 1dfe1a004c32d9b5051b04796a8cd4f470304d26 Mon Sep 17 00:00:00 2001 From: Trevor Slocum Date: Fri, 13 Jan 2023 15:49:45 -0800 Subject: [PATCH] Add jumping --- component/player.go | 4 +- game/game.go | 230 ++++++++++++++++++++++++-------------------- world/world.go | 2 +- 3 files changed, 128 insertions(+), 108 deletions(-) diff --git a/component/player.go b/component/player.go index 03148e2..ebfbb8d 100644 --- a/component/player.go +++ b/component/player.go @@ -82,8 +82,8 @@ var AllPlayerFrames = [][][]FrameData{ } type Player struct { - X float64 - Y float64 + X, Y float64 + VX, VY float64 Color color.Color PlayerNum int diff --git a/game/game.go b/game/game.go index 3663e8d..c19f264 100644 --- a/game/game.go +++ b/game/game.go @@ -136,10 +136,6 @@ func (g *Game) startNetworkGame() { world.ConnectionActive = true } -func (g *Game) playerStateUpdated() { - world.Player1, world.Player2 = g.Players[0], g.Players[1] -} - func (g *Game) InitNetworking(localPort int, numPlayers int, players []ggpo.Player, numSpectators int) { var result error var inputBits InputBits = 0 @@ -174,6 +170,122 @@ func (g *Game) InitNetworking(localPort int, numPlayers int, players []ggpo.Play peer.SetDisconnectNotifyStart(1000) } +func (g *Game) ReadInputs() InputBits { + var in InputBits + + if ebiten.IsKeyPressed(ebiten.KeyArrowUp) || ebiten.IsKeyPressed(ebiten.KeyW) { + in.setButton(ButtonUp) + } + if ebiten.IsKeyPressed(ebiten.KeyArrowDown) || ebiten.IsKeyPressed(ebiten.KeyS) { + in.setButton(ButtonDown) + } + if ebiten.IsKeyPressed(ebiten.KeyArrowLeft) || ebiten.IsKeyPressed(ebiten.KeyA) { + in.setButton(ButtonLeft) + } + if ebiten.IsKeyPressed(ebiten.KeyArrowRight) || ebiten.IsKeyPressed(ebiten.KeyD) { + in.setButton(ButtonRight) + } + + if inpututil.IsKeyJustPressed(ebiten.KeyH) { + in.setButton(ButtonPunch) + } + + return in +} + +func (g *Game) applyPhysics() { + for i := 0; i < 2; i++ { + p := &g.Players[i] + + // Apply gravity. + if p.VY > -world.Gravity { + p.VY -= 1 + if p.VY < -world.Gravity { + p.VY = -world.Gravity + } + } + + // Apply velocity. + p.X, p.Y = p.X+p.VX, p.Y+p.VY + + // TODO check player collision. + + // Apply ground collision. + if p.Y-component.PlayerSize < 0 { + p.Y = component.PlayerSize + } + } +} + +func (g *Game) UpdateByInputs(inputs []InputBits) { + for i, input := range inputs { + opp := 0 + if i == 0 { + opp = 1 + } + 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)) + + g.Players[i].VX = g.Players[i].VX * 0.8 + g.Players[i].VY = g.Players[i].VY * 0.8 + + if input.isButtonOn(ButtonUp) && !component.TranslateRect(playerRect, 0, -1).Overlaps(oppRect) { + grounded := g.Players[i].Y == float64(component.PlayerSize) + // TODO check when last jump, grounded + if grounded { + g.Players[i].VY = 20 + } + log.Println("JUMP", grounded) + } + if input.isButtonOn(ButtonDown) && !component.TranslateRect(playerRect, 0, 1).Overlaps(oppRect) { + //g.Players[i].VY = -1 + // TODO crouch + } + if input.isButtonOn(ButtonLeft) && !component.TranslateRect(playerRect, -1, 0).Overlaps(oppRect) { + g.Players[i].VX = -1 + } + if input.isButtonOn(ButtonRight) && !component.TranslateRect(playerRect, 1, 0).Overlaps(oppRect) { + g.Players[i].VX = 1 + } + + if g.Players[i].Action == component.ActionIdle { + if input.isButtonOn(ButtonPunch) { + g.Players[i].Action = component.ActionPunch + g.Players[i].ActionTicksLeft = len(component.AllPlayerFrames[component.ActionPunch]) // TODO + continue + } + } + + if g.Players[i].ActionTicksLeft != 0 { + g.Players[i].ActionTicksLeft-- + if g.Players[i].ActionTicksLeft == 0 { + g.Players[i].Action = component.ActionIdle + g.Players[i].ActionTicksLeft = len(component.AllPlayerFrames[component.ActionIdle]) // TODO + } + + // TODO Apply hitboxes + if g.Players[i].ActionTicksLeft != 0 { + //frameNum := g.Players[i].ActionTicksLeft - 1 + //frame := component.AllPlayerFrames[g.Players[i].Action][frameNum] + //log.Printf("frame %+v", frame) + } + } + } + + g.applyPhysics() +} + +func (g *Game) ReadInputsP2() InputBits { + var in InputBits + + // TODO Support local multiplayer? + return in +} + +func (g *Game) playerStateUpdated() { + world.Player1, world.Player2 = g.Players[0], g.Players[1] +} + func (g *Game) RunFrame() { input := g.ReadInputs() buffer := encodeInputs(input) @@ -204,107 +316,6 @@ func (g *Game) RunFrame() { g.playerStateUpdated() } -func (g *Game) AdvanceFrame(inputs []InputBits, disconnectFlags int) { - g.UpdateByInputs(inputs) - - err := world.Backend.AdvanceFrame(uint32(g.Checksum())) - if err != nil { - panic(err) - } -} - -func (g *Game) applyPhysics() { - // Apply gravity. - for i := 0; i < 2; i++ { - p := &g.Players[i] - - p.Y -= world.Gravity - if p.Y-component.PlayerSize < 0 { - p.Y = component.PlayerSize - } - } -} - -func (g *Game) UpdateByInputs(inputs []InputBits) { - for i, input := range inputs { - opp := 0 - if i == 0 { - opp = 1 - } - 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 input.isButtonOn(ButtonUp) && !component.TranslateRect(playerRect, 0, -1).Overlaps(oppRect) { - g.Players[i].Y-- - } - if input.isButtonOn(ButtonDown) && !component.TranslateRect(playerRect, 0, 1).Overlaps(oppRect) { - g.Players[i].Y++ - } - if input.isButtonOn(ButtonLeft) && !component.TranslateRect(playerRect, -1, 0).Overlaps(oppRect) { - g.Players[i].X-- - } - if input.isButtonOn(ButtonRight) && !component.TranslateRect(playerRect, 1, 0).Overlaps(oppRect) { - g.Players[i].X++ - } - - if g.Players[i].Action == component.ActionIdle { - if input.isButtonOn(ButtonPunch) { - g.Players[i].Action = component.ActionPunch - g.Players[i].ActionTicksLeft = len(component.AllPlayerFrames[component.ActionPunch]) // TODO - continue - } - } - - if g.Players[i].ActionTicksLeft != 0 { - g.Players[i].ActionTicksLeft-- - if g.Players[i].ActionTicksLeft == 0 { - g.Players[i].Action = component.ActionIdle - g.Players[i].ActionTicksLeft = len(component.AllPlayerFrames[component.ActionIdle]) // TODO - } - - // TODO Apply hitboxes - if g.Players[i].ActionTicksLeft != 0 { - //frameNum := g.Players[i].ActionTicksLeft - 1 - //frame := component.AllPlayerFrames[g.Players[i].Action][frameNum] - //log.Printf("frame %+v", frame) - } - } - } - - g.applyPhysics() -} - -func (g *Game) ReadInputs() InputBits { - var in InputBits - - if ebiten.IsKeyPressed(ebiten.KeyArrowUp) || ebiten.IsKeyPressed(ebiten.KeyW) { - in.setButton(ButtonUp) - } - if ebiten.IsKeyPressed(ebiten.KeyArrowDown) || ebiten.IsKeyPressed(ebiten.KeyS) { - in.setButton(ButtonDown) - } - if ebiten.IsKeyPressed(ebiten.KeyArrowLeft) || ebiten.IsKeyPressed(ebiten.KeyA) { - in.setButton(ButtonLeft) - } - if ebiten.IsKeyPressed(ebiten.KeyArrowRight) || ebiten.IsKeyPressed(ebiten.KeyD) { - in.setButton(ButtonRight) - } - - if inpututil.IsKeyJustPressed(ebiten.KeyH) { - in.setButton(ButtonPunch) - } - - return in -} - -func (g *Game) ReadInputsP2() InputBits { - var in InputBits - - // TODO Support local multiplayer? - return in - -} - func (g *Game) Checksum() int { h := sha1.New() h.Write([]byte(g.String())) @@ -316,6 +327,15 @@ func (g *Game) Checksum() int { return sum } +func (g *Game) AdvanceFrame(inputs []InputBits, disconnectFlags int) { + g.UpdateByInputs(inputs) + + err := world.Backend.AdvanceFrame(uint32(g.Checksum())) + if err != nil { + panic(err) + } +} + func (g *Game) Update() error { if ebiten.IsWindowBeingClosed() || (!world.WASM && ebiten.IsKeyPressed(ebiten.KeyEscape)) { g.Exit() diff --git a/world/world.go b/world/world.go index e49cd58..63fc17b 100644 --- a/world/world.go +++ b/world/world.go @@ -15,7 +15,7 @@ const ( InternalScreenWidth, InternalScreenHeight = 854, 480 - Gravity = 1.0 + Gravity = 8.0 GroundHeight = 100 // TODO