The site uses cookies that you may not want. Continued use means acceptance. For more information see our privacy policy.

Working on a Local Single Page Application.

If only my editor’s highlighter supported template literals.

I’ll surely post about it more detail as I get it fully built, but I thought I’d write about it as I’ve been working on it.

As I’ve written before ( 19 September 2020: “How I Track Games to Buy”) about how I track games to buy, using bookmarks, it occurred to me that I’d like something a little more defined than using bookmark titles to store data. And when I say a little, I mean that. I don’t want a relational database (though there is one built in the browser, if I want to use it). I don’t want a server to configure.

I do want a simple web application, often called a SPASingle-Page Application (Wikipedia: “Single-page application”). But as I said, no server. That makes it an LSPA, or Local Single-Page Application. And single-page really means single file, as in one HTML document that contains all the markup, all the code, and all the styles in one package.

The secret of the modern browser is that it has a ton of functionality that it doesn’t get credit for. While (unfortunately) the behavior of localStorage in the file: schema is undefined, at present Firefox makes it a per-file access, so as long as you persist the filename and path, you get the storage back. To be a little more sure of things, you can export the JSON data as a file, and import it from a file.

I’ve used one-off HTML files for other projects before, including years and years ago for some of my Computer Science classes where choice-of-language was wide-open, but it’s been awhile. In general, the browser is a nice platform to write for, but it’s underdeveloped in terms of making these kind of one-file applications widespread. To be fair, there are concerns about users downloading random HTML files and opening up vulnerabilities, but the general shape of browser security seems to guard decently against it such that enabling more local, serverless, in-browser applications would be useful.

People use spreadsheets for all sorts of data storage and simple applications because it’s got all those tools. They could be doing basically the same thing with a browser. (That’s in fact what I am doing with a browser.) In some cases, the numerical prowess of a spreadsheet will make their task easier. In other cases, the web-awareness of the browser makes my task a lot easier.

One place where a spreadsheets take the one-file ideal slightly further: they store the data in the application. Fair enough.

I looked at various libraries to bootstrap building the editing side of things from a JSON schema. There are a bunch of them, but none seemed very easy to integrate or to do what I wanted with it. It took me less time to build the equivalent for my own purposes than I spent looking at and trying to understand the umpteen JSON-to-forms Javascript libraries. And for mine I don’t add dependencies like underscore.js or jQuery.

On the other hand, I’ve spent a bit of my times dusting my ability to write Javascript, wondering what’s canonical these days. There are proper classes with constructors now (but you don’t have to use them). There are things like Map()s that are better than plain objects in some ways, but aren’t as nice to use in other ways.

To save a file, you have to:

  1. Create an anchor (A).
  2. Create a Blob.
  3. Create an object URL for the Blob.
  4. Add the URL as the anchor’s href attribute.
  5. Add the desired filename as the anchor’s download attribute.
  6. Add the anchor to the document.
  7. Call click() on the anchor (the actual download occurs).
  8. Clean up.

Seems like a lot of extra work for a very usual thing. (A roughly similar process to load from a file, except using an input with type of "file" and some other specifics.)

Anyhow, the one feature I’m relying on an extension for that Bookmarks have out of the box is the ability to get the title and URL in a single action. Mozilla Addons: Hiroaki Nakamura: “Format Link” is an add-on I already use to do that for other cases. But it seems like it’s something browsers should support, given how much we all use the web. We still need computers that understand our most-used forms of data as logical objects, but until then there’s nice extensions to help us.

With that ability, the main pieces of data for tracking a game are available with a paste, which isn’t too much more than simply adding a bookmark. The rest of the data was already stuff I was filling in by hand, but it will soon be into my application rather than cramming it all in the bookmark’s title.

Anything else you’d want from a server-provided service can be built locally and only using Javascript. Given I don’t expect to have hundreds of thousands of games to track, I don’t even need to use a relational database. The browser can handle filtering, sorting, search.

For heavier uses, like media databases, solely relying on a LSPA might not be enough power or might not be able to handle some things like creating thumbnails, but for many other uses, it’s a powerful model that I’d like to see more support and frameworks for people to make use of, especially non-programmers or people with only a little knowledge.

Fun with Context Free

Math is a tool that creates order and chaos in equal (or was it inequal?) measure.

Context Free Art is a simple art-generation context-free language that uses recursion (among other things) to generate images (and videos). I recently saw a post about it, and I decided to try it out. Then I found a folder in my files from 2013 where I had previously come across it and forgotten all about it.

While more suited to the abstract, it’s possible to create more traditional art with it, as seen in two of the four examples at the bottom.

Here is a sample input to the program:

// Sample input
// two slashes make a comment

