quadtree
This commit is contained in:
parent
f88f7f9d12
commit
110141ae44
1 changed files with 128 additions and 24 deletions
152
main.go
152
main.go
|
|
@ -17,12 +17,70 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
type quadnode struct {
|
||||||
|
topleft, bottomright rl.Vector2
|
||||||
|
magnet *magnet
|
||||||
|
parent *quadnode
|
||||||
|
nodes []*quadnode
|
||||||
|
}
|
||||||
|
|
||||||
|
func newQuadTree() *quadnode {
|
||||||
|
return &quadnode{
|
||||||
|
topleft: rl.NewVector2(0, 0),
|
||||||
|
bottomright: rl.NewVector2(windowWidth, windowHeight),
|
||||||
|
nodes: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *quadnode) subdivide() {
|
||||||
|
halfX := q.bottomright.X/2
|
||||||
|
halfY := q.bottomright.X/2
|
||||||
|
|
||||||
|
q.nodes = []*quadnode{
|
||||||
|
{
|
||||||
|
topleft: q.topleft,
|
||||||
|
bottomright: rl.Vector2{X: halfX, Y: halfY},
|
||||||
|
parent: q,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
topleft: rl.Vector2{X: halfX, Y: q.topleft.Y},
|
||||||
|
bottomright: rl.Vector2{X: q.bottomright.X, Y: halfY},
|
||||||
|
parent: q,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
topleft: rl.Vector2{X: q.topleft.X, Y: halfY},
|
||||||
|
bottomright: rl.Vector2{X: halfX, Y: q.bottomright.Y},
|
||||||
|
parent: q,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
topleft: rl.Vector2{X: halfX, Y: halfY},
|
||||||
|
bottomright: q.bottomright,
|
||||||
|
parent: q,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *quadnode) drawBoundaries() {
|
||||||
|
if q.nodes == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, node := range q.nodes {
|
||||||
|
node.drawBoundaries()
|
||||||
|
size := rl.Vector2Subtract(node.bottomright, node.topleft)
|
||||||
|
rl.DrawRectangleLines(
|
||||||
|
int32(node.topleft.X), int32(node.topleft.Y),
|
||||||
|
int32(size.X), int32(size.Y),
|
||||||
|
rl.Green,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type magnet struct {
|
type magnet struct {
|
||||||
pos rl.Vector2
|
pos rl.Vector2
|
||||||
speed rl.Vector2
|
speed rl.Vector2
|
||||||
color rl.Color
|
color rl.Color
|
||||||
// force float32
|
mass float32
|
||||||
// radius float32
|
radius float32
|
||||||
}
|
}
|
||||||
|
|
||||||
// type ball struct {
|
// type ball struct {
|
||||||
|
|
@ -34,15 +92,40 @@ type magnet struct {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// parâmetros
|
// parâmetros
|
||||||
const initalMagnetCount = 100
|
const initalMagnetCount = 10
|
||||||
const windowWidth = 700
|
const windowWidth = 700
|
||||||
const windowHeight = 700
|
const windowHeight = 700
|
||||||
const magnetRadius = 5
|
const magnetRadius = 5
|
||||||
const gravConst float32 = 10
|
const gravConst float32 = 10
|
||||||
|
|
||||||
// func insideArea(pos rl.Vector2) (bool, bool) {
|
func tick(magnets []*magnet) {
|
||||||
// return pos.X > 0 && pos.X < windowWidth, pos.Y > 0 && pos.Y < windowHeight
|
|
||||||
// }
|
for _, a := range magnets {
|
||||||
|
for _, b := range magnets {
|
||||||
|
if a == b { continue }
|
||||||
|
// não creio que isso esteja certo porem isso quaqueja que nem um pato
|
||||||
|
direction := rl.Vector2Normalize(rl.Vector2Subtract(a.pos, b.pos))
|
||||||
|
distance := rl.Vector2Distance(a.pos, b.pos)
|
||||||
|
distanceSquared := math.Pow(float64(distance), 2)
|
||||||
|
force := gravConst / float32(distanceSquared)
|
||||||
|
acceleration := rl.Vector2Scale(direction, force)
|
||||||
|
|
||||||
|
if distance < magnetRadius*2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// f = m * a
|
||||||
|
forceA := rl.Vector2Scale(acceleration, a.mass)
|
||||||
|
forceB := rl.Vector2Scale(acceleration, b.mass)
|
||||||
|
a.speed = rl.Vector2Add(a.speed, rl.Vector2Negate(forceB))
|
||||||
|
b.speed = rl.Vector2Add(b.speed, forceA)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, magnet := range magnets {
|
||||||
|
magnet.pos = rl.Vector2Add(magnet.pos, magnet.speed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (m *magnet) update(magnets []*magnet) {
|
func (m *magnet) update(magnets []*magnet) {
|
||||||
magnetsPull := rl.Vector2{}
|
magnetsPull := rl.Vector2{}
|
||||||
|
|
@ -52,9 +135,9 @@ func (m *magnet) update(magnets []*magnet) {
|
||||||
|
|
||||||
direction := rl.Vector2Normalize(rl.Vector2Subtract(m.pos, magnet.pos))
|
direction := rl.Vector2Normalize(rl.Vector2Subtract(m.pos, magnet.pos))
|
||||||
distance := rl.Vector2Distance(magnet.pos, m.pos)
|
distance := rl.Vector2Distance(magnet.pos, m.pos)
|
||||||
if (distance < magnetRadius*2) {
|
if (distance < magnetRadius*2 + 10) {
|
||||||
// direction = rl.Vector2Negate(direction)
|
direction = rl.Vector2Negate(direction)
|
||||||
continue
|
// continue
|
||||||
}
|
}
|
||||||
distanceSquared := math.Pow(float64(distance), 2)
|
distanceSquared := math.Pow(float64(distance), 2)
|
||||||
force := gravConst / float32(distanceSquared)
|
force := gravConst / float32(distanceSquared)
|
||||||
|
|
@ -74,28 +157,30 @@ func (m *magnet) update(magnets []*magnet) {
|
||||||
m.pos = newPos
|
m.pos = newPos
|
||||||
}
|
}
|
||||||
|
|
||||||
func randomMagnet() *magnet {
|
func newMagnet(x, y, mass float32) *magnet {
|
||||||
newMagnet := magnet{
|
newMagnet := magnet{
|
||||||
pos: rl.Vector2{
|
pos: rl.Vector2{X: x, Y: y},
|
||||||
X: float32(rand.Intn(windowWidth - 100) + 50),
|
|
||||||
Y: float32(rand.Intn(windowHeight - 100) + 50),
|
|
||||||
},
|
|
||||||
color: rl.NewColor(
|
color: rl.NewColor(
|
||||||
uint8(rand.Int()),
|
uint8(rand.Int()),
|
||||||
uint8(rand.Int()),
|
uint8(rand.Int()),
|
||||||
uint8(rand.Int()),
|
uint8(rand.Int()),
|
||||||
255,
|
255,
|
||||||
),
|
),
|
||||||
|
mass: mass,
|
||||||
|
radius: mass,
|
||||||
}
|
}
|
||||||
return &newMagnet
|
return &newMagnet
|
||||||
}
|
}
|
||||||
|
|
||||||
func createMagnets(n int) []*magnet {
|
func randomMagnets(n int) []*magnet {
|
||||||
var magnets []*magnet
|
var magnets []*magnet
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
magnets = append(magnets, randomMagnet())
|
x := float32(rand.Intn(windowWidth - 100) + 50)
|
||||||
|
y := float32(rand.Intn(windowHeight - 100) + 50)
|
||||||
|
magnets = append(magnets, newMagnet(x, y, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
return magnets
|
return magnets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,29 +192,48 @@ func main() {
|
||||||
defer rl.CloseWindow()
|
defer rl.CloseWindow()
|
||||||
rl.SetTargetFPS(60)
|
rl.SetTargetFPS(60)
|
||||||
|
|
||||||
magnets := createMagnets(initalMagnetCount)
|
magnets := randomMagnets(initalMagnetCount)
|
||||||
|
|
||||||
|
quadtree := newQuadTree()
|
||||||
|
quadtree.subdivide()
|
||||||
|
|
||||||
|
pause := true
|
||||||
|
|
||||||
for !rl.WindowShouldClose() {
|
for !rl.WindowShouldClose() {
|
||||||
|
|
||||||
rl.BeginDrawing()
|
rl.BeginDrawing()
|
||||||
rl.ClearBackground(rl.Black)
|
rl.ClearBackground(rl.Black)
|
||||||
rl.DrawFPS(0, 0)
|
rl.DrawFPS(0, 0)
|
||||||
|
|
||||||
// func rl.DrawText(text string, posX int32, posY int32, fontSize int32, col color.RGBA)
|
|
||||||
rl.DrawText(strconv.Itoa(len(magnets)), 0, 20, 20, rl.White)
|
rl.DrawText(strconv.Itoa(len(magnets)), 0, 20, 20, rl.White)
|
||||||
|
if pause {
|
||||||
|
rl.DrawText("pausado (E)", 0, 40, 20, rl.White)
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
if rl.IsKeyPressed(rl.KeyR) {
|
if rl.IsKeyPressed(rl.KeyR) {
|
||||||
magnets = createMagnets(len(magnets))
|
magnets = randomMagnets(initalMagnetCount)
|
||||||
}
|
}
|
||||||
if rl.IsKeyPressed(rl.KeyW) {
|
if rl.IsKeyPressed(rl.KeyW) {
|
||||||
magnets = append(magnets, createMagnets(100)...)
|
magnets = append(magnets, randomMagnets(100)...)
|
||||||
|
}
|
||||||
|
if rl.IsKeyPressed(rl.KeyE) {
|
||||||
|
pause = !pause
|
||||||
|
}
|
||||||
|
if rl.IsKeyPressed(rl.KeySpace) {
|
||||||
|
mouse := rl.GetMousePosition()
|
||||||
|
magnets = append(magnets, newMagnet(mouse.X, mouse.Y, 50))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !pause {
|
||||||
|
tick(magnets)
|
||||||
|
}
|
||||||
|
|
||||||
|
quadtree.drawBoundaries()
|
||||||
|
|
||||||
for _, magnet := range magnets {
|
for _, magnet := range magnets {
|
||||||
magnet.update(magnets)
|
rl.DrawCircleV(magnet.pos, magnet.radius+1, rl.White)
|
||||||
rl.DrawCircleV(magnet.pos, magnetRadius+1, rl.White)
|
rl.DrawCircleV(magnet.pos, magnet.radius, magnet.color)
|
||||||
rl.DrawCircleV(magnet.pos, magnetRadius, magnet.color)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rl.EndDrawing()
|
rl.EndDrawing()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue