I'm trying to make a beat-em-up style game in the vien of the old TMNT arcade games.
I've made good progress on the character movement engine, I've even got a rudimentary combo system in place, but I'm going to have to start working on enemy movement soon, and I really don't know where to even start. I was wondering if anyone could give me any pointers or advice on where to start, or point me in the direction of an apropriate article that might help me get started.
After thinking about it a bit, I imagine I'm going to have to program different states for the enemies to be in, one for analizing whether or not there's an openining to attack available and which player to attack, one for moving into position to attack, one for actaully attacking, one for retreat if the situation warrants it etc.
The main one that I'm stuck on conceptually, (I don't even have MMF in front of me right now, I'm at work just pondering this over) is the analyzing. So for instance it's set up so that one enemy can line up on either end of the player to attack, and two more can flank either side to wait for an opening. How would I have the program determine if there're any enemies, and how many, already attacking the character?
Basically, I'm asking how I would go about assigning states to characters (most likely event groups that are inactive/active) and how to have a character check what state other characters are in.
You could use a separate counter labeled "attackInProgress" or something like that, and when an enemy decides to attack, set it to 1. When he's knocked out or retreats, or the player moves out of range or whatever, set it to 0. Have the other enemies check the counter each cycle to see if the player is open for attack. If the counter is set to 1, they wait. If it's 0, they move in.
If you want to get complicated, have two counters, one each for the left and right flank of the player. If an enemy is waiting to attack, he can check both counters, and if one is open he can move into position.
As far as positioning the enemies when they're waiting, you could have a set of invisible targets set up that follow the player's position (say, forming the four courners of a square around him). If the enemy is in "waiting" mode, he can seek out the nearest target and stick to it. That way he'll be in position when a slot opens for attack.
At least, that's how I'd try it. I'm sure there are a hundred different ways.
That's pretty much what I had in mind. I could have six targets around the character and flags for each one.
I'll probably have to download the Isometric extension and one of the Pathfinding ones...
(my old version of TGF doesn't have any of these newfangled extensions, and I haven't ordered the new MMF yet, I'm just working with the demo at the moment)
Would the Isometric extension help when I want them to be able to move at the X axis at a faster rate than they can move through the Y axis? (which as much as I can figure it kinda fakes into a Z axis...) Or would I be better off keeping the movement customized?
The ISO ext. is for making games in an iso view similar to the Strike Series (Desert Strike, Jungle Strike) or the Final Fantasy Tactics.
I'm not really sure if you could get it to work for a beat em up, but I think that a perspective like that would seriously hamper your game. Either way, good luck on it duder.
Yeah, isometric would definitely not work for a beat-em up like TMNT. I'm not terribly familiar with TGF, but I know there's a tutorial around somewhere for MMF1.5 that shows how to layer active objects based on thier Y coordinate. That's what you need.
Edit:
What I mean to say is, the tutorial is about showing an object "in front" of another object if it's Y coordinate is higher, and "in back" if it's Y coordinate is lower. I'm pretty sure you can do it easily with layer.cox, but I don't know if there's a TGF version.
From what I udnerstand there's a rather simple Layer extension for MMF that'd take care of that part easilly so I'm not too concerned with that.
I'm more concerned about the enemies moving around at a different rate on the X and Y axis, I could program this easilly, but I'm not sure how I'd do this and implement some sort of pathfinding so they don't walk through each other.
And how would I have a monster check whether there is a target location without a flipped flag? Is there a command or function for this? I'm not familiar with how to achieve this.
Have the AI shoot a bigish detector and set any flag of the enemy to on.
Flag(x) of Enemy = on AND Detector is overlapping Enemy AND Detector is overlapping Player AND Player Flag is Off(the flag for determining if person can be hit or not).
The above event is a bit wierd, and it does kind of exploit some bugs in CT products, but it works even in a huge group of enemies.
I'm not the greatest at explaining things, so let me know if you're confused.
You'd keep the enemies from walking through each other the same way you'd keep them from walking through walls, I guess. Make a collision box for them. Only, instead of around the entire enemy, just put it around thier feet, like this:
That way, Johan Von Kakhipants won't bump into Pimpy McPurplepants, or whatever other pallette-swapped characters you might have.
Like Fred Redtrousers, maybe. Or Billy O'Greenjeans. Who knows. Just so long as it's the same character with a different colored outfit, you're fine. It's the mark of a truly authentic beat-em up.
Hah, I LOVE the feather. I'm sure the feet marker can help, but what I'm unsure about is how to make them actually try to walk around the other character instead of just stopping.
Perhaps I could have another mode for the AI where they step back and move to the side and then try again.
I think you're overthinking this "pathfinding" issue. I don't think it's as hard as you're thinking it's going to be.
Let's say enemy A is directly behind enemy B, and enemy B is attacking the player from the right, then enemy A will be looking for a waiting target. Let's say he picks the top right target. He tries to move left and up. So first he tries to move left, and is blocked by B. Then he moves up. Then he tries to move left, and is blocked by B again. Then he moves up. Now he tries to move left and, whaddaya know, he's not blocked any more, so he moves left. Then he moves up. Now he's even with the target, so he moves left but not up. Pretty simple, really. Requires no pathfinding, and you don't have to stop him. Just restrict his movements.
Just about every beat-em up game I've ever played behaves pretty much like that. Except for special enemies that just plow through everything, that is.
By a route obscure and lonely,
Haunted by ill angels only,
Where an Eidolon, named night,
On a black throne reigns upright,
I have reached these lands but newly
From an ultimate dim Thule
From a wild clime that lieth, sublime,
Out of space
Out of time.
Boy, I haven't even gotten to making them move and I've already got a problem.
I'm having one object act as a sensor for the enemies, and there's another object on top of it which is the visible graphic, but doesn't actually interact with anything.
The problem is that any time I need to change the animation for the graphic (for instance when the enemy gets hit) the graphic changes for every single instance of the enemy if there are more than one on the screen.
By a route obscure and lonely,
Haunted by ill angels only,
Where an Eidolon, named night,
On a black throne reigns upright,
I have reached these lands but newly
From an ultimate dim Thule
From a wild clime that lieth, sublime,
Out of space
Out of time.
By a route obscure and lonely,
Haunted by ill angels only,
Where an Eidolon, named night,
On a black throne reigns upright,
I have reached these lands but newly
From an ultimate dim Thule
From a wild clime that lieth, sublime,
Out of space
Out of time.
Check out one of the many tutorials on "spread values." Do a search here, and on the clickteam boards. You will find the answers you seek. I had this same question just last week when my enemies had messed up gravity. When one enemy would land, all the other enemies that were falling would stop in midair because when one enemy's falling flag needed to be turned off, MMF was turning off all of them.
You'll need the fastloop object for this. Basically, you need to make a loop for each type of enemy. The loop will run once for every enemy. To distinguish each enemy as an individual, you need to index each with a unique number. This is where spread values come in. Basically, it breaks down like this:
Let's say you have an enemy named Bob. There are three Bobs on the screen, and each should have it's own action, animation, life guage, etc.
1. Make a counter called "bobCounter." This will keep track of the current Bob that the loop is working on. Before the beginning of every loop, set it to ZERO.
2. Name an Alterable Value in your enemy properties to "spread" or "index" or something like that, so you can keep track of what Alt Value it is easily. This is where you will store each enemy's unique identifying number.
3. Start your fastloop like so:
* Always
- Start Loop #1 for NObjects("Bob") loop(s)
This will run your loop once for every instance of "Bob" in your frame. Loop #1 is just an example, you can use whatever number.
4. At the beginning of every loop, use this command:
* Fast Loop object: Loop Trigger #1
- Spread value 0 into Alterable Value "index" of Bob
You can find the Spread Value command under the Alterable Values section. Anyway, when you tell MMF to "Spread value 0," what it's doing is assigning a number to each Bob in the order that it was created, starting with zero. So now each of your Bobs has a different number in it's Alt Value "index." They're now labeled 0, 1 and 2. If you change the command to another number, like "Spread value 2," it will number each of your Bobs starting with 2 so you'd have Bobs 2, 3 and 4. Hope that doesn't confuse you. Let's just stick with "Spread value 0."
5. Now, whenever you perform any action or change any data in one of your Bobs, you need to tell MMF specifically which Bob it's working on. That's where the counter comes in. Since you set it to zero before the loop began, it will start working on Bob 0 first, and only Bob 0, as long as you do this:
* Fast Loop object: Loop Trigger #1
* Alt Value "index" of Bob = value(bobCounter)
- (check for collisions, scan for an opening, punch, move, change animation, yaddayadda whatever)
Now when you tell Bob to change animation, the only Bob changing animation is the Bob who's index number matches the current number in the bobCounter. Which brings us to
6. At the end of your loop, add 1 to bobCounter. Then the loop starts over, and begins work on the next Bob. That's it.
Hope this helps, and that I wasn't too confusing. Just search for those tuts and check them out. Good luck...
I was wondering that, actually. It didn't seem necessary to do the spread value command inside of the loop, but one of the tutorials I read had it set up that way. Oh well, it doesn't make much difference, I guess.
By a route obscure and lonely,
Haunted by ill angels only,
Where an Eidolon, named night,
On a black throne reigns upright,
I have reached these lands but newly
From an ultimate dim Thule
From a wild clime that lieth, sublime,
Out of space
Out of time.