From 5f7c6f7b8537756422a264e64205d7d0e458e730 Mon Sep 17 00:00:00 2001 From: silva guimaraes Date: Sat, 16 Sep 2023 00:22:29 -0300 Subject: [PATCH] particle system --- main.go | 324 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 231 insertions(+), 93 deletions(-) diff --git a/main.go b/main.go index af5c391..79d7796 100644 --- a/main.go +++ b/main.go @@ -12,6 +12,7 @@ const ( HEIGHT = 700 buildingSpacing = 2.5 buildingSize = 1.2 + maxBuildingHeight = 10 maxColumns = 5 enemyAcc = 0.01 maxSpeed = 0.1 @@ -41,6 +42,172 @@ type healthBar struct { lastUpdate float64 } +type character struct { + camera rl.Camera + damage int +} + +type projectile struct { + pos rl.Vector3 + speed rl.Vector3 +} + +type scene struct { + buildings []*building + healthBar *healthBar + projectiles []*projectile + character *character + emitters []*emitter +} + +type particle struct { + // birth float32 + lifetime float64 + pos rl.Vector3 + speed rl.Vector3 +} + +type emitter struct { + particles []*particle + pos rl.Vector3 + particleAmount int +} + + +var city *scene + +func update_emitters() { + for _, e := range city.emitters { + e.update() + } +} + +func newEmitter(pos rl.Vector3, particleAmount int) *emitter { + emitter := emitter{ + pos: pos, + particleAmount: particleAmount, + } + + for i := 0; i < particleAmount; i++ { + direction := rl.NewVector3( + rand.Float32()*2 - 1, + 1, + rand.Float32()*2 - 1, + ) + direction = rl.Vector3Normalize(direction) + direction = rl.Vector3Scale(direction, 0.3 + rand.Float32()/3) + particle := particle{ + lifetime: rl.GetTime() + 1, + speed: direction, + pos: pos, + } + emitter.particles = append(emitter.particles, &particle) + } + + return &emitter +} + +func (e *emitter) update() { + gravity := rl.NewVector3(0, -0.02, 0) + for _, particle := range e.particles { + if rl.GetTime() > particle.lifetime { + continue + } + particle.pos = rl.Vector3Add(particle.pos, particle.speed) + particle.speed = rl.Vector3Add(particle.speed, gravity) + rl.BeginBlendMode(rl.BlendAdditive) + { + rl.DrawSphere(particle.pos, 0.2, rl.Red) + } + rl.EndBlendMode() + } +} + +// retona true caso projétil precise ser destruido +func (p *projectile) isHit() bool { + gravity := rl.NewVector3(0, -0.02, 0) + p.speed = rl.Vector3Add(p.speed, gravity) + p.pos = rl.Vector3Add(p.pos, p.speed) + + if p.pos.Y < 0 { + city.emitters = append(city.emitters, newEmitter(p.pos, 100)) + for _, building := range city.buildings { + if dist := rl.Vector3Distance(p.pos, building.pos); dist < 10 { + building.causeDamage(3) + } + + } + return true + } + + rl.DrawSphere(p.pos, 0.5, rl.Gray) + return false +} + +func update_projectiles() { + for i, p := range city.projectiles { + if hit := p.isHit(); hit { + city.projectiles[i] = city.projectiles[len(city.projectiles)-1] + city.projectiles = city.projectiles[:len(city.projectiles)-1] + } + } +} + + +func (c *character) kill_aurea() { + const min = 10 + for _, b := range city.buildings { + if distance := rl.Vector3Distance(c.camera.Position, b.pos); distance < min { + b.causeDamage(c.damage) + } + } +} + +func (c *character) throw_bomb(){ + if !rl.IsMouseButtonPressed(rl.MouseRightButton) { + return + } + + direction := rl.Vector3Subtract(c.camera.Target, c.camera.Position) + + projectile := projectile{ + pos: c.camera.Position, + speed: rl.Vector3Scale(direction, 0.15), + } + + city.projectiles = append(city.projectiles, &projectile) +} + +func (c *character) update() { + shake := rl.NewVector3( + randomShake(0.003) * city.healthBar.damageTaken, + randomShake(0.003) * city.healthBar.damageTaken, + randomShake(0.003) * city.healthBar.damageTaken, + ) + c.camera.Target = rl.Vector3Add(c.camera.Target, shake) + + c.laser_beam() + + // c.kill_aurea() + + c.throw_bomb() +} + +func newCharacter() *character { + + camera := rl.Camera3D{ + Position: rl.NewVector3(4.0, 2.0, 4.0), + Target: rl.NewVector3(0.0, 1.8, 0.0), + Up: rl.NewVector3(0.0, 1.0, 0.0), + Fovy: 80.0, + Projection: rl.CameraPerspective, + } + return &character{ + camera: camera, + damage: 1, + } +} + func draw_plane() { rl.DrawPlane( rl.NewVector3(16, 0.0, 16), @@ -53,13 +220,13 @@ func randomShake(amount float32) float32 { return rand.Float32() * amount - amount/2 } -func (hb *healthBar) update(buildings []*building) { +func (hb *healthBar) update() { const MARGIN = 20 const BARWIDTH = (WIDTH - MARGIN*2) currentLife := 0 - maxLife := buildingsHealth * len(buildings) - for _, b := range buildings { + maxLife := buildingsHealth * len(city.buildings) + for _, b := range city.buildings { currentLife += b.life } position := rl.NewVector2(MARGIN, 10) @@ -85,7 +252,6 @@ func (hb *healthBar) update(buildings []*building) { hb.lastUpdate = rl.GetTime() hb.life = currentLife hb.damageTaken *= 0.95 - } func newHealthBar(buildings []*building) *healthBar { @@ -95,12 +261,12 @@ func newHealthBar(buildings []*building) *healthBar { } func (b *building) causeDamage(damage int) { - if b.animate != nil { + if b.animate != nil || b.life <= 0 { return } - b.animate = shakeBuilding(*b) + b.animate = shakeBuilding(b) b.life -= damage - fmt.Println("damage:", b.life) + fmt.Println("damage:", damage, "life:", b.life) } func newBuilding(x, z float32) *building { @@ -114,7 +280,7 @@ func newBuilding(x, z float32) *building { pos := rl.NewVector3(x * buildingSpacing, 0, z * buildingSpacing) size := rl.NewVector3( buildingSize, - float32(rl.GetRandomValue(1, 7)), + float32(rl.GetRandomValue(1, maxBuildingHeight)), buildingSize, ) min := rl.NewVector3( @@ -153,17 +319,21 @@ func drawWireframe(building building) { ) } -func shakeBuilding(b building) animationFunc { +func shakeBuilding(b *building) animationFunc { var frame remainingFrames = 60 * 0.7 return func() remainingFrames { - building := b + building := *b if frame % 4 == 0 { - building.color = rl.RayWhite + if b.life == 0 { + building.color = rl.NewColor(255, 0, 0, 255) + } else { + building.color = rl.RayWhite + } } - drawWireframe(b) + drawWireframe(building) shake := rl.NewVector3( rand.Float32() * .2 - .1, @@ -183,11 +353,15 @@ func shakeBuilding(b building) animationFunc { } -func draw_buildings(buildings []*building) { - for _, building := range buildings { +func draw_buildings() { + for _, building := range city.buildings { hasAnimation := building.animate != nil + if building.life <= 0 && !hasAnimation { + continue + } + if hasAnimation { remainingFrames := building.animate() @@ -199,34 +373,30 @@ func draw_buildings(buildings []*building) { continue } - if building.life == 0 { - continue - } - drawWireframe(*building) rl.DrawCubeV(building.pos, building.size, building.color) } } -func damage_building(camera rl.Camera, buildings []*building) { +func (c *character) laser_beam() { if !rl.IsMouseButtonDown(rl.MouseLeftButton) { return } ray := rl.Ray{ - Position: camera.Position, - Direction: rl.Vector3Subtract(camera.Target, camera.Position), + Position: c.camera.Position, + Direction: rl.Vector3Subtract(c.camera.Target, c.camera.Position), } closestDistance := math.Inf(1) var closest *building - for _, building := range buildings { + for _, building := range city.buildings { if building.life == 0 { continue } - playerDistance := rl.Vector3Distance(camera.Position, building.pos) + playerDistance := rl.Vector3Distance(c.camera.Position, building.pos) if playerDistance < float32(closestDistance) { @@ -241,10 +411,22 @@ func damage_building(camera rl.Camera, buildings []*building) { } if closest != nil { - closest.causeDamage(3) + closest.causeDamage(c.damage) } } +func newBuildings() []*building { + var buildings []*building + + for i := 0; i < 32; i++ { + for j := 0; j < 32; j++ { + buildings = append(buildings, newBuilding(float32(i), float32(j))) + } + } + + return buildings +} + func main() { fmt.Println("hello world") rl.SetConfigFlags(rl.FlagMsaa4xHint) @@ -254,58 +436,44 @@ func main() { rl.DisableCursor() rl.SetMousePosition(WIDTH/2, HEIGHT/2) - var enemies []*enemy - - for i := 0; i < 10; i++ { - pos := rl.NewVector3( - float32(rl.GetRandomValue(-10, 10)), - 2, - float32(rl.GetRandomValue(-10, 10)), - ) - enemies = append(enemies, &enemy{ pos: pos }) - } - - camera := rl.Camera3D{} - camera.Position = rl.NewVector3(4.0, 2.0, 4.0) - camera.Target = rl.NewVector3(0.0, 1.8, 0.0) - camera.Up = rl.NewVector3(0.0, 1.0, 0.0) - camera.Fovy = 80.0 - camera.Projection = rl.CameraPerspective - - var buildings []*building - - for i := 0; i < 32; i++ { - for j := 0; j < 32; j++ { - buildings = append(buildings, newBuilding(float32(i), float32(j))) - } - } - + character := newCharacter() + buildings := newBuildings() healthBar := newHealthBar(buildings) + city = &scene{ + buildings: buildings, + healthBar: healthBar, + character: character, + } + + // direction := rl.Vector3Subtract(character.camera.Target, character.camera.Position) + // aim := direction + for !rl.WindowShouldClose() { - // shake := rl.NewVector3( - // rand.Float32() * .4 - .2, - // rand.Float32() * .4 - .2, - // rand.Float32() * .4 - .2, - // ) - // shake = rl.Vector3Scale(shake, float32(math.Sin(rl.GetTime()) + 1)/3) - // camera.Target = rl.Vector3Add(camera.Target, shake) - rl.UpdateCamera(&camera, rl.CameraFirstPerson) + rl.UpdateCamera(&character.camera, rl.CameraFirstPerson) rl.BeginDrawing() rl.ClearBackground(rl.LightGray) - rl.BeginMode3D(camera) + rl.BeginMode3D(character.camera) { - - damage_building(camera, buildings) + character.update() draw_plane() - draw_buildings(buildings) + update_projectiles() + draw_buildings() + update_emitters() + + + + // direction = rl.Vector3Subtract( + // character.camera.Target, character.camera.Position) + // aim = rl.Vector3Lerp(direction, aim, 0.95) + // rl.DrawSphere(rl.Vector3Add(character.camera.Position, aim), 0.1, rl.Red) } rl.EndMode3D() @@ -322,40 +490,10 @@ func main() { rl.DrawFPS(0, HEIGHT-30) - healthBar.update(buildings) + healthBar.update() rl.EndDrawing() } rl.CloseWindow() } - - - - // for _, e := range enemies { - // - // if dist := rl.Vector3Distance(camera.Position, e.pos); dist > 8 { - // rl.DrawSphere(e.pos, 1, rl.Blue) - // e.speed = 0 - // continue - // } - // rl.DrawSphere(e.pos, 1, rl.Red) - // - // direction := rl.Vector3Normalize(rl.Vector3Subtract(camera.Position, e.pos)) - // e.speed += enemyAcc - // e.speed = float32(math.Mod(float64(e.speed), maxSpeed)) - // direction.Y = 0 - // direction = rl.Vector3Scale(direction, e.speed) - // e.pos = rl.Vector3Add(e.pos, direction) - // } - // fmt.Println( - // rl.Vector3Subtract(camera.Target, camera.Position), - // ) - - // ray = rl.GetMouseRay(rl.GetMousePosition(), camera) - - // rl.GetRayCollisionBox(ray - // ) - - -