Add local match support
This commit is contained in:
parent
0cd961dd83
commit
cf1be8e89d
105
game/game.go
105
game/game.go
|
@ -95,7 +95,9 @@ func (g *Game) Layout(_, _ int) (screenWidth, screenHeight int) {
|
|||
func (g *Game) startLocalGame() {
|
||||
log.Println("Playing against the computer")
|
||||
|
||||
// TODO
|
||||
world.Local = true
|
||||
world.ConnectionActive = true
|
||||
world.ConnectPromptVisible = false
|
||||
}
|
||||
|
||||
func (g *Game) startNetworkGame() {
|
||||
|
@ -191,28 +193,28 @@ func (g *Game) ReadInputs() InputBits {
|
|||
var in InputBits
|
||||
|
||||
if ebiten.IsKeyPressed(ebiten.KeyArrowUp) || ebiten.IsKeyPressed(ebiten.KeyW) {
|
||||
in.setButton(ButtonUp)
|
||||
in.setButtonOn(ButtonUp)
|
||||
}
|
||||
if ebiten.IsKeyPressed(ebiten.KeyArrowDown) || ebiten.IsKeyPressed(ebiten.KeyS) {
|
||||
in.setButton(ButtonDown)
|
||||
in.setButtonOn(ButtonDown)
|
||||
}
|
||||
if ebiten.IsKeyPressed(ebiten.KeyArrowLeft) || ebiten.IsKeyPressed(ebiten.KeyA) {
|
||||
in.setButton(ButtonLeft)
|
||||
in.setButtonOn(ButtonLeft)
|
||||
}
|
||||
if ebiten.IsKeyPressed(ebiten.KeyArrowRight) || ebiten.IsKeyPressed(ebiten.KeyD) {
|
||||
in.setButton(ButtonRight)
|
||||
in.setButtonOn(ButtonRight)
|
||||
}
|
||||
|
||||
if ebiten.IsKeyPressed(ebiten.KeyH) {
|
||||
in.setButton(ButtonPunch)
|
||||
in.setButtonOn(ButtonPunch)
|
||||
}
|
||||
|
||||
if ebiten.IsKeyPressed(ebiten.KeyL) {
|
||||
in.setButton(ButtonTaunt)
|
||||
in.setButtonOn(ButtonTaunt)
|
||||
}
|
||||
|
||||
if ebiten.IsKeyPressed(ebiten.KeyEnter) {
|
||||
in.setButton(ButtonStart)
|
||||
in.setButtonOn(ButtonStart)
|
||||
}
|
||||
|
||||
return in
|
||||
|
@ -306,6 +308,8 @@ func (g *Game) applyPhysics() {
|
|||
} else {
|
||||
p.X = o.X + component.PlayerSize
|
||||
}
|
||||
|
||||
p.VX, o.VX = o.VX, p.VX // TODO
|
||||
}
|
||||
|
||||
if g.Winner == 0 && p.Y < -world.GroundHeight {
|
||||
|
@ -341,6 +345,38 @@ func (g *Game) UpdateByInputs(inputs []InputBits) {
|
|||
g.Players[i].VY = g.Players[i].VY * 0.8
|
||||
|
||||
if g.Players[i].Action == component.ActionIdle {
|
||||
if input.isButtonOn(ButtonTaunt) {
|
||||
var tauntAction component.PlayerAction
|
||||
switch {
|
||||
case input.isButtonOn(ButtonUp):
|
||||
tauntAction = component.ActionTaunt1
|
||||
case input.isButtonOn(ButtonRight):
|
||||
tauntAction = component.ActionTaunt2
|
||||
case input.isButtonOn(ButtonDown):
|
||||
tauntAction = component.ActionTaunt3
|
||||
case input.isButtonOn(ButtonLeft):
|
||||
tauntAction = component.ActionTaunt4
|
||||
}
|
||||
if tauntAction != 0 {
|
||||
g.Players[i].Action = tauntAction
|
||||
g.Players[i].ActionTicksLeft = len(component.AllPlayerFrames[tauntAction])
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if input.isButtonOn(ButtonPunch) {
|
||||
if !g.Players[i].NoPunch {
|
||||
g.Players[i].Action = component.ActionPunch
|
||||
g.Players[i].ActionTicksLeft = len(component.AllPlayerFrames[component.ActionPunch]) // TODO
|
||||
|
||||
g.Players[i].NoPunch = true
|
||||
|
||||
continue
|
||||
}
|
||||
} else if g.Players[i].NoPunch {
|
||||
g.Players[i].NoPunch = false
|
||||
}
|
||||
|
||||
if input.isButtonOn(ButtonUp) && !component.TranslateRect(playerRect, 0, -1).Overlaps(oppRect) {
|
||||
var grounded bool
|
||||
for _, physRect := range world.PhysicsRects {
|
||||
|
@ -363,34 +399,6 @@ func (g *Game) UpdateByInputs(inputs []InputBits) {
|
|||
if input.isButtonOn(ButtonRight) && !component.TranslateRect(playerRect, 1, 0).Overlaps(oppRect) {
|
||||
g.Players[i].VX = 1
|
||||
}
|
||||
|
||||
if input.isButtonOn(ButtonPunch) {
|
||||
if !g.Players[i].NoPunch {
|
||||
g.Players[i].Action = component.ActionPunch
|
||||
g.Players[i].ActionTicksLeft = len(component.AllPlayerFrames[component.ActionPunch]) // TODO
|
||||
|
||||
g.Players[i].NoPunch = true
|
||||
|
||||
continue
|
||||
}
|
||||
} else if g.Players[i].NoPunch {
|
||||
g.Players[i].NoPunch = false
|
||||
}
|
||||
|
||||
if input.isButtonOn(ButtonTaunt) {
|
||||
switch {
|
||||
case input.isButtonOn(ButtonRight):
|
||||
g.Players[i].Action = component.ActionTaunt2
|
||||
case input.isButtonOn(ButtonDown):
|
||||
g.Players[i].Action = component.ActionTaunt3
|
||||
case input.isButtonOn(ButtonLeft):
|
||||
g.Players[i].Action = component.ActionTaunt4
|
||||
default: // ButtonUp or no direction specified
|
||||
g.Players[i].Action = component.ActionTaunt1
|
||||
}
|
||||
g.Players[i].ActionTicksLeft = len(component.AllPlayerFrames[g.Players[i].Action])
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// TODO player starts in idle action?
|
||||
|
@ -469,6 +477,17 @@ func (g *Game) playerStateUpdated() {
|
|||
world.Winner = g.Winner
|
||||
}
|
||||
|
||||
func (g *Game) RunLocalFrame() {
|
||||
inputs := make([]InputBits, 2)
|
||||
inputs[0] = g.ReadInputs()
|
||||
if world.Mirror || true {
|
||||
inputs[1] = mirrorInput(inputs[0])
|
||||
}
|
||||
g.UpdateByInputs(inputs)
|
||||
|
||||
g.playerStateUpdated()
|
||||
}
|
||||
|
||||
func (g *Game) RunFrame() {
|
||||
input := g.ReadInputs()
|
||||
buffer := encodeInputs(input)
|
||||
|
@ -568,12 +587,16 @@ func (g *Game) Update() error {
|
|||
}
|
||||
|
||||
if world.ConnectionActive {
|
||||
err := world.Backend.Idle(0)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if !world.Local {
|
||||
err := world.Backend.Idle(0)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
g.RunFrame()
|
||||
g.RunFrame()
|
||||
} else {
|
||||
g.RunLocalFrame()
|
||||
}
|
||||
}
|
||||
|
||||
err := gohan.Update()
|
||||
|
|
|
@ -29,10 +29,14 @@ func (i *InputBits) isButtonOn(button InputButton) bool {
|
|||
return *i&(1<<button) > 0
|
||||
}
|
||||
|
||||
func (i *InputBits) setButton(button InputButton) {
|
||||
func (i *InputBits) setButtonOn(button InputButton) {
|
||||
*i |= 1 << button
|
||||
}
|
||||
|
||||
func (i *InputBits) setButtonOff(button InputButton) {
|
||||
*i &^= 1 << button
|
||||
}
|
||||
|
||||
func readI32(b []byte) int32 {
|
||||
if len(b) < 4 {
|
||||
return 0
|
||||
|
@ -98,3 +102,34 @@ func encodeInputsGob(inputs Input) []byte {
|
|||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func mirrorInput(inputs InputBits) InputBits {
|
||||
left, right := inputs.isButtonOn(ButtonRight), inputs.isButtonOn(ButtonLeft)
|
||||
down, up := inputs.isButtonOn(ButtonUp), inputs.isButtonOn(ButtonDown)
|
||||
|
||||
if left {
|
||||
inputs.setButtonOn(ButtonLeft)
|
||||
} else {
|
||||
inputs.setButtonOff(ButtonLeft)
|
||||
}
|
||||
|
||||
if right {
|
||||
inputs.setButtonOn(ButtonRight)
|
||||
} else {
|
||||
inputs.setButtonOff(ButtonRight)
|
||||
}
|
||||
|
||||
if down {
|
||||
inputs.setButtonOn(ButtonDown)
|
||||
} else {
|
||||
inputs.setButtonOff(ButtonDown)
|
||||
}
|
||||
|
||||
if up {
|
||||
inputs.setButtonOn(ButtonUp)
|
||||
} else {
|
||||
inputs.setButtonOff(ButtonUp)
|
||||
}
|
||||
|
||||
return inputs
|
||||
}
|
||||
|
|
|
@ -226,7 +226,7 @@ func (u *UISystem) Draw(e gohan.Entity, screen *ebiten.Image) error {
|
|||
if p.ActionTicksLeft != 0 {
|
||||
// Draw a rect over stunned players.
|
||||
if p.Action == component.ActionStunned {
|
||||
playerRect := world.FloatRect(p.X, p.Y, p.X+float64(component.PlayerSize), p.Y+float64(component.PlayerSize))
|
||||
playerRect := world.FloatRect(p.X, p.Y, p.X+float64(component.PlayerWidth), p.Y+float64(component.PlayerHeight))
|
||||
|
||||
fillColor := color.RGBA{123, 30, 255, 255}
|
||||
u.drawBox(screen, fillColor, playerRect)
|
||||
|
@ -291,7 +291,7 @@ func (u *UISystem) Draw(e gohan.Entity, screen *ebiten.Image) error {
|
|||
if world.Debug != 0 {
|
||||
var ping int64
|
||||
var framesBehind float64
|
||||
if !world.ConnectPromptVisible {
|
||||
if !world.ConnectPromptVisible && !world.Local {
|
||||
p1Stats, err := world.Backend.GetNetworkStats(ggpo.PlayerHandle(1))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network stats for player 1: %s", err)
|
||||
|
|
|
@ -50,6 +50,9 @@ var (
|
|||
|
||||
CurrentPlayer = 1
|
||||
|
||||
Local bool // Playing against computer
|
||||
Mirror bool // AI should mirror player movements
|
||||
|
||||
Backend ggpo.Backend
|
||||
|
||||
// These variables are cached to prevent race conditions.
|
||||
|
|
Loading…
Reference in New Issue