package main import rl "vendor:raylib" import "core:fmt" import "core:math/rand" import "core:slice" import "core:math" bullets : [dynamic]Bullet Bullet :: struct{ pos: vec3, vel: vec3, radius: f32, alive: bool, } bullet_spawn :: proc(pos: vec3, dir: f32) -> Bullet { return Bullet { pos = pos, vel = get_vec_from_angle(dir) * 70, alive = true, radius = 0.7 } } bullet_process :: proc(bullet: ^Bullet, game: ^Game, delta: f32) { bullet.vel = rl.Vector3MoveTowards(bullet.vel, {}, 60 * delta) bullet.pos += bullet.vel * delta if rl.Vector3LengthSqr(bullet.vel) < 0.2 { bullet.alive = false } if rl.CheckCollisionCircles(bullet.pos.xy, bullet.radius, Head.pos.xy, Head.radius) { bullet.alive = false if game.snake_health == 0 { diff := bullet.pos - Head.pos diff_ang := math.atan2(-diff.y, diff.x) angle := angle_cycle(Head.dir - diff_ang, -math.PI, math.PI) if abs(angle) > math.PI / 3 { rl.PlaySound(Res.Sfx.LightningHit) explode(bullet.pos, 1, 0.6, rl.YELLOW) Head.health -= 1 } } return } for &segment in Segments { if rl.CheckCollisionCircles(bullet.pos.xy, bullet.radius, segment.pos.xy, segment.collider_radius) { bullet.alive = false rl.PlaySound(Res.Sfx.LightningHit) if segment.health > 0 { segment.health -= 1 explode(bullet.pos, 1, 0.6, rl.YELLOW) if segment.health == 0 { segment.collider_radius = 1.5 explode(segment.pos, 3, 0.7, rl.RED) rl.PlaySound(Res.Sfx.SnakeSegmentExplode) } } } } } bullet_draw :: proc(bullet: ^Bullet, game: ^Game) { rl.DrawSphere(bullet.pos, 0.5, rl.YELLOW) line_count := 0 bdraw := slice.clone_to_dynamic(game.bullets[:]) rand.shuffle(bdraw[:]) for &bul in bdraw { if &bul == bullet { continue } if line_count > 0 { break } if rl.Vector3LengthSqr(bul.pos - bullet.pos) > 70 { continue } line_count += 1 rl.DrawLine3D(bullet.pos, bul.pos, rl.YELLOW) } }