Playdate Nim bindings - C performance, Python like syntax

Awesome! Any update to support nim 2.0?

Slowly working on it!

I did a benchmark using @Tengu base template.

Here's my results drawing all (8) the texts in a rect, right aligned!

Lua: 18-19 fps
Nim: 30 fps

Here's the project that includes the Nim version too.
text-in-rect-perf-test.zip (29.1 KB)

3 Likes

30 (default refresh rate limit) implies it could be even faster in Nim

It is 30 fps with unlocked frame rate.
Unfortunately this type of algorithm seems to be bottlenecked by the Playdate struggling a lot doing string manipulations and allocations. I kept them at minimum.

Also, not sure but getTextWidth might be another bottleneck.

1 Like

I hope to share a nim vs Lua benchmark soon, which uses a nim implementation of @matt's benchmark. I'll share it with @samdze first to see if I'm not misrepresenting nim performance due to my Nim noobishness.

Edit: see link below for results

1 Like

Hi All,
I'm very new to Nim and not sure what I'm doing wrong. I've followed the steps on the playdate-nim git page and have come across a few issues. I'm using vscode on wondows, any help is very much appreciated.

Issue 1.

when I get to the step: nimble setup

I get the below error.


   Tip: 1 messages have been suppressed, use --verbose to show them.

packageparser.nim(395) readPackageInfo

Error:  Could not read package info file in E:\playdate\Games_nim\Test_01\Test_01.nimble;
    ...   Reading as ini file failed with:
    ...     Invalid section: .
    ...   Evaluating as NimScript file failed with:
    ...     E:\playdate\Games_nim\Test_01\Test_01.nimble(14, 1) Error: undeclared identifier: 'r'
    ... printPkgInfo() failed.

Turns out the Test_01.nimble file had strange characters in the last two lines and if I replaced the lines with the below it ran the "nimble setup" command without a problem.


requires "playdate"
include playdate/build/nimble

Not sure if this is correct or not?

I've decided to go with the base temple project on git hub "playdate_example" which is the folder vscode is set to but I get this error when I run nimble simulate:


C:\Users\edit2pc\nimcache\playdate_example_d\simulator@mC@c@sUsers@sedit2pc@s.nimble@spkgs@splaydate-0.12.0@splaydate@sfile.nim.c:8:10: fatal error: pd_api.h: No such file or directory
8 | #include "pd_api.h"
| ^~~~~~~~~~
compilation terminated.
C:\Users\edit2pc\nimcache\playdate_example_d\simulator@mC@c@sUsers@sedit2pc@s.nimble@spkgs@splaydate-0.12.0@splaydate@stypes.nim.c:8:10: fatal error: pd_api.h: No such file or directory
8 | #include "pd_api.h"
| ^~~~~~~~~~
compilation terminated.
C:\Users\edit2pc\nimcache\playdate_example_d\simulator@mC@c@sUsers@sedit2pc@s.nimble@spkgs@splaydate-0.12.0@splaydate@ssprite.nim.c:8:10: fatal error: pd_api.h: No such file or directory
8 | #include "pd_api.h"
| ^~~~~~~~~~
compilat i oErnror : teBurilmd ifanilaed ftore pdac.ka
ge: playdate_example
... Execution failed with exit code 1
... Command: C:\Users\edit2pc.nimble\bin\nim.exe c --colors:on --noNimbleP thC:\Users\edit2pc\nimcache\playdate_example_d\simulator@mC@c@sUsers@sedit2pc@s.nimble@spkgs@splaydate-0.12.0@splaydate@ssound.nim.c:8:10: - :si mul tofatal error: r d:debpd_api.h: No such file or directory
8 | #include ug d:"pd_api.h"Ni bl
| ePk Ve^~rs on
=0.c8.o0 m--ppaithl:C:\Uasetrsi\eodint2 pc\t.neimrblem\pikgns\apltayedadte.-0
.12.0 -o:E:\playdate\Games_nim\playdate-nim-main\playdate_example\playdate_example.exe E:\playdate\Games_nim\playdate-nim-main\playdate_example\src\playdate_example.nim
C:\Users\edit2pc\nimcache\playdate_example_d\simulator@mplaydate_example.nim.c:8:10: fatal error: pd_api.h: No such file or directory
8 | #include "pd_api.h"
| ^
~


Have I missed something? It looks like it can't find the api files but I don't know what I'm meant to do.

Solved!

I found the problem, I feel so stupid! I had the environment path set to the C:\palydatesdk\bin instead of C:\palydatesdk.

Ehy, glad you already solved the problem!
Feel free to ask for support here or on GitHub!

