Dimensions introduction


Dimension Deflation is a platformer game where player is able to switch between 3D and 2D environment. Main inspiration for the project is Super Paper Mario. The game is in development for over a year as of writing this post. The scope of the project is enormous for a solo developer and a lot of stuff needs to be done on engine level.
This post is a summary of the work I have accomplished so far but doesn’t include everything, it mainly focuses on the engine level stuff.

Engine

For this project I decided to use the Godot engine.

  • Godot is open-source I can add all the core mechanics of the game directly to the engine and avoid tediously attaching core mechanic functionality as scripts to every single object in game, which could be error prone.
  • Godot node based architecture with clear distinction between 2D and 3D nodes made it possible to modify the base classes (Node2D and Spatial as of version 3) and enable the core mechanic to work on every node which derives from those classes and extends them depending on the need.
  • Godot allows multiple separate physical worlds to exists at the same. Every 2D environment can exists on its own without affecting others. Without that I would have to use some workaround to make sure bodies won’t collide with bodies which shouldn’t be there (adding offset to their location or affecting their collision masks)

Core mechanic

The core mechanic of the game is switching between 3D and 2D on the fly. At any moment game is in one of the four states: 3D, 2D and transition states between them (3D->2D and 2D->3D are technically separate states). Game also keeps track which 2D environment is active. Current iteration of the project allows only up to one 2D environment to be active at the time.
Technically the game is primarly 3D, there’s only one 3D world loaded at once and multiple 2D worlds we can travel into.

DimensionMatrix

DimensionMatrix is a custom Spatial node which is designed to project 3D nodes into 2D and be a point of reference when both 3D and 2D nodes are syncing their properties and transform. It is a box shaped area with defined width, height and depth. Each DimensionMatrix has its own separate World2D inside which every projected 2D object reside. DimensionMatrix uses collision masks to filter out the colliders we don’t want to be projected to 2D. Whenever a 3D object with colliders enters the area it creates a 2D counterpart with a counterpart 2D collider created from the 3D collider, this collider is then updated in 2D mode to reflect the collision shape of 3D world. Projection works for most of the colliders in the engine (convex, concave, box, sphere, cyllinder, capsule, ray) and in any combination of the position and orientation of the affected objects (the attached screenshot contains a now fixed issue related to rotation of some colliders not being applied).

3D and 2D relation To simulate objects going between 3D and 2D game defines one-to-many counterpart relation between 3D and 2D nodes. That relation is implemented on the engine level in base classes and exposed to GDScript so derived node can use and expand based on them. Nodes are syncing their properties and transform (location and rotation) according to the needs, by default transform is synced per frame and properties only during transitions. The relation between 2D and 3D nodes can be defined in the editor, by setting the path to 3D counterpart in Node2D instance. Spatial nodes can define what script will be attached to the newly created counterpart Node2D. Every Spatial node can be instructed to create a counterpart Node2D by calling the “create_counterpart_object_2d” method and passing the reference to DimensionMatrix inside which new counterpart will be located.

(Please take a note of the debug text visible on the video it reports when game is in 2D or 3D mode. At the time of recording the camera switchng wasn't implemented)

Derived classes can override virtual functions in either C++ or GDScript to customize the Dimensions mechanic, including: syncing custom properties, special behavior when object is affected by switching dimension, creating custom counterpart 2D object and so on.

Prototype of the prototype

And now some history: First iteration of the game was made using GDScript. It was already implementing the base concept for Dimension Matrix which was a scene made from Viewport, CollisionArea.

In this prototype a lot of heavy lifting was performed by the nodes. Player object had a ton of code to create its 2D counterpart, check the global state of the game and follow the counterpart. The was also an implementation to support creating box collider counterparts using a derived from RigidBody script. Without finishing rest of the colliders and body types I started moving all the functionality to C++ and as soon as they were in the engine I gradually removed a lot of code from the GDScripts.

Future of the project

I’m still working on the game, there’s still a lot of stuff I didn’t discussed in this post but I didn’t want to make it too long. I may add those extra tidbits in a new post some other time. The plan for now is to work on gameplay and create some first playable levels. I already have a story in mind which I don’t want to discuss at this moment. I’m designing this game as a 3D/2D platformer primarly with puzzle elements being on the second place. I want the player to be able to run, jump, climb and whatever else platformers do + also switching dimensions on the way. I have ideas for multiple related mechanics I want to experiment with. I would like to explore the concept of how objects and characters are adapting to whenever they are in 3D or 2D.

Get Dimension Deflation

Leave a comment

Log in with itch.io to leave a comment.