Level Creation and Initial Playtesting

So since the last update, the first level of GhostLight, currently being dubbed ‘Purgatory’ has been fleshed out a little, and undergone some very brief playtesting, this little article is going to be a summary of that process, as well as an update to the current state of the game.

So first of all, I’ve actually made the level, using 2D Toolkit’s tilemap it is literally as simple as selecting the tile from your tileset and ‘painting’ it onto the stage. However, some things need to be taken into account; the way 2D Toolkit creates the levels is it lumps all tiles painted on a certain layer together and creates a hitbox through edge colliders. The issue is if you want tiles to overlap, or if you want background/special tiles, then this doesn’t really work. Thankfully there’s a ‘layers’ option, each layer remains separate from each other, so you can have a layer for player hazards, and tag them appropriately using Unity’s tagging system.

levellayers

The above image shows my current workstation, I use a single layer for Hazards (such as the spikes that can be seen in the level), a platform (Foreground) layer, that the player will actually move on, a foreground effects layer that handles overlapping or transition tiles, (The edges of some tiles have transparent areas, so with this I can overlay them over other tiles to provide a nicer transition), and two background layers for similar reasons.

I had a quick playtest of my admittedly short level, and so did my girlfriend, and immediately the first problem with my desired mechanics arose. So originally, I had planned to introduce a sequential jumping mechanic, similar to the 3D Mario games, where pressing the jump button as the player landed would propel them further, and higher. The level was designed around this mechanic, which may have been a bad idea in retrospect, as trying to navigate the level with this mechanic proved very troubling.

It just didn’t feel natural for a 2D game to move that way, it felt like the control listener was too inaccurate to provide a tight window for the double jump that didn’t seem ‘cheap’ or inconsistent. With a little bit of tweaking I instead swapped it out for a more traditional double jump.

However there were more issues arising from what I thought would be a very basic and simple implementation; making long jumps felt very difficult, not in the sense of timing, but due to the nature of how I’d programmed the jumps (and how it detected whether the player was grounded), trying to jump at the edge of a ledge whilst running nearly always failed, the player would always jump just a little too late, taking away the important aspect of control and fairness required in a 2D platformer.

I came up with a solution, inspired from Juicy Beast’s similar implementation in their game “Toto Temple Deluxe!” where is the player has just left the ground and has not yet used their initial jump, then instead of immediately using their double jump, treat them as if they are still grounded. Let them use their first jump despite being just off of the ground, and the results were great! The player felt much more in control and the game felt much more forgiving in this element.

(By the way, Juice Beast has their own Dev Blog, and wrote about their implementation of the above mechanic here! I highly recommend you check it out and read through their series about Toto Temple Deluxe!)

I’d like to go into a bit of technical depth in how I implemented this, showing some of my code, so that anyone who’s not quite sure about how to make something like this can hopefully learn something!

//The following code is within the Control Handler function, that deals with all the basic player controls
//Unity has built in methods to detect certain Inputs.
//If the player has pressed the jump button, the character is grounded or they haven't double jumped, and the counter to allow them to jump hasn't expired
if (Input.GetKeyDown(KeyCode.Space) && (isGrounded || (!hasDoubleJumped || lastOnLandCounter > 0.0f)))
{
        //The timer for when the player was last on land is told to begin by setting the buffer variable to true
	lastOnLandBuffer = true;
	jumpPressedTimer = jumpPressedTimerMax;
        
        //If the land buffer timer has ended, and the player isn't grounded, it's considered a double jump
	if (!isGrounded && lastOnLandCounter <= 0.0f)
	{
		hasDoubleJumped = true;
	}
        
        //If the counter is still running, it's set to zero, and the player is vaulted along the positive y axis by our jump amount
	lastOnLandCounter = 0.0f;
	GetComponent().velocity = new Vector2(GetComponent().velocity.x, jumpHeight);
}

//This is called during the Fixed Update function a set amount of times each second
void LastOnLand()
{
	//A counter to check if the player has just fallen off the land or not, allowing them to jump still
	if (!lastOnLandBuffer && !isGrounded)
	{
		lastOnLandCounter = lastOnLandMax;
		lastOnLandBuffer = true;
	}

	if (lastOnLandCounter > 0.0f) 
        {
		lastOnLandCounter--;
	}
}

If the above just seems like jibberish to you don’t worry about it! Although please let me know how you feel about code examples in the comments to I know whether to include them in future πŸ™‚

Switch-activated doors have also been added but I think this article is long enough, so next time πŸ˜‰
Hope you all enjoyed!

Level Design and Tile Sets

I’d decided from quite early on that I wanted project ghostlight to use a tile-based aesthetic, as it would not only fit the style I wanted to achieve, but also allow me to create large and complex environments without creating lots of custom areas.

tile-based games are comprised of a tile set, a single image containing all the ’tiles’ a single board will use. Fortunately, unity fully supports a single image having multiple sprites inside of it, unfortunately, however, is each tile would have to be it’s own object with it’s own individual properties, which would create a large amount of overhead and complexity. I was struggling with a way around this concept for a while until I ran into Sam, the dev behind FreakZone GamesΒ at a local gaming meetup.

Off-topic for a moment; Sam’s games are really good, so you should go and check them out at the link above!

Sam ended up recommending a Unity asset called the 2D Toolkit, which has a built in Tile set creator, allowing me to create an entire 2D level using my tiles, without all the overhead.

The next step would be designing my level, the most important thing was for it to teach the player the mechanics they required for the rest of the game, so for this level I focused on the most basic mechanics:

  • Jumping
    • A sequential jump (think like the 3D Mario games)
    • Jumping on enemies is how you kill them
  • Shining your torch
    • Shining the torch at a lamp lights it and acts as a puzzle solving mechanic to open doors
    • Shining the torch at flaming enemies (ghost-firey-stuff) extinguishes the fire and allows you to jump on them to kill them
      • Some enemies could only be extinguished from certain directions
    • The torch beam can be reflected by mirrors

Whew, seems like a lot to teach a player over one small level. From looking at the list you can tell some mechanics, such as jumping on enemies to hurt/kill them, are common features of the 2D Platformer genre, and so may be easier to show.

leveldesign1

The above was my final design for the first level, I’ll do a little walk through of the first section, but anyone who’s interested in level design or game design, it’d be worth looking through the rest of my plan, and try to figure out what each area is trying to teach or test, or what I could do better.

So the player starts with a pillar to his left blocking that direction, and some pillars in the background, so the natural direction to go is right, moving this direction the player meets a small wall, allowing them to figure out the most basic controls (jumping, moving, etc) without any fear of failure.

The player is then immediately tested on this skill with a basic jump over a gap, but again with no risk of failure, whilst performing this jump the player will probably see the series of platforms with items (coins or something), but at the moment they cant seem to jump high enough to get on top of it. So they keep moving right, the one direction they’ve found that yields progress.

They jump onto the smaller block, as they’ve learnt they can do, and then immediately jump to get the coins/ascend the hill and WOAH SEQUENTIAL JUMPING WOOOOO.

So jumping twice in a row allows the player to go higher and further, now the player can use this skill they learnt and put it to the test to grab more loot from the area they couldn’t previously reach.

Hopefully that made sense, I just finished creating this level design yesterday so wanted to share it with you. Hope you enjoy! And I’ll leave you with a portion of the Tile set I finished last night πŸ™‚tileset

– Josh