Lachlan's misadventures in games programming

Friday, 30 September 2011

War of the Apocalypse Samurai - A Potential Plot?

9/30/2011 02:52:00 pm Posted by Lachlan , No comments

I've had a general idea of what I'd like War of the Apocalypse Samurai to be for quite some time - a prince of persia-ery sword fighting platform game owing heavy inspiration to Samurai and Revisionist Western Films (ie. Kill Bill Volume 1 and Volume 2 Respectively). I've never had a story that would tie it together.

I think I do now. I've been playing with the idea of using the platform engine to make a James Bond-ish game.  During this week I concluded that it would be a good idea for such a game to be set in a fictional version of the 1960s - middle of the Cold War. One thing has lead to another, and now I have an idea for the Samurai Game I want which is at once plausible (given the ridiculous world) and very pulpy.

In 196-, the soviets were losing the cold war. Fearing the possibility of losing a nuclear war, and unable to afford to continue to build a brand new nuclear arsenal, the soviets train and hire the 4 greatest warriors living for $250000 (~$1.8m in today's currency) each, organises and trains them as the Apocalypse Samurai and places them around the world to be able to identify and kill any person on the planet within 5 hours. A credible threat to be able to retaliate to any nuclear attack without having to just bomb a civilian population.

Unfortunately, they overestimated the inhumanity of their anonymous elite force and directed War to kill her father. She defected to the US and was further trained and offered complete immunity to remove the Apocalypse Samurai from the world, and the Dragon who controls them. The game would consist of finding and killing each of the Samurai and finally the Dragon and the Beast across the whole world.

I like this idea. I want to see how well this could work...

Wednesday, 28 September 2011

Platform Progress - Collision Detection Sucks

9/28/2011 03:27:00 pm Posted by Lachlan , No comments
Those red boxes? The things you can collide with. The white box?  You. Simple looking I know - but slowly getting there
I've been wrestling with collision detection quite extensively over the last week and a bit (and a bit more). I've had varying things working, but they either partially work by colliding well and not necessarily putting the actor back quite where it needs to go, or getting stuck in walls, and generally not being able to register as a collision when they're just touching - or freezing the box if it could.

I've ended up using a simplified case of the technique in http://www.metanetsoftware.com/technique/tutorialA.html - it's the one they use for 'N'. If I end up adding ramps or anything I may have to do it in more detail, but it seems to work. However, the code wasn't liberal enough in detection of collision where the platform and actor are just touching - without overlap. So, I've added a simple, more liberal check at the end. Code is below, if it's your sort of thing or you need help doing something similar.


  1 void Feature::TotalCollision(Actor* actor, float dt)
  2     //Method described in this... partially
  3     //http://www.metanetsoftware.com/technique/tutorialA.html#section5
  4 {
  5     //These shouldn't be using typecast x1() but instead x - w/2 or something - Maybe
  6     //This may change if features start being defined by x, w, y & h rather then
  7     //w and h being calculated and the feature being defined by (x1, y1) and (x2, y2).
  8     float left_a = actor->x() - (actor->w() / 2);
  9     float left_f = (float)x1();
 10     float right_a = actor->x() + (actor->w() / 2);
 11     float right_f = (float)x2();
 12     float top_a = actor->y() - (actor->h() / 2);
 13     float top_f = (float)y1();
 14     float bottom_a = actor->y() + (actor->h() / 2);
 15     float bottom_f = (float)y2();
 16     float midx_f = (left_f + right_f) / 2;
 17     float midy_f = (top_f + bottom_f) / 2;
 18
 19     //bool colliding = Collides(left_a, right_a, top_a, bottom_a, left_f, right_f, top_f, bottom_f);
 20
 21     bool colliding = true;
 22             
 23     if (bottom_a <= top_f) { colliding = false; };
 24     if (top_a >= bottom_f) { colliding = false; };
 25     if (right_a <= left_f) { colliding = false; };
 26     if (left_a >= right_f) { colliding = false; };
 27
 28
 29     if (colliding)
 30     {
 31         float x_overlap = (actor->x() > midx_f) ? left_a - right_f : right_a - left_f;
 32         float y_overlap = (actor->y() > midy_f) ? top_a - bottom_f : bottom_a - top_f;
 33         if (std::abs(x_overlap) > std::abs(y_overlap))
 34         {
 35             actor->set_y(actor->y() - y_overlap);    
 36             actor->set_dy(0);        
 37             actor->set_v_collided (true);
 38         }
 39         else
 40         {
 41             actor->set_x(actor->x() - x_overlap);
 42             actor->set_dx(0);        
 43             actor->set_h_collided (true);
 44         }        
 45     }
 46
 47     //These fill the special case uncovered by the above where there needs to be a collision
 48     //for whether or not we can jump or not, but the code doesn't need to move the actor
 49     if
 50     (
 51         ((bottom_a == top_f) || (bottom_f == top_a)) &&
 52         !((left_a > right_f) || (right_a < left_f))
 53     ) 
 54     {
 55         actor->set_v_collided(true) ;
 56     } ;
 57
 58     if
 59     (
 60         ((right_a == left_f) || (right_f == left_a)) &&
 61         !((top_a > bottom_f) || (bottom_a < top_f))
 62     ) 
 63     {
 64         actor->set_h_collided(true) ;
 65     } ;
 66
 67 }



By the way - if any of you know a good, easy way to highlight code for blogs - preferably an online utility, I'd really appreciate knowing it.



Lachlan

Tuesday, 27 September 2011

Super Mario Bros: How Nintendo taught players the mechanics without a tutorial in Worlds 1-1 to 1-3.

9/27/2011 01:55:00 am Posted by Lachlan , , 2 comments

After some excellent company watching Flying High! and MASH (the movie), as well as excellent pizza from Gary at International Pizza in Montmorency, I set my mind at playing some of Super Mario Bros on the NES... or an emulated version thereof at any rate. During which, I learnt a few things:

  1.  Don't try to take screenshots through Nestopia with filters enabled. I had the NTSC filter for some old style scaling and colour bleed, but it ended up really squashed and odd
  2. Nintendo games rightfully deserve their reputation for difficulty. But, I made it to the end of the second world without losing a single life, and to the castle in the third world before losing the game. Fun fact: I've been spoiled by the SNES 'Super Mario Bros All Stars' versions of these games. I was expecting to start at the start of the world. Second Fun Fact: You don't. Also - I think the physics are noticeably different between All Stars and the original.
  3. The first few levels are brilliant game design.
I'm going to focus on Point #2. If what you want is difficulty, look at SMB 'The Lost Levels' or Super Meat Boy - I'm not in the mood to discuss it. And not good enough at platformers to discuss it anyway.

Super Mario Bros. has no tutorial. It has never needed one. I would, of course assume that it came with a manual - but even that (as you will soon bare witness) is not even required. I will clarify that the controls were made more intuitive by the fact that the control consisted solely of a D-Pad (The plus shaped thing with arrows on it for you non-gamer sorts), a select button, a start button, an A button and a B button. Controls weren't difficult to remember or even simply figure out. But they were improved by excellent early level design.

I'm going to demonstrate to you that the game teaches you how to play it, by playing it through the first few levels (particularly just World 1), and expose to you some of the brilliance. I'd like to forewarn that tutorial means teaches you how to play the game - not how to play it well.

World 1-1

This is about the first thing the player sees. He either runs into the Goomba and dies - and learns he can't run into the Goomba, or he successfully jumps over it. He'll usually in the process hit one of the ? blocks, and see coins come out with little numbers. You see the points go up, you see coins go up, you've been rewarded and you know that ? blocks can be rewarding.
So, you move forward, and find another couple of ? blocks, and the first has a Mushroom in it! Note how the location of the pipe means that the mushroom comes back to you, and that you actually require effort to avoid the mushroom. doesn't just fall off the screen. The Mushroom makes you bigger, at you'll probably figure out that you can now break the   Bricks.

You come across more pipes. You may figure out you can go down select pipes, you may not. I don't have a copy of the manual to check whether it hinted it or not. There is no indicator - and the first pipe doesn't let you so... brilliance has its exceptions. Or, we just take it as an old fashioned secret.

More Goomba's after returning from the secret area...

There's a staircase, and the flag. The flag moves to wherever you hit the pole which provides some feedback that higher is better. And the design of the level (staircase) hints that you should try to hit the top too.

World 1-2
A hint that something is different. At least it clearly takes control of Mario from the moment the character appears on screen.

This pair of Goomba's are the first indication that you can jump on two things successively for more points. Most people will do this on their first or second playthrough and learn.


Moving forward somewhat, you get the first clear indication (if you're still lucky/skilled enough to be big) that you can destroy blocks - as you're forced to. You also get the first introduction to turtles, and their mechanic of being able to jump on their shells.
You also get a sighting that there are the things that come out of pipes at a safe enough distance to guarantee survival - and they stop coming if you come too close. It's a good way of introducing the new enemy.


The level then introduces, in a very limited quantity, the first moving platforms. These become particularly important in the next level. You can't avoid them, forcing the player to learn of their safety.

World 1-3
Very brief comments. The world introduces the new platforms gently. Players have already encountered green turtles, but not red turtles - who turn around at the edges of platforms. The game introduces this by putting a turtle that is generally almost close to the end up top very close to the end of its platform (hence making the player feel that the turtle is going to land on the player) before the player sees it turn around. Red Turtles are used extensively in the level to emphasise the gameplay mechanic.

Studios seem to have lost the art of teaching players to play the game without an overly basic, trivial tutorial - or worse uninteractive video's. I might discuss this again. But, there are exceptions.

These problems have been most successfully avoided by Valve. I can list 3 very clear examples where Valve has been able to teach players the mechanics of the game effectively without a tutorial - being Half Life 2, Portal and Team Fortress 2. The latter two are particularly notable as Valve's customer-centric tester-centric approach to game design can most clearly be seen. If you own either game, I highly recommend playing the audio commentaries to understand how the games were designed. I was going to write more about the subject, but it is late and I'm tired. I may discuss it again later.


Lachlan

Tuesday, 20 September 2011

Platform Progress - Moving White Boxes - With Control!

9/20/2011 02:42:00 pm Posted by Lachlan No comments
I've got movement working! I've made a new class called 'FatController' who can get key-bindings and issue commands. There are a couple of odd things with Collision (half fixed), and you can jump when you're not on ground - but both of those problems will be fixed this afternoon.

I did do one kind of cool thing with FatController - in addition to the typical bindings of KeyUp and KeyDown I added a new set WingKey - so buttons like Left/Right which only one can be down at a time work. The KeyDown is called when it changes, and when you take a key off it goes back to the other one if it's still down, or calls the KeyUp if its not.

Video might be coming soon. If I can get the stupid thing to work... Either way - it's not that impressive.

But it works.

Friday, 16 September 2011

Ancient CRT Emulation

9/16/2011 03:21:00 pm Posted by Lachlan No comments
I was playing around with some idea's today about making stuff look early CRT era old. I was partially inspired by playing wee bits of fallout 2, and this article on SNES emulation - and making it work accurately rather then conveniently.

I tried to make a couple of screenshot mockups to see what could happen - not with anything I'll make (at the moment), but to see what kind of styles we could go for. I came up with these:

Completely original - except letters used from http://www.zee-3.com/pickfordbros/archive/bitmapfonts.php 
The infamous Doom title screen. Zoom in (click) for the detail
The first of these was just an idea for a piece of tiny art that I brought to fruition. The details are similar to the Doom one, which I'll explain more fully. The Doom one was me seeing what I could do to make something look old. I recommend zooming in.

What I did (all in Gimp)
- Started with the 320x240 resolution picture of the Doom title screen
- Resized it with no interpolation (ie. just making to blocks bigger) to 1280x960
- Colourised it to Amber
- Changed the colour curve to make it almost (but not quite) 4 colour - this works because the analogue screen I'm trying to emulate does have some transition between the 4 colours (but still actually 4 colours - just slightly more... antialiased) ... or something like that
- Duplicated the layer
- Blurred the top layer (lightly)
- Blurred the bottom layer more
- Added the lines at 40% opacity with a fill tool with a pattern on the top layer
- Merged layers
- Applied the lens distortion effect

It still could do with a few things to make it look more real - the colour still isn't quite right, the scanlines are in reality partially horizontal as well as vertical, there are little grey dots near the corners I couldn't be bothered with fixing and there could be some reflection on the screen, and maybe a little darker towards the edges.

I'd be fascinated to see if I could get this to run in real-time - though, I doubt it would be even remotely possible without lots of pixel shaders. It'd be fantastic to do though for a retro styled game. It's ironic it requires so much clockpower to make something look so old.


Lachlan

Platform Progress - Moving White Boxes - With Gravity and Collision!

9/16/2011 01:44:00 am Posted by Lachlan No comments
I've decided I'm going to post a basic list of things I'm doing whenever I'm doing them. I'm going to do some ol' fashioned devlogging. Maybe...

For those of you who never do maths, I use Δ a few times in this devlog. It is the greek letter Delta meaning (in this concept) the rate of change. ΔΔ means the rate of change, of the rate of change.

As of today, I have some working collision detection. Its not perfect yet, so if  Δx, Δy or Δt are too severe, it'll end up with the sprite either hovering or getting stuck. Maybe - I haven't got it stuck yet. Each Feature (which might be a platform or many other things) has a collision function which is as of right now either kNone or kTotal. The former being don't collide with this at all, the latter being everything collides with every facet of it. These will be expanded on later.

I've also got some basic gravity working. I define a ΔΔx and ΔΔy for gravity purposes, and a max Δx and Δy due to gravity. The result being that my white box speeds up until it reaches the max speed I've set for objects in the world, and then keeps going while the program runs, or the box runs into a feature.

A productive evening.

I've also included my current source metrics below - if that's your sort of thing. I might put it up a little more often. There won't be much from me until at least next week, owing to a take-home exam on property law over the weekend. There is a good chance of a couple of reviews coming soon. They'll likely be for:
- Rock of Ages
- Jamestown
Without giving a full review, both are cheap, fun, worthwhile and fantastic for split screen multiplayer.

Maybe also Grim Fandango - or maybe a 'Let's Play' - I dunno. Either way, it is my absolute favourite game of all time, and I highly recommend you play it (probably through Residual to get it working on a modern computer)

Cordially and Nerdily Yours,


Lachlan


Current Stats:

Files 62
Lines 4472
Statements 2552
% Branches 22.5
% Comments 2.9
Class Defs 28
Methods/Class 8.79
Avg Stmts/Method 6
Max Complexity 47
Max Depth 9+
Avg Depth 2
Avg Complexity 2.82
Functions 9

Wednesday, 14 September 2011

Platform Progress - Moving White Boxes

9/14/2011 06:13:00 pm Posted by Lachlan No comments
I sense that having a good design before you start would help. Unfortunately, I doubt that is going to happen yet - mostly 'cause I have very little clue, most of the time. It would make adding more stuff easier.

I didn't think I would need Floating Point numbers when I started being able to be handled by my PuppetMaster - turns out I did. The code made a mess. The reason for all this was, I'm beginning to add 'Actors' - players, monsters etc. At the moment, this means just a white box. A white box that due to my incompetence spent quite some time being debugged this afternoon!

Result: I now have a moving white box, that will maintain pace regardless of framerate. I'm going to start dealing with logic for it soon.

Btw - apologies for running so slowly. I get distracted, and have had a take-home exam to prepare for and do over the last week or so.

Some more reviews might be coming soon though.


Lachlan

Friday, 2 September 2011

Platform Progress

9/02/2011 11:51:00 am Posted by Lachlan No comments
I'm slowly progressing with my platform engine - working toward getting the basis of the editor working. As of yesterday, I can finally create new platforms by cloning other platforms. I'm working on getting the platforms to be able to generate their own 'recipes' so I will be able to save the maps and load them again.

The engine is actually fairly odd. Lots of things are stored in std::map's with strings. The whole thing is built around the PuppetMaster. Greenspun's Tenth Rule (though there are no proceeding laws) states that Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp. I'm slowly seeing this become true with my platform engine. It makes at least a minimal amount of sense to me, but I'm not always really certain I've done everything the best way - as can be expected from somebody who hasn't written much like this before. It's interesting just how much time I've been spending on the editor (which will still be buggy, and likely unfit for public consumption) because as I'm building it, I'm building the infrastructure. I'm not sure yet how I'm going to handle some of the odder things specifically related to platform games - like movement functions. It is my intention to build all of these out of the same feature rather then using polymorphism as I want to be able to create new types of platforms and features without changing code. I am considering whether I could add lua scripts as an alternative, though they may be slower.


Once I get this stuff down at least basically, I'm going to start dealing with Player-Characters/Actors/Monsters etc. Then I'm going to make a basic proof of concept game to test the engine. It will likely end up being a clone of World 1-1 of the original Super Mario Bros - or something like that.


Then I'll start working on the next full game. I've had a few concepts that I'll detail soon.




Lachlan.