Wish TLDraw offered a cylinder shape. I know my needs are quite niche, but I really like using this app for back-of-the-napkin architecture diagrams of software systems, and having a cylinder shape to represent a database or queue would really come in handy.

Playing around with Vintage Logo this morning. HT to @odd and @mandaris for posting a link to this iOS app. They’ve got some very nice logo templates here, including this art deco one featuring a bird in flight.

Used it to make this logo, which I call: lodgings for the evening.

An art deco inspired logo featuring a line drawing of a bird in flight in blue, and the name β€˜the cockatiel cafe’ written along in cursive writing in red

I can’t for the life of me remember how to create a child page in Notion’s mobile app. Why do they hide that option with the bullets and headings? Couldn’t the New Page button be context specific, instead of creating a new top-level page wherever you press it?

Reliving my European trip through my posts here. They’ve started to appear on my On This Day page.

I sometimes wonder if I should’ve posted more at the time. I deliberately kept to my usual pace of one or two posts a day, mainly because others suggest that it’s usually not a great idea posting loads of photos of your trip on social media, lest you make people jealous about what you’re currently doing. Although, when they say “social media” they mean Instagram or TikTok and not Micro.blog, although one could make the case that’s still kinda, sorta, if-you-squint-and-tilt-your-head social media, maybe?

Ah well, doesn’t matter. I think I made to right call: living the moment instead of spending all my time working out whether something was post worthy. Plus, I’ve still got loads of photo and journal entries that I could turn into blog posts. Maybe one day I will.

Adjusting my SQL code formatting preferences at the moment, and it just feel so… byzantine. There’s probably close to 200 different settings here (I stopped counting after 100) and hunting through them trying to find the one that controls whether parenthesis should appear on the same line as the CREATE statement is so time-consuming.

It would be nice for editors to provide a way to “learn” a code formatting style. They can present you with some sample code and say to you, “format this the way you’d like to see it and we’ll learn from that.” There can be several of these samples, presented to you one at a time, each one intended to answer a particular question about how the style should be. For example: one might have a dramatically narrow page width, forcing the user to break long lines.

From that, they can build a profile that will be used to configure the formatter. The configuration will essentially be the same as what’s used by formatters today β€” and can be transferred or checked into source control like a regular config file. It’ll just come from this learning routine, rather than the user poking through piles of checkboxes and pickers spread across 8 different tabs (I counted those as well).

Could this be something an onboard LLMs can actually do? Not sure. But if code editors are looking for “AI” features to add to their product, this might be one worth considering.

Side Scroller 95

I haven’t been doing much work on new projects recently. Mainly, I’ve been perusing my archives looking for interesting things to play around with. Some of them needed some light work to get working again but really I just wanted to experience them.

I did come across one old projects which I’ll talk about here: a game I called Side Scroller 95.Β  And yes, the “95” refers to Windows 95.

This was a remake of Side Scroller, a QBasic game I made back in the day. Having played around with Delphi programming after a while, and finding a bunch of DirectX 7 components, I set about recreating this game.Β  I’m not sure why I decided to remake this game vs. making something new. Was it because it was simple enough to try, or I found the levels interesting? Maybe? I can’t really say.

SS95 showing level E2M2.

Anyway, there wasn’t much to this game from the beginning. All the movement was cell based, with the usual assortment of solid tiles, hazards, and keys and locks (no pickups though). I eventually added a simple enemy as well: a robot which just went from left to right.

Level set 2 has the more interesting levels. This is S2E7, showing the player loose breath while underwater.
Level S2E8, with a "gold" tile scheme and backdrop.
Level S2E10, with a rainbow scheme and lots of invisible laser emitters.
Level S2E11, with an "underwater" scheme, which is just blues and greens. Also note the only enemy of the game, which was a robot that moved from left to right.

This project really showcases my crappy art skills at the time (I wish I could say they improved, but that would be a lie). The tiles and sprites were creating using MSPaint. This was back in the day when MSPaint was actually quite usable for pixel art, where drawing a rectangle actually rendered a rectangle then and there, rather than product an object which could be moved around (it’s just not the same now). The backgrounds were made by making gradients in Microsoft Word, taking a screenshot, and cropping them. And the sound effects were taken from the PC version of Metal Gear Solid (the WAV files were just sitting there on the file system).