Thanks, Samdze. I’m very keen to get my head around Nim as it looks great and thank you for putting all this work into nim-playdate.

I’ve got the example project working and now I’m trying to do a few things myself but hitting a few walls not sure if some of my code is wrong or not in the Nim bindings yet. I can create a sprite, draw it, move it but not change its centre. I have noticed this is a newish command in C and not sure if it’s in the Nim binding or I’m just doing it wrong? Here is the code I’ve used, all work except setCenter().

    # create bitmap
    my_Bitmap = try: playdate.graphics.newBitmap(MY_IMAGE_PATH) except: nil

    # create sprite
    my_sprite = playdate.sprite.newSprite()
    my_sprite.add()
    my_sprite.moveTo(200, 120)
    my_sprite.setImage(my_Bitmap, kBitmapUnflipped)
    my_sprite.setCenter(0.5, 1.0)

This is normal for now, the current version of the Nim bindings doesn't implement setCenter and getCenter.

But there's a pull request that adds them: Add sprite setCenter and getCenter by samdze · Pull Request #33 · samdze/playdate-nim · GitHub

It will be included in the next update!

Thanks for clearing that up. I think I might be having the same issue with BitmapTables so was wondering if there is any way of getting a list of the commands that are connected with the Nim bindings? Unless there is a list some somewhere already.

For now, the only way to reliably have a list of all the functions available is to inspect the source code.

But you can also get some support from VSCode autocomplete with one of the Nim editor plugins, it should show you the methods you can call on each object.

Also keep in mind that the bindings have a more object-oriented approach compared to the C API, so e.g. C BitmapTable functions are often defined as BitmapTable "methods" in Nim.

Thanks that's very helpful, I didn't even think about VScode autocomplete. I'm more of an artist than a coder so still getting my head around how a lot of the coding tools work and features they offer.

1 Like

I’ve made a lot of progress however one of the simplest things has still got me stuck. I can’t seem to scale a sprite like below with setSize(). VScode tells me it wants

setSize(this: ptr PlaydateSprite; sprite: LCDSprite; width: float;
height: float)?

# create bitmap
my_Bitmap = try: playdate.graphics.newBitmap(MY_IMAGE_PATH) except: nil

# create sprite
my_sprite = playdate.sprite.newSprite()
my_sprite.add()
my_sprite.moveTo(200, 120)
my_sprite.setSize(2, 1)

I don’t know what the difference is between LCDsprite and playdateSprite?

I think you found an oversight in the bindings. setSize signature is supposed to be setSize(this: LCDSprite, width: float, height: float), so that will be fixed in the next version!

The difference between the two types is that LCDSprite is the object that represents an individual sprite, PlaydateSprite is instead an SDK global object that provides essential functions related to sprites (such as creating a new sprite) but not bound to a single sprite in particular.

Another thing: setSize on a sprite doesn't scale it, to do that in the C/Nim API I suspect you should use LCDBitmap's drawScaled and use setDrawFunction on a sprite to use it as the sprite drawing method.

No worries I'll stay away from scaling for the moment.

Sorry to be a pest but another issue that I can't solve is after I compile for playdate simulator I get the following error. It all seems to work but the error worries me.

15:23:37: SDK: C:\PlaydateSDK
15:23:37: Release: 2.2.0
15:23:37: CMD: playdate.pdx
pdx directory not found: playdate.pdx
15:23:37: Loading: E:\playdate\Games_nim\test_05_Player_sprite\test_05_Player_sprite.pdx
Loading C API game: E:/playdate/Games_nim/test_05_Player_sprite/test_05_Player_sprite.pdx/pdex.dll
pc_sprite_free: non-NULL value required for argument 's'
15:23:37: Loading: OK

It seems to only happen when I use this code that is imported to create the player:

type
Player* = LCDSprite

proc initPlayer*(xPos: float, yPos: float, image: LCDBitmap): Player =
result = new(Player)
result = playdate.sprite.newSprite()
result.setImage(image, kBitmapUnflipped)
result.moveTo(xPos, yPos)
result.add()

Also the pdx directory not found has been like that from day one but I just ignore it and load the file manually in the playdate simulator.

That warning is probably caused by this line:

result = new(Player)

Initializing a LCDSprite this way is not supported, then you deallocate it (warning here, because result didn't have a valid handle to a LCDSprite) to replace it with a valid playdate.sprite.newSprite().

This error:
pdx directory not found: playdate.pdx
I'm not sure what's causing it without the project at hand.

Are we able to extend the sprite class like in lua? Or is it better to create a object that tracks all the info then gets the sprite to read that info at another point.