Rolling Cubes is a game that I made for the 2022 Game Maker's Toolkit game jam, with the theme "roll of the dice".
My first thought was to make a platformer where you play as a cube that rolls around (which would have had stuff in common with some of my previous games, where you play as a circle). My second thought was basically Game Type B from the final game, inspired by Tetris but also probably a bit more like Puyo Puyo.
The first game that I implemented was Game Type A. You press an arrow key to move all of the dice that can move in that direction, which is a mechanic I've seen before; the only game I can think of with that mechanic is 2048, but I feel like I've seen some other game do something similar even before that (maybe an old Flash game?). Dice would appear at certain intervals (faster as the game progressed), and you'd lose if the entire board filled up.
Some problems I encountered:
In my original plan, if a dice touched another dice, then neither of them would move on that axis (like, if a dice is directly to the right of another dice, neither of them could move left or right), because if you tried to roll one it would bump into the other. I decided instead that I liked sliding better.
Also, I was thinking of making the board tilt when you pressed a direction (thus sort of explaining why all the dice were moving), but that didn't look good when I actually tried it (and I was worried maybe it'd make people motion-sick? I'm not sure I'm a good judge of that).
Oh, and the board was originally much bigger. I think making it smaller was my first attempt at fixing the problem that the board never fills up.
Adding a second game type was not actually that hard, since it uses mostly the same code.
Some ideas that I changed or ended up not implementing:
Again, I'm not sure if it's balanced properly, since I'm not that good at it (or at least wasn't when I made it), and unlike similar games (Tetris, Puyo Puyo), any dice has all six sides, so in theory it might always be possible to make a match (and there's a maximum speed, and dice don't fall while they're moving horizontally, so it might be possible to play forever if you're good at it).
I had plans to have a puzzle mode that gave non-random, premade puzzles where you had to get chains, which would have spaces on the board that weren't there (which would block the dice from moving into them) and cubes that were fixed in place (which would block the dice from moving towards or away from them, like the pre-sliding version). I decided that coming up with puzzles was probably too hard in the limited time allowed, and didn't make it. It would have been similar to some other games that were entered in the jam.
Since the game only cares about whether things match, and not about the actual numbers, my first idea was to have symbols on the dice instead of numbers. I wanted them to be asymmetric, so that you could at least in theory learn which side of the figure points to which other side (so e.g. maybe the point of the triangle always points to the star or something). My ideas for shapes were a triangle, a star, and a house shape, with opposite sides having the same shape but inverted colors (so, one would be dark-on-light, the other light-on-dark).
I eventually decided to use numbers instead, I think so that it would more clearly fit with the "dice" theme, but I used triangles for the dots to keep with my original asymmetry idea. The triangles point to the 1 side when possible (which I modeled as the front of the die), and for the 1 and 6 sides, they point to the 2 side (which I modeled as the top).
For colors, I initially had six different colors, but then I looked up colorblind-friendly palettes (I didn't want to use blue and orange yet again, since I already did that for X/), and found one that was a magenta-ish red, sky blue, and slightly orangish yellow, which I approximated. I realized partway through that actually the red should probably be a bit more magenta, but for some reason I didn't get around to changing it before the deadline. (I just changed it now as I was writing this.)
Also between the first version I posted on itch.io and a later version (before the deadline), I changed which colors went with which dice to hopefully make things a bit more distinctive; now the two dice with white backgrounds have very different-looking numbers, and one of the white backgrounds is used in 3-number mode.
I also made a black-and-white mode (like I've been doing for most of my other games), just in case the default colors don't work for some people. (Like, in case the dots don't have enough contrast.)
Dice explode by making each of their sides fly off, because that was an easy animation that I could program.
I intended from the beginning to make music for the game, but I put it off and ended up doing most of the music in the last two hours before the deadline.
I composed Type B's music first, using 6/8 time because dice have six sides. Also it only uses six notes (C, D, E, F, G, A, no B's).
Type A's music is made of random shufflings of six notes (this time excluding D instead of B), which is then layered on top of itself at three different speeds.
This game, like all my other jam games, is written in JavaScript, not using anyone else's engine. I've been sort of making my own framework over the years by factoring out code that's useful for multiple games. I'm glad that this time the rules didn't say anything about the majority of the code being written during the jam, because that mean that I can use the whole framework and have an options menu and configurable controls, which I didn't the previous two jams.
This year there was an extra issue, though, in that my keyboard on my laptop is broken, and I haven't done anything about it yet, so I did most of my development on my older laptop. I'm happy to report that this game runs perfectly smoothly on a laptop from 2009, on Firefox 16.0.2 (at least if you don't go full screen), with the exception that audio doesn't work because that version of Firefox doesn't support web audio.
3D libraries? WebGL? What are those?
This is the first 3D game that I've made in a long time, and the first 3D game that I've made in JavaScript. I didn't want to learn a 3D library in 3 days, and my old laptop probably wouldn't support it anyways, so the entire game is drawn using 2D graphics, and I do all the perspective calculations myself.
Fortunately, there was some point in the past when I worked out how to convert 3D coordinates into 2D, and the answer is surprisingly simple: you just divide the x and y coordinates by the z coordinate (assuming that z is positive into the screen, which is what I used). Also you have to move and scale stuff both before and after the division.
My code uses z into the screen and y down (because 2D graphics often uses y down), which looking at this tweet looks like no major framework does? Also the board is initially oriented vertically, facing the screen, before being rotated (i.e., the pieces in Game Type B are moving down, towards positive y), so negative z is the front of the dice.
To make sure that things in front appear in front of things in back, I made a big array of all the faces of all the cubes, and then sorted it by distance to the camera. (Initially I tried sorting by z coordinate, and that ended up with some faces in the wrong order, even with a single cube; then I tried distance from camera, and it worked.)
A dice can be oriented various ways—each of six sides can be in front, and then it can be turned in any of four orientations—so I had to figure out how to represent that in my code. My first thought was to have a 3-by-3 matrix representing the rotation; then I quickly changed my mind and decided to have two variables, one for the front face and the other for the top face, thinking that would be simpler. Then I realized I'd be using matrices anyways, so I switched to using matrices again. Each dice has a 3-by-3 matrix with all 0's, 1's, and -1's; the rotation animation adds on to that matrix. Which side is the front is determined by transforming the center of each face and seeing which has the smallest z coordinate.
DiceGame
class, and I didn't want to refactor.
array[x][y]
?", you might be thinking if you know some JavaScript (or similar languages). No, I mean like array[[x, y]]
. I'll leave it as an exercise to the reader what this actually does and what hidden gotchas there are. (Hint: Array indices are converted to strings.)
Day 1: