Archived

This topic is now archived and is closed to further replies.

Dravidian Kayne

Street Fighter style issues

Recommended Posts

Okay I''ve decided to impliment a street-fighter style fighting system implimented into my RPG. Basically you use spells, attacks, and what-not by doing a key-command. The key command must be performed within a certain amount of time (say 1/4 or 1/2 a second). If in that time you press an order of keys, you do a special attack. Now here''s my problem...how can I write code to allow for errors in input and still perform the action? For instance, in a street fighter game, a hadoken was done by pressing DOWN-DOWNFORWARD-FORWARD then a punch. However, if your first command was slightly to the right of down, or the last was a little high, it would still perform the hadoken. Another that is more complex, an uppercut was FORWARD-DOWN-DOWNFORWARD. If you ever played practice in more recent street fighters, you could turn on a feature which showed your input. You''d notice that you would do the command and about 3-5 extra buttons were inputed that you didn''t intend, yet it still performed the command. How do they do this? Does anyone know of a not-too-complex way to handle this? I think I might be able to design a way in a couple thousand lines of code, but it seems like a waste of time and file size for something that probably could be done simpler. Thanks. Dravidian Kayne~

Share this post


Link to post
Share on other sites
If it's the way you describe, there's a couple of ways you can go about it.

The simplest possible way is to define a range:-

So imagine if you are expecting the 'G' key to be pressed- you could add a form of tollerance to the nearby keys..

So G is your ideal key, give it the value of 1.

F and H are nearby, they're likely to be pressed in a hurry - on the same normalised scale they would have the range of say, 0.75 (or higher, I'm just guessing here - you'd probably want to calculate the range based on a normal distribution). TY and VB are also likely keystrikes - they could have a value of say 0.5 (NOTE: these are purley made up and you WILL want to experiment)

So:- you want the G key pressed 3 times - your ideal is 3 (normalised to 1).

