Fighting Game AI Tutorial
Ok a lot of people have been asking me to do this so I am posting it here. Please tell me if you find any errors.
Artificial programming is one of the most difficult things you can program and I only recommend attempting this if you are good at programming in scratch.
The AI in this tutorial should act like the computer controlled player in my project Merry Smashmas.
STEP 1:BASIC MOVEMENT
You can find a project that uses the codes in this tutorial as well as codes from Sprite Movement Done Right @ http://scratch.mit.edu/projects/archmage/76272
For realistic movement see Sprite movement Done Right. It is important that you do this because this tutorial will focus on moving velocity variables instead of directly moving x and y positions.
Sprite Movement Done Right http://scratch.mit.edu/projects/archmage/72848
Ok, before we make the computer controlled player attack we have to make it so that the sprite chases the player’s sprite.
We will refer to the human controlled sprite as player1 and the AI controlled sprite as player2.
So put in this code in the AI controlled sprite.
<when green flag clicked>
<forever>
<if> << <( <abs( (( <x position><-> <x position> of player1 )) <<> 50 )> >>
<set{ nearPlayer }to(1
<else>
<set{ nearPlayer} to (0
<if> <(<< <{ xVelocity }> <<> <{ maxVelocity }> <and> <( <{ nearPlayer }> <=> 0 )> >>)>
<if><( <x position> <>> <x position> of player1 )>
<change{ xVelocity }by( (( <{ accelCPU }> <*> -1 ))
<else>
<change{ xVelocity }by( ( <{ accelCPU }> )
<if> << <( <y position> <<> (( <y position> of player1 <-> 50 )) )> <and> <touching[ ground >>
<change{ yVelocity }by( 15
<if> <( <{ xVelocity }> <>> 0 )>
<point in direction( 90
<else>
<point in direction( -90
Now I will explain what this code does.
Firstly, there should be 5 local variables in the player2 sprite.
xVelocity-controls horizontal movement
yVelocity-controls vertical movement
maxVelocity- set the maximum value for the xVelocity variable
nearPlayer- used to tell if the sprite is near player1
accelCPU- sets the acceleration for the sprite
if> << <( <abs( (( <x position><-> <x position> of player1 )) <<> 50 )> >>
<set{ nearPlayer }to(1
<else>
<set{ nearPlayer} to (0
This sets the nearPlayer variable. If nearPlayer equals 1 then the sprite is near player1 if nearPlayer equals 0 then it is not near player1. The code checks to see if the 2 sprites are less than 50 units away horizontally.
<if> <(<< <{ xVelocity }> <<> <{ maxVelocity }> <and> <( <{ nearPlayer }> <=> 0 )> >>)>
<if><( <x position> <>> <x position> of player1 )>
<change{ xVelocity }by( (( <{ accelCPU }> <*> -1 ))
<else>
<change{ xVelocity }by( ( <{ accelCPU }> )
This code will only execute if it has not passed the sprite’s max velocity and if it is not near the player. If player1 is left of the sprite it decreases the xVelocity which will make the sprite move left. If player1 is right of the sprite it increases the xVelocity which will make the sprite move right.
<if> << <( <y position> <<> (( <y position> of player1 <+> 50 )) )> <and> <touching[ ground >>
<change{ yVelocity }by( 15
This will cause the sprite to “jump" if the yposition of player1 is 50 units greater than the yposition of the player2 sprite. The sprite must also be touching the ground sprite in order to jump.
<if> <( <{ xVelocity }> <>> 0 )>
<point in direction( 90
<else>
<point in direction( -90
This script will make the sprite face right if it is moving right and face left if it is moving left.
Thats the end of step 1. I'll continue this later.
Last edited by archmage (2008-01-05 16:04:55)
Offline
STEP 2: DEALING DAMMAGE
Find the project file for this part @ http://scratch.mit.edu/projects/archmage/76631
Now that your AI controlled sprite can move you will want it do deal damage.
To do this put the following code on the player2 sprite.
<when green flag clicked>
<set{ health }to( 100
<switch to costume[ idle
<forever if> <( <{ nearPlayer }> <=> 1 )>
<switch to costume[ idle
<wait( 0.1 )secsc>
<set{ attacking }to( 1
<switch to costume[ attack
<wait(0.1)secsc>
<switch to costume[ idle
<set{ attacking }to( 0
<wait( 0.3 )secsc>
<when green flag clicked>
<forever if> << <touching[ player1 <and> <( <{ attacking }> of player1 <=> 1 )> >>
<change{ health }by( -5
<wait( 0.2 )secsc>
And put this code on the player 1 sprite.
<when green flag clicked>
<set{ health }to( 100
<switch to costume[ idle
<forever if> <( <key[ space ]pressed?> )>
<switch to costume[ idle
<wait( 0.1 )secsc>
<set{ attacking }to( 1
<switch to costume[ attack
<wait(0.1)secsc>
<switch to costume[ idle
<set{ attacking }to( 0
<wait( 0.3 )secsc>
<when green flag clicked>
<forever if> << <touching[ player2 <and> <( <{ attacking }> of player2 <=> 1 )> >>
<change{ health }by( -5
<wait( 0.2 )secsc>
Variables that are needed for this part on both sprites are
health- set the health for each player which will decrease as damage is taken
attacking- used to check if a sprite is attacking
Now for the code explanation
<when green flag clicked>
<set{ health }to( 100
<switch to costume[ idle
<forever if> <( <{ nearPlayer }> <=> 1 )>
<switch to costume[ idle
<wait( 0.1 )secsc>
<set{ attacking }to( 1
<switch to costume[ attack
<wait(0.1)secsc>
<switch to costume[ idle
<set{ attacking }to( 0
<wait( 0.3 )secsc>
The first thing this code does is set the health variable to 100 and sets the costume to the idle costume. Next, if the the sprite is near the player it will go into the attacking sequence. In the attacking sequence the costume is first set to idle then the attacking variable is set to 1 then the costume is set back to idle and the attacking variables goes to 0 again, also there is a small 0.1 second break between each costume change and a 0.3 second break at the end of the loop to prevent rapid attacks.
<when green flag clicked>
<forever if> << <touching[ player2 <and> <( <{ attacking }> of player2 <=> 1 )> >>
<change{ health }by( -5
<wait( 0.2 )secsc>
All this code does is check to see if the opposing sprite has it's attacking variable set to 1 and is touching the sprite. If the condition is true then the sprite's health variable decreases.
And the scripts on the player1 sprite have similar functions except that the attack sequence is executed when the space bar is pressed.
So now what you should have is a opponent that attacks whenever it comes close to it's opponent. It is impossible to beat this opponent so next I will tell you how to create a reaction time for the computer controled player.
Last edited by archmage (2008-01-05 16:00:10)
Offline
STEP 3: REACTION TIME
To see a demonstration of the programming used in this tutorial go to http://scratch.mit.edu/projects/archmage/78621
Ok, if you did everything correctly you should an opponent that attacks every time it gets close enough to the human player. At this point the opponent will be impossible to beat because it attacks right away and doesn't give any time for the human player to attack.
To fix this we must give our AI a delay before it can attack.
We do this using the following codes.
First alter the main attacking code of the AI sprite to look like this.
This has a new variable called randomAction put in.
<when green flag clicked>
<set{ health }to( 100
<switch to costume[ idle
<forever if> << <( <{ nearPlayer }> <=> 1 )> <and> <( <{ randomAction }> <=> 1 )> >>
<switch to costume[ idle
<wait( 0.1 )secsc>
<set{ attacking }to( 1
<switch to costume[ attack
<wait(0.1)secsc>
<switch to costume[ idle
<set{ attacking }to( 0
<wait( 0.3 )secsc>
<when green flag clicked>
<set{ reactionDelay }to( 10
<forever>
<set{ randomAction }to( <pick random( 1 )to( reactionDelay
<wait( 0.1 )secsc>
Now for an explanation of the code.
<when green flag clicked>
<set{ health }to( 100
<switch to costume[ idle
<forever if> << <( <{ nearPlayer }> <=> 1 )> <and> <( <{ nearPlayer }>randomAction <=> 1 )> >>
We altered this part so that the AI will not constantly attack 100% of the time. Instead it will only execute the fighting code when the randomAction variable is equal to one and in the code below we will be able to control how ofter the randomAction variable equals one.
<when green flag clicked>
<set{ reactionDelay }to( 10
<forever>
<set{ randomAction }to( <pick random( 1 )to( reactionDelay
<wait( 0.1 )secsc>
This code is used to control how likely it is that the randomAction variable is equal to one using the reactionDelay variable. Every time the code in the forever block executes it sets the randomAction variable to any whole number from 1 to the reactionDelay variable which we have set to ten. The AI's attack delay time can be set using the reactionDelay variable. If the reactionDelay variable is set to a higher number the AI's reaction time will be slower and if the reactionDelay variable is set to a lower number the AI's reaction time will be faster.
And now you have a fully functional AI
If you feel that have left anything out or that I have made a mistake please post in this thread and let me know
Last edited by archmage (2008-01-11 12:21:08)
Offline
I am now programming this program demonstrated in this tutorial myself. Let up finish it then you can look at it in action.
Offline
lyssa295 wrote:
Can i help make it? I am pretty good at programming
Help make what?
Offline
lyssa295 wrote:
the game
I don't know what game you are talking about
Offline
I don't really need any help writing the tutorial but if you think there is something that I should have included that I didn't include you can tell me
Offline
Lucario621 wrote:
Ok, I admit I can read most of it but 2 things. number 1 is that to me it kinda looks not very clear though clear enough to read. Number 2 is when is says in the second part explained:
Change x velocity by: (accelcpu multiplied by ___)
All it says there is well, nothing,so what goes there? also what do you set the variables maxVelocity and accelCPU to?
Hey dude, can you reply to this or what?
Offline
Lucario621 wrote:
Lucario621 wrote:
Ok, I admit I can read most of it but 2 things. number 1 is that to me it kinda looks not very clear though clear enough to read. Number 2 is when is says in the second part explained:
Change x velocity by: (accelcpu multiplied by ___)
All it says there is well, nothing,so what goes there? also what do you set the variables maxVelocity and accelCPU to?Hey dude, can you reply to this or what?
Well I think here when it says accelCPU multiplied by, the picture is hiding the number
Offline
Well I can see it just fine. But if you can't see it just download the demo project and you can look at all the scripts.
Offline
Hey, you should follow how the real smash bros game works, not just dealing damage, the more damage then more change of x velocity of other player when you attack him. And if he has over 300 damage you will do a super more powerful attack than usual and 100% chance 1 hit K.O.
Offline
Lucario621 wrote:
Hey, you should follow how the real smash bros game works, not just dealing damage, the more damage then more change of x velocity of other player when you attack him. And if he has over 300 damage you will do a super more powerful attack than usual and 100% chance 1 hit K.O.
Actually in Merry Smashmas I didn't even alter the x and y velocity variables to make them fly. What I did was make the sprite point towards the opponent and I used the move block to move them by a variable that was saved as their current dammage * -1. This variable which I called smashedPwr was constantly increased until it equaled 0.
This is not a smash bros tutorial so I decided to use health like most traditional fighting games.
Last edited by archmage (2008-01-06 12:33:09)
Offline
JSO wrote:
Archmage - i really like this way of tutorials...
Thanks
I try to be as clear as possible.
Offline
<if> <( <{ xVelocity }> <>> 0 )>
<point in direction( 90
<else>
<point in direction( -90
This script will make the sprite face right if it is moving right and face left if it is moving left.
Thats the end of step 1. I'll continue this later.
If you are pointing direction -90, than wouldn't you be upside down?
Offline
Lucario621 wrote:
<if> <( <{ xVelocity }> <>> 0 )>
<point in direction( 90
<else>
<point in direction( -90
This script will make the sprite face right if it is moving right and face left if it is moving left.
Thats the end of step 1. I'll continue this later.If you are pointing direction -90, than wouldn't you be upside down?
You have to select left and right directions only.
Last edited by archmage (2008-01-08 15:57:58)
Offline
Lucario621 wrote:
P.S. You have horrible handwriting.
I wouldn't say that if I were you.
That was written on the computer.
Lucario621 wrote:
Number 2 is when is says in the second part explained:
Change x velocity by: (accelcpu multiplied by ___)
All it says there is well, nothing,so what goes there? also what do you set the variables maxVelocity and accelCPU to?
When you multiply a number, e.g., 5, by -1, the number gets reversed: 5 changes to -5.
That makes the sprite either increase it's xVelocity (Change x velocity by: accelCPU) or decrease (Change x velocity by: accelcpu multiplied by -1), i.e. move right or left.
Offline