Sokoban Devlog #1

A while back I wrote some code for converting a tiny PNG image into a level by just using colour codes to denote walls, floors, void, etc. And then paired that with some code that bitmasks all the squares around itself to find out which tile should represent it from a tilesheet (an excellent tutorial on which can be found here), I’d used this to build some 2D grid levels but not much else.

The goal was to start building some simple hand-crafted Sokoban levels and then perhaps expand on that with a couple extra mechanics later on.

So I decided to re-tool it to use 3D tiles and a rotation values so that it could build simple 3D levels out of a small set of tiles I constructed using Kenney’s nature pack.

First, I created a set of tiles to represent the major situations (there are some notable tiles missing, such as diagonal connections, those situations will just default to using an ‘island’ tile)

The three at the far back are extended below the rest of the tiles as they’ll be used to build the outer rim of the level which will appear to be ‘floating’ in space. The way I’ve achieved this is just by marking tiles as ‘bordered by void’ when building the level out of the PNG file, and if it notices a tile is bordered by void it’ll attempt to use a tile from this alternate tileset if it can find one (I’ve only built corner, straight and inner corner) otherwise it will default. This will work so long as I keep the border between playable area and void 2 tiles thick and free of complex shapes.

Next, I decided that playing around with multiple tiny PNG files (often 16×16 or 20×20 pixesl) was a pain, so I wrote a tiny piece of code to split one PNG into the multiple level textures.

public class PNGMapSplitter {

    // this class splits a PNG into multiple 'maps' based on a width/height
    // eg: this png is 5 levels wide and 2 high, for a total of 10 levels packed
    // ask for a lvl index and it'll return the tile for that level

    public static Texture2D[] SplitTexture(int cellWidth, int cellHeight, Texture2D texture)
    {
        int tx_width = texture.width;
        int tx_height = texture.height;
        Texture2D[] splitTextures;

        int cells_x = tx_width / cellWidth;
        int cells_y = tx_height / cellHeight;

        if(tx_width % cellWidth != 0 || tx_height % cellHeight != 0)
        {
            Debug.LogError("PNGMapSplitter: Error: Texture not divisible by supplied cell size");
            splitTextures = new Texture2D[0];
            return splitTextures;
        }

        splitTextures = new Texture2D[cells_x * cells_y];
        int i = 0;

        for(int y = cells_y-1; y >= 0; y--)
        {
            for (int x = 0; x < cells_x; x++)
            {
                Rect rect = new Rect(x*cellWidth, y*cellHeight, cellWidth, cellHeight);
                splitTextures[i] = CopyRectToTexture2D(rect, texture);
                i++;
            }
        }

        return splitTextures;
    }

    static Texture2D CopyRectToTexture2D(Rect rect, Texture2D texture)
    {
        Texture2D tex = new Texture2D((int)rect.width, (int)rect.height);
        tex.anisoLevel = 0;
        tex.wrapMode = TextureWrapMode.Clamp;
        tex.filterMode = FilterMode.Point;

        for(int x = 0; x < rect.width; x++)
        {
            for(int y = 0; y < rect.height; y++)
            {
                var pixel = texture.GetPixel((int)rect.x + x, (int)rect.y + y);
                tex.SetPixel(x, y, pixel);
            }
        }

        return tex;
    }
}

This means I can just use a single image with all the levels on it, provided all the levels on that image are the same width and height. (this image is scaled up 400% the actual levels are 20×20 pixels)

I’ve use a very simple colour code that’s hard-coded into the level builder for now.

  • Black – Walls
  • White – Walkable area
  • Magenta – Empty Void
  • Yellow – Solid Void (walls will count this as a solid wall for bitmasking purposes)
  • Red/Green/Cyan – Crate/Goal/Player Spawn

This is the result of loading those first five levels, it looks very bland for the moment but each tile has a couple of ‘detail spawn’ objects that will later spawn random details to help make the place seem a bit more lively.

Now I can start working on spawning the gameplay objects and scripting the mechanics.

 

Return of the Brain launched!

Hooray! I’ve finally moved everything over from different hosting locations into one nice location, here!

I’ve brought across all of the tutorials I’ve written so far, and have plenty of room for more to come in the future.

For now, if you’ve any comments or feedback I can be reached on Twitter @The_A_Drain

Peace!

#GBJAM – Kitty Quest – Post Mortem

*Update 17/10/2016*

So the voting has ended and we placed 24th out of almost 500! I am ecstatic with that result, so proud of how much positive feedback we’ve received for the game too. There’s talk on the wind of putting out an updated version with more enemies and more levels so stay tuned! View the full results here.

*End Update*

Last week saw almost 500 games made for GBJAM5, a game jam that aims to celebrate all-things Gameboy. What an amazing sight to see, almost 500 games in just 10 days. That’s *insane*. I participated along with my friend Jessica Fleur, and together we made Kitty Quest!

Here is a selection of the ones you should look at because they are amazing!