// command to build:
// cfdg -s 1920x1080 -m 1000000 sample.cfdg sample.png

// cfdg the command
// -s set size to 1080p
// -m set the maximum number of shapes; helps in case of too much recursion
// [file].cfdg the input file
// [file].png the output image

// Required to kick things off.
startshape Sample

// Make a default background color (random)
CF::Background = [b rand(-0.5,-0.25) sat rand(0.25,0.75) h randint(360)]
// b is brightness; sat is saturation; h is hue

shape Sample {
    SQUARE [s 100 x -200]
    CIRCLE [s 100]
    TRIANGLE [s 100 x 200]

// s is size; x is horizontal position

There are three basic shapes available. Can you guess what they are?

From left, on a pink background: a black square, a black circle, and a black triangle.

And you can make your own shapes, using path declarations:

path ZA {
    MOVETO(-0.5, 0)
    LINETO(0, 1)
    LINETO(0.5, 0)
    ARCTO(-0.5, 0, -1)
    // STROKE()[]
    FILL() []

This example path creates a piece of pizza! Notice it has STROKE commented out. If you want, you can make outlined shapes using that.

From left, on a brown background: a white pizza slice shape, a black pizza slice outline, and a white pizza slice shape with a black outline.

Github: MtnViewJohn: context-free: Wiki has most of the details on how to use the tool, though you can also look at the gallery of the official website (linked above), where users have provided samples that include their source code.

Anyway, just a short writeup. Here’s some pictures I made with it:

On a green background, a cone-looking tornado kind of thing with colors shifting from green to yellow to pink to purple.
A misshapen earth-like figure with water, land, and clouds, seen on a space-like background.
A sky with clouds and sun above dirt filled with plants and a few trees.
A psychedelic swirl of green, yellow, orange, red, pink, purple, and blue.

Messing with Godot

My early experience in working on a toy platformer game.

I recently downloaded Godot, a game engine and game development environment. I never did much with games, so I figured I might mess about. So far I’ve been playing around with the 2D stuff, something that could be a platformer-style game.

Godot does a decent job of making concepts clear, though as with any new effort, searching is your friend. Most hurdles have been in figuring out the math to use for custom physics, and even there the engine provides a lot of the basics.

One of the hardest challenges in any program is keeping organized and picking up the right way to implement things. There are places I know I should use custom signals, but I don’t quite understand exactly how to wire them up the right way, so I’m relying on direct calls. My tile map places overlapping tiles. Or places where I know I should be processing velocity changes in the frame process function, but I’m modifying the velocity directly, which means I have to make sure it doesn’t get eaten by a collision.

Eaten by a collision? If you run into a wall, that wall eats your velocity in the direction it opposes. Godot provides collision checking which you can use in custom physics, but it’s up to you to decide how to handle collisions because you might want to bounce, or some collisions might break blocks or teleport you or whatever you want them to do. In my case, the collisions should eat the velocity:

func collide_normal(vel, nnorm):
    var out_vel = Vector2(vel.x, vel.y)
    var dot_product = vel.x * nnorm.x + vel.y * nnorm.y
    if sign(vel.x) != sign(nnorm.x):
        out_vel.x -= dot_product * nnorm.x
    if sign(vel.y) != sign(nnorm.y):
        out_vel.y -= dot_product * nnorm.y

    return out_vel

This function takes a velocity (with an X component and a Y component for how much the object moves frame-to-frame, which together also tells you what direction, like the slope of a line) and a normal vector. A normal vector also has an X and a Y, but if you remember the unit circle from trigonometry, it’s normalized so that it has a length of one, and it points away from the face of an object.

Given those two components, the function negates the velocity that is pointed against the given normal vector. In my case it also has two conditional checks that are used in case either of the components happen to agree in sign (same as direction). Without those, the function would just as happily negate the part of a velocity that points the same way as the normal vector.

But that’s the kind of thing you have to do if you’re poking around and not taking time to do it properly inside the frame process function. Otherwise the bouncy spring you added will sometimes behave like a wall, if the signal of your collision with it happens to come right before the frame process checks if you collided with anything and decides to cancel the bounce.

One of the other things I’m considering is experimenting with a “ghost” player. Godot has its own built-in physics, which is usually applied to inanimate objects, but not to controlled objects and, depending, on animate enemies. But it looks like there are times that it might be handy to ride on the built-in physics, so I believe I can create an invisible player surrogate that will respond to the built-in physics, and for limited uses that might save some code and allow for cool things with limited effort.

I haven’t tried to do any fancy graphics yet (e.g., animations and particles), nor tried anything in 3D, but it’s still fun to mess around with my bouncy springs and gravity fields.