M_Sea
M_Sea

Reputation: 491

python pygame make the alien group move

Update 12/7

Finally i found the reason why i cant use Group to calling the methods , for the method name must update() so that the Group can calling.

in my codes i modify like this then it worked!!

def update(self):
     self.x =self.rect.x + self.speed
     self.rect.x = self.x
def position(aliens):
    aliens.update()

=============================================

Edit the question make it clearly

def update(self):
            self.x =self.ai.setting.alien_speed_factor
            self.rect.x = self.x

def update_aliens(aliens):
       aliens.update()

These two from the book, and i use it in my codes, for the aliens is a Group it called error #AttributeError: 'Group' object has no attribute 'position'

How to make Group aliens to execute update()???

I am writing script to make the alien group to move, one for my own way and another is from the book, when i refer to the book i found a mistake, i am not sure whether is it wrong.

Book "Python Crash Course" page 243

I use

def update(aliens):
    for alien in aliens:
        alien.position()

instead of the code from book:

def update(aliens):
        aliens.position()

which returns

>> AttributeError: 'Group' object has no attribute 'position'

then the runing the script is correct, so is this a mistake in book? or i use the wrong way to run the original codes?

here's my code:

#!/usr/bin/python
import sys
import pygame as p


class Setting():
    def __init__(self,width,height):
        self.w=width
        self.h=height
        self.flag=p.RESIZABLE
        self.screen=p.display.set_mode((self.w,self.h),self.flag)
        p.display.set_caption("Muhaha")



class Alien(p.sprite.Sprite):
    def __init__(self):
        super().__init__()
        pic=p.image.load("../image/ship.jpg").convert_alpha()
        self.image=p.transform.smoothscale(pic,(100,100))
        self.rect=self.image.get_rect()
        self.x = float(self.rect.x)
        self.rect.x=(self.rect.width)
        self.speed=1
    def create(self,setting,aliens):
        spacex=setting.w-(self.rect.x)*2
        spacey=(setting.h)/2-self.rect.y
        alien_number=int(spacex/(2*(self.rect.width)))
        alien_row=int(spacey/(2*(self.rect.height)))
        for row in range(alien_row):
           for number in range(alien_number):
               alien=Alien()
               alien.rect.x=alien.rect.x+2*alien.rect.width*number
               alien.rect.y=alien.rect.y+2*alien.rect.height*row
               aliens.add(alien)

    def position(self):
        self.x =self.rect.x + self.speed
        self.rect.x = self.x
    def update(aliens):
        aliens.position()        #AttributeError: 'Group' object has no attribute 'position'
                                 #i think the correct code is>> for alien in aliens:
                                 #                              alien.position()

    def blit(setting,aliens):
        aliens.draw(setting.screen)

def game():
    p.init()
    setting=Setting(1200,800)
    alien=Alien()
    aliens=p.sprite.Group()
    alien.create(setting,aliens)
    while True:
         for event in p.event.get():
             if event.type == p.QUIT:
                 sys.exit()
         setting.screen.fill((255,0,0))
         Alien.blit(setting,aliens)
         Alien.update(aliens)
         p.display.flip()
game()

Upvotes: 1

Views: 236

Answers (1)

sloth
sloth

Reputation: 101122

Yes, it seems like a bug. And to be honest, the entire code looks horrible.

As a first step, remove the blit and position functions from the Alien class, change the update function to this:

def update(self):
    self.x = self.rect.x + self.speed
    self.rect.x = self.x  

and in the main loop, instead of

     Alien.blit(setting,aliens)
     Alien.update(aliens)

do

    aliens.update()
    aliens.draw(setting.screen)

Calling update on a Group will call the update of all Sprite instances in that Group, so there's not need to iterate over all sprites manually.

In the same vein, calling draw on a Group will draw all sprites in that Group to the Surface passed as argument (usually the screen surface). Again, there's no need to do this in the Alien class, which is supposed to represent a single sprite.

Some other issues:

  • the image for the Alien sprite is loaded from disk every time an new instance is created
  • there's no FPS limit, so the game does not run at a constant speed
  • it's common to name your main function, well, 'main'
  • an instance of Alien is created to just create more instances with the create instance method, and then the update function is used like a class method

Upvotes: 1

Related Questions