I’ve decided to make a video game, with the collaboration and the encouragement of some close friends in a Discord channel.
We’ve been screwing around there, mostly making demos in Löve 2D and I think we’re ready to graduate from the experimentation phase to the hell-yeah-let’s-do-this phase.
So here I am to wear the already so well-worn ground of The Dev Log, and start to log our adventures.
I’ll be working on this game in intervals. Monday, Wednesday, and Friday for the 1-2 hours of free time I have.
I intend to make my first full fledged game a 2 dimensional one, hoping to keeping it simple. That whole extra dimension, I assume, adds exponential challenges.
In fact, if I could make a 1d game I would (table that idea for later).
I have four engines I’ve been considering, that specifically shine on the 2d front. I’ve used all of them to varying degrees to develop little demos and toys, some of which I’ll share in my next dev log.
My friend tests these engines in “Time To Walk,” how long it takes to get the engine to a 2d character to walk. I was thinking of something very similar earlier in the day “Time to Square” how long to get a 2d square I could move around via the arrow or WASD keys in two dimensions.
The following initial test demos all revolve around “Time To Square.”
Unity
Unity has become a de facto standard in game design for both 2d and 3d games, especially of the indie variety.
I wish I could say “it’s not hard to see why” but like Blender, or Fruity Loops, there seems to be a learning curve. But like those applications I’m sure learning it is very rewarding and comes with a lot of perks.
For instance Unity has a whole asset store built into the application, with many free assets available. In working with some of the other engines, it’s admittedly a pain to download or create assets and link them up in their appropriate directories, particularly in engines that are really more of code frameworks like Phaser and Löve 2D.
I don’t like that Unity requires a license and terms and a login just to use it. But it is part of the tradeoff for Unity being a tool that really helps centralize and guide you through much of the development process.
Time to square: 30 minutes.
Somewhat embarrassing. I created a player sprite and the code below to move the sprite in tandem with input (love the Input.GetAxisRaw() functions that map to the WASD and arrow keys automatically).
It all seemed as though it should have worked. That part was all done within about 5 minutes. I spent about 25 figuring out I didn’t have anything visual mapped to the sprite, so I couldn’t see it moving around the game window…good grief. Once I mapped a small round dot on there we were good to go.
The code is apparently written in C# which is a language I have some familiarity with having used it in a previous job and writing XNA game demos back in the day. It’s Microsoft’s (IMHO superior) answer to Java.
Code and results below:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayrMovement : MonoBehaviour
{
public float moveSpeed = 5f;
void Update()
{
float moveX = Input.GetAxisRaw("Horizontal");
float moveY = Input.GetAxisRaw("Vertical");
Vector2 movement = new Vector2(moveX, moveY).normalized;
transform.Translate(movement * moveSpeed * Time.deltaTime);
}
}

Godot
I dusted off Godot. I haven’t used it in a while, same with Unity. So I had to update these applications to use them. You might even say…I was waiting for Godot…to load.
Godot was a struggle, but not in the sense that Unity was. It was more like the interface was fighting me. I managed to lose my simple project a couple times completely accidentally starting over and losing the screen I was on. Something about the way the tabs are arranged and inspector menu area kept throwing me off.
But 30 minutes later I did have a working prototype.
The most odd thing though is that I had to use the GUI to map inputs to the inputs in the code

What the heck is this? Well…in a way it’s nice to know you have freedom to map as many or as few keys or button inputs to whatever you want. But this is in a weird menu: Project > Project Settings >Input Map, and I keep forgetting where to find it.
These types of applications can do so much so I understand that things have to be nearly hidden to give you all of the features of the software. But it was just annoying to set up all of these keys.
I did eventually get it. The code uses a proprietary Python style language called GD Script. As in GD…why isn’t my script working this time?
Code and results below
extends CharacterBody2D
@export var speed := 200.0
func _physics_process(delta):
var direction := Vector2.ZERO
if Input.is_action_pressed("ui_right") or Input.is_action_pressed("move_right"):
direction.x += 1
if Input.is_action_pressed("ui_left") or Input.is_action_pressed("move_left"):
direction.x -= 1
if Input.is_action_pressed("ui_down") or Input.is_action_pressed("move_down"):
direction.y += 1
if Input.is_action_pressed("ui_up") or Input.is_action_pressed("move_up"):
direction.y -= 1
velocity = direction.normalized() * speed
move_and_slide()

