I blog about anything I find interesting, and since I have a lot of varied interests, my blog entries are kind of all over the place. You can browse my tags to sort them by topic and see which ones I frequently write about, or the archive has a complete history of my posts, dating back to 2008!
Besides my blog, I have pages for my creative projects, which are linked to on the navigation bar.
I write a lot about Linux and Android, Minecraft, and I like to rant about stuff. Generally anything that makes me curious. Also check out my Bookmarks for all sorts of cool websites about various topics I'm interested in.
As I've been working on my videogame (codenamed Project: Doodle), I created a few Go libraries that I'm releasing as open source software that can be used to create other, unrelated applications (other games, other kinds of graphical programs, etc.)
These libraries are still in "early development" (meaning I may change their API around a bit as I refactor and add new features) but they are generally stable and I'm good about documenting changes in the code, if you wanna play around with these and aren't afraid of occasional breakages.
This is just a quick blog post letting people know about these libraries. I'll probably post again when these libraries reach a stable "1.0" state, where their API won't change and they'll have a degree of stability guaranteed to them.
I'm generally using GitHub as a mirror for these libraries and will accept issues and pull requests filed on GitHub (I wouldn't expect or want anybody to sign up an account on my local Gitea instance).
I decided early on for my game that I would be using libSDL for my game's graphics, audio, controller inputs and so on -- at least to start out with. I didn't want my game to rely on SDL though: I needed the flexibility to swap it out for OpenGL or Vulkan or Metal or any other back-end driver as needed to expand my game to future platforms.
So I created go/render as a "rendering engine library" for 2D graphics in Go. It presents an API interface for drawing pixels to the screen which can be implemented by various back-end "drivers" that do the real work.
Currently it supports SDL2 for desktop applications (Linux, macOS and Windows) as well as a WebAssembly driver that uses the HTML Canvas API. (I have a build of my game to WebAssembly, but WASM performance is not great yet.) Examples are included in the git repo for both desktop and WASM applications.
My game also required a UI toolkit for easily adding buttons, panels, windows and basic user interface controls to the game.
There were a handful of options I could've gone with: desktop UI toolkits like Gtk+ or Qt could've wrapped around my SDL surface and provided menu bars and button toolbars, but I wanted to minimize my inclusion of C or C++ libraries with my Go application. I was fortunate that go-sdl2 provided clear documentation how to cross-compile my program for Windows, and I didn't wanna push my luck bringing in yet more C libraries that might've made my game harder to ship. This also ruled out some potential SDL2-based C libraries for UI controls as well.
So I created my own UI toolkit in Go, and it uses my
go/render library as its
graphics back-end: meaning my UI toolkit can work for SDL2 desktop applications
and as WebAssembly applets.
It currently supports widgets such as Labels, Buttons, Checkboxes, Tooltips and (virtual) Windows (with title bars that can be dragged around and closed). The Frame widget allows easy arrangement of child widgets using Tk-style Pack and Place controls.
Future planned widgets include: menus and menu bars, tabbed frames, text input boxes, scrollbars and sliders (in roughly that order).
The newest library implements a simple audio engine for playing music and sound effects. My game needed these, and doesn't have any fancy requirements yet, so this library provides the basics for loading music (.mp3 and .ogg) and sounds (.wav) and playing, pausing and stopping them.
Currently it only supports the SDL2 (Mixer) driver. This module is independent
go/render and you can mix and match (or not) that library.
Future planned features include: adding WebAssembly support (Web Audio API), maybe branch out to other back-end drivers as needed.
Here is another alpha release of the game I've been working on, codenamed Project: Doodle.
Doodle is a "drawing-based maze game" where you can draw your own levels freehand and then play them as a 2D platformer game. You can drag premade "doodads" such as buttons, doors and keys into your level to add some interaction to it.
The game comes with the "doodad.exe" command-line program which helps in creating custom doodads; it's the tool I used to create the default ones that come with the game.
The game is free to download in its alpha versioned form.
Note: the program isn't signed yet for Windows and Mac so you may need to click through some warning dialogs. This is an early alpha release and I'll get the signatures sorted out eventually in future releases.
Mac users: let me know if the performance is okay. I only tested running it in the QEMU virtual machine I built it in, and it got < 30 frames per second there (hit F3 key in-game to see the FPS). Linux binaries and Windows (in Wine) ran at full 60 FPS for me.
In case you happen to clip out of bounds in the game and fall to the bottom of the map, press the Enter key to open the in-game developer console and type in cheats like these:
import antigravityturns off gravity for the player character; arrow keys freely move you in any direction.
ghost modeturns off collision detection for the player, allowing you to pass through walls, floors and solid doodads.
The README.md contains more.
Note that this primarily focused on the back-end side of things, and won't cover all the craziness that has evolved in the front-end space (leading up to React.js, Vue, Webpack, and so on). Plenty has been said elsewhere on the Internet about the evolution of front-end development.
I first started writing websites when I was twelve years old back around the year 1999. HTML 4.0 was a brand new specification and the common back-end languages at the time were Perl, PHP, Coldfusion and Apache Server Side Includes.
A couple of years ago I started the progress of slowly de-googling my life: lessening my reliance on Google services, moving my data to my own servers and limiting what data Google can collect about me going forward as well as deleting the data they already have.
In this blog post I'll talk about the Google services I used to use and the solutions I found for replacing them. The full list of Google services I used to use and have found alternatives for include:
Also check out some of my personal notes I've been taking as I went:
I've been working on a videogame the past couple of years, off and on. It's called...
...for now. I have a better name picked out for it, but I'm going to be callling it Project: Doodle (while it's in alpha) so that the finished version will be distinct from the alpha versions, of which it may end up looking nothing like!
The theme of Doodle is centered around hand-drawn, side-scrolling platformer type mazes. You can draw your own levels using freehand and basic drawing tools, color in some fire or water, and drag in pre-made "Doodads" like buttons, keys and doors to add some interaction to your level.
Read more for a screenshot, more information and alpha version download links (Linux, Windows and Mac OS).
I added a new feature to my Go blog app that sort of automates a Tumblr-style "Ask Me" feature, which I found useful for other blogs I run on this codebase.
So Kirsle.net has gained an ask me anything page. It's like a Contact Me form except your question will become a blog post with my answer attached and you might receive a notification e-mail if you want.
I was discussing passwords with someone recently and thought of a neat little hands-on exercise that shows not only how password hashing works, but shows you a real-world example of cracking a weakly hashed password just using Google.
The hands-on exercise should be easily approachable for beginners. I'll also go over a general history of passwords on the Internet -- I've been working as a web developer long enough to watch the whole transition from MD5 to bcrypt play out.
Any Unix-like environment with the
md5sum command. Most Linux distros have it
by default as part of the
coreutils package. The Windows Subsystem for Linux
Mac OS might have these built-in too. Not sure.
Probably one of the most frustrating things to deal with as a software developer is time. Specifically time zones and daylight savings time and all that nonsense. Tom Scott has a video about it but I have a recent story of my own.
This week at work, we lost about two days of effort trying to make our web application timezone-aware. Apparently, time zones are so ridiculously complicated, that it's basically impossible to store a time with an arbitrary time zone in your database while remembering what the time zone is.
Don't believe me?
I got this e-mail today about RiveScript and thought my response would be good for a general audience as well.
Hello Noah i want to know...
- What is Vanilla Rivescript?
- What can Vanilla Rivescript do?
- How can i install or use Vanilla Rivescript?
In the past, I had been tasked to update some Python web apps to have them send e-mails out whenever they run into an uncaught Exception in one of our endpoints. This way we could identify any runtime errors in production and fix them.
In Python it was pretty easy: our web framework, Flask, provides a way to catch
any error that happens in any of your HTTP routes. Even if you didn't use Flask,
you can set
to a function and catch exceptions globally whenever other code failed to.
But then we had an app written in Go and it needed to have this feature, too. If it were simply a web service, this wouldn't have been bad, but this particular service listened on both an HTTP port and a separate TCP port in another goroutine.
Catching HTTP panics in middleware (or the standard
net/http library, which
catches panics itself) doesn't do anything to help catch the panics thrown by
the TCP server. So, like
sys.excepthook, I needed to find a way to globally
catch panics in my app.
This was surprisingly very hard to do.