Version Française
The game
This game has ben created during the 2022 game jam on Développez.com.Weirdly, we were not inspired at all regarding the game’s name, so we kept its codename until release: WE2022 (for "week-end").
This year’s themes were "Play with camera(s)" and "Big Brother".
You are locked up in a prison cell, probably because you have the power
to grab and send objects through camera feedback screens.
The distracted prison guards left an entire surveillance console in your
cell, giving you access to all cameras in the complex.
Use your power to free your way out by interacting with the environment
through cameras.
More information in the dedicated thread: https://www.developpez.net/forums/d2142720/applications/developpement-2d-3d-jeux/projets/we-jv12-participation-nom-cpp-opengl-d3d12-outils-blender-trenchbroom/
Making the game
Before the jam
1 or 2 months before the start of the jam, I started experimenting with post-processes in my engine, precisely bloom and depth-of-field, hoping I could use them in the coming game jam.Looking for an idea
Once the themes were made public, I absolutely wanted to use several render-to-texture to represent camera feedback, so it felt better to avoid multiplying post-processes, they were flawed anyway.I first came up with a few ideas:
- First, several cameras around on a road intersection, with red lights: the player watches a surveillance console, when a cas is visible, they can click it, which then activates a camera inside the car, and the player can look for "forbidden" objects (pretty much the same dystopia as my previous jam game). But I was tired of games that put pressure on the player and/or with limited time (in this case, requiring the player to react before the car is outside of the cameras’ range), we have to go back to 2017 to find one of my games were the player can take their time (our procedural escape-game), I wanted a game where you could chill a bit.
- Then I thought of going back to my underwater game project and make it some kind of 2-player Mario Kart, where all bonuses’ effects are related to the players’ cameras (grow/shrink you camera or the other player’s, skew the other player’s camera...) But I figured most people in the jam wouldn’t have a friend available to test it with them, and even if I somehow managed to get an AI working, the concept doesn’t work anymore when you play alone.
Then I looked for an idea relying on a surveillance console, like the first concept. At some point, I told myself that what added originality in the first idea was the ability to interact directly with objects through the camera, instead of relying on buttons or switches around the surveillance console. I though that picking up objects through the camera, and sending them back through another camera to interact with something else, was pretty cool.
The goal would be to free your way by interacting with cameras. At some point Biiscuit thought of a variation: we would open a door using a surveillance console, then you would move to a new room with another console giving access to other cameras to open another door, and so on. I suggested we could bring one console with us, ala Quadrilateral Cowboy. But actually, I didn’t feel like I could add a character’s 3D collisions with the map in the allotted time. (I didn’t have this ready in my toolbox :p except maybe if, like in my 2020 runner, you were moving only on flat ground.) I would have liked that at the end of our game, you could physically move to the exit.
How it went
Programming-wise, the first goal was to have several render-to-texture, and display them on quads in the world. I struggled with this for longer than I should have, then I had 4 screens in a basic map at around 2 in the morning. Then manage mouse picking on those quads.Horror: with all my post-process and shadows experiments, I modified my inverse matrix calculation (hard to do right when you’re bad at maths), but now my projection for mouse-picking was broken. I decided to use my old computation and fix it after the jam. It was a pain to fix (a lot of lines of code that look a lot like each other), but in the end it was a stupid mistake (I had mixed the calculation of components with a incompatible determinant computation).
Then, the challenge was to pick an object through the render-to-texture. I made it by de-projecting the intersection point of the mouse on the quad to act as if the render-to-texture was the actual player’s screen, then test picking as in the first case (I don’t know if I make myself clear here). I tested with a key made for a previous project (and update of the underwater game, by the way).
All these took me at least half a day on saturday.
A few hours later, I had an inventory at the bottom of the screen, where every picked up object was added. Once all the issues with picking through screens were solved, it was easy to drag an object from the inventory to another object through a screen.
During that time, Biiscuit was creating objects in Blender: a crowbar, a digicode, an access card.
When importing these objects in the game, I realized my .glb and .gltf loader was very lacking: I loaded all the json data, but in the end it worked correctly only when there was a single mesh (and a single skin, but htat’s irrelevant for this project), with a single primiting, in glTF’s terminology. That was enough when I was the only one making the models and I knew the constraint, but from an artist’s point of view, that’s a bug. And using several materials to have areas with different colors in Blender makes that mesh divided in several primitives in the glTF.
My management of the scene’s nodes was wrong too, so if a parent node was scaled and translated, the transform was wrong in the end.
To get this to a working state in the game, I slightly changed the model loading to load all primitives, and I painted the vertex with the color of their material. There was now way I could support all material features, I don’t know if I will someday :p
It’s because of these issues that I decided to start creating a model viewer after the jam (I’m focusing on glTF and my own internal formats) to avoid these kind of surprises in the future. I’m testing it with lot of models from the format’s github, and others I find on sketchfab, to make my loader rock-solid.
My goal is first to support all scene features and all combinations of animation formats (separate mesh animations, skeletal animations, and morph targets later), and as amny material features as I can, depending on my game’s needs.
Until now, glTF’s specification is pretty well done, I didn’t struggle much, except for one thing that wasn’t very explicit: if a node has a negative scale, faces of the child mesh(es) must be flipped. And the crowbar happens to have a negative scale :p Hopefully, someone made a lot of models for testing this case: https://github.com/KhronosGroup/glTF-Asset-Generator/blob/master/Output/Positive/Node_NegativeScale/README.md. Biiscuit’s crowbar works well now, I still need to test all these models.
Biiscuit also created the game’s map, in TrenchBroom, and the relevant textures, notably cardboard boxes and wooden crates. In this game, since picking are the only required collisions, using a CSG editor doesn’t make much sense, but I wasn’t confident in loading a map entirely made in Blender (And given all the issues I had for small objects, I was right :p)
Around 5PM on Sunday, I made progress on some "easy" features:
Not in chronological order:
- Ability to place items and cameras Trenchbroom
- Interactions between doors and inventory objects
- Localization: it’s one of the few engine features I manage to add before the jam’s deadline, I’m pretty proud it works so easily. The in-game texts are displayed in French or English, depending on Windows’ language.
- Ability to switch camera on a screen by clicking on another visible camera
- ”Save” cameras that have already been clicked-on to cycle through them with the keyboard’s arrow keys
- Display an object’s name when hovering it with the mouse
I released a proof of concept around 7:30PM, with a work-in-progress map and a few cameras, the only object was still the big red key and there was only one door to interact with to win.
I still had to add:
- Displaying text when hovering the paper note in the inventory
- Get the digicode to work. No script in this project, it’s all hard-coded.
- The Pause menu, from which you can only leave the game or continue.
At the last moment, I got the final map to add objects and cameras, before doing that I tested if it was displaying correctly in the game, and it was all black... After losing some time, it turned out it was the old unitialized variable mistake :p One shader uniform (the Projection matrix) was initialized only if I was drawing the render-to-texture for cameras, and since there was no camera yet in the map (unlike my small test map where I was testing feature), even the "real world" was showing wrong.
I then added entities (objects to pick up, cameras, turned some brush groups into brush entities for doors), tested the level was working, then sent it around 1AM.
There are still a few things I’m not satisfied with, like the feature of cycling through available cameras with the arrow keys is not well explained in my opinion (ideally, it required more on-screens UI), or the fact that the screens are just floating quads and we don’t see the "physical" monitor aroung them, when you don’t know about the game you don’t realize it’s supposed to represent a surveillance console. But when watching other people play the game, it seemed to have the effect we hoped for :)
I got a few lessons from this jam:
- Don’t half-bake engine features (expect maybe if you’re the only one using them and you know their limitations)
- Add asserts as soon as you know something can be used wrong (ie. draw before initializing every uniform of a shader)