Pygame的多个子弹问题

时间:2019-02-13 16:27:19

标签: python pygame

我是pygame的新手,正在尝试创建我的第一个pygame项目。这是一个2D平台化侧面滚动器,而我的子弹对象存在多个问题。

  1. 子弹只能向一个方向移动
  2. 屏幕随着玩家的移动而滚动,子弹离开屏幕,尽管具有删除功能,但子弹会在2/3分钟后重新出现在屏幕上(朝拍摄方向)。
  3. 子弹运动与玩家的运动相关联,因此当玩家向后移动时,所有子弹对象也向后移动相同的数量,从而产生了它们已经停止的错觉。 作为最近的新手,我不确定如何解决这些问题。任何建议将不胜感激。

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)

1 个答案:

答案 0 :(得分:0)

  
      
  1. 屏幕随着玩家的移动而滚动,子弹离开屏幕,尽管具有删除功能,但子弹会在2/3分钟后重新出现在屏幕上(朝拍摄方向)。
  2.   

这是由整数溢出引起的。项目符号离开屏幕左侧之后,项目符号将永远不会从列表bullets中删除。项目符号的x坐标不断增加,直到溢出为止。因此,x坐标的值从可能的最高值切换到可能的最低值。这导致子弹稍后再次“出现”在屏幕右侧。

项目符号离开屏幕后,从列表bullets中删除项目符号:

w = display.get_width()
for b in [b for b in bullets if b[0] < 0 or b[0] > w]:
    bullets.remove(b)
  
      
  1. 子弹运动与玩家的运动相关联,因此当玩家向后移动时,所有子弹对象也向后移动相同的数量,从而产生了它们已经停止的错觉。作为最近的新手,我不确定如何解决这些问题。任何建议将不胜感激。
  2.   

移动子弹时必须补偿滚动量。注意每一帧的滚动距离,并将其添加到项目符号位置:

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

但是请注意,玩家的速度,因此滚动和子弹的速度都相等。这导致外观,如果玩家向前移动,则子弹停滞不前,因为子弹和玩家以相同的速度向前移动。