magnets/main.go

222 lines
5.3 KiB
Go

package main
import (
"fmt"
"math"
"math/rand"
rl "github.com/gen2brain/raylib-go/raylib"
)
type magnet struct {
pos rl.Vector2
color rl.Color
force float32
radius float32
}
type state struct {
windowHeight int32
windowWidth int32
magnetsDistance float32
}
type ball struct {
pos rl.Vector2
originGrid rl.Vector2
radius float32
speed rl.Vector2
}
func (ball *ball) update(magnets []magnet) (bool, rl.Color) {
magnetsPull := rl.Vector2{}
const ballMass float32 = 1
const gravConst float32 = 8
for _, magnet := range magnets {
direction := rl.Vector2Normalize(
rl.Vector2Subtract(ball.pos, magnet.pos),
)
distance := rl.Vector2Distance(magnet.pos, ball.pos)
force := gravConst * (ballMass * magnet.force) / distance
acceleration := rl.Vector2Scale(direction, -force)
magnetsPull = rl.Vector2Add(magnetsPull, acceleration)
}
// fmt.Println(magnetsPull)
ball.speed = rl.Vector2Add(ball.speed, magnetsPull)
ball.pos = rl.Vector2Add(ball.speed, ball.pos)
for _, magnet := range magnets {
distance := rl.Vector2Distance(ball.pos, magnet.pos)
if distance < magnet.radius + ball.radius {
return true, magnet.color
}
}
return false, rl.NewColor(0, 0, 0, 0)
}
func main() {
state := state{
windowWidth: 800,
windowHeight: 450,
}
rl.InitWindow(
state.windowWidth, state.windowHeight,
"raylib [core] example - basic window",
)
defer rl.CloseWindow()
// rl.SetTargetFPS(60)
const RADIUS = 10
const FORCE = 8
magnets := []magnet{
{
color: rl.Red,
radius: RADIUS,
force: FORCE,
},
{
color: rl.Green,
radius: RADIUS,
force: FORCE,
},
{
color: rl.Blue,
radius: RADIUS,
force: FORCE,
},
}
// pocisionar imas no meio da tela
xCenter := float32(state.windowWidth / 2)
yCenter := float32(state.windowHeight / 2)
var magnetsDistance float32 = 80
for i := range magnets {
angle := 2.0 * math.Pi * float64(i) / float64(len(magnets))
magnets[i].pos = rl.Vector2{
X: float32(math.Cos(angle)) * magnetsDistance + xCenter,
Y: float32(math.Sin(angle)) * magnetsDistance + yCenter,
}
}
verticalGrids := 60
horizontalGrids := 60
grid := make([][]rl.Color, verticalGrids)
for i := range grid {
grid[i] = make([]rl.Color, horizontalGrids)
for j := range grid[i] {
grid[i][j] = rl.Black
}
}
// ball := ball{
// pos: rl.Vector2{0, 0},
// originGrid: rl.Vector2{X: 0, Y: 0},
// }
//
gridSize := rl.Vector2{
X: float32(state.windowWidth / int32(verticalGrids)),
Y: float32(state.windowHeight / int32(horizontalGrids)),
}
var fallingBall []*ball
var fallingBallOrder []rl.Vector2
for y := range grid {
for x := range grid[y] {
fallingBallOrder = append(fallingBallOrder, rl.Vector2{
X: float32(x),
Y: float32(y),
})
}
}
rand.Shuffle(len(fallingBallOrder), func(i, j int) {
fallingBallOrder[i], fallingBallOrder[j] =
fallingBallOrder[j], fallingBallOrder[i]
})
for _, randomGrid := range fallingBallOrder {
x := randomGrid.X * gridSize.X + gridSize.X/2
y := randomGrid.Y * gridSize.Y + gridSize.Y/2
fallingBall = append(fallingBall, &ball{
pos: rl.Vector2{X: x, Y: y},
speed: rl.Vector2{},
radius: RADIUS/2,
originGrid: randomGrid,
})
}
for !rl.WindowShouldClose() {
rl.BeginDrawing()
rl.ClearBackground(rl.Black)
for y := range grid {
for x := range grid[y] {
pos := rl.Vector2{
X: gridSize.X * float32(x),
Y: gridSize.Y * float32(y),
}
rl.DrawRectangleV(pos, gridSize, grid[y][x])
}
}
for i := range magnets {
rl.DrawCircleV(magnets[i].pos, RADIUS+2, rl.Black)
rl.DrawCircleV(magnets[i].pos, RADIUS, magnets[i].color)
}
if len(fallingBall) == 0 {
rl.EndDrawing()
continue
}
for i := 0; i < len(fallingBall); i++ {
ball := fallingBall[i]
rl.DrawCircleV(
ball.pos, ball.radius/2+1, rl.Black,
)
rl.DrawCircleV(
ball.pos, ball.radius/2,
rl.NewColor(100, 100, 100, 255),
)
if hit, color := ball.update(magnets); hit {
x := ball.originGrid.X
y := ball.originGrid.Y
grid[int(y)][int(x)] = color
// remover bola
fallingBall[i] = fallingBall[len(fallingBall)-1]
fallingBall = fallingBall[:len(fallingBall)-1]
}
}
// fmt.Println("foo")
rl.EndDrawing()
}
stat := make(map[rl.Color]int)
stat[rl.Red] = 0
stat[rl.Green] = 0
stat[rl.Blue] = 0
for y := range grid {
for x := range grid[y] {
stat[grid[y][x]] += 1
}
}
fmt.Println(stat)
}