Porting SpaceShooter to Godot

2024-03-20 00:00:00 +0000

A while back I decided to try out the Godot game engine. It’s free and open source, and you know I love FOSS! You can read about Godot here by the way. Super cool project that I intend to do more wtih in the future.

Anyway, on my Java Games page there is mention of a game I simply called ‘Space Shooter’. Think Galaga but with resource management. It’s a neat project, except that you need Java installed to play it, but Godot can fix that! I re-made the game in Godot in some downtime between work and school, click here to download the game!

This isn’t a fully polished project that I’d release on Steam, so you won’t find instructions on how to play it. I’m sure you can figure it out.

Collect Call mapping software

2024-02-13 00:00:00 +0000

While I was creating Collect Call, I ended up writing some code to interpret Tiled levels to be playable in my game. Though the format needs to be very similar to my own levels, it is possible to load custom levels into the game.

You can download a kit full of mapping assets here, or go to the GitHub repository.

If you’re interested, here’s all the details for making custom levels.

Currently, Collect Call isn’t available to the public, but it should be on Steam in May! If you’d like early access, message me on Discord or by email. For now, here’s the Steam store page. The below is copied from the ReadMe for the mapping kit.

Collect Call Mapmaking Kit

This repository contains all the assets used to create levels for Collect Call. Before you start creating your own maps, it’s recommended to explore some existing ones to understand the process.

You can download Tiled from https://mapeditor.org

Opening Existing Maps

In the maps folder, you’ll find 15 maps created for Collect Call. You can open these maps using Tiled. If you encounter red Xs, don’t worry; that just means Tiled couldn’t automatically find the Tilesets. All Tilesets for these maps are in the tileset folder. Locate the missing files by following the prompts in Tiled.

Making Your Own Maps

When you distribute your map, you will need to include the map’s .tmx file along with any other assets needed to run it. That includes any custom textures, dialogue files, etc. These should all be in one folder together. Collect Call scans two places for map folders. The first is the Custom folder located in the same directory as the game’s .jar file, and second is the content you’ve downloaded from Steam Workshop. Collect Call scans for .tmx files with names starting with “cc_”. The maps that are found are displayed in the game select screen by their file names with the “cc_” and “.tmx” removed and any underscores replaced with spaces. A map named “cc_Collect_Call.tmx” would be displayed as “Collect Call”, so use this to set your mod’s name! If your mod contains multiple maps, the later maps do not need to follow any specific naming convention. Maps are loaded when the game is prompted to open a map file by a LevelSwitch object.

Map Properties

Each map has properties that control how the game interprets it. Important parameters include:

  • defaultZoom: Controls the default camera zoom (usually a decimal between 0.1 and 0.3).
  • weatherParticleTextures: Path to weather particle textures (e.g., “textures/raindrop.png”).
  • weatherParticlesSpawnAngle: Angle for particle spawn relative to the player.
  • weatherParticlesSpeed: Speed of particle movement.
  • weatherParticlesSpread: Spread of particles when spawned.

Layers in Tiled

Tiled organizes maps into layers. Tile layers contain textures, and object layers store data about map locations.

Tile Layers

Your maps can have multiple tile layers for a parallax effect. Tile layers don’t require special properties.

Object Layers

Object layers store data about map locations, including required and optional layers:

Required Object Layers:

  • EntitySpawner: Controls entity spawn points.
  • LevelCollision: Defines the world’s collision.
  • LevelSwitch: Manages level switching, including game-ending transitions.

Optional Layers:

  • Hints: Provides button prompts.
  • CameraModes: Overrides default camera behavior.
  • PuzzleObjects: Places puzzles in the level.
  • Ladders: Controls player ladder interactions.

For detailed information on each layer and its properties, see the sections below.


Objects here control the placement and hitboxes of entities:

  • speed: Speed of the entity.
  • textureHeight: Height of the entity’s texture.
  • texturePath: Path to the entity’s texture/animation.
  • textureWidth: Width of the entity’s texture.
  • type: Sets entity class (Player, Follower, or Prop).


