mspraggs / potentia

Southampton Game Jam 2015
0 stars 0 forks source link

Desert Enemies #73

Open DivFord opened 9 years ago

DivFord commented 9 years ago

I'm going to post concepts for desert enemies in this thread. Feedback very welcome, as well as suggestions for more enemies.

rollerlizard

This one is based on a real lizard that curls up into a wheel. I thought it would be fun as an enemy that wanders around, then rolls into a spiky-death-wheel and charges at you.

EDIT: And it definitely isn't a Sandshrew...

Fyll commented 9 years ago

Seems nice. I'll have to put some sort of charging code into the AI.

My first thought was Sandy T-Rex rather than Sandshrew.

mspraggs commented 9 years ago

That's really cool! Plus it'll be easier to get enemies without weapons off the ground at first.

DivFord commented 9 years ago

That's a good point. I was planning to stick to animals for the basic desert, so that works out quite well.

Fyll commented 9 years ago

So that I can start work on this (I promise I'll bother to do fire one of these days...), specifically what do we want him to do? This is the impression I got:

if (player is within a certain distance and on the same x plane) {
    Go in a straight line towards where the player was.
    When you hit a wall or the player, rethink your strategy.
}
else
    Pace back and forth (not falling into any pits).

Is that about right? This does mean he could charge into a pit if the player cunningly stood in front of it.

DivFord commented 9 years ago

Sounds about right to me. I see no problem with clever players making use of terrain. That's a good thing, surely.

Would it be wise to frame the charge as an attack? Firstly because sprite sheets will probably have an "attack" animation that would be rolling-up for this guy, but maybe shooting or hitting for another enemy. Secondly, because I can imagine various AIs including the "if (player is within a certain distance and on the same x plane) {" part so it might make sense to have:

if (player is within a certain distance and on the same x plane) {
    Attack ();
}
else
    Pace ();

and:

Attack () {
    if (attackType == charge) {
        Go in a straight line towards where the player was.
            When you hit a wall or the player, rethink your strategy.
    }
}
Fyll commented 9 years ago

The way the AI works is that the unit'd have 2 tactics:

I think the only conditions programmed in were that the player is within/without a given distance, and whether or not the unit is on the ground. I couldn't think of any others.

DivFord commented 9 years ago

Ok, sounds good. I'll make a start on the art tomorrow.

I'm sure we'll think of more conditions as we go along. I was considering a vulture enemy that only attacks if your health is low…

In fact, how about I list all my ideas.

Fyll commented 9 years ago

"If your health is low..."?

The pacing in the air might be a bit fiddly using only what I've currently got, but is probably doable, especially if I write some code for it.

Spitting venom would act as a gun. Otherwise, fine.

Melee attack would act the same as the Mole Mitt (so, a gun). Also fine.

Tortoise seems nice and easy. I'm not sure where the threatening part of him is if he just hides when you get too close (obstacle, maybe?).

DivFord commented 9 years ago

Derp. Forgot there was no health… Maybe if you're on your last life? Or just drop that one.

Hence the question mark on the shell part. Maybe he hides if you attack him from range, then pops back out when you come within his reach?

Fyll commented 9 years ago

Do you even get tortoises in the desert? Would he just be the generic walk back and forth enemy? I think having him as an indestructible enemy who can't kill you, but just paces back and forth might be nice (maybe hiding in his shell if you get close enough), sort of like a moving platform.

DivFord commented 9 years ago

You do, yes. I like your idea, not least because it deals with the little voice in my head telling me that tortoises are herbivores, and don't attack people. Having non-dangerous creatures makes sense for the first zone as well.

EDIT: Also, a question. What do you plan to make enemies do when they die? Are the bodies disappearing, or remaining in play? In other words, should I be making a 'dead' animation?

Fyll commented 9 years ago

At the moment they just get deleted when they die.

I could probably make them fade out (or explode! :P) fairly easily. The same might be true for leaving a prop (their body) behind, but I'm less certain of that.

DivFord commented 9 years ago

Presumably, if you did go down the prop route, you'd want the body on a separate sprite sheet anyway. I won't bother making one for now.

Fyll commented 9 years ago

Having written some of the code, there're two ways I can see to do charging (one more hacky than the other):

Any thoughts/alternatives?

DivFord commented 9 years ago

The only alternative that occurs to me is allowing the AI code to change the movement speed.

Couldn't you go with the dash button option, but not add in any player input to use it? That way the player won't behave differently to now, and we shouldn't need new anims.

It may be sensible to separate the way enemies use sprites from the way the player does. I suspect we'll be adding in lots more behaviors that need new animation. I was imagining that enemies would have an 'attack' animation, which would basically cover whatever unique behavior that enemy had (charging, shooting, hiding in shell, etc).

Fyll commented 9 years ago

Okay.

I intend to redo how the sprites work at some point, using a map to take things to positions on the spritesheet, but am still slowly mulling over how it'd work. Hopefully, that'd sort out this problem and let the enemies do whatever they want. Also, if I get the sprites to work as I'd like, we could have enemies who hide in their shell when you're far away, but charge you when you're close!

DivFord commented 9 years ago

Just what I was hoping for :)

