Python Forum
[pygame] Moving an object at angles
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[pygame] Moving an object at angles
#1
I did all the code for moving at angles. I made it so that rotating to the right, it goes up to 359 and then 360 is 0. I have a slight problem that I can't figure out how to solve. The problem is with direction the object is moving. I appreciate any help in pointing out where I went wrong. Thx in advance.
import pygame, math, sys

#Initiation
pygame.init()
screen = pygame.display.set_mode((500, 500))

#Constants
get_ticks = pygame.time.get_ticks
clock = pygame.time.Clock()
fps = 60


class Object():
    def __init__(self, rect):
        self.rect = rect
        self.ticks = 0

    def draw(self):
        pygame.draw.rect(screen, (255, 255, 255), self.rect)

    def move(self, angle):
        rectAdd = self.calculate(angle)
        self.rect[0] += rectAdd[0]
        self.rect[1] += rectAdd[1]
        
    def calculate(self, angle):
        angleCheck = [0, 90, 180, 270, 45, 135, 225, 315]
        tanSafeAngle = angle
        while tanSafeAngle > 90:
            tanSafeAngle -= 90
        tanAngle = math.tan(math.radians(tanSafeAngle))
        if angle not in angleCheck:
            movement = [0, 0]
            x, num = self.directionCalculation(angle, 'side')
            movement[x] = num
            self.ticks += 1
            while self.ticks - tanAngle > 0:
                x, num = self.directionCalculation(angle, 'forward')
                movement[x] += num
                self.ticks -= tanAngle
            return movement
        else:
            angleMovement = {0 : (0, -1), 90 : (1, 0), 180 : (0, 1), 270 : (-1, 0),
                             45 : (1, -1), 135 : (1, 1), 225 : (-1, 1), 315 : (-1, -1)}
            return angleMovement[angle]

    def directionCalculation(self, angle, direction):
        directionDict = {'side' : {0 : (1, -1), 90 : (0, 1), 180 : (1, 1), 270 : (0, -1)},
                         'forward' : {0 : (0, 1), 90 : (1, 1), 180 : (0, -1), 270 : (1, -1)}}
        count = 0
        for angleComparison in directionDict[direction]:
            if angle > angleComparison and angle < angleComparison + 90:
                return directionDict[direction][angleComparison]
Here is the code below the class I used to test it
obj = Object([50, 50, 50, 50])
rotation = 10
for x in range(0, 100):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            break
    screen.fill((0, 0, 0))
    obj.move(rotation)
    obj.draw()
    pygame.display.update()
    clock.tick(fps)
pygame.quit()
sys.exit()
Reply
#2
Here an example
import os
import pygame
from pygame.sprite import Sprite
from math import radians, sin, cos
 
class Scene:
    def on_draw(self, surface): pass
    def on_event(self, event): pass
    def on_update(self, delta): pass
 
class Manager:
    def __init__(self, caption, width, height, center=True):
        if center:
            os.environ['SDL_VIDEO_CENTERED'] = '1'
 
        # Basic pygame setup
        pygame.display.set_caption(caption)
        self.surface = pygame.display.set_mode((width, height))
        self.rect = self.surface.get_rect()
        self.clock = pygame.time.Clock()
        self.running = False
        self.delta = 0
        self.fps = 60
 
        # Scene Interface
        self.scene = Scene()
 
    def mainloop(self):
        self.running = True
        while self.running:
            for event in pygame.event.get():
                self.scene.on_event(event)
 
            self.scene.on_update(self.delta)
            self.scene.on_draw(self.surface)
            pygame.display.flip()
            self.delta = self.clock.tick(self.fps)
 
class BaseSprite(Sprite):
    def __init__(self, image, position, anchor="topleft"):
        Sprite.__init__(self)
        self.original_image = image
        self.image = image
        self.rect = image.get_rect()
        setattr(self.rect, anchor, position)
 
    def draw(self, surface):
        surface.blit(self.image, self.rect)
 
class RotationMovementKeys:
    def __init__(self, sprite, up, down, left, right):
        self.sprite = sprite
        self.up = up
        self.down = down
        self.left = left
        self.right = right
 
        self.angle = 0
        self.speed = 0.04
        self.rotation_speed = 0.08
        self.center = pygame.Vector2(self.sprite.rect.center)
        self.set_direction()
 
    def set_direction(self):
        rad = radians(self.angle)
        self.direction = pygame.Vector2(sin(rad), cos(rad))
 
    def do_rotate(self):
        self.sprite.image = pygame.transform.rotate(self.sprite.original_image, self.angle)
        self.sprite.rect = self.sprite.image.get_rect()
        self.sprite.rect.center = self.center
        self.set_direction()
 
    def on_keydown(self, keys_press, delta):
        if keys_press[self.up]:
            self.center -= self.direction * delta * self.speed
            self.sprite.rect.center = self.center
        elif keys_press[self.down]:
            self.center += self.direction * delta * (self.speed / 2)
            self.sprite.rect.center = self.center
 
        if keys_press[self.right]:
            self.angle = (self.angle - self.rotation_speed * delta) % 360
            self.do_rotate()
        elif keys_press[self.left]:
            self.angle = (self.angle + self.rotation_speed * delta) % 360
            self.do_rotate()
 
class Example(Scene):
    def __init__(self, manager):
        self.create_image()
        self.manager = manager
        self.sprite = BaseSprite(self.rectangle, manager.rect.center, "center")
        self.sprite_movement = RotationMovementKeys(self.sprite,
            pygame.K_w, pygame.K_s, pygame.K_a, pygame.K_d)
 
    def create_image(self):
        self.rectangle = pygame.Surface((10, 20), pygame.SRCALPHA)
        self.rectangle.fill(pygame.Color('dodgerblue'))
        self.rectangle.fill(pygame.Color('white'), (2, 2, 6, 3))
 
    def on_draw(self, surface):
        surface.fill(pygame.Color("black"))
        self.sprite.draw(surface)
 
    def on_event(self, event):
        if event.type == pygame.QUIT:
            self.manager.running = False
 
    def on_update(self, delta):
        keys = pygame.key.get_pressed()
        self.sprite_movement.on_keydown(keys, delta)
 
def main():
    pygame.init()
    manager = Manager("Rotation Example", 800, 600)
    manager.scene = Example(manager)
    manager.mainloop()
 
if __name__ == "__main__":
    main()
99 percent of computer problems exists between chair and keyboard.
Reply
#3
I just noticed that I got the values switched on directionDict for forward and side movement. I'll switch them to how it should be and then test it out and see if it works.
Reply
#4
While my does work after making that change, the example you provided is less complicated. Thank you for your help!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Pygame sprite not moving michael1789 1 2,842 Nov-10-2019, 03:54 AM
Last Post: michael1789
  [PyGame] pygame.draw.rect function stretches across the screen instead of moving BubblesTheGiraffe 2 3,658 Jun-11-2019, 08:32 PM
Last Post: metulburr
  drawing, moving, and collision problems (pygame) SheeppOSU 26 14,725 Apr-22-2019, 03:09 AM
Last Post: SheeppOSU
  Moving an object in a circular path pi314159geek 1 14,241 Dec-25-2017, 12:06 PM
Last Post: Windspar

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020