The level editor. Unfortunately, it doesn't render well in Crossover so here's how it looks in Delphi 7's form designer.
The "Level Properties" form in the level editor, showing how Sprites were configured. Adding sprites were an absolute nightmare.

The game itself is pretty unremarkable, although I would say that one attribute that I really enjoyed doing is adding level scripts. These were Pascel scripts β€” interpreted by a Delphi control I found β€” that intercepted events, such as triggers or timeouts, and modified the level in some way. This was done late in the project, so it wasn’t used much, but it did make for some unique level-specific elements in the later levels. An example of one of the level scripts is provided below. This added platforms which ascended one cell at a time when activated. I forget most of what the built-ins did but I believe the OnActivateX hooks fired when a switch was triggered and the OnTimedEventX fired when a timer elapsed.Β 

unit LevelScr;

uses SSUTIL;

const
  INT_STX  = 0;
  INT_STY  = 1;
  INT_EDX  = 2;
  INT_EDY  = 3;

  INT_CURX = 4;
  INT_CURY = 5;

procedure LevSetupMove(sx, sy, ex, ey: integer);
begin
  SetStackInteger(INT_STX, sx); 
  SetStackInteger(INT_STY, sy);
  SetStackInteger(INT_EDX, ex);
  SetStackInteger(INT_EDY, ey);

  SetStackInteger(INT_CURX, sx);
  SetStackInteger(INT_CURY, sy);
end;

procedure OnActivate1(tag: integer; ison: boolean);
begin
  case tag of
    1: LevSetupMove(6, 9, 6, 5);
    2: LevSetupMove(18, 9, 18, 4);
    3: begin
     LevSetupMove(20, 19, 20, 16);
     Level.SetTile(21, 18, 52);
       end;
    4: LevSetupMove(11, 23, 11, 19);
    5: LevSetupMove(10, 23, 10, 17);
    6: LevSetupMove(9, 17, 9, 15);
    7: LevSetupMove(9, 15, 9, 13);
    8: LevSetupMove(9, 13, 9, 11);
  end;
  SetupTimer(1, 2, 1, true); 
end;

procedure OnActivate2(tag: integer; ison: boolean);
begin
  case tag of
    1: LevSetupMove(20, 20, 20, 16);
  end;
  SetupTimer(2, 2, 1, true); 
end;

procedure OnTimedEvent1(event: integer);
var cx, cy: integer;
begin
    
  cx := StackInteger(INT_CURX);
  cy := StackInteger(INT_CURY);

  if ((cx = StackInteger(INT_EDX)) and
    (cy = StackInteger(INT_EDY))) then
  begin
    ResetTimer(1);
  end
  else
  begin
    Level.SetTile(cx, cy, 12);
    cy := cy - 1;
    Level.SetTile(cx, cy, 13);

    SetStackInteger(INT_CURX, cx);
    SetStackInteger(INT_CURY, cy);
    PlaySound(11, false);
  end;
end;

procedure OnTimedEvent2(event: integer);
var cx, cy: integer;
begin
    
  cx := StackInteger(INT_CURX);
  cy := StackInteger(INT_CURY);

  if ((cx = StackInteger(INT_EDX)) and
    (cy = StackInteger(INT_EDY))) then
  begin
    ResetTimer(2);
    Explode(cy, cx);
  end
  else
  begin
    cy := cy - 1;
    Level.SetTile(cx, cy, 0);

    SetStackInteger(INT_CURX, cx);
    SetStackInteger(INT_CURY, cy);
    PlaySound(11, false);
  end;
end;

end.

One other hallmark of this project was completely gutting all the hard-coded logic and moving it into a game definition file. I build a pretty simple “game designer” tool which managed all the artwork, tile and sprite definitions, and also had custom logic implemented using that same Pascal interpreter I was using for the level scripts. I never used it for anything than the “Side Scroller” game, apart from a recreation of the File Platform game I also built way back when.

