1

I am new to the pygame scene and attempting to create my first pygame project. It's a 2d platforming side scroller, and I am having multiple issues with my bullet objects.

  1. Bullets only move in one direction
  2. The screen scrolls as the player moves, and bullets go off the screen and despite having a remove feature, the bullets reappear on the screen (in direction shot) 2/3 minutes later.
  3. The bullet movement is linked to the player movement such that when the player moves back, all bullet objects also move back by the same amount, giving the illusion that they have stopped. Being recently new I am not really sure how to go about fixing these issues. Any suggestions will be greatly appreciated.

import pygame
import math, random, sys, time
from pygame.locals import *
pygame.init()
jump = False
jump_offset = 0
jump_height = 250

k = pygame.key.get_pressed()


#Window Settings
w = 1280
h = 720
half_w = w /2
half_h = h /2
AREA = w*h

#Defining colours
BLACK = (   0,   0,   0)
WHITE = ( 255, 255, 255)

#Initialising the window
display = pygame.display.set_mode((w,h))
pygame.display.set_caption("Platformer") 
Clock = pygame.time.Clock()
FPS = 300

def events():
        for event in pygame.event.get():
                if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
                        pygame.quit()
                        sys.exit()

def do_jumping():
        global jump_height
        global jump
        global jump_offset
        if jump:
                jump_offset += 3

                if jump_offset >= jump_height:
                        jump = False
        elif jump_offset > 0 and jump == False:
                jump_offset -= 3

bg = pygame.image.load("background.png").convert()
bgWidth, bgHeight = bg.get_rect().size

stageWidth = bgWidth*2 
stagePosX = 0 

startScrollPosX = half_w

circleRadius = 25
circlePosX = circleRadius

pPosX = circleRadius
pPosY = 602
pVelX = 0

playersprite = pygame.image.load("playerSprite.png").convert_alpha()
playersprite = pygame.transform.scale(playersprite, (130,130))
bullets = []
bulletSprite = pygame.image.load("Bullet1.png").convert_alpha()
bulletSprite = pygame.transform.scale(bulletSprite, (20,10))
#------------------------MAIN PROGRAM LOOP------------------------#
next_bullet_time = 0
bullet_delay = 300
while True:
    current_time = pygame.time.get_ticks()
    events()
    do_jumping()
    k = pygame.key.get_pressed()
    if k[K_RIGHT]:
        pVelX = 2
    if k[K_LEFT]:
        pVelX = -2
    if k[K_UP] and jump == False and jump_offset == 0:
            jump = True
    if not k[K_RIGHT] and not k[K_LEFT]:
            pVelX = 0
    if k[K_SPACE]:
            if current_time > next_bullet_time:
                    next_bullet_time = current_time + bullet_delay
                    bullets.append([circlePosX+30, pPosY-20 - jump_offset])

    pPosX += pVelX
    if pPosX > stageWidth - circleRadius-25: pPosX = stageWidth - circleRadius-25
    if pPosX < circleRadius+55:pPosX = circleRadius+55
    if pPosX < startScrollPosX: circlePosX = pPosX
    elif pPosX > stageWidth - startScrollPosX: circlePosX = pPosX - stageWidth + w
    else:
        circlePosX = startScrollPosX
        stagePosX += -pVelX

    for b in range(len(bullets)):
            bullets[b][0] += 2

    for bullet in bullets[:]:
            if bullet[0] < 0:
                    bullets.remove(bullet)

    rel_x = stagePosX % bgWidth
    display.blit(bg,(rel_x - bgWidth, 0))
    if rel_x < w:
            display.blit(bg, (rel_x, 0))

    for bullet in bullets:
            display.blit(bulletSprite, pygame.Rect(bullet[0], bullet[1], 0, 0,))

    display.blit(playersprite, (int(circlePosX-80),pPosY-100 - jump_offset))

    pygame.display.update()
    Clock.tick(FPS)
    display.fill(BLACK)
c-x-berger
  • 991
  • 12
  • 30
  • 1
    "I cant reproduce the this behaviour" - It appears that this only works when the character has moved into the scrolling area of the stage. Allow the screen to scroll and then move left while shooting. – Jack Harrison Feb 14 '19 at 10:06

1 Answers1

0
  1. The screen scrolls as the player moves, and bullets go off the screen and despite having a remove feature, the bullets reappear on the screen (in direction shot) 2/3 minutes later.

This is caused by an integral numeric overflow. A bullet is never removed from the list bullets, after the bullet left the screen at the left. The x coordinate of the bullet is incremented continuously until it overflows. So the value of the x coordinate switches from the highest possible to the lowest possible value. Thsi causes that the bullet "appears" again at the right of the screen a while later.

Remove the bullets from the list bullets after the bullet left the screen:

w = display.get_width()
for b in [b for b in bullets if b[0] < 0 or b[0] > w]:
    bullets.remove(b)
  1. The bullet movement is linked to the player movement such that when the player moves back, all bullet objects also move back by the same amount, giving the illusion that they have stopped. Being recently new I am not really sure how to go about fixing these issues. Any suggestions will be greatly appreciated.

The the amount of scrolling has to be compensated when moving the bullets. Notice the scroll distance in every frame and add the amount to the bullet position:

pPosX += pVelX
scroll = 0
if pPosX > stageWidth - circleRadius-25: pPosX = stageWidth - circleRadius-25
if pPosX < circleRadius+55:pPosX = circleRadius+55
if pPosX < startScrollPosX: circlePosX = pPosX
elif pPosX > stageWidth - startScrollPosX: circlePosX = pPosX - stageWidth + w
else:
    circlePosX = startScrollPosX
    stagePosX += -pVelX
    scroll = -pVelX

for b in range(len(bullets)):
    bullets[b][0] += 2 + scroll

But note, the speed of the player, thereby also the scrolling and the speed of the bullets is equal. This leads to the appearance, that the bullets stand still, if the player moves forward, because bullets and player move forward with equal speed.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174