|
|
|
@ -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)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|