Enemies
Subscribe to Tech with Tim
In this tutorial we will be creating enemies that can move around the screen following a predefined path.
IMPORTANT You will need to download the images below before starting.
Images
If you have been following since the first tutorial you should already have these images, if not please download them from one of the options below.
GitHub: Click Here!
Download Zip:
Please ensure you place these images in the same directory as your python script.
Note: The folder you downloaded has the images and assets for the entire finished game. The images that we will be working with in this tutorial end in an E.png
Loading Images
The following lists will be used a class variables to store our images for the enemy. We will place these lists inside of a class that we create in the next step.
walkRight = [pygame.image.load('R1E.png'), pygame.image.load('R2E.png'), pygame.image.load('R3E.png'), pygame.image.load('R4E.png'), pygame.image.load('R5E.png'), pygame.image.load('R6E.png'), pygame.image.load('R7E.png'), pygame.image.load('R8E.png'), pygame.image.load('R9E.png'), pygame.image.load('R10E.png'), pygame.image.load('R11E.png')] walkLeft = [pygame.image.load('L1E.png'), pygame.image.load('L2E.png'), pygame.image.load('L3E.png'), pygame.image.load('L4E.png'), pygame.image.load('L5E.png'), pygame.image.load('L6E.png'), pygame.image.load('L7E.png'), pygame.image.load('L8E.png'), pygame.image.load('L9E.png'), pygame.image.load('L10E.png'), pygame.image.load('L11E.png')]
Enemy Class
Like we've done in the previous tutorials we will use a class to create our enemy. We will start by pasting the code from above into our class. Then we will create the init method and set up some basic attributes for our enemy.
class enemy(object): walkRight = [pygame.image.load('R1E.png'), pygame.image.load('R2E.png'), pygame.image.load('R3E.png'), pygame.image.load('R4E.png'), pygame.image.load('R5E.png'), pygame.image.load('R6E.png'), pygame.image.load('R7E.png'), pygame.image.load('R8E.png'), pygame.image.load('R9E.png'), pygame.image.load('R10E.png'), pygame.image.load('R11E.png')] walkLeft = [pygame.image.load('L1E.png'), pygame.image.load('L2E.png'), pygame.image.load('L3E.png'), pygame.image.load('L4E.png'), pygame.image.load('L5E.png'), pygame.image.load('L6E.png'), pygame.image.load('L7E.png'), pygame.image.load('L8E.png'), pygame.image.load('L9E.png'), pygame.image.load('L10E.png'), pygame.image.load('L11E.png')] def __init__(self, x, y, width, height, end): self.x = x self.y = y self.width = width self.height = height self.path = [x, end] # This will define where our enemy starts and finishes their path. self.walkCount = 0 self.vel = 3
The next method we will add will be the draw() method. This will work similarly to our player classes draw method as we will also be doing animation in here.
# Goes inside the enemy class def draw(self, win): self.move() if self.walkCount + 1 >= 33: # Since we have 11 images for each animtion our upper bound is 33. # We will show each image for 3 frames. 3 x 11 = 33. self.walkCount = 0 if self.vel > 0: # If we are moving to the right we will display our walkRight images win.blit(self.walkRight[self.walkCount//3], (self.x,self.y)) self.walkCount += 1 else: # Otherwise we will display the walkLeft images win.blit(self.walkLeft[self.walkCount//3], (self.x,self.y)) self.walkCount += 1
The next method we add will be the move() method. This will move our enemy every frame. Since we want our enemy to be moving along a path we must figure out how much to move the enemy by and in what direction. We call this move method from our draw class as every time we draw the enemy we want to move first move it to a new position.
# Goes inside the enemy class def move(self): if self.vel > 0: # If we are moving right if self.x < self.path[1] + self.vel: # If we have not reached the furthest right point on our path. self.x += self.vel else: # Change direction and move back the other way self.vel = self.vel * -1 self.x += self.vel self.walkCount = 0 else: # If we are moving left if self.x > self.path[0] - self.vel: # If we have not reached the furthest left point on our path self.x += self.vel else: # Change direction self.vel = self.vel * -1 self.x += self.vel self.walkCount = 0
Creating an Enemy
Now that we've created an enemy class we need to create an instance of that class. We will do this the same way we created an instance of our player class (man). Just outside and above our main loop.
goblin = enemy(100, 410, 64, 64, 300)
Now that we've created an instance we need to draw our goblin on the window. We will place the following code inside or redrawGameWindow function.
goblin.draw()
And now our goblin should be appearing on the screen and walking around!
Full Code
This is what the full code looks like now.
import pygame pygame.init() win = pygame.display.set_mode((500,480)) pygame.display.set_caption("First Game") walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'), pygame.image.load('R4.png'), pygame.image.load('R5.png'), pygame.image.load('R6.png'), pygame.image.load('R7.png'), pygame.image.load('R8.png'), pygame.image.load('R9.png')] walkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('L3.png'), pygame.image.load('L4.png'), pygame.image.load('L5.png'), pygame.image.load('L6.png'), pygame.image.load('L7.png'), pygame.image.load('L8.png'), pygame.image.load('L9.png')] bg = pygame.image.load('bg.jpg') char = pygame.image.load('standing.png') clock = pygame.time.Clock() class player(object): def __init__(self,x,y,width,height): self.x = x self.y = y self.width = width self.height = height self.vel = 5 self.isJump = False self.left = False self.right = False self.walkCount = 0 self.jumpCount = 10 self.standing = True def draw(self, win): if self.walkCount + 1 >= 27: self.walkCount = 0 if not(self.standing): if self.left: win.blit(walkLeft[self.walkCount//3], (self.x,self.y)) self.walkCount += 1 elif self.right: win.blit(walkRight[self.walkCount//3], (self.x,self.y)) self.walkCount +=1 else: if self.right: win.blit(walkRight[0], (self.x, self.y)) else: win.blit(walkLeft[0], (self.x, self.y)) class projectile(object): def __init__(self,x,y,radius,color,facing): self.x = x self.y = y self.radius = radius self.color = color self.facing = facing self.vel = 8 * facing def draw(self,win): pygame.draw.circle(win, self.color, (self.x,self.y), self.radius) class enemy(object): walkRight = [pygame.image.load('R1E.png'), pygame.image.load('R2E.png'), pygame.image.load('R3E.png'), pygame.image.load('R4E.png'), pygame.image.load('R5E.png'), pygame.image.load('R6E.png'), pygame.image.load('R7E.png'), pygame.image.load('R8E.png'), pygame.image.load('R9E.png'), pygame.image.load('R10E.png'), pygame.image.load('R11E.png')] walkLeft = [pygame.image.load('L1E.png'), pygame.image.load('L2E.png'), pygame.image.load('L3E.png'), pygame.image.load('L4E.png'), pygame.image.load('L5E.png'), pygame.image.load('L6E.png'), pygame.image.load('L7E.png'), pygame.image.load('L8E.png'), pygame.image.load('L9E.png'), pygame.image.load('L10E.png'), pygame.image.load('L11E.png')] def __init__(self, x, y, width, height, end): self.x = x self.y = y self.width = width self.height = height self.path = [x, end] self.walkCount = 0 self.vel = 3 def draw(self, win): self.move() if self.walkCount + 1 >= 33: self.walkCount = 0 if self.vel > 0: win.blit(self.walkRight[self.walkCount//3], (self.x,self.y)) self.walkCount += 1 else: win.blit(self.walkLeft[self.walkCount//3], (self.x,self.y)) self.walkCount += 1 def move(self): if self.vel > 0: if self.x < self.path[1] + self.vel: self.x += self.vel else: self.vel = self.vel * -1 self.x += self.vel self.walkCount = 0 else: if self.x > self.path[0] - self.vel: self.x += self.vel else: self.vel = self.vel * -1 self.x += self.vel self.walkCount = 0 def redrawGameWindow(): win.blit(bg, (0,0)) man.draw(win) goblin.draw(win) for bullet in bullets: bullet.draw(win) pygame.display.update() #mainloop man = player(200, 410, 64,64) goblin = enemy(100, 410, 64, 64, 300) bullets = [] run = True while run: clock.tick(27) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False for bullet in bullets: if bullet.x < 500 and bullet.x > 0: bullet.x += bullet.vel else: bullets.pop(bullets.index(bullet)) keys = pygame.key.get_pressed() if keys[pygame.K_SPACE]: if man.left: facing = -1 else: facing = 1 if len(bullets) < 5: bullets.append(projectile(round(man.x + man.width //2), round(man.y + man.height//2), 6, (0,0,0), facing)) if keys[pygame.K_LEFT] and man.x > man.vel: man.x -= man.vel man.left = True man.right = False man.standing = False elif keys[pygame.K_RIGHT] and man.x < 500 - man.width - man.vel: man.x += man.vel man.right = True man.left = False man.standing = False else: man.standing = True man.walkCount = 0 if not(man.isJump): if keys[pygame.K_UP]: man.isJump = True man.right = False man.left = False man.walkCount = 0 else: if man.jumpCount >= -10: neg = 1 if man.jumpCount < 0: neg = -1 man.y -= (man.jumpCount ** 2) * 0.5 * neg man.jumpCount -= 1 else: man.isJump = False man.jumpCount = 10 redrawGameWindow() pygame.quit()