Objects represent the world’s collision. No extra properties necessary.


Controls switching to other levels, including game-ending transitions:

  • destinationMapFilePath: Path to the next level. Enter “modpath/” for the folder your custom map is in. Example: “modpath/dialogues/example.json”.
  • destinationX: Player’s x-axis upon switching.
  • destinationY: Player’s y-axis upon switching.


Provides button prompts:

  • button: Button prompt (A, B, X, Y, Left, Right, Up, Down, StickUp, Start).
  • showDist: Distance for button prompt visibility.


Overrides default camera behavior:

  • cameramode: “center” or “follow” for camera behavior.
  • targetzoom: Camera zoom distance.


Place interactable dialogues in the world. Dialogues are written as .json files. This kit contains an example one.

  • rootFilePath: Path to the .json file containing this dialogue. Enter “modpath/” for the folder your custom map is in. Example: “modpath/dialogues/example.json”.
  • textureFilePath: Path to the texture for this object. Set it to an empty string to make it invisible.


PuzzleObjects are used to place puzzles within the level. They include required and optional properties.

Required Properties:

  • puzzlePieceID (INT): Unique identifier for a puzzle piece, starting from 0. Do not skip IDs to avoid game crashes.
  • textureFilePath (STRING): Path to the texture file. Must be present; set as an empty string for an invisible object.
  • type (STRING): Controls the type of puzzle object loaded.
  • deactivateAfterSeconds (FLOAT): Object remains active for this duration; not used by all puzzle types.

Optional Properties:

  • animateOnInternalActivation (BOOLEAN): Animation unaffected by the defaultActivated property.
  • defaultActivated (BOOLEAN): Enables the object when it would be inactive and vice versa.
  • flipped (BOOLEAN): Flips the object’s texture.
  • or (BOOLEAN): If enabled, only 1 item in the activators list is needed to activate this object, rather than all of them.
  • passiveAnimationFilePath (STRING): Path to an animation the object should play when inactive.
  • permanentlyActivated (BOOLEAN): If enabled, the object stays active forever.
  • loopAnimation (BOOLEAN): If enabled, the object plays its animation as long as it is activated.

PuzzleObject Types:


Generic puzzle object activated by other puzzle objects.

  • activators (STRING): Comma-separated list of puzzle object IDs that this object should listen to.


    • Clock:
      • onTime (FLOAT): Length of time, in milliseconds, that it should be on.
      • offTime (FLOAT): Length of time, in milliseconds, that it should be off.
    • FlagSetter:
      • flags (STRING): Comma-separated list of flags this object should set.
    • PuzzleCollision:
      • Subtypes:

        • MovingPlatform:
          • absoluteActivatedPos (BOOLEAN - optional): Activated position relative to the map rather than the object’s default position.
          • activatedX (FLOAT): Sets where the object will move on the X-axis when activated.
          • activatedY (FLOAT): Sets where the object will move on the Y-axis when activated.
          • time (FLOAT): Time, in seconds, for the object to move between positions.
        • ToggleCollision:
          • No special properties.


Generic puzzle object activated by entities.

  • activators (STRING): Comma-separated list of entity types that this object should listen for.
  • gravity (FLOAT): Strength that this object will pull activators towards it. Use a negative number to repel activators.


    • FlagListener:
      • activators (STRING): Comma-separated list of flag strings the object should listen for.
    • UseListener:
      • highlightAnimation (STRING): Path to an alternate texture/animation that should show when the player gets close.


Set similar to LevelCollision; player gets ladder controls when overlapping a rectangle object in the Ladders layer.

Empires is now online!

2023-06-21 00:00:00 +0000

The Empires simulation I posted about a while back is now online so you can run it in a web browser. Try it HERE! If you’re curious about it, press F12 to view the source code. If you have suggestions, you post them as Issues to the GitHub repository or on my Discord server.


