Reputation: 31
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)
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
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.
Upvotes: 1