From 110141ae4434b28e8c0cf7b17c0045f8bc627498 Mon Sep 17 00:00:00 2001 From: silva guimaraes Date: Fri, 18 Aug 2023 01:19:22 -0300 Subject: [PATCH] quadtree --- main.go | 152 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 128 insertions(+), 24 deletions(-) diff --git a/main.go b/main.go index c10ff96..55fbe9e 100644 --- a/main.go +++ b/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 { pos rl.Vector2 speed rl.Vector2 color rl.Color - // force float32 - // radius float32 + mass float32 + radius float32 } // type ball struct { @@ -34,15 +92,40 @@ type magnet struct { // } // parâmetros -const initalMagnetCount = 100 +const initalMagnetCount = 10 const windowWidth = 700 const windowHeight = 700 const magnetRadius = 5 const gravConst float32 = 10 -// func insideArea(pos rl.Vector2) (bool, bool) { -// return pos.X > 0 && pos.X < windowWidth, pos.Y > 0 && pos.Y < windowHeight -// } +func tick(magnets []*magnet) { + + 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) { magnetsPull := rl.Vector2{} @@ -52,9 +135,9 @@ func (m *magnet) update(magnets []*magnet) { direction := rl.Vector2Normalize(rl.Vector2Subtract(m.pos, magnet.pos)) distance := rl.Vector2Distance(magnet.pos, m.pos) - if (distance < magnetRadius*2) { - // direction = rl.Vector2Negate(direction) - continue + if (distance < magnetRadius*2 + 10) { + direction = rl.Vector2Negate(direction) + // continue } distanceSquared := math.Pow(float64(distance), 2) force := gravConst / float32(distanceSquared) @@ -74,28 +157,30 @@ func (m *magnet) update(magnets []*magnet) { m.pos = newPos } -func randomMagnet() *magnet { +func newMagnet(x, y, mass float32) *magnet { newMagnet := magnet{ - pos: rl.Vector2{ - X: float32(rand.Intn(windowWidth - 100) + 50), - Y: float32(rand.Intn(windowHeight - 100) + 50), - }, + pos: rl.Vector2{X: x, Y: y}, color: rl.NewColor( uint8(rand.Int()), uint8(rand.Int()), uint8(rand.Int()), 255, ), + mass: mass, + radius: mass, } return &newMagnet } -func createMagnets(n int) []*magnet { +func randomMagnets(n int) []*magnet { var magnets []*magnet 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 } @@ -107,29 +192,48 @@ func main() { defer rl.CloseWindow() rl.SetTargetFPS(60) - magnets := createMagnets(initalMagnetCount) + magnets := randomMagnets(initalMagnetCount) + + quadtree := newQuadTree() + quadtree.subdivide() + + pause := true for !rl.WindowShouldClose() { + rl.BeginDrawing() rl.ClearBackground(rl.Black) 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) + if pause { + rl.DrawText("pausado (E)", 0, 40, 20, rl.White) + } { if rl.IsKeyPressed(rl.KeyR) { - magnets = createMagnets(len(magnets)) + magnets = randomMagnets(initalMagnetCount) } 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 { - magnet.update(magnets) - rl.DrawCircleV(magnet.pos, magnetRadius+1, rl.White) - rl.DrawCircleV(magnet.pos, magnetRadius, magnet.color) + rl.DrawCircleV(magnet.pos, magnet.radius+1, rl.White) + rl.DrawCircleV(magnet.pos, magnet.radius, magnet.color) } rl.EndDrawing()