Reputation: 5015
Please any help would be greatly appreciated. I am writing a game with Pygame and after creating all the classes and methods I need. When I run the game I see five alien characters of my game showing up from the left side of the screen joined together before I actually see what i wanted my code to display (aliens moving at random positions down the screen).
here is my code:
class Alien():
def __init__(self, image):
self.x = random.randrange(20,width - 20)
self.y = random.randrange(-200, -20)
self.speed = random.randint(1, 5)
self.image = pygame.image.load(os.path.join("../images", image)).convert_alpha()
self.rect = self.image.get_rect()
def move_down(self):
self.rect.y += self.speed
def draw(self, screen):
screen.blit(self.image, self.rect)
its implementation
for i in range (20):
aliens = Alien("alien.png")
enemies.append(aliens)
done = False
while done == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.fill(white)
for i in range(len(enemies)):
enemies[i].move_down()
enemies[i].draw(screen)
enemies[i].check_landed()
pygame.display.flip()
clock.tick(30)
note: I have removed some code for clarity. result
Upvotes: 2
Views: 1192
Reputation: 101042
You store the position of the aliens in the fields self.x
and self.y
, but to draw them, you actually don't use self.x
and self.y
, but self.rect
.
You create self.rect
by calling self.image.get_rect()
, and when you call get_rect()
on a Surface
, the position of the Rect
is always (0, 0)
.
So the x
coordinate is always 0
, hence they are all on the left side of the screen.
I suggest rewriting your code to:
class Alien():
# pass the Surface to the instance instead of the filename
# this way, you only load the image once, not once for each alien
def __init__(self, image):
self.speed = random.randint(1, 5)
self.image = image
# since we're going to use a Rect of drawing, let's use the
# same Rect to store the correct position of the alien
self.rect = self.image.get_rect(top=random.randrange(-200, -20), left=random.randrange(20,width - 20))
def move_down(self):
# the Rect class has a lot of handy functions like move_ip
self.rect.move_ip(0, self.speed)
def draw(self, screen):
screen.blit(self.image, self.rect)
# load the image once. In more complex games, you usually
# want to abstract the loading/storing of images
alienimage = pygame.image.load(os.path.join("../images", 'alien.png')).convert_alpha()
for _ in range (20):
aliens = Alien(alienimage)
enemies.append(aliens)
done = False
while done == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.fill(white)
# just use a "regular" for loop to loop through all enemies
for enemy in enemies:
enemy.move_down()
enemy.draw(screen)
enemy.check_landed()
pygame.display.flip()
clock.tick(30)
You could go further and use the Sprite
- and Group
-class to further generalize your code, but that's another topic.
Upvotes: 2