Add multi monitor multiplayer
This commit is contained in:
parent
352c7af7ce
commit
696b827a7d
146
base.go
146
base.go
@ -2,28 +2,29 @@ package main
|
||||
|
||||
import "github.com/veandco/go-sdl2/sdl"
|
||||
|
||||
const (
|
||||
openingWidth = 7
|
||||
)
|
||||
|
||||
type Base struct {
|
||||
rect sdl.Rect
|
||||
owner *Player
|
||||
owner *Player
|
||||
openingWidth int32
|
||||
gameObject *GameObject
|
||||
}
|
||||
|
||||
func (base *Base) tick(players *[]*Player) {
|
||||
for _, player := range *players {
|
||||
if player.cullingRect.HasIntersection(&base.rect) {
|
||||
if player.gameObject.baseRect.HasIntersection(&base.gameObject.baseRect) {
|
||||
if player.rechargeCooldown == 0 && player.energy < MaxEnergy {
|
||||
player.energy++
|
||||
if MaxEnergy-player.energy < 4 {
|
||||
player.energy++
|
||||
} else {
|
||||
player.energy += 4
|
||||
}
|
||||
if player == base.owner {
|
||||
player.rechargeCooldown = RechargeCooldownOwn
|
||||
} else {
|
||||
player.rechargeCooldown = RechargeCooldownOpponent
|
||||
}
|
||||
}
|
||||
if player == base.owner && player.repairCooldown == 0 && player.health < MaxHealth {
|
||||
player.health++
|
||||
if player == base.owner && player.repairCooldown == 0 && player.shields < MaxShields {
|
||||
player.shields++
|
||||
player.repairCooldown = RepairCooldown
|
||||
}
|
||||
}
|
||||
@ -31,112 +32,79 @@ func (base *Base) tick(players *[]*Player) {
|
||||
}
|
||||
|
||||
func (base *Base) render(camera *sdl.Rect, surface *sdl.Surface) {
|
||||
borderWidth := base.rect.W - openingWidth
|
||||
borderWidthA := borderWidth / 2
|
||||
borderWidthB := borderWidth - borderWidthA + 1
|
||||
if borderWidth < 0 {
|
||||
panic("Bad border width")
|
||||
}
|
||||
rects := []sdl.Rect{
|
||||
{
|
||||
X: base.rect.X,
|
||||
Y: base.rect.Y,
|
||||
W: 1,
|
||||
H: base.rect.H,
|
||||
},
|
||||
{
|
||||
X: base.rect.X + base.rect.W,
|
||||
Y: base.rect.Y,
|
||||
W: 1,
|
||||
H: base.rect.H,
|
||||
},
|
||||
{
|
||||
X: base.rect.X,
|
||||
Y: base.rect.Y,
|
||||
W: borderWidthA,
|
||||
H: 1,
|
||||
},
|
||||
{
|
||||
X: base.rect.X + borderWidthA + openingWidth,
|
||||
Y: base.rect.Y,
|
||||
W: borderWidthB,
|
||||
H: 1,
|
||||
},
|
||||
{
|
||||
X: base.rect.X,
|
||||
Y: base.rect.Y + base.rect.H,
|
||||
W: borderWidthA,
|
||||
H: 1,
|
||||
},
|
||||
{
|
||||
X: base.rect.X + borderWidthA + openingWidth,
|
||||
Y: base.rect.Y + base.rect.H,
|
||||
W: borderWidthB,
|
||||
H: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rect := range rects {
|
||||
if camera.HasIntersection(&rect) {
|
||||
cameraCompensatedRect := sdl.Rect{
|
||||
X: rect.X - camera.X,
|
||||
Y: rect.Y - camera.Y,
|
||||
W: rect.W,
|
||||
H: rect.H,
|
||||
}
|
||||
surface.FillRect(&cameraCompensatedRect, (*base.owner).color2)
|
||||
}
|
||||
}
|
||||
base.gameObject.render(camera, surface)
|
||||
}
|
||||
|
||||
func (base *Base) build(gameMap *GameMap) {
|
||||
borderWidth := base.rect.W - openingWidth
|
||||
borderWidth := base.gameObject.baseRect.W - base.openingWidth
|
||||
borderWidthA := borderWidth / 2
|
||||
if borderWidth < 0 {
|
||||
panic("Bad border width")
|
||||
}
|
||||
if base.rect.H < 9 {
|
||||
if base.gameObject.baseRect.H < 9 {
|
||||
panic("Bad border height")
|
||||
}
|
||||
if gameMap.width-base.rect.X-base.rect.W <= 0 {
|
||||
if gameMap.width-base.gameObject.baseRect.X-base.gameObject.baseRect.W <= 0 {
|
||||
panic("Bad base x location")
|
||||
}
|
||||
if gameMap.height-base.rect.Y-base.rect.H <= 0 {
|
||||
if gameMap.height-base.gameObject.baseRect.Y-base.gameObject.baseRect.H <= 0 {
|
||||
panic("Bad base y location")
|
||||
}
|
||||
if base.rect.X < 0 || base.rect.Y < 0 {
|
||||
if base.gameObject.baseRect.X < 0 || base.gameObject.baseRect.Y < 0 {
|
||||
panic("Bad base negative location")
|
||||
}
|
||||
for x := base.rect.X; x < base.rect.X+base.rect.W+1; x++ {
|
||||
for y := base.rect.Y; y < base.rect.Y+base.rect.H+1; y++ {
|
||||
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
|
||||
}
|
||||
}
|
||||
for y := base.rect.Y; y < base.rect.Y+base.rect.H; y++ {
|
||||
gameMap.tiles[base.rect.X][y] = 4
|
||||
gameMap.tiles[base.rect.X+base.rect.W][y] = 4
|
||||
for y := base.gameObject.baseRect.Y; y < base.gameObject.baseRect.Y+base.gameObject.baseRect.H; y++ {
|
||||
gameMap.tiles[base.gameObject.baseRect.X][y] = 4
|
||||
gameMap.tiles[base.gameObject.baseRect.X+base.gameObject.baseRect.W][y] = 4
|
||||
}
|
||||
for x := base.rect.X; x < base.rect.X+borderWidthA; x++ {
|
||||
gameMap.tiles[x][base.rect.Y] = 4
|
||||
gameMap.tiles[x][base.rect.Y+base.rect.H] = 4
|
||||
for x := base.gameObject.baseRect.X; x < base.gameObject.baseRect.X+borderWidthA; x++ {
|
||||
gameMap.tiles[x][base.gameObject.baseRect.Y] = 4
|
||||
gameMap.tiles[x][base.gameObject.baseRect.Y+base.gameObject.baseRect.H] = 4
|
||||
}
|
||||
for x := base.rect.X + borderWidthA + openingWidth; x < base.rect.X+base.rect.W+1; x++ {
|
||||
gameMap.tiles[x][base.rect.Y] = 4
|
||||
gameMap.tiles[x][base.rect.Y+base.rect.H] = 4
|
||||
for x := base.gameObject.baseRect.X + borderWidthA + base.openingWidth; x < base.gameObject.baseRect.X+base.gameObject.baseRect.W+1; x++ {
|
||||
gameMap.tiles[x][base.gameObject.baseRect.Y] = 4
|
||||
gameMap.tiles[x][base.gameObject.baseRect.Y+base.gameObject.baseRect.H] = 4
|
||||
}
|
||||
}
|
||||
|
||||
func createBases(players *[]*Player, gameMap *GameMap) *[]*Base {
|
||||
bases := &[]*Base{}
|
||||
|
||||
for ownerID, player := range *players {
|
||||
gameObject := &GameObject{}
|
||||
gameObject.baseRect = sdl.Rect{
|
||||
X: player.gameObject.baseRect.X - 14,
|
||||
Y: player.gameObject.baseRect.Y - 14,
|
||||
W: 35,
|
||||
H: 35,
|
||||
}
|
||||
openingWidth := int32(float64(player.gameObject.baseRect.W) * 1.5)
|
||||
if openingWidth%2 == 0 {
|
||||
openingWidth++
|
||||
}
|
||||
|
||||
borderWidth := gameObject.baseRect.W - openingWidth
|
||||
borderWidthA := borderWidth / 2
|
||||
borderWidthB := borderWidth - borderWidthA + 1
|
||||
if borderWidth < 0 {
|
||||
panic("Bad border width")
|
||||
}
|
||||
gameObject.addColor((*player).playerColors.body)
|
||||
gameObject.addColoredRect(0, 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(borderWidthA+openingWidth, 0, borderWidthB, 1, 0)
|
||||
gameObject.addColoredRect(0, gameObject.baseRect.H, borderWidthA, 1, 0)
|
||||
gameObject.addColoredRect(borderWidthA+openingWidth, gameObject.baseRect.H, borderWidthB, 1, 0)
|
||||
*bases = append(*bases, &Base{
|
||||
rect: sdl.Rect{
|
||||
X: player.posX - 14,
|
||||
Y: player.posY - 14,
|
||||
W: 35,
|
||||
H: 35,
|
||||
},
|
||||
owner: (*players)[ownerID],
|
||||
gameObject: gameObject,
|
||||
owner: (*players)[ownerID],
|
||||
openingWidth: openingWidth,
|
||||
})
|
||||
(*bases)[ownerID].build(gameMap)
|
||||
}
|
||||
|
14
bullet.go
14
bullet.go
@ -149,14 +149,16 @@ func (bullet *Bullet) tick(gameMap *GameMap,
|
||||
}
|
||||
hitPlayer := false
|
||||
for _, player := range *players {
|
||||
if player.rect1.HasIntersection(&bulletRect) ||
|
||||
player.rect2.HasIntersection(&bulletRect) ||
|
||||
player.rect3.HasIntersection(&bulletRect) ||
|
||||
player.rect4.HasIntersection(&bulletRect) {
|
||||
hitPlayer = true
|
||||
player.health -= 20
|
||||
if hitPlayer {
|
||||
break
|
||||
}
|
||||
for _, coloredRect := range player.gameObject.getCurrentRects() {
|
||||
if coloredRect.rect.HasIntersection(&bulletRect) {
|
||||
hitPlayer = true
|
||||
player.shields -= 10
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if collisionResult != 0 || hitPlayer {
|
||||
bullet.explode(gameMap, bulletParticleMap)
|
||||
|
87
gameobject.go
Normal file
87
gameobject.go
Normal file
@ -0,0 +1,87 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
"image/color"
|
||||
)
|
||||
|
||||
type GameObject struct {
|
||||
baseRect sdl.Rect
|
||||
borderRect sdl.Rect
|
||||
orientation uint8
|
||||
visualRects [][]*ColoredRect
|
||||
colors []color.Color
|
||||
}
|
||||
|
||||
type ColoredRect struct {
|
||||
color color.Color
|
||||
rect *sdl.Rect
|
||||
}
|
||||
|
||||
func adjustRectToCamera(object *sdl.Rect, camera *sdl.Rect) *sdl.Rect {
|
||||
return &sdl.Rect{
|
||||
X: object.X - camera.X,
|
||||
Y: object.Y - camera.Y,
|
||||
W: object.W,
|
||||
H: object.H,
|
||||
}
|
||||
}
|
||||
|
||||
func (gameObject *GameObject) adjustRectToCamera(offset *sdl.Rect, camera *sdl.Rect) *sdl.Rect {
|
||||
return &sdl.Rect{
|
||||
X: gameObject.baseRect.X + offset.X - camera.X,
|
||||
Y: gameObject.baseRect.Y + offset.Y - camera.Y,
|
||||
W: offset.W,
|
||||
H: offset.H,
|
||||
}
|
||||
}
|
||||
|
||||
func (gameObject *GameObject) render(camera *sdl.Rect, surface *sdl.Surface) {
|
||||
if camera.HasIntersection(&gameObject.baseRect) {
|
||||
if Debug {
|
||||
gameObject.borderRect = sdl.Rect{
|
||||
X: gameObject.baseRect.X - 1,
|
||||
Y: gameObject.baseRect.Y - 1,
|
||||
W: gameObject.baseRect.W + 2,
|
||||
H: gameObject.baseRect.H + 2,
|
||||
}
|
||||
borderRectFinal := adjustRectToCamera(&gameObject.borderRect, camera)
|
||||
baseRectFinal := adjustRectToCamera(&gameObject.baseRect, camera)
|
||||
surface.FillRect(borderRectFinal, sdl.MapRGBA(surface.Format, 20, 192, 128, 64))
|
||||
surface.FillRect(baseRectFinal, sdl.MapRGBA(surface.Format, 255, 20, 10, 64))
|
||||
}
|
||||
if RenderGameObjects {
|
||||
for _, coloredRect := range gameObject.visualRects[gameObject.orientation] {
|
||||
finalRect := gameObject.adjustRectToCamera(coloredRect.rect, camera)
|
||||
r, g, b, a := coloredRect.color.RGBA()
|
||||
surface.FillRect(finalRect, sdl.MapRGBA(surface.Format, uint8(r), uint8(g), uint8(b), uint8(a)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (gameObject *GameObject) addColoredRect(x, y, w, h int32, color uint8) {
|
||||
if gameObject.visualRects == nil {
|
||||
gameObject.visualRects = make([][]*ColoredRect, 0)
|
||||
}
|
||||
if uint8(len(gameObject.visualRects)) <= gameObject.orientation {
|
||||
gameObject.visualRects = append(gameObject.visualRects, make([]*ColoredRect, 0))
|
||||
}
|
||||
if uint8(len(gameObject.colors)) > color {
|
||||
gameObject.visualRects[gameObject.orientation] = append(gameObject.visualRects[gameObject.orientation],
|
||||
&ColoredRect{
|
||||
color: gameObject.colors[color],
|
||||
rect: &sdl.Rect{
|
||||
X: x, Y: y, W: w, H: h,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (gameObject *GameObject) getCurrentRects() []*ColoredRect {
|
||||
return gameObject.visualRects[gameObject.orientation]
|
||||
}
|
||||
|
||||
func (gameObject *GameObject) addColor(color color.Color) {
|
||||
gameObject.colors = append(gameObject.colors, color)
|
||||
}
|
90
graphics.go
90
graphics.go
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
)
|
||||
|
||||
@ -10,9 +11,24 @@ func initializeSDL() {
|
||||
}
|
||||
}
|
||||
|
||||
func setupWindowAndSurface() (*sdl.Window, *sdl.Surface) {
|
||||
func setupWindowAndSurface(playerIndex uint8) (*sdl.Window, *sdl.Surface) {
|
||||
const windowWidth, windowHeight = 160, 100
|
||||
window, err := sdl.CreateWindow("test", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, windowWidth, windowHeight, sdl.WINDOW_SHOWN|sdl.WINDOW_RESIZABLE)
|
||||
window, err := sdl.CreateWindow(fmt.Sprintf("Tunneler - player %d", playerIndex), sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, windowWidth, windowHeight, sdl.WINDOW_SHOWN|sdl.WINDOW_RESIZABLE)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
logicalSurface, err := sdl.CreateRGBSurface(0, windowWidth, windowHeight, 32, 0, 0, 0, 0)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return window, logicalSurface
|
||||
}
|
||||
|
||||
func setupMapWindowAndSurface() (*sdl.Window, *sdl.Surface) {
|
||||
const windowWidth, windowHeight = MapWidth, MapHeight
|
||||
window, err := sdl.CreateWindow("Tunneler map", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, windowWidth, windowHeight, sdl.WINDOW_SHOWN|sdl.WINDOW_RESIZABLE)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -81,7 +97,6 @@ func handleWindowResize(window *sdl.Window, logicalSurface *sdl.Surface) {
|
||||
letterboxX := (windowWidth - newWidth) / 2
|
||||
letterboxY := (windowHeight - newHeight) / 2
|
||||
|
||||
windowSurface.FillRect(nil, 0)
|
||||
srcRect := &sdl.Rect{X: 0, Y: 0, W: logicalSurface.W, H: logicalSurface.H}
|
||||
dstRect := &sdl.Rect{X: letterboxX, Y: letterboxY, W: newWidth, H: newHeight}
|
||||
|
||||
@ -89,68 +104,45 @@ func handleWindowResize(window *sdl.Window, logicalSurface *sdl.Surface) {
|
||||
window.UpdateSurface()
|
||||
}
|
||||
|
||||
func renderScene(logicalSurface, playSurface, HUDSurface *sdl.Surface, gameMap *GameMap, players *[]*Player, bases *[]*Base, bullets *[]*Bullet, bulletParticles *[]*BulletParticle, camera *sdl.Rect, playSurfaceRect, playSurfaceTargetRect, HUDSurfaceRect, HUDSurfaceTargetRect *sdl.Rect) {
|
||||
HUDColor := sdl.MapRGBA(HUDSurface.Format, 101, 101, 101, 255)
|
||||
logicalColor := sdl.MapRGBA(HUDSurface.Format, 101, 101, 0, 255)
|
||||
playColor := sdl.MapRGBA(HUDSurface.Format, 101, 0, 101, 255)
|
||||
|
||||
logicalSurface.FillRect(nil, logicalColor)
|
||||
playSurface.FillRect(nil, playColor)
|
||||
HUDSurface.FillRect(nil, HUDColor)
|
||||
|
||||
(*players)[0].track(camera)
|
||||
|
||||
gameMap.render(camera, playSurface)
|
||||
|
||||
for _, bullet := range *bullets {
|
||||
(*bullet).render(camera, playSurface)
|
||||
(*bullet).tick(gameMap, bulletParticles, bullets, players)
|
||||
}
|
||||
|
||||
for _, base := range *bases {
|
||||
(*base).render(camera, playSurface)
|
||||
(*base).tick(players)
|
||||
}
|
||||
|
||||
for _, player := range *players {
|
||||
(*player).render(camera, playSurface)
|
||||
(*player).tick()
|
||||
}
|
||||
|
||||
for _, bulletParticle := range *bulletParticles {
|
||||
bulletParticle.render(camera, playSurface)
|
||||
bulletParticle.tick(bulletParticles)
|
||||
}
|
||||
|
||||
renderHud((*players)[0], HUDSurface)
|
||||
|
||||
playSurface.BlitScaled(playSurfaceRect, logicalSurface, playSurfaceTargetRect)
|
||||
HUDSurface.BlitScaled(HUDSurfaceRect, logicalSurface, HUDSurfaceTargetRect)
|
||||
}
|
||||
|
||||
func adjustWindow(window *sdl.Window, logicalSurface *sdl.Surface, pixelBG uint32) {
|
||||
func adjustWindow(window *sdl.Window, logicalSurface *sdl.Surface) {
|
||||
// Get window surface and handle any errors
|
||||
windowSurface, err := window.GetSurface()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Retrieve window dimensions
|
||||
windowWidth, windowHeight := windowSurface.W, windowSurface.H
|
||||
aspectRatio := float64(logicalSurface.W) / float64(logicalSurface.H)
|
||||
newWidth := windowWidth
|
||||
newHeight := int32(float64(windowWidth) / aspectRatio)
|
||||
|
||||
if newHeight > windowHeight {
|
||||
// Calculate aspect ratio
|
||||
logicalAspectRatio := float64(logicalSurface.W) / float64(logicalSurface.H)
|
||||
windowAspectRatio := float64(windowWidth) / float64(windowHeight)
|
||||
|
||||
var newWidth, newHeight int32
|
||||
if windowAspectRatio > logicalAspectRatio {
|
||||
// Window is wider than logical surface
|
||||
newHeight = windowHeight
|
||||
newWidth = int32(float64(windowHeight) * aspectRatio)
|
||||
newWidth = int32(float64(windowHeight) * logicalAspectRatio)
|
||||
} else {
|
||||
// Window is taller or equal in aspect ratio
|
||||
newWidth = windowWidth
|
||||
newHeight = int32(float64(windowWidth) / logicalAspectRatio)
|
||||
}
|
||||
|
||||
// Calculate letterbox positions
|
||||
letterboxX := (windowWidth - newWidth) / 2
|
||||
letterboxY := (windowHeight - newHeight) / 2
|
||||
|
||||
windowSurface.FillRect(nil, pixelBG)
|
||||
// Fill background
|
||||
windowSurface.FillRect(nil, sdl.MapRGBA(logicalSurface.Format, 80, 20, 10, 255))
|
||||
|
||||
// Set source and destination rectangles
|
||||
srcRect := &sdl.Rect{X: 0, Y: 0, W: logicalSurface.W, H: logicalSurface.H}
|
||||
dstRect := &sdl.Rect{X: letterboxX, Y: letterboxY, W: newWidth, H: newHeight}
|
||||
|
||||
// Perform the scaled blit
|
||||
logicalSurface.BlitScaled(srcRect, windowSurface, dstRect)
|
||||
|
||||
// Update the window surface
|
||||
window.UpdateSurface()
|
||||
}
|
||||
|
151
hud.go
151
hud.go
@ -2,77 +2,82 @@ package main
|
||||
|
||||
import "github.com/veandco/go-sdl2/sdl"
|
||||
|
||||
func renderHud(player *Player, surface *sdl.Surface) {
|
||||
eRects := []sdl.Rect{
|
||||
{
|
||||
X: 5,
|
||||
Y: 4,
|
||||
W: 6,
|
||||
H: 1,
|
||||
},
|
||||
{
|
||||
X: 5,
|
||||
Y: 4,
|
||||
W: 1,
|
||||
H: 5,
|
||||
},
|
||||
{
|
||||
X: 5,
|
||||
Y: 6,
|
||||
W: 6,
|
||||
H: 1,
|
||||
},
|
||||
{
|
||||
X: 5,
|
||||
Y: 8,
|
||||
W: 6,
|
||||
H: 1,
|
||||
},
|
||||
}
|
||||
|
||||
sRects := []sdl.Rect{
|
||||
{
|
||||
X: 5,
|
||||
Y: 18,
|
||||
W: 6,
|
||||
H: 1,
|
||||
},
|
||||
{
|
||||
X: 5,
|
||||
Y: 18,
|
||||
W: 1,
|
||||
H: 3,
|
||||
},
|
||||
{
|
||||
X: 5,
|
||||
Y: 20,
|
||||
W: 6,
|
||||
H: 1,
|
||||
},
|
||||
{
|
||||
X: 10,
|
||||
Y: 20,
|
||||
W: 1,
|
||||
H: 3,
|
||||
},
|
||||
{
|
||||
X: 5,
|
||||
Y: 22,
|
||||
W: 6,
|
||||
H: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rect := range eRects {
|
||||
surface.FillRect(&rect, sdl.MapRGBA(surface.Format, 243, 235, 28, 255))
|
||||
}
|
||||
for _, rect := range sRects {
|
||||
surface.FillRect(&rect, sdl.MapRGBA(surface.Format, 40, 243, 243, 255))
|
||||
}
|
||||
|
||||
surface.FillRect(&sdl.Rect{X: 16, Y: 3, W: 90, H: 7}, sdl.MapRGBA(surface.Format, 0, 0, 0, 255))
|
||||
surface.FillRect(&sdl.Rect{X: 16, Y: 17, W: 90, H: 7}, sdl.MapRGBA(surface.Format, 0, 0, 0, 255))
|
||||
|
||||
surface.FillRect(&sdl.Rect{X: 17, Y: 4, W: int32(player.energy / 20), H: 5}, sdl.MapRGBA(surface.Format, 243, 235, 28, 255))
|
||||
surface.FillRect(&sdl.Rect{X: 17, Y: 18, W: int32(player.health), H: 5}, sdl.MapRGBA(surface.Format, 40, 243, 243, 255))
|
||||
var letterOffsets = []int32{
|
||||
2,
|
||||
10,
|
||||
18,
|
||||
}
|
||||
|
||||
var letterColors []uint32
|
||||
|
||||
// Map function to convert value from range [0, 6] to range [0, 88]
|
||||
func mapRange(x, minX, maxX, minY, maxY uint16) int32 {
|
||||
// Perform conversion to float64 to ensure proper division
|
||||
return int32((float64(x-minX)/float64(maxX-minX))*float64(maxY-minY) + float64(minY))
|
||||
}
|
||||
|
||||
var rects = [][]sdl.Rect{
|
||||
// Define the rects with modified Y-values
|
||||
{
|
||||
{X: 5, Y: 0, W: 6, H: 1},
|
||||
{X: 5, Y: 0, W: 1, H: 5},
|
||||
{X: 5, Y: 2, W: 6, H: 1},
|
||||
{X: 5, Y: 4, W: 6, H: 1},
|
||||
},
|
||||
|
||||
{
|
||||
{X: 6, Y: 0, W: 4, H: 1}, // Top bar of "A"
|
||||
{X: 5, Y: 1, W: 1, H: 4}, // Left vertical line of "A"
|
||||
{X: 10, Y: 1, W: 1, H: 4}, // Right vertical line of "A"
|
||||
{X: 6, Y: 3, W: 4, H: 1}, // Middle bar of "A"
|
||||
},
|
||||
|
||||
{
|
||||
{X: 5, Y: 0, W: 6, H: 1},
|
||||
{X: 5, Y: 0, W: 1, H: 3},
|
||||
{X: 5, Y: 2, W: 6, H: 1},
|
||||
{X: 10, Y: 2, W: 1, H: 3},
|
||||
{X: 5, Y: 4, W: 6, H: 1},
|
||||
},
|
||||
}
|
||||
|
||||
func initHud(surface *sdl.Surface) {
|
||||
letterColors = []uint32{
|
||||
sdl.MapRGBA(surface.Format, 243, 235, 28, 255),
|
||||
sdl.MapRGBA(surface.Format, 255, 80, 40, 255),
|
||||
sdl.MapRGBA(surface.Format, 40, 243, 243, 255),
|
||||
}
|
||||
HUDColor := sdl.MapRGBA(surface.Format, 101, 101, 101, 255)
|
||||
surface.FillRect(nil, HUDColor)
|
||||
|
||||
for letterIndex, letter := range rects {
|
||||
for _, letterRect := range letter {
|
||||
offsetRect := letterRect
|
||||
offsetRect.Y += letterOffsets[letterIndex]
|
||||
surface.FillRect(&offsetRect, letterColors[letterIndex])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func renderHud(player *Player, surface *sdl.Surface) {
|
||||
|
||||
for _, letterOffset := range letterOffsets {
|
||||
surface.FillRect(&sdl.Rect{X: 16, Y: letterOffset - 1, W: 90, H: 7}, 0)
|
||||
}
|
||||
|
||||
HUDValues := []int32{
|
||||
mapRange(player.energy, 0, MaxEnergy, 0, 88),
|
||||
mapRange(player.ammunition, 0, MaxAmmunition, 0, 88),
|
||||
mapRange(player.shields, 0, MaxShields, 0, 88),
|
||||
}
|
||||
|
||||
for HUDValueIndex, HUDValue := range HUDValues {
|
||||
surface.FillRect(
|
||||
&sdl.Rect{
|
||||
X: 17,
|
||||
Y: letterOffsets[HUDValueIndex],
|
||||
W: HUDValue,
|
||||
H: 5},
|
||||
letterColors[HUDValueIndex])
|
||||
}
|
||||
}
|
||||
|
268
main.go
268
main.go
@ -5,15 +5,21 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
MapWidth = 1000 // Width of the map
|
||||
MapHeight = 1000 // Height of the map
|
||||
MaxEnergy = 1760
|
||||
MaxHealth = 88
|
||||
NormalShotCost = 3
|
||||
SuperShotCost = 20
|
||||
MovementCost = 1
|
||||
DiggingCost = 2
|
||||
ShootDiggingCostBonus = 1
|
||||
MapWidth = 1000 // Width of the map
|
||||
MapHeight = 1000 // Height of the map
|
||||
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
|
||||
@ -22,137 +28,159 @@ const (
|
||||
MovementCooldown = 2
|
||||
MovementCooldownNoEnergy = 4
|
||||
DiggingCooldownNoEnergy = 8
|
||||
ReloadCooldown = 16
|
||||
|
||||
Debug = false
|
||||
MapWindow = true
|
||||
RenderGameObjects = true
|
||||
ProfilerOn = true
|
||||
|
||||
JoyStickDeadZone = 8000
|
||||
|
||||
DoAllKeymapsPlayers = true
|
||||
DoJoyStickPlayers = true
|
||||
DoKeymapPlayer = true
|
||||
)
|
||||
|
||||
var mapWindow *sdl.Window
|
||||
var mapSurface *sdl.Surface
|
||||
var mapRendererRect = &sdl.Rect{X: 0, Y: 0, W: MapWidth, H: MapHeight}
|
||||
|
||||
func main() {
|
||||
initializeSDL()
|
||||
defer sdl.Quit()
|
||||
|
||||
window, logicalSurface := setupWindowAndSurface()
|
||||
window.SetTitle("GOing to tunnel")
|
||||
defer window.Destroy()
|
||||
defer logicalSurface.Free()
|
||||
|
||||
playSurface, playSurfaceRect, playSurfaceTargetRect := setupPlaySurface()
|
||||
defer playSurface.Free()
|
||||
|
||||
HUDSurface, HUDSurfaceRect, HUDSurfaceTargetRect := setupHUDSurface()
|
||||
defer HUDSurface.Free()
|
||||
|
||||
pixelBG := sdl.MapRGBA(logicalSurface.Format, 80, 20, 10, 255)
|
||||
|
||||
gameMap := GameMap{}
|
||||
gameMap := &GameMap{}
|
||||
gameMap.createGameMap(MapWidth, MapHeight)
|
||||
|
||||
players := &[]*Player{}
|
||||
initPlayerColors()
|
||||
createPlayers(getNeededPlayers(), playerColors, keyMaps, joyMaps, gameMap, players)
|
||||
|
||||
createPlayer(
|
||||
sdl.MapRGBA(playSurface.Format, 0, 0, 182, 255),
|
||||
sdl.MapRGBA(playSurface.Format, 44, 44, 255, 255),
|
||||
sdl.MapRGBA(playSurface.Format, 243, 235, 28, 255),
|
||||
&gameMap,
|
||||
players)
|
||||
defer closeThings(players)
|
||||
|
||||
createPlayer(
|
||||
sdl.MapRGBA(playSurface.Format, 44, 184, 44, 255),
|
||||
sdl.MapRGBA(playSurface.Format, 0, 249, 0, 255),
|
||||
sdl.MapRGBA(playSurface.Format, 243, 235, 28, 255),
|
||||
&gameMap,
|
||||
players)
|
||||
bases := createBases(players, gameMap)
|
||||
|
||||
bases := createBases(players, &gameMap)
|
||||
|
||||
bulletMap := &[]*Bullet{}
|
||||
bulletParticleMap := &[]*BulletParticle{}
|
||||
|
||||
camera := sdl.Rect{X: 0, Y: 0, W: 76, H: 76}
|
||||
bullets := &[]*Bullet{}
|
||||
bulletParticles := &[]*BulletParticle{}
|
||||
|
||||
for playerIndex, player := range *players {
|
||||
initPlayer(uint8(playerIndex), player)
|
||||
}
|
||||
if MapWindow {
|
||||
mapWindow, mapSurface = setupMapWindowAndSurface()
|
||||
}
|
||||
running := true
|
||||
for running {
|
||||
currentTime := sdl.GetTicks64()
|
||||
frameStart := sdl.GetTicks64()
|
||||
for playerIndex, player := range *players {
|
||||
// Delay to achieve roughly 60 FPS
|
||||
if player.local {
|
||||
running = doPlayerFrame(uint8(playerIndex), player, players, gameMap, bases, bullets, bulletParticles)
|
||||
if !running {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if MapWindow {
|
||||
gameMap.render(mapRendererRect, mapSurface)
|
||||
for _, bullet := range *bullets {
|
||||
(*bullet).render(mapRendererRect, mapSurface)
|
||||
}
|
||||
for _, base := range *bases {
|
||||
(*base).render(mapRendererRect, mapSurface)
|
||||
}
|
||||
for _, playerLoop := range *players {
|
||||
(*playerLoop).render(mapRendererRect, mapSurface)
|
||||
}
|
||||
for _, bulletParticle := range *bulletParticles {
|
||||
bulletParticle.render(mapRendererRect, mapSurface)
|
||||
}
|
||||
adjustWindow(mapWindow, mapSurface)
|
||||
}
|
||||
//now tick world
|
||||
for _, bullet := range *bullets {
|
||||
(*bullet).tick(gameMap, bulletParticles, bullets, players)
|
||||
}
|
||||
for _, base := range *bases {
|
||||
(*base).tick(players)
|
||||
}
|
||||
for _, bulletParticle := range *bulletParticles {
|
||||
bulletParticle.tick(bulletParticles)
|
||||
}
|
||||
|
||||
running = handleEvents(window, logicalSurface)
|
||||
enforceFrameRate(frameStart, 60)
|
||||
}
|
||||
}
|
||||
|
||||
func initPlayer(playerIndex uint8, player *Player) {
|
||||
player.window, player.logicalSurface = setupWindowAndSurface(playerIndex)
|
||||
logicalColor := sdl.MapRGBA(player.logicalSurface.Format, 101, 101, 0, 255)
|
||||
player.logicalSurface.FillRect(nil, logicalColor)
|
||||
|
||||
player.playSurface, player.playSurfaceRect, player.playSurfaceTargetRect = setupPlaySurface()
|
||||
playColor := sdl.MapRGBA(player.playSurface.Format, 101, 0, 101, 255)
|
||||
player.playSurface.FillRect(nil, playColor)
|
||||
|
||||
player.HUDSurface, player.HUDSurfaceRect, player.HUDSurfaceTargetRect = setupHUDSurface()
|
||||
initHud(player.HUDSurface)
|
||||
player.camera = &sdl.Rect{X: 0, Y: 0, W: 76, H: 76}
|
||||
}
|
||||
|
||||
func doPlayerFrame(playerIndex uint8, player *Player, players *[]*Player, gameMap *GameMap, bases *[]*Base, bullets *[]*Bullet, bulletParticles *[]*BulletParticle) bool {
|
||||
running := true
|
||||
var (
|
||||
totalHandleEventsTime, totalRenderTime, totalFrameTime uint64
|
||||
totalScalingTime, frameCount uint64
|
||||
isShooting, shouldContinue bool
|
||||
)
|
||||
frameStart := sdl.GetTicks64()
|
||||
|
||||
// Profile handleEvents
|
||||
totalHandleEventsTime += profileSection(func() {
|
||||
running = handleEvents(player.window, player.logicalSurface)
|
||||
keyboard := sdl.GetKeyboardState()
|
||||
shouldContinue, isShooting = handleInput(keyboard, bullets, player, gameMap, player.playSurface.Format, players)
|
||||
running = running && shouldContinue
|
||||
})
|
||||
|
||||
running = running && handleInput(keyboard, bulletMap, (*players)[0], &gameMap, playSurface.Format, players)
|
||||
// Profile rendering (aggregate all renderings)
|
||||
totalRenderTime += profileSection(func() {
|
||||
player.track(player.camera)
|
||||
gameMap.render(player.camera, player.playSurface)
|
||||
|
||||
renderScene(logicalSurface, playSurface, HUDSurface, &gameMap, players, bases, bulletMap, bulletParticleMap, &camera, playSurfaceRect, playSurfaceTargetRect, HUDSurfaceRect, HUDSurfaceTargetRect)
|
||||
|
||||
adjustWindow(window, logicalSurface, pixelBG)
|
||||
|
||||
// Calculate delay to achieve roughly 60 FPS
|
||||
frameDuration := 1000 / 60
|
||||
elapsed := sdl.GetTicks64() - currentTime
|
||||
if delay := frameDuration - int(elapsed); delay > 0 {
|
||||
sdl.Delay(uint32(delay))
|
||||
for _, bullet := range *bullets {
|
||||
(*bullet).render(player.camera, player.playSurface)
|
||||
}
|
||||
for _, base := range *bases {
|
||||
(*base).render(player.camera, player.playSurface)
|
||||
}
|
||||
for _, playerLoop := range *players {
|
||||
(*playerLoop).render(player.camera, player.playSurface)
|
||||
}
|
||||
for _, bulletParticle := range *bulletParticles {
|
||||
bulletParticle.render(player.camera, player.playSurface)
|
||||
}
|
||||
|
||||
player.tick(isShooting, bullets, player.playSurface.Format)
|
||||
renderHud(player, player.HUDSurface)
|
||||
player.playSurface.BlitScaled(player.playSurfaceRect, player.logicalSurface, player.playSurfaceTargetRect)
|
||||
player.HUDSurface.BlitScaled(player.HUDSurfaceRect, player.logicalSurface, player.HUDSurfaceTargetRect)
|
||||
})
|
||||
|
||||
// Profile window adjustments
|
||||
totalScalingTime += profileSection(func() {
|
||||
adjustWindow(player.window, player.logicalSurface)
|
||||
})
|
||||
|
||||
frameEnd := sdl.GetTicks64()
|
||||
totalFrameTime += frameEnd - frameStart
|
||||
frameCount++
|
||||
|
||||
// Log profiling information every 1000 frames
|
||||
if frameCount%1000 == 0 && ProfilerOn && playerIndex == 0 {
|
||||
logProfilingInfo(totalHandleEventsTime, totalRenderTime, totalScalingTime, totalFrameTime, frameCount)
|
||||
resetProfilingCounters(&totalHandleEventsTime, &totalRenderTime, &totalScalingTime, &totalFrameTime, &frameCount)
|
||||
}
|
||||
}
|
||||
|
||||
func handleInput(keyboard []uint8, bullets *[]*Bullet, player *Player, gameMap *GameMap, format *sdl.PixelFormat, players *[]*Player) bool {
|
||||
shoot := false
|
||||
super := false
|
||||
|
||||
// Flags to track movement in each direction
|
||||
moveUp := false
|
||||
moveDown := false
|
||||
moveLeft := false
|
||||
moveRight := false
|
||||
|
||||
// Process keyboard input
|
||||
for key, value := range keyboard {
|
||||
if value == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if key == sdl.SCANCODE_ESCAPE {
|
||||
return false
|
||||
} else if key == sdl.SCANCODE_SPACE {
|
||||
shoot = true
|
||||
} else if key == sdl.SCANCODE_LCTRL {
|
||||
super = true
|
||||
} else if key == sdl.SCANCODE_W {
|
||||
moveUp = true
|
||||
} else if key == sdl.SCANCODE_S {
|
||||
moveDown = true
|
||||
} else if key == sdl.SCANCODE_A {
|
||||
moveLeft = true
|
||||
} else if key == sdl.SCANCODE_D {
|
||||
moveRight = true
|
||||
}
|
||||
}
|
||||
|
||||
// Handle shooting after the loop
|
||||
if shoot {
|
||||
player.shoot(super, bullets, format)
|
||||
}
|
||||
|
||||
// Determine player orientation for diagonal movement
|
||||
if moveUp && moveRight {
|
||||
player.orientation = 4 // Up-Right
|
||||
} else if moveUp && moveLeft {
|
||||
player.orientation = 5 // Up-Left
|
||||
} else if moveDown && moveRight {
|
||||
player.orientation = 6 // Down-Right
|
||||
} else if moveDown && moveLeft {
|
||||
player.orientation = 7 // Down-Left
|
||||
} else if moveUp {
|
||||
player.orientation = 0 // Up
|
||||
} else if moveRight {
|
||||
player.orientation = 1 // Right
|
||||
} else if moveDown {
|
||||
player.orientation = 2 // Down
|
||||
} else if moveLeft {
|
||||
player.orientation = 3 // Left
|
||||
}
|
||||
|
||||
// Handle movement after the loop
|
||||
if moveUp || moveDown || moveLeft || moveRight {
|
||||
if player.tryMove(gameMap, shoot, players) {
|
||||
player.energy -= MovementCost
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
return running
|
||||
}
|
||||
|
4
map.go
4
map.go
@ -49,12 +49,12 @@ func (gameMap *GameMap) getTileColor(x int32, y int32) color.Color {
|
||||
|
||||
func (gameMap *GameMap) createGameMap(width int32, height int32) {
|
||||
gameMap.tiles = make([][]uint8, width)
|
||||
perlinNoiseRock := perlin.NewPerlin(2, 2, 4, time.Now().Unix())
|
||||
perlinNoiseRock := perlin.NewPerlin(2, 4, 8, time.Now().Unix())
|
||||
perlinNoiseSoil := perlin.NewPerlin(2, 8, 4, time.Now().Unix())
|
||||
for i := range gameMap.tiles {
|
||||
gameMap.tiles[i] = make([]uint8, height)
|
||||
for j := range gameMap.tiles[i] {
|
||||
perlinRock := perlinNoiseRock.Noise2D(float64(i)/float64(width)*3, float64(j)/float64(height)*3)
|
||||
perlinRock := perlinNoiseRock.Noise2D(float64(i)/float64(width)*6, float64(j)/float64(height)*6)
|
||||
if perlinRock > 0.2 {
|
||||
gameMap.tiles[i][j] = 1
|
||||
} else {
|
||||
|
540
player.go
540
player.go
@ -7,107 +7,50 @@ import (
|
||||
)
|
||||
|
||||
type Player struct {
|
||||
posX int32
|
||||
posY int32
|
||||
orientation uint8
|
||||
color1 uint32
|
||||
color2 uint32
|
||||
color3 uint32
|
||||
local bool
|
||||
playerColors PlayerColors
|
||||
keyMap KeyMap
|
||||
joyMap JoyMap
|
||||
joyStick *sdl.Joystick
|
||||
camera *sdl.Rect
|
||||
energy uint16
|
||||
health uint16
|
||||
ammunition uint16
|
||||
shields uint16
|
||||
digCooldown uint8
|
||||
shootCooldown uint8
|
||||
repairCooldown uint8
|
||||
rechargeCooldown uint8
|
||||
movementCooldown uint8
|
||||
rect1 sdl.Rect
|
||||
rect2 sdl.Rect
|
||||
rect3 sdl.Rect
|
||||
rect4 sdl.Rect
|
||||
cullingRect sdl.Rect
|
||||
reloadCooldown uint8
|
||||
gameObject *GameObject
|
||||
|
||||
window *sdl.Window
|
||||
|
||||
logicalSurface *sdl.Surface
|
||||
playSurface *sdl.Surface
|
||||
HUDSurface *sdl.Surface
|
||||
|
||||
playSurfaceRect *sdl.Rect
|
||||
HUDSurfaceRect *sdl.Rect
|
||||
|
||||
playSurfaceTargetRect *sdl.Rect
|
||||
HUDSurfaceTargetRect *sdl.Rect
|
||||
}
|
||||
|
||||
func (player *Player) track(camera *sdl.Rect) {
|
||||
camera.X = player.posX - 37
|
||||
camera.Y = player.posY - 38
|
||||
camera.X = player.gameObject.baseRect.X - 37
|
||||
camera.Y = player.gameObject.baseRect.Y - 38
|
||||
}
|
||||
|
||||
func (player *Player) render(camera *sdl.Rect, surface *sdl.Surface) {
|
||||
relativePlayerX := player.posX - camera.X
|
||||
relativePlayerY := player.posY - camera.Y
|
||||
|
||||
switch player.orientation {
|
||||
case 0: // Up
|
||||
player.rect1 = sdl.Rect{X: relativePlayerX, Y: relativePlayerY + 1, W: 1, H: 6}
|
||||
player.rect2 = sdl.Rect{X: relativePlayerX + 4, Y: relativePlayerY + 1, W: 1, H: 6}
|
||||
player.rect3 = sdl.Rect{X: relativePlayerX + 1, Y: relativePlayerY + 2, W: 3, H: 4}
|
||||
player.rect4 = sdl.Rect{X: relativePlayerX + 2, Y: relativePlayerY, W: 1, H: 4}
|
||||
|
||||
case 1: // Right
|
||||
player.rect1 = sdl.Rect{X: relativePlayerX + 1, Y: relativePlayerY + 1, W: 6, H: 1}
|
||||
player.rect2 = sdl.Rect{X: relativePlayerX + 1, Y: relativePlayerY + 5, W: 6, H: 1}
|
||||
player.rect3 = sdl.Rect{X: relativePlayerX + 2, Y: relativePlayerY + 2, W: 4, H: 3}
|
||||
player.rect4 = sdl.Rect{X: relativePlayerX + 4, Y: relativePlayerY + 3, W: 4, H: 1}
|
||||
|
||||
case 2: // Down
|
||||
player.rect1 = sdl.Rect{X: relativePlayerX, Y: relativePlayerY + 1, W: 1, H: 6}
|
||||
player.rect2 = sdl.Rect{X: relativePlayerX + 4, Y: relativePlayerY + 1, W: 1, H: 6}
|
||||
player.rect3 = sdl.Rect{X: relativePlayerX + 1, Y: relativePlayerY + 2, W: 3, H: 4}
|
||||
player.rect4 = sdl.Rect{X: relativePlayerX + 2, Y: relativePlayerY + 4, W: 1, H: 4}
|
||||
|
||||
case 3: // Left
|
||||
player.rect1 = sdl.Rect{X: relativePlayerX + 1, Y: relativePlayerY + 1, W: 6, H: 1}
|
||||
player.rect2 = sdl.Rect{X: relativePlayerX + 1, Y: relativePlayerY + 5, W: 6, H: 1}
|
||||
player.rect3 = sdl.Rect{X: relativePlayerX + 2, Y: relativePlayerY + 2, W: 4, H: 3}
|
||||
player.rect4 = sdl.Rect{X: relativePlayerX, Y: relativePlayerY + 3, W: 4, H: 1}
|
||||
|
||||
case 4: // Up-Right
|
||||
player.rect1 = sdl.Rect{X: relativePlayerX + 1, Y: relativePlayerY + 6, W: 5, H: 1}
|
||||
player.rect2 = sdl.Rect{X: relativePlayerX + 1, Y: relativePlayerY + 2, W: 1, H: 4}
|
||||
player.rect3 = sdl.Rect{X: relativePlayerX + 2, Y: relativePlayerY + 2, W: 4, H: 4}
|
||||
player.rect4 = sdl.Rect{X: relativePlayerX + 4, Y: relativePlayerY + 2, W: 2, H: 2}
|
||||
|
||||
case 5: // Up-Left
|
||||
player.rect1 = sdl.Rect{X: relativePlayerX + 1, Y: relativePlayerY + 6, W: 5, H: 1}
|
||||
player.rect2 = sdl.Rect{X: relativePlayerX + 5, Y: relativePlayerY + 2, W: 1, H: 5}
|
||||
player.rect3 = sdl.Rect{X: relativePlayerX + 1, Y: relativePlayerY + 2, W: 4, H: 4}
|
||||
player.rect4 = sdl.Rect{X: relativePlayerX + 1, Y: relativePlayerY + 2, W: 2, H: 2}
|
||||
|
||||
case 6: // Down-Right
|
||||
player.rect1 = sdl.Rect{X: relativePlayerX + 1, Y: relativePlayerY + 1, W: 5, H: 1}
|
||||
player.rect2 = sdl.Rect{X: relativePlayerX + 1, Y: relativePlayerY + 1, W: 1, H: 5}
|
||||
player.rect3 = sdl.Rect{X: relativePlayerX + 2, Y: relativePlayerY + 2, W: 4, H: 4}
|
||||
player.rect4 = sdl.Rect{X: relativePlayerX + 4, Y: relativePlayerY + 4, W: 2, H: 2}
|
||||
|
||||
case 7: // Down-Left
|
||||
player.rect1 = sdl.Rect{X: relativePlayerX + 1, Y: relativePlayerY + 1, W: 4, H: 1}
|
||||
player.rect2 = sdl.Rect{X: relativePlayerX + 5, Y: relativePlayerY + 1, W: 1, H: 5}
|
||||
player.rect3 = sdl.Rect{X: relativePlayerX + 1, Y: relativePlayerY + 2, W: 4, H: 4}
|
||||
player.rect4 = sdl.Rect{X: relativePlayerX + 1, Y: relativePlayerY + 4, W: 2, H: 2}
|
||||
}
|
||||
|
||||
// Common part: Rendering player
|
||||
player.cullingRect = sdl.Rect{X: player.posX, Y: player.posY, W: 7, H: 7}
|
||||
cameraAdjustedCullingRect := sdl.Rect{
|
||||
X: player.cullingRect.X - camera.X,
|
||||
Y: player.cullingRect.Y - camera.Y,
|
||||
W: player.cullingRect.W,
|
||||
H: player.cullingRect.H,
|
||||
}
|
||||
cameraAdjustedCullingRectBorder := sdl.Rect{
|
||||
X: player.cullingRect.X - camera.X - 1,
|
||||
Y: player.cullingRect.Y - camera.Y - 1,
|
||||
W: player.cullingRect.W + 2,
|
||||
H: player.cullingRect.H + 2,
|
||||
}
|
||||
if camera.HasIntersection(&player.cullingRect) {
|
||||
surface.FillRect(&cameraAdjustedCullingRectBorder, sdl.MapRGBA(surface.Format, 10, 255, 255, 64))
|
||||
surface.FillRect(&cameraAdjustedCullingRect, sdl.MapRGBA(surface.Format, 255, 20, 10, 64))
|
||||
surface.FillRect(&player.rect1, player.color1)
|
||||
surface.FillRect(&player.rect2, player.color1)
|
||||
surface.FillRect(&player.rect3, player.color2)
|
||||
surface.FillRect(&player.rect4, player.color3)
|
||||
player.gameObject.baseRect = sdl.Rect{X: player.gameObject.baseRect.X, Y: player.gameObject.baseRect.Y, W: 7, H: 7}
|
||||
|
||||
if player.shields > 0 && player.shields <= MaxShields {
|
||||
player.gameObject.render(camera, surface)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (player *Player) digBlock(posX, posY int32, gameMap *GameMap, isShooting bool) uint8 {
|
||||
@ -122,7 +65,7 @@ func (player *Player) digBlock(posX, posY int32, gameMap *GameMap, isShooting bo
|
||||
return 2
|
||||
}
|
||||
|
||||
func (player *Player) tick() {
|
||||
func (player *Player) tick(isShooting bool, bullets *[]*Bullet, format *sdl.PixelFormat) {
|
||||
if player.digCooldown > 0 {
|
||||
player.digCooldown--
|
||||
}
|
||||
@ -138,6 +81,17 @@ func (player *Player) tick() {
|
||||
if player.movementCooldown > 0 {
|
||||
player.movementCooldown--
|
||||
}
|
||||
if player.reloadCooldown > 0 {
|
||||
player.reloadCooldown--
|
||||
} else if player.ammunition < MaxAmmunition && !isShooting && player.energy > ReloadCost {
|
||||
player.ammunition++
|
||||
player.reloadCooldown = ReloadCooldown
|
||||
player.energy -= ReloadCost
|
||||
}
|
||||
if player.shields <= 0 {
|
||||
player.shields = MaxShields + 1
|
||||
player.explode(bullets)
|
||||
}
|
||||
}
|
||||
|
||||
func (player *Player) tryMove(gameMap *GameMap, isShooting bool, players *[]*Player) (moved bool) {
|
||||
@ -151,21 +105,21 @@ func (player *Player) tryMove(gameMap *GameMap, isShooting bool, players *[]*Pla
|
||||
shouldPenalizeDigging := false
|
||||
stopped := false
|
||||
|
||||
switch player.orientation {
|
||||
switch player.gameObject.orientation {
|
||||
case 0: // Up
|
||||
collisionRect := sdl.Rect{
|
||||
X: player.posX,
|
||||
Y: player.posY - 1,
|
||||
X: player.gameObject.baseRect.X,
|
||||
Y: player.gameObject.baseRect.Y - 1,
|
||||
W: 5,
|
||||
H: 7,
|
||||
}
|
||||
for _, opponent := range *players {
|
||||
if opponent != player && opponent.cullingRect.HasIntersection(&collisionRect) {
|
||||
if opponent != player && opponent.gameObject.baseRect.HasIntersection(&collisionRect) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for x := player.posX; x < player.posX+5 && !stopped; x++ {
|
||||
for y := player.posY - 1; y < player.posY+7; y++ {
|
||||
for x := player.gameObject.baseRect.X; x < player.gameObject.baseRect.X+5 && !stopped; x++ {
|
||||
for y := player.gameObject.baseRect.Y - 1; y < player.gameObject.baseRect.Y+7; y++ {
|
||||
digResult := player.digBlock(x, y, gameMap, isShooting)
|
||||
if digResult == 1 {
|
||||
shouldPenalizeDigging = true
|
||||
@ -181,23 +135,23 @@ func (player *Player) tryMove(gameMap *GameMap, isShooting bool, players *[]*Pla
|
||||
}
|
||||
if !stopped {
|
||||
moved = true
|
||||
player.posY--
|
||||
player.gameObject.baseRect.Y--
|
||||
}
|
||||
|
||||
case 1: // Right
|
||||
collisionRect := sdl.Rect{
|
||||
X: player.posX + 1,
|
||||
Y: player.posY,
|
||||
X: player.gameObject.baseRect.X + 1,
|
||||
Y: player.gameObject.baseRect.Y,
|
||||
W: 7,
|
||||
H: 5,
|
||||
}
|
||||
for _, opponent := range *players {
|
||||
if opponent != player && opponent.cullingRect.HasIntersection(&collisionRect) {
|
||||
if opponent != player && opponent.gameObject.baseRect.HasIntersection(&collisionRect) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for y := player.posY; y < player.posY+7 && !stopped; y++ {
|
||||
for x := player.posX + 1; x < player.posX+8; x++ {
|
||||
for y := player.gameObject.baseRect.Y + 1; y < player.gameObject.baseRect.Y+6 && !stopped; y++ {
|
||||
for x := player.gameObject.baseRect.X + 1; x < player.gameObject.baseRect.X+8; x++ {
|
||||
digResult := player.digBlock(x, y, gameMap, isShooting)
|
||||
if digResult == 1 {
|
||||
shouldPenalizeDigging = true
|
||||
@ -213,23 +167,23 @@ func (player *Player) tryMove(gameMap *GameMap, isShooting bool, players *[]*Pla
|
||||
}
|
||||
if !stopped {
|
||||
moved = true
|
||||
player.posX++
|
||||
player.gameObject.baseRect.X++
|
||||
}
|
||||
|
||||
case 2: // Down
|
||||
collisionRect := sdl.Rect{
|
||||
X: player.posX,
|
||||
Y: player.posY + 1,
|
||||
X: player.gameObject.baseRect.X,
|
||||
Y: player.gameObject.baseRect.Y + 1,
|
||||
W: 5,
|
||||
H: 7,
|
||||
}
|
||||
for _, opponent := range *players {
|
||||
if opponent != player && opponent.cullingRect.HasIntersection(&collisionRect) {
|
||||
if opponent != player && opponent.gameObject.baseRect.HasIntersection(&collisionRect) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for x := player.posX; x < player.posX+5 && !stopped; x++ {
|
||||
for y := player.posY + 1; y < player.posY+8; y++ {
|
||||
for x := player.gameObject.baseRect.X; x < player.gameObject.baseRect.X+5 && !stopped; x++ {
|
||||
for y := player.gameObject.baseRect.Y + 1; y < player.gameObject.baseRect.Y+8; y++ {
|
||||
digResult := player.digBlock(x, y, gameMap, isShooting)
|
||||
if digResult == 1 {
|
||||
shouldPenalizeDigging = true
|
||||
@ -245,23 +199,23 @@ func (player *Player) tryMove(gameMap *GameMap, isShooting bool, players *[]*Pla
|
||||
}
|
||||
if !stopped {
|
||||
moved = true
|
||||
player.posY++
|
||||
player.gameObject.baseRect.Y++
|
||||
}
|
||||
|
||||
case 3: // Left
|
||||
collisionRect := sdl.Rect{
|
||||
X: player.posX - 1,
|
||||
Y: player.posY,
|
||||
X: player.gameObject.baseRect.X - 1,
|
||||
Y: player.gameObject.baseRect.Y,
|
||||
W: 7,
|
||||
H: 5,
|
||||
}
|
||||
for _, opponent := range *players {
|
||||
if opponent != player && opponent.cullingRect.HasIntersection(&collisionRect) {
|
||||
if opponent != player && opponent.gameObject.baseRect.HasIntersection(&collisionRect) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for y := player.posY; y < player.posY+6 && !stopped; y++ {
|
||||
for x := player.posX - 1; x < player.posX+6; x++ {
|
||||
for y := player.gameObject.baseRect.Y + 1; y < player.gameObject.baseRect.Y+6 && !stopped; y++ {
|
||||
for x := player.gameObject.baseRect.X - 1; x < player.gameObject.baseRect.X+6; x++ {
|
||||
digResult := player.digBlock(x, y, gameMap, isShooting)
|
||||
if digResult == 1 {
|
||||
shouldPenalizeDigging = true
|
||||
@ -277,23 +231,23 @@ func (player *Player) tryMove(gameMap *GameMap, isShooting bool, players *[]*Pla
|
||||
}
|
||||
if !stopped {
|
||||
moved = true
|
||||
player.posX--
|
||||
player.gameObject.baseRect.X--
|
||||
}
|
||||
|
||||
case 4: // Up-Right
|
||||
collisionRect := sdl.Rect{
|
||||
X: player.posX + 1,
|
||||
Y: player.posY - 1,
|
||||
X: player.gameObject.baseRect.X + 1,
|
||||
Y: player.gameObject.baseRect.Y - 1,
|
||||
W: 7,
|
||||
H: 7,
|
||||
}
|
||||
for _, opponent := range *players {
|
||||
if opponent != player && opponent.cullingRect.HasIntersection(&collisionRect) {
|
||||
if opponent != player && opponent.gameObject.baseRect.HasIntersection(&collisionRect) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for x := player.posX + 1; x < player.posX+8 && !stopped; x++ {
|
||||
for y := player.posY - 1; y < player.posY+7; y++ {
|
||||
for x := player.gameObject.baseRect.X + 1; x < player.gameObject.baseRect.X+8 && !stopped; x++ {
|
||||
for y := player.gameObject.baseRect.Y - 1; y < player.gameObject.baseRect.Y+6; y++ {
|
||||
digResult := player.digBlock(x, y, gameMap, isShooting)
|
||||
if digResult == 1 {
|
||||
shouldPenalizeDigging = true
|
||||
@ -309,24 +263,24 @@ func (player *Player) tryMove(gameMap *GameMap, isShooting bool, players *[]*Pla
|
||||
}
|
||||
if !stopped {
|
||||
moved = true
|
||||
player.posX++
|
||||
player.posY--
|
||||
player.gameObject.baseRect.X++
|
||||
player.gameObject.baseRect.Y--
|
||||
}
|
||||
|
||||
case 5: // Up-Left
|
||||
collisionRect := sdl.Rect{
|
||||
X: player.posX - 1,
|
||||
Y: player.posY - 1,
|
||||
X: player.gameObject.baseRect.X - 1,
|
||||
Y: player.gameObject.baseRect.Y - 1,
|
||||
W: 7,
|
||||
H: 7,
|
||||
}
|
||||
for _, opponent := range *players {
|
||||
if opponent != player && opponent.cullingRect.HasIntersection(&collisionRect) {
|
||||
if opponent != player && opponent.gameObject.baseRect.HasIntersection(&collisionRect) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for x := player.posX - 1; x < player.posX+6 && !stopped; x++ {
|
||||
for y := player.posY - 1; y < player.posY+7; y++ {
|
||||
for x := player.gameObject.baseRect.X - 1; x < player.gameObject.baseRect.X+6 && !stopped; x++ {
|
||||
for y := player.gameObject.baseRect.Y - 1; y < player.gameObject.baseRect.Y+6; y++ {
|
||||
digResult := player.digBlock(x, y, gameMap, isShooting)
|
||||
if digResult == 1 {
|
||||
shouldPenalizeDigging = true
|
||||
@ -342,24 +296,24 @@ func (player *Player) tryMove(gameMap *GameMap, isShooting bool, players *[]*Pla
|
||||
}
|
||||
if !stopped {
|
||||
moved = true
|
||||
player.posX--
|
||||
player.posY--
|
||||
player.gameObject.baseRect.X--
|
||||
player.gameObject.baseRect.Y--
|
||||
}
|
||||
|
||||
case 6: // Down-Right
|
||||
collisionRect := sdl.Rect{
|
||||
X: player.posX + 1,
|
||||
Y: player.posY + 1,
|
||||
X: player.gameObject.baseRect.X + 1,
|
||||
Y: player.gameObject.baseRect.Y + 1,
|
||||
W: 7,
|
||||
H: 7,
|
||||
}
|
||||
for _, opponent := range *players {
|
||||
if opponent != player && opponent.cullingRect.HasIntersection(&collisionRect) {
|
||||
if opponent != player && opponent.gameObject.baseRect.HasIntersection(&collisionRect) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for x := player.posX + 1; x < player.posX+8 && !stopped; x++ {
|
||||
for y := player.posY + 1; y < player.posY+8; y++ {
|
||||
for x := player.gameObject.baseRect.X + 1; x < player.gameObject.baseRect.X+8 && !stopped; x++ {
|
||||
for y := player.gameObject.baseRect.Y + 1; y < player.gameObject.baseRect.Y+8; y++ {
|
||||
digResult := player.digBlock(x, y, gameMap, isShooting)
|
||||
if digResult == 1 {
|
||||
shouldPenalizeDigging = true
|
||||
@ -375,24 +329,24 @@ func (player *Player) tryMove(gameMap *GameMap, isShooting bool, players *[]*Pla
|
||||
}
|
||||
if !stopped {
|
||||
moved = true
|
||||
player.posX++
|
||||
player.posY++
|
||||
player.gameObject.baseRect.X++
|
||||
player.gameObject.baseRect.Y++
|
||||
}
|
||||
|
||||
case 7: // Down-Left
|
||||
collisionRect := sdl.Rect{
|
||||
X: player.posX - 1,
|
||||
Y: player.posY + 1,
|
||||
X: player.gameObject.baseRect.X - 1,
|
||||
Y: player.gameObject.baseRect.Y + 1,
|
||||
W: 7,
|
||||
H: 7,
|
||||
}
|
||||
for _, opponent := range *players {
|
||||
if opponent != player && opponent.cullingRect.HasIntersection(&collisionRect) {
|
||||
if opponent != player && opponent.gameObject.baseRect.HasIntersection(&collisionRect) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for x := player.posX - 1; x < player.posX+6 && !stopped; x++ {
|
||||
for y := player.posY + 1; y < player.posY+8; y++ {
|
||||
for x := player.gameObject.baseRect.X - 1; x < player.gameObject.baseRect.X+6 && !stopped; x++ {
|
||||
for y := player.gameObject.baseRect.Y + 1; y < player.gameObject.baseRect.Y+8; y++ {
|
||||
digResult := player.digBlock(x, y, gameMap, isShooting)
|
||||
if digResult == 1 {
|
||||
shouldPenalizeDigging = true
|
||||
@ -408,13 +362,16 @@ func (player *Player) tryMove(gameMap *GameMap, isShooting bool, players *[]*Pla
|
||||
}
|
||||
if !stopped {
|
||||
moved = true
|
||||
player.posX--
|
||||
player.posY++
|
||||
player.gameObject.baseRect.X--
|
||||
player.gameObject.baseRect.Y++
|
||||
}
|
||||
}
|
||||
|
||||
// Penalties and cooldown handling
|
||||
if shouldPenalizeDigging {
|
||||
if isShooting && player.ammunition < MaxAmmunition && rand.Intn(2) == 0 {
|
||||
player.ammunition++
|
||||
}
|
||||
if ranOutOfEnergy {
|
||||
player.digCooldown = DiggingCooldownNoEnergy
|
||||
}
|
||||
@ -433,96 +390,327 @@ func (player *Player) tryMove(gameMap *GameMap, isShooting bool, players *[]*Pla
|
||||
return
|
||||
}
|
||||
|
||||
func (player *Player) shoot(super bool, bullets *[]*Bullet, format *sdl.PixelFormat) {
|
||||
if (super && player.energy <= SuperShotCost) || (!super && player.energy <= NormalShotCost) {
|
||||
func (player *Player) getRGBAColor(colorIndex uint8, format *sdl.PixelFormat) uint32 {
|
||||
var selectedColor color.Color
|
||||
switch colorIndex {
|
||||
case 0:
|
||||
selectedColor = player.playerColors.tracks
|
||||
case 1:
|
||||
selectedColor = player.playerColors.body
|
||||
case 2:
|
||||
selectedColor = player.playerColors.cannon
|
||||
}
|
||||
var r, g, b, a uint8
|
||||
if selectedColor != nil {
|
||||
rt, gt, bt, at := selectedColor.RGBA()
|
||||
r, g, b, a = uint8(rt), uint8(gt), uint8(bt), uint8(at)
|
||||
}
|
||||
return sdl.MapRGBA(format, r, g, b, a)
|
||||
|
||||
}
|
||||
|
||||
func (player *Player) shoot(super bool, bullets *[]*Bullet) {
|
||||
if (super && (player.energy <= SuperShotCost || player.ammunition < MaxAmmunition)) || (!super && (player.energy <= NormalShotCost || player.ammunition < 1)) {
|
||||
return
|
||||
}
|
||||
if player.shootCooldown == 0 {
|
||||
var shootX, shootY int32
|
||||
|
||||
switch player.orientation {
|
||||
switch player.gameObject.orientation {
|
||||
case 0: // Up
|
||||
shootY = player.posY - 1
|
||||
shootX = player.posX + 2
|
||||
shootY = player.gameObject.baseRect.Y - 1
|
||||
shootX = player.gameObject.baseRect.X + 2
|
||||
break
|
||||
case 1: // Right
|
||||
shootY = player.posY + 3
|
||||
shootX = player.posX + 8
|
||||
shootY = player.gameObject.baseRect.Y + 3
|
||||
shootX = player.gameObject.baseRect.X + 8
|
||||
break
|
||||
case 2: // Down
|
||||
shootX = player.posX + 2
|
||||
shootY = player.posY + 8
|
||||
shootX = player.gameObject.baseRect.X + 2
|
||||
shootY = player.gameObject.baseRect.Y + 8
|
||||
break
|
||||
case 3: // Left
|
||||
shootY = player.posY + 3
|
||||
shootX = player.posX - 2
|
||||
shootY = player.gameObject.baseRect.Y + 3
|
||||
shootX = player.gameObject.baseRect.X - 2
|
||||
break
|
||||
case 4: // Up-Right
|
||||
shootY = player.posY - 1
|
||||
shootX = player.posX + 5
|
||||
shootY = player.gameObject.baseRect.Y
|
||||
shootX = player.gameObject.baseRect.X + 5
|
||||
break
|
||||
case 5: // Up-Left
|
||||
shootY = player.posY - 1
|
||||
shootX = player.posX - 1
|
||||
shootY = player.gameObject.baseRect.Y
|
||||
shootX = player.gameObject.baseRect.X - 1
|
||||
break
|
||||
case 6: // Down-Right
|
||||
shootY = player.posY + 5
|
||||
shootX = player.posX + 5
|
||||
shootY = player.gameObject.baseRect.Y + 5
|
||||
shootX = player.gameObject.baseRect.X + 5
|
||||
break
|
||||
case 7: // Down-Left
|
||||
shootY = player.posY + 5
|
||||
shootX = player.posX - 1
|
||||
shootY = player.gameObject.baseRect.Y + 5
|
||||
shootX = player.gameObject.baseRect.X - 1
|
||||
break
|
||||
}
|
||||
|
||||
// Set bullet color
|
||||
r, g, b, a := sdl.GetRGBA(player.color2, format)
|
||||
bulletColor := color.RGBA{R: r, G: g, B: b, A: a}
|
||||
bulletColor := player.playerColors.body
|
||||
|
||||
// Create and add the bullet
|
||||
*bullets = append(*bullets, &Bullet{
|
||||
posX: shootX,
|
||||
posY: shootY,
|
||||
direction: player.orientation,
|
||||
direction: player.gameObject.orientation,
|
||||
color: bulletColor,
|
||||
super: super,
|
||||
})
|
||||
|
||||
// Set cooldown and decrease energy
|
||||
player.shootCooldown = ShootCooldown
|
||||
if super {
|
||||
player.energy -= SuperShotCost
|
||||
player.ammunition = 0
|
||||
} else {
|
||||
player.energy -= NormalShotCost
|
||||
player.ammunition--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createPlayer(color1 uint32, color2 uint32, color3 uint32, gameMap *GameMap, players *[]*Player) {
|
||||
func (player *Player) explode(bullets *[]*Bullet) {
|
||||
// Set bullet color
|
||||
bulletColor := player.playerColors.body
|
||||
|
||||
for x := player.gameObject.baseRect.X - BlastRadius; x < BlastRadius*2+1; x++ {
|
||||
for y := player.gameObject.baseRect.Y - BlastRadius; y < BlastRadius*2+1; y++ {
|
||||
// Create and add the bullet
|
||||
*bullets = append(*bullets, &Bullet{
|
||||
posX: x,
|
||||
posY: y,
|
||||
direction: uint8(rand.Intn(8)),
|
||||
color: bulletColor,
|
||||
super: true,
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createPlayers(amount uint8, playerColors []PlayerColors, keyMaps []KeyMap, joyMaps []JoyMap, gameMap *GameMap, players *[]*Player) {
|
||||
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 (DoAllKeymapsPlayers && i <= uint8(len(keyMaps))) || (DoKeymapPlayer && i == 0) || (uint8(joyStickCount) <= i) {
|
||||
keyMap = keyMaps[addedKeyboardPlayers]
|
||||
addedKeyboardPlayers++
|
||||
} else {
|
||||
joyStickIndex := i - uint8(addedKeyboardPlayers)
|
||||
joyMap = joyMaps[joyStickIndex]
|
||||
joyStick = sdl.JoystickOpen(int(joyStickIndex))
|
||||
}
|
||||
createPlayer(
|
||||
playerColors[i],
|
||||
keyMap,
|
||||
joyMap,
|
||||
joyStick,
|
||||
gameMap,
|
||||
players,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func closeThings(players *[]*Player) {
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createPlayer(playerColors PlayerColors, keyMap KeyMap, joyMap JoyMap, joyStick *sdl.Joystick, gameMap *GameMap, players *[]*Player) {
|
||||
coordsAreValid := false
|
||||
var posX, posY int32
|
||||
for !coordsAreValid {
|
||||
posX = int32(16 + rand.Intn(int(gameMap.width-36)))
|
||||
posY = int32(16 + rand.Intn(int(gameMap.height-36)))
|
||||
maxTries := 1000
|
||||
for !coordsAreValid && maxTries >= 0 {
|
||||
maxTries--
|
||||
posX = int32(16 + rand.Intn(int(gameMap.width-43)))
|
||||
posY = int32(16 + rand.Intn(int(gameMap.height-43)))
|
||||
|
||||
coordsAreValid = true
|
||||
for _, player := range *players {
|
||||
distance := (player.posX-posX)*(player.posX-posX) + (player.posY-posY)*(player.posY-posY)
|
||||
distance := (player.gameObject.baseRect.X-posX)*(player.gameObject.baseRect.X-posX) +
|
||||
(player.gameObject.baseRect.Y-posY)*(player.gameObject.baseRect.Y-posY)
|
||||
if distance < 300*300 { // Check if distance is less than 300 units
|
||||
coordsAreValid = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if posX < 16 || posX > gameMap.width-36-7 || posY < 16 || posY > gameMap.height-36-7 {
|
||||
coordsAreValid = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if maxTries < 0 {
|
||||
panic("Could not place all players, increase map size")
|
||||
}
|
||||
|
||||
gameObject := &GameObject{}
|
||||
|
||||
gameObject.baseRect = sdl.Rect{
|
||||
X: posX,
|
||||
Y: posY,
|
||||
W: 7,
|
||||
H: 7,
|
||||
}
|
||||
|
||||
gameObject.addColor(playerColors.tracks)
|
||||
gameObject.addColor(playerColors.body)
|
||||
gameObject.addColor(playerColors.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(1, 1, 6, 1, 0)
|
||||
gameObject.addColoredRect(1, 5, 6, 1, 0)
|
||||
gameObject.addColoredRect(2, 2, 4, 3, 1)
|
||||
gameObject.addColoredRect(4, 3, 4, 1, 2)
|
||||
|
||||
gameObject.orientation = 2 // Down
|
||||
gameObject.addColoredRect(0, 1, 1, 6, 0)
|
||||
gameObject.addColoredRect(4, 1, 1, 6, 0)
|
||||
gameObject.addColoredRect(1, 2, 3, 4, 1)
|
||||
gameObject.addColoredRect(2, 4, 1, 4, 2)
|
||||
|
||||
gameObject.orientation = 3 // Left
|
||||
gameObject.addColoredRect(1, 1, 6, 1, 0)
|
||||
gameObject.addColoredRect(1, 5, 6, 1, 0)
|
||||
gameObject.addColoredRect(2, 2, 4, 3, 1)
|
||||
gameObject.addColoredRect(0, 3, 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
|
||||
|
||||
*players = append(*players, &Player{
|
||||
posX: posX,
|
||||
posY: posY,
|
||||
orientation: 3,
|
||||
color1: color1,
|
||||
color2: color2,
|
||||
color3: color3,
|
||||
health: MaxHealth,
|
||||
energy: MaxEnergy,
|
||||
playerColors: playerColors,
|
||||
keyMap: keyMap,
|
||||
joyMap: joyMap,
|
||||
joyStick: joyStick,
|
||||
shields: MaxShields,
|
||||
energy: MaxEnergy,
|
||||
gameObject: gameObject,
|
||||
local: true,
|
||||
})
|
||||
}
|
||||
|
387
playerData.go
Normal file
387
playerData.go
Normal file
@ -0,0 +1,387 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
"image/color"
|
||||
)
|
||||
|
||||
type KeyMap struct {
|
||||
exit int
|
||||
shoot int
|
||||
super int
|
||||
up int
|
||||
down int
|
||||
left int
|
||||
right int
|
||||
}
|
||||
|
||||
var keyMaps = []KeyMap{
|
||||
{
|
||||
exit: sdl.SCANCODE_ESCAPE,
|
||||
shoot: sdl.SCANCODE_SPACE,
|
||||
super: sdl.SCANCODE_LCTRL,
|
||||
up: sdl.SCANCODE_W,
|
||||
down: sdl.SCANCODE_S,
|
||||
left: sdl.SCANCODE_A,
|
||||
right: sdl.SCANCODE_D,
|
||||
},
|
||||
{
|
||||
exit: sdl.SCANCODE_END,
|
||||
shoot: sdl.SCANCODE_RETURN,
|
||||
super: sdl.SCANCODE_RCTRL,
|
||||
up: sdl.SCANCODE_UP,
|
||||
down: sdl.SCANCODE_DOWN,
|
||||
left: sdl.SCANCODE_LEFT,
|
||||
right: sdl.SCANCODE_RIGHT,
|
||||
},
|
||||
}
|
||||
|
||||
type JoyMap struct {
|
||||
xAxis int
|
||||
yAxis int
|
||||
|
||||
exitButton int
|
||||
shootButton int
|
||||
superButton int
|
||||
|
||||
upButton int
|
||||
downButton int
|
||||
leftButton int
|
||||
rightButton int
|
||||
}
|
||||
|
||||
var joyMaps = []JoyMap{
|
||||
{
|
||||
xAxis: 0,
|
||||
yAxis: 1,
|
||||
|
||||
exitButton: 0,
|
||||
shootButton: 1,
|
||||
superButton: 2,
|
||||
|
||||
upButton: 3,
|
||||
downButton: 4,
|
||||
leftButton: 5,
|
||||
rightButton: 6,
|
||||
},
|
||||
}
|
||||
|
||||
type PlayerColors struct {
|
||||
tracks color.Color
|
||||
body color.Color
|
||||
cannon color.Color
|
||||
}
|
||||
|
||||
func getNeededPlayers() (neededPlayers uint8) {
|
||||
neededPlayers = 0
|
||||
if DoAllKeymapsPlayers {
|
||||
neededPlayers += uint8(len(keyMaps))
|
||||
} else if DoKeymapPlayer && len(keyMaps) > 0 {
|
||||
neededPlayers++
|
||||
}
|
||||
if DoJoyStickPlayers {
|
||||
neededPlayers += uint8(sdl.NumJoysticks())
|
||||
}
|
||||
if neededPlayers < 2 {
|
||||
neededPlayers = 2
|
||||
}
|
||||
return neededPlayers
|
||||
}
|
||||
|
||||
var playerColors []PlayerColors
|
||||
|
||||
func initPlayerColors() {
|
||||
playerColors = []PlayerColors{
|
||||
{
|
||||
tracks: color.RGBA{B: 182, A: 255},
|
||||
body: color.RGBA{R: 44, G: 44, B: 255, A: 255},
|
||||
cannon: color.RGBA{R: 243, G: 235, B: 28, A: 255},
|
||||
},
|
||||
{
|
||||
tracks: color.RGBA{R: 44, G: 184, B: 44, A: 255},
|
||||
body: color.RGBA{G: 249, A: 255},
|
||||
cannon: color.RGBA{R: 243, G: 235, B: 28, A: 255},
|
||||
},
|
||||
// Set 3
|
||||
{
|
||||
tracks: color.RGBA{R: 255, A: 255}, // Bright Red
|
||||
body: color.RGBA{G: 255, B: 255, A: 255}, // Cyan
|
||||
cannon: color.RGBA{R: 255, G: 165, A: 255}, // Orange
|
||||
},
|
||||
// Set 4
|
||||
{
|
||||
tracks: color.RGBA{R: 75, B: 130, A: 255}, // Indigo
|
||||
body: color.RGBA{R: 255, G: 20, B: 147, A: 255}, // Deep Pink
|
||||
cannon: color.RGBA{G: 128, B: 128, A: 255}, // Teal
|
||||
},
|
||||
// Set 5
|
||||
{
|
||||
tracks: color.RGBA{R: 255, G: 105, B: 180, A: 255}, // Hot Pink
|
||||
body: color.RGBA{R: 34, G: 139, B: 34, A: 255}, // Forest Green
|
||||
cannon: color.RGBA{A: 255}, // Black
|
||||
},
|
||||
// Set 6
|
||||
{
|
||||
tracks: color.RGBA{R: 128, A: 255}, // Maroon
|
||||
body: color.RGBA{R: 255, G: 255, A: 255}, // Yellow
|
||||
cannon: color.RGBA{B: 128, A: 255}, // Navy Blue
|
||||
},
|
||||
// Set 7
|
||||
{
|
||||
tracks: color.RGBA{R: 255, G: 69, A: 255}, // Red-Orange
|
||||
body: color.RGBA{G: 206, B: 209, A: 255}, // Dark Turquoise
|
||||
cannon: color.RGBA{R: 50, G: 205, B: 50, A: 255}, // Lime Green
|
||||
},
|
||||
// Set 8
|
||||
{
|
||||
tracks: color.RGBA{R: 128, G: 128, A: 255}, // Olive
|
||||
body: color.RGBA{R: 255, G: 105, B: 180, A: 255}, // Hot Pink
|
||||
cannon: color.RGBA{G: 191, B: 255, A: 255}, // Deep Sky Blue
|
||||
},
|
||||
// Set 9
|
||||
{
|
||||
tracks: color.RGBA{R: 255, G: 20, B: 20, A: 255}, // Bright Red
|
||||
body: color.RGBA{G: 255, B: 127, A: 255}, // Spring Green
|
||||
cannon: color.RGBA{R: 186, G: 85, B: 211, A: 255}, // Medium Orchid
|
||||
},
|
||||
// Set 10
|
||||
{
|
||||
tracks: color.RGBA{R: 255, G: 215, A: 255}, // Gold
|
||||
body: color.RGBA{B: 139, A: 255}, // Dark Blue
|
||||
cannon: color.RGBA{R: 238, G: 130, B: 238, A: 255}, // Violet
|
||||
},
|
||||
// Set 11
|
||||
{
|
||||
tracks: color.RGBA{R: 210, G: 105, B: 30, A: 255}, // Chocolate
|
||||
body: color.RGBA{R: 72, G: 61, B: 139, A: 255}, // Dark Slate Blue
|
||||
cannon: color.RGBA{R: 152, G: 251, B: 152, A: 255}, // Pale Green
|
||||
},
|
||||
// Set 12
|
||||
{
|
||||
tracks: color.RGBA{R: 220, G: 20, B: 60, A: 255}, // Crimson
|
||||
body: color.RGBA{R: 255, G: 250, B: 205, A: 255}, // Lemon Chiffon
|
||||
cannon: color.RGBA{G: 128, A: 255}, // Green
|
||||
},
|
||||
// Set 13
|
||||
{
|
||||
tracks: color.RGBA{R: 139, B: 139, A: 255}, // Dark Magenta
|
||||
body: color.RGBA{R: 144, G: 238, B: 144, A: 255}, // Light Green
|
||||
cannon: color.RGBA{R: 255, G: 69, A: 255}, // Orange Red
|
||||
},
|
||||
// Set 14
|
||||
{
|
||||
tracks: color.RGBA{B: 255, A: 255}, // Blue
|
||||
body: color.RGBA{R: 240, G: 128, B: 128, A: 255}, // Light Coral
|
||||
cannon: color.RGBA{R: 218, G: 165, B: 32, A: 255}, // Goldenrod
|
||||
},
|
||||
// Set 15
|
||||
{
|
||||
tracks: color.RGBA{R: 65, G: 105, B: 225, A: 255}, // Royal Blue
|
||||
body: color.RGBA{R: 255, G: 222, B: 173, A: 255}, // Navajo White
|
||||
cannon: color.RGBA{R: 255, B: 255, A: 255}, // Magenta
|
||||
},
|
||||
// Set 16
|
||||
{
|
||||
tracks: color.RGBA{R: 147, G: 112, B: 219, A: 255}, // Medium Purple
|
||||
body: color.RGBA{G: 255, B: 127, A: 255}, // Spring Green
|
||||
cannon: color.RGBA{R: 255, G: 255, A: 255}, // Yellow
|
||||
},
|
||||
// Set 17
|
||||
{
|
||||
tracks: color.RGBA{R: 255, G: 140, A: 255}, // Dark Orange
|
||||
body: color.RGBA{R: 127, G: 255, A: 255}, // Chartreuse
|
||||
cannon: color.RGBA{R: 25, G: 25, B: 112, A: 255}, // Midnight Blue
|
||||
},
|
||||
// Set 18
|
||||
{
|
||||
tracks: color.RGBA{R: 240, G: 230, B: 140, A: 255}, // Khaki
|
||||
body: color.RGBA{R: 173, G: 216, B: 230, A: 255}, // Light Blue
|
||||
cannon: color.RGBA{R: 128, B: 128, A: 255}, // Purple
|
||||
},
|
||||
// Set 19
|
||||
{
|
||||
tracks: color.RGBA{R: 70, G: 130, B: 180, A: 255}, // Steel Blue
|
||||
body: color.RGBA{R: 255, G: 99, B: 71, A: 255}, // Tomato
|
||||
cannon: color.RGBA{R: 154, G: 205, B: 50, A: 255}, // Yellow Green
|
||||
},
|
||||
// Set 20
|
||||
{
|
||||
tracks: color.RGBA{R: 106, G: 90, B: 205, A: 255}, // Slate Blue
|
||||
body: color.RGBA{R: 255, G: 182, B: 193, A: 255}, // Light Pink
|
||||
cannon: color.RGBA{R: 46, G: 139, B: 87, A: 255}, // Sea Green
|
||||
},
|
||||
// Set 21
|
||||
{
|
||||
tracks: color.RGBA{R: 199, G: 21, B: 133, A: 255}, // Medium Violet Red
|
||||
body: color.RGBA{G: 255, B: 255, A: 255}, // Aqua
|
||||
cannon: color.RGBA{R: 255, G: 160, B: 122, A: 255}, // Light Salmon
|
||||
},
|
||||
// Set 22
|
||||
{
|
||||
tracks: color.RGBA{B: 139, A: 255}, // Dark Blue
|
||||
body: color.RGBA{R: 173, G: 255, B: 47, A: 255}, // Green Yellow
|
||||
cannon: color.RGBA{R: 255, G: 228, B: 181, A: 255},
|
||||
},
|
||||
// Set 23
|
||||
{
|
||||
tracks: color.RGBA{R: 205, G: 92, B: 92, A: 255}, // Indian Red
|
||||
body: color.RGBA{G: 191, B: 255, A: 255}, // Deep Sky Blue
|
||||
cannon: color.RGBA{R: 255, G: 255, B: 224, A: 255}, // Light Yellow
|
||||
},
|
||||
// Set 24
|
||||
{
|
||||
tracks: color.RGBA{R: 139, G: 69, B: 19, A: 255}, // Saddle Brown
|
||||
body: color.RGBA{R: 255, G: 99, B: 71, A: 255}, // Tomato
|
||||
cannon: color.RGBA{R: 70, G: 130, B: 180, A: 255}, // Steel Blue
|
||||
},
|
||||
// Set 25
|
||||
{
|
||||
tracks: color.RGBA{R: 135, G: 206, B: 250, A: 255}, // Light Sky Blue
|
||||
body: color.RGBA{R: 255, G: 105, B: 180, A: 255}, // Hot Pink
|
||||
cannon: color.RGBA{R: 184, G: 134, B: 11, A: 255}, // Dark Goldenrod
|
||||
},
|
||||
// Set 26
|
||||
{
|
||||
tracks: color.RGBA{G: 255, A: 255}, // Lime
|
||||
body: color.RGBA{R: 255, G: 228, B: 225, A: 255}, // Misty Rose
|
||||
cannon: color.RGBA{R: 128, A: 255}, // Maroon
|
||||
},
|
||||
// Set 27
|
||||
{
|
||||
tracks: color.RGBA{R: 255, B: 255, A: 255}, // Magenta
|
||||
body: color.RGBA{G: 100, A: 255}, // Dark Green
|
||||
cannon: color.RGBA{R: 255, G: 222, B: 173, A: 255}, // Navajo White
|
||||
},
|
||||
// Set 28
|
||||
{
|
||||
tracks: color.RGBA{R: 138, G: 43, B: 226, A: 255}, // Blue Violet
|
||||
body: color.RGBA{R: 255, G: 228, B: 181, A: 255}, // Moccasin
|
||||
cannon: color.RGBA{R: 47, G: 79, B: 79, A: 255}, // Dark Slate Gray
|
||||
},
|
||||
// Set 29
|
||||
{
|
||||
tracks: color.RGBA{R: 255, G: 182, B: 193, A: 255}, // Light Pink
|
||||
body: color.RGBA{G: 128, B: 128, A: 255}, // Teal
|
||||
cannon: color.RGBA{R: 255, G: 255, B: 240, A: 255}, // Ivory
|
||||
},
|
||||
// Set 30
|
||||
{
|
||||
tracks: color.RGBA{R: 255, G: 127, B: 80, A: 255}, // Coral
|
||||
body: color.RGBA{R: 25, G: 25, B: 112, A: 255}, // Midnight Blue
|
||||
cannon: color.RGBA{R: 173, G: 255, B: 47, A: 255}, // Green Yellow
|
||||
},
|
||||
// Set 31
|
||||
{
|
||||
tracks: color.RGBA{R: 218, G: 112, B: 214, A: 255}, // Orchid
|
||||
body: color.RGBA{R: 244, G: 164, B: 96, A: 255}, // Sandy Brown
|
||||
cannon: color.RGBA{R: 255, G: 239, B: 213, A: 255}, // Papaya Whip
|
||||
},
|
||||
// Set 32
|
||||
{
|
||||
tracks: color.RGBA{G: 250, B: 154, A: 255}, // Medium Spring Green
|
||||
body: color.RGBA{R: 138, G: 43, B: 226, A: 255}, // Blue Violet
|
||||
cannon: color.RGBA{R: 255, G: 69, A: 255}, // Orange Red
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func handleInput(keyboard []uint8, bullets *[]*Bullet, player *Player, gameMap *GameMap, format *sdl.PixelFormat, players *[]*Player) (bool, bool) {
|
||||
if !player.local || player.shields <= 0 || player.shields > MaxShields {
|
||||
return true, false
|
||||
}
|
||||
shoot := false
|
||||
super := false
|
||||
|
||||
// Flags to track movement in each direction
|
||||
moveUp := false
|
||||
moveDown := false
|
||||
moveLeft := false
|
||||
moveRight := false
|
||||
|
||||
if player.keyMap.exit != player.keyMap.shoot {
|
||||
// Process keyboard input
|
||||
for key, value := range keyboard {
|
||||
if value == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if key == player.keyMap.exit {
|
||||
return false, shoot
|
||||
} else if key == player.keyMap.shoot {
|
||||
shoot = true
|
||||
} else if key == player.keyMap.super {
|
||||
super = true
|
||||
} else if key == player.keyMap.up {
|
||||
moveUp = true
|
||||
} else if key == player.keyMap.down {
|
||||
moveDown = true
|
||||
} else if key == player.keyMap.left {
|
||||
moveLeft = true
|
||||
} else if key == player.keyMap.right {
|
||||
moveRight = true
|
||||
}
|
||||
}
|
||||
} else if player.joyStick != nil {
|
||||
if player.joyStick.NumAxes() > player.joyMap.xAxis+1 &&
|
||||
player.joyStick.NumAxes() > player.joyMap.yAxis+1 &&
|
||||
player.joyMap.exitButton != player.joyMap.shootButton {
|
||||
|
||||
xAxis := player.joyStick.Axis(player.joyMap.xAxis)
|
||||
yAxis := player.joyStick.Axis(player.joyMap.yAxis)
|
||||
|
||||
moveRight = xAxis > JoyStickDeadZone
|
||||
moveLeft = xAxis < -JoyStickDeadZone
|
||||
moveUp = yAxis > JoyStickDeadZone
|
||||
moveDown = yAxis < -JoyStickDeadZone
|
||||
|
||||
} else {
|
||||
moveUp = player.joyStick.Button(player.joyMap.upButton) == sdl.PRESSED
|
||||
moveDown = player.joyStick.Button(player.joyMap.downButton) == sdl.PRESSED
|
||||
moveLeft = player.joyStick.Button(player.joyMap.leftButton) == sdl.PRESSED
|
||||
moveRight = player.joyStick.Button(player.joyMap.rightButton) == sdl.PRESSED
|
||||
}
|
||||
if player.joyStick.Button(player.joyMap.exitButton) == sdl.PRESSED {
|
||||
return false, shoot
|
||||
}
|
||||
if player.joyStick.Button(player.joyMap.shootButton) == sdl.PRESSED {
|
||||
shoot = true
|
||||
}
|
||||
if player.joyStick.Button(player.joyMap.superButton) == sdl.PRESSED {
|
||||
super = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Handle shooting after the loop
|
||||
if shoot {
|
||||
player.shoot(super, bullets)
|
||||
}
|
||||
|
||||
// Determine player orientation for diagonal movement
|
||||
if moveUp && moveRight {
|
||||
player.gameObject.orientation = 4 // Up-Right
|
||||
} else if moveUp && moveLeft {
|
||||
player.gameObject.orientation = 5 // Up-Left
|
||||
} else if moveDown && moveRight {
|
||||
player.gameObject.orientation = 6 // Down-Right
|
||||
} else if moveDown && moveLeft {
|
||||
player.gameObject.orientation = 7 // Down-Left
|
||||
} else if moveUp {
|
||||
player.gameObject.orientation = 0 // Up
|
||||
} else if moveRight {
|
||||
player.gameObject.orientation = 1 // Right
|
||||
} else if moveDown {
|
||||
player.gameObject.orientation = 2 // Down
|
||||
} else if moveLeft {
|
||||
player.gameObject.orientation = 3 // Left
|
||||
}
|
||||
|
||||
// Handle movement after the loop
|
||||
if moveUp || moveDown || moveLeft || moveRight {
|
||||
if player.tryMove(gameMap, shoot, players) {
|
||||
player.energy -= MovementCost
|
||||
}
|
||||
}
|
||||
|
||||
return true, shoot
|
||||
}
|
38
profiler.go
Normal file
38
profiler.go
Normal file
@ -0,0 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
)
|
||||
|
||||
func profileSection(section func()) uint64 {
|
||||
start := sdl.GetTicks64()
|
||||
section()
|
||||
end := sdl.GetTicks64()
|
||||
return end - start
|
||||
}
|
||||
|
||||
func logProfilingInfo(handleEventsTime, renderTime, scaleTime, frameTime, frameCount uint64) {
|
||||
floatFrame := float64(frameCount)
|
||||
fmt.Printf("Average handleEvents time: %f ms\n", float64(handleEventsTime)/floatFrame)
|
||||
fmt.Printf("Average render time: %f ms\n", float64(renderTime)/floatFrame)
|
||||
fmt.Printf("Average scaling time: %f ms\n", float64(scaleTime)/floatFrame)
|
||||
fmt.Printf("Average frame time: %f ms\n", float64(frameTime)/floatFrame)
|
||||
fmt.Print("\n")
|
||||
}
|
||||
|
||||
func resetProfilingCounters(handleEventsTime, renderTime, scaleTime, frameTime *uint64, frameCount *uint64) {
|
||||
*handleEventsTime = 0
|
||||
*renderTime = 0
|
||||
*scaleTime = 0
|
||||
*frameTime = 0
|
||||
*frameCount = 0
|
||||
}
|
||||
|
||||
func enforceFrameRate(frameStart uint64, targetFPS int) {
|
||||
frameDuration := 1000 / targetFPS
|
||||
elapsed := sdl.GetTicks64() - frameStart
|
||||
if delay := frameDuration - int(elapsed); delay > 0 {
|
||||
sdl.Delay(uint32(delay))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user