Saturday, March 29, 2014

Difficult to Convey...

Until I've a firm idea of how I need the cameras to behave, this week I turned my attention to another idea for Citadel which I'd jotted down in my big book of ideas many moons ago: conveyor belts.

I'd always loved the idea of the player entering a vast, underground robot factory (those robots emerging from the traps have to be made somewhere, right?), and it seemed logical that such a factory would feature conveyors (and other dangerous machinery - but more of that another time).

However, although I was keen to try out some ideas, it was tinged with the realization that I'd have to revisit the player control routines and bash them into better shape before I could implement the conveyor logic.

One of the key issues was that the player movement code used a system that counted how many pixels the player moved, in order to get the Monitor craft to stop after it had moved one tile. Thankfully, Game Maker allows you to check this with the place_snapped command (as I discovered when implementing basic enemy movement a couple of weeks ago), so my player movement code needed a revamp.

* * *

Once the basic control routines had been tweaked (which, surprisingly, worked first time after I'd fired up the code), next came the task of detecting conveyor tiles and moving the player accordingly. This is the difficult part for me - breaking the problem down through analysis and working out the best solution; sometimes there are multiple solutions, so it's always a big dilemma.

I wanted to use the typical platform game convention that a) when at rest, the player will move at the speed of the conveyor, b) the player will move slower than usual if they try to travel against the direction of the conveyor, and c) the player will move faster than normal if they move with the conveyor.

Essentially, the basic logic works as follows:

  1. Check that the player is snapped to the grid (i.e. not already moving).
  2. Check for a conveyor tile beneath Monitor.
  3. Check to see if the player is trying to move; if so, check direction and adjust speed.
  4. Otherwise, set the player's speed to that of the conveyor.

Rather than duplicate masses of code, I came up with a nifty script-based system that allows me to feed a bunch of speed parameters to a central control routine, and in practice, it worked beautifully (I actually surprised myself with how simple it was and how well it worked!).

Flushed with that success, I redesigned part of my test level to include some conveyors, and it was really neat to see Monitor riding the conveyor belts around the level!

* * *

Later on, I showed my progress to the Mrs. and (typically!) a bug chose that precise moment to appear: essentially, because the tilesize is a power of two, the player's speed must also be similarly proportioned or the movement routine messes up when the player moves too far and 'skips over' a tile boundary.

On the plus side, I did hit upon the idea of a variation to the conveyor belts in the form of a Portal 2-style Excursion Funnel (which restricts all player movement), or possibly an electromagnetic conveyor that doesn't allow the player to sidestep off the conveyor at any point. And as I was typing up this blog entry, I also hit on the idea of special switches that reverse a conveyor's direction. Hmmm!

Monday, March 24, 2014

Camera Shenanigans

I spent a little time over the weekend putting together a list of some areas of the game I'd like to tinker with; although I currently have a lot of prototyped code in the game (and nothing actually 100% finished), I'm liking the experimental phase as it allows me to a) learn Game Maker in a much more hands-on fashion, and b) helps me iron out those unexpected kinks and foibles.

