Playbox2d (port of box2d lite physics engine to C and Playdate SDK)

I've finally got a copy of my C port of box2d lite up on Github. Please make and submit changes. Included is a Playdate SDK demo of movement, friction, drawing, joints, etc.

playbox-demo

Feel free to discuss here, ask questions, etc. I'll try to get some time together to create documentation for the library. For now, the demo will have to be that.

Performance is best I've seen so far, as far as physics engines are concerned on device. Good performance up to about 8 active bodies in world.

19 Likes

Going to definitely try using this. Thanks so much for putting this together!

1 Like

Very cool, many thanks for this!

1 Like

This is sick! I cant wait to try some physics on-device.

1 Like

How would you suggest making a multi-segment "joint" between two bodies? Is that possible? Am thinking along lines of a chain or rope connecting two things...

I experimented a bit with that for my prototype Lil' Crane and I didn't find a satisfying solution. Box2d lite is well suited for the Playdate because it is limited in scope which also mean that it is a bit limited to do stuff like strings.

In the end I ended up using a single joint for a whole rope and just render the rope with a curve if the distance between bodies was less than the length of the joint.

If you want the rope or chain to actually collide with the other bodies, you need to create a series of slim bodies and link them with show joints. But the issue is that is will not be great for performance and I think bodies will very easily get crazy and unstable. I could work but it will need a lot of tweaking.

1 Like

Your idea of rendering a curve even though the joint is a line is excellent, I may well do that in conjunction with the "softness" property, which as far as I can tell allows the joint to stretch. Will try to come up with a "droop" curve for the rope if it's not being stretched...

Thanks!

2 Likes

Hello. Appreciate this isn't a Lua and C general help forum, but wondered if you could help point me in the right direction. How do I include things like this into my project? I'm a Mac user, so not sure if the makefile is relevant to me. Do I need to use a builder?

Thanks.

Edit: Tried it in Nova and it works perfectly. Thinking I need a builder for VS Code. I'll use Nova in the meantime. Thanks for sharing.

Edit 2: Is it possible to get the force of a collision? Or the velocity?

1 Like

I am trying to use it in my project but I am a linux user, how can I add this to my vscode project? When I import to simulator allways says that playbox is not found.
Thanks so much

Take a look at the makefile for the example and how it references playbox2d. Also main.c for how to add playbox2d API to the Lua runtime.

Check the Makefile in the example and main.c for how to add the API to the Lua runtime. Nova handles building this for you and I highly recommend it for Playdate dev. :slight_smile:

1 Like

Yeah. It’s ace. I bought it :slight_smile:

Loving the physics. And it’s fun getting back into code. No grand ambitions but good for the soul (and the brain).

1 Like

I will check these things. Nova is only for macOS and I dont have mac and I love Linux.
Thanks so much

1 Like

I'm also trying to get this working with Nova, however I'm running into errors on building. I'm pretty new to developing on Mac, so not quite sure where my issue is. I downloaded the directory from GitHub, loaded it in Nova and tried to build with the Playdate extension, however I get this error. Do you have any ideas? I appreciate all the work you've done on porting this!

Task Terminated with exit code 1
/usr/local/bin/arm-none-eabi-gcc
detected_OS is "Darwin"
mkdir -p build
mkdir -p build/dep
mkdir -p `dirname build/extension/main.o`
/usr/local/bin/arm-none-eabi-gcc -g -c -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-sp-d16 -D__FPU_USED=1 -O2 -falign-functions=16 -fomit-frame-pointer -gdwarf-2 -Wall -Wno-unused -Wstrict-prototypes -Wno-unknown-pragmas -fverbose-asm -Wdouble-promotion -ffunction-sections -fdata-sections -Wa,-ahlms=build/main.lst -DTARGET_PLAYDATE=1 -DTARGET_EXTENSION=1  -MD -MP -MF build/dep/main.o.d -I . -I . -I /Users/ME/Developer/PlaydateSDK/C_API -I extension -I playbox2d extension/main.c -o build/extension/main.o
make: /usr/local/bin/arm-none-eabi-gcc: Bad CPU type in executable
make: *** [build/extension/main.o] Error 1
The file /Users/ME/Downloads/playbox2d-main/playboxdemo.pdx does not exist.
Task “Build” exited with a non-zero exit status: 1.

It's failing at:

make: /usr/local/bin/arm-none-eabi-gcc: Bad CPU type in executable

Are you running an M1 Mac?

You'll need to install Rosetta to run the Intel-only arm toolchain on an M1 Mac.

softwareupdate --install-rosetta

From: https://apple.stackexchange.com/a/408379/15281

2 Likes

Ah, that was it, after running that I was able to get it working!

1 Like

I can't seem to get it to work. I can build it with make if I comment out the last line of the Makefile.

