package main import ( // "fmt" "fmt" "math" "math/rand" "strconv" rl "github.com/gen2brain/raylib-go/raylib" ) type quadnode struct { // pos, size rl.Vector2 pos, size rl.Vector2 magnet *magnet parent *quadnode nodes []*quadnode debug string } func newQuadTree() *quadnode { return &quadnode{ pos: rl.NewVector2(0, 0), size: rl.NewVector2(windowWidth, windowHeight), nodes: nil, debug: "root", } } func (q *quadnode) subdivide() { halfX := q.size.X/2 halfY := q.size.Y/2 halfSize := rl.NewVector2(halfX, halfY) q.nodes = []*quadnode{ { pos: q.pos, size: halfSize, parent: q, debug: "0", }, { pos: rl.NewVector2(q.pos.X + halfX, q.pos.Y), size: halfSize, parent: q, debug: "1", }, { pos: rl.NewVector2(q.pos.X, q.pos.Y + halfY), size: halfSize, parent: q, debug: "2", }, { pos: rl.NewVector2(q.pos.X + halfX, q.pos.Y + halfY), size: halfSize, parent: q, debug: "3", }, } fmt.Println(q.debug) fmt.Println("halfX", halfX, "halfY", halfY) for i, node := range q.nodes { fmt.Println(i, node.pos, node.size) } // fmt.Println(q.nodes) } func (q *quadnode) drawBoundaries() { if q.nodes == nil { return } for _, node := range q.nodes { rl.DrawRectangleLines( int32(node.pos.X), int32(node.pos.Y), int32(node.size.X), int32(node.size.Y), rl.Green, ) } for _, node := range q.nodes { node.drawBoundaries() } } type magnet struct { pos rl.Vector2 speed rl.Vector2 color rl.Color mass float32 radius float32 } // parâmetros const initalMagnetCount = 10 const windowWidth = 700 const windowHeight = 700 const magnetRadius = 5 const gravConst float32 = 10 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{} for _, magnet := range magnets { if m == magnet { continue } direction := rl.Vector2Normalize(rl.Vector2Subtract(m.pos, magnet.pos)) distance := rl.Vector2Distance(magnet.pos, m.pos) if (distance < magnetRadius*2 + 10) { direction = rl.Vector2Negate(direction) // continue } distanceSquared := math.Pow(float64(distance), 2) force := gravConst / float32(distanceSquared) acceleration := rl.Vector2Scale(direction, -force) magnetsPull = rl.Vector2Add(magnetsPull, acceleration) } m.speed = rl.Vector2Add(m.speed, magnetsPull) newPos := rl.Vector2Add(m.speed, m.pos) // x, y := insideArea(newPos) // if !x { newPos.X = -newPos.X; m.speed.X = 0 } // if !y { newPos.Y = -newPos.Y; m.speed.Y = 0 } m.pos = newPos } func newMagnet(x, y, mass float32) *magnet { newMagnet := magnet{ 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 randomMagnets(n int) []*magnet { var magnets []*magnet for i := 0; i < n; i++ { x := float32(rand.Intn(windowWidth - 100) + 50) y := float32(rand.Intn(windowHeight - 100) + 50) magnets = append(magnets, newMagnet(x, y, 1)) } return magnets } func main() { rl.InitWindow( windowWidth, windowHeight, "barnes hut", ) defer rl.CloseWindow() rl.SetTargetFPS(60) magnets := randomMagnets(initalMagnetCount) quadtree := newQuadTree() quadtree.subdivide() quadtree.nodes[0].subdivide() quadtree.nodes[1].subdivide() quadtree.nodes[2].subdivide() quadtree.nodes[3].subdivide() quadtree.nodes[2].nodes[0].subdivide() pause := true for !rl.WindowShouldClose() { rl.BeginDrawing() rl.ClearBackground(rl.Black) rl.DrawFPS(0, 0) 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 = randomMagnets(initalMagnetCount) } if rl.IsKeyPressed(rl.KeyW) { 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 { rl.DrawCircleV(magnet.pos, magnet.radius+1, rl.White) rl.DrawCircleV(magnet.pos, magnet.radius, magnet.color) } rl.EndDrawing() } fmt.Println("hello world") }