There are a number of ways to have python move game objects around the screen. Up until recently I hadn't really tried much other than tying keys to a function that would move a rectangle object by an offset.
Something like this:
*** in the sprite class***
def change_pos(self, x, y):
self.change_x += x
self.change_y += y
*** in the main loop ***
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_UP:
player.change_pos(0, -PS)
I'd set up a global for player speed (PS) that I could hand to the change_pos function as a positive or negative value based on the direction the player wanted to go.
This way works fine, but it's not really all that flexible. What if you wanted to have the player sprite keep moving a bit after the player releases the movement keys? For that you'd need to use a bit of physics. There are a ton of different ways to do something like this, and I've read through some tutorials on it. Since I'm not very good with math though, most of it was way over my head. I came up with a very simplistic approach to the whole thing.
I created a sprite object with an attribute to store a list of forces that will act as inertia to be applied to the object. Then I took out the change_pos() function and replaced it with this:
def apply_force():
for i in self.forces:
i -= friction
if self.up:
self.forces[0] += speed
if self.down:
self.forces[1] +=speed
if self.left:
self.forces[2] +=speed
if self.right:
self.forces[3] +=speed
In the player sprite's update function, I can say:
def update():
self.apply_force()
self.rect.top += (self.forces[1] - self.forces[0])
self.rect.left += (self.forces[3] - self.forces[2])
You can play around with the values that you use for speed, and friction. Speed is how fast your player object gains speed and friction is how fast the object is slowed. You may want to add something to the end of your apply_force() function to cap the forces. I used something like this:
for i in self.forces:
if i > 200:
i=200
if i < 0:
i=0
Also, if you want, you can have your main loop use actual time to update instead of FPS which can be affected by the power of the system you're running on. Up until recently I had been using the following in my main loop:
clock = pygame.time.Clock()
while 1:
clock.tick(60)
It actually makes more sense to use the following:
FPS = 60
clock = pygame.time.Clock()
while 1:
milliseconds = clock.tick(FPS)
seconds = milliseconds / 1000.0
Then change the player class update function to take seconds as an argument. This will give you a much more consistent movement:
self.rect.top += (self.forces[1] - self.forces[0]) * seconds
self.rect.left += (self.forces[3] - self.forces[2]) * seconds
There are of course, more accurate ways to produce the same effect, but I found this pretty simple to understand and easy to implement.
-Newt
No comments:
Post a Comment