Python Forum
[PyGame] Terrible Sprite controls, need help.
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] Terrible Sprite controls, need help.
#11
I'm running the event loop you posted.
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
 
    delta = clock.tick(60)
    keys = pygame.key.get_pressed()
    window.fill(pygame.Color('black'))
    ship.update(keys, delta)
 
    pygame.display.flip()
Reply
#12
When I get more time. I play around with the math.
Example rough draft.
import pygame
import math
pygame.init()

window = pygame.display.set_mode((800, 800))
clock = pygame.time.Clock()


class Ship(pygame.sprite.Sprite):
    def __init__(self, position, anchor="center"):

        self.original_image = pygame.Surface((10, 20), pygame.SRCALPHA)
        self.original_image.fill((100, 200, 200))
        self.image = self.original_image.copy()

        self.rect = self.image.get_rect(**{anchor: position})
        self.position = pygame.Vector2(self.rect.center)
        self.start_position = pygame.Vector2(position)

        self.angle = 180
        self.velocity = pygame.Vector2(0, 0)
        self.decay = 0.98
        self.thrust = 0.0005
        self.max_speed = 0.1
        self.rotate_speed = 0.06
        self.direction = self.calculate_direction()
        self.backpedal = 2

    def calculate_direction(self):
        rads = math.radians(self.angle)
        return pygame.Vector2(math.sin(rads), math.cos(rads))

    def draw(self, surface):
        surface.blit(self.image, self.rect)

    def movement(self, keys, delta):
        if keys[pygame.K_r]:
            self.reset()

        # Forwards Thrust
        if keys[pygame.K_SPACE] or keys[pygame.K_w] or keys[pygame.K_UP]:
            speed = self.direction * self.thrust * delta
            self.velocity += speed

            if self.velocity.x > self.max_speed:
                self.velocity.x = self.max_speed

            if self.velocity.y > self.max_speed:
                self.velocity.y = self.max_speed

        # Backwards Thrust
        elif keys[pygame.K_DOWN] or keys[pygame.K_s]:
            speed = self.direction * self.thrust * delta / self.backpedal
            self.velocity -= speed

            if self.velocity.x < -self.max_speed:
                self.velocity.x = -self.max_speed

            if self.velocity.y < -self.max_speed:
                self.velocity.y = -self.max_speed

        if keys[pygame.K_LEFT] or keys[pygame.K_a]:
            self.angle = (self.angle + self.rotate_speed * delta) % 360
            self.update_rotation()
        elif keys[pygame.K_RIGHT] or keys[pygame.K_d]:
            self.angle = (self.angle - self.rotate_speed * delta) % 360
            self.update_rotation()

        # Drifting
        self.velocity * self.decay
        self.position += self.velocity * delta
        self.rect.center = self.position

    def reset(self):
        pass

    def update_rotation(self):
        self.image = pygame.transform.rotate(self.original_image, self.angle)
        self.rect = self.image.get_rect(center=self.rect.center)
        self.direction = self.calculate_direction()

    def update(self, keys, delta):
            self.movement(keys, delta)
            self.draw(window)


ship = Ship((400, 400))
run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    delta = clock.tick(60)
    keys = pygame.key.get_pressed()
    window.fill(pygame.Color('black'))
    ship.update(keys, delta)

    pygame.display.flip()
99 percent of computer problems exists between chair and keyboard.
Reply
#13
Here a smooth space movement example.
import pygame
import math
pygame.init()

window = pygame.display.set_mode((800, 800))
clock = pygame.time.Clock()

class Text(pygame.sprite.Sprite):
    def __init__(self, text, font, color, position, anchor="topleft"):
        super().__init__()
        self.font = font
        self.color = color
        self.position = position
        self.anchor = anchor
        self.render(text)

    def render(self, text):
        self.image = self.font.render(text, 1, self.color)
        self.rect = self.image.get_rect(**{self.anchor: self.position})

