particle system

This commit is contained in:
silva guimaraes 2023-09-16 00:22:29 -03:00
parent 6d25ee261b
commit 5f7c6f7b85

322
main.go
View file

@ -12,6 +12,7 @@ const (
HEIGHT = 700 HEIGHT = 700
buildingSpacing = 2.5 buildingSpacing = 2.5
buildingSize = 1.2 buildingSize = 1.2
maxBuildingHeight = 10
maxColumns = 5 maxColumns = 5
enemyAcc = 0.01 enemyAcc = 0.01
maxSpeed = 0.1 maxSpeed = 0.1
@ -41,6 +42,172 @@ type healthBar struct {
lastUpdate float64 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() { func draw_plane() {
rl.DrawPlane( rl.DrawPlane(
rl.NewVector3(16, 0.0, 16), rl.NewVector3(16, 0.0, 16),
@ -53,13 +220,13 @@ func randomShake(amount float32) float32 {
return rand.Float32() * amount - amount/2 return rand.Float32() * amount - amount/2
} }
func (hb *healthBar) update(buildings []*building) { func (hb *healthBar) update() {
const MARGIN = 20 const MARGIN = 20
const BARWIDTH = (WIDTH - MARGIN*2) const BARWIDTH = (WIDTH - MARGIN*2)
currentLife := 0 currentLife := 0
maxLife := buildingsHealth * len(buildings) maxLife := buildingsHealth * len(city.buildings)
for _, b := range buildings { for _, b := range city.buildings {
currentLife += b.life currentLife += b.life
} }
position := rl.NewVector2(MARGIN, 10) position := rl.NewVector2(MARGIN, 10)
@ -85,7 +252,6 @@ func (hb *healthBar) update(buildings []*building) {
hb.lastUpdate = rl.GetTime() hb.lastUpdate = rl.GetTime()
hb.life = currentLife hb.life = currentLife
hb.damageTaken *= 0.95 hb.damageTaken *= 0.95
} }
func newHealthBar(buildings []*building) *healthBar { func newHealthBar(buildings []*building) *healthBar {
@ -95,12 +261,12 @@ func newHealthBar(buildings []*building) *healthBar {
} }
func (b *building) causeDamage(damage int) { func (b *building) causeDamage(damage int) {
if b.animate != nil { if b.animate != nil || b.life <= 0 {
return return
} }
b.animate = shakeBuilding(*b) b.animate = shakeBuilding(b)
b.life -= damage b.life -= damage
fmt.Println("damage:", b.life) fmt.Println("damage:", damage, "life:", b.life)
} }
func newBuilding(x, z float32) *building { func newBuilding(x, z float32) *building {
@ -114,7 +280,7 @@ func newBuilding(x, z float32) *building {
pos := rl.NewVector3(x * buildingSpacing, 0, z * buildingSpacing) pos := rl.NewVector3(x * buildingSpacing, 0, z * buildingSpacing)
size := rl.NewVector3( size := rl.NewVector3(
buildingSize, buildingSize,
float32(rl.GetRandomValue(1, 7)), float32(rl.GetRandomValue(1, maxBuildingHeight)),
buildingSize, buildingSize,
) )
min := rl.NewVector3( 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 var frame remainingFrames = 60 * 0.7
return func() remainingFrames { return func() remainingFrames {
building := b building := *b
if frame % 4 == 0 { if frame % 4 == 0 {
if b.life == 0 {
building.color = rl.NewColor(255, 0, 0, 255)
} else {
building.color = rl.RayWhite building.color = rl.RayWhite
} }
}
drawWireframe(b) drawWireframe(building)
shake := rl.NewVector3( shake := rl.NewVector3(
rand.Float32() * .2 - .1, rand.Float32() * .2 - .1,
@ -183,11 +353,15 @@ func shakeBuilding(b building) animationFunc {
} }
func draw_buildings(buildings []*building) { func draw_buildings() {
for _, building := range buildings { for _, building := range city.buildings {
hasAnimation := building.animate != nil hasAnimation := building.animate != nil
if building.life <= 0 && !hasAnimation {
continue
}
if hasAnimation { if hasAnimation {
remainingFrames := building.animate() remainingFrames := building.animate()
@ -199,34 +373,30 @@ func draw_buildings(buildings []*building) {
continue continue
} }
if building.life == 0 {
continue
}
drawWireframe(*building) drawWireframe(*building)
rl.DrawCubeV(building.pos, building.size, building.color) 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) { if !rl.IsMouseButtonDown(rl.MouseLeftButton) {
return return
} }
ray := rl.Ray{ ray := rl.Ray{
Position: camera.Position, Position: c.camera.Position,
Direction: rl.Vector3Subtract(camera.Target, camera.Position), Direction: rl.Vector3Subtract(c.camera.Target, c.camera.Position),
} }
closestDistance := math.Inf(1) closestDistance := math.Inf(1)
var closest *building var closest *building
for _, building := range buildings { for _, building := range city.buildings {
if building.life == 0 { if building.life == 0 {
continue continue
} }
playerDistance := rl.Vector3Distance(camera.Position, building.pos) playerDistance := rl.Vector3Distance(c.camera.Position, building.pos)
if playerDistance < float32(closestDistance) { if playerDistance < float32(closestDistance) {
@ -241,10 +411,22 @@ func damage_building(camera rl.Camera, buildings []*building) {
} }
if closest != nil { 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() { func main() {
fmt.Println("hello world") fmt.Println("hello world")
rl.SetConfigFlags(rl.FlagMsaa4xHint) rl.SetConfigFlags(rl.FlagMsaa4xHint)
@ -254,58 +436,44 @@ func main() {
rl.DisableCursor() rl.DisableCursor()
rl.SetMousePosition(WIDTH/2, HEIGHT/2) rl.SetMousePosition(WIDTH/2, HEIGHT/2)
var enemies []*enemy character := newCharacter()
buildings := newBuildings()
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)))
}
}
healthBar := newHealthBar(buildings) 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() { 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.BeginDrawing()
rl.ClearBackground(rl.LightGray) rl.ClearBackground(rl.LightGray)
rl.BeginMode3D(camera) rl.BeginMode3D(character.camera)
{ {
character.update()
damage_building(camera, buildings)
draw_plane() 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() rl.EndMode3D()
@ -322,40 +490,10 @@ func main() {
rl.DrawFPS(0, HEIGHT-30) rl.DrawFPS(0, HEIGHT-30)
healthBar.update(buildings) healthBar.update()
rl.EndDrawing() rl.EndDrawing()
} }
rl.CloseWindow() 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
// )