Mitchell Martin
Mitchell Martin

Reputation: 31

How to program angled movement (for a Sonic game)?

I've been trying to get a Sonic The Hedgehog game working in Pygame and it works for the most part. Sonic can run fast, jump across platforms like a normal platformer, gets affected by gravity, collects rings, etc. (check attached video)

https://imgur.com/a/q1YrAXO

However, I cannot for the life of me get Sonic to run at different angles and go up slopes and loops like in the real games. I am aware such a project doesn't exist in Pygame (for the public to access anyway) and making the precise, mathematically accurate scripts can be hard to do.

Problematic code:
(from levels.py)

    def update(self):
        self.sonic.update()
        self.camera.update(self.sonic)  # Follow Sonic

        # Keep Sonic grounded
        self.sonic.grounded = False  
        for tile in self.tile_group:
            if self.sonic.mask.overlap(tile.mask, (tile.rect.x - self.sonic.hitbox.x, tile.rect.y - self.sonic.hitbox.y)):  
                self.sonic.Yvel = 0
                self.sonic.grounded = True  
                self.sonic.jumped = False
                self.sonic.angle = tile.angle
                break 

(from characters.py)

        if not self.grounded:
            self.Yvel += self.gravityforce  # Apply gravity
            self.Yvel = min(self.Yvel, 10)  # Cap max fall speed
            self.Xvel = self.groundSpeed
        else:
            # Adjusting speed with some trigonometry
            self.Yvel = self.groundSpeed * math.sin(self.angle * -1)
            self.Xvel = self.groundSpeed * math.cos(self.angle)    

        self.x += self.Xvel
        self.rect.x = self.x  # Update self.rect with the new x coordinate
        self.y += self.Yvel
        self.rect.y = self.y
        self.hitbox.x = self.x
        self.hitbox.y = self.y

I am using Tiled for mapmaking by the way, I'm not sure if that helps in my situation. I've manually added an angle attribute to the tiles currently in use and given them unique angles such as 20, 45, 90, etc. (which is why Sonic suddenly changes angle and jumps/phases through floor at times).

With all that being said, can anyone help or offer some advice? Literally anything will be appreciated.

Upvotes: 2

Views: 65

Answers (1)

EuanG
EuanG

Reputation: 1082

You can use vector math so that the character follows the surface angle. Create a horizontal movement vector and then rotate it by the negative of the surface angle. That way when the character position is updated the movement should be aligned along the slope.

e.g.

if not self.grounded:
    # Apply gravity normally when in the air.
    self.Yvel += self.gravityforce
    self.Yvel = min(self.Yvel, 10)
else:
    # On the ground, create a horizontal movement vector…
    speed = self.groundSpeed * move_direction  # move_direction = -1, 0, or 1
    speed_vector = pygame.math.Vector2(speed, 0)
    # ...then rotate it to follow the surface.
    # (Note: the minus sign adjusts for your coordinate system.)
    speed_vector = speed_vector.rotate(-self.angle)
    self.Xvel = speed_vector.x
    self.Yvel = speed_vector.y

Example output of pygame script I wrote to show this working.

enter image description here

enter image description here

enter image description here

enter image description here

Upvotes: 1

Related Questions