raylib-teste/main.go
2023-09-14 01:26:05 -03:00

344 lines
7.7 KiB
Go

package main
import (
"fmt"
"math"
"math/rand"
rl "github.com/gen2brain/raylib-go/raylib"
)
const (
WIDTH = 1100
HEIGHT = 700
buildingSpacing = 2.5
buildingSize = 1.2
maxColumns = 5
enemyAcc = 0.01
maxSpeed = 0.1
)
type enemy struct {
pos rl.Vector3
speed float32
}
type remainingFrames int
type animationFunc func()remainingFrames
type building struct {
pos rl.Vector3
size rl.Vector3
color rl.Color
life int
boundingBox rl.BoundingBox
animate animationFunc
}
type healthBar struct {
life int
damageTaken int
lastUpdate float64
}
func draw_plane() {
rl.DrawPlane(
rl.NewVector3(16, 0.0, 16),
rl.NewVector2(128.0, 128.0),
rl.NewColor(50, 50, 50, 255),
)
}
func (hb *healthBar) update(buildings []*building) {
const margin = 20
buildingsLife := 0
maxCityLife := 3 * len(buildings)
for _, b := range buildings {
buildingsLife += b.life
}
position := rl.NewVector2(margin, 10)
cityLife := (WIDTH-margin*2) * buildingsLife/maxCityLife
size := rl.NewVector2(float32(cityLife), 10)
hb.damageTaken += cityLife - hb.life
damageTaken := size
damageTaken.X += float32(hb.damageTaken)
rl.DrawRectangleV(position, damageTaken, rl.Orange)
rl.DrawRectangleV(position, size, rl.Red)
hb.lastUpdate = rl.GetTime()
}
func newHealthBar(buildings []*building) *healthBar {
return &healthBar{
life: 3 * len(buildings),
}
}
func (b *building) causeDamage() {
if b.animate != nil {
return
}
b.animate = shakeBuilding(*b)
b.life -= 1
fmt.Println("damage:", b.life)
}
func newBuilding(x, z float32) *building {
color := rl.NewColor(
uint8(rl.GetRandomValue(0, 180)),
uint8(rl.GetRandomValue(0, 180)),
uint8(rl.GetRandomValue(0, 180)),
255,
)
pos := rl.NewVector3(x * buildingSpacing, 0, z * buildingSpacing)
size := rl.NewVector3(
buildingSize,
float32(rl.GetRandomValue(1, 7)),
buildingSize,
)
min := rl.NewVector3(
pos.X - buildingSize/2,
0,
pos.Z - buildingSize/2,
)
max := rl.NewVector3(
pos.X + buildingSize/2,
size.Y/2,
pos.Z + buildingSize/2,
)
return &building{
color: color,
life: 3,
pos: pos,
size: size,
boundingBox: rl.NewBoundingBox(min, max),
}
}
func drawWireframe(building building) {
increasedSize := rl.Vector3Scale(building.size, 1.05)
invertedColor := building.color
invertedColor.R += 127
invertedColor.G += 127
invertedColor.B += 127
rl.DrawCubeWiresV(
building.pos,
increasedSize,
invertedColor,
)
}
func shakeBuilding(b building) animationFunc {
var frame remainingFrames = 60 * 0.7
return func() remainingFrames {
building := b
if frame % 4 == 0 {
building.color = rl.RayWhite
}
drawWireframe(b)
shake := rl.NewVector3(
rand.Float32() * .2 - .1,
rand.Float32() * .1 - .05,
rand.Float32() * .2 - .1,
)
// shake = rl.Vector3Scale(shake, float32(math.Sin(rl.GetTime()) + 1)/3)
rl.DrawCubeV(
rl.Vector3Add(building.pos, shake),
building.size,
building.color,
)
frame -= 1
return frame
}
}
func draw_buildings(buildings []*building) {
for _, building := range buildings {
hasAnimation := building.animate != nil
if hasAnimation {
remainingFrames := building.animate()
if remainingFrames == 0 {
building.animate = nil
}
continue
}
if building.life == 0 {
continue
}
drawWireframe(*building)
rl.DrawCubeV(building.pos, building.size, building.color)
}
}
func damage_building(camera rl.Camera, buildings []*building) {
if !rl.IsMouseButtonDown(rl.MouseLeftButton) {
return
}
ray := rl.Ray{
Position: camera.Position,
Direction: rl.Vector3Subtract(camera.Target, camera.Position),
}
closestDistance := math.Inf(1)
var closest *building
for _, building := range buildings {
if building.life == 0 {
continue
}
playerDistance := rl.Vector3Distance(camera.Position, building.pos)
if playerDistance < float32(closestDistance) {
collision := rl.GetRayCollisionBox(ray, building.boundingBox)
if collision.Hit {
closestDistance = float64(playerDistance)
closest = building
}
}
}
if closest != nil {
closest.causeDamage()
}
}
func main() {
fmt.Println("hello world")
rl.SetConfigFlags(rl.FlagMsaa4xHint)
rl.InitWindow(WIDTH, HEIGHT, "raylib [core] example - 3d camera first person")
rl.SetTargetFPS(60)
rl.HideCursor()
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)))
}
}
healthBar := newHealthBar(buildings)
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.BeginDrawing()
rl.ClearBackground(rl.LightGray)
rl.BeginMode3D(camera)
{
damage_building(camera, buildings)
draw_plane()
draw_buildings(buildings)
}
rl.EndMode3D()
rl.DrawLineV(
rl.NewVector2(WIDTH/2-5, HEIGHT/2-5),
rl.NewVector2(WIDTH/2+5, HEIGHT/2+5),
rl.Red,
)
rl.DrawLineV(
rl.NewVector2(WIDTH/2-5, HEIGHT/2+5),
rl.NewVector2(WIDTH/2+5, HEIGHT/2-5),
rl.Red,
)
rl.DrawFPS(0, HEIGHT-30)
healthBar.update(buildings)
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
// )