pythonpython-3.xpygamepygame2

How do I move to the mouse pointer and point towards it at the same time?


I am quite new to Pygame 2 (actually python in general), and I wanted to make a little game for school. I used the code from this, but I can't get it to move towards the cursor when I press SPACE. I don't want it to move in the x/y axis... This is the code btw

import sys, pygame, math
from pygame.locals import *
spaceship = ('spaceship.png')
mouse_c = ('cursor.png')
backg = ('background.jpg')
lazer = pygame.mixer.Sound("pew.WAV")
pygame.init()

display_width = 1280
display_height = 720
screen = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("Space Survival")

bk = pygame.image.load(backg).convert_alpha()
space_ship = pygame.image.load(spaceship).convert_alpha()
mousec = pygame.image.load(mouse_c).convert_alpha()
clock = pygame.time.Clock()
pygame.mouse.set_visible(False)
Ammo = 20
Fuel = 200

while True:
    for event in pygame.event.get():
    if event.type == QUIT:
        pygame.quit()
        sys.exit()
    elif event.type == MOUSEBUTTONDOWN and event.button == 1 and Ammo <= 20:
        print("Pew")
        pygame.mixer.Sound.play(lazer)
    elif event.type == MOUSEBUTTONDOWN and event.button == 3 and Fuel <= 200:
        print("Boost")

screen.blit(bk, (0, 0))
pos = pygame.mouse.get_pos()
angle = 270-math.atan2(pos[1]-(display_height/2),pos[0]-(display_width/2))*180/math.pi
rotimage = pygame.transform.rotate(space_ship,angle)
rect = rotimage.get_rect(center=((display_width/2),(display_height/2)))
screen.blit(rotimage,rect) #I need space_ship to rotate towards my cursor
screen.blit(mousec, (pos))
pygame.display.update()
clock.tick(60)   #FPS

Running Pygame 2.0 on Python 3.8. Any tips will be much appreciated :)


Solution

  • Write a function that "follows2 an target:

    def FollowMe(pops, fpos, step):
        # [...]
    

    I recommend to compute the distance between the spaceship and the mouse and the unit direction vector from (fpos) to (pops).
    The distance can be get by computing the Euclidean distance. Pygame provides distance_to() for that. Th unit direction vector can be computed by dividing the direction vector by the distance or by normalizing (normalize()) the direction vector:

    target_vector       = pygame.math.Vector2(pops)
    follower_vector     = pygame.math.Vector2(fpos)
    
    distance = follower_vector.distance_to(target_vector)
    direction_vector = target_vector - follower_vector
    if distance > 0:
        direction_vector /= distance
    

    Now you can define an exact step_distance and move to follower in direction of the sprite:

    if distance > 0:
        new_follower_vector = follower_vector + direction_vector * step_distance.
    

    Define a step and ensure that the step distance is not grater than the step:

    step_distance = min(distance, step)
    

    The maximum step distance is

    max_step = distance - minimum_distance
    

    Put it all together:

    def FollowMe(pops, fpos, step):
        target_vector       = pygame.math.Vector2(pops)
        follower_vector     = pygame.math.Vector2(fpos)
        new_follower_vector = pygame.math.Vector2(fpos)
    
        distance = follower_vector.distance_to(target_vector)
        if distance > 0:
            direction_vector    = (target_vector - follower_vector) / distance
            step_distance       = min(distance, step)
            new_follower_vector = follower_vector + direction_vector * step_distance
    
        return (new_follower_vector.x, new_follower_vector.y)
    

    See also How to make smooth movement in pygame.

    Use the function to move the space ship in the direction of the mouse and pygame.key.get_pressed() to move the ship when SPACE is pressed. pygame.key.get_pressed() returns a list with the state of each key. If a key is held down, the state for the key is True, otherwise False. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement:

    ship_pos = display_width // 2, display_height // 2
    
    while True:
        # [...]
    
        keys = pygame.key.get_pressed()
        if keys[pygame.K_SPACE]:
            ship_pos = FollowMe(pos, ship_pos, 3)
        angle = 270-math.atan2(pos[1]-ship_pos[1],pos[0]-ship_pos[0])*180/math.pi
        rotimage = pygame.transform.rotate(space_ship,angle)
        rect = rotimage.get_rect(center=ship_pos)
    

    For the rotation of an image see How to rotate an image(player) to the mouse direction? and How do I rotate an image around its center using PyGame?

    See also Rotate towards target or mouse respectivley Move towards target and the answer to the question How do I rotate a sprite towards the mouse and move it?


    Minimal example without any usage of external resources (sound and images):

    import sys, pygame, math
    from pygame.locals import *
    pygame.init()
    
    def FollowMe(pops, fpos, step):
        target_vector       = pygame.math.Vector2(pops)
        follower_vector     = pygame.math.Vector2(fpos)
        new_follower_vector = pygame.math.Vector2(fpos)
    
        distance = follower_vector.distance_to(target_vector)
        if distance > 0:
            direction_vector    = (target_vector - follower_vector) / distance
            step_distance       = min(distance, step)
            new_follower_vector = follower_vector + direction_vector * step_distance
    
        return (new_follower_vector.x, new_follower_vector.y) 
    
    display_width = 1280
    display_height = 720
    screen = pygame.display.set_mode((display_width,display_height))
    pygame.display.set_caption("Space Survival")
    clock = pygame.time.Clock() 
    
    bk = pygame.Surface(screen.get_size())
    space_ship = pygame.Surface((20, 50), pygame.SRCALPHA)
    space_ship.fill((0, 255, 0)) 
    mousec = pygame.Surface((20, 20), pygame.SRCALPHA)
    mousec.fill((255, 0, 0)) 
    
    ship_pos = display_width // 2, display_height // 2
    
    while True:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
    
        pos = pygame.mouse.get_pos()
        keys = pygame.key.get_pressed()
        if keys[pygame.K_SPACE]:
            ship_pos = FollowMe(pos, ship_pos, 3)
        angle = 270-math.atan2(pos[1]-ship_pos[1],pos[0]-ship_pos[0])*180/math.pi
        rotimage = pygame.transform.rotate(space_ship,angle)
        rect = rotimage.get_rect(center=ship_pos)
        
        screen.blit(bk, (0, 0))
        screen.blit(rotimage,rect)
        screen.blit(mousec, pos)
        pygame.display.update()