package main import ( "github.com/veandco/go-sdl2/sdl" "image/color" "strconv" "sync" ) var baseMutex sync.RWMutex type Base struct { ownerID uint32 openingWidth int32 gameObject *GameObject } func (base *Base) tick(players map[uint32]*Player) { playersMutex.RLock() for playerID, player := range players { if player.gameObject.baseRect.HasIntersection(base.gameObject.baseRect) { if player.rechargeCooldown == 0 && player.energy < serverConfig.MaxEnergy { if serverConfig.MaxEnergy-player.energy < 4 { player.energy++ } else { player.energy += 4 } if playerID == base.ownerID { player.rechargeCooldown = serverConfig.RechargeCooldownOwn } else { player.rechargeCooldown = serverConfig.RechargeCooldownOpponent } } if playerID == base.ownerID && player.repairCooldown == 0 && player.shields < serverConfig.MaxShields { player.shields++ player.repairCooldown = serverConfig.RepairCooldown } } } playersMutex.RUnlock() } func (base *Base) render(camera *sdl.Rect, surface *sdl.Surface, bases map[uint32]*Base) { base.gameObject.render(camera, surface) if !base.gameObject.inView && !config.Server { delete(bases, base.ownerID) } } func (base *Base) build(gameMap *GameMap) { if gameMap.width-uint32(base.gameObject.baseRect.X)-uint32(base.gameObject.baseRect.W) <= 0 { panic("Bad base x location") } if gameMap.height-uint32(base.gameObject.baseRect.Y)-uint32(base.gameObject.baseRect.H) <= 0 { panic("Bad base y location") } if base.gameObject.baseRect.X < 0 || base.gameObject.baseRect.Y < 0 { panic("Bad base negative location " + strconv.Itoa(int(base.gameObject.baseRect.X)) + " - " + strconv.Itoa(int(base.gameObject.baseRect.Y))) } base.gameObject.adjustBaseRect() for x := base.gameObject.baseRect.X; x < base.gameObject.baseRect.X+base.gameObject.baseRect.W; x++ { for y := base.gameObject.baseRect.Y; y < base.gameObject.baseRect.Y+base.gameObject.baseRect.H; y++ { gameMap.tiles[x][y] = 0 } } for _, rectT := range base.gameObject.getCurrentRects() { rect := sdl.Rect{ X: rectT.rect.X + base.gameObject.baseRect.X, Y: rectT.rect.Y + base.gameObject.baseRect.Y, W: rectT.rect.W, H: rectT.rect.H, } for x := rect.X; x < rect.X+rect.W; x++ { for y := rect.Y; y < rect.Y+rect.H; y++ { gameMap.tiles[x][y] = 4 } } } } func createBase(gameMap *GameMap, baseColor color.Color, posX, posY, ownerID, openingWidth uint32) *Base { gameObject := &GameObject{} gameObject.baseRect = &sdl.Rect{ X: int32(posX), Y: int32(posY), W: 35, H: 35, } if openingWidth%2 == 0 { openingWidth++ } borderWidth := gameObject.baseRect.W - int32(openingWidth) borderWidthA := borderWidth / 2 borderWidthB := borderWidth - borderWidthA + 1 if borderWidth < 0 { panic("Bad border width") } gameObject.addColor(baseColor) gameObject.addColoredRect(0, 0, 1, gameObject.baseRect.H-1, 0) gameObject.addColoredRect(gameObject.baseRect.W, 0, 1, gameObject.baseRect.H-1, 0) gameObject.addColoredRect(0, 0, borderWidthA, 1, 0) gameObject.addColoredRect(borderWidthA+int32(openingWidth), 0, borderWidthB, 1, 0) gameObject.addColoredRect(0, gameObject.baseRect.H-1, borderWidthA, 1, 0) gameObject.addColoredRect(borderWidthA+int32(openingWidth), gameObject.baseRect.H-1, borderWidthB, 1, 0) base := &Base{ gameObject: gameObject, ownerID: ownerID, openingWidth: int32(openingWidth), } 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 } } baseMutex.Lock() delete(bases, base.ownerID) baseMutex.Unlock() } func createBases(players map[uint32]*Player, gameMap *GameMap) map[uint32]*Base { bases := map[uint32]*Base{} playersMutex.RLock() for ownerID, player := range players { baseMutex.Lock() 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), ) baseMutex.Unlock() } playersMutex.RUnlock() return bases }