Phaser
Ahhhh…Phaser. Out of all of the engines mentioned, this is the one I have the most familiarity and hands on experience with. I’ll link up some demos to prove it in my next dev log, so stop being skeptical.
Phaser is on some weird end of the Spectrum where it might even be the hardest for some people to pick up, since it’s strictly a code framework with no user interface, and it uses Javascript, which I always found to be a language with a never-ending learning curve, and I don’t mean that in a good way.
Some of its concepts are hard to grasp compared to more procedural programming languages. It’s littered with anonymous and first class functions, aka, things I’m saying just to sound smart.
There are async annoyances, all kinds of weird quirks of the language and varying standards and levels of support within the language, not to mention web support vs local/node support…and don’t get me started on the varying runtimes and Typescript. The ecosystem is kind of all over the place. Javascript is one of the most frustrating things man has created, so of course it’s everywhere.
Every time I start a Javascript project I think it’s going to be easy. Then I bang my head on little idiosyncratic challenge after idiosyncratic challenge…sigh…and yet I love it the way one loves an abusive spouse. I just can’t quit Javascript.
So it’s no wonder I’m an ace with Phaser.
I actually love it. and I got the following built in roughly 2 minutes. (not a joke).
Phaser doesn’t really have an asset library per se. But what it does have is a huge community and excellent documentation with a huge depth of demo code that make sit easy to pick up and learn.
Because it’s built for the web it’s also super portable. Portability isn’t something I’ve mentioned much though, because honestly most of these engines have already proven themselves to be portable to the point that they can be on a website, or on a phone application.
Most game engines are completely cross platform. But it’s worth noting with Phaser because it’s more than just an embedded web toy.
Here is a list of games built in Phaser for instance
It is also worth noting that you can’t get the kind of performance from Phaser that you can from the other engines. The other ones are more low level and Phaser is built for the browser. So that can be a challenge if you want to make something ambitious with it.
And despite being built on a horrendous language. I’ve always found it fun to write in. And if you’re already a JS pro, you’ll pick it up no problem.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Phaser 3: Move the Square</title>
<style>
body { margin: 0; padding: 0; overflow: hidden; background: #222; }
canvas { display: block; margin: auto; }
</style>
<!-- ✅ Phaser 3 via CDN -->
<script src="https://cdn.jsdelivr.net/npm/phaser@3.60.0/dist/phaser.js"></script>
</head>
<body>
<script>
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#1d1d1d',
physics: {
default: 'arcade',
arcade: {
debug: false
}
},
scene: {
preload,
create,
update
}
};
let player;
let cursors;
const game = new Phaser.Game(config);
function preload() {
// No assets to load, we're using graphics
}
function create() {
// ✅ Create a square using Graphics
const graphics = this.add.graphics({ fillStyle: { color: 0x00ffcc } });
graphics.fillRect(0, 0, 50, 50);
// Convert it to a texture
graphics.generateTexture('player', 50, 50);
graphics.destroy(); // no longer needed
player = this.physics.add.sprite(400, 300, 'player');
player.setCollideWorldBounds(true); // Stay inside the screen
// ✅ Set up keyboard input
cursors = this.input.keyboard.createCursorKeys();
}
function update() {
const speed = 200;
player.setVelocity(0);
if (cursors.left.isDown) {
player.setVelocityX(-speed);
} else if (cursors.right.isDown) {
player.setVelocityX(speed);
}
if (cursors.up.isDown) {
player.setVelocityY(-speed);
} else if (cursors.down.isDown) {
player.setVelocityY(speed);
}
}
</script>
</body>
</html>

