249 lines
6.8 KiB
Go
249 lines
6.8 KiB
Go
package main
|
|
|
|
// veja:
|
|
// The relationship between chaos, fractal and physics
|
|
// https://www.youtube.com/watch?v=C5Jkgvw-Z6E
|
|
|
|
import (
|
|
// "fmt"
|
|
"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 ball struct {
|
|
pos rl.Vector2
|
|
originGrid rl.Vector2
|
|
radius float32
|
|
speed rl.Vector2
|
|
steps int
|
|
}
|
|
|
|
// parâmetros
|
|
const windowWidth = 700
|
|
const windowHeight = 700
|
|
const gridDivision = 4
|
|
const verticalGrids = windowHeight/gridDivision
|
|
const horizontalGrids = windowWidth/gridDivision
|
|
const magnetsDistance float32 = 80
|
|
const magnetRadius = 10
|
|
const gravConst float32 = 50
|
|
const magnetsAngle = 30
|
|
const luminance = false
|
|
const hideBalls = true
|
|
const hideMagnets = false
|
|
var startingBallSpeed = rl.Vector2{X: 0, Y: 0} // joga a bola em alguma diração
|
|
// antes que ela comece a ser atraida pelos ímãs
|
|
var cameraOffset = rl.Vector2{X: 0, Y: 0}
|
|
|
|
func (ball *ball) update(magnets []magnet) (bool, rl.Color) {
|
|
magnetsPull := rl.Vector2{}
|
|
|
|
for _, magnet := range magnets {
|
|
direction := rl.Vector2Normalize(
|
|
rl.Vector2Subtract(ball.pos, magnet.pos),
|
|
)
|
|
distance := rl.Vector2Distance(magnet.pos, ball.pos)
|
|
distanceSquared := math.Pow(float64(distance), 2)
|
|
force := gravConst / float32(distanceSquared)
|
|
|
|
acceleration := rl.Vector2Scale(direction, -force)
|
|
|
|
magnetsPull = rl.Vector2Add(magnetsPull, acceleration)
|
|
}
|
|
|
|
ball.speed = rl.Vector2Add(ball.speed, magnetsPull)
|
|
ball.pos = rl.Vector2Add(ball.speed, ball.pos)
|
|
|
|
// verificar se bola parou em cima de um ímã
|
|
for _, magnet := range magnets {
|
|
|
|
distance := rl.Vector2Distance(ball.pos, magnet.pos)
|
|
|
|
insideMagnet := distance < magnet.radius /* + ball.radius */
|
|
// atRest := math.Abs(float64(rl.Vector2Length(ball.speed))) < 0.01
|
|
|
|
if insideMagnet /* && atRest */ {
|
|
if luminance { magnet.color.A = uint8(ball.steps) }
|
|
return true, magnet.color
|
|
}
|
|
}
|
|
return false, rl.NewColor(0, 0, 0, 0)
|
|
}
|
|
|
|
// var colors = []rl.Color{
|
|
// rl.Red, rl.Green, rl.Blue, rl.Yellow, rl.NewColor(0, 255, 255, 255),
|
|
// rl.Magenta, rl.White,
|
|
// }
|
|
|
|
func main() {
|
|
rl.InitWindow(
|
|
windowWidth, windowHeight,
|
|
"magnets",
|
|
)
|
|
defer rl.CloseWindow()
|
|
// rl.SetTargetFPS(60)
|
|
|
|
magnets := []magnet{
|
|
{
|
|
color: rl.Red,
|
|
radius: magnetRadius,
|
|
// force: magnetForce,
|
|
},
|
|
{
|
|
color: rl.Gray,
|
|
radius: magnetRadius,
|
|
// force: magnetForce,
|
|
},
|
|
{
|
|
color: rl.White,
|
|
radius: magnetRadius,
|
|
// force: magnetForce,
|
|
},
|
|
{
|
|
color: rl.Yellow,
|
|
radius: magnetRadius,
|
|
// force: magnetForce,
|
|
},
|
|
{
|
|
color: rl.Magenta,
|
|
radius: magnetRadius,
|
|
// force: magnetForce,
|
|
},
|
|
}
|
|
|
|
// posiciona imas em volta de um circulo
|
|
xCenter := float32(windowWidth / 2) + cameraOffset.X
|
|
yCenter := float32(windowHeight / 2) + cameraOffset.Y
|
|
for i := range magnets {
|
|
angle := 2.0 * math.Pi * float64(i) / float64(len(magnets)) + magnetsAngle
|
|
|
|
magnets[i].pos = rl.Vector2{
|
|
X: float32(math.Cos(angle)) * magnetsDistance + xCenter,
|
|
Y: float32(math.Sin(angle)) * magnetsDistance + yCenter,
|
|
}
|
|
}
|
|
|
|
|
|
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(windowWidth / int32(verticalGrids)),
|
|
Y: float32(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: startingBallSpeed,
|
|
radius: magnetRadius/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])
|
|
}
|
|
}
|
|
if !hideMagnets {
|
|
for i := range magnets {
|
|
rl.DrawCircleV(magnets[i].pos, magnetRadius+2, rl.Black)
|
|
rl.DrawCircleV(magnets[i].pos, magnetRadius, magnets[i].color)
|
|
}
|
|
}
|
|
|
|
if len(fallingBall) == 0 {
|
|
rl.EndDrawing()
|
|
continue
|
|
}
|
|
|
|
|
|
for i := 0; i < len(fallingBall); i++ {
|
|
ball := fallingBall[i]
|
|
|
|
if !hideBalls {
|
|
// rl.DrawCircleV(
|
|
// ball.pos, ball.radius/2+1, rl.Black,
|
|
// )
|
|
// rl.DrawCircleV(
|
|
// ball.pos, ball.radius/2,
|
|
// rl.NewColor(100, 100, 100, 255),
|
|
// )
|
|
// bolas são difíceis de se calcular =/
|
|
rl.DrawRectangleV(
|
|
rl.Vector2{X: ball.pos.X-1, Y: ball.pos.Y-1 },
|
|
rl.Vector2{X: ball.radius+1, Y: ball.radius+1},
|
|
rl.Black,
|
|
)
|
|
rl.DrawRectangleV(
|
|
ball.pos, rl.Vector2{X: ball.radius, Y: ball.radius},
|
|
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]
|
|
}
|
|
ball.steps += 1
|
|
}
|
|
|
|
// fmt.Println("foo")
|
|
|
|
rl.EndDrawing()
|
|
}
|
|
|
|
fmt.Println("hello world")
|
|
|
|
}
|