Hello! I created a procedural level generation method for my 1st game (a runner,) using only global variables and collisions. It’s my 1st tutorial, so please offer suggestions. Oh and the CAPX is included! : )
How it works
The Player runs towards the right. Trigger runs in the opposite position.
On collision between Player and Trigger, a number of things happen:
- The system creates a block of objects (like a composed solid platform.) We define those in advance with a “Blocks” global variable –number-.)
- We ask Trigger to re-set its X position on the way of Player, and then collisions continue to happen, and blocks to be created.
- Order (numerical global variable): Any other action we ask from the system is also executed; the “Order” GVAR lets us define what happens at each collision. For this project, let’s add 1 to the value of Order at each collision.
- Example: Order = 1: a single Solid platform is created, Order = 2: system creates a triple Solid, and so on.
- Series (num. GVAR): it will allow us to re-use groups of Orders later in the level (for example the 20 first Orders relative to the 20 first collisions,) we use the Series to group the Orders.
Note that for this tutorial CAPX I kept the events under 60 (edit: 64,) I used the minimum just to show how the basic system works, but if you grab a Construct 2 license, you won’t have any limit.
Let’s continue with a little more detail about objects and variables.
Sprite object with platform behavior, set default controls: no. Simulate platform pressing right, simulate jump on any click, up key or space bar. Acceleration and deceleration: 10000.
Sprite object with solid behavior + bullet behavior (set angle: no) and three frame images, it will form the floor for the Player. Animation speed: 0.
A sprite object with bullet behavior; it has the same direction and speed as the Solid sprite (floor.) I chose the name because it will trigger creation of objects.
Tiled background object for the blue sky.
Block =1 is formed by 3 instances of the Solid sprite (floor,) which have frame 0, frame1 and frame 2. We could call it a single platform.
If Block =2 then the system will create the same as Block =1 except that the middle (frame 1 in green) is doubled, we could call this Block a double platform (Two instances of frame 1.)
Order: as included in the CAPX’s description; it lets us decide what happens at each collision of Player with Trigger; in other words: what happens when Order = 1, Order = 2 etc.
Series: As explained earlier, series controls a number of Order values, and thus what happens in a particular part of the level, say from Order = 1 to Order = 20, it helps us to control how many things happen in a part of a level, then we can reuse a particular Series whenever we want.
Making the system work:
It was not evident, but after many tries it finally worked! In general, whenever I had a problem, adding a new variable allowed me to solve the problem.
For example: how to position the Y of new Solid Blocks at every collision (Order) without affecting all the previously created Solid object instances on the screen?
Solution: we use a global variable SolidY. When its value changes, only the newly created Solid object instances will be affected. What we do everytime: change SolidY global variable right before the objects are created (using the collisions.)
How to control the length of the gaps between each Block (group of Solids)?
First we define a general interaction that happens at each collision between Player and Trigger:
Then we simply change the value TriggerX GVAR whether we need the Blocks to be created farther from Player or closer to it. We do this inside the Order actions.
For example, how to reduce this jump gap between these two blocks? (Notice we are at Series = 2, Order = 1)
The solution is we go to the previous event, right before Player collides with Trigger, and we look at which Series and order we were at (look at the top right, red rectangle, seems like we were at Series = 1, Order = 3):
So once we determined the responsible event, in this case: Series = 1 Order = 3, we simply reduce TriggerX, so that it becomes closer to the Player; the closer the object Trigger is and the sooner the next block is created, which means a shorter jumping gap between the two blocks:
Now we can see the change in the game, it works!
Also another significant addition to make the system work: we need to work a little more on controlling some global variables by resetting them, this is to avoid having unwanted created objects, and conflicts between GVARs that may cause the system to create nothing at all. Infact, I think this is the only way I found to make the procedural system work, period : )
Expand the image, I added explanations:
Other problems you may encounter when blocks are meant to be created by the system:
If Blocks are not created, check the debug and make sure Global Variables have the right values, otherwise correct the error in the events.
When Blocks are created but do not follow the "set angle of motion to 180°," then place the "set angle of motion" event right under the definition of Block groups (groups of solids,) as follows:
Solids (floor): the change in their Y position can affect all the Solids at once: this can be fixed with “System: Trigger once while true.” Use this on each necessary action in events (example: when defining the Blocks -groups of Solids-)
Solids have the same frame (the last frame, say frame 2): make sure you set the animation speed to 0!
Alright, I think I covered as much as I wished, in the simplest way possible. I hope that you'll find this little method handy or fun to try, or develop even! And of course do not hesitate to ask questions or offer suggestions.
Thanks for reading and have great times! : )