One such foible reared its head over the weekend, in the form of some nasty gaps between the background tiles. I'd implemented a camera system which not only dampens the camera's movement as it tracks the player, but also allows the camera to zoom in and out (in the version of Citadel in my head, I've always loved the idea of zooming in tight in times of close combat, or zooming out to emphasize the size and scale of the underground cities).

After a little detective work - and more than a little cursing - I stumbled across this article which explains the issue and why it happens (and not a moment too soon - I'd already downloaded Unity as a threat to Game Maker if it didn't start to behave itself!). I spent an hour this afternoon tweaking the tileset, adding a gap between the tiles and padding the edges of each tile image.

After reconstructing the map, I fired up the game and the gaps had become a thing of the past - one of those classic situations where, despite the work that went on behind the scenes, the game looks virtually identical to the way it did before.

Friday, March 21, 2014

Sprite Sheets to the Wind...

The past few days have seen me dipping into other projects (i.e. paid work!), so my time on Citadel has been somewhat limited. However, I managed to use my time wisely, and dedicated my efforts to tweaking some of the graphics (now that my tile size is definitely 64x64... definitely... for now...).

One of the tasks on my list was to arrange all of the C64 sprites on a master sprite sheet, on a 64x64 pixel grid.This serves two purposes:

1. Although I import my sprites using strips, on a case-by-case basis, having all of the sprites laid out on one sheet in PhotoShop is extremely useful (not least because it allows me to see typically how much space the sprites use, and how much of each texture page remains). Plus, it means that I'm only ever updating one file - a huge pet peeve of mine is having a lot of clutter in my working folders.

2.  Currently, sprites can be any size, which can cause issues given that a) everything moves on a tile-by-tile basis, and b) things can move at different speeds. Plus, if I want a sprite to appear in the center of a tile, I have to add additional code to calculate the sprite's width and height, divide by two, and add this to the sprite's co-ordinates. Messy, and unnecessary. By ensuring that all sprites are 64x64, all sprites can have their origin set to the top-left of the sprite and everything will work perfectly.

The downside, of course, is that smaller sprites will contain a certain amount of empty space around the outer edges, but the wasted memory, at this point in time, is minimal.

* * *

In the process of laying out the sprite sheet, I needed to flip back and forth from the C64 version to ensure that my sprites were sitting in the right spot inside each 64x64 tile. Basically, C64 sprites are 24x21 pixels in size. In Citadel, everything is based around 32x32 pixel background tiles, and thus, the sprites are positioned roughly at the center of each 32x32 tile (4 pixels in from the left, and 7 pixels from the top, in case you were really desperate to know!).

On a couple of occasions, I had to do a little bit of detective work to understand why some of my ripped sprites didn't look the same as they do on the C64 (and in the process, I discovered that Martin Walker is doing an awful lot of neat stuff behind the scenes that the player will never know about or truly appreciate).

One of these tricks involves plotting a different background tile behind each trap, depending on the trap's contents. In the case of switches and weapons pods, the C64 version plots a unique tile filled with one of the game's background colours; this effectively allows the switches and weapon pods to use four colours (three sprite colours + background) instead of just three. A really simple idea, but extremely effective.

* * *

After a few sessions, the updated graphics were imported, and after tweaking (and simplifying) some of the logic code, all of my 64x64 sprites were in and working perfectly; everything aligns/snaps to the grid, and my trap animations now align perfectly with the background tiles (something which simply wasn't possible using smaller sprites and approximate positioning).

I rounded off tonight's session by tinkering with the force-field doors that will litter the cities (aside: I really need to produce a task list and start getting at least one task per day off my plate). It didn't take long to create an animated object which I can place in the levels, and after adding a couple of lines of code, I was able to stop the enemies passing through them (which now means I can out run the little blighters - at least, until I put in the player/force-field collision!).

Monday, March 17, 2014

Tightening up the graphics...

Tonight's session saw me making a few changes to Citadel's graphics scale. Previously, I was using the C64's resolution, i.e. all my game tiles set to 32x32 pixels. This is all well and good if I merely wanted to emulate the C64 and never zoom in or out; but seeing as I do want to zoom, some changes and tweaks were necessary.

The biggest alteration involved creating a brand new tileset with 64x64 tiles, tweaking the sprite sizes to match, and adjusting the viewport settings within Game Maker to a more appropriate zoom. I also took the liberty of creating a tilesize constant, which I then used throughout the code; in future, should I ever change the tile size again, most of the fiddly work I did tonight will be done for me just by changing one value in the editor.

I rounded off the evening by doing some research into why my tiles were blurry; it turns out that Game Maker only allows texture pages of 2048x2048, and automatically scales images that are too big. So not only were my tiles getting compacted to an eighth of their intended size, they were getting stretched back out again when drawn to the screen. It's often amazing how much a game can be transformed with just a couple of hours' work. Here's hoping this productivity continues. :)


Ohhh Snap!

Another lengthy gap between blog posts, but I can assure you, things in the world of Citadel have been progressing, if a little slower than I would have liked. That said, there has been plenty of procrastination. One of the biggest problems I have right now is focus; I'm so enamored with Game Maker, I see so much potential and have dozens of ideas I'd love to try. The problem with this, of course, is a) not having that much spare time for one project, let alone half a dozen, b) not having eight pairs of hands, and c) I'm not even at what you'd consider an intermediate level of proficiency with Game Maker (yet).

