Thursday 9 May 2013

If it looks stupid and it works...



It doesn't seem to matter how much planning I do, I always end up needing to improvise at some point. When I started this project I promised myself a few things, one of which was that I would have very neat, organized, readable code with a very rigid design. Well, it's less than a week in and I'm already breaking promises.


While I was building my collision detection for the zombie objects. I realized a couple things:

1. My Controller class was referencing my Zombie class a whole lot.

2. In order to make use of the same collision detection I was using for my player, my Zombie class was going to need to reference my Controller class.

Crap.

Unfortunately, this isn't really good design. It's called circular referencing and is the result of poor planning. The problem I had was that C++ only allows the code to reference other parts of the code that have already been declared. That means that if I declare class a before class b, then I can only reference class a from b, not vice versa. I searched message boards for hours in order to make this work. I found what I thought was a solution in forward declaration.

The idea behind forward declaration is that the code can reference what is essentially a hollow declaration of a class at the very beginning so that it can later be called to at any point. It's sort of like giving out a fake phone number at a bar. The guy can tell all his friends he has your number without technically lying, but he probably won't ever be able to talk to you (Sandra).

Pictured: Not me.

This has a couple restrictions.

The first restriction is that you can only initialize a pointer to a class that you've forward declared. If you don't know what a pointer is, it's basically directions to what you want. Instead of storing "Bender's House." you're storing "Turn left of main street."

The second restriction is you can only pass the Class objects that you've forward declared by reference. This is a little more complex to explain. When you call a function, it has something called scope. Scope is basically the part of the code that the function can manipulate. Think of the function like a king. A king's scope is his kingdom. When you call to a function and give it a variable or class to work with ("pass" a variable) you are taking something outside it's scope and creating a copy of it inside it's scope. That means that if you modify the variable passed in the function it has no effect on the variable outside a function. One way to get around that is to pass the variable by reference. This basically means any changes made to a variable passed into the function are permanent.

The third restriction is that you can't actually manipulate a class you've forward declared. You can only make reference to it. The last three paragraphs were basically a very roundabout way of saying that this third restriction sunk me. That was kind of unnecessary eh? But hey, you learned something I bet so 'sall good.

For the first time, I had to break my first promise. I ended up coding the zombie movement entirely in one function. When a target location was passed into the "move" function, it does all direction calculation, speed calculation and collision detection. (Boo!)

Luckily it sort of works. Zombies don't go through walls anymore! (Yay!)

Just like I said about two week before the dog show, I'll probably get it fixed and make it prettier. For now though? I'm just happy it works.


Another thing I did


is get a basic line of site system working. You can only see zombie that you have a clear line of vision too. Or sometimes you don't. I don't know, there are still some bugs. I'm pretty proud of it though. You can see it (and the bugs I'm talking about around frame 4-ish) below:


The way it works is very similar to zombie movement in general. It turns the distance between the player and the zombie into a triangle where the x and y differences are the edges. It then adds certain ratios to x and y so that x + y = 1, the idea being that it moves along the hypotenuse of the triangle. If it detects a wall at any step, it decides that the player can't see the zombie. It's Pretty simple and kind of buggy but it's serviceable. If I need to do an overhaul then I'll do it further along into development.

Oh yeah, I also added some basic graphics to make the game look fancier.

Actually, it's changed a lot since my last screenshots.

2 comments:

  1. Kudos, its starting to actually come together and look like a game

    ReplyDelete
  2. TL:DR Code got messy but effective.

    ReplyDelete