Latest Posts (10 found)
NULL on error 2 months ago

Carimbo now have a better stack trace and Sentry integration

As I’ve already said countless times, I’m working on my first game for Steam, which you can check out online at reprobate.site . Since it’s a paid game, I need to provide proper bug support. With that in mind, and based on both professional and personal experience, I decided to use Sentry . At first, integrating C++ and Lua should have been straightforward, but I ran into some issues when using the Conan package manager. Initially, the package wasn’t being included in the compiler’s include flags, which led me to open an issue both on Conan Center and on Sentry Native . After spending a whole day on this, I eventually found out that the fix was actually pretty simple. Now Carimbo has native support for Sentry, both on the web (WebAssembly) and natively (Android, iOS, Linux, Windows, and macOS). Here’s how I managed to get it working. This was certainly my biggest problem. For some reason, even when following Conan’s documentation, I couldn’t get it to include the header path for Sentry Native. In the end, my solution looked like this: The native part was pretty easy, but for the web part I had an insight while walking, because I realized I could inject JavaScript using the Emscripten API. Since the game assets are stored in a compressed file, PhysicsFS provides an API to handle them transparently. It’s great for distributing the game — you only need the cartridge.zip and the executable — and it works even better on the web. The engine must provide a searcher so that Lua can find the game’s other Lua scripts. For this, I use a custom searcher: it first looks for the scripts inside the game package, and if they’re not found, it falls back to the interpreter’s default search to load them from the standard library. To improve stack traces, the secret lies in the second parameter of lua.load. You can pass a string starting with followed by the file name. This alone gives you a much richer stack trace. In Carimbo, I have a terminate hook that catches any exception and atexit hooks to always handle cleanup. This way, I can provide Sentry support in a practically universal and abstract manner for the engine’s user. You can find more details about the engine and its implementation in the official repository: github.com/willtobyte/carimbo .

0 views
NULL on error 4 months ago

Replacing Lua’s math.random module with the Xorshift algorithm

I recently discovered that V8 , the engine behind Node.js and Chrome , has been using since 2014 . Out of curiosity, I checked what the Lua VM uses, and to my surprise, it relies on the standard C library, which is extremely slow. You can find more details here: v8/src/numbers/math-random.cc at main · v8/v8 I’m currently working on a game that uses random in the main loop, which is quite slow. So to work around that, I implemented a pseudo-random function. This is a Linear Congruential Generator (LCG) — one of the oldest and simplest methods for generating pseudorandom numbers. For the noise effect, I end up calling random up to 6 times per loop, which is extremely costly, and not even the C++ implementation of below could save me. Anyway, I ended up replacing Lua’s implementation with the one below, because optimizations are always welcome — especially when the gain in randomness is significantly higher.

0 views
NULL on error 4 months ago

Poor’s Man Shaders

Spoiler: it’s not shaders I’m waiting for a universal solution that the SDL developers are working on — cross-platform, multi-API shaders, the SDL_shadercross . The idea is that you write shaders in a single language, and at runtime, they get compiled for the target GPU. Unfortunately, it’s a large and complex project, and it will take time before it becomes stable. In the meantime, in my Carimbo engine, I was wondering if I could implement something similar to shaders — something that would allow Lua code to write arbitrary pixels into a buffer and stream that buffer into a texture. So I created what I call a canvas, which is basically a texture the same size as the screen, rendered after certain elements. The set_pixel function receives a pointer to a uint32_t buffer that exactly matches the texture size. This pointer is actually a Lua string, which I found to be the most performant way to transfer data between Lua and C++ without relying on preallocated buffers. On Lua side: Some effects I’ve created so far: https://youtu.be/GUWTWRQuzxw https://youtu.be/usJ9QM7V8BI https://youtu.be/DUhQmL91cNA

0 views
NULL on error 4 months ago

AI will replace programmers—just not yet, because it still generates very extremely inefficient code.

I was working on my engine, which includes a sort of canvas where Lua code can generate chunks of pixels and send them in batches for the C++ engine to render. This worked very well and smoothly at 60 frames per second with no frame drops at low resolutions (240p, which is the screen size of my games). However, when I happened to try 1080p, the frame rate dropped. Since I was in a rush and a bit lazy—because I can’t afford to spend too much time on personal projects—I decided to use AI to optimize it, and this was the best solution I could squeeze out. It went from 40 FPS down to 17, much worse than the initial implementation! Naturally, the code was not just complex, but also way slower. That’s when I decided to take my brain off the shelf and came up with this solution: Kabum! Smooth 60 frames per second, even at 8K resolution or higher.