2023-06-21 00:00:00 +0000

A while back I found a fun website that could simulate wars between empires on a world map. You could watch them grow and decline, form alliances, explore territory. But a few things I wanted to change.

The first thing that bothered me was that the empires, or ‘colonies’ as the site called them, would often not base their conflicts or alliances on mutually shared values. They seemed mostly random. The second issue was performance. The website slowed to a crawl if you had it simulate a very detailed world, sometimes you could measure it in seconds per frame rather than frames per second! The third thing was that the site didn’t give you a great visualization of what the colonies were thinking, how they were planning their next move.

So, over the last weekend, I decided to make my own version. It’s super rough for the moment, but it is a thing!

Quick rundown of the view modes. You press the corresponding number key to switch mode.

1: Empire colors 2: Strength of each pixel 3: Empire ideology 4: Resource management 5: Time since last capture 6: Border friction

If you’re interested in trying it out, I’ve got a download on GitHub. It’s written in Java, so you’ll need to have the JDK or JRE installed. Leave requests on the repo if you like, maybe I’ll expand this thing.

Advancement Command has dropped.

2023-05-09 00:00:00 +0000

New Minecraft plugin! This plugin allows you to run console commands when a group of advancements are made.

Advancements can be grouped into ‘sets’, which are defined using the config.yml file.

When all the advancements in a set are made, the commands for that set will run.

The PlaceholderAPI plugin, found here, is required since many commands will require a player’s name or some other contextual information.

An example config is below, and this is generated automatically if the plugin runs without any config. Note that advancements should include the namespace.

# Configuration file for AdvancementCommand plugin

#setting to true will cause the plugin to print extra information which may be useful for debugging.
#debug mode will spam your console! Turn it off when you're done.
debug: false

# Define sets of advancements and commands
  #set names can be anything! They will be printed to console in debug mode!
    #namespaced paths for every advancement needed for this set
    #other namespaces are possible if you have them
      - "minecraft:story/craft_planks"
      - "minecraft:story/upgrade_tools"
    #commands that will be run if the set is met.
    #commands should not include the beginning /
    #be sure to install any PlaceholderAPI expansions that are required.
    #in debug mode, warnings will be displayed about possibly missing expansions.
      - "give %player_name% minecraft:diamond_pickaxe"
      - "tellraw %player_name% {\"text\":\"Congratulations on completing the set!\"}"
      - "minecraft:story/smelt_iron"
      - "minecraft:story/enter_the_nether"
      - "give %player_name% minecraft:diamond_sword"
      - "tellraw %player_name% {\"text\":\"You have completed the second set!\"}"

You can download the plugin here.

Ledges plugin has launched!

2022-01-30 00:00:00 +0000

I polished the Ledges plugin today, and I’m now confident that its ready for release. I finished adding Leaderboards, accessible with /showleaderboard, and I added a config.yml so that it can be customized. I made a video explaining how to set up the plugin, you can find that here:

You can download the plugin here.

ElytraDogfights gets new documentation!

2022-01-18 00:00:00 +0000

Today I updated the download page for ElytraDogfights, with a full explaination of the config.yml and a video explaining the installation process. At the same time, I also was learning the Olive video editor. I’ll embed that video here, leave a comment to tell me how I did.

You can check out the updated SpigotMC.org page here.

ElytraDogfights 1.5.3 is out!

2022-01-18 00:00:00 +0000

Hello! It has been a LONG time since I last worked on this plugin, but I intend to return to Minecraft plugin development.
That starts with ElytraDogfights 1.5.3, which ensures compatibility with Minecraft 1.18. I’ll be making a video documenting the plugin in full sometime soon, along with a post on this site explaining installation and customization.
You can download the new ElytraDogfights release here!

First post!

2022-01-17 00:00:00 +0000

Finally decided to nuke the old version of this website and build a new one. Using the Forty theme by HTML5 UP and Andrew Banchich, liking it so far!