2D Game Development

2D game development is not the easy version of 3D – it is its own craft, where readable art, tight controls, and a clear game feel matter more than polygon counts. Software Splash builds 2D games across mobile, PC, and browser, in Unity, Godot, and purpose-fit engines.

Where 2D Wins

2D reaches players on any device, loads instantly in a browser, and lets a small team ship a complete, polished game rather than an unfinished ambitious one. For puzzle, platformer, card, casual, and hyper-casual games – and for many serious-game and training uses – it is simply the right tool.

What We Build

  • 2D gameplay systems with responsive controls and satisfying game feel
  • Sprite and animation pipelines, or integration of art you already have
  • Mobile, PC, and browser builds from a shared codebase
  • Progression, monetization, and live-ops for games meant to keep players

Working out whether your idea suits 2D or 3D? Tell us the concept and target platforms – we will recommend honestly and prototype the core loop first.

Godot or Unity for a 2D Project?

Both are capable and the choice usually comes down to your team and your target. Godot’s 2D pipeline was built for 2D from the start, the editor is light, iteration is quick, and the project is open source, which matters to teams who want no exposure to a vendor’s licensing decisions.

Unity brings a larger ecosystem, more third party tooling, and a smoother path if the project later grows a 3D component or needs an established console pipeline. If you already have C# people, Unity is the shorter route. If the project is small, browser focused, and you value a lean toolchain, Godot deserves a serious look. Platforms covers what each target adds regardless of which engine you pick.

Game Feel Is Built From Small Deliberate Cheats

What makes a 2D game feel good is a stack of forgiveness the player never consciously notices. Input buffering so a jump pressed just before landing still fires. Coyote time so a jump just after leaving a ledge still counts. Hit pause on impact. Screen shake within reason. Animation with anticipation and follow through. Collision boxes that are more generous to the player than to the enemy.

None of it shows in a screenshot and all of it is the difference between controls that feel tight and controls that feel floaty. It is tuning work, it needs playtesting to get right, and it is the first thing cut when a schedule tightens. That is usually the wrong cut, because it is the part players feel immediately.

Sprites or Skeletal Animation?

Sprite sheets give complete artistic control over every frame and produce the classic hand animated look, at the cost of memory, atlas management, and a large amount of drawing for each new action. Skeletal 2D animation lets you reuse a rig across many moves, swap equipment, and blend between states, at the cost of a more constrained look and a runtime dependency you now maintain.

Character heavy games with many actions usually favor skeletal. Games where each frame is a drawing with its own personality usually favor sheets. Deciding after the art has started is expensive in a way that is easy to avoid.

Aspect Ratios Will Find Your Bugs

A 2D game has to survive tall phones, short tablets, ultrawide monitors, and browser windows people resize mid session. Decide early whether you letterbox, extend the visible area, or scale, because each option has gameplay consequences. A wider view can show players something you intended to keep offscreen.

Pixel art adds a further constraint, since non-integer scaling produces shimmer that pixel artists notice instantly. Safe areas around notches, rounded corners, and system gesture regions belong in the same conversation, and they are much easier to handle before the UI is laid out.

2D Deserves Consideration for Training Work

Much training content is naturally flat. Schematic diagrams, control panel faceplates, wiring runs, process flows, and decision trees are two dimensional to begin with, and rendering them in 3D adds navigation the learner has to manage before they can learn anything.

A 2D module opens in a browser, runs on hardware people already have, and is quicker to update when the procedure changes. Simulation and Training Software Development covers where the extra dimension earns its place, which is mostly spatial tasks and physical procedures, and where a flat interface teaches the same thing with less friction.

Where 2D Costs More Than People Expect

Two areas surprise teams. Text and localization, because a 2D interface is often drawn as art, and a language that runs forty percent longer than English breaks a layout that was designed around a specific string. And atlas management on a content heavy game, where texture memory and draw call batching stop being an afterthought once the sprite count climbs.

Both are cheaper to plan for than to retrofit. Decide the localization approach before the UI is drawn, and set an atlas convention before the art team has produced a thousand sprites.

What the Prototype Is Supposed to Prove

A prototype exists to answer two questions, and both are answerable before a single finished asset exists. Is the loop worth repeating, which only playing it settles, and does the lowest target device hold the frame budget under the heaviest scene you expect, which only measuring settles. Final art has no bearing on either answer, so it does not belong here.

