0

I'm currently building a small plat former for my A-Level project and have ran into an issue that I or my friends cant solve. The player seems to glide a lot to the right and not to the left (note: the small glide on the left is whats needed) and platforms seem to not move correctly either, some do as needed like the walls but then floors don't and everything clips to the right side of the screen. Any suggestions would be helpful.

import pygame as pg
import random
import time
vec = pg.math.Vector2
#Player Props
PLAYER_ACC = 1.5
PLAYER_FRICTION = -0.12
PLAYER_GRAV = 0.8
#Display
WIDTH = 1800
HEIGHT = 1000
#Colours
WHITE = (225,225,255)
BLACK = (0,0,0)
RED = (225,0,0)
BLUE = (0,0,225)
PURPLE = (95, 11, 239)
ORANGE = (250,123,10)

class Player(pg.sprite.Sprite):
    def __init__(self, game):
        #Player spawn and location
        pg.sprite.Sprite.__init__(self)
        self.game = game
        self.image = pg.Surface((32, 32))
        self.image.fill(PURPLE)
        self.rect = self.image.get_rect()
        self.pos = vec(WIDTH/2, 200)
        self.vel = vec(0, 0)
        self.acc = vec (0, 0)

    def jump(self):
        #Jumping  when standing on playform
        self.rect.x += 1
        hits = pg.sprite.spritecollide(self, self.game.platformsA, False)
        self.rect.x -= 1
        if hits:
            self.vel.y = -20

    def update(self):
        #Player Movement/Gravity
        self.acc = vec (0, PLAYER_GRAV)
        self.vy = 1
        keys = pg.key.get_pressed()
        if keys[pg.K_LEFT]:
            self.acc.x = -PLAYER_ACC 
        if keys[pg.K_RIGHT]:
            self.acc.x = PLAYER_ACC 
        #Accelaration/Friction
        self.acc.x += self.vel.x * PLAYER_FRICTION
        self.vel += self.acc
        if self.vel[1]> 10:
            self.vel[1] = 10
        self.pos += self.vel + 0.25 * self.acc
        self.rect.midbottom = self.pos


class Platform(pg.sprite.Sprite):
    def __init__(self, x, y, w, h):
        #Building Platforms
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((w, h))
        self.rect = self.image.get_rect()
        self.image.fill(WHITE)
        self.rect.x = x
        self.rect.y = y


class Game:
    def __init__(self):
        #initialize game window etc
        pg.init()
        pg.mixer.init()
        self.screen = pg.display.set_mode((WIDTH, HEIGHT))
        self.screen.fill(BLACK)
        pg.display.update()
        pg.display.set_caption('Fur-Rush')
        self.clock = pg.time.Clock()
        self.running = True

    def new(self):
        #start new game/spawn everything
        self.all_sprites = pg.sprite.Group()
        self.platforms = pg.sprite.Group()
        self.platformsA = pg.sprite.Group()
        self.platformsB = pg.sprite.Group()
        self.platformsWa = pg.sprite.Group()
        self.platformsWb = pg.sprite.Group()
        self.player = Player(self)
        self.all_sprites.add(self.player)
        #Read platform dimensions from platforms.txt
        with open ('platforms.txt','r') as me:
            allplat = (me.read().split('\n'))
            newplat = [x.replace(',','').split(' ') for x in allplat]
        #Recursive loop to add platforms
        for x in range(len(newplat)):
            name = str(newplat[x][0])
            plat = Platform(int(newplat[x][1]), int(newplat[x][2]), int(newplat[x][3]), int(newplat[x][4]))
            self.all_sprites.add(plat)
            self.platforms.add(plat)
            if 'A' in str(name):
                self.platformsA.add(plat)
            elif 'B' in str(name):
                self.platformsB.add(plat)
            elif 'Wa' in str(name):
                self.platformsWa.add(plat)
            elif 'Wb' in str(name):
                self.platformsWb.add(plat)
        self.run()

    def run(self):
        #game loop
        self.playing = True
        while self.playing:
                self.clock.tick(60)
                self.events()
                self.update()
                self.draw()

    def update(self):
        #game loop - update
        self.all_sprites.update()
        #Top of platform
        hits = pg.sprite.spritecollide(self.player, self.platformsA, False)
        if hits:
            self.player.pos.y = hits[0].rect.top
            self.player.vel.y = 0
        #Bottom of platform
        hits2 = pg.sprite.spritecollide(self.player, self.platformsB, False)
        if hits2:
            self.player.pos.y = (hits2[0].rect.top + 42)
            self.player.vel.y = 0
        #Walls for left dectection
        hits3 = pg.sprite.spritecollide(self.player, self.platformsWa, False)
        if hits3:
            self.player.pos.x = (hits3[0].rect.right+16)
            self.player.vel.x = 0
        #Walls for right dectection
        hits4 = pg.sprite.spritecollide(self.player, self.platformsWb, False)
        if hits4:
            self.player.pos.x = (hits4[0].rect.left - 16)
            self.player.vel.x = 0

        #moving camra/display with player
            #left
        if self.player.rect.left <= WIDTH/3:
            self.player.pos.x += abs(self.player.vel.x)
            for plat in self.platforms:
                plat.rect.x += abs(self.player.vel.x)

            #right (ISSUES)
        if self.player.rect.right >=WIDTH/1.5:
            self.player.pos.x -= abs(self.player.vel.x)
            for plat in self.platforms:
                plat.rect.x -= abs(self.player.vel.x)

            #bottom
        if self.player.rect.top >= HEIGHT/1.25:
            self.player.pos.y += 0.1
            for plat in self.platforms:
                plat.rect.y -= 7

            #top
        if self.player.rect.bottom <= HEIGHT/5:
            self.player.pos.y -= 0.1
            for plat in self.platforms:
                plat.rect.y += 7

    def events(self):
        #game loop - events
        for event in pg.event.get():
            #check for closed window
            if event.type == pg.QUIT:
                if self.playing:
                    self.playing = False
                self.running = False
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_UP:
                    self.player.jump()

    def draw(self):
        # Game loop draw
        self.screen.fill(BLACK)
        self.all_sprites.draw(self.screen)
        #after drawing everything, flip
        pg.display.flip()

    def show_start_screen(self):
        #start screen
        pass

    def show_end_screen(self):
        #Level end screen
        pass