class Ship(pygame.sprite.Sprite):
    def __init__(self, position, anchor="center"):
        super().__init__()

        self.original_image = pygame.Surface((10, 20), pygame.SRCALPHA)
        self.original_image.fill((100, 200, 200))
        self.image = self.original_image.copy()

        self.rect = self.image.get_rect(**{anchor: position})
        self.position = pygame.Vector2(self.rect.center)
        self.start_position = pygame.Vector2(self.position)

        self.angle = 180
        self.velocity = pygame.Vector2(0, 0)
        self.decay = 0.999
        self.thrust = 0.0006
        self.max_speed = 0.8
        self.rotate_speed = 0.06
        self.direction = self.calculate_direction()
        self.backpedal = 2

        self.speed_cap = lambda n: max(min(n, self.max_speed), -self.max_speed)

    def calculate_direction(self):
        rads = math.radians(self.angle)
        return pygame.Vector2(math.sin(rads), math.cos(rads))

    def draw(self, surface):
        surface.blit(self.image, self.rect)

    def movement(self, keys, delta):
        if keys[pygame.K_r]:
            self.reset()

        # Forwards Thrust
        if keys[pygame.K_SPACE] or keys[pygame.K_w] or keys[pygame.K_UP]:
            self.velocity += self.direction * self.thrust * delta
            self.velocity.x = self.speed_cap(self.velocity.x)
            self.velocity.y = self.speed_cap(self.velocity.y)

        # Backwards Thrust
        elif keys[pygame.K_DOWN] or keys[pygame.K_s]:
            self.velocity -= self.direction * self.thrust * delta / self.backpedal
            self.velocity.x = self.speed_cap(self.velocity.x)
            self.velocity.y = self.speed_cap(self.velocity.y)

        if keys[pygame.K_LEFT] or keys[pygame.K_a]:
            self.angle = (self.angle + self.rotate_speed * delta) % 360
            self.update_rotation()
        elif keys[pygame.K_RIGHT] or keys[pygame.K_d]:
            self.angle = (self.angle - self.rotate_speed * delta) % 360
            self.update_rotation()

        # Drifting
        self.position += self.velocity
        self.rect.center = self.position
        self.velocity *= self.decay

    def reset(self):
        self.angle = 180
        self.velocity = pygame.Vector2(0, 0)
        self.update_rotation()
        self.position = pygame.Vector2(self.start_position)
        self.rect.center = self.position

    def update_rotation(self):
        self.image = pygame.transform.rotate(self.original_image, self.angle)
        self.rect = self.image.get_rect(center=self.rect.center)
        self.direction = self.calculate_direction()

    def update(self, keys, delta):
            self.movement(keys, delta)
            self.draw(window)


ship = Ship((400, 400))
run = True
current_velocity = pygame.Vector2(ship.velocity)
velocity = "x: {:.3f}, y: {:.3f}"
font = pygame.font.Font(None, 28)
text = Text(velocity.format(0, 0), font, pygame.Color('white'), (10, 10))
sprites = pygame.sprite.Group()
sprites.add(ship, text)
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    delta = clock.tick(60)
    keys = pygame.key.get_pressed()
    window.fill(pygame.Color('black'))
    sprites.update(keys, delta)
    if current_velocity != ship.velocity:
        current_velocity = pygame.Vector2(ship.velocity)
        text.render(velocity.format(*current_velocity))

    sprites.draw(window)

    pygame.display.flip()
99 percent of computer problems exists between chair and keyboard.
Reply
#14
Wow, this thing works amazingly. Thank-you so very much. I shall give this code a place of honor.
Reply
#15
Still needs a little work. It moving to fast on angles.
Max speed should be adjust by ship direction.
Let max speed equals 0.8.
angle 180 max speed would be (0, 0.8).
angle 45 max speed would be (0.565685, 0.565685).
99 percent of computer problems exists between chair and keyboard.
Reply
#16
Angle max speed fix.
import pygame
import math
pygame.init()

window = pygame.display.set_mode((800, 800))
clock = pygame.time.Clock()

class Text(pygame.sprite.Sprite):
    def __init__(self, text, font, color, position, anchor="topleft"):
        super().__init__()
        self.font = font
        self.color = color
        self.position = position
        self.anchor = anchor
        self.render(text)

    def render(self, text):
        self.image = self.font.render(text, 1, self.color)
        self.rect = self.image.get_rect(**{self.anchor: self.position})

