Reputation: 667
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
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
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