Could we make it data-driven? In fact, could we make enemies in general data-driven? By which I mean, have txt files with their stats, ai tactics, and sprite mapping. It would help with the plug-and-play testing Matt was talking about, and would keep enemies from cluttering up the code.

Fyll commented 9 years ago

They're currently stored in a UnitList. Is that not equivalent? I would put the map (or whatever it needs to figure out how sprites work) into the UnitListData, alongside their tactics and stats.

DivFord commented 9 years ago

Ah, Ok, that's pretty much the same. The only advantage to my way is that individual enemies would have their own files, so it would be easier to find them. Plus, we wouldn't need to compile every time we changed them.

With the map, presumably we're associating Strings (eg. walk_01) to vectors (eg. 0,1). Is that right?

Fyll commented 9 years ago

True, but as always, I'm an advocate of keeping the code inside the game.

I've been trying to think of some way to directly associate the things with the Vectors, rather than having something which converts the property (moving left) to the string (walk_01).

Also, if the sprites are all in rows, we could just use y indices instead of full Vectors.

DivFord commented 9 years ago

Not sure I understand that second point…

Surely part of the point of this is to allow the sprites not to be in rows. We'd stop wasting texture space that way.

Fyll commented 9 years ago

Fair enough. I was just thinking of the Player spritesheet for now.

Fyll commented 9 years ago

Okay, I've pushed a first attempt at doing the sprites by map. It's a bit ugly, but it's as good as I could think of it. I've only done it for Units so far (everything else still uses the same methods they did earlier, but Units are the ones that most wanted this change anyway), and it feels like it might be a bit too much overkill for some things (like bullets).