detected_OS is "Linux"
mkdir -p build
mkdir -p build/dep
cp build/pdex.bin Source
gcc -shared -fPIC -lm -DTARGET_SIMULATOR=1 -DTARGET_EXTENSION=1 -I . -I ~/PlaydateSDK/C_API -I extension -I playbox2d -o build/pdex.so extension/main.c playbox2d/array.c playbox2d/maths.c playbox2d/body.c playbox2d/joint.c playbox2d/collide.c playbox2d/arbiter.c playbox2d/world.c playbox2d/playbox.c ~/PlaydateSDK/C_API/buildsupport/setup.c
touch Source/pdex.bin
cp build/pdex.so Source
~/PlaydateSDK/bin/pdc -sdkpath ~/PlaydateSDK Source playboxdemo.pdx

But I get this error when I open it with the simulator

11:28:19: Loading: OK
update failed: main.lua:58: attempt to index a nil value (global 'playbox')
stack traceback:
	main.lua:58: in function 'setup'
	main.lua:8: in function <main.lua:6>

Edit: I'm able to get it to run on the simulator on Linux, just not on the simulator on Windows.

Something is not setting up playbox correctly. Specifically, the registerPlaybox() method looks like it's never called because that is what makes Lua aware of the playbox global.

The call is located in the main.c file:

int eventHandler(PlaydateAPI* playdate, PDSystemEvent event, uint32_t arg) {
  if(event == kEventInitLua) {
    pd = playdate;
    registerPlaybox();     // <--- here
  }
  return 0;
}

I didn't run into any problems related to 'registerPlaybox()' (just a datapoint)

(It's a wonder what some regular sleep and no interruptions can do - have been on vacation since Wednesday) - I finally had time to attempt setting up the Playdate SDK for mixed C/Lua builds on both an M1 Mac Mini and my regular Windows workstation, and have the playbox2d demo built, up and running on both (had to tweak the sources a bit to get Visual Studio 2019 happy, it didn't like 'unknown size' for a type of 'void*' or unsized array declarations): VS2019 tweaks .

This is neat stuff! I can't wait to build a minigame/easteregg with it.

Running on MacOS Ventura (M1)

Running on Win11/x64 from Visual Studio 2019

If it helps anyone, here's the CMakeLists.txt file I put together so CMake could generate the VS2019 solution files:

cmake_minimum_required(VERSION 3.14)
set(CMAKE_C_STANDARD 11)

set(ENVSDK $ENV{PLAYDATE_SDK_PATH})

if (NOT ${ENVSDK} STREQUAL "")
	# Convert path from Windows
	file(TO_CMAKE_PATH ${ENVSDK} SDK)
else()
	execute_process(
			COMMAND bash -c "egrep '^\\s*SDKRoot' $HOME/.Playdate/config"
			COMMAND head -n 1
			COMMAND cut -c9-
			OUTPUT_VARIABLE SDK
			OUTPUT_STRIP_TRAILING_WHITESPACE
	)
endif()

if (NOT EXISTS ${SDK})
	message(FATAL_ERROR "SDK Path not found; set ENV value PLAYDATE_SDK_PATH")
	return()
endif()

set(CMAKE_CONFIGURATION_TYPES "Debug;Release")
set(CMAKE_XCODE_GENERATE_SCHEME TRUE)

# Game Name Customization
set(PLAYDATE_GAME_NAME playboxdemo)
set(PLAYDATE_GAME_DEVICE playboxdemo_DEVICE)

project(${PLAYDATE_GAME_NAME} C ASM)

if (TOOLCHAIN STREQUAL "armgcc")
	add_executable(${PLAYDATE_GAME_DEVICE} ${SDK}/C_API/buildsupport/setup.c extension/main.c playbox2d/arbiter.c playbox2d/arbiter.h playbox2d/array.c playbox2d/array.h playbox2d/body.c playbox2d/body.h playbox2d/collide.c playbox2d/joint.c playbox2d/joint.h playbox2d/maths.c playbox2d/maths.h playbox2d/platform.h playbox2d/playbox.c playbox2d/playbox.h playbox2d/world.c playbox2d/world.h )
else()
	add_library(${PLAYDATE_GAME_NAME} SHARED extension/main.c extension/main.c playbox2d/arbiter.c playbox2d/arbiter.h playbox2d/array.c playbox2d/array.h playbox2d/body.c playbox2d/body.h playbox2d/collide.c playbox2d/joint.c playbox2d/joint.h playbox2d/maths.c playbox2d/maths.h playbox2d/platform.h playbox2d/playbox.c playbox2d/playbox.h playbox2d/world.c playbox2d/world.h )
endif()

include(${SDK}/C_API/buildsupport/playdate_game.cmake)

Beyond that, all I did was work through the ARM/CMake toolchain installation steps described in 3. Building on Windows using Visual Studio/CMake and picked VS for build as describe in 3.3. Building for the Simulator using Visual Studio .

Building on the Mac was dirt simple (bought Nova and used it :wink: )