Add networking
This commit is contained in:
parent
842c41fdca
commit
dc854d411f
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
proto/tuneller.pb.go
|
||||||
|
proto/*
|
||||||
|
config.json
|
84
base.go
84
base.go
@ -1,38 +1,44 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/veandco/go-sdl2/sdl"
|
import (
|
||||||
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
|
"image/color"
|
||||||
|
)
|
||||||
|
|
||||||
type Base struct {
|
type Base struct {
|
||||||
owner *Player
|
ownerID uint32
|
||||||
openingWidth int32
|
openingWidth int32
|
||||||
gameObject *GameObject
|
gameObject *GameObject
|
||||||
}
|
}
|
||||||
|
|
||||||
func (base *Base) tick(players *[]*Player) {
|
func (base *Base) tick(players map[uint32]*Player) {
|
||||||
for _, player := range *players {
|
for playerID, player := range players {
|
||||||
if player.gameObject.baseRect.HasIntersection(&base.gameObject.baseRect) {
|
if player.gameObject.baseRect.HasIntersection(&base.gameObject.baseRect) {
|
||||||
if player.rechargeCooldown == 0 && player.energy < MaxEnergy {
|
if player.rechargeCooldown == 0 && player.energy < serverConfig.MaxEnergy {
|
||||||
if MaxEnergy-player.energy < 4 {
|
if serverConfig.MaxEnergy-player.energy < 4 {
|
||||||
player.energy++
|
player.energy++
|
||||||
} else {
|
} else {
|
||||||
player.energy += 4
|
player.energy += 4
|
||||||
}
|
}
|
||||||
if player == base.owner {
|
if playerID == base.ownerID {
|
||||||
player.rechargeCooldown = RechargeCooldownOwn
|
player.rechargeCooldown = serverConfig.RechargeCooldownOwn
|
||||||
} else {
|
} else {
|
||||||
player.rechargeCooldown = RechargeCooldownOpponent
|
player.rechargeCooldown = serverConfig.RechargeCooldownOpponent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if player == base.owner && player.repairCooldown == 0 && player.shields < MaxShields {
|
if playerID == base.ownerID && player.repairCooldown == 0 && player.shields < serverConfig.MaxShields {
|
||||||
player.shields++
|
player.shields++
|
||||||
player.repairCooldown = RepairCooldown
|
player.repairCooldown = serverConfig.RepairCooldown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (base *Base) render(camera *sdl.Rect, surface *sdl.Surface) {
|
func (base *Base) render(camera *sdl.Rect, surface *sdl.Surface, bases map[uint32]*Base) {
|
||||||
base.gameObject.render(camera, surface)
|
base.gameObject.render(camera, surface)
|
||||||
|
if !base.gameObject.inView && !config.Server {
|
||||||
|
delete(bases, base.ownerID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (base *Base) build(gameMap *GameMap) {
|
func (base *Base) build(gameMap *GameMap) {
|
||||||
@ -44,10 +50,10 @@ func (base *Base) build(gameMap *GameMap) {
|
|||||||
if base.gameObject.baseRect.H < 9 {
|
if base.gameObject.baseRect.H < 9 {
|
||||||
panic("Bad border height")
|
panic("Bad border height")
|
||||||
}
|
}
|
||||||
if gameMap.width-base.gameObject.baseRect.X-base.gameObject.baseRect.W <= 0 {
|
if gameMap.width-uint32(base.gameObject.baseRect.X)-uint32(base.gameObject.baseRect.W) <= 0 {
|
||||||
panic("Bad base x location")
|
panic("Bad base x location")
|
||||||
}
|
}
|
||||||
if gameMap.height-base.gameObject.baseRect.Y-base.gameObject.baseRect.H <= 0 {
|
if gameMap.height-uint32(base.gameObject.baseRect.Y)-uint32(base.gameObject.baseRect.H) <= 0 {
|
||||||
panic("Bad base y location")
|
panic("Bad base y location")
|
||||||
}
|
}
|
||||||
if base.gameObject.baseRect.X < 0 || base.gameObject.baseRect.Y < 0 {
|
if base.gameObject.baseRect.X < 0 || base.gameObject.baseRect.Y < 0 {
|
||||||
@ -72,41 +78,59 @@ func (base *Base) build(gameMap *GameMap) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createBases(players *[]*Player, gameMap *GameMap) *[]*Base {
|
func createBase(gameMap *GameMap, baseColor color.Color, posX, posY, ownerID, openingWidth uint32) *Base {
|
||||||
bases := &[]*Base{}
|
|
||||||
|
|
||||||
for ownerID, player := range *players {
|
|
||||||
gameObject := &GameObject{}
|
gameObject := &GameObject{}
|
||||||
gameObject.baseRect = sdl.Rect{
|
gameObject.baseRect = sdl.Rect{
|
||||||
X: player.gameObject.baseRect.X - 14,
|
X: int32(posX),
|
||||||
Y: player.gameObject.baseRect.Y - 14,
|
Y: int32(posY),
|
||||||
W: 35,
|
W: 35,
|
||||||
H: 35,
|
H: 35,
|
||||||
}
|
}
|
||||||
openingWidth := int32(float64(player.gameObject.baseRect.W) * 1.5)
|
|
||||||
if openingWidth%2 == 0 {
|
if openingWidth%2 == 0 {
|
||||||
openingWidth++
|
openingWidth++
|
||||||
}
|
}
|
||||||
|
|
||||||
borderWidth := gameObject.baseRect.W - openingWidth
|
borderWidth := gameObject.baseRect.W - int32(openingWidth)
|
||||||
borderWidthA := borderWidth / 2
|
borderWidthA := borderWidth / 2
|
||||||
borderWidthB := borderWidth - borderWidthA + 1
|
borderWidthB := borderWidth - borderWidthA + 1
|
||||||
if borderWidth < 0 {
|
if borderWidth < 0 {
|
||||||
panic("Bad border width")
|
panic("Bad border width")
|
||||||
}
|
}
|
||||||
gameObject.addColor((*player).playerColors.body)
|
gameObject.addColor(baseColor)
|
||||||
gameObject.addColoredRect(0, 0, 1, gameObject.baseRect.H, 0)
|
gameObject.addColoredRect(0, 0, 1, gameObject.baseRect.H, 0)
|
||||||
gameObject.addColoredRect(gameObject.baseRect.W, 0, 1, gameObject.baseRect.H, 0)
|
gameObject.addColoredRect(gameObject.baseRect.W, 0, 1, gameObject.baseRect.H, 0)
|
||||||
gameObject.addColoredRect(0, 0, borderWidthA, 1, 0)
|
gameObject.addColoredRect(0, 0, borderWidthA, 1, 0)
|
||||||
gameObject.addColoredRect(borderWidthA+openingWidth, 0, borderWidthB, 1, 0)
|
gameObject.addColoredRect(borderWidthA+int32(openingWidth), 0, borderWidthB, 1, 0)
|
||||||
gameObject.addColoredRect(0, gameObject.baseRect.H, borderWidthA, 1, 0)
|
gameObject.addColoredRect(0, gameObject.baseRect.H, borderWidthA, 1, 0)
|
||||||
gameObject.addColoredRect(borderWidthA+openingWidth, gameObject.baseRect.H, borderWidthB, 1, 0)
|
gameObject.addColoredRect(borderWidthA+int32(openingWidth), gameObject.baseRect.H, borderWidthB, 1, 0)
|
||||||
*bases = append(*bases, &Base{
|
base := &Base{
|
||||||
gameObject: gameObject,
|
gameObject: gameObject,
|
||||||
owner: (*players)[ownerID],
|
ownerID: ownerID,
|
||||||
openingWidth: openingWidth,
|
openingWidth: int32(openingWidth),
|
||||||
})
|
}
|
||||||
(*bases)[ownerID].build(gameMap)
|
base.build(gameMap)
|
||||||
|
return base
|
||||||
|
}
|
||||||
|
|
||||||
|
func (base *Base) delete(bases map[uint32]*Base) {
|
||||||
|
for x := base.gameObject.baseRect.X; x < base.gameObject.baseRect.X+base.gameObject.baseRect.W+1; x++ {
|
||||||
|
for y := base.gameObject.baseRect.Y; y < base.gameObject.baseRect.Y+base.gameObject.baseRect.H+1; y++ {
|
||||||
|
gameMap.tiles[x][y] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete(bases, base.ownerID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createBases(players map[uint32]*Player, gameMap *GameMap) map[uint32]*Base {
|
||||||
|
bases := map[uint32]*Base{}
|
||||||
|
for ownerID, player := range players {
|
||||||
|
bases[ownerID] = createBase(gameMap,
|
||||||
|
player.playerColors.body,
|
||||||
|
uint32(player.gameObject.baseRect.X-14),
|
||||||
|
uint32(player.gameObject.baseRect.Y-14),
|
||||||
|
ownerID,
|
||||||
|
uint32(float64(player.gameObject.baseRect.W)*1.5),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return bases
|
return bases
|
||||||
}
|
}
|
||||||
|
60
bullet.go
60
bullet.go
@ -6,47 +6,53 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var bulletLastID = uint32(0)
|
||||||
|
var bulletParticleLastID = uint32(0)
|
||||||
|
|
||||||
type Bullet struct {
|
type Bullet struct {
|
||||||
posX, posY int32
|
posX, posY int32
|
||||||
direction uint8
|
direction uint8
|
||||||
color color.Color
|
color color.Color
|
||||||
super bool
|
super bool
|
||||||
|
id uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
type BulletParticle struct {
|
type BulletParticle struct {
|
||||||
posX, posY int32
|
posX, posY int32
|
||||||
expirationTimer uint8
|
expirationTimer uint32
|
||||||
color color.Color
|
color color.Color
|
||||||
|
id uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bulletParticle *BulletParticle) render(camera *sdl.Rect, surface *sdl.Surface) {
|
func (bulletParticle *BulletParticle) render(camera *sdl.Rect, surface *sdl.Surface, bulletParticles map[uint32]*BulletParticle) {
|
||||||
if camera.IntersectLine(&bulletParticle.posX, &bulletParticle.posY, &bulletParticle.posX, &bulletParticle.posY) {
|
if camera.IntersectLine(&bulletParticle.posX, &bulletParticle.posY, &bulletParticle.posX, &bulletParticle.posY) {
|
||||||
relativeBulletX := bulletParticle.posX - camera.X
|
relativeBulletX := bulletParticle.posX - camera.X
|
||||||
relativeBulletY := bulletParticle.posY - camera.Y
|
relativeBulletY := bulletParticle.posY - camera.Y
|
||||||
surface.Set(int(relativeBulletX), int(relativeBulletY), bulletParticle.color)
|
surface.Set(int(relativeBulletX), int(relativeBulletY), bulletParticle.color)
|
||||||
|
} else if !config.Server {
|
||||||
|
delete(bulletParticles, bulletParticle.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bulletParticle *BulletParticle) tick(particles *[]*BulletParticle) {
|
func (bulletParticle *BulletParticle) tick(particles map[uint32]*BulletParticle) {
|
||||||
if bulletParticle.expirationTimer <= 0 {
|
if bulletParticle.expirationTimer <= 0 {
|
||||||
for i, particle := range *particles {
|
delete(particles, bulletParticle.id)
|
||||||
if particle == bulletParticle {
|
} else {
|
||||||
*particles = append((*particles)[:i], (*particles)[i+1:]...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bulletParticle.expirationTimer--
|
bulletParticle.expirationTimer--
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (bullet *Bullet) render(camera *sdl.Rect, surface *sdl.Surface) {
|
func (bullet *Bullet) render(camera *sdl.Rect, surface *sdl.Surface, bullets map[uint32]*Bullet) {
|
||||||
if camera.IntersectLine(&bullet.posX, &bullet.posY, &bullet.posX, &bullet.posY) {
|
if camera.IntersectLine(&bullet.posX, &bullet.posY, &bullet.posX, &bullet.posY) {
|
||||||
relativeBulletX := bullet.posX - camera.X
|
relativeBulletX := bullet.posX - camera.X
|
||||||
relativeBulletY := bullet.posY - camera.Y
|
relativeBulletY := bullet.posY - camera.Y
|
||||||
surface.Set(int(relativeBulletX), int(relativeBulletY), bullet.color)
|
surface.Set(int(relativeBulletX), int(relativeBulletY), bullet.color)
|
||||||
|
} else if !config.Server {
|
||||||
|
delete(bullets, bullet.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bullet *Bullet) explode(gameMap *GameMap, bulletParticleMap *[]*BulletParticle) {
|
func (bullet *Bullet) explode(gameMap *GameMap, bulletParticleMap map[uint32]*BulletParticle) {
|
||||||
// Define the possible directions with their x and y velocity components.
|
// Define the possible directions with their x and y velocity components.
|
||||||
directions := [][2]int{
|
directions := [][2]int{
|
||||||
{0, -1}, // Up
|
{0, -1}, // Up
|
||||||
@ -75,13 +81,15 @@ func (bullet *Bullet) explode(gameMap *GameMap, bulletParticleMap *[]*BulletPart
|
|||||||
|
|
||||||
// Check for collision and bullet behavior (normal or super).
|
// Check for collision and bullet behavior (normal or super).
|
||||||
if collision == 1 || collision == 0 || (bullet.super && collision == 2) {
|
if collision == 1 || collision == 0 || (bullet.super && collision == 2) {
|
||||||
*bulletParticleMap = append(*bulletParticleMap, &BulletParticle{
|
bulletParticleMap[bulletParticleLastID] = &BulletParticle{
|
||||||
posX: xPos,
|
posX: xPos,
|
||||||
posY: yPos,
|
posY: yPos,
|
||||||
expirationTimer: uint8(5 + rand.Intn(10)), // Randomize expiration time between 15 and 25.
|
expirationTimer: uint32(5 + rand.Intn(10)), // Randomize expiration time between 15 and 25.
|
||||||
color: bullet.color,
|
color: bullet.color,
|
||||||
})
|
id: bulletParticleLastID,
|
||||||
if xPos > 0 && yPos > 0 && xPos < MapWidth && yPos < MapHeight {
|
}
|
||||||
|
bulletParticleLastID++
|
||||||
|
if xPos > 0 && yPos > 0 && uint32(xPos) < serverConfig.MapWidth && uint32(yPos) < serverConfig.MapHeight {
|
||||||
gameMap.tiles[xPos][yPos] = 0
|
gameMap.tiles[xPos][yPos] = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,12 +101,14 @@ func (bullet *Bullet) explode(gameMap *GameMap, bulletParticleMap *[]*BulletPart
|
|||||||
xPos, yPos := bullet.posX+int32(xOffset), bullet.posY+int32(yOffset)
|
xPos, yPos := bullet.posX+int32(xOffset), bullet.posY+int32(yOffset)
|
||||||
collision := gameMap.checkCollision(xPos, yPos)
|
collision := gameMap.checkCollision(xPos, yPos)
|
||||||
if collision == 1 || collision == 0 || (bullet.super && collision == 2) {
|
if collision == 1 || collision == 0 || (bullet.super && collision == 2) {
|
||||||
*bulletParticleMap = append(*bulletParticleMap, &BulletParticle{
|
bulletParticleMap[bulletParticleLastID] = &BulletParticle{
|
||||||
posX: xPos,
|
posX: xPos,
|
||||||
posY: yPos,
|
posY: yPos,
|
||||||
expirationTimer: uint8(15 + rand.Intn(15)),
|
expirationTimer: uint32(15 + rand.Intn(15)),
|
||||||
color: bullet.color,
|
color: bullet.color,
|
||||||
})
|
id: bulletParticleLastID,
|
||||||
|
}
|
||||||
|
bulletParticleLastID++
|
||||||
gameMap.tiles[xPos][yPos] = 0
|
gameMap.tiles[xPos][yPos] = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,7 +117,7 @@ func (bullet *Bullet) explode(gameMap *GameMap, bulletParticleMap *[]*BulletPart
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (bullet *Bullet) tick(gameMap *GameMap,
|
func (bullet *Bullet) tick(gameMap *GameMap,
|
||||||
bulletParticleMap *[]*BulletParticle, bulletMap *[]*Bullet, players *[]*Player) {
|
bulletParticleMap map[uint32]*BulletParticle, bulletMap map[uint32]*Bullet, players map[uint32]*Player) {
|
||||||
var nextX, nextY int32
|
var nextX, nextY int32
|
||||||
nextX, nextY = bullet.posX, bullet.posY
|
nextX, nextY = bullet.posX, bullet.posY
|
||||||
switch bullet.direction {
|
switch bullet.direction {
|
||||||
@ -148,13 +158,13 @@ func (bullet *Bullet) tick(gameMap *GameMap,
|
|||||||
H: 1,
|
H: 1,
|
||||||
}
|
}
|
||||||
hitPlayer := false
|
hitPlayer := false
|
||||||
for _, player := range *players {
|
for _, player := range players {
|
||||||
if hitPlayer {
|
if hitPlayer {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
for _, coloredRect := range player.gameObject.getCurrentRects() {
|
for _, coloredRect := range player.gameObject.getCurrentRects() {
|
||||||
if coloredRect.rect.HasIntersection(&bulletRect) {
|
if player.gameObject.adjustRectWorld(coloredRect.rect).HasIntersection(&bulletRect) {
|
||||||
hitPlayer = true
|
hitPlayer = player.shields <= serverConfig.MaxShields
|
||||||
player.shields -= 10
|
player.shields -= 10
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -162,11 +172,7 @@ func (bullet *Bullet) tick(gameMap *GameMap,
|
|||||||
}
|
}
|
||||||
if collisionResult != 0 || hitPlayer {
|
if collisionResult != 0 || hitPlayer {
|
||||||
bullet.explode(gameMap, bulletParticleMap)
|
bullet.explode(gameMap, bulletParticleMap)
|
||||||
for i, bulletInMap := range *bulletMap {
|
delete(bulletMap, bullet.id)
|
||||||
if bulletInMap == bullet {
|
|
||||||
*bulletMap = append((*bulletMap)[:i], (*bulletMap)[i+1:]...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
bullet.posX = nextX
|
bullet.posX = nextX
|
||||||
bullet.posY = nextY
|
bullet.posY = nextY
|
||||||
|
@ -7,10 +7,12 @@ import (
|
|||||||
|
|
||||||
type GameObject struct {
|
type GameObject struct {
|
||||||
baseRect sdl.Rect
|
baseRect sdl.Rect
|
||||||
|
prevBaseRect sdl.Rect
|
||||||
borderRect sdl.Rect
|
borderRect sdl.Rect
|
||||||
orientation uint8
|
orientation uint8
|
||||||
visualRects [][]*ColoredRect
|
visualRects [][]*ColoredRect
|
||||||
colors []color.Color
|
colors []color.Color
|
||||||
|
inView bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type ColoredRect struct {
|
type ColoredRect struct {
|
||||||
@ -27,6 +29,15 @@ func adjustRectToCamera(object *sdl.Rect, camera *sdl.Rect) *sdl.Rect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gameObject *GameObject) adjustRectWorld(offset *sdl.Rect) *sdl.Rect {
|
||||||
|
return &sdl.Rect{
|
||||||
|
X: gameObject.baseRect.X + offset.X,
|
||||||
|
Y: gameObject.baseRect.Y + offset.Y,
|
||||||
|
W: offset.W,
|
||||||
|
H: offset.H,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (gameObject *GameObject) adjustRectToCamera(offset *sdl.Rect, camera *sdl.Rect) *sdl.Rect {
|
func (gameObject *GameObject) adjustRectToCamera(offset *sdl.Rect, camera *sdl.Rect) *sdl.Rect {
|
||||||
return &sdl.Rect{
|
return &sdl.Rect{
|
||||||
X: gameObject.baseRect.X + offset.X - camera.X,
|
X: gameObject.baseRect.X + offset.X - camera.X,
|
||||||
@ -38,7 +49,8 @@ func (gameObject *GameObject) adjustRectToCamera(offset *sdl.Rect, camera *sdl.R
|
|||||||
|
|
||||||
func (gameObject *GameObject) render(camera *sdl.Rect, surface *sdl.Surface) {
|
func (gameObject *GameObject) render(camera *sdl.Rect, surface *sdl.Surface) {
|
||||||
if camera.HasIntersection(&gameObject.baseRect) {
|
if camera.HasIntersection(&gameObject.baseRect) {
|
||||||
if Debug {
|
gameObject.inView = true
|
||||||
|
if config.Debug {
|
||||||
gameObject.borderRect = sdl.Rect{
|
gameObject.borderRect = sdl.Rect{
|
||||||
X: gameObject.baseRect.X - 1,
|
X: gameObject.baseRect.X - 1,
|
||||||
Y: gameObject.baseRect.Y - 1,
|
Y: gameObject.baseRect.Y - 1,
|
||||||
@ -50,13 +62,15 @@ func (gameObject *GameObject) render(camera *sdl.Rect, surface *sdl.Surface) {
|
|||||||
surface.FillRect(borderRectFinal, sdl.MapRGBA(surface.Format, 20, 192, 128, 64))
|
surface.FillRect(borderRectFinal, sdl.MapRGBA(surface.Format, 20, 192, 128, 64))
|
||||||
surface.FillRect(baseRectFinal, sdl.MapRGBA(surface.Format, 255, 20, 10, 64))
|
surface.FillRect(baseRectFinal, sdl.MapRGBA(surface.Format, 255, 20, 10, 64))
|
||||||
}
|
}
|
||||||
if RenderGameObjects {
|
if config.RenderGameObjects {
|
||||||
for _, coloredRect := range gameObject.visualRects[gameObject.orientation] {
|
for _, coloredRect := range gameObject.visualRects[gameObject.orientation] {
|
||||||
finalRect := gameObject.adjustRectToCamera(coloredRect.rect, camera)
|
finalRect := gameObject.adjustRectToCamera(coloredRect.rect, camera)
|
||||||
r, g, b, a := coloredRect.color.RGBA()
|
r, g, b, a := coloredRect.color.RGBA()
|
||||||
surface.FillRect(finalRect, sdl.MapRGBA(surface.Format, uint8(r), uint8(g), uint8(b), uint8(a)))
|
surface.FillRect(finalRect, sdl.MapRGBA(surface.Format, uint8(r), uint8(g), uint8(b), uint8(a)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
gameObject.inView = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
go.mod
1
go.mod
@ -5,4 +5,5 @@ go 1.21
|
|||||||
require (
|
require (
|
||||||
github.com/aquilax/go-perlin v1.1.0
|
github.com/aquilax/go-perlin v1.1.0
|
||||||
github.com/veandco/go-sdl2 v0.4.40
|
github.com/veandco/go-sdl2 v0.4.40
|
||||||
|
google.golang.org/protobuf v1.34.2
|
||||||
)
|
)
|
||||||
|
6
go.sum
6
go.sum
@ -1,4 +1,10 @@
|
|||||||
github.com/aquilax/go-perlin v1.1.0 h1:Gg+3jQ24wT4Y5GI7TCRLmYarzUG0k+n/JATFqOimb7s=
|
github.com/aquilax/go-perlin v1.1.0 h1:Gg+3jQ24wT4Y5GI7TCRLmYarzUG0k+n/JATFqOimb7s=
|
||||||
github.com/aquilax/go-perlin v1.1.0/go.mod h1:z9Rl7EM4BZY0Ikp2fEN1I5mKSOJ26HQpk0O2TBdN2HE=
|
github.com/aquilax/go-perlin v1.1.0/go.mod h1:z9Rl7EM4BZY0Ikp2fEN1I5mKSOJ26HQpk0O2TBdN2HE=
|
||||||
|
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||||
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/veandco/go-sdl2 v0.4.40 h1:fZv6wC3zz1Xt167P09gazawnpa0KY5LM7JAvKpX9d/U=
|
github.com/veandco/go-sdl2 v0.4.40 h1:fZv6wC3zz1Xt167P09gazawnpa0KY5LM7JAvKpX9d/U=
|
||||||
github.com/veandco/go-sdl2 v0.4.40/go.mod h1:OROqMhHD43nT4/i9crJukyVecjPNYYuCofep6SNiAjY=
|
github.com/veandco/go-sdl2 v0.4.40/go.mod h1:OROqMhHD43nT4/i9crJukyVecjPNYYuCofep6SNiAjY=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||||
|
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||||
|
13
graphics.go
13
graphics.go
@ -27,13 +27,12 @@ func setupWindowAndSurface(playerIndex uint8) (*sdl.Window, *sdl.Surface) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setupMapWindowAndSurface() (*sdl.Window, *sdl.Surface) {
|
func setupMapWindowAndSurface() (*sdl.Window, *sdl.Surface) {
|
||||||
const windowWidth, windowHeight = MapWidth, MapHeight
|
window, err := sdl.CreateWindow("Tunneler map", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, int32(serverConfig.MapWidth), int32(serverConfig.MapWidth), sdl.WINDOW_SHOWN|sdl.WINDOW_RESIZABLE)
|
||||||
window, err := sdl.CreateWindow("Tunneler map", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, windowWidth, windowHeight, sdl.WINDOW_SHOWN|sdl.WINDOW_RESIZABLE)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
logicalSurface, err := sdl.CreateRGBSurface(0, windowWidth, windowHeight, 32, 0, 0, 0, 0)
|
logicalSurface, err := sdl.CreateRGBSurface(0, int32(serverConfig.MapWidth), int32(serverConfig.MapWidth), 32, 0, 0, 0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -42,12 +41,12 @@ func setupMapWindowAndSurface() (*sdl.Window, *sdl.Surface) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setupPlaySurface() (*sdl.Surface, *sdl.Rect, *sdl.Rect) {
|
func setupPlaySurface() (*sdl.Surface, *sdl.Rect, *sdl.Rect) {
|
||||||
playSurface, err := sdl.CreateRGBSurface(0, 76, 76, 32, 0, 0, 0, 0)
|
playSurface, err := sdl.CreateRGBSurface(0, config.CameraW, config.CameraH, 32, 0, 0, 0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
playSurfaceRect := &sdl.Rect{X: 0, Y: 0, W: 76, H: 76}
|
playSurfaceRect := &sdl.Rect{X: 0, Y: 0, W: config.CameraW, H: config.CameraH}
|
||||||
playSurfaceTargetRect := &sdl.Rect{X: 42, Y: 0, W: 76, H: 76}
|
playSurfaceTargetRect := &sdl.Rect{X: 42, Y: 0, W: config.CameraW, H: config.CameraH}
|
||||||
|
|
||||||
return playSurface, playSurfaceRect, playSurfaceTargetRect
|
return playSurface, playSurfaceRect, playSurfaceTargetRect
|
||||||
}
|
}
|
||||||
@ -58,7 +57,7 @@ func setupHUDSurface() (*sdl.Surface, *sdl.Rect, *sdl.Rect) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
HUDSurfaceRect := &sdl.Rect{X: 0, Y: 0, W: 112, H: 25}
|
HUDSurfaceRect := &sdl.Rect{X: 0, Y: 0, W: 112, H: 25}
|
||||||
HUDSurfaceTargetRect := &sdl.Rect{X: 24, Y: 76, W: 112, H: 25}
|
HUDSurfaceTargetRect := &sdl.Rect{X: 24, Y: config.CameraH, W: 112, H: 25}
|
||||||
|
|
||||||
return HUDSurface, HUDSurfaceRect, HUDSurfaceTargetRect
|
return HUDSurface, HUDSurfaceRect, HUDSurfaceTargetRect
|
||||||
}
|
}
|
||||||
|
8
hud.go
8
hud.go
@ -11,7 +11,7 @@ var letterOffsets = []int32{
|
|||||||
var letterColors []uint32
|
var letterColors []uint32
|
||||||
|
|
||||||
// Map function to convert value from range [0, 6] to range [0, 88]
|
// Map function to convert value from range [0, 6] to range [0, 88]
|
||||||
func mapRange(x, minX, maxX, minY, maxY uint16) int32 {
|
func mapRange(x, minX, maxX, minY, maxY uint32) int32 {
|
||||||
// Perform conversion to float64 to ensure proper division
|
// Perform conversion to float64 to ensure proper division
|
||||||
return int32((float64(x-minX)/float64(maxX-minX))*float64(maxY-minY) + float64(minY))
|
return int32((float64(x-minX)/float64(maxX-minX))*float64(maxY-minY) + float64(minY))
|
||||||
}
|
}
|
||||||
@ -66,9 +66,9 @@ func renderHud(player *Player, surface *sdl.Surface) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
HUDValues := []int32{
|
HUDValues := []int32{
|
||||||
mapRange(player.energy, 0, MaxEnergy, 0, 88),
|
mapRange(player.energy, 0, serverConfig.MaxEnergy, 0, 88),
|
||||||
mapRange(player.ammunition, 0, MaxAmmunition, 0, 88),
|
mapRange(player.ammunition, 0, serverConfig.MaxAmmunition, 0, 88),
|
||||||
mapRange(player.shields, 0, MaxShields, 0, 88),
|
mapRange(player.shields, 0, serverConfig.MaxShields, 0, 88),
|
||||||
}
|
}
|
||||||
|
|
||||||
for HUDValueIndex, HUDValue := range HUDValues {
|
for HUDValueIndex, HUDValue := range HUDValues {
|
||||||
|
339
main.go
339
main.go
@ -1,74 +1,213 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
type ServerConfig struct {
|
||||||
MapWidth = 1000 // Width of the map
|
MapWidth uint32
|
||||||
MapHeight = 1000 // Height of the map
|
MapHeight uint32
|
||||||
BlastRadius = 5
|
BlastRadius uint32
|
||||||
|
|
||||||
MaxEnergy = 3520
|
MaxEnergy uint32
|
||||||
MaxAmmunition = 6
|
MaxAmmunition uint32
|
||||||
MaxShields = 100
|
MaxShields uint32
|
||||||
|
|
||||||
NormalShotCost = 7
|
NormalShotCost uint32
|
||||||
SuperShotCost = 80
|
SuperShotCost uint32
|
||||||
ReloadCost = 4
|
ReloadCost uint32
|
||||||
MovementCost = 1
|
MovementCost uint32
|
||||||
DiggingCost = 3
|
DiggingCost uint32
|
||||||
ShootDiggingCostBonus = 1
|
ShootDiggingCostBonus uint32
|
||||||
|
|
||||||
ShootCooldown = 8
|
ShootCooldown uint32
|
||||||
RechargeCooldownOwn = 0
|
RechargeCooldownOwn uint32
|
||||||
DiggingCooldown = 4
|
DiggingCooldown uint32
|
||||||
RechargeCooldownOpponent = 6
|
RechargeCooldownOpponent uint32
|
||||||
RepairCooldown = 4
|
RepairCooldown uint32
|
||||||
MovementCooldown = 2
|
MovementCooldown uint32
|
||||||
MovementCooldownNoEnergy = 4
|
MovementCooldownNoEnergy uint32
|
||||||
DiggingCooldownNoEnergy = 8
|
DiggingCooldownNoEnergy uint32
|
||||||
ReloadCooldown = 16
|
ReloadCooldown uint32
|
||||||
|
}
|
||||||
|
|
||||||
Debug = false
|
type Config struct {
|
||||||
MapWindow = false
|
Debug bool `json:"debug"`
|
||||||
RenderGameObjects = true
|
MapWindow bool `json:"map_window"`
|
||||||
ProfilerOn = true
|
RenderGameObjects bool `json:"render_game_objects"`
|
||||||
ProfilerInterval = 100
|
ProfilerOn bool `json:"profiler_on"`
|
||||||
|
ProfilerInterval uint64 `json:"profiler_interval"`
|
||||||
|
Server bool `json:"server"`
|
||||||
|
CameraW int32 `json:"camera_w"`
|
||||||
|
CameraH int32 `json:"camera_h"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Client bool `json:"client"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
JoyStickDeadZone int16 `json:"joystick_dead_zone"`
|
||||||
|
DoAllKeymapsPlayers bool `json:"do_all_keymaps_players"`
|
||||||
|
DoJoyStickPlayers bool `json:"do_joystick_players"`
|
||||||
|
DoKeymapPlayer bool `json:"do_keymap_player"`
|
||||||
|
}
|
||||||
|
|
||||||
JoyStickDeadZone = 8000
|
func loadOrCreateConfig(filename string) (*Config, error) {
|
||||||
|
config := &Config{
|
||||||
|
Debug: false,
|
||||||
|
MapWindow: false,
|
||||||
|
RenderGameObjects: true,
|
||||||
|
ProfilerOn: false,
|
||||||
|
ProfilerInterval: 100,
|
||||||
|
Server: false,
|
||||||
|
CameraW: 76,
|
||||||
|
CameraH: 76,
|
||||||
|
Version: "69420",
|
||||||
|
Client: true,
|
||||||
|
Address: "192.168.1.8:5074",
|
||||||
|
JoyStickDeadZone: 8000,
|
||||||
|
DoAllKeymapsPlayers: false,
|
||||||
|
DoJoyStickPlayers: true,
|
||||||
|
DoKeymapPlayer: true,
|
||||||
|
}
|
||||||
|
|
||||||
DoAllKeymapsPlayers = false
|
// Check if the file exists
|
||||||
DoJoyStickPlayers = true
|
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||||
DoKeymapPlayer = true
|
// File does not exist, create it with the default config
|
||||||
)
|
data, err := json.MarshalIndent(config, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to marshal config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filename, data, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to write config file: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Println("Config file created with default values.")
|
||||||
|
} else {
|
||||||
|
// File exists, load the config
|
||||||
|
data, err := ioutil.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to read config file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(data, config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to unmarshal config: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Println("Config file loaded.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var config *Config
|
||||||
|
|
||||||
|
var gameMap = &GameMap{}
|
||||||
|
|
||||||
|
var serverConfig = ServerConfig{
|
||||||
|
MapWidth: 1000,
|
||||||
|
MapHeight: 1000,
|
||||||
|
BlastRadius: 5,
|
||||||
|
|
||||||
|
MaxEnergy: 3520,
|
||||||
|
MaxAmmunition: 6,
|
||||||
|
MaxShields: 100,
|
||||||
|
|
||||||
|
NormalShotCost: 7,
|
||||||
|
SuperShotCost: 80,
|
||||||
|
ReloadCost: 4,
|
||||||
|
MovementCost: 1,
|
||||||
|
DiggingCost: 3,
|
||||||
|
ShootDiggingCostBonus: 1,
|
||||||
|
|
||||||
|
ShootCooldown: 8,
|
||||||
|
RechargeCooldownOwn: 0,
|
||||||
|
DiggingCooldown: 4,
|
||||||
|
RechargeCooldownOpponent: 6,
|
||||||
|
RepairCooldown: 4,
|
||||||
|
MovementCooldown: 2,
|
||||||
|
MovementCooldownNoEnergy: 4,
|
||||||
|
DiggingCooldownNoEnergy: 8,
|
||||||
|
ReloadCooldown: 16,
|
||||||
|
}
|
||||||
|
|
||||||
var mapWindow *sdl.Window
|
var mapWindow *sdl.Window
|
||||||
var mapSurface *sdl.Surface
|
var mapSurface *sdl.Surface
|
||||||
var mapRendererRect = &sdl.Rect{X: 0, Y: 0, W: MapWidth, H: MapHeight}
|
var mapRendererRect = &sdl.Rect{X: 0, Y: 0, W: int32(serverConfig.MapWidth), H: int32(serverConfig.MapHeight)}
|
||||||
|
|
||||||
|
var netPlayerMapper = map[*net.Conn]*Player{}
|
||||||
|
|
||||||
|
var clientInitialized = false
|
||||||
|
|
||||||
|
var worldLock sync.Mutex
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
initializeSDL()
|
initializeSDL()
|
||||||
defer sdl.Quit()
|
defer sdl.Quit()
|
||||||
|
configX, err := loadOrCreateConfig("config.json")
|
||||||
gameMap := &GameMap{}
|
if err != nil {
|
||||||
gameMap.createGameMap(MapWidth, MapHeight)
|
log.Fatal(err)
|
||||||
|
}
|
||||||
players := &[]*Player{}
|
config = configX
|
||||||
|
players := make(map[uint32]*Player)
|
||||||
initPlayerColors()
|
initPlayerColors()
|
||||||
|
bullets := make(map[uint32]*Bullet)
|
||||||
|
bulletParticles := make(map[uint32]*BulletParticle)
|
||||||
|
bases := make(map[uint32]*Base)
|
||||||
|
|
||||||
|
if config.Client && config.Server {
|
||||||
|
panic("You can' t run client and server in the same instance")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !config.Client {
|
||||||
|
gameMap.createGameMap(true)
|
||||||
createPlayers(getNeededPlayers(), playerColors, keyMaps, joyMaps, gameMap, players)
|
createPlayers(getNeededPlayers(), playerColors, keyMaps, joyMaps, gameMap, players)
|
||||||
|
bases = createBases(players, gameMap)
|
||||||
|
} else {
|
||||||
|
// Create a connection to the server
|
||||||
|
conn, err := net.Dial("tcp", config.Address)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to connect to server: %v", err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
go handleConnectionClient(&conn, players, bases, bullets, bulletParticles)
|
||||||
|
for !clientInitialized {
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
defer closeThings(players)
|
defer closeThings(players)
|
||||||
|
|
||||||
bases := createBases(players, gameMap)
|
for playerIndex, player := range players {
|
||||||
|
|
||||||
bullets := &[]*Bullet{}
|
|
||||||
bulletParticles := &[]*BulletParticle{}
|
|
||||||
|
|
||||||
for playerIndex, player := range *players {
|
|
||||||
initPlayer(uint8(playerIndex), player)
|
initPlayer(uint8(playerIndex), player)
|
||||||
}
|
}
|
||||||
if MapWindow {
|
|
||||||
|
if config.Server {
|
||||||
|
listen, err := net.Listen("tcp", "0.0.0.0:5074")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
// close listener
|
||||||
|
defer listen.Close()
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
conn, err := listen.Accept()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
go handleRequest(conn, players, bullets, bases)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.MapWindow {
|
||||||
mapWindow, mapSurface = setupMapWindowAndSurface()
|
mapWindow, mapSurface = setupMapWindowAndSurface()
|
||||||
}
|
}
|
||||||
running := true
|
running := true
|
||||||
@ -82,6 +221,7 @@ func main() {
|
|||||||
currentTime := sdl.GetTicks64()
|
currentTime := sdl.GetTicks64()
|
||||||
deltaTime := currentTime - prevTime
|
deltaTime := currentTime - prevTime
|
||||||
prevTime = currentTime
|
prevTime = currentTime
|
||||||
|
worldLock.Lock()
|
||||||
|
|
||||||
// Catch up in case of a large delta time
|
// Catch up in case of a large delta time
|
||||||
for deltaTime > maxDeltaTime {
|
for deltaTime > maxDeltaTime {
|
||||||
@ -91,34 +231,34 @@ func main() {
|
|||||||
runGameLogic(players, gameMap, bases, bullets, bulletParticles)
|
runGameLogic(players, gameMap, bases, bullets, bulletParticles)
|
||||||
}
|
}
|
||||||
|
|
||||||
for playerIndex, player := range *players {
|
// Run logic for the remaining delta time
|
||||||
|
runGameLogic(players, gameMap, bases, bullets, bulletParticles)
|
||||||
|
|
||||||
|
for playerIndex, player := range players {
|
||||||
if player.local {
|
if player.local {
|
||||||
running := doPlayerFrame(uint8(playerIndex), player, players, gameMap, bases, bullets, bulletParticles)
|
running = doPlayerFrame(uint8(playerIndex), player, players, gameMap, bases, bullets, bulletParticles)
|
||||||
if !running {
|
if !running {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run logic for the remaining delta time
|
|
||||||
runGameLogic(players, gameMap, bases, bullets, bulletParticles)
|
|
||||||
|
|
||||||
// Render logic
|
// Render logic
|
||||||
if MapWindow {
|
if config.MapWindow {
|
||||||
// Profile rendering (aggregate all renderings)
|
// Profile rendering (aggregate all renderings)
|
||||||
totalRenderTime += profileSection(func() {
|
totalRenderTime += profileSection(func() {
|
||||||
gameMap.render(mapRendererRect, mapSurface)
|
gameMap.render(mapRendererRect, mapSurface)
|
||||||
for _, bullet := range *bullets {
|
for _, bullet := range bullets {
|
||||||
(*bullet).render(mapRendererRect, mapSurface)
|
(*bullet).render(mapRendererRect, mapSurface, bullets)
|
||||||
}
|
}
|
||||||
for _, base := range *bases {
|
for _, base := range bases {
|
||||||
(*base).render(mapRendererRect, mapSurface)
|
(*base).render(mapRendererRect, mapSurface, bases)
|
||||||
}
|
}
|
||||||
for _, playerLoop := range *players {
|
for _, playerLoop := range players {
|
||||||
(*playerLoop).render(mapRendererRect, mapSurface)
|
(*playerLoop).render(mapRendererRect, mapSurface, players)
|
||||||
}
|
}
|
||||||
for _, bulletParticle := range *bulletParticles {
|
for _, bulletParticle := range bulletParticles {
|
||||||
bulletParticle.render(mapRendererRect, mapSurface)
|
bulletParticle.render(mapRendererRect, mapSurface, bulletParticles)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
totalScalingTime += profileSection(func() {
|
totalScalingTime += profileSection(func() {
|
||||||
@ -131,30 +271,70 @@ func main() {
|
|||||||
frameCount++
|
frameCount++
|
||||||
|
|
||||||
// Log profiling information every 1000 frames
|
// Log profiling information every 1000 frames
|
||||||
if frameCount%ProfilerInterval == 0 && ProfilerOn {
|
if frameCount%config.ProfilerInterval == 0 && config.ProfilerOn {
|
||||||
logMapProfilingInfo(totalRenderTime, totalScalingTime, totalFrameTime, frameCount)
|
logMapProfilingInfo(totalRenderTime, totalScalingTime, totalFrameTime, frameCount)
|
||||||
resetMapProfilingCounters(&totalRenderTime, &totalScalingTime, &totalFrameTime, &frameCount)
|
resetMapProfilingCounters(&totalRenderTime, &totalScalingTime, &totalFrameTime, &frameCount)
|
||||||
}
|
}
|
||||||
|
worldLock.Unlock()
|
||||||
enforceFrameRate(currentTime, 60)
|
enforceFrameRate(currentTime, 60)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Separate function to handle game logic
|
// Separate function to handle game logic
|
||||||
func runGameLogic(players *[]*Player, gameMap *GameMap, bases *[]*Base, bullets *[]*Bullet, bulletParticles *[]*BulletParticle) {
|
func runGameLogic(players map[uint32]*Player, gameMap *GameMap, bases map[uint32]*Base, bullets map[uint32]*Bullet, bulletParticles map[uint32]*BulletParticle) {
|
||||||
// Tick world
|
// Tick world
|
||||||
for _, bullet := range *bullets {
|
|
||||||
|
if config.Server {
|
||||||
|
//update remote player maps
|
||||||
|
for _, player := range players {
|
||||||
|
if player.local {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
go player.updateRemotePlayerMap()
|
||||||
|
go player.updateRemotePlayerBases(bases)
|
||||||
|
go player.updateRemotePlayerBullets(bullets)
|
||||||
|
go player.updateRemotePlayerBulletParticles(bulletParticles)
|
||||||
|
go player.updateRemotePlayerPlayers(players)
|
||||||
|
fail := player.sendInfoToPlayer()
|
||||||
|
if fail {
|
||||||
|
if player.connection != nil {
|
||||||
|
(*player.connection).Close()
|
||||||
|
}
|
||||||
|
delete(players, player.playerID)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fail = player.sendUpdatesToPlayer(players)
|
||||||
|
if fail {
|
||||||
|
if player.connection != nil {
|
||||||
|
(*player.connection).Close()
|
||||||
|
}
|
||||||
|
delete(players, player.playerID)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, bullet := range bullets {
|
||||||
(*bullet).tick(gameMap, bulletParticles, bullets, players)
|
(*bullet).tick(gameMap, bulletParticles, bullets, players)
|
||||||
}
|
}
|
||||||
for _, base := range *bases {
|
for _, player := range players {
|
||||||
|
if player.local {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
(*player).tick(bullets)
|
||||||
|
}
|
||||||
|
for _, base := range bases {
|
||||||
(*base).tick(players)
|
(*base).tick(players)
|
||||||
}
|
}
|
||||||
for _, bulletParticle := range *bulletParticles {
|
for _, bulletParticle := range bulletParticles {
|
||||||
bulletParticle.tick(bulletParticles)
|
bulletParticle.tick(bulletParticles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func initPlayer(playerIndex uint8, player *Player) {
|
func initPlayer(playerIndex uint8, player *Player) {
|
||||||
|
if !player.local {
|
||||||
|
return
|
||||||
|
}
|
||||||
player.window, player.logicalSurface = setupWindowAndSurface(playerIndex)
|
player.window, player.logicalSurface = setupWindowAndSurface(playerIndex)
|
||||||
logicalColor := sdl.MapRGBA(player.logicalSurface.Format, 101, 101, 0, 255)
|
logicalColor := sdl.MapRGBA(player.logicalSurface.Format, 101, 101, 0, 255)
|
||||||
player.logicalSurface.FillRect(nil, logicalColor)
|
player.logicalSurface.FillRect(nil, logicalColor)
|
||||||
@ -165,13 +345,13 @@ func initPlayer(playerIndex uint8, player *Player) {
|
|||||||
|
|
||||||
player.HUDSurface, player.HUDSurfaceRect, player.HUDSurfaceTargetRect = setupHUDSurface()
|
player.HUDSurface, player.HUDSurfaceRect, player.HUDSurfaceTargetRect = setupHUDSurface()
|
||||||
initHud(player.HUDSurface)
|
initHud(player.HUDSurface)
|
||||||
player.camera = &sdl.Rect{X: 0, Y: 0, W: 76, H: 76}
|
player.camera = &sdl.Rect{X: 0, Y: 0, W: config.CameraW, H: config.CameraH}
|
||||||
}
|
}
|
||||||
|
|
||||||
func doPlayerFrame(playerIndex uint8, player *Player, players *[]*Player, gameMap *GameMap, bases *[]*Base, bullets *[]*Bullet, bulletParticles *[]*BulletParticle) bool {
|
func doPlayerFrame(playerIndex uint8, player *Player, players map[uint32]*Player, gameMap *GameMap, bases map[uint32]*Base, bullets map[uint32]*Bullet, bulletParticles map[uint32]*BulletParticle) bool {
|
||||||
running := true
|
running := true
|
||||||
var (
|
var (
|
||||||
isShooting, shouldContinue bool
|
shouldContinue bool
|
||||||
)
|
)
|
||||||
frameStart := sdl.GetTicks64()
|
frameStart := sdl.GetTicks64()
|
||||||
|
|
||||||
@ -179,7 +359,7 @@ func doPlayerFrame(playerIndex uint8, player *Player, players *[]*Player, gameMa
|
|||||||
player.totalHandleEventsTime += profileSection(func() {
|
player.totalHandleEventsTime += profileSection(func() {
|
||||||
running = handleEvents(player.window, player.logicalSurface)
|
running = handleEvents(player.window, player.logicalSurface)
|
||||||
keyboard := sdl.GetKeyboardState()
|
keyboard := sdl.GetKeyboardState()
|
||||||
shouldContinue, isShooting = handleInput(keyboard, bullets, player, gameMap, players)
|
shouldContinue = handleInput(keyboard, bullets, player, gameMap, players)
|
||||||
running = running && shouldContinue
|
running = running && shouldContinue
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -188,20 +368,21 @@ func doPlayerFrame(playerIndex uint8, player *Player, players *[]*Player, gameMa
|
|||||||
player.track(player.camera)
|
player.track(player.camera)
|
||||||
gameMap.render(player.camera, player.playSurface)
|
gameMap.render(player.camera, player.playSurface)
|
||||||
|
|
||||||
for _, bullet := range *bullets {
|
for _, bullet := range bullets {
|
||||||
(*bullet).render(player.camera, player.playSurface)
|
(*bullet).render(player.camera, player.playSurface, bullets)
|
||||||
}
|
}
|
||||||
for _, base := range *bases {
|
for _, base := range bases {
|
||||||
(*base).render(player.camera, player.playSurface)
|
(*base).render(player.camera, player.playSurface, bases)
|
||||||
}
|
}
|
||||||
for _, playerLoop := range *players {
|
for _, playerLoop := range players {
|
||||||
(*playerLoop).render(player.camera, player.playSurface)
|
(*playerLoop).render(player.camera, player.playSurface, players)
|
||||||
}
|
}
|
||||||
for _, bulletParticle := range *bulletParticles {
|
for _, bulletParticle := range bulletParticles {
|
||||||
bulletParticle.render(player.camera, player.playSurface)
|
bulletParticle.render(player.camera, player.playSurface, bulletParticles)
|
||||||
}
|
}
|
||||||
|
|
||||||
player.tick(isShooting, bullets, player.playSurface.Format)
|
player.tick(bullets)
|
||||||
|
player.gameObject.prevBaseRect = player.gameObject.baseRect
|
||||||
renderHud(player, player.HUDSurface)
|
renderHud(player, player.HUDSurface)
|
||||||
player.playSurface.BlitScaled(player.playSurfaceRect, player.logicalSurface, player.playSurfaceTargetRect)
|
player.playSurface.BlitScaled(player.playSurfaceRect, player.logicalSurface, player.playSurfaceTargetRect)
|
||||||
player.HUDSurface.BlitScaled(player.HUDSurfaceRect, player.logicalSurface, player.HUDSurfaceTargetRect)
|
player.HUDSurface.BlitScaled(player.HUDSurfaceRect, player.logicalSurface, player.HUDSurfaceTargetRect)
|
||||||
@ -217,7 +398,7 @@ func doPlayerFrame(playerIndex uint8, player *Player, players *[]*Player, gameMa
|
|||||||
player.frameCount++
|
player.frameCount++
|
||||||
|
|
||||||
// Log profiling information every 1000 frames
|
// Log profiling information every 1000 frames
|
||||||
if player.frameCount%ProfilerInterval == 0 && ProfilerOn && playerIndex == 0 {
|
if player.frameCount%config.ProfilerInterval == 0 && config.ProfilerOn && playerIndex == 0 {
|
||||||
logProfilingInfo(player.totalHandleEventsTime, player.totalRenderTime, player.totalScalingTime, player.totalFrameTime, player.frameCount)
|
logProfilingInfo(player.totalHandleEventsTime, player.totalRenderTime, player.totalScalingTime, player.totalFrameTime, player.frameCount)
|
||||||
resetProfilingCounters(&player.totalHandleEventsTime, &player.totalRenderTime, &player.totalScalingTime, &player.totalFrameTime, &player.frameCount)
|
resetProfilingCounters(&player.totalHandleEventsTime, &player.totalRenderTime, &player.totalScalingTime, &player.totalFrameTime, &player.frameCount)
|
||||||
}
|
}
|
||||||
|
33
map.go
33
map.go
@ -16,8 +16,8 @@ type GameMap struct {
|
|||||||
//tile 3 - soil 2
|
//tile 3 - soil 2
|
||||||
//tile 4 - base
|
//tile 4 - base
|
||||||
//tile 5 - world edge (should not be present in the map object)
|
//tile 5 - world edge (should not be present in the map object)
|
||||||
width int32
|
width uint32
|
||||||
height int32
|
height uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetTileColorValue(value uint8) color.Color {
|
func GetTileColorValue(value uint8) color.Color {
|
||||||
@ -40,7 +40,7 @@ func GetTileColorValue(value uint8) color.Color {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gameMap *GameMap) getTileColor(x int32, y int32) color.Color {
|
func (gameMap *GameMap) getTileColor(x int32, y int32) color.Color {
|
||||||
if x < 0 || x >= gameMap.width || y < 0 || y >= gameMap.height {
|
if x < 0 || x >= int32(gameMap.width) || y < 0 || y >= int32(gameMap.height) {
|
||||||
return GetTileColorValue(5)
|
return GetTileColorValue(5)
|
||||||
} else {
|
} else {
|
||||||
tileValue := gameMap.tiles[x][y]
|
tileValue := gameMap.tiles[x][y]
|
||||||
@ -48,10 +48,9 @@ func (gameMap *GameMap) getTileColor(x int32, y int32) color.Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gameMap *GameMap) createGameMap(width int32, height int32) {
|
func (gameMap *GameMap) createGameMap(withData bool) {
|
||||||
// Initialize the 2D slice for game tiles
|
// Initialize the 2D slice for game tiles
|
||||||
gameMap.tiles = make([][]uint8, width)
|
gameMap.tiles = make([][]uint8, serverConfig.MapWidth)
|
||||||
|
|
||||||
// Create Perlin noise generators
|
// Create Perlin noise generators
|
||||||
perlinNoiseRock := perlin.NewPerlin(2, 4, 8, time.Now().Unix())
|
perlinNoiseRock := perlin.NewPerlin(2, 4, 8, time.Now().Unix())
|
||||||
perlinNoiseSoil := perlin.NewPerlin(2, 8, 4, time.Now().Unix())
|
perlinNoiseSoil := perlin.NewPerlin(2, 8, 4, time.Now().Unix())
|
||||||
@ -61,23 +60,24 @@ func (gameMap *GameMap) createGameMap(width int32, height int32) {
|
|||||||
|
|
||||||
// Loop over the rows
|
// Loop over the rows
|
||||||
for i := range gameMap.tiles {
|
for i := range gameMap.tiles {
|
||||||
|
|
||||||
|
if withData {
|
||||||
|
// Launch a goroutine for each row
|
||||||
// Increment WaitGroup counter for each goroutine
|
// Increment WaitGroup counter for each goroutine
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
||||||
// Launch a goroutine for each row
|
|
||||||
go func(i int) {
|
go func(i int) {
|
||||||
defer wg.Done() // Signal that this goroutine is done
|
defer wg.Done() // Signal that this goroutine is done
|
||||||
|
|
||||||
// Initialize the row
|
// Initialize the row
|
||||||
gameMap.tiles[i] = make([]uint8, height)
|
gameMap.tiles[i] = make([]uint8, serverConfig.MapHeight)
|
||||||
|
|
||||||
// Process each tile in the row
|
// Process each tile in the row
|
||||||
for j := range gameMap.tiles[i] {
|
for j := range gameMap.tiles[i] {
|
||||||
perlinRock := perlinNoiseRock.Noise2D(float64(i)/float64(width)*6, float64(j)/float64(height)*6)
|
perlinRock := perlinNoiseRock.Noise2D(float64(i)/float64(serverConfig.MapWidth)*6, float64(j)/float64(serverConfig.MapHeight)*6)
|
||||||
if perlinRock > 0.2 {
|
if perlinRock > 0.2 {
|
||||||
gameMap.tiles[i][j] = 1
|
gameMap.tiles[i][j] = 1
|
||||||
} else {
|
} else {
|
||||||
perlinSoil := perlinNoiseSoil.Noise2D(float64(i)/float64(width)*10, float64(j)/float64(height)*10)
|
perlinSoil := perlinNoiseSoil.Noise2D(float64(i)/float64(serverConfig.MapWidth)*10, float64(j)/float64(serverConfig.MapHeight)*10)
|
||||||
if perlinSoil >= 0 {
|
if perlinSoil >= 0 {
|
||||||
gameMap.tiles[i][j] = 2
|
gameMap.tiles[i][j] = 2
|
||||||
} else {
|
} else {
|
||||||
@ -86,14 +86,19 @@ func (gameMap *GameMap) createGameMap(width int32, height int32) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}(i)
|
}(i)
|
||||||
|
} else {
|
||||||
|
for x := uint32(0); x < serverConfig.MapWidth; x++ {
|
||||||
|
gameMap.tiles[x] = make([]uint8, serverConfig.MapHeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for all goroutines to finish
|
// Wait for all goroutines to finish
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
// Set the dimensions of the game map
|
// Set the dimensions of the game map
|
||||||
gameMap.width = width
|
gameMap.width = serverConfig.MapWidth
|
||||||
gameMap.height = height
|
gameMap.height = serverConfig.MapHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gameMap *GameMap) render(camera *sdl.Rect, surface *sdl.Surface) {
|
func (gameMap *GameMap) render(camera *sdl.Rect, surface *sdl.Surface) {
|
||||||
@ -131,7 +136,7 @@ func (gameMap *GameMap) checkCollision(posX, posY int32) uint8 {
|
|||||||
//1 destructible collision
|
//1 destructible collision
|
||||||
//2 rock collision
|
//2 rock collision
|
||||||
//3 indestructible collision
|
//3 indestructible collision
|
||||||
if posX >= gameMap.width || posX < 0 || posY >= gameMap.height || posY < 0 {
|
if posX >= int32(gameMap.width) || posX < 0 || posY >= int32(gameMap.height) || posY < 0 {
|
||||||
return 3
|
return 3
|
||||||
}
|
}
|
||||||
switch gameMap.tiles[posX][posY] {
|
switch gameMap.tiles[posX][posY] {
|
||||||
|
@ -74,15 +74,15 @@ type PlayerColors struct {
|
|||||||
|
|
||||||
func getNeededPlayers() (neededPlayers uint8) {
|
func getNeededPlayers() (neededPlayers uint8) {
|
||||||
neededPlayers = 0
|
neededPlayers = 0
|
||||||
if DoAllKeymapsPlayers {
|
if config.DoAllKeymapsPlayers {
|
||||||
neededPlayers += uint8(len(keyMaps))
|
neededPlayers += uint8(len(keyMaps))
|
||||||
} else if DoKeymapPlayer && len(keyMaps) > 0 {
|
} else if config.DoKeymapPlayer && len(keyMaps) > 0 {
|
||||||
neededPlayers++
|
neededPlayers++
|
||||||
}
|
}
|
||||||
if DoJoyStickPlayers {
|
if config.DoJoyStickPlayers {
|
||||||
neededPlayers += uint8(sdl.NumJoysticks())
|
neededPlayers += uint8(sdl.NumJoysticks())
|
||||||
}
|
}
|
||||||
if neededPlayers < 2 {
|
if neededPlayers < 2 && !config.Server {
|
||||||
neededPlayers = 2
|
neededPlayers = 2
|
||||||
}
|
}
|
||||||
return neededPlayers
|
return neededPlayers
|
||||||
@ -285,9 +285,9 @@ func initPlayerColors() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleInput(keyboard []uint8, bullets *[]*Bullet, player *Player, gameMap *GameMap, players *[]*Player) (bool, bool) {
|
func handleInput(keyboard []uint8, bullets map[uint32]*Bullet, player *Player, gameMap *GameMap, players map[uint32]*Player) bool {
|
||||||
if !player.local || player.shields <= 0 || player.shields > MaxShields {
|
if !player.local || player.shields <= 0 || player.shields > serverConfig.MaxShields {
|
||||||
return true, false
|
return true
|
||||||
}
|
}
|
||||||
shoot := false
|
shoot := false
|
||||||
super := false
|
super := false
|
||||||
@ -306,7 +306,7 @@ func handleInput(keyboard []uint8, bullets *[]*Bullet, player *Player, gameMap *
|
|||||||
}
|
}
|
||||||
|
|
||||||
if key == player.keyMap.exit {
|
if key == player.keyMap.exit {
|
||||||
return false, shoot
|
return false
|
||||||
} else if key == player.keyMap.shoot {
|
} else if key == player.keyMap.shoot {
|
||||||
shoot = true
|
shoot = true
|
||||||
} else if key == player.keyMap.super {
|
} else if key == player.keyMap.super {
|
||||||
@ -329,10 +329,10 @@ func handleInput(keyboard []uint8, bullets *[]*Bullet, player *Player, gameMap *
|
|||||||
xAxis := player.joyStick.Axis(player.joyMap.xAxis)
|
xAxis := player.joyStick.Axis(player.joyMap.xAxis)
|
||||||
yAxis := player.joyStick.Axis(player.joyMap.yAxis)
|
yAxis := player.joyStick.Axis(player.joyMap.yAxis)
|
||||||
|
|
||||||
moveRight = xAxis > JoyStickDeadZone
|
moveRight = xAxis > config.JoyStickDeadZone
|
||||||
moveLeft = xAxis < -JoyStickDeadZone
|
moveLeft = xAxis < -config.JoyStickDeadZone
|
||||||
moveUp = yAxis > JoyStickDeadZone
|
moveUp = yAxis > config.JoyStickDeadZone
|
||||||
moveDown = yAxis < -JoyStickDeadZone
|
moveDown = yAxis < -config.JoyStickDeadZone
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
moveUp = player.joyStick.Button(player.joyMap.upButton) == sdl.PRESSED
|
moveUp = player.joyStick.Button(player.joyMap.upButton) == sdl.PRESSED
|
||||||
@ -341,7 +341,7 @@ func handleInput(keyboard []uint8, bullets *[]*Bullet, player *Player, gameMap *
|
|||||||
moveRight = player.joyStick.Button(player.joyMap.rightButton) == sdl.PRESSED
|
moveRight = player.joyStick.Button(player.joyMap.rightButton) == sdl.PRESSED
|
||||||
}
|
}
|
||||||
if player.joyStick.Button(player.joyMap.exitButton) == sdl.PRESSED {
|
if player.joyStick.Button(player.joyMap.exitButton) == sdl.PRESSED {
|
||||||
return false, shoot
|
return false
|
||||||
}
|
}
|
||||||
if player.joyStick.Button(player.joyMap.shootButton) == sdl.PRESSED {
|
if player.joyStick.Button(player.joyMap.shootButton) == sdl.PRESSED {
|
||||||
shoot = true
|
shoot = true
|
||||||
@ -379,9 +379,9 @@ func handleInput(keyboard []uint8, bullets *[]*Bullet, player *Player, gameMap *
|
|||||||
// Handle movement after the loop
|
// Handle movement after the loop
|
||||||
if moveUp || moveDown || moveLeft || moveRight {
|
if moveUp || moveDown || moveLeft || moveRight {
|
||||||
if player.tryMove(gameMap, shoot, players) {
|
if player.tryMove(gameMap, shoot, players) {
|
||||||
player.energy -= MovementCost
|
player.energy -= serverConfig.MovementCost
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, shoot
|
return true
|
||||||
}
|
}
|
||||||
|
133
tuneller.proto
Normal file
133
tuneller.proto
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package goingtunneling;
|
||||||
|
option go_package = "./proto";
|
||||||
|
|
||||||
|
message Position {
|
||||||
|
int32 posX = 1;
|
||||||
|
int32 posY = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Player {
|
||||||
|
uint32 playerID = 1;
|
||||||
|
PlayerLocation location = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PlayerLocation {
|
||||||
|
Position position = 1;
|
||||||
|
uint32 orientation = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Bullet {
|
||||||
|
Position position = 1;
|
||||||
|
uint32 direction = 2;
|
||||||
|
Color color = 3;
|
||||||
|
uint32 id = 4;
|
||||||
|
bool super = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Color {
|
||||||
|
uint32 red = 1;
|
||||||
|
uint32 green = 2;
|
||||||
|
uint32 blue = 3;
|
||||||
|
uint32 alpha = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BulletParticle {
|
||||||
|
Position position = 1;
|
||||||
|
uint32 expirationTimer = 2;
|
||||||
|
Color color = 3;
|
||||||
|
uint32 id = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ServerInfo {
|
||||||
|
uint32 maxEnergy = 1;
|
||||||
|
uint32 maxAmmunition = 2;
|
||||||
|
uint32 maxShields = 3;
|
||||||
|
uint32 mapWidth = 4;
|
||||||
|
uint32 mapHeight = 5;
|
||||||
|
uint32 normalShotCost = 6;
|
||||||
|
uint32 superShotCost = 7;
|
||||||
|
uint32 reloadCost = 8;
|
||||||
|
uint32 movementCost = 9;
|
||||||
|
uint32 diggingCost = 10;
|
||||||
|
uint32 shootDiggingBonus = 11;
|
||||||
|
uint32 shootCooldown = 12;
|
||||||
|
uint32 rechargeCooldown = 13;
|
||||||
|
uint32 rechargeOpponentCooldown = 14;
|
||||||
|
uint32 repairCooldown = 15;
|
||||||
|
uint32 diggingCooldown = 16;
|
||||||
|
uint32 movementCooldown = 17;
|
||||||
|
uint32 movementCooldownNoEnergy = 18;
|
||||||
|
uint32 diggingCooldownNoEnergy = 19;
|
||||||
|
uint32 reloadCooldown = 20;
|
||||||
|
uint32 blastRadius = 21;
|
||||||
|
uint32 playerID = 22;
|
||||||
|
uint32 playerColorID = 23;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PlayerUpdate {
|
||||||
|
uint32 energy = 1;
|
||||||
|
uint32 ammo = 2;
|
||||||
|
uint32 shields = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BaseLocation {
|
||||||
|
Position position = 1;
|
||||||
|
Player owner = 2;
|
||||||
|
Color color = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TileUpdate {
|
||||||
|
Position position = 1;
|
||||||
|
uint32 kind = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WorldUpdate {
|
||||||
|
repeated Player players = 1;
|
||||||
|
repeated BaseLocation base = 2;
|
||||||
|
repeated Bullet bullets = 3;
|
||||||
|
repeated BulletParticle bulletParticles = 4;
|
||||||
|
repeated TileUpdate tileUpdate = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ClientBound {
|
||||||
|
oneof clientBoundMessage {
|
||||||
|
ServerInfo serverInfo = 1;
|
||||||
|
PlayerUpdate playerUpdate = 2;
|
||||||
|
PlayerLocation playerLocationUpdate = 3;
|
||||||
|
WorldUpdate worldUpdate = 4;
|
||||||
|
PlayerStartResponse playerStartResponse = 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message DigBlock {
|
||||||
|
Position position = 1;
|
||||||
|
bool isShooting = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Shoot {
|
||||||
|
bool super = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PlayerAction {
|
||||||
|
oneof playerAction {
|
||||||
|
DigBlock digBlock = 1;
|
||||||
|
Shoot shoot = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message PlayerStartRequest {
|
||||||
|
string version = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PlayerStartResponse {
|
||||||
|
string version = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ServerBound {
|
||||||
|
oneof serverBoundMessage {
|
||||||
|
PlayerLocation playerPosition = 1;
|
||||||
|
PlayerAction playerAction = 2;
|
||||||
|
PlayerStartRequest playerStartRequest = 3;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user