Looping in Python
Question: I am trying to make a sprite in pygame throw a grenade. What I would like is
for it to move forward a bit, then stopping. My problem is getting the grenade
to smoothly move forward. What the following code does is having it move to
the point of intrest immediately, not smoothly moving.

[Grenade Class]

    
    
    #Grenade Class
    class Explosive(pygame.sprite.Sprite):
        def __init__(self, location):
            pygame.sprite.Sprite.__init__(self)
            self.pos = location
            self.image = Nade
            self.rect = self.image.get_rect()
            self.rect.right = self.image.get_rect().right
            self.rect.left = self.image.get_rect().left
            self.rect.top = self.image.get_rect().top
            self.rect.bottom = self.image.get_rect().bottom
            self.rect.center = location
        def move(self):
            if Player.direction == 0:
                self.rect.centery = self.rect.centery - 5
            if Player.direction == 180:
                    self.rect.centery = self.rect.centery + 5
            if Player.direction == 90:
                self.rect.centerx = self.rect.centerx + 5
            if Player.direction == 270:
                self.rect.centerx = self.rect.centerx - 5 
    

[Throwing the Grenade(in main loop)]

    
    
    if event.key == pygame.K_e and grenadeNum > 0:
                Grenade = Explosive([Player.rect.centerx, Player.rect.centery])
                for i in range(1, 10)
                    Grenade.move()
    


Answer: While you do need to update the display, there is a second issue. Right now,
you are not telling it to wait at all, so it will make all ten movements with
no delay. This will be just as abrupt, so you may want to import time and add
a time.sleep() somewhere in there. Because moving the grenade in a self
contained "for" loop, if you have anything else going on this will stop. If
you have a while loop to manage everything, call an "update" function on the
grenades and they will have counters to know if they should move during this
round. If other sprites need to do things, you can then call their methods as
well. Finally, just to speed up the program, you can only update the screen in
the portion that the sprite moves in. When you put this all together, it is
something along these lines:

    
    
    import time
    
    grenades = pygame.sprite.RenderUpdates()        #initializes a pygame group for sprites
    
    class Explosive(pygame.sprite.Sprite):
    def __init__(self, location):
        pygame.sprite.Sprite.__init__(self)
        self.pos = location
        self.image = Nade
        self.rect = self.image.get_rect()
        self.rect.right = self.image.get_rect().right
        self.rect.left = self.image.get_rect().left
        self.rect.top = self.image.get_rect().top
        self.rect.bottom = self.image.get_rect().bottom
        self.rect.center = location
        self.move_counter = 10               #adds a counter for how many rounds left of moving the grenade has
    def update(self):
        if self.move_counter > 0:            #checks that self still has turns left to move
            <insert screen variable name>.fill(<insert background color>,self.rect)    #erases self in old location
            if Player.direction == 0:
                self.rect.centery = self.rect.centery - 5
            if Player.direction == 180:
                    self.rect.centery = self.rect.centery + 5
            if Player.direction == 90:
                self.rect.centerx = self.rect.centerx + 5
            if Player.direction == 270:
                self.rect.centerx = self.rect.centerx - 5
            pygame.display.update(self.draw((screen)))    #draws self in new location
            self.move_counter -= 1           #subtracts one from the counter to mark that another turn of moving has passed by
    
    while True:
        grenades.update()
        #anything else you want to do in real time here
        time.sleep(0.1)
    