A charging animation is accounted for, but nothing else (like ducking into a shell). I could imagine adding a few "special" slots to it (allocated to buttons 1, 2, and 3, but not for the player), but there is then going to have to be a limit to the number of animated abilities an enemy can have. Charging was done because it was an easy check (are you moving faster than you should be? Okay, you're charging).

Thinking about the tortoise, I keep picturing him with transition animations (turning slowly around, pulling into his shell). The code is really unprepared for this, but I could start working on it if we think it's worth having.

DivFord commented 9 years ago

I hadn't thought of that, but you may have a point. It will look really odd if a big, slow character like that just flips direction instantly. I suppose we could try it without, and see how it looks, before you start coding that.

Fyll commented 9 years ago

Fair enough. I should probably be working anyway....

Thinking about the SpriteMap, it'd probably help out with the Block code, as each combination of neighbouring blocks could be mapped to the appropriate part of the sprite sheet

DivFord commented 9 years ago

The sprite sheet for the roller lizard is in the repo. Not sure if you saw.

Fyll commented 9 years ago

I hadn't noticed. Knowing now that it's in there, I've typed up the maps into UnitList.cpp (well, copied/pasted most of them as it has the same layout as the PC spritesheet), so the Roller Lizard should be ready to go (our first enemy, yay!).

As a quick warning, I've noticed now that the AI is a bit cautious about walking too close to obstacles (he's happy to roll into them though, just not while he's ambling about), so he turns around roughly 1 step before he reaches the wall. I'll look into fixing this at some later point.

Also, do you think you could add on a couple of frames of getting into/out of a ball, as he just suddenly switches into one at the moment?

DivFord commented 9 years ago

I'm getting a constant flickering between the turning anims. He never seems to walk, just turn round and round as he drifts around. I assume you aren't having that problem?

EDIT: I changed the level to fill in the holes. I think the problem was that he was on very narrow platforms, and is probably related to the walking into obstacles bug you mentioned.

Fyll commented 9 years ago

Yeah, probably. He turns a few steps earlier than he should. If he's turning too quickly after the last time he turned, he'll just start the new turning animation (thus, appearing to jump between frames).

DivFord commented 9 years ago

Can we lock the AI during the turning animation? (i.e. no new instruction to turn while the turn is in progress). Or maybe just stop moving if walled in on both sides. That would probably look better.

It also occurred to me that I've made jumping animations for him that don't really get used. Would a palette-swapped jumping lizard be worth making?

Fyll commented 9 years ago

The AI'll have to be souped up before it can sensibly handle jumping enemies, so maybe at some later point down the line. At the very least, the falling and landing frames are used at the moment.

Stopping the AI was something I meant to do earlier, but completely forgot about it while implementing animations (also, it turned out to be a fair bit fiddlier than I expected). It should be done now though.

DivFord commented 9 years ago

That works better. The continual rotation is still a bit odd though… How hard is it to check if he's blocked on both sides?

Also, I got this error: Warning: Sprite::setTexPos() - unrecognised sprite key: 39 I thought it was related to him dying, but it doesn't seem to be.

Fyll commented 9 years ago

That'll be some state unaccounted for. Let's see... 39 = 0b100111: Dead, Rolling, Moving, and Left, so it's when he's dieing during his rolling animation. I'd forgotten to add those to the Dead lists, but they should be in now.

DivFord commented 9 years ago

That seems to have fixed it. Quite hard to tell with this one, but I think I got him while he was rolling.

Next question: Can we narrow his hit-box a bit? Currently he kills you slightly before making contact, which seems unfair.

Fyll commented 9 years ago

Actually, that's something that's currently un-fixable. The reason being that he uses his standing hitbox, even when compacted down into a ball (at least, I assume that's what's causing it). Unless I allow the hitbox to change with the frames (which could be considerably messy code-wise), the only other ways I can think of is if I always use his ball hitbox, or you either make his ball-form bigger or move it forwards in the sprite (as you should never be worrying about bumping into his back).

Even then, I can appreciate that this may be something we want the capacity to do further down the line, so I'll look into it.

DivFord commented 9 years ago

Are you aware that the lizards can kill each other? If you place two in a level and jump over them, the second one rolls into the first and both die.

Fyll commented 9 years ago

Hah! I'm guessing we don't want that.

I've moved the if(obj.lethal()) from Unit::collide() into Player::collide(). That should have fixed it.

DivFord commented 9 years ago

Umm… Is the lizard now immune to being shot?

EDIT: Except by the magnet hand. Must still be vulnerable to fire.

Fyll commented 9 years ago

Bleh. My quick fix broke some other stuff (Bullets are lethal, so no longer work). I've undone it and will think about it some more later.

DivFord commented 9 years ago

Could we add playerLethal? So lethal would affect units in general, but playerLethal would only affect the player.

Fyll commented 9 years ago

Yes... Probably. I don't see why it wouldn't work, but seeing as I'm going to be having a good look at Bullets (splitting beams off) after I finish collisions, I was going to wait until I've done that before looking into this.

Thinking about it off the top of my head, we could just put a check in Bullet::collide() that kills any Players or Units that it collides with. The question then, is how many things are we going to want that are Player-lethal but not Unit-lethal? Is it just bullets?

DivFord commented 9 years ago

I think you've got that backwards… Bullets are lethal, lizards are playerLethal. I can see us doing something like spikes (which would be lethal to both players and monsters), so a special case in bullet probably isn't the best solution.

Fyll commented 9 years ago

Fair enough. I'll run through the code and stick it in at some point. I'd be more tempted to use an enum:

enum LethalityType {
    LTL_SAFE = 0,
    LTL_PLAYER = 1,
    LTL_UNIT = 2,

    LTL_TOTAL = LTL_UNIT & LTL_PLAYER
};

Or something like that, so we can define different types of lethality if need be. Alternatively, we could make the ObjectTypes a binary enum, then have lethality be a combination of the things it can kill (e.g. lethal_ = OBJ_UNIT & OBJ_PLAYER; would mean the thing can kill both Units and Players).

DivFord commented 9 years ago

Either that, or a binary enum for damage, and another for vulnerability. If bitwise AND-ing them together gives an answer greater than 0, the target is vulnerable to at least one of the types of damage dealt. It's more complicated. Depends if we need the flexibility.

Fyll commented 9 years ago

Thinking about it (again), bullets that should be able to kill (Cannon, Flamethrower, Mole mitt?), have effects that label them as themselves (Breaking, Burning, and Digging), so the Units could be set to die when they recieve the appropriate effect. This way, different enemies could have their own defences and weaknesses.

I believe this is the same as what you're suggesting, except using already existing code.

DivFord commented 9 years ago

I like that idea. Ties enemies into the existing puzzle system a lot better. Now it's not just a question of shooting it, you have to work out the right gun to shoot it with.

Fyll commented 9 years ago

Lovely. The when-you-get-hit-by-an-effect code will have to be carefully relocated from Block to Object, which is the only potential problem I can foresee. Otherwise, this should work great!

Fyll commented 8 years ago

Okay, I've sorted this out. Two Roller Lizards should not kill each other now, but they can still kill you.