This tutorial combines Zig
, Raylib
and Box2D
together to show some cool stuff.
Long story short, Raylib
is capable of drawing 2D/3D graphics/UIs for any purpose, and Box2D
is capable of simulating real-world physics.
This project uses zig 0.12.0-dev.1834+f36ac227b
, if you use zig 0.11
, all xxx_build.zig
and build.zig
might not work.
This repo depends on box2c
and raylib
repos and has separate build step to compile them from source.
git submodule update --init --depth=1
# Submodule 'box2c' (https://github.com/erincatto/box2c.git) registered for path 'box2c'
# Submodule 'raylib' (https://github.com/raysan5/raylib.git) registered for path 'raylib'
# Cloning into '/home/wison/zig/raylib-box2d-tutorials/box2c'...
# Cloning into '/home/wison/zig/raylib-box2d-tutorials/raylib'...
# remote: Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
# remote: Enumerating objects: 27, done.
# remote: Counting objects: 100% (27/27), done.
# remote: Compressing objects: 100% (12/12), done.
# remote: Total 14 (delta 11), reused 2 (delta 0), pack-reused 0
# Unpacking objects: 100% (14/14), 1.88 KiB | 481.00 KiB/s, done.
# From https://github.com/erincatto/box2c
# * branch 519ded32531e1574caba32700481f4b5294dc383 -> FETCH_HEAD
# Submodule path 'box2c': checked out '519ded32531e1574caba32700481f4b5294dc383'
# Submodule path 'raylib': checked out '99f22a47ff09ae3bef4ee16c1910953efc46832b'
Open raylib/src/build.zig
and add .preferred_optimize_mode
support like below:
const optimize = b.standardOptimizeOption(.{
// .preferred_optimize_mode = .ReleaseFast,
.preferred_optimize_mode = .ReleaseSmall,
});
After that, zig build -Drelease=true
works, that’s what raylib_build.zig
does!!!
zig build --help | grep "run-"
# run-dynamic-box Run the dynamic-box demo
# run-centre-with-player-position Run the centre-with-player-position demo
# run-move-and-zoom-by-mouse Run the move-and-zoom-by-mouse demo
# run-first-person-view Run the first-person-view demo
# run-how-to-draw-images-and-textures Run the how-to-draw-images-and-textures demo
# run-how-to-play-audio Run the how-to-play-audio demo
# run-how-to-deal-with-fonts Run the how-to-deal-with-fonts demo
# run-temp-test Run the temp-test demo
For example:
zig build run-dynamic-box
All demo run steps don’t create binary files into zig-out/bin
folder, if you want to produce binary files, please run zig build
or zig build -Drelease=true
.
# Optional, remove cache and existing files
rm -rf zig-cache zig-out
# Create release build
zig build -Drelease=true
# List release binaries
ls -lht zig-out/{lib,bin}
# zig-out/bin:
# total 13M
# -rwxr-xr-x 1 7.0M Dec 25 16:49 click-to-generate-dynamic-boxes*
# -rwxr-xr-x 1 6.0M Dec 25 16:49 temp-test*
#
# zig-out/lib:
# total 14M
# -rw-r--r-- 1 14M Dec 25 16:49 libbox2c.a
raylib_build.zig
runscd raybuild && zig build
command behind the scenes to create a static library and a few header files:ls -lht raylib/zig-out/{lib, include} # raylib/zig-out/lib: # total 12M # -rw-r--r-- 1 wison wison 12M Dec 25 16:25 libraylib.a # # raylib/zig-out/include: # total 416K # -rw-r--r-- 1 wison wison 226K Dec 25 15:30 rlgl.h # -rw-r--r-- 1 wison wison 123K Dec 25 15:30 raylib.h # -rw-r--r-- 1 wison wison 62K Dec 25 15:30 raymath.h
box2c_buidl.zig
creates a static library:zig-out/lib/libbox2c.a
, and it depends onraylib build
.
demo_build.zig
create all demo run steps, each demo binary links toraylib/zig-out/lib/libraylib.a
andzig-out/lib/libbox2c.a
statically.
Raylib
API cheatsheet is here.
Represent a physics world, it’s a collection of bodies, fixtures, and constraints that interact together.
Box2D supports the creation of multiple worlds (each of them has different World Id
).
Simulate a physical object in the real world, its physical attribute affects every simulation step calculation in the world
Each body has a type:
static
(default): zero mass, zero velocity, may be manually movedkinematic
: zero mass, non-zero velocity set by user, moved by solverdynamic
: positive mass, non-zero velocity determined by forces, moved by solver
The body itself doesn’t have geometry attributes (how it looks), that’s why usually a body will have a Shape attached to it to represent the geometry attributes.
It represents the geometry attributes of a given Body
, it determines how the Body
looks like:
Polygon Shape
- Including Box/Rectangle/Square (4 vertices polygon)Circle Shape
Capsule Shape
Chain Shape
- used as surface
Also, it has the following physical attributes, e.g:
- friction (default value
0.6
) - restitution (default is
0.0
): affect the bouncing behaviour - density (default is
0.0
): affect the mass
Here are the steps about how to create a rigid body in the Box2D world:
- Create
b2BodyDef
instance with the following attributes:- init position
- type
static
(default): zero mass, zero velocity, may be manually movedkinematic
: zero mass, non-zero velocity set by user, moved by solverdynamic
: positive mass, non-zero velocity determined by forces, moved by solver
- Create a body instance (
b2BodyId)
by the givenb2BodyDef
, body instance is heap-allocated and it has no geometry (no shape), it represents the physical attributes:- position
- velocity
- acceleration
- force
- torque
- mass
- etc.
- Create
Shape
(heap-allocated) and attach it to theBody
, it determines how theBody
looks like:b2MakeBox/b2MakeRoundedBox
-> Polygon Shape - Including Box/Rectangle/Square (4 vertices polygon)b2Circle
-> Circle Shapeb2MakeCapsule
-> Capsule ShapeChain Shape
- used as surface
You need to create
b2ShapeDef
to describe the other physical attributes, e.g:- friction (default value
0.6
) - restitution (default is
0.0
): affect the bouncing behaviour - density (default is
0.0
): affect the mass