class Ship(pygame.sprite.Sprite):
    def __init__(self, position, anchor="center"):
        super().__init__()

        self.original_image = pygame.Surface((10, 20), pygame.SRCALPHA)
        self.original_image.fill((100, 200, 200))
        self.image = self.original_image.copy()

        self.rect = self.image.get_rect(**{anchor: position})
        self.position = pygame.Vector2(self.rect.center)
        self.start_position = pygame.Vector2(self.position)

        self.angle = 180
        self.velocity = pygame.Vector2(0, 0)
        self.decay = 0.999
        self.thrust = 0.0006
        self.max_speed = 0.8
        self.rotate_speed = 0.06
        self.direction = self.calculate_direction()
        self.backpedal = 2

        #self.speed_cap = lambda n: max(min(n, self.max_speed), -self.max_speed)

    def calculate_direction(self):
        rads = math.radians(self.angle)
        return pygame.Vector2(math.sin(rads), math.cos(rads))

    def draw(self, surface):
        surface.blit(self.image, self.rect)

    def movement(self, keys, delta):
        if keys[pygame.K_r]:
            self.reset()

        # Forwards Thrust
        if keys[pygame.K_SPACE] or keys[pygame.K_w] or keys[pygame.K_UP]:
            self.speed_cap(self.direction * self.thrust * delta)

        # Backwards Thrust
        elif keys[pygame.K_DOWN] or keys[pygame.K_s]:
            self.speed_cap(-(self.direction * self.thrust * delta / self.backpedal))

        if keys[pygame.K_LEFT] or keys[pygame.K_a]:
            self.angle = (self.angle + self.rotate_speed * delta) % 360
            self.update_rotation()
        elif keys[pygame.K_RIGHT] or keys[pygame.K_d]:
            self.angle = (self.angle - self.rotate_speed * delta) % 360
            self.update_rotation()

        # Drifting
        self.position += self.velocity
        self.rect.center = self.position
        self.velocity *= self.decay

    def reset(self):
        self.angle = 180
        self.velocity = pygame.Vector2(0, 0)
        self.update_rotation()
        self.position = pygame.Vector2(self.start_position)
        self.rect.center = self.position

    def speed_cap(self, speed):
        rads = math.radians(self.angle)
        max_speed = pygame.Vector2(abs(math.sin(rads)), abs(math.cos(rads))) * self.max_speed
        if speed.x > 0:
            if self.velocity.x < max_speed.x:
                self.velocity.x += speed.x
        else:
            if self.velocity.x > -max_speed.x:
                self.velocity.x += speed.x

        if speed.y > 0:
            if self.velocity.y < max_speed.y:
                self.velocity.y += speed.y
        else:
            if self.velocity.y > -max_speed.y:
                self.velocity.y += speed.y

    def update_rotation(self):
        self.image = pygame.transform.rotate(self.original_image, self.angle)
        self.rect = self.image.get_rect(center=self.rect.center)
        self.direction = self.calculate_direction()

    def update(self, keys, delta):
            self.movement(keys, delta)
            self.draw(window)


ship = Ship((400, 400))
run = True
current_velocity = pygame.Vector2(ship.velocity)
velocity = "x: {:.3f}, y: {:.3f}"
font = pygame.font.Font(None, 28)
text = Text(velocity.format(0, 0), font, pygame.Color('white'), (10, 10))
sprites = pygame.sprite.Group()
sprites.add(ship, text)
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    delta = clock.tick(60)
    keys = pygame.key.get_pressed()
    window.fill(pygame.Color('black'))
    sprites.update(keys, delta)
    if current_velocity != ship.velocity:
        current_velocity = pygame.Vector2(ship.velocity)
        text.render(velocity.format(*current_velocity))

    sprites.draw(window)

    pygame.display.flip()
99 percent of computer problems exists between chair and keyboard.
Reply
#17
You've really gone above and beyond for me. I appreciate the effort immensely.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [PyGame] My Pygame Sprite not appearing... noodlespinbot 3 4,891 Oct-30-2020, 06:51 AM
Last Post: robinmurphy
  My Pygame Sprite not appearing... noodlespinbot 1 2,877 Apr-08-2020, 11:25 AM
Last Post: pyzyx3qwerty
  [PyGame] Sprite image.get_rect() moves sprite to 0, 0 michael1789 2 5,724 Dec-13-2019, 08:37 PM
Last Post: michael1789
  Pygame sprite not moving michael1789 1 3,869 Nov-10-2019, 03:54 AM
Last Post: michael1789
  Sprite not rendering Clunk_Head 2 3,438 Oct-03-2019, 11:27 AM
Last Post: Clunk_Head
  Need help making a sprite GalaxyCoyote 4 4,297 Aug-11-2019, 09:12 PM
Last Post: metulburr
  creating sprite mask pfaber11 5 4,904 Jun-12-2019, 09:39 PM
Last Post: pfaber11
  [PyGame] assigning rect to sprite pfaber11 1 2,782 May-18-2019, 05:39 PM
Last Post: metulburr
  moving a sprite pfaber11 3 3,322 May-15-2019, 12:52 PM
Last Post: pfaber11
  [PyGame] Need Help With Sprite ghost0fkarma 2 3,970 Jan-09-2018, 02:14 PM
Last Post: ghost0fkarma

Forum Jump:

User Panel Messages

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