Continuing the last post, to fix the fighter is flipped when it goes behind another fighter. In the “fighter.py” file, create self.flip = False. And in the move() function we add an if-elif statement to check if the x-coordinate of the enemy is larger than the x-coordinate of the fighter, so self.flip is false (means not flip) and otherwise is true (means is flip). In the attack() function, we add the self.flip into the attacking_rect variable.
When you attack to another fighter from behind, the green box is appear next to the another fighter, which mean the fighter and its weapon are flipped.
Now we can load the fighters image into the game. First, you go to Coding With Russ’s Github to download the sprite sheets of warrior and wizard. In the “main.py” file, load the sprite sheets of warrior and wizard. And create the lists of warrior and wizard animation steps. Because the sprite sheets of those have 7 rows and 10 columns, but every row does not have the same number of the image. So we need to create the animation step, which means the number of the image of one row. You can see it below.
Then create the size and data of warrior and wizard. And add them to the fighter class.
The self.size equals data[0] which means the self.size equals the fighter size.
In the “fighter.py” file, create a load_images() function, need 2 arguments is sprite sheets and animation steps. And creating an empty list is animation_list. In the load_images() function, we do a for loop use the enumerate to loop over the animation steps. The y is the index of the object in the list, like the index of the first object in the list is 0, and the animation is the value of the index, like in the warrior animation steps list [10, 8, 1, 7, 7, 3, 7], the value of the first object in the list is 10 so the animation is 10.
Create another empty list is temp_image_list. And use the for loop to loop the animation. In the for loop, create a temp image variable using the subsurface the sprite sheets. In the subsurface, the first two parameters are the x and the y which is the position of the image in the sprite sheets, and the last two are the size of the image. x is 0 times self.size equal 0 and y is 0 times self.size equal 0, so we start from the (0,0) and the last two parameters is equal self.size, so we got the first image in the first row in sprite sheets.
We got the first image and added it into the temp_image_list. And it will loop again to get the next image. the x right now is 1 times self.size equals the self.size and the y still 0 times the self.size. So the position is still on the first row but it goes to the next image. You can see it below.
And it will loop over the first row, and when over the first row, it will add the temp_image_list into the animation_list. And the y become 1 and loops the second row. And it will loop every image in the sprite sheets. We create self.animation_list equals self.load_images, and self.image equals self.animation_list. In the draw() function, add the blit() method.
After you run the code, the fighters appear on the screen game.
But the size of the fighters is too small, so to fix that we create scales for the warrior and wizard in the “main.py” file. And in the “fighter.py”, create a variable is self.image_scale =data[1]. And when adding an image to temp_image_list we use the scale to make it bigger.
The position of the fighter is wrong, but the size is right. So we just fix the position of the fighter to make it in the right spot. In the “main.py”, create the warrior and wizard offset. And go to the “fighter.py”, the self.offset equal data[2]. And in the blit() method, add the self.offset into that method to make the fighter in the right spot.
After you run the code, the fighters are in the right spot.
But when the fighter is behind the enemy, it does not face the enemy. We use the flip() method to fix this problem. In the draw() function, create a img variable that uses the flip() method and in the blit() method, just replace the self.image to img.
This is before you added the code.
And this is after you added the code.
But have the problem that the wizard (the fighter on the left) is not facing to the warrior.
To make that, we make the self.flip equal flip. And when we call it, just add False for the warrior and True for the wizard.
After you run the code, the fighters will face each other.
Now we animation the fighters. We use the pygame.time.get_ticks() to make the fighters animate. This function gives a time which has been running in milliseconds. In the def __init__ of Fighter class, create self.update_time equal pygame.time.get_ticks(). And create a update() function, create a variable animation cooldown = 50 and write if-elif statement to check if the pygame.time.get_ticks() minus the self.update_time is larger than animate cooldown, so the self.frame_index plus 1 and self.update_time equal pygame.time.get_ticks(). And just call this function in the “main.py” file.
You can see how it animates below.
But we have an error that the self.frame_index is index out of range when we run the code. We add more if-elif statement to check if self.frame_index is larger or equal to the length of self.animation_list[self.action], the self.frame_index is equal 0.
Running
To make the fighter can animated running like the image above. Create the update_action() function, need 1 argument is new_action. In this function, if new_action is not equal to self.action, self.action equals new_action and self.frame_index = 0. The self.action is 0 the fighter is standing, 1 is running, 2 is jump, 3 is attack type 1, 4 is attack type 2, 5 the fighters get hit, and 6 is dead. In the update() function, add an if-elif statement, if self.running is True, self.update_action(1) and otherwise the self.update_action(0).
Jumping
When the fighter jumps, it will look like the image below. it just animates standing when it jumps.
To make the fighter animated when it’s jumping, just do like the running add an if-elif to check if self.jump is True, self.update_action(2). Because 2 is jump.
And this how it animated after you added the if-elif statement.
Attack
Just like the running and jumping, we just add an if statement. But attack has 2 types of attack, so on move() function, the self.attack_type is 0. And in update() function, check if attacking is true, check if self.attack_type is 1 so the self.update_action(3) and if self.attack_type is 2 so the self.update_action(4).
But we have one problem: when we hold the “r” or “t”, the fighter will keep attacking and not stop. You can see it below.
To fix this, in the if statement check if the frame_index is out of range, we add one more if statement to check if self.action is 3 or 4, the self.attacking is False. The fighter will attack and wait a second, and it can attack again when you run the code.
Hit
Now we can animate the fighter when it got hit by another fighter. Just like another action, add an if statement to check if self.hit is true, so the self.update_action(5). And in attack() function, in the if statement is checked does the fighter’s weapon collide with the enemy. We add target.hit is true.
But like you see in the video above, the enemy just got hit again and again. In the if it is checked the frame_index, add more if statement to check if self.action is 5, the self.hit is False, self.attacking is False, and self.attack_cooldown is 20.
When you run the code, the problem is fixed. This is what I’m doing today by following Coding With Russ’s tutorial. I will finish this game in my next blog post.
No Responses