Mega's Competition Dev Log #3

Posted by Astryl on April 7, 2014, 11:26 a.m.

One week in and 23 days to go.

Most of my work has been on the engine, unsurprisingly, though I have taken the time to work on some art for the game.

My next challenge began this morning. It involves this:

These enemies are all static placeholders in the game; I have yet to add their AI. And on that topic…

Designing an AI system

With the original game, I was rushed. I'm rushed now too, but I just happen to have taken a hint from the last time that the copy-paste enemy code reuse in Exile was bad. It got to the point that, while I was working on the old improvements before I lost them, I just deleted all Enemy related code. That also happened to trim 5000 lines of code from the game.

In the original 'system', every type of enemy inherited some virtual methods from the Enemy class. And that's where the natural C++ code reuse ended.

One of the things I copy-pasted frequently was the billboard drawing code. For each enemy I had copied the same 100 line segment and pasted it in. Collision code? Same thing. Movement code? Same thing.

This time, I've been taking bits of code that I know I'm going to be reusing and adding them to the base class. The update method for my Fallen Knight enemy contains a single line:

drawBillboard(spr_walk, position);

Of course, it will contain quite a few more lines by the end of this, but already this is far better than the nightmare that was my 2012 Enemy class.

Anyway. AI. I'm using a simple state system, using an enum to store a few basic states:

AI_IDLE
AI_FIND
AI_ATTACK
AI_SHOOT
AI_FLEE

For each of these I'll create a method in each derived class to handle these states (Or ignore them and change state to something that class can handle).

Then, using the methods in the base class, I detect and change between states.

I'm envisioning something like this:

void EnemyFallenKnight::ai_idle() // Starting state
{
    if(Map::GetMap().isPlayerNear(this->pos) && 
       Map::GetMap().checkLOS(this->pos, Player::GetPlayer().pos))
    {
        // Wake up, we can see the player
        this->state = AI_FIND;
        this->clearPath();
    }
}

void EnemyFallenKnight::ai_find()
{
    // Find a path to player if possible
   if(path.empty()) 
   {
        path = findPath(this->pos, Player::GetPlayer()::pos);
   }
   else
   {
        // Move towards path.front(), then pop it and 
        // continue on to the next point, until we're one step away from the
        // player.
        if(nearnEnoughToPlayer)
        {
            this->state = AI_ATTACK; 
        }
   }
}

Some pseudocode, though I have a few of the methods implemented already.

Should have this done by tomorrow, if I can get a few hours of solid work in tonight.

On another front, I added in some better 2D editing to my editor. Box selection, which you can fill/set the height/flatten/fill with lights. Pretty easy, though reliant on keyboard shortcuts.

One last screenshot, then I'm back to planning.

Comments

InvisibleMan 10 years, 7 months ago

This is definitely looking cool :)

Regarding your issues with the enemies though: I personally use, and recommend, an Entity Component System. It's probably too late to implement it now, but just wanted to throw that out there as another option. There's a wealth of information on the subject over on the Gamedev StackExchange, and there is a C++ port of the Artemis framework, which I've looked into using before.

death 10 years, 7 months ago

why does the lighting not seem to make any sense ? the direction is completely random lol xD

yeah making a bunch of unique enemies is quite a pain. once you have your basic enemy code it's pretty easy to use as a base for all enemies but the problem i see, especially in FPS games, is that developers rarely make any changes from enemy to enemy. in most games all they do is change their speed, weapon and model/sprite and wow it's a whole new enemy! or so they think.

for my game, i've actually taken a lot of time to sit down and write out unique enemy types that don't rely on walking towards the player and shooting endlessly. of course this resulted in a bunch of cool and/or awkward ideas that are really hard to implement and would take an outrageous amount of time for enemies that may not fit the fast paced action of an FPS anyway…. oh well. Good luck, can't wait to see what you come up with this time :P

Acid 10 years, 7 months ago

Looking cooler ever day. I have to agree that the lighting seems weird, but it looks good nonetheless.

Astryl 10 years, 7 months ago

@InvisibleMan: I've actually been switching over to an ECS based system, though slowly. The rendering and collision detection is handled by the entity manager, which uses information in the various Enemy subclasses to render/collide them. The only thing I have yet to move into the manager is the logic, though I've already made some advances towards that by integrating LUA scripts. Bit of a big rebase though, so I'm not going to try finish it off before the end of the comp.

@death: Yeah, enemy variation is a bit of a pain. I'm not sure how much I'll be able to do in 23 days, but I'll do what I can.

@Acid: Flipped normals. I've been intending to fix those since ages ago.

EDIT :

Done.

death 10 years, 7 months ago

ahhh there we go, looks and feels better :P

23 days isn't a whole lot for adding different enemies. i've spend months working on a single enemy lol xD but for a proper little game, i think you should at least aim for 4 well built enemies. reuse them like Doom by making them well balanced versus the player. don't waste any time on low level enemies that are just there for the slaughter :P

Astryl 10 years, 7 months ago

Yeah, that's the general idea. Also, I'm focusing on producing at least one high quality level, with at least five minutes of good gameplay, over stretching it thin like last time.

death 10 years, 7 months ago

5 mins is a bit short :P didn't the guys who made Doom spend like a single day per level? i'm sure you can do a little more than that :P well depending on the sizes of the levels and whether or not keys, puzzles or other elements are going to be in them.

if you look at Hexen, that game CAN be beaten incredibly fast if you know where everything is, but if you don't, you can spend hours in one area trying to figure out what to do lol.

Astryl 10 years, 7 months ago

Hmm, not 100% certain yet, but I might decide to switch over to my 'backup plan'. Worried that the scope of this game requires more time to complete, and have it feel like a fully fledged experience.

And yes, I've had a backup plan since day one. :P

death 10 years, 7 months ago

so what is this back up plan? :P

Astryl 10 years, 7 months ago

As usual, a platformer. But I have an interesting combat system planned for it this time that draws a bit of inspiration from an old NES game called Karateka. Not too much, because that game had problems :P

EDIT: A bit more detail on the combat.

I'm planning on a 'stance based' combat system. When you get into a fight, instead of the combat being focused more around jumping around/running around and slashing wildly at an enemy, the player will enter a fighting stance (And the enemy will follow suite). Oh, and the combat is based on swords.

From this point on, pressing the direction keys or using the gamepad in a certain direction will play the first animation in a 'move'. So I can press Left->Right, Right->Up,Left->Up->Right to get the following sequence of attacks:

- Wide slash to right

- Short upwards slash (As well as a parry move)

- Heavy downwards slash

Sounds somewhat complicated, but it only needs a few animations for each 'weight' of move (First moves don't have much force behind them, second level moves will have action lines and a bit of force, third level moves will convey as much force as possible).

So generally speaking, I want to focus on the combat experience, and make it the key feature of the game. Art is probably going to be relatively low form/color to make the animations easier to deal with, and I have a way to work the colors theme into my idea too.