Moving in eight directions is a little artificial in that you don't see many things moving like this in real life. Most mobile things can rotate freely, but move in the direction they are pointing, or perhaps backward—but definitely in more than eight compass directions. We can still use the same Up, Down, Left, and Right keys to simulate this, but we have to change what the keys control. What we want to do is have keys for left and right that control rotation and keys for forward and back movement, which would give our sprite the ability to move in any direction. Listing 6-3 uses exactly the same set of keys but uses this free rotation control to move the sprite around the screen.
Listing 6-3. Free Rotation Control (keyrotatemovement.py)
background_image_filename = 'sushiplate.jpg' sprite_image_filename = 'fugu.png'
import pygame from pygame.locals import * from sys import exit from gameobjects.vector2 import Vector2 from math import *
screen = pygame.display.set_mode((640, 480), 0, 32)
background = pygame.image.load(background_image_filename).convert() sprite = pygame.image.load(sprite_image_filename).convert_alpha()
clock = pygame.time.Clock()
sprite_pos = Vector2(200, 150) sprite_speed = 300. sprite_rotation = 0.
sprite_rotation_speed = 360. # Degrees per second while True:
for event in pygame.event.get(): if event.type == QUIT: exit()
pressed_keys = pygame.key.get_pressed()
rotation_direction = 0. movement_direction = 0.
rotation_direction = +1.0 if pressed_keys[K_RIGHT]:
rotation_direction = -1.0 if pressed_keys[K_UP]:
movement_direction = +1.0 if pressed_keys[K_DOWN]:
movement_direction = -1.0
rotated_sprite = pygame.transform.rotate(sprite, sprite_rotation) w, h = rotated_sprite.get_size()
sprite_draw_pos = Vector2(sprite_pos.x-w/2, sprite_pos.y-h/2) screen.blit(rotated_sprite, sprite_draw_pos)
time_passed = clock.tick() time_passed_seconds = time_passed / 1000.0
sprite_rotation += rotation_direction * sprite_rotation_speed time_passed_seconds heading_x = sin(sprite_rotation*pi/180.0) heading_y = cos(sprite_rotation*pi/180.0) heading = Vector2(heading_x, heading_y) heading *= movement_direction sprite_pos+= heading * sprite_speed * time_passed_seconds pygame.display.update()
Listing 6-3 works in a similar way to the previous example, but it calculates the heading differently. Rather than create a heading vector from whatever keys are pressed, we create the heading from the rotation of the sprite (stored in the variable sprite_rotation). It is this value that we modify when the appropriate key is pressed. When the Right key is pressed, we add to the sprite rotation, turning it one way. And when the Left key is pressed, we subtract from the rotation to turn it in the opposite direction.
To calculate the heading vector from the rotation, we must calculate the sine and cosine of the angle, which we can do with the sin and cos functions found in the math module. The sin function calculates the x component, and cos calculates the y component. Both functions take an angle in radians (there are 2 * pi radians in a circle), but since Listing 6-3 uses degrees it has to convert the rotation to radians by multiplying by pi and dividing by 180. After we assemble the heading vector from the two components, it can be used as before to give us time-based movement.
Before Listing 6-3 displays the sprite, the sprite is rotated visually so we can see which way it is facing. This is done with a function from the transform module called rotate, which takes a surface plus an angle and returns a new surface containing the rotated sprite. A problem with this function is that the returned sprite may not have the same dimensions as the original (see Figure 6-2), so we can't blit it to the same coordinate as the unrotated sprite or it will be drawn in the wrong position on screen. A way to work around this is to draw the sprite in a position that puts the center of the sprite image underneath the sprite's position on screen. That way, the sprite will be in the same position on the screen regardless of the size of the rotated surface.
Was this article helpful?