GOingTunneling/bullet.go

175 lines
4.6 KiB
Go

package main
import (
"github.com/veandco/go-sdl2/sdl"
"image/color"
"math/rand"
)
type Bullet struct {
posX, posY int32
direction uint8
color color.Color
super bool
}
type BulletParticle struct {
posX, posY int32
expirationTimer uint8
color color.Color
}
func (bulletParticle *BulletParticle) render(camera *sdl.Rect, surface *sdl.Surface) {
if camera.IntersectLine(&bulletParticle.posX, &bulletParticle.posY, &bulletParticle.posX, &bulletParticle.posY) {
relativeBulletX := bulletParticle.posX - camera.X
relativeBulletY := bulletParticle.posY - camera.Y
surface.Set(int(relativeBulletX), int(relativeBulletY), bulletParticle.color)
}
}
func (bulletParticle *BulletParticle) tick(particles *[]*BulletParticle) {
if bulletParticle.expirationTimer <= 0 {
for i, particle := range *particles {
if particle == bulletParticle {
*particles = append((*particles)[:i], (*particles)[i+1:]...)
}
}
}
bulletParticle.expirationTimer--
}
func (bullet *Bullet) render(camera *sdl.Rect, surface *sdl.Surface) {
if camera.IntersectLine(&bullet.posX, &bullet.posY, &bullet.posX, &bullet.posY) {
relativeBulletX := bullet.posX - camera.X
relativeBulletY := bullet.posY - camera.Y
surface.Set(int(relativeBulletX), int(relativeBulletY), bullet.color)
}
}
func (bullet *Bullet) explode(gameMap *GameMap, bulletParticleMap *[]*BulletParticle) {
// Define the possible directions with their x and y velocity components.
directions := [][2]int{
{0, -1}, // Up
{0, 1}, // Down
{-1, 0}, // Left
{1, 0}, // Right
{-1, -1}, // Up-Left Diagonal
{1, -1}, // Up-Right Diagonal
{-1, 1}, // Down-Left Diagonal
{1, 1}, // Down-Right Diagonal
}
if !bullet.super {
// Loop through each direction to generate particle streams.
for _, dir := range directions {
// Randomize the number of particles in each stream.
particlesInStream := rand.Intn(5)
for i := 0; i < particlesInStream; i++ {
// Determine particle's position based on its direction and step count.
step := rand.Intn(3) + 1 // Step can be 1, 2, or 3 units.
xOffset := dir[0] * step
yOffset := dir[1] * step
xPos, yPos := bullet.posX+int32(xOffset), bullet.posY+int32(yOffset)
collision := gameMap.checkCollision(xPos, yPos)
// Check for collision and bullet behavior (normal or super).
if collision == 1 || collision == 0 || (bullet.super && collision == 2) {
*bulletParticleMap = append(*bulletParticleMap, &BulletParticle{
posX: xPos,
posY: yPos,
expirationTimer: uint8(5 + rand.Intn(10)), // Randomize expiration time between 15 and 25.
color: bullet.color,
})
if xPos > 0 && yPos > 0 && xPos < MapWidth && yPos < MapHeight {
gameMap.tiles[xPos][yPos] = 0
}
}
}
}
} else {
for xOffset := -3; xOffset <= 3; xOffset++ {
for yOffset := -3; yOffset <= 3; yOffset++ {
xPos, yPos := bullet.posX+int32(xOffset), bullet.posY+int32(yOffset)
collision := gameMap.checkCollision(xPos, yPos)
if collision == 1 || collision == 0 || (bullet.super && collision == 2) {
*bulletParticleMap = append(*bulletParticleMap, &BulletParticle{
posX: xPos,
posY: yPos,
expirationTimer: uint8(15 + rand.Intn(15)),
color: bullet.color,
})
gameMap.tiles[xPos][yPos] = 0
}
}
}
}
}
func (bullet *Bullet) tick(gameMap *GameMap,
bulletParticleMap *[]*BulletParticle, bulletMap *[]*Bullet, players *[]*Player) {
var nextX, nextY int32
nextX, nextY = bullet.posX, bullet.posY
switch bullet.direction {
case 0: //up
nextY -= 1
break
case 1: //right
nextX += 1
break
case 2: //down
nextY += 1
break
case 3: //left
nextX -= 1
break
case 4: //up right
nextY -= 1
nextX += 1
break
case 5: //up left
nextY -= 1
nextX -= 1
break
case 6: //down right
nextY += 1
nextX += 1
break
case 7: //down left
nextY += 1
nextX -= 1
break
}
collisionResult := gameMap.checkCollision(nextX, nextY)
bulletRect := sdl.Rect{
X: bullet.posX,
Y: bullet.posY,
W: 1,
H: 1,
}
hitPlayer := false
for _, player := range *players {
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)
for i, bulletInMap := range *bulletMap {
if bulletInMap == bullet {
*bulletMap = append((*bulletMap)[:i], (*bulletMap)[i+1:]...)
}
}
} else {
bullet.posX = nextX
bullet.posY = nextY
}
}