main.odin (2743B)
1 // Odin + Box2D + Raylib example with stacking boxes and a shape attached to the cursor that can smack the shapes. 2 // Made (mostly) during this stream: https://www.youtube.com/watch?v=LYW7jdwEnaI 3 4 // I have updated this to use the `vendor:box2d` bindings instead of the ones I used on the stream. 5 6 package game 7 8 import b2 "../box2d" 9 import rl "vendor:raylib" 10 import "core:math" 11 12 create_box :: proc(world_id: b2.WorldId, pos: b2.Vec2) -> b2.BodyId{ 13 body_def := b2.DefaultBodyDef() 14 body_def.type = .dynamicBody 15 body_def.position = pos 16 body_id := b2.CreateBody(world_id, body_def) 17 18 shape_def := b2.DefaultShapeDef() 19 shape_def.density = 1 20 shape_def.friction = 0.3 21 22 box := b2.MakeBox(20, 20) 23 box_def := b2.DefaultShapeDef() 24 _ = b2.CreatePolygonShape(body_id, box_def, box) 25 26 return body_id 27 } 28 29 main :: proc() { 30 rl.InitWindow(1280, 720, "Box2D + Raylib example") 31 32 world_def := b2.DefaultWorldDef() 33 world_def.gravity = b2.Vec2{0, -1} 34 world_id := b2.CreateWorld(world_def) 35 defer b2.DestroyWorld(world_id) 36 37 ground := rl.Rectangle { 38 0, 600, 39 1280, 120, 40 } 41 42 ground_body_def := b2.DefaultBodyDef() 43 ground_body_def.position = b2.Vec2{ground.x, -ground.y-ground.height} 44 ground_body_id := b2.CreateBody(world_id, ground_body_def) 45 46 ground_box := b2.MakeBox(ground.width, ground.height) 47 ground_shape_def := b2.DefaultShapeDef() 48 _ = b2.CreatePolygonShape(ground_body_id, ground_shape_def, ground_box) 49 50 bodies: [dynamic]b2.BodyId 51 52 px: f32 = 400 53 py: f32 = -400 54 55 num_per_row := 10 56 num_in_row := 0 57 58 for _ in 0..<50 { 59 b := create_box(world_id, {px, py}) 60 append(&bodies, b) 61 num_in_row += 1 62 63 if num_in_row == num_per_row { 64 py += 30 65 px = 200 66 num_per_row -= 1 67 num_in_row = 0 68 } 69 70 px += 30 71 } 72 73 body_def := b2.DefaultBodyDef() 74 body_def.type = .dynamicBody 75 body_def.position = b2.Vec2{0, 4} 76 body_id := b2.CreateBody(world_id, body_def) 77 78 shape_def := b2.DefaultShapeDef() 79 shape_def.density = 1000 80 shape_def.friction = 0.3 81 82 circle: b2.Circle 83 circle.radius = 40 84 _ = b2.CreateCircleShape(body_id, shape_def, circle) 85 86 time_step: f32 = 1.0 / 60 87 sub_steps: i32 = 4 88 89 for !rl.WindowShouldClose() { 90 rl.BeginDrawing() 91 rl.ClearBackground(rl.BLACK) 92 93 rl.DrawRectangleRec(ground, rl.RED) 94 mouse_pos := rl.GetMousePosition() 95 96 b2.Body_SetTransform(body_id, {mouse_pos.x, -mouse_pos.y}, {}) 97 b2.World_Step(world_id, time_step, sub_steps) 98 99 for b in bodies { 100 position := b2.Body_GetPosition(b) 101 r := b2.Body_GetRotation(b) 102 a := math.atan2(r.s, r._c) 103 // Y position is flipped because raylib has Y down and box2d has Y up. 104 rl.DrawRectanglePro({position.x, -position.y, 40, 40}, {20, 20}, a*(180/3.14), rl.YELLOW) 105 } 106 107 rl.DrawCircleV(mouse_pos, 40, rl.MAGENTA) 108 rl.EndDrawing() 109 } 110 111 rl.CloseWindow() 112 }