The second question is the one commonly measured wrong. Testing the opening area proves very little, because the opening area is the lightest content the game will ever have. The scene worth building is the density you expect at the hardest moment, with the particle counts, enemy counts, and layer counts you are hoping for rather than the ones you happen to have, so the result is a number to design against instead of a discovery made late.

What a prototype deliberately leaves out, and why its absence is not a gap:

  • Menus, settings, and options screens, which are known work with no unknowns in them
  • Save and load, which constrains the data model but not the loop
  • Monetization, ads, and store integration, which follow from a game that holds attention
  • Localization and text handling, which is a layout decision made before the UI is drawn
  • Analytics and crash reporting, which have nothing to report until there are players
  • Final art, audio, and any effects pass, all of which make a bad loop feel better than it is

What the Project Needs From You

Art is the dependency that most often arrives in an unusable form. Layered or vector sources can be re-exported at a different size, recolored, and split into extra frames as animation needs grow. Flattened exports at the wrong size can only be scaled, and raster art scaled up shows immediately in motion even when a still frame looks acceptable. Skeletal art needs the rig project file, not just the exported atlas and animation data, or every new move means rebuilding the rig from scratch.

A short list of decisions belongs at the very start, because each one either sets a budget everything downstream is designed against or creates an account that is painful to move later:

  • The device floor: the oldest phone or lowest spec machine that has to run this at the target frame rate, which fixes the memory and fill rate budget
  • The target platforms, including whether a console version is a possibility later, because input abstraction and certification assumptions are cheaper to build in than to add
  • Who owns the store accounts, the analytics property, and any backend project
  • Whether the game has to talk to something you already run, such as a login system, a learning platform, or an existing player database
  • Whether audio is licensed, commissioned, or already in hand, since music and effects have their own lead time and their own rights questions
  • Data and audience constraints: age rating targets, whether ads are acceptable, and what player data you are willing to collect
  • Whether anything has to be authoritative outside the device, because one leaderboard turns a standalone build into a service with accounts, storage, and ongoing operational work

A Browser Build Is a Hosting Problem as Much as a Build Problem

The output of a web export is a large binary plus asset data, normally shipped pre-compressed with gzip or brotli. The host has to send the matching Content-Encoding header for those files, or the browser downloads bytes it cannot decode and the loader fails with an error that says nothing useful about the real cause. The same applies to MIME type: WebAssembly served as something other than application/wasm falls back off the streaming compile path, which shows up as a slower start rather than a failure, so it tends to go unnoticed.

Anything that uses threads needs SharedArrayBuffer, and SharedArrayBuffer needs cross-origin isolation, meaning the embedding document sends Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp. Those headers apply to the whole page, not just the game, so third-party embeds on that page that do not send CORP headers stop loading. On a marketing site with ads, chat widgets, or hosted fonts, that is usually the moment a single-threaded build becomes the right answer.

Storage and memory behave differently in a tab than in an installed app. There is no writable filesystem, so saves land in IndexedDB or localStorage, both of which the browser can evict; Safari's tracking prevention caps script-writable storage at seven days of non-use, which quietly deletes progress for a player who comes back after a fortnight. A 32-bit WebAssembly heap also cannot exceed 4 GB and mobile browsers reclaim tabs long before that. Audio has its own gate: the context stays suspended until a real user gesture resumes it, so the first tap has to do that explicitly or the game runs silently.

Where the Frame Time Actually Goes in 2D

What a 2D scene has is a stack of large, mostly transparent quads drawn over each other. Every parallax layer, particle, glow, and soft shadow shades the pixels it covers even where the sprite is fully transparent there, because the blend still runs. That cost is fill rate, it scales with the resolution of the panel rather than with object count, and it is why a scene that looks trivial in the editor can miss the frame budget on a high density phone screen.

The diagnostic that separates the two causes takes one change: halve the render resolution and measure again. If frame time drops roughly in proportion, the cost is fill, and the fixes are fewer and smaller transparent layers, tight-fitted sprite meshes instead of full quads, and cutting full-screen effect passes. If frame time barely moves, the cost is on the CPU: per-object update code, physics queries, per-frame allocations that appear as periodic pauses unrelated to what is on screen, and material or texture state changes that stop the renderer merging sprites into one submission.