g = Game()
g.show_start_screen()
while g.running:
    g.new()
    g.show_end_screen()

pg.quit()

file needed to run code must be called "platforms.txt" and have the following:

plA, -300, 126, 1500, 10
plB, -300, 136, 1500, 10
plA2, -300, 536, 1100, 10
plB2, -300, 546, 1100, 10
plA3, -100, 336, 1300, 10
plB3, -100, 346, 1300, 10
plA4, 1000, 536, 200, 10
plB4, 1000, 546, 200, 10
plA5, 800, 1526, 200, 10
plB5, 800, 1536, 200, 10
plWa, -300, 136, 20, 400
plWb, 1180, 136, 20, 400
plWa2, 800, 546, 20, 1000
plWb2, 1000, 546, 20, 1000
  • May I point you to [this](https://stackoverflow.com/a/14357169/142637) question? Seperating the scrolling logic into its own function seems to be a good start. – sloth Oct 16 '18 at 09:18

1 Answers1

1

I didn't run the full code, but by a quick look the problem seems to be here:

if keys[pg.K_LEFT]:
    self.acc.x = -PLAYER_ACC 
if keys[pg.K_RIGHT]:
    self.acc.x = PLAYER_ACC 
#Accelaration/Friction
self.acc.x += self.vel.x * PLAYER_FRICTION

PLAYER_FRICTION is positive and you're adding/multiplying it without changing the direction of the friction.

You can either determine which direction you want it applied to (by multiplying it by -1 depending on the direction), or have separate frictions for separate directions, in case you want to apply some sort of weird effect.

So, you either have something like this:

PLAYER_FRICTION_LEFT = 0.12
PLAYER_FRICTION_RIGHT = -0.12
...
...
    if keys[pg.K_LEFT]:
        self.acc.x = -PLAYER_ACC 
        self.acc.x += self.vel.x * PLAYER_FRICTION_LEFT
    if keys[pg.K_RIGHT]:
        self.acc.x = PLAYER_ACC 
        self.acc.x += self.vel.x * PLAYER_FRICTION_RIGHT

Or something like this:

if keys[pg.K_LEFT]:
    self.acc.x = -PLAYER_ACC
    friction = -PLAYER_FRICTION
if keys[pg.K_RIGHT]:
    self.acc.x = PLAYER_ACC
    friction = PLAYER_FRICTION

self.acc.x += self.vel.x * friction
ChatterOne
  • 3,381
  • 1
  • 18
  • 24
  • Thanks for the suggestion and I tried this but it only seemed to make the problem worse by speeding the player up so much that it bypasses the wall and launches outside the map. – Howey The 2nd FoxGaming Oct 17 '18 at 08:47
  • 1
    If it speeds up instead of slowing down, then you need to reverse when the `-` sign is used. Also, if it bypasses the wall: welcome to the world of collision detection. If your sprites move fast enough there's a chance that you'll skip collision because they "jump" between positions. You can find quite a few questions on stackoverflow with the same problem. Alternatively, have a look on https://gamedev.stackexchange.com – ChatterOne Oct 17 '18 at 09:05