|
|
|
@ -19,10 +19,6 @@ import (
|
|
|
|
|
"github.com/hajimehoshi/ebiten/v2/inpututil" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
var backend ggpo.Backend |
|
|
|
|
|
|
|
|
|
var currentPlayer = 1 |
|
|
|
|
|
|
|
|
|
type Game struct { |
|
|
|
|
Players []component.Player |
|
|
|
|
} |
|
|
|
@ -30,18 +26,23 @@ type Game struct {
|
|
|
|
|
var addedGame bool |
|
|
|
|
|
|
|
|
|
func NewGame() (*Game, error) { |
|
|
|
|
var player1 = component.Player{ |
|
|
|
|
X: 50, |
|
|
|
|
Y: 50, |
|
|
|
|
Color: color.RGBA{255, 0, 0, 255}, |
|
|
|
|
PlayerNum: 1, |
|
|
|
|
player1 := component.Player{ |
|
|
|
|
PlayerNum: 1, |
|
|
|
|
Color: color.RGBA{255, 0, 0, 255}, |
|
|
|
|
Action: component.ActionIdle, |
|
|
|
|
ActionTicksLeft: 1, |
|
|
|
|
X: 50, |
|
|
|
|
Y: 50, |
|
|
|
|
} |
|
|
|
|
var player2 = component.Player{ |
|
|
|
|
X: 150, |
|
|
|
|
Y: 50, |
|
|
|
|
Color: color.RGBA{0, 0, 255, 255}, |
|
|
|
|
PlayerNum: 2, |
|
|
|
|
player2 := component.Player{ |
|
|
|
|
PlayerNum: 2, |
|
|
|
|
Color: color.RGBA{0, 0, 255, 255}, |
|
|
|
|
Action: component.ActionIdle, |
|
|
|
|
ActionTicksLeft: 1, |
|
|
|
|
X: 150, |
|
|
|
|
Y: 50, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
g := &Game{ |
|
|
|
|
Players: []component.Player{player1, player2}, |
|
|
|
|
} |
|
|
|
@ -78,68 +79,78 @@ func (g *Game) Layout(_, _ int) (screenWidth, screenHeight int) {
|
|
|
|
|
return world.ScreenWidth, world.ScreenHeight |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (g *Game) Update() error { |
|
|
|
|
if ebiten.IsWindowBeingClosed() || (!world.WASM && ebiten.IsKeyPressed(ebiten.KeyEscape)) { |
|
|
|
|
g.Exit() |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
func (g *Game) startLocalGame() { |
|
|
|
|
log.Println("Playing against the computer") |
|
|
|
|
|
|
|
|
|
if world.ConnectPromptConfirmed && !world.ConnectPromptActive { |
|
|
|
|
address := "" |
|
|
|
|
port := world.ConnectPromptText |
|
|
|
|
if strings.ContainsRune(port, ':') { |
|
|
|
|
split := strings.Split(port, ":") |
|
|
|
|
if len(split) == 2 { |
|
|
|
|
address = split[0] |
|
|
|
|
port = split[1] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
p, err := strconv.Atoi(port) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Fatalf("failed to read port: %s", err) |
|
|
|
|
// TODO
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (g *Game) startNetworkGame() { |
|
|
|
|
address := "" |
|
|
|
|
port := world.ConnectPromptText |
|
|
|
|
if strings.ContainsRune(port, ':') { |
|
|
|
|
split := strings.Split(port, ":") |
|
|
|
|
if len(split) == 2 { |
|
|
|
|
address = split[0] |
|
|
|
|
port = split[1] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
p, err := strconv.Atoi(port) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Fatalf("failed to read port: %s", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
log.Println("start networking") |
|
|
|
|
localPort := world.LocalPort |
|
|
|
|
if localPort == 0 { |
|
|
|
|
localPort = p + 1 |
|
|
|
|
} |
|
|
|
|
if world.LocalPort != 0 { |
|
|
|
|
log.Printf("Client port for connection: %d", world.LocalPort) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
localPort := world.LocalPort |
|
|
|
|
if localPort == 0 { |
|
|
|
|
localPort = p + 1 |
|
|
|
|
} |
|
|
|
|
numPlayers := 2 |
|
|
|
|
playerSize := 20 |
|
|
|
|
|
|
|
|
|
numPlayers := 2 |
|
|
|
|
playerSize := 20 |
|
|
|
|
players := make([]ggpo.Player, numPlayers) |
|
|
|
|
if world.ConnectPromptHost { |
|
|
|
|
log.Printf("Hosting at " + address + ":" + port + "...") |
|
|
|
|
players := make([]ggpo.Player, numPlayers) |
|
|
|
|
if world.ConnectPromptHost { |
|
|
|
|
log.Printf("Hosting at " + address + ":" + port + "...") |
|
|
|
|
|
|
|
|
|
players[0] = ggpo.NewLocalPlayer(playerSize, 1) |
|
|
|
|
players[1] = ggpo.NewRemotePlayer(playerSize, 2, "127.0.0.1", localPort) |
|
|
|
|
} else { |
|
|
|
|
log.Printf("Connecting to " + address + ":" + port + "...") |
|
|
|
|
players[0] = ggpo.NewLocalPlayer(playerSize, 1) |
|
|
|
|
players[1] = ggpo.NewRemotePlayer(playerSize, 2, "127.0.0.1", localPort) |
|
|
|
|
} else { |
|
|
|
|
log.Printf("Connecting to " + address + ":" + port + "...") |
|
|
|
|
|
|
|
|
|
players[0] = ggpo.NewRemotePlayer(playerSize, 1, address, p) |
|
|
|
|
players[1] = ggpo.NewLocalPlayer(playerSize, 2) |
|
|
|
|
currentPlayer = 2 |
|
|
|
|
} |
|
|
|
|
world.CurrentPlayer = 2 |
|
|
|
|
players[0] = ggpo.NewRemotePlayer(playerSize, 1, address, p) |
|
|
|
|
players[1] = ggpo.NewLocalPlayer(playerSize, 2) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if world.LocalPort != 0 { |
|
|
|
|
log.Printf("Client port for connection: %d", world.LocalPort) |
|
|
|
|
} |
|
|
|
|
l := p |
|
|
|
|
if !world.ConnectPromptHost { |
|
|
|
|
l = localPort |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
l := p |
|
|
|
|
if !world.ConnectPromptHost { |
|
|
|
|
l = localPort |
|
|
|
|
} |
|
|
|
|
g.InitNetworking(l, numPlayers, players, 0) |
|
|
|
|
|
|
|
|
|
g.InitNetworking(l, numPlayers, players, 0) |
|
|
|
|
world.ConnectionActive = true |
|
|
|
|
} |
|
|
|
|
func (g *Game) Update() error { |
|
|
|
|
if ebiten.IsWindowBeingClosed() || (!world.WASM && ebiten.IsKeyPressed(ebiten.KeyEscape)) { |
|
|
|
|
g.Exit() |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if world.ConnectPromptConfirmed && !world.ConnectionActive { |
|
|
|
|
if world.ConnectPromptText == "" { |
|
|
|
|
g.startLocalGame() |
|
|
|
|
} else { |
|
|
|
|
g.startNetworkGame() |
|
|
|
|
} |
|
|
|
|
g.playerStateUpdated() |
|
|
|
|
|
|
|
|
|
world.ConnectPromptActive = true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if world.ConnectPromptActive { |
|
|
|
|
err := backend.Idle(0) // TODO Why 0?
|
|
|
|
|
if world.ConnectionActive { |
|
|
|
|
err := world.Backend.Idle(0) |
|
|
|
|
if err != nil { |
|
|
|
|
panic(err) |
|
|
|
|
} |
|
|
|
@ -174,8 +185,8 @@ func (g *Game) InitNetworking(localPort int, numPlayers int, players []ggpo.Play
|
|
|
|
|
|
|
|
|
|
peer := ggpo.NewPeer(session, localPort, numPlayers, inputSize) |
|
|
|
|
//peer := ggpo.NewSyncTest(&session, numPlayers, 8, inputSize, true)
|
|
|
|
|
backend = &peer |
|
|
|
|
session.backend = backend |
|
|
|
|
world.Backend = &peer |
|
|
|
|
session.backend = world.Backend |
|
|
|
|
peer.InitializeConnection() |
|
|
|
|
peer.Start() |
|
|
|
|
|
|
|
|
@ -186,13 +197,13 @@ func (g *Game) InitNetworking(localPort int, numPlayers int, players []ggpo.Play
|
|
|
|
|
var handle ggpo.PlayerHandle |
|
|
|
|
result = peer.AddPlayer(&players[i], &handle) |
|
|
|
|
if players[i].PlayerType == ggpo.PlayerTypeLocal { |
|
|
|
|
currentPlayer = int(handle) |
|
|
|
|
world.CurrentPlayer = int(handle) |
|
|
|
|
} |
|
|
|
|
if result != nil { |
|
|
|
|
log.Fatalf("There's an issue from AddPlayer") |
|
|
|
|
} |
|
|
|
|
if players[i].PlayerType == ggpo.PlayerTypeLocal { |
|
|
|
|
peer.SetFrameDelay(handle, FRAME_DELAY) |
|
|
|
|
peer.SetFrameDelay(handle, frameDelay) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
peer.SetDisconnectTimeout(3000) |
|
|
|
@ -204,7 +215,7 @@ func (g *Game) RunFrame() {
|
|
|
|
|
buffer := encodeInputs(input) |
|
|
|
|
|
|
|
|
|
//fmt.Println("Attempting to add local inputs")
|
|
|
|
|
result := backend.AddLocalInput(ggpo.PlayerHandle(currentPlayer), buffer, len(buffer)) |
|
|
|
|
result := world.Backend.AddLocalInput(ggpo.PlayerHandle(world.CurrentPlayer), buffer, len(buffer)) |
|
|
|
|
|
|
|
|
|
//fmt.Println("Attempt to add local inputs complete")
|
|
|
|
|
if result == nil { |
|
|
|
@ -213,7 +224,7 @@ func (g *Game) RunFrame() {
|
|
|
|
|
disconnectFlags := 0 |
|
|
|
|
|
|
|
|
|
//fmt.Println("Attempting to synchronize inputs")
|
|
|
|
|
values, result = backend.SyncInput(&disconnectFlags) |
|
|
|
|
values, result = world.Backend.SyncInput(&disconnectFlags) |
|
|
|
|
if result == nil { |
|
|
|
|
//fmt.Println("Attempt synchronize inputs was sucessful")
|
|
|
|
|
inputs := decodeInputs(values) |
|
|
|
@ -225,25 +236,17 @@ func (g *Game) RunFrame() {
|
|
|
|
|
} else { |
|
|
|
|
//fmt.Printf("Attempt to add local inputs unsuccessful: %s\n", result)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
g.playerStateUpdated() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (g *Game) AdvanceFrame(inputs []InputBits, disconnectFlags int) { |
|
|
|
|
g.UpdateByInputs(inputs) |
|
|
|
|
err := backend.AdvanceFrame(uint32(g.Checksum())) |
|
|
|
|
|
|
|
|
|
err := world.Backend.AdvanceFrame(uint32(g.Checksum())) |
|
|
|
|
if err != nil { |
|
|
|
|
panic(err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for i := range g.Players { |
|
|
|
|
if g.Players[i].ActionTicksLeft != 0 { |
|
|
|
|
g.Players[i].ActionTicksLeft-- |
|
|
|
|
if g.Players[i].ActionTicksLeft == 0 { |
|
|
|
|
g.Players[i].Action = component.ActionIdle |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
g.playerStateUpdated() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (g *Game) UpdateByInputs(inputs []InputBits) { |
|
|
|
@ -264,7 +267,23 @@ func (g *Game) UpdateByInputs(inputs []InputBits) {
|
|
|
|
|
if g.Players[i].Action == component.ActionIdle { |
|
|
|
|
if input.isButtonOn(ButtonPunch) { |
|
|
|
|
g.Players[i].Action = component.ActionPunch |
|
|
|
|
g.Players[i].ActionTicksLeft = 25 // TODO
|
|
|
|
|
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)
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|