I loved taking part and although it left me exhausted by submission, I managed to submit an entry I am actually legitimately proud of. Kitty Quest is a reasonably complete-feeling game, it even has sound effects and music, something I usually forget about completely, let alone make my own.

_01_title

What went right

#1 Gameboy Limitations and Sprites!

I am really proud of how we made use of the colour palette limitations. The tiles Jess made look really nice and I’m very happy with how sleek and dynamic the cat sprite looks despite being made out of just two colours. It’s animated, functions well and for the most part it’s quite clear what you can and can’t interact with which aids playability.

leberu1

#2 Levels!

Even though they were made in such a hurry, I’ve had some pretty good feedback about the size and design of the levels. Level 1-3 are quite simple levels that introduce the concepts of wall-jumping and obstacles that hurt you. Then 4 and 5 ramp up the size before 6 and 7 ramp up the difficulty. While it shows they were made in a hurry, I’m pretty happy with how they turned out.

We planned to have more enemies and more features, but ultimately if we’d done that it’s probably we’d only have had 1 or 2 levels and I wouldn’t have been satisfied with that at all. Having fewer things also allowed me more time to polish them and fix some nasty bugs.

04_moretings

On a technical side, I decided very early on in the jam to build them in Tiled with a very simple set of rules (solid square collision tiles and everything else is either a game object or a detail tile) and that worked fantastically. While I did spend some time farting around figuring out how to import my placed objects with Tiled2Unity, it allowed me to build all the levels quickly and relatively painlessly. Which was awesome!

#3  Pre-existing Utilities

I had a couple of pre-existing utilities laying around from previous work that were perfect for this jam and saved me a good chunk of time. A couple of utilities for linear interpolation, playing sounds with a single function call, and my pixel-perfect camera setup. Having those ready to go from initial project setup was so helpful. Additionally, pimping out my camera setup to people who were also participating in the jam helped with point #4.

#4 Social media reach!

I’ve been neglecting social media a lot recently and wanted to change that. So I’m now available on twitter again and I’ve been posting development shots in places like reddit and itch.io. Regular gif updates served two purposes, it got eyes on the game and peoples kind responses to them help keep my motivation topped up. My previous 3 games on itch.io have a combined total of about 400 views over months. Kitty Quest got over 500 in less than a day. So I’m super happy with that.

#5 Early Submission

I made absolutely sure not to leave submission to the last minute to give myself some to fix any game-breaking bugs (which was crucial!) and to build the games itch.io page and to just play through the game and make last-minute fixes without being panicked because the deadline is looming. So I locked everything down 12 hours before submission and then only worked on fixing critical bugs and preparing the submission builds. Which saved me so much hassle.

What went wrong

#1 Planning/Time Managment

Despite being relatively organised, I still had to balance my time between working full-time and working on the jam game. I got a lot done in the mornings by getting up earlier than usual, but this wasn’t sustainable and by the last couple of days I was lagging, badly, and I had to slow it down a bit.

Additionally, with some better planning and structure in the order that I tackled features I could have added some more variety with next to no effort. For example enemies that move vertically rather than just horizontally would’ve given me a lot more flexibility in designing levels and had I thought of it before I made the enemies, easier to implement too. But the haphazard way I’d thrown together placing them in Tiled, importing them into Unity and then spawning them on level load made alterations difficult.

#2 Rust/Lack of Practice

As I’d not done a game jam in a relatively long time, I was unprepared for how quickly you need to race through certain tasks to get back to making the actual game. I spent way too long on things like the menu screens and UI simply because I’d forgotten how to do some simple tasks or had to change the way I do them slightly because last time I’d done them was in Unity 3.x.

Also fonts. I wasted a lot of time sorting out fonts and having to learn on-the-go how I’d implement bitmap fonts, which wasted pretty much a whole afternoon’s work. This is something so basic and fundamental I should have had working from the get-go.

#3 Stress/Anxiety

Due to the jam falling at the same time as a work deadline, things got pretty stressful during the weekdays and my anxiety started to kick in. I started having to take regular breaks and found my pace to be very stop/start. On more than one day I called it quits early simply because I felt like I was banging my head against a brick wall and making no progress and only stressing myself out further.

What to take forward

Having a couple of general utilities around, like the sound management script I mentioned earlier, was a godsend. Really saved my ass from having to re-invent the wheel under pressure and waste time getting unity to do simple things like automatically handle playing and disposing of sounds.

So this got me thinking. There’s no reason I can’t do the same thing for a bunch of other general-purpose functionality like screen/sprite flashes, screen transitions/fades, dialogue boxes, healthbars, timers etc. I want to spend a bit of time essentially putting together a ‘game jam essentials’ kit that I can start new projects or prototypes with. They’ll come in really handy for any future jams and if I make them correctly, can be extensible easily so that anything I make in future jams can be rolled back into that initial package.

Additionally, I can move forward safe in the knowledge that I still got this. I can still do game jams no problemo, all I have to do is not let the stress or self-doubt get to me and I’ve proven to myself here that I can do it.