This commit is contained in:
silva guimaraes 2025-01-25 23:28:00 -03:00
parent df56b0237e
commit 9a0383488d

247
main.go
View file

@ -3,7 +3,6 @@ package main
import ( import (
"fmt" "fmt"
"math" "math"
// "path"
"strconv" "strconv"
rl "github.com/gen2brain/raylib-go/raylib" rl "github.com/gen2brain/raylib-go/raylib"
@ -11,8 +10,10 @@ import (
// diz para um inimigo como ele deve se mover // diz para um inimigo como ele deve se mover
type movementPattern func(*enemy) rl.Vector2 type movementPattern func(*enemy) rl.Vector2
// diz para um inimigo em que condições atirar. acionado pelo movementPattern // diz para um inimigo em que condições atirar. acionado pelo movementPattern
type shootingPattern func(*enemy) type shootingPattern func(*enemy)
// diz para uma bala como ela deve se mover. // diz para uma bala como ela deve se mover.
type bulletMovementPattern func(*bullet) rl.Vector2 type bulletMovementPattern func(*bullet) rl.Vector2
@ -26,6 +27,8 @@ type game struct {
interfaceWidth int32 interfaceWidth int32
frame float32 frame float32
enemies []*enemy enemies []*enemy
waves []*wave
currentWave int
bullets []*bullet bullets []*bullet
score int score int
gameSpeed float32 // 1 = velocidade normal gameSpeed float32 // 1 = velocidade normal
@ -59,6 +62,11 @@ type enemy struct {
hitBoxRadius float32 hitBoxRadius float32
} }
type wave struct {
enemies []*enemy
entrance movementPattern
}
func (g game) insideArena(v rl.Vector2) bool { func (g game) insideArena(v rl.Vector2) bool {
return v.X >= 0 && v.Y >= 0 && return v.X >= 0 && v.Y >= 0 &&
v.Y <= float32(g.arenaHeight) && v.X <= float32(g.arenaWidth) v.Y <= float32(g.arenaHeight) && v.X <= float32(g.arenaWidth)
@ -81,12 +89,14 @@ func (b *bullet) update(g *game, index int) {
} }
func bulletExplosion(g *game, rate, amount int, bulletSpeed, size float32) shootingPattern { func bulletExplosion(g *game, rate, amount int, bulletSpeed, size float32) shootingPattern {
t := newTimer(second)
return func(e *enemy) { return func(e *enemy) {
if int(g.frame) % rate != 0 {
t.tick(g)
if !t.isTimeout() {
return return
} }
t.reset()
// radius := e.hitBoxRadius
var bullets []*bullet var bullets []*bullet
@ -130,21 +140,62 @@ bulletMoveSpeed float32) shootingPattern {
} }
} }
func burstShootAtPlayer(g *game, p *player, type timer struct {
rate int, bulletMoveSpeed float32) shootingPattern { time, ttl float32
start float64
}
func (t *timer) tick(g *game) {
t.time += rl.GetFrameTime() * g.gameSpeed
}
func (t *timer) isTimeout() bool {
return t.time >= t.ttl
}
func (t *timer) reset() {
t.start = float64(t.time)
t.time = 0
}
func newTimer(duration float32) *timer {
return &timer {
time: 0,
ttl: duration,
start: rl.GetTime(),
}
}
var second float32 = 1
func burstShootAtPlayer(g *game, p *player, rate float32, bulletMoveSpeed float32) shootingPattern {
flag := true flag := true
off := newTimer(second)
on := newTimer(second*rate)
return func(e *enemy) { return func(e *enemy) {
if int(g.frame) % 100 == 0 {
fmt.Printf("\r %f %f", rl.GetTime(), rl.GetFrameTime())
off.tick(g)
if off.isTimeout() {
flag = !flag flag = !flag
fmt.Println()
fmt.Println(off)
off.reset()
fmt.Println(off)
fmt.Println()
} }
if !flag { if !flag {
return return
} }
if int(g.frame) % rate != 0 { on.tick(g)
if !on.isTimeout() {
return return
} }
on.reset()
direction := rl.Vector2Subtract(p.pos, e.pos) direction := rl.Vector2Subtract(p.pos, e.pos)
direction = rl.Vector2Normalize(direction) direction = rl.Vector2Normalize(direction)
@ -196,42 +247,65 @@ func horizonalPattern(g *game) movementPattern {
} }
} }
// func foobarPattern(g *game) movementPattern { func sineHorizonalPattern(g *game) movementPattern {
// direction := rl.Vector2{X: 4, Y: 0}
// pos := rl.Vector2{}
// state := 0 return func(e *enemy) rl.Vector2 {
// wait := 0 if e.shoot != nil {
// e.shoot(e)
// return func(e *enemy) rl.Vector2 { }
//
// switch state {
// case 0: // init result := rl.Vector2Add(direction, e.pos)
// pos.X = e.pos.X if !g.insideArena(result) {
// state = 1 direction = rl.Vector2Negate(direction)
// return pos }
// case 1: // descer
// pos.Y += 1 sine := rl.Vector2{
// if pos.Y >= 100 { state = 2; wait = 50 } X: 0,
// return pos Y: float32(math.Sin(float64(g.frame*0.04))*2),
// case 2: // atirar por um tempo }
// e.shoot(e)
// wait -= 1 return rl.Vector2Add(sine, direction)
// if wait <= 0 { state = 3; wait = 60 } }
// return pos }
// case 3: // wait
// wait -= 1 func foobarPattern(g *game) movementPattern {
// if wait <= 0 { state = 4 }
// return pos pos := rl.Vector2{}
// case 4: // retornar state := 0
// pos.Y -= 3 wait := 0
// if pos.Y - e.hitBoxRadius < 0 {
// e.health = 0 return func(e *enemy) rl.Vector2 {
// }
// return pos switch state {
// } case 0: // init
// panic(state) pos.X = e.pos.X
// } state = 1
// } return pos
case 1: // descer
pos.Y += 1
if pos.Y >= 100 { state = 2; wait = 50 }
return pos
case 2: // atirar por um tempo
e.shoot(e)
wait -= 1
if wait <= 0 { state = 3; wait = 60 }
return pos
case 3: // wait
wait -= 1
if wait <= 0 { state = 4 }
return pos
case 4: // retornar
pos.Y -= 3
if pos.Y - e.hitBoxRadius < 0 {
e.health = 0
}
return pos
}
panic(state)
}
}
func (e *enemy) checkHit(g *game) (bool, *bullet, int) { func (e *enemy) checkHit(g *game) (bool, *bullet, int) {
for index, bullet := range g.bullets { for index, bullet := range g.bullets {
@ -254,8 +328,11 @@ func (g *game) killEnemy(index int) {
g.enemies = g.enemies[:len(g.enemies)-1] g.enemies = g.enemies[:len(g.enemies)-1]
} }
func (e *enemy) update(g *game) {
func (e *enemy) update(g *game, index int) { if e.health <= 0 {
return
}
enemyColor := rl.Blue enemyColor := rl.Blue
@ -272,10 +349,6 @@ func (e *enemy) update(g *game, index int) {
g.backgroundColor = rl.NewColor(20, 20, 20, 255) g.backgroundColor = rl.NewColor(20, 20, 20, 255)
} }
if e.health <= 0 {
g.killEnemy(index)
return
}
rl.DrawCircleV(e.pos, e.hitBoxRadius, enemyColor) rl.DrawCircleV(e.pos, e.hitBoxRadius, enemyColor)
} }
@ -291,10 +364,18 @@ func (p *player) move(g *game) {
p.speed = rl.Vector2{X: 0, Y: 0} p.speed = rl.Vector2{X: 0, Y: 0}
if rl.IsKeyDown(rl.KeyW) { p.speed.Y -= 1 } if rl.IsKeyDown(rl.KeyW) {
if rl.IsKeyDown(rl.KeyS) { p.speed.Y += 1 } p.speed.Y -= 1
if rl.IsKeyDown(rl.KeyA) { p.speed.X -= 1 } }
if rl.IsKeyDown(rl.KeyD) { p.speed.X += 1 } if rl.IsKeyDown(rl.KeyS) {
p.speed.Y += 1
}
if rl.IsKeyDown(rl.KeyA) {
p.speed.X -= 1
}
if rl.IsKeyDown(rl.KeyD) {
p.speed.X += 1
}
if !(p.speed.X == 0 && p.speed.Y == 0) { if !(p.speed.X == 0 && p.speed.Y == 0) {
// jogador se move mais rapido na diagonal caso o contrario // jogador se move mais rapido na diagonal caso o contrario
@ -391,6 +472,15 @@ func (p *player) update(g *game) {
} }
func (g *game) fullClear() bool {
for _, e := range g.waves[g.currentWave].enemies {
if e.health != 0 {
return false
}
}
return true
}
func main() { func main() {
state := &game{ state := &game{
@ -416,8 +506,8 @@ func main() {
rl.SetConfigFlags(rl.FlagMsaa4xHint) rl.SetConfigFlags(rl.FlagMsaa4xHint)
rl.InitWindow(state.arenaWidth+state.interfaceWidth, state.arenaHeight, "danmaku") rl.InitWindow(state.arenaWidth+state.interfaceWidth, state.arenaHeight, "danmaku")
rl.SetTargetFPS(60) targetFPS := 120
rl.SetTargetFPS(int32(targetFPS))
// shader_path := path.Join("shaders", "trails.glsl") // shader_path := path.Join("shaders", "trails.glsl")
// shader := rl.LoadShader("", shader_path) // shader := rl.LoadShader("", shader_path)
@ -427,27 +517,54 @@ func main() {
// state.arenaHeight, // state.arenaHeight,
// ) // )
state.enemies = []*enemy{ state.waves = []*wave{
{
enemies: []*enemy{
{
pos: rl.Vector2{X: 100, Y: 100},
health: 100,
hitBoxRadius: 20,
move: sineHorizonalPattern(state),
shoot: burstShootAtPlayer(state, &player, 0.1, 4),
},
},
},
{
enemies: []*enemy{
{
pos: rl.Vector2{X: 100, Y: 100},
health: 100,
hitBoxRadius: 20,
move: horizonalPattern(state),
shoot: bulletExplosion(state, targetFPS, 20, 2, 11),
},
},
},
{
enemies: []*enemy{
{ {
pos: rl.Vector2{X: 200, Y: 200}, pos: rl.Vector2{X: 200, Y: 200},
health: 100, health: 100,
hitBoxRadius: 20, hitBoxRadius: 20,
move: horizonalPattern(state), move: horizonalPattern(state),
shoot: bulletExplosion(state, 60, 20, 2, 11), shoot: bulletExplosion(state, targetFPS, 20, 2, 11),
}, },
{ {
pos: rl.Vector2{X: 100, Y: 100}, pos: rl.Vector2{X: 100, Y: 100},
health: 100, health: 100,
hitBoxRadius: 20, hitBoxRadius: 20,
move: horizonalPattern(state), move: horizonalPattern(state),
shoot: burstShootAtPlayer(state, &player, 20, 4), shoot: burstShootAtPlayer(state, &player, 0.2, 4),
}, },
{ {
pos: rl.Vector2{X: 50, Y: 250}, pos: rl.Vector2{X: 50, Y: 250},
health: 100, health: 100,
hitBoxRadius: 20, hitBoxRadius: 20,
move: horizonalPattern(state), move: horizonalPattern(state),
shoot: bulletExplosion(state, 60, 20, 2, 11), shoot: bulletExplosion(state, targetFPS, 20, 2, 11),
// shoot: shootStraightDown(state),
},
},
}, },
} }
@ -462,8 +579,16 @@ func main() {
player.update(state) player.update(state)
if state.fullClear() {
state.currentWave++
}
if state.currentWave >= len(state.waves) {
break
}
state.enemies = state.waves[state.currentWave].enemies
for i := 0; i < len(state.enemies); i++ { for i := 0; i < len(state.enemies); i++ {
state.enemies[i].update(state, i) state.enemies[i].update(state)
} }
for i := 0; i < len(state.bullets); i++ { for i := 0; i < len(state.bullets); i++ {
@ -481,6 +606,7 @@ func main() {
state.gameSpeed = 1 state.gameSpeed = 1
} }
// rl.EndTextureMode() // rl.EndTextureMode()
// { // shaders // { // shaders
@ -526,7 +652,6 @@ func main() {
rl.DrawFPS(0, 0) rl.DrawFPS(0, 0)
} }
rl.EndDrawing() rl.EndDrawing()
} }