317 lines
10 KiB
Go
317 lines
10 KiB
Go
package main
|
|
|
|
import (
|
|
"github.com/veandco/go-sdl2/sdl"
|
|
"math/rand"
|
|
"net"
|
|
)
|
|
|
|
func getUnusedColor(colors []PlayerColors, players map[uint32]*Player) uint32 {
|
|
for i, c := range colors {
|
|
foundPlayerWithColor := false
|
|
var colorCompare []uint8
|
|
clrR, clrG, clrB, clrA := c.tracks.RGBA()
|
|
colorCompare = append(colorCompare, uint8(clrR), uint8(clrG), uint8(clrB), uint8(clrA))
|
|
clrR, clrG, clrB, clrA = c.body.RGBA()
|
|
colorCompare = append(colorCompare, uint8(clrR), uint8(clrG), uint8(clrB), uint8(clrA))
|
|
clrR, clrG, clrB, clrA = c.cannon.RGBA()
|
|
colorCompare = append(colorCompare, uint8(clrR), uint8(clrG), uint8(clrB), uint8(clrA))
|
|
playersMutex.RLock()
|
|
for _, player := range players {
|
|
var playerColorsCompare []uint8
|
|
plrR, plrG, plrB, plrA := player.playerColors.tracks.RGBA()
|
|
playerColorsCompare = append(playerColorsCompare, uint8(plrR), uint8(plrG), uint8(plrB), uint8(plrA))
|
|
plrR, plrG, plrB, plrA = player.playerColors.body.RGBA()
|
|
playerColorsCompare = append(playerColorsCompare, uint8(plrR), uint8(plrG), uint8(plrB), uint8(plrA))
|
|
plrR, plrG, plrB, plrA = player.playerColors.cannon.RGBA()
|
|
playerColorsCompare = append(playerColorsCompare, uint8(plrR), uint8(plrG), uint8(plrB), uint8(plrA))
|
|
foundPlayerWithColor = false
|
|
if len(playerColorsCompare) == len(colorCompare) {
|
|
for i, c := range colorCompare {
|
|
if playerColorsCompare[i] == c {
|
|
foundPlayerWithColor = true
|
|
} else {
|
|
foundPlayerWithColor = false
|
|
break
|
|
}
|
|
}
|
|
if foundPlayerWithColor {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
playersMutex.RUnlock()
|
|
if !foundPlayerWithColor {
|
|
return uint32(i)
|
|
}
|
|
}
|
|
return uint32(len(colors) - 1)
|
|
}
|
|
|
|
func createPlayers(amount uint8, playerColors []PlayerColors, keyMaps []KeyMap, joyMaps []JoyMap, gameMap *GameMap, players map[uint32]*Player, bases map[uint32]*Base) {
|
|
joyStickCount := sdl.NumJoysticks()
|
|
if amount > uint8(len(keyMaps)+len(joyMaps)) || amount > uint8(len(keyMaps)+joyStickCount) {
|
|
panic("Too many players, not enough inputs")
|
|
}
|
|
if amount >= uint8(len(playerColors)) {
|
|
panic("Too many players, not enough colors")
|
|
}
|
|
addedKeyboardPlayers := 0
|
|
for i := uint8(0); i < amount; i++ {
|
|
var keyMap KeyMap
|
|
var joyMap JoyMap
|
|
var joyStick *sdl.Joystick
|
|
|
|
if (config.DoAllKeymapsPlayers && i <= uint8(len(keyMaps))) || (config.DoKeymapPlayer && i == 0) || (uint8(joyStickCount) <= i) {
|
|
keyMap = keyMaps[(addedKeyboardPlayers+int(config.KeyBindOffset))%(len(keyMaps)-1)]
|
|
addedKeyboardPlayers++
|
|
} else {
|
|
joyStickIndex := i - uint8(addedKeyboardPlayers)
|
|
joyMap = joyMaps[joyStickIndex]
|
|
joyStick = sdl.JoystickOpen(int(joyStickIndex))
|
|
}
|
|
unusedColor := getUnusedColor(playerColors, players)
|
|
createPlayer(
|
|
true,
|
|
playerColors[unusedColor],
|
|
unusedColor,
|
|
nil,
|
|
keyMap,
|
|
joyMap,
|
|
joyStick,
|
|
gameMap,
|
|
players,
|
|
bases,
|
|
)
|
|
}
|
|
}
|
|
|
|
func closeThings(players map[uint32]*Player) {
|
|
playersMutex.Lock()
|
|
for _, player := range players {
|
|
if player.joyStick != nil {
|
|
player.joyStick.Close()
|
|
}
|
|
if player.window != nil {
|
|
_ = player.window.Destroy()
|
|
}
|
|
if player.logicalSurface != nil {
|
|
player.logicalSurface.Free()
|
|
}
|
|
if player.playSurface != nil {
|
|
player.playSurface.Free()
|
|
}
|
|
if player.HUDSurface != nil {
|
|
player.HUDSurface.Free()
|
|
}
|
|
}
|
|
playersMutex.Unlock()
|
|
}
|
|
|
|
func createPlayer(local bool, thisPlayerColors PlayerColors, thisPlayerColorIndex uint32, conn *net.TCPConn, keyMap KeyMap, joyMap JoyMap, joyStick *sdl.Joystick, gameMap *GameMap, players map[uint32]*Player, bases map[uint32]*Base) uint32 {
|
|
coordsAreValid := false
|
|
var posX, posY uint32
|
|
maxTries := 1000
|
|
baseSize := uint32(36) // Since the base is 36x36
|
|
minDistance := uint32(200) // Minimum distance between bases
|
|
maxDistance := uint32(500) // Maximum distance between bases
|
|
|
|
for !coordsAreValid && maxTries >= 0 {
|
|
maxTries--
|
|
posX = uint32(16 + rand.Intn(int(gameMap.width-baseSize-16)))
|
|
posY = uint32(16 + rand.Intn(int(gameMap.height-baseSize-16)))
|
|
|
|
coordsAreValid = true
|
|
baseMutex.RLock()
|
|
for _, base := range bases {
|
|
basePosX := uint32(base.gameObject.baseRect.X)
|
|
basePosY := uint32(base.gameObject.baseRect.Y)
|
|
|
|
// Calculate the distance between the edges of the bases
|
|
distanceX := max(0, max(basePosX-posX-baseSize, posX-basePosX-baseSize))
|
|
distanceY := max(0, max(basePosY-posY-baseSize, posY-basePosY-baseSize))
|
|
|
|
distanceSquared := distanceX*distanceX + distanceY*distanceY
|
|
|
|
if distanceSquared < minDistance*minDistance && distanceSquared > maxDistance*maxDistance {
|
|
coordsAreValid = false
|
|
break
|
|
}
|
|
}
|
|
baseMutex.RUnlock()
|
|
|
|
// Edge clamping to ensure the base is within the map boundaries
|
|
if posX < 16 || posX > gameMap.width-baseSize-16 || posY < 16 || posY > gameMap.height-baseSize-16 {
|
|
coordsAreValid = false
|
|
break
|
|
}
|
|
}
|
|
|
|
if maxTries < 0 {
|
|
panic("Could not place all players, increase map size")
|
|
}
|
|
|
|
gameObject := &GameObject{}
|
|
|
|
gameObject.baseRect = &sdl.Rect{
|
|
X: int32(posX),
|
|
Y: int32(posY),
|
|
W: 7,
|
|
H: 7,
|
|
}
|
|
|
|
gameObject.addColor(thisPlayerColors.tracks)
|
|
gameObject.addColor(thisPlayerColors.body)
|
|
gameObject.addColor(thisPlayerColors.cannon)
|
|
|
|
gameObject.orientation = 0 // Up
|
|
gameObject.addColoredRect(0, 1, 1, 6, 0)
|
|
gameObject.addColoredRect(4, 1, 1, 6, 0)
|
|
gameObject.addColoredRect(1, 2, 3, 4, 1)
|
|
gameObject.addColoredRect(2, 0, 1, 4, 2)
|
|
|
|
gameObject.orientation = 1 // Right
|
|
gameObject.addColoredRect(0, 0, 6, 1, 0)
|
|
gameObject.addColoredRect(0, 4, 6, 1, 0)
|
|
gameObject.addColoredRect(1, 1, 4, 3, 1)
|
|
gameObject.addColoredRect(3, 2, 4, 1, 2)
|
|
|
|
gameObject.orientation = 2 // Down
|
|
gameObject.addColoredRect(0, 0, 1, 6, 0)
|
|
gameObject.addColoredRect(4, 0, 1, 6, 0)
|
|
gameObject.addColoredRect(1, 1, 3, 4, 1)
|
|
gameObject.addColoredRect(2, 3, 1, 4, 2)
|
|
|
|
gameObject.orientation = 3 // Left
|
|
gameObject.addColoredRect(1, 0, 6, 1, 0)
|
|
gameObject.addColoredRect(1, 4, 6, 1, 0)
|
|
gameObject.addColoredRect(2, 1, 4, 3, 1)
|
|
gameObject.addColoredRect(0, 2, 4, 1, 2)
|
|
|
|
gameObject.orientation = 4 // Up-Right
|
|
gameObject.addColoredRect(3, 0, 1, 1, 0)
|
|
gameObject.addColoredRect(2, 1, 1, 1, 0)
|
|
gameObject.addColoredRect(1, 2, 1, 1, 0)
|
|
gameObject.addColoredRect(0, 3, 1, 1, 0)
|
|
gameObject.addColoredRect(6, 3, 1, 1, 0)
|
|
gameObject.addColoredRect(5, 4, 1, 1, 0)
|
|
gameObject.addColoredRect(4, 5, 1, 1, 0)
|
|
gameObject.addColoredRect(3, 6, 1, 1, 0)
|
|
|
|
gameObject.addColoredRect(3, 1, 1, 1, 1)
|
|
gameObject.addColoredRect(2, 2, 2, 1, 1)
|
|
gameObject.addColoredRect(1, 3, 2, 1, 1)
|
|
|
|
gameObject.addColoredRect(4, 3, 2, 1, 1)
|
|
gameObject.addColoredRect(2, 4, 3, 1, 1)
|
|
gameObject.addColoredRect(3, 5, 1, 1, 1)
|
|
|
|
gameObject.addColoredRect(5, 1, 1, 1, 2)
|
|
gameObject.addColoredRect(4, 2, 1, 1, 2)
|
|
gameObject.addColoredRect(3, 3, 1, 1, 2)
|
|
|
|
// Up-Left orientation (Y-axis reflection)
|
|
gameObject.orientation = 5 // Up-Left
|
|
gameObject.addColoredRect(3, 0, 1, 1, 0)
|
|
gameObject.addColoredRect(4, 1, 1, 1, 0)
|
|
gameObject.addColoredRect(5, 2, 1, 1, 0)
|
|
gameObject.addColoredRect(6, 3, 1, 1, 0)
|
|
gameObject.addColoredRect(0, 3, 1, 1, 0)
|
|
gameObject.addColoredRect(1, 4, 1, 1, 0)
|
|
gameObject.addColoredRect(2, 5, 1, 1, 0)
|
|
gameObject.addColoredRect(3, 6, 1, 1, 0)
|
|
|
|
gameObject.addColoredRect(3, 1, 1, 1, 1)
|
|
gameObject.addColoredRect(3, 2, 2, 1, 1)
|
|
gameObject.addColoredRect(4, 3, 2, 1, 1)
|
|
|
|
gameObject.addColoredRect(1, 3, 2, 1, 1)
|
|
gameObject.addColoredRect(2, 4, 3, 1, 1)
|
|
gameObject.addColoredRect(3, 5, 1, 1, 1)
|
|
|
|
gameObject.addColoredRect(1, 1, 1, 1, 2)
|
|
gameObject.addColoredRect(2, 2, 1, 1, 2)
|
|
gameObject.addColoredRect(3, 3, 1, 1, 2)
|
|
|
|
// Down-Right orientation (X-axis reflection)
|
|
gameObject.orientation = 6 // Down-Right
|
|
gameObject.addColoredRect(3, 6, 1, 1, 0)
|
|
gameObject.addColoredRect(2, 5, 1, 1, 0)
|
|
gameObject.addColoredRect(1, 4, 1, 1, 0)
|
|
gameObject.addColoredRect(0, 3, 1, 1, 0)
|
|
gameObject.addColoredRect(6, 3, 1, 1, 0)
|
|
gameObject.addColoredRect(5, 2, 1, 1, 0)
|
|
gameObject.addColoredRect(4, 1, 1, 1, 0)
|
|
gameObject.addColoredRect(3, 0, 1, 1, 0)
|
|
|
|
gameObject.addColoredRect(3, 5, 1, 1, 1)
|
|
gameObject.addColoredRect(2, 4, 2, 1, 1)
|
|
gameObject.addColoredRect(1, 3, 2, 1, 1)
|
|
|
|
gameObject.addColoredRect(4, 3, 2, 1, 1)
|
|
gameObject.addColoredRect(2, 2, 3, 1, 1)
|
|
gameObject.addColoredRect(3, 1, 1, 1, 1)
|
|
|
|
gameObject.addColoredRect(5, 5, 1, 1, 2)
|
|
gameObject.addColoredRect(4, 4, 1, 1, 2)
|
|
gameObject.addColoredRect(3, 3, 1, 1, 2)
|
|
|
|
// Down-Left orientation (XY reflection)
|
|
gameObject.orientation = 7 // Down-Left
|
|
gameObject.addColoredRect(3, 6, 1, 1, 0)
|
|
gameObject.addColoredRect(4, 5, 1, 1, 0)
|
|
gameObject.addColoredRect(5, 4, 1, 1, 0)
|
|
gameObject.addColoredRect(6, 3, 1, 1, 0)
|
|
gameObject.addColoredRect(0, 3, 1, 1, 0)
|
|
gameObject.addColoredRect(1, 2, 1, 1, 0)
|
|
gameObject.addColoredRect(2, 1, 1, 1, 0)
|
|
gameObject.addColoredRect(3, 0, 1, 1, 0)
|
|
|
|
gameObject.addColoredRect(3, 1, 1, 1, 1)
|
|
gameObject.addColoredRect(2, 2, 3, 1, 1)
|
|
gameObject.addColoredRect(1, 3, 2, 1, 1)
|
|
|
|
gameObject.addColoredRect(4, 3, 2, 1, 1)
|
|
gameObject.addColoredRect(3, 4, 2, 1, 1)
|
|
gameObject.addColoredRect(3, 5, 1, 1, 1)
|
|
|
|
gameObject.addColoredRect(1, 5, 1, 1, 2)
|
|
gameObject.addColoredRect(2, 4, 1, 1, 2)
|
|
gameObject.addColoredRect(3, 3, 1, 1, 2)
|
|
|
|
gameObject.orientation = 0
|
|
gameObject.adjustBaseRect()
|
|
|
|
if !local && (keyMap.exit != keyMap.shoot || joyMap.exitButton != joyMap.shootButton) {
|
|
panic("Input assigned to remote player")
|
|
}
|
|
|
|
knownGameMap := GameMap{width: gameMap.width, height: gameMap.height, tiles: make([][]uint8, serverConfig.MapWidth)}
|
|
for i := uint32(0); i < serverConfig.MapWidth; i++ {
|
|
knownGameMap.tiles[i] = make([]uint8, serverConfig.MapHeight)
|
|
}
|
|
|
|
playersMutex.Lock()
|
|
players[lastPlayerID] = &Player{
|
|
playerColors: thisPlayerColors,
|
|
playerColorID: thisPlayerColorIndex,
|
|
keyMap: keyMap,
|
|
joyMap: joyMap,
|
|
joyStick: joyStick,
|
|
shields: serverConfig.MaxShields,
|
|
energy: serverConfig.MaxEnergy,
|
|
gameObject: gameObject,
|
|
local: local,
|
|
connection: conn,
|
|
playerID: lastPlayerID,
|
|
knownBulletParticles: make(map[uint32]*BulletParticle),
|
|
knownBases: make(map[uint32]*Base),
|
|
knownPlayers: make(map[uint32]*Player),
|
|
knownBullets: make(map[uint32]*Bullet),
|
|
knownGameMap: &knownGameMap,
|
|
}
|
|
playersMutex.Unlock()
|
|
lastPlayerID++
|
|
return lastPlayerID - 1
|
|
}
|