The game definition editor, showing the image tab.
How tile logic was configured. This was modelled after the triggers used in Red Alert's map editor.
How sprite logic was configured.
Game logic scripts, which was used to extend the built-in actions.

Again, nothing about this was remarkable, and for a long time I had no way to get this working. But thanks to Whisky I managed to launch this for the first time in ages and have a play. I don’t know when I’ll be able to do so again, nor whether it’s a good use of my time to try, so I recorded some screencasts of the gameplay which you can see here:

The desire to move away from cell-based movement and physics continued my drive in making platform based games in Delphi. I eventually managed to build such a game, which I will talk about once I can get it working again.

Coding like it’s 2003.

Screenshot of Mac OS showing Delphi 7 running in Crossover

Poking around WinWorld this morning and found a working copy of Borland Delphi 7. Works perfectly in Crossover.

Bulk Image Selection

Some light housekeeping first: this is the 15th post on this blog so I thought it was time for a proper domain name. Not that buying a domain automatically means I’ll keep at it, but it does feel like I’ve got some momentum writing here now, so I’ll take the $24.00 USD risk. I’d also like to organise a proper site favicon too. I’ve got some ideas but I’ve yet to crack open Affinity Design just yet.

Anyway, I’ve been spending some time on Photo Bucket on and off this past week. I’ve fully implemented the new page model mentioned in the last post, and hooked it up to the switcher in the “Design” admin section. I’ve also built the public gallery and gallery item page.

Example of the landing page showing galleries (yes a lot of Jeff Wayne's War of the Worlds album covers in my test images.
Click one of the galleries to view the items within that gallery.

They’re a little on the simplistic side. That’s partly due to my minimalistic design sensibilities, but it’s also because I haven’t spent a lot of time on the public pages yet. I probably shouldn’t leave it too late, lest my impressions on how it looks drops to the point where I loose interest in working on this again. It’s a challenge, but I guess my counterΒ  is that I’ll probably be spending more time in the admin section, so as long as the experience is good enough there, I can probably go by with a very basic public site for now (but not for ever). Now that galleries can be shown on the landing page, I’d like to organise another deployment so that I can start showing images in galleries. But before I do, I’ll need an easy way to move all the existing images into a gallery. Clicking into 25 individual imagesΒ  just to select which gallery they should belong to doesn’t sound desirable to me. So I spent some time adding batch operations to the image admin page. The way it works is that by pressing Shift and clicking the images, you can now select them and perform batch operations, such as add them to a gallery (this is the only one I have now).

I do like how the selection indictor came out. It’s got some DaVinci Resolve vibes (I’ve been using DaVinci Resolve recently to edit some videos so I may have been inspired by their design language here) but I think I might need to use another highlight colour though: I think the black bleeds too easily into the images. Also, while I was recording the demo, I realise I broke the ability to rearrange gallery items. I may need to fix that before redeploying. Clicking “Gallery” brings up a model similar to the one used in the individual image page.Β  It work’s slightly differently though: instead of choosing whether the images appear in the gallery or not, this one is used to choose which galleries to add the selected images to.
I’m not sure that this is the best modal for this. It was quick to add, but I get the feeling that using the same model in slightly different ways could confuse people. So I might do something else here. An idea I have is a modal more like the following:

A better modal for managing galleries for multiple images.

The idea is that all the galleries will be listed like before, but will have a three-segmented button to the right. The centre button will be selected by default, and will show how many of the selected images are currently within that particular gallery. To the left will be the option to remove those images from the gallery, and to the right will be the option to add all the remaining selected images to the gallery. These are identified with the number of the selected images each gallery will have when the user clicks “Save”: 0 for none, and the number of selected images for all. For good measure is an option to add all the selected images into a brand new gallery. This will require some backend work so I haven’t started work on this yet. Not sure if this too will be a bit confusing: may need some additional text explaining how it all works. I’m hoping that users would recognise it as operating similar to the Gallery model for a single image.