pepper5319
pepper5319

Reputation: 667

Looping in Python

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()

Upvotes: 1

Views: 192

Answers (2)

trevorKirkby
trevorKirkby

Reputation: 1897

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)

Upvotes: 1

mbdavis
mbdavis

Reputation: 4010

you need to redraw the screen after each move, I think the code is:

pygame.display.update()

so your for loop should be like this:

for i in range(1, 10)
    Grenade.move()
    pygame.display.update()

This might not be too efficient, so be sure to look out for more effective ways, for example if the grenade is the only moving object in your scene then you're going to want to only redraw that.

Upvotes: 0

Related Questions