0 views
NULL on error 6 months ago

How to avoid dynamic linking of Steam’s client library using a very old trick

As you know, this blog is more focused on sharing code snippets than on teaching, so today I’m going to show you something I recently discovered. If you’ve been following me, you know I’ve been working in my free time on a 2D game engine where creators can build games using only Lua — and I’d say, even fairly complex ones. Right now, I’m working on a point-and-click game that you can play here: https://bereprobate.com/. It’s built using this same engine, and I’m publishing builds in parallel to Steam and the Web using GitHub Actions. The thing is, Steam — which is the main target platform for this game — supports achievements, and I want to include them. But to use achievements, you have to link the Steam library to your engine. The problem is, doing that creates a dependency on that library in the binaries, which I don’t want. I also don’t want to maintain a separate build just for that. Then I thought: “Why not load the Steam library dynamically? Use LoadLibraryA on Windows and dlopen on macOS. (Sorry Linux — it’s Proton-only for now.)” I tried the experiment below, and it worked. If the DLL/dylib is present, the Steam features work just fine. If not, everything runs normally. Achivement class

0 views
NULL on error 6 months ago

I’ve built an IoT device to let my family know when I’m in a meeting

Do you work from home, and do people in your household always show up at the worst possible moments? Let me introduce the “I’m in Meeting” IoT device: it lights up at your office door whenever you turn on your webcam. It consists of an ESP32 with connected to Wi-Fi, using the Arduino framework for simplicity. The ESP32 exposes an HTTP server that handles a PATCH request on the /camera endpoint. This endpoint receives a JSON payload with a status of “on” or “off”, and turns the LED panel red or blue accordingly. For those who don’t know, mDNS (or Bonjour on Apple platforms) is a way to assign an IP address to a .local hostname for the device, so I don’t need to figure out its IP manually—just use the local domain. Super convenient, right? On the other side, I have a Python daemon that periodically queries Apple’s API to check if any cameras are in use, and then sends a PATCH request with “on” or “off” to http://esp32.local/camera. Very simple, but quite useful. See in action here https://youtu.be/c-cD_JLuCuQ Source code https://github.com/skhaz/onair

0 views
NULL on error 8 months ago

Building and Publishing Games to Steam Directly from GitHub Actions

I have been using GitHub Actions extensively both at work and in personal projects, as shown in this post What I’ve been automating with GitHub Actions, an automated life . In my free time, I’m working on a 2D hide-and-seek game, and as you might expect, I’ve automated the entire release pipeline for publishing on Steam. After a few attempts, when it finally worked, it felt like magic: all I had to do was create a new tag, and within minutes, the Steam client was downloading the update. As I mentioned earlier, I have a 2D engine that, while simple, is quite comprehensive. With each new tag, I compile it in parallel for Windows, macOS, Linux, and WebAssembly. Once compilation is complete, I create a release and publish it on GitHub. Releases · willtobyte/carimbo Publishing on Steam is quite simple. First, you need a developer account with the correct documentation and fees paid. After that, you’ll need to generate some secret keys as follows: If you don’t have the steamcmd application installed, you’ll need to install it using: Copy the contents of the authentication file: Note: You must have MFA enabled. After logging in, run the command below and copy the output into a GitHub Action variable named . Also, create the variables with your username and with your game’s ID. Additionally, the Action downloads the latest Carimbo release for Windows only (sorry Linux and macOS users, my time is limited). Ideally, I should pin the runtime version (the Carimbo version) using something like a runtime.txt file. Maybe I’ll implement this in the future, but for now, everything runs on the bleeding edge. :-) Boom! If everything is correct, your game should appear in your Steam client under the list of owned games.

0 views
NULL on error 1 years ago

My First Game with Carimbo, My Homemade Engine, For my Son

