I've created a dragon that moves towards the player, and while doing so it has an animation where it flies. However, if the player stands at certain angles to the dragon, the flying animation stops until it is either directly above/to the side of the player, or immediately diagonal.
For example, standing below the dragon will trigger the animation, but standing below and over to the right will cause the dragons animation to pause until it is immediately diagonal. Here is a fully runnable example;
Main game
from Rooms import *
from Player import *
import pygame
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
pygame.init()
screen_width = 1080
screen_height = 607
screen = pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption('Labyrinth')
block_list = pygame.sprite.Group()
all_sprites_list = pygame.sprite.Group()
rooms = []
room = Room0()
rooms.append(room)
current_room_no = 0
current_room = rooms[current_room_no]
player = Player("Isaac.png", 420, 150, current_room)
all_sprites_list.add(player)
clock = pygame.time.Clock()
done = False
# -- MAIN PROGRAM LOOP -- #
# -- Event processing --
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# Player controls
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.changespeed(-7, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(7, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, -7)
elif event.key == pygame.K_DOWN:
player.changespeed(0, 7)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.changespeed(7, 0)
elif event.key == pygame.K_RIGHT:
player.changespeed(-7, 0)
elif event.key == pygame.K_UP:
player.changespeed(0, 7)
elif event.key == pygame.K_DOWN:
player.changespeed(0, -7)
# -- Game Logic --
all_sprites_list.update()
current_room.enemy_sprites.update(player)
# Hit detection
screen.blit(current_room.background_image, current_room.background_position)
all_sprites_list.draw(screen)
current_room.enemy_sprites.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
Dragon class
import pygame
import math
from Player import Player
import time
BLACK = (0, 0, 0)
class SpriteSheet(object):
def __init__(self, file_name):
self.sprite_sheet = pygame.image.load(file_name).convert()
def get_image(self, x, y, width, height):
image = pygame.Surface([width, height]).convert()
image.blit(self.sprite_sheet, (0, 0), (x, y, width, height))
image.set_colorkey(BLACK)
return image
class Dragon(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.flying_frames_l = []
self.flying_frames_r = []
sprite_sheet = SpriteSheet("Dragon.png")
# Flying left
image = sprite_sheet.get_image(12, 22, 95, 85)
self.flying_frames_l.append(image)
image = sprite_sheet.get_image(140, 35, 95, 67)
self.flying_frames_l.append(image)
image = sprite_sheet.get_image(18, 138, 96, 55)
self.flying_frames_l.append(image)
image = sprite_sheet.get_image(128, 131, 96, 63)
self.flying_frames_l.append(image)
image = sprite_sheet.get_image(140, 35, 95, 67)
self.flying_frames_l.append(image)
image = sprite_sheet.get_image(12, 22, 95, 85)
self.flying_frames_l.append(image)
# Flying right
image = sprite_sheet.get_image(12, 22, 95, 85)
image = pygame.transform.flip(image, True, False)
self.flying_frames_r.append(image)
image = sprite_sheet.get_image(140, 35, 95, 67)
image = pygame.transform.flip(image, True, False)
self.flying_frames_r.append(image)
image = sprite_sheet.get_image(18, 138, 96, 55)
image = pygame.transform.flip(image, True, False)
self.flying_frames_r.append(image)
image = sprite_sheet.get_image(128, 131, 96, 63)
image = pygame.transform.flip(image, True, False)
self.flying_frames_r.append(image)
image = sprite_sheet.get_image(140, 35, 95, 67)
image = pygame.transform.flip(image, True, False)
self.flying_frames_r.append(image)
image = sprite_sheet.get_image(12, 22, 95, 85)
image = pygame.transform.flip(image, True, False)
self.flying_frames_r.append(image)
self.image = self.flying_frames_r[0]
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
self.speedx = 0
self.speedy = 0
self.health = 100
def update(self, player):
posx = self.rect.x
posy = self.rect.y
dx = self.rect.x - player.rect.x
dy = self.rect.y - player.rect.y
dist = math.hypot(dx, dy)
dx = dx / dist
dy = dy / dist
if dx > 0:
self.speedx = -1.5
if dx <= 0:
self.speedx = -1.5
if dy >= 0:
self.speedy = -1.5
if dy <= 0:
self.speedy = -1.5
self.rect.x += dx * self.speedx
self.rect.y += dy * self.speedy
if self.rect.x < player.rect.x:
frame = (posx // 10) % len(self.flying_frames_l)
self.image = self.flying_frames_l[frame]
else:
frame = (posx // 10) % len(self.flying_frames_r)
self.image = self.flying_frames_r[frame]
if self.rect.y < player.rect.y:
frame = (posy // 10) % len(self.flying_frames_l)
self.image = self.flying_frames_l[frame]
else:
frame = (posy // 10) % len(self.flying_frames_r)
self.image = self.flying_frames_r[frame]
Player class
import pygame
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
class Player(pygame.sprite.Sprite):
def __init__(self, filename, x, y, current_room):
super().__init__()
self.image = pygame.image.load(filename).convert()
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.change_x = 0
self.change_y = 0
def changespeed(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
self.rect.x += self.change_x
self.rect.y += self.change_y
Room class
import Player
import pygame
from Enemies import Dragon
class Room(object):
enemy_sprites = None
def __init__(self):
self.enemy_sprites = pygame.sprite.Group()
class Room0(Room):
def __init__(self):
super().__init__()
enemy = Dragon(380, 280)
self.enemy_sprites.add(enemy)
self.background_position = [0, 0]
self.background_image = pygame.image.load("Floor.png").convert()
This is the spritesheet im using to make it easier to run the code