1

I made a program where an object will rotate towards your mouse on the screen. now I need to make it so that the object will rotate towards another moving object. here is my code:

import pygame
import math
import sys
from pygame.locals import *;
from sys import exit
pygame.init()


blk = pygame.Color(0,0,0)
BG = ('BG.png')
pygame.init()
screen = pygame.display.set_mode((800, 600))
B_G = pygame.image.load(BG).convert_alpha()
clock = pygame.time.Clock()
pygame.mouse.set_visible(False)
fpsclock = pygame.time.Clock()



class Shork(pygame.sprite.Sprite):


 def __init__(self):
  pygame.sprite.Sprite.__init__(self)
  self.image = pygame.image.load('SHORK.png')
  screen = pygame.display.get_surface()
  self.x = 62
  self.y = 50
  self.direction = "down"

 def Moving(self):

  if self.direction == "right":
   self.x += 2
  elif self.direction == "left":
   self.x -= 2
  elif self.direction == "down":
   self.y += 2
  elif self.direction == "up":
   self.y -= 2


 def Path(self):

  if self.x == 62 and self.y == 538:
   self.direction = "right"

  if self.x == 246 and self.y == 538:
   self.direction = "up"

  if self.x == 246 and self.y == 366:
   self.direction = "left"

  if self.x == 176 and self.y == 366:
   self.direction = "up"

  if self.x == 176 and self.y == 114:
   self.direction = "right"

  if self.x == 530 and self.y == 114:
   self.direction = "down"

  if self.x == 530 and self.y == 366:
   self.direction = "left"

  if self.x == 460 and self.y == 366:
   self.direction = "down"

  if self.x == 460 and self.y == 538:
   self.direction = "right"

  if self.x == 644 and self.y == 538:
   self.direction = "up"
  if self.y == 0:
   sys.exit()

Shork = Shork()

Run = True


while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN and event.button == 1:
            print("test1")
        elif event.type == MOUSEBUTTONDOWN and event.button == 3:
            print("test3")
    while Run:
      fpsclock.tick(60)

      for event in pygame.event.get():

       if event.type == pygame.QUIT:
          Run = False

    pos = pygame.mouse.get_pos()
    angle = 360-math.atan2(pos[1]-300,pos[0]-400)*180/math.pi
    rotimage = pygame.transform.rotate(B_G,angle)
    Shork.Moving() 
    Shork.Path()
    screen.blit(Shork.image, (Shork.x, Shork.y))
    pygame.display.update()
    rect = rotimage.get_rect(center=(400,300))
    screen.blit(rotimage,rect)
    pygame.display.update()
    screen.fill(blk)

BG is the object that I need to rotate and SHORK is the object that BG needs to rotate towards. The middle portion of the code is just pathing for an object to follow. The code that I am struggling with is this:

pos = pygame.mouse.get_pos()
angle = 360-math.atan2(pos[1]-300,pos[0]-400)*180/math.pi
rotimage = pygame.transform.rotate(B_G,angle)
Shork.Moving() 
Shork.Path()
screen.blit(Shork.image, (Shork.x, Shork.y))
pygame.display.update()
rect = rotimage.get_rect(center=(400,300))
screen.blit(rotimage,rect)
pygame.display.update()

This currently works for following the mouse but I cannot for the life of me figure out how to make BG rotate towards SHORK. P.S. I am just starting to learn python so please try to be patient. :)

3 Answers3

0

You need to change angle to use Shork's x/y value instead of pos. You should also probably update Shork's values before calculating the angle, so I moved Shork.Moving and Shork.Path to the beginning of the block.

Shork.Moving() 
Shork.Path()
pos = pygame.mouse.get_pos()
angle = 360-math.atan2(Shork.y-300,Shork.x-400)*180/math.pi
rotimage = pygame.transform.rotate(B_G,angle)
screen.blit(Shork.image, (Shork.x, Shork.y))
pygame.display.update()
rect = rotimage.get_rect(center=(400,300))
screen.blit(rotimage,rect)
pygame.display.update()
user161778
  • 524
  • 2
  • 9
0

If this may help you here is a repo of a complete game with several levels which I wrote some years ago while learning Python and Pygame. It has rotating spaceships rotating to any angle, enemy ships that turn and follow you, enemy ships that turn and flee when shot at (artificial intelligence), ateroids etc.

Space Gladiator - The Spiritual Warrior

emorphus
  • 550
  • 9
  • 20
-2

I recommend to use vectors.

# To get the distance to the mouse just subtract the position vector
# of the sprite from the mouse position.
x, y = pg.mouse.get_pos() - self.pos
self.angle = math.degrees(math.atan2(y, x))
# Rotate the image (keep a copy of the original image around).
self.image = pg.transform.rotozoom(self.orig_image, -self.angle, 1)
self.rect = self.image.get_rect(center=self.rect.center)

You can also get the angle of a pygame.math.Vector2 by calling its as_polar method which returns the polar coordinates.

distance = pg.mouse.get_pos() - self.pos
radius, self.angle = distance.as_polar()

Here's a minimal working example with a moving sprite that rotates toward the mouse (move left and right with 'a' and 'd').

import sys
import math

import pygame as pg
from pygame.math import Vector2


pg.init()

BLUEGREEN = pg.Color(0, 90, 100)
GREEN = pg.Color('springgreen1')


class Player(pg.sprite.Sprite):

    def __init__(self, x, y, *spritegroups):
        super().__init__(spritegroups)
        self.image = pg.Surface((50, 30), pg.SRCALPHA)
        pg.draw.polygon(self.image, GREEN, ((1, 1), (49, 14), (1, 29)))
        self.orig_image = self.image
        self.rect = self.image.get_rect(center=(x, y))
        self.pos = Vector2(x, y)
        self.vel = Vector2(0, 0)
        self.angle = 0

    def handle_event(self, event):
        if event.type == pg.KEYDOWN:
            if event.key == pg.K_a:
                self.vel.x = -3.5
            elif event.key == pg.K_d:
                self.vel.x = 3.5
        if event.type == pg.KEYUP:
            if event.key == pg.K_a and self.vel.x < 0:
                self.vel.x = 0
            elif event.key == pg.K_d and self.vel.x > 0:
                self.vel.x = 0

    def update(self):
        # Update the position vector by adding the velocity vector.
        self.pos += self.vel
        self.rect.center = self.pos
        # Get the distance and angle to the target.
        x, y = pg.mouse.get_pos() - self.pos
        self.angle = math.degrees(math.atan2(y, x))
        # Rotate the image (rotozoom looks better than transform.rotate).
        self.image = pg.transform.rotozoom(self.orig_image, -self.angle, 1)
        self.rect = self.image.get_rect(center=self.rect.center)


def main():
    screen = pg.display.set_mode((640, 480))
    pg.display.set_caption('Rotation')
    clock = pg.time.Clock()

    sprite_group = pg.sprite.Group()
    player = Player(200, 300, sprite_group)
    done = False

    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True
            player.handle_event(event)

        sprite_group.update()

        screen.fill(BLUEGREEN)
        sprite_group.draw(screen)

        pg.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    main()
    pg.quit()
    sys.exit()
skrx
  • 19,980
  • 5
  • 34
  • 48