implementar padrões de tiro

This commit is contained in:
silva guimaraes 2023-07-23 13:57:02 -03:00
parent fdacb47681
commit 1ddc892c70

174
main.go
View file

@ -2,25 +2,24 @@ package main
import ( import (
"fmt" "fmt"
"math"
"strconv" "strconv"
rl "github.com/gen2brain/raylib-go/raylib" rl "github.com/gen2brain/raylib-go/raylib"
) )
type movementPattern int type movementPattern func(*enemy)rl.Vector2
type shootingPattern int type shootingPattern func(*enemy)
type bulletMovementPattern func(*bullet)rl.Vector2
const ( type hazard interface { // inimigos e projéteis
horizontal movementPattern = iota Pos() rl.Vector2
circular movementPattern = iota }
)
type game struct { type game struct {
arenaWidth int32 arenaWidth int32
arenaHeight int32 arenaHeight int32
interfaceWidth int32 interfaceWidth int32
time int frame int
enemies []*enemy enemies []*enemy
bullets []*bullet bullets []*bullet
score int score int
@ -46,9 +45,10 @@ type player struct {
type enemy struct { type enemy struct {
pos rl.Vector2 pos rl.Vector2
health int health int
movePattern func(*enemy)rl.Vector2 move movementPattern
shootPattern func() shoot shootingPattern
hitBoxRadius float32 hitBoxRadius float32
bulletMoveSpeed float32
} }
func (g game) insideArena(v rl.Vector2) bool { func (g game) insideArena(v rl.Vector2) bool {
@ -72,25 +72,66 @@ func (b *bullet) update(g *game, index int) {
rl.DrawCircleV(b.pos, b.size, rl.Yellow) rl.DrawCircleV(b.pos, b.size, rl.Yellow)
} }
func (e *enemy) shoot(g *game) {
if g.time % 15 != 0 { func burstShootAtPlayer(g *game, p *player) shootingPattern {
flag := true
return func(e *enemy) {
if g.frame % 100 == 0 {
flag = !flag
}
if !flag {
return return
} }
if g.frame % 2 == 0 {
return
}
direction := rl.Vector2Subtract(p.pos, e.pos)
direction = rl.Vector2Normalize(direction)
direction = rl.Vector2Scale(direction, e.bulletMoveSpeed)
g.bullets = append(g.bullets, &bullet{ g.bullets = append(g.bullets, &bullet{
speed: rl.Vector2{X: 0, Y: 10}, speed: direction,
size: 4, size: 12,
dmg: 1, dmg: 1,
enemy: true, enemy: true,
pos: e.pos, pos: e.pos,
}) })
} }
}
func horizonalPattern(g *game) (func(*enemy)rl.Vector2) { func shootStraightDown(g *game) shootingPattern {
return func(e *enemy) {
if g.frame % 10 != 0 {
return
}
g.bullets = append(g.bullets, &bullet{
speed: rl.Vector2{X: 0, Y: 5},
size: 12,
dmg: 1,
enemy: true,
pos: e.pos,
})
}
}
func shootStill() movementPattern {
return func(e *enemy) rl.Vector2 {
e.shoot(e)
return e.pos
}
}
func horizonalPattern(g *game) movementPattern {
direction := rl.Vector2{X: 4, Y: 0} direction := rl.Vector2{X: 4, Y: 0}
return func(e *enemy) rl.Vector2 { return func(e *enemy) rl.Vector2 {
result := rl.Vector2Add(direction, e.pos) result := rl.Vector2Add(direction, e.pos)
e.shoot(e)
if !g.insideArena(result) { if !g.insideArena(result) {
direction = rl.Vector2Negate(direction) direction = rl.Vector2Negate(direction)
} }
@ -98,31 +139,43 @@ func horizonalPattern(g *game) (func(*enemy)rl.Vector2) {
} }
} }
func circlePattern(g *game, center rl.Vector2) (func(*enemy)rl.Vector2) { // func aimPlayerPattern(g *game, p *player) movementPattern {
// }
t := float64(0.5) func foobarPattern(g *game) movementPattern {
pos := rl.Vector2{}
state := 0
wait := 0
return func(e *enemy) rl.Vector2 { return func(e *enemy) rl.Vector2 {
// x' = (x - x₀) * cos(θ) - (y - y₀) * sin(θ) + x₀
// y' = (x - x₀) * sin(θ) + (y - y₀) * cos(θ) + y₀
// x' = x * cos(θ) - y * sin(θ) switch state {
// y' = x * sin(θ) + y * cos(θ) case 0: // init
pos.X = e.pos.X
// result := center state = 1
// return pos
// result.X = result.X + (e.pos.X - result.X) * float32(math.Cos(t)) - case 1: // descer
// (e.pos.Y - result.Y) * float32(math.Sin(t)) pos.Y += 1
// if pos.Y >= 100 { state = 2; wait = 50 }
// result.Y = result.Y + (e.pos.Y - result.Y) * float32(math.Sin(t)) + return pos
// (e.pos.Y - result.Y) * float32(math.Cos(t)) case 2: // atirar por um tempo
e.shoot(e)
result := center wait -= 1
result.X = result.X * float32(math.Cos(t)) - result.Y * float32(math.Sin(t)) if wait <= 0 { state = 3; wait = 60 }
result.Y = result.X * float32(math.Sin(t)) - result.Y * float32(math.Cos(t)) return pos
case 3: // wait
t += .08 wait -= 1
return result 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)
} }
} }
@ -134,7 +187,6 @@ func (e *enemy) checkHit(g *game) (bool, *bullet, int) {
continue continue
} }
distance := rl.Vector2Distance(e.pos, bullet.pos) - bullet.size distance := rl.Vector2Distance(e.pos, bullet.pos) - bullet.size
// fmt.Println(distance)
if distance < e.hitBoxRadius { if distance < e.hitBoxRadius {
return true, bullet, index return true, bullet, index
@ -153,8 +205,8 @@ func (e *enemy) update(g *game, index int) {
enemyColor := rl.Blue enemyColor := rl.Blue
if e.movePattern != nil { if e.move != nil {
e.pos = e.movePattern(e) e.pos = e.move(e)
} }
if hit, bullet, idx := e.checkHit(g); hit { if hit, bullet, idx := e.checkHit(g); hit {
@ -169,8 +221,6 @@ func (e *enemy) update(g *game, index int) {
return return
} }
e.shoot(g)
rl.DrawCircleV(e.pos, e.hitBoxRadius, enemyColor) rl.DrawCircleV(e.pos, e.hitBoxRadius, enemyColor)
} }
@ -203,12 +253,11 @@ func (p *player) move(g *game) {
} }
func (p *player) shoot(g *game){ func (p *player) shoot(g *game){
if g.time % 5 != 0 { if g.frame % 5 != 0 {
return return
} }
if rl.IsMouseButtonDown(rl.MouseLeftButton) { if rl.IsMouseButtonDown(rl.MouseLeftButton) {
// (mal) leva em consideração a velocidade do jogador
mouse := rl.GetMousePosition() mouse := rl.GetMousePosition()
direction := rl.Vector2Subtract(mouse, p.pos) direction := rl.Vector2Subtract(mouse, p.pos)
direction = rl.Vector2Add(direction, p.speed) direction = rl.Vector2Add(direction, p.speed)
@ -281,31 +330,40 @@ func main() {
pos: rl.Vector2{X: 200, Y: 200}, pos: rl.Vector2{X: 200, Y: 200},
health: 10, health: 10,
hitBoxRadius: 10, hitBoxRadius: 10,
movePattern: horizonalPattern(state), bulletMoveSpeed: 6,
}, move: horizonalPattern(state),
{ // shoot: shootStraightDown(state),
pos: rl.Vector2{X: 169, Y: 222}, shoot: burstShootAtPlayer(state, &player),
health: 10,
hitBoxRadius:10,
movePattern: horizonalPattern(state),
},
{
pos: rl.Vector2{X: 400, Y: 400},
health: 10,
hitBoxRadius:10,
// movePattern: circlePattern(state, rl.Vector2{X: 200, Y: 200}),
}, },
// {
// pos: rl.Vector2{X: 169, Y: 222},
// health: 10,
// hitBoxRadius:10,
// bulletMoveSpeed: 6,
// move: horizonalPattern(state),
// shoot: shootStraightDown(state),
// },
// {
// pos: rl.Vector2{X: 400, Y: 400},
// health: 10,
// hitBoxRadius:10,
// bulletMoveSpeed: 6,
// move: foobarPattern(state),
// shoot: shootStraightDown(state),
// },
{ {
pos: rl.Vector2{X: 200, Y: 200}, pos: rl.Vector2{X: 200, Y: 200},
health: 10, health: 10,
hitBoxRadius:10, hitBoxRadius:10,
// movePattern: circlePattern(state, rl.Vector2{X: 200, Y: 200}), bulletMoveSpeed: 6,
move: shootStill(),
shoot: shootStraightDown(state),
}, },
} }
currectScore := 0 currectScore := 0
for ; !rl.WindowShouldClose(); state.time += 1 { for ; !rl.WindowShouldClose(); state.frame += 1 {
rl.BeginDrawing() rl.BeginDrawing()
rl.ClearBackground(rl.Black) rl.ClearBackground(rl.Black)