But you get GHG = ((1 + 0.75 + 1)/3 = 0.92: Your entered keypress was 92% likely to be what you wanted. If you gave your player 80% accuracy then this press would succeed.

GGG = 100% (Success at 80% tollerance)
GHG = 92% (Fail at 80%)
GFT = ((1+ 0.75 + 0.5)) = 75% (Fail at 80%)

Obviously this means you'll have to have a map of tollerances for each key (perhaps you could determine them based on the ASCII value? eg asc('G') -/+ 1 = 75% likely.

This is perhaps how I'd do it, there's probably better ones around though. Hope this has prompted some thought.


[edited by - downgraded on May 26, 2004 4:12:04 AM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Why not have a "master" key and a few "apprentice" keys defined? So, like the other poster said, G as the master and F and H as the apprentice ones and use a simple rule like:

"User can press two or three apprentice keys per combination, as long as the keys are not pressed in a sequence."

If the keycombo is GACK, this would mean HACK, HACL, GAVK are OK, but HSCK, GAVL, GSXK are not. Then depending on the key combo lenght you define the margin of error in number of allowed wrong keys. Might be easier than calculating percentages.

Also some testing might provide you with good feedback as to which mistypings are common and which ones are not. That would help you reduce the number of apprentice keys even more, especially since missing keys is often related to where the hand position was before the combo was started.

Share this post


Link to post
Share on other sites
I think I would try this on a timing basis. I.e if you are allowing 1 second to complete the entire command then you would want each key of the command to be pressed in sequence within this time.

I would suggest some kind of pattern matching. i.e. if you press DOWN you could feasibly go into either a Hadoken or Dragon Punch depending upon your next command. You know you have around 1 second to complete the entire move, and if there are three keys in the command, that means you should expect to see the other two keys within this time and in the correct sequence. If you do then the move can be executed, if not then reset the timer.

Or, thinking about it - you could perform a check every few frames over the last few commands entered. lets say the user did the following:
U,L,L,U,D,L,D,DF,F

Every now and then the system would check over these commands and try to match them against the pattern D,DF,F for the Hadoken, which in this example would be encountered at the end.
Also, you could allow a certain number of ''noise'' keys inbetween each key actually contributing to the overall command. i.e.
D,L,DF,U,F could still be counted as a Hadoken if you allow one ''noise'' key inbetween the good ones.

I hope this makes sense! It''s a lot harder to describe than I thought....

Share this post


Link to post
Share on other sites
Thanks for the responses. However I''m not planning on using the Keyboard (although it is an option, so all those methods will have to be researched). My plan is to use a controller. So it would literally be like a street fighter. You''d press Forward (i.e.:Left), then Down, then Down-Forward to perform an uppercut. So how would it be done like that? Using the examples above together I could come up with something like (based on a 3-input command): (Note: I decided to use degrees for calculations)

Command 1:
-Forward = 0;
-Else = 180;

Command 2:
-Down = -90;
-Down-Forward = -45;
-Down-Backward = -135;
-Else = 0;

Command 3:
-Down-Forward = -45;
-Forward = 0;
-Down = -90;
-Else = 0;

When the user presses the first command, it sets the timer to 0. Then narrow down the possibilities of commands available by the input of the first command. If user presses Forward, then narrow to the list of all commands beginning with Forward. The next command narrows down the list to any command in the range of -45 to -135. The final command singles out the one command available that has a range from 0 to -90 for the last input. A timer check will be made with EVERY input. If the timer is above 1 second, then it resets the timer to 0 and sets that command as the first command. Get it?

Tell me if this sounds like a good way to go about it.

Dravidian Kayne~

Share this post


Link to post
Share on other sites
The difference between the keyboard and the joypad is not as much as you might expect. Once you have the input actualy working (using DirectInput or whatever) you simply need to map that input to the commands. You might define functions to read the input, like so....

if (Keyboard(DIR_LEFT) || (JoyPad(DIR_LEFT))
{
> LEFT command entered
}

I think the implementation you describe is about right. However you need to be careful when resetting the timer. If you simply reset it every 1 second or every time you press DOWN this will mess it all up. Some commands might have DOWN in the middle of them, and you don''t want to reset it then!

You might want to store commands in a list until they hit a certain age. For example, you might store them as a string like so: U,D,L,D,L,U,D,DF,F,U,D...
And check every few frames or so that the oldest command in the list is still more recent than 1 second... This way, if you do match a pattern to a command you know it was executed within 1 second....

Perhaps....

Share this post


Link to post
Share on other sites
Something I posted a while ago regarding a similar question:

What about coding a movie trainer? Make a program where you edit moves for your game, by definying a key sequence/combination. Then, add a "training" feature to your program, that allows you to try to perform the move many, many times.

Have your program record the ways you peformed the moves, and add use that data to adjust timing between keys, or even if a certain key in the sequence in mandatory or not (thus creating shortcuts).

That way you won''t wast so much time editing moves by hand, since you can build a small human input database for each move.

Share this post


Link to post
Share on other sites
The trick is not to pay attention to buttons in-between buttons.

Keep a list of the last 10 or so buttons pressed, with the time they were pressed included. When the player presses a trigger button (punch, kick), run through the list backwards and check the keys. Check for the last sequence direction first, then search for the next-to-last. Compare the times in-between the keys, but don't pay attention to keys not included in the sequence.

For example, in the sequence B,B,F: Check for "Forward" first, then make sure "Back" was pressed before it within the time limit, then make sure "Back" was pressed again before it within the time limit. Don't bother checking other buttons. Only pay attention to the buttons in the sequence you're checking.

Always check your sequences from hardest to easiest. Check "F,D,DF,F" before "D,DF,F". Because the latter would be included in the first.

[edited by - Jiia on May 28, 2004 4:18:12 PM]

Share this post


Link to post
Share on other sites
Please, for the love of god, don''t do a Street Fighter game on the keyboard. I mean, fighting games on the keyboard are fine, but the SF rolls are impossible. Play One Must Fall 2097 to see how painful it is. Arcade sticks and gamepads are not optional for hadokens.

What I would recommend is a command system that works based on tapped sequences to do spells and items. For example, Evil Zone and Destrega for PSOne. Those games work by sequences, where you tap back + back + attack to do a super.

Alternately, there is Tongue of the Fatman for old (386) PC. Simple fighting game, no rolls or specials, just punches, and an inventory. So, you had the attack key, some inventory keys. Between fights you''d purchase equipment for your inventory, like throwing knives, electric knuckles, or landmines.

But please, please avoid hadoken keys on the keyboard. It just hurts too much.

Share this post


Link to post
Share on other sites
quote:
Original post by Jiia
The trick is not to pay attention to buttons in-between buttons.

Keep a list of the last 10 or so buttons pressed, with the time they were pressed included. When the player presses a trigger button (punch, kick), run through the list backwards and check the keys. Check for the last sequence direction first, then search for the next-to-last. Compare the times in-between the keys, but don''t pay attention to keys not included in the sequence.

This is, so far, the best solution posted. Buffer the buttons pressed, and check if it contains a move or not. So you could do something like this:

const ButtonBuffer HADOKEN_MOVE("D","DF","F");

if ( buttons_pressed.contains(HADOKEN_MOVE) )
{
   // do hadoken
}

Share this post


Link to post
Share on other sites