Löve 2D
The most annoying thing about Löve 2D is the umlaut in the damn name. I don’t just have this key lying around my keyboard. And hey, I’ve been calling it “Love” ok? Ok? Last I checked the umlaut means it’s pronounced Louuuuuuve. Like we’re going to The Freaking Lourve. And I wont pronounce it like that ok? I’m just not gonna.
Love 2d is written in Lua. It’s a language I learned specifically to write in Löve. Why Löve? One word: Balatro.
What the hell is a Balatro? I think it’s some kind of esoteric name for a Jester, I don’t know. freaking Google it.
Balatro is an amazing roguelike indie card game that was a breakout success. An addicting little masterpiece that no one can stop playing (you might say they löve it). It’s much like another of my favorites Slay The Spire.
After hearing it was developed in this little-known engine, I got curious.
Firstly, I löve Lua. It has some quirks I don’t like…like you really have to think ahead on when and how your variables get initialized to make sure they’re initialized in the right order or the program will throw a fit.
The indices start from 1 instead of 0. This throws me off constantly.
But it reminds me of Python and Ruby in its simplicity. And it’s quickly become one of my favorite languages to write in. There’s just something comfy about it.
But after having experimented with Löve 2d quite a bit, I feel like there just isn’t as much foundation laid as I’d like. You have to hunt around for libraries in Github, sometimes I’d find very basic things I needed only uploaded to the Löve2d forums by SomeGenericGuy56.
The documentation is solid, but I’ve found some things change between versions and somehow I’m never looking at the right docs.
Then…I’ve had a lot of problems with the WASM web players the community has built for it. It seems that I just can’t get my games to act exactly the same on desktop as on the web.
If I’m doing something very basic that seems to work…but I’ve been creating rhythm game prototypes and I get different behavior between these two places. Which means the portability just isn’t where I need it.
And it’s a shame, because I am falling in löve with Löve2d, even if only slightly.
And of course 3d support isn’t there, it’s right there in the name. Code and results below. Took me ~5 minutes to get to square.
-- Size of the square
local player = {
x = 400,
y = 300,
size = 50,
speed = 200
}
function love.load()
love.window.setTitle("Move the Square - LÖVE2D")
love.window.setMode(800, 600)
end
function love.update(dt)
if love.keyboard.isDown("left") then
player.x = player.x - player.speed * dt
elseif love.keyboard.isDown("right") then
player.x = player.x + player.speed * dt
end
if love.keyboard.isDown("up") then
player.y = player.y - player.speed * dt
elseif love.keyboard.isDown("down") then
player.y = player.y + player.speed * dt
end
end
function love.draw()
love.graphics.setColor(0, 1, 0.8) -- Teal-like color
love.graphics.rectangle("fill", player.x, player.y, player.size, player.size)
end

Verdicts
Dammit I’m a programmer and not a game designer, Jim. And it shows in my Time To Square in anything that is just a code and go solution.
But I also have the foresight to know that games are not simple code demos. And subsequently it’s nice to have an asset pipeline, and all of your things in one place and interfaces to tie behaviors together and give you an idea of the object oriented structure of your program.
I think I’ll bite the bullet and start developing in Unity, which I’ve been avoiding really learning. But that isn’t to say I won’t continue to make some of my stuff in a couple engines at a time until I’m fully convinced.
Comparisons
Feature / Engine | Unity | Godot | LÖVE2D | PhaserJS |
---|---|---|---|---|
Language(s) | C# | GDScript (Python-like), C#, C++ | Lua | JavaScript |
2D Support | ✅ Excellent (but 3D-focused) | ✅ Native, first-class | ✅ Pure 2D | ✅ Excellent |
3D Support | ✅ Industry standard | ⚠️ Improving, decent for simple 3D | ❌ None | ⚠️ Very basic, limited |
Asset Pipeline | ✅ Powerful, supports FBX, etc. | ⚠️ More limited, but improving | ❌ Manual | ⚠️ Browser-oriented assets only |
Editor GUI | ✅ Polished, professional | ✅ Lightweight and efficient | ❌ Code-only | ❌ Code-only |
Scene System | ✅ Hierarchical GameObjects | ✅ Node-based scene tree | ❌ DIY | ✅ States & Scenes (JS-based) |
Ease of Use | ⚠️ Steeper learning curve | ✅ Great for beginners | ✅ Simple, but no editor | ✅ Easy for JS devs |
Performance | ✅ High | ✅ Great for 2D, good 3D | ✅ Very fast | ⚠️ JS engine, good in browser |
Cross-Platform Export | ✅ PC, Console, Mobile, Web | ✅ PC, Mobile, Web, limited console | ✅ PC, Mobile (via love.js) | ✅ Web (HTML5), Mobile |
Open Source | ❌ Closed (proprietary) | ✅ MIT Licensed | ✅ zlib/libpng License | ✅ MIT Licensed |
Web Export | ✅ Via WebGL | ✅ HTML5/WebAssembly | ✅ With love.js (extra setup) | ✅ Native |
Community & Docs | ✅ Massive community, docs, assets | ✅ Growing, solid docs | ⚠️ Smaller, niche | ⚠️ Active but more fragmented |
Cost | ⚠️ Free w/ royalties after revenue | ✅ 100% Free and open | ✅ 100% Free and open | ✅ 100% Free and open |
Ideal For | Full-scale 3D/2D games | Indie games, 2D/3D prototypes | Fast 2D prototyping | Browser/mobile arcade games |
Best Features | Asset store, 3D tools, polish | Lightweight, scene system, free | Super fast iteration | Runs in browser, dev speed |
Biggest Drawback | Licensing, bloat, setup time | Less 3D polish, ecosystem smaller | No editor, minimal engine | Browser-only, performance limits |