Thus, the only thing I could do to calm the rising wave of "what if's" in my head was to write an orderly list of all the projects I'd like to tackle, and pick ONE that I can tinker with alongside my Citadel remake. It sounds like a plan - I hope by unconscious brain takes the hint.

* * *

 Yesterday I sat down at the keyboard for the first time in over a week, in a vain attempt to get my enemies moving. One of the biggest issues with programming (for me, anyway) is knowing how to break a task down into logical steps. I'd been thinking - and possibly over-thinking - enemy movement and AI for the game, to the point where I had no idea where to start, or what the best approach might be.

In desperation, I'd Googled "enemy movement routines game maker", which ultimately led me to an excerpt from a Game Maker book, where they discussed enemies moving on a tile-by-tile basis (in other words, precisely what I need for Citadel). Key to the routine was the place_snapped command, which allows you to check whether or not an object is aligned to a grid.

After an hour or so at the keyboard (along with a puzzling period of 15 minutes where I was tweaking the code for an object but getting no results; it turned out that I was debugging the code for the wrong object, and naturally, much slapping of the head soon followed), my enemies were finally emerging from traps and chasing me, tenaciously, around the level.

Although some of the graphics will have to be re-imported to work with the grid snapping (essentially, changing the origins of sprites and adding some padding around their edges), the code is starting to take shape; I now have a clearer picture of how the AI/State machines will be structured, and once the movent routines are done I can then allow enemies to start shooting back. :)

Saturday, March 1, 2014

Deep Thought...

A fairly big gap in blog posts, but that's not to say that things haven't been progressing. Much of my time recently has been spent investigating various tutorials and demos in order to work out how Game Maker (GM) handles paths and suchlike; these will be useful for getting the enemies to move around the level and hunt down the player. I could, admittedly, do the hard work myself and use an A* algorithm, but with so many in-built functions in GM, it seems silly to re-invent the wheel without considering all other options.

After a few late-night sessions, and much head-scratching, it became apparent that I'd probably have to use an A* algorithm - great as they are, the in-build functions just won't cut it in terms of what I want to achieve. Luckily, I have a very small and sweet A* testbed created in Blitz+ which I had planned to use for the earlier incarnation of Citadel, so I'll need to set aside a chunk of time to convert it across to GM.

* * *