Pixel art has a useful property here. Rendering the world to a small render target and upscaling that single image costs far less fill than drawing every sprite at native panel resolution, and it keeps the pixel grid intact at the same time. The consequence is that UI and text usually want to be drawn at native resolution in a second pass, which makes where each element lives a decision rather than an accident.

When a Game Engine Is the Wrong Tool

A card game, a quiz, an interactive schematic, or a scored branching scenario embedded in an existing web page often does not need an engine at all. A general engine brings its whole runtime with it, and that runtime is usually the largest single thing the player downloads before your content appears. A Canvas or WebGL library such as PixiJS is a fraction of that, and building the same thing in DOM and CSS goes further: real text input, text that can be selected and translated, and screen reader behavior that works without being reimplemented.

The crossover point is not about scale but about how many engine subsystems the project genuinely uses. An asset and scene pipeline, a physics solver, animation state machines, unified input across touch, keyboard, and gamepad, an audio mixer, and one codebase that exports to app stores and console pipelines are all real work you are not doing yourself. When a project needs two or three of those, the runtime it carries is paid back several times over.

Frequently Asked Questions

What has to exist before development can start?

A core loop described concretely enough to build, and one person on your side who can make design decisions without escalating them. "The player does this, then this, and the reason to do it again is that" is enough to begin; a genre and a mood board is not. The second requirement matters more than it sounds, because 2D game feel is settled by a long series of small judgment calls, and a call that has to travel through a committee costs more in schedule than the change itself.

What form does existing art need to be in?

Check pixel density and color space before anything else, because art repurposed from print or web material is almost always authored at the wrong resolution and in the wrong color space, and CMYK print art in particular shifts once it is sampled as a texture. Pivot points and frame naming matter as much as the images, since animation data and code reference frames by name and a rename late in production breaks both at once. Settle the reference resolution once at the start, because it is the resolution the art is authored against and every scaling decision afterward is derived from it.

Can you take over a project someone else started?

Usually, and what decides it is what comes with the project rather than how the code is written. It needs the version control history or at least a snapshot that builds, the exact engine version it was built against, the source art rather than only the imported copies, and the licenses or accounts for any paid plugins in use. Missing plugins are the common blocker: a project referencing a package nobody can download will not open cleanly, and replacing one means rewriting whatever depended on its API. Engine version matters for the same reason, since moving across a major version is a migration with its own testing, not a setting to change.

What does a handover of the project actually include?

More than a repository. A handover is usable when it carries the source, the exact engine and plugin versions it builds with, the export and build settings for each target, the source art and audio rather than imported copies, and the signing material. Signing is the part discovered too late: an Android upload keystore cannot be regenerated, and without it, or without enrollment in Play App Signing, no one can publish an update to the existing listing, only a new listing under a new package name.

Does one shared codebase mean the builds are identical?

No, and input is where they diverge most. A touch control has to be large enough for a thumb that also covers what it is pointing at, so a scheme designed around a gamepad rarely survives being mapped to touch and usually has to be redesigned instead. Storage, purchase, and sign-in integrations are per-platform work regardless of how much game code is shared. Each store then adds its own privacy declarations, rating questionnaires, and metadata requirements, which are submission work rather than development work.

How does a browser build get onto our own website?

Normally as an iframe pointing at a directory of build files served over HTTPS from a domain you control. The hosting constraints are the ones described above, and the component that usually breaks them is a CDN, because some recompress responses or strip the encoding headers the build depends on in transit. If your site runs on a platform that does not let you set response headers, serving the build from a subdomain you do control, or from a game host that provides an embeddable page, sidesteps the problem entirely.

Does the game need a server?

Only if something has to be true across devices or has to be trusted. Local saves, local score tables, and offline play need nothing behind them. Anything the player can benefit from changing is a different matter, since the client runs on their machine and its values are editable, so a shared leaderboard needs server-side validation or an accepted level of manipulation. In-app purchases are the other case: receipts have to be validated against the store rather than against the app's own record, or a refunded or replayed receipt keeps the entitlement. Live-ops is the third, because changing drop rates, prices, or event windows without shipping a build means that configuration is data fetched at runtime, not code compiled into the binary.