The bullets are going to need a tiny bit more work.
Specifically, what I mean is there should be a bullet fired animation whenever we shoot.
This is going to be a simple animation, although it needs to be in the position of the entity.
Almost specifically, it has to move along with the entity.
If we kept this one in place and move the entity, it would look really weird.
But that is all we need.
Let's implement all of it.
Once again, here we have the project and I want to keep on working in my bullets in here.
Besides the bullets, I want to create another class.
This one is called fire animation.
This one is also going to be a Sprite, although it's going to be an animated one.
But that's not going to make much of a difference.
As always, we need the init method and here we need self.
We need an entity.
We need a surface list that we're going to cycle through for the animation.
Then we need a direction.
And finally we need groups.
First of all, and here as always, we have to call super under init and pass in the groups.
Once we have that, I also want to keep the entity as an attribute.
The entity could be either a player or an enemy.
Once I have that, I want to turn the surface list into some frames.
This I am doing by simply storing them in a frames attribute.
This is going to be the surface list.
Although here we are going to have the same problem we had with the bullet image that this animation
let me show it actually in the project folder we have graphics and in there we have fire.
And these are the two animations for the bullet fire animation.
This is what I want to play.
Although as you can notice here, they are both pointing to the right.
If my player, for example, is facing to the left, this isn't helpful, which means we have to add
a tiny bit more code to flip every single frame inside of self dot frames.
And that, I think, could be a really good exercise for you.
Use list comprehension to flip every frame inside frames, although only do it if direction x is smaller
than zero.
I guess I went a bit fast here, but certain frames is just going to be a list of surfaces which should
make it easy to work with all of them so positively now.
And try this one yourself.
First of all, what we have to check is if direction X is smaller than zero, that means we are facing
to the left.
If that is the case, I want to get my frames and I want to use list comprehension.
And here I want to, let's say for frame in self frames and this should be frame for frame and self
frames.
This would literally just copy the entire list.
So this is not very helpful right now.
But what we can do with this is we can apply a method in this case PI game, dot, transform, dot,
flip and pass in the frame.
True for X and false for Y.
That way we are flipping every single frame inside of self dot frames.
The result is going to be a new list of surfaces and this is what we are assigning to self dot frames.
That way we have flipped all of them so I can get rid of the exercise text here and there we go.
Once we have that, we need to basic thing for the animation, which means we need some kind of frame
index that by default is going to be zero.
Finally, we need self taught image and this is self taught frames and in here we need self taught frame
index.
And for now, let's say for the rectangle, I just want to place self taught image dot get underscore
rect at the center of self dot entity.
So this one needs to be direct and the center.
This entity comes from this entity here, and this entity is passed in via the parameters.
That is how we are getting this data.
As a matter of fact, let's actually start using it.
That is going to be much more visual.
This is going to happen in Main Pi.
And here, first of all, I want to import my fire animation and this fire animation we are going to
create whenever anybody calls the shoot method.
So in here, I want to create a fire animation.
Now we have to get out of the arguments.
And for this, we have to get a bunch of arguments.
Let me copy them.
We are going to need all of those and let's go through them one by one.
Entity is the one we are getting from the parameters.
This is why we needed this parameter.
We didn't need it for the bullets, but I did include it earlier anyway.
And this is why surface list is what we do have to import.
This is going to if I minimize all of these methods, all of this is a bit easier to read.
Besides self-taught, polished surface.
I want to have fire surface.
And this is multiple surfaces too specifically, actually.
And since this is only going to be two, we can be a bit manual here.
All I have to do is spy game, image load and then here I need to have we have to go up on folder,
then graphics, then fire and then zero dot png.
Also, don't forget to convert alpha all of this.
This is going to give us one surface and this I want to copy.
And paste it here again.
Except now this should be one PNG.
If I showed a folder again, we are importing zero and one PNG.
That's all we do here.
I suppose to make all of this a bit cleaner, we could put it over multiple lines.
This is much easier to read.
And this via surface list I want to pass into this surface list.
And it's really important to import these fire surfaces here and not inside of this method or when we
create this fire animation.
Because, remember, importing graphics is kind of hardware intensive.
So we want to do it as little as possible.
If we are doing it right here, we are only doing it once.
If we are doing it here, we are doing it every time a bullet gets fired, which would be really bad
for performance.
All right.
But besides that direction, we still have.
And for groups, all we need is self dot all sprites.
And with that, let's actually try this and see what we get.
If I now shoot a bullet, we are getting an error because there is no attribute z.
I could have seen that one coming, but inside of bullet this is very easily fixed.
All we have to do is self dot z and then here we need layers.
And in here I want to have level.
And now we run this again.
There we go.
Now we can see a fire animation that is also pointing in the right direction.
So that's a start, but definitely not great.
This is looking very funky, but definitely something we can work with.
I guess.
First of all, this should be animated, which means I want to have an animate function that needs self
and delta time along with that.
For now, let me add pass in here.
Besides that, I also need an update method that has self and delta time.
In here.
All I really want to do for now is self-taught, animate, and this needs delta time.
And this animate basically has to do two things.
Number one, it has to animate the sprite by using these frames.
And number two, it has to destroy the Sprite once the animation is finished.
This is going to be your exercise.
You have already seen multiple times how to animate a sprite.
This one shouldn't be too difficult.
But now, instead of looping this animation, you are only playing it once.
And once you reach the end of it, you are supposed to destroy the entire object.
So possibly now.
And try to figure this one out yourself.
Let's go through it one by one.
Let me put it all the way at the bottom here.
First of all, I want to have a self doubt frame index.
That's equal, let's say 15 multiplied by Delta time.
15 is the animation speed.
Delta time is well Delta time.
And at the end of the animation, we have to set self-taught image.
It's going to be self-taught frames.
And then here we want to have the integer of self frame index.
This is more or less covering the first part, although now if this frame index becomes longer than
the length of these frames, we are just getting an error.
But instead I want to destroy the entire sprite, which means I want to run self taught frame index
is greater or equal than the length of self frames.
And if that is the case, I want to destroy the Sprite and only if that is not the case.
So else I want to update the image.
That way we are increasing this number.
If it gets too large, we are destroying the sprite.
But if it's not, then we updating the image.
That way we have an animation.
Let me get rid of the exercise text here.
And this is looking pretty good.
Let's try.
You can now see we have the fire animation.
Let me stand still.
You can see it quite well.
The only problem now is that it is in the wrong place, but that we can work on.
All we really have to do is give this one an offset and then we should be good to go.
Which means before I'm creating the rectangle, I want to do a few more things.
Let me add some comments here.
This is going to be the offset and I should generally be better with naming.
Let's call this one the position.
This one is going to be the image and all of this stuff up here.
Is going to be the setup that's looking much cleaner or the proper offset.
We are going to need an X offset and we are going to need a Y offset.
Now, in this case, I need to know if the player is facing left or right.
And let's say in this case, I want this X offset to be 60 if direction x is smaller than zero.
Which means if this one here is my player and my player is currently facing to the right, I want to
go from the centre 60 pixels to the right.
However, if my player is facing the other direction, I want to go -60 pixels, which means if this
condition is not true.
So else I want to have -60.
And a similar thing we have to do for why?
Because the player can either be standing or ducking.
If the player is standing, I want this to be ten.
If entity dot duck is true, then I want this to be -16.
All of this, I want to say in self doubt of.
This is just going to be a vector with the X offset and the Y offset.
And now when I'm placing the center, all I have to do is to add my self dot offset.
And now let's run this.
That is not great.
Something has gone wrong here, and I'm quite sure what it was.
We want to have 60 if direction is greater than zero.
This means we are facing to the right.
And then I want to have this 60.
So we're going 60 pixels to the right.
And now let's try this again.
There we go.
This is feeling much better, although we still have a problem if I move around.
The fire animation isn't exactly following the player.
The reason here is that while the fire animation isn't following the player, this animation or the
sprite, once we are creating it is not moving, but we want it to move along with the player.
And for that, we are going to need.
Let me call it move.
And here we need self and nothing else.
And there's only a single line of code needed in here.
All we have to do is self dot rec center.
It's basically going to be what we have created up here.
The difference now is we don't just want to do this once.
We want to do it multiple times as long as the thing exists.
This should be self-taught rec center.
So now, besides animating, this thing should also move.
And now let's try this.
And that is feeling much better.
Now we have a proper fire animation and we also have bullets.
That is feeling quite good.
We are definitely making progress for this game.