Today I had a chunk of time to kill, so I spent a couple of hours re-reading Martin Walker's Citadel diary in Zzap!64, mainly to familiarize myself with his thoughts on the enemy AI (I'd previously gone through his diary and written copious notes, but this was a great refresher). It was extremely useful, for instance, to see how he built up the enemy behaviors layer by layer, adding more complex attributes for some of the more advanced enemies (it had completely escaped my mind, for example, that many enemies will follow the player but stay just out of reach of the player's weapons).

* * *

This afternoon, I had planned to take a pass through some of GM's various tutorials; thus far I've been watching some YouTube videos, but  although they're great for covering specifics, it's very easy to overlook some of the fundamental basics, and given that I'd been banging my head against the wall over global/local variables recently, I figured I'd go back to square one.

Wednesday, February 19, 2014

Silver Bullets...

After adding the basics of the weapons system yesterday, this evening I attempted to add some more polish to the system, including environmental collisions. I started off by adding a new sprite for the player bullets (the one I'd chosen was a little weedy), and then added a routine that allows the player to fire bullets to the left and right (depending on where the mouse pointer is on-screen).

I hit a snag with the bullet generation, and thus a little time was spent reading various articles to work out the source of the issue. Essentially, every time a bullet is fired, an alarm is set; this counts down to zero, during which time another bullet cannot be fired (a simple system to stop bullets being spewed every frame).

The problem with Game Maker's alarms is that unless the alarm is checked by an event, it doesn't function (this seems lame until you consider that it's just the engine being ruthlessly efficient). The solution is pretty simple - just add a code segment that is triggered when the alarm fires, but leave the file blank.

After fixing the alarm issue, I took the next step of adding vertical firing, then rounded off the bullet routines by adding collision states (so that the bullets explode when they hit a wall). The next step was to bring the pieces together and allow the enemies to be taken out by bullets, which was a matter of 30 second's work. I then reaped the rewards of the evening's session as I wandered around the map firing bullets and taking out any enemy that dared get in my way! :)

Interestingly enough, I came up with an idea while roaming the maze and flinging out bullets, and wrapped up the night's session by creating a crate entity; these will litter the levels, and act as either bonus repositories (a la Half Life), or simply allow the player to nudge them around the map to provide useful - if temporary - cover from enemy fire.

Tuesday, February 18, 2014

Spawny Twonk...

I had one simple aim for tonight's Game Maker session: make the traps spew out enemies. I started off by importing some temporary sprites for the enemy from the C64 version of Citadel, which also included "appear-from-trap" animations.It's a pretty straightforward process for a trap to generate an instance of an object - the real trick was to organise the enemy code so that the object can have different states (appear, patrol, destroyed, etc.).

Once the little blighter was successfully emerging from the gloom, it was time to add some rudimentary movement code. If you recall, the player in Citadel moves one square at a time, and the same is true of the enemies; thus, I looked for a way to allow the enemies to use the same movement logic as the player (rather than re-invent the wheel - or at least, duplicate wads of code - for every entity in the game). Luckily, Game Maker has a handy script system, which is essentially a function that you can call from anywhere but affects the object which called it.

Simply: say I had a movement script that adjusted the player's X and Y co-ordinates. If I call this from the player object, the player moves. If I call this from the enemy object, the enemy moves. Pretty neat, and a stellar way to modularize code.

In order to test the movement script, I then had to plug in some rudimentary AI - in this case, I made the enemy follow the player left and right (merely to check that the code was working and the enemy didn't try to fly through walls).

Flushed with success, I rounded off the night by starting on a rudimentary weapons system; after all, I'm not teaching the enemies to hunt me down unless I'm armed. :)

Sunday, February 16, 2014

Into the Citadel...

Yesterday I spent an entire morning re-reading my Blog from the last ten years (it's amazing how well I can remember coding sessions from 2006, but can barely remember what I had for lunch yesterday). My motivation was really twofold: firstly, I wanted to try and re-capture some of the drive and enthusiasm I had back then, and secondly, I wanted to re familiarize myself with some of the ideas and concepts I had for Citadel, way back when.

I also took the liberty of going through my Citadel design notepad which I scribbled in religiously during my university years from 2007-2009 (word to budding designers: write every idea down, and make sure you keep them - you never know when you may need to draw from them). It was an interesting read, and of course, it's always rewarding when you manage to impress yourself with an idea you can't even remember having!

* * *

Today, faced with a snowstorm outside and not much else in the way of commitments, I decided to sit down and start plugging away on the game. I needed to try a new way of working, and so I just dove in with no real game plan, and no desire to get it right (merely, just get it working). I already had my Mayhem testbed to work from, so I ripped out the collision system and began adding Citadel assets.

One of the first things I like to do is set up a basic shell, so that the game starts with a title screen, which links to the game, and in turn links back to the title screen. It not only makes the project instantly feel more rounded, it also gets you thinking about structure from the outset (there's nothing worse than having to take a pile of demo code that works perfectly, then break it into a million pieces as you try and fit it into a framework later on).

After the basic shell and collision were in and working, I imported sprites for the main player ("Monitor"), a test enemy, and a trap. The player control system was up and running in its most basic form fairly quickly, and within a few minutes I was roaming around the first level of the game looking for things to kill. :)

The next idea was to try and get a simple trap in and working (in Citadel, enemies, pickups, and switches are spawned from traps, which open as they player gets close). A fairly simple idea resulted in me banging my head against a wall for almost an hour trying to get a few simple lines of code to work.

After a shower and a little time to think, I came back to the keyboard and Googled the command in question, and managed to find a really common-sense Wiki which listed common mistakes for each of the Game Maker commands. Needless to say, I was making one of those mistakes, that of my code being called in the wrong event. Twenty seconds later, the code was working and the balance of the universe restored. :)

* * *

After lunch, I returned to the game to start refining a few things, including the player control, animation, and collision. In Citadel, the player moves one tile at a time (a quaint idea which gives the gameplay a unique twist), and luckily I had a testbed written in Blitz Max from 2010 that did the job perfectly; thankfully, it was a relatively simple process to translate this code to GMS.

Next came a slight tweak to the collision system. Due to the fact that the player moves on a square-by-square basis, the collision is actually quite simple: in essence, the squares around the player are analyzed before the player moves, so there are no checks to see if the player is colliding when they are moving, just checks before they move to see if the adjacent squares are free.

Once the control and animation were working as intended, I rounded off the day's session by tweaking the trap code so that it opens when the player gets within a certain range. Now the real magic begins: making the traps spew out enemies. :)

Sunday, February 9, 2014

Back to the Future...


They say that life is what happens when you're making other plans, and that certainly rings true as I sit down to tap in a Blog entry after a hiatus of almost two years; more incredibly, it's almost ten years since I started this Blog back in July 2004, as I searched for a programming language to create a game and satisfy my creative urges.

The programming language was Blitz+, and the project I had in mind was a remake of Martin Walker's seminal Commodore 64 title, Citadel (not to be confused with the BBC microcomputer game of the same name). The search for a decent map/level editor led me to create my own, and thus Citadel took a back seat for two years while I worked on FishEd, a map editing tool of which I am immensely proud.

During that time, of course, new languages came out, including Blitz Max, and thus Citadel was again on hold until I had mastered this new language (during which time, thoughts of re-writing FishEd in Blitz Max once again pulled me away from the process of actually writing the game).

And of course, one needs to throw life into the mix: during those ten years, I got married, moved to Canada, lived and worked on a horse farm, started two new businesses, got divorced, went to university, relocated from the West coast to the East coast of Canada, started a new career in radio/broadcasting, and got married for a second time.

It's no wonder that poor Citadel had to take a back seat for so long.

Fast-forward ten years from 2004, and games development is a generation or two removed from what it was back then; the iPhone was just a germ of an idea; there were no app stores; Steam was a fledgeling platform that nobody thought would grow or survive. Most importantly, if you wanted to make a game, typically you had to learn a language and do things the hard way.

One constant remains, however: I still want to remake Citadel.

* * *

When I recently looked at the array of tools at my disposal, it dawned on me that though the potential was huge, the choice just as overwhelming as it was back in 2004 (this is partly my fault: as soon as I have to choose between two or more things, my brain goes haywire). However, I'd like to think that I've matured and grown since 2004, and thus I arrived at a final decision fairly quickly: Game Maker Studio, which narrowly beat Unity to the finish line.

I won't bore you (too much) with my thought processes, but essentially GMS appealed to me for a number of reasons:
  1. I can create the game and edit the levels all in one package, giving me more focus.
  2. I was able to boot it up and get results in minutes; Unity's initial learning curve had me struggling to just load an example project without tearing my hair out.
  3. It's as simple or as complex as you make it; the in-built actions and events make it easy to rough out game mechanics, which you can later refine by adding code as you learn.
  4. I can output to a variety of different platforms, including HTML5, Windows, iOS, etc.

Last week, after Game Maker Studio had sat on my hard drive for months, something started nagging me to begin using it, so I stole some hours here and watched some excellent tutorial videos put together by Shaun Spalding (you can find his YouTube page HERE). Today, I spent an hour creating this:



An hour. One hour. Including the time it took to convert the graphics into the correct format. Flushed with this success, I was certain that Game Maker would be the package of choice to put together a remake of Citadel. Finally, after ten years, things seem to be happening.