https://youtu.be/nVRzCstyspQ After a while, I decided to resume work on my game engine . I made a game for my son. I could have used an existing engine, but I chose to write everything from scratch because code is like pasta—it’s much better and more enjoyable when homemade. This actually reminds me of when my father used to build my toys, from kites to wooden slides. Good memories. I have decided to do the same using what I know: programming. You can watch it here or play it here , (runs in the browser thanks to WebAssembly), use and for moving around and to shoot. The engine was written in C++17, and the games are in Lua. The engine exposes some primitives to the Lua VM, which in turn coordinates the entire game. Game source code and engine source code . Artwork by Aline Cardoso @yuugenpixie . The entire game is scripted in Lua . First, we create the engine itself. Then we point to some resources for asset prefetching; they are loaded lazily to avoid impacting the game loop . We created the postal service, which is something I borrowed from languages like Erlang , where an entity can send messages to any other. As we’ll see below, the bullet sends a hit message when it collides with the octopus, and the octopus, upon receiving the hit, decrements its own health. We also obtain the SoundManager to play sounds and spawn the main entities. It’s not a triple-A title, but I’m very careful with resource management. A widely known technique is to create an object pool that you can reuse. In the code below, we limit it to a maximum of 3 bullets present on the screen. The method is a callback called each loop in the engine. In the case of the bullet, I check if it has approached the green octopus. If so, I send a message to it indicating that it received a hit. On the octopus’s side, when it receives a “hit” message, the entity triggers an explosion animation, switches to attack mode, and decreases its health by 1. If it reaches 0, it changes the animation to “dead”. And finally, the player’s , where I apply the velocity if any movement keys are pressed, or set the animation to idle if none are pressed. We also have the projectile firing, where the fire function is called, taking an instance of a bullet from the pool, placing it in a semi-random position, and applying velocity. In the end, he requested some minor tweaks, such as the projectile being the princess sprite, the target being the player, and the entity that shoots being the green octopus. 🤷‍♂️

0 views
NULL on error 1 years ago

How I saved a few dozen dollars by migrating my personal projects from the cloud to a Raspberry Pi

Since the first URL shorteners emerged, that’s always drawn me in for some reason, perhaps because I figured out on my own that they encoded the primary key in base36 (maybe). So around ~2010, I decided to make my own. It was called “encurta.ae” (make it short there in Portuguese), and it was based on AppEngine. Even back then, I was quite fond of serverless and such. It worked great locally, but when I deployed it, the datastore IDs were too large, causing the URLs to be too long. Fast-forward to nowadays, I’ve decided to bring this project to life again. This time with a twist: when shortening the URL, the shortener would take a screenshot of the website and embed Open Graph tags in the redirect URL. This way, when shared on a social network, the link would display a title, description, and thumbnail that accurately represent what the user is about to open. Typically, I use serverless for my personal projects because they scale to zero, thus eliminating costs when not in use. However, after working with serverless for many years, I’ve been wanting to experiment with a more grounded and down-to-earth approach to development and deployment. Deployment is done using Docker Compose, via SSH using the DOCKER_HOST environment variable pointing directly to a Raspberry Pi that I had bought and never used before. Now it saves me $5 per month, and I can keep a limited number of projects running on it. And then you might ask: How do you expose it to the internet? I use Cloudflare Tunnel ; the setup is simple and creates a direct connection between the Raspberry Pi and the nearest Point of Presence . This type of hosting is extremely advantageous because the server’s IP and/or ports are never revealed; it stays behind my firewall. Everything goes through Cloudflare. I have more than one Docker Compose file, and that’s what’s coolest. Locally, I run one, for deployment I instruct the Compose to read two others for logging and tunneling. Then for deploying Example of the “worker queue” It’s noticeable that it took a bit more effort than if I had used a task queue. However, it turned out to be quite robust and easy to debug, and for that reason alone, it was worth it. In sharing the shortened link ( https://takealook.pro/4MP ) for my company Ultratech Software on social networks, you can have a really nice preview, as seen below. Take A Look I opted to use Go , with several goroutines performing tasks in parallel, and a purely written work queue mechanism. Playwright & Chromium for automation and screenshot. SQLite for the database (it’s simple) Backblaze for storage BunnyCDN for cotent delivery Papertrail for logging

0 views
NULL on error 1 years ago

My 2024 Setup

As can be seen, I am using Kagi, which delivers excellent results without any garbage or ads, instead of Google. I also use email with my own domain through Apple’s iCloud email system, which allows for custom domains, as well as calendar and other features, all outside Google’s domain. Unfortunately, I have to maintain my Google account to use YouTube and occasionally for sites that do not allow creating accounts with a username and password, but only through Single Sign-On (SSO). brew as package manager asdf as language & tools management Zed as code editor Bear as notes keeping Firefox as browser Kagi as search engine ChatGPT as AI assistant Bruno as API client OrbStack as Docker desktop replacement, plus virtual machines Apple ecosystem for mail, calendar, reminders, music, messaging, and more.

0 views