问题
I am currently taking an A level computer science course in which I have to create a game for a project. I know this code is probably not efficient but I am trying to keep it to my own work and would like a hand with one bit that I am confused on.
I am trying to scroll the screen right and left which i know is done by moving every object on the screen in the relevant direction. I have created boundaries for which the screen should start to move when the robot is within them. But for the code i have written the platforms move without them being updated on the screen and the speed of the robot changes when it is within these boundaries
Any ideas or help would be appreciated.
import pygame as pg
import time
import random
pg.init()#initiates pygame
display_height = 690#Creates width and height of screen
display_width = 1024
#Colours
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
sky = (73,71,65) # grey
Robot_height = 99#Height of robot
Robot_width = 112#Width of robot
lives = 3 #Robot Lives
Bullet_Fired = False
PowerUp_Active = False
Robot_acc = 0.3 #Robot Acceleration
vec = pg.math.Vector2
gameDisplay = pg.display.set_mode((display_width,display_height)) #Sets display properties of window
pg.display.set_caption ("Game") #Title on window
clock = pg.time.Clock()
robotImg = pg.image.load("robot1.png") #Loads robots image
#Class for platforms
class Platform(pg.sprite.Sprite):
def __init__(self, x,y,w,h):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((w,h))
self.image.fill(blue)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
#List of platforms
PLATFORM_LIST = [(0,display_height - 40,display_width,40),
(display_width /2 - 50,display_height * 3/4,100,20)]
#Platform group
platforms = pg.sprite.Group()
#class for robot
class RobotClass(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((Robot_width,Robot_height))
self.rect = self.image.get_rect()
self.rect.center = (display_width / 2, display_height / 2)
self.RobotPos = vec(display_width / 2, display_height / 2)
self.bottom = (0,0)
self.vel = vec(0, 0)
self.acc = vec(0, 0.3)
#Creates Robot
Robot = RobotClass()
for plat in PLATFORM_LIST:
p = Platform(*plat)
platforms.add(p)
def draw():
for plat in PLATFORM_LIST:
p = Platform(*plat)
pg.draw.rect(gameDisplay, blue, (p))
#Jump function
def jump():
#Checks pixel below robot to see if there is a collision
Robot.rect.x = Robot.rect.x +1
hits = pg.sprite.spritecollide(Robot , platforms, False)
Robot.rect.x = Robot.rect.x -1
if hits:
#Gives robot velocity of 5 upwards
Robot.vel.y = -10
#game loop
def game_loop():
pg.draw.rect(gameDisplay, red, Robot.rect, 2)
Robot_friction = -0.3 #Friction value
vec = pg.math.Vector2 #Setting vec as vector quantity
while True:
for event in pg.event.get():
if event.type == pg.QUIT:
pg.quit
quit()
#Starts acceleration when key is pressed
if event.type == pg.KEYDOWN:
if event.key == pg.K_LEFT:
Robot.acc.x = -Robot_acc
elif event.key == pg.K_RIGHT:
Robot.acc.x = Robot_acc
elif event.key == pg.K_UP:
jump()
#Adds friction to accleration to slow robot down when key is not being pressed
if event.type == pg.KEYUP:
if event.key == pg.K_LEFT or event.key == pg.K_RIGHT:
Robot.acc.x = Robot.acc.x * Robot_friction
#Adjusts velocity of robot by adding the acceleration on each cycle
Robot.vel = Robot.vel+ Robot.acc
#Fills background
gameDisplay.fill(sky)
#Draws the platforms to the screen and adds them to platform group
draw()
#Changes Robot position according to its velocity,acceleration and the friction
Robot.RobotPos = Robot.RobotPos + Robot.vel + 0.5 * Robot.acc
#Loads robot onto screen
gameDisplay.blit(robotImg,(Robot.rect))
pg.draw.rect(gameDisplay, red, Robot.rect, 2)
#Updates display
pg.display.update()
clock.tick(60)
#Sets bottom of robot to its position
Robot.rect.midbottom = Robot.RobotPos
#Collision detection
if Robot.vel.y > 0:
hits = pg.sprite.spritecollide(Robot , platforms, False)
if hits:
#Puts Robot on top of platform
Robot.RobotPos.y = hits[0].rect.top + 1
Robot.vel.y = 0
#Scrolling
if Robot.rect.left < display_width/4:
print("left")
Robot.RobotPos.x = Robot.RobotPos.x - abs(Robot.vel.x)
print(Robot.vel)
for plat in platforms:
plat.rect.x = plat.rect.x + abs(Robot.vel.x)
pg.draw.rect(gameDisplay, blue, (PLATFORM_LIST[0]))
if Robot.rect.right > (display_width-display_width/4):
print("right")
Robot.RobotPos.x = Robot.RobotPos.x + abs(Robot.vel.x)
print(Robot.vel)
for plat in platforms:
plat.rect.x = plat.rect.x - abs(Robot.vel.x)
#Sets top velocity of robot
if Robot.vel.x > 6:
Robot.vel.x = 6
if Robot.vel.x < -6:
Robot.vel.x = -6
#Makes robot velocity = 0 when it is close to 0
if Robot.vel.x < 0.05 and Robot.vel.x > -0.05:
Robot.acc.x = 0
Robot.vel.x = 0
game_loop()
pg.quit()
quit()
回答1:
So here we go. Here you are updating the platforms if the robot reached the limit:
for plat in platforms:
plat.rect.x = plat.rect.x - abs(Robot.vel.x)
But when you draw the platforms you draw from the original PLATFORM_LIST list:
def draw():
for plat in PLATFORM_LIST:
p = Platform(*plat)
pg.draw.rect(gameDisplay, blue, (p))
So what ends up happening is even though you are updating the platforms properly, you are drawing from the original list, so you are not drawing the updated the list. You should draw from the platform list you are updating:
def draw():
for plat in platforms:
pg.draw.rect(gameDisplay, blue, plat)
Second, I discovered once you hit the left scroll limit, the movement back to the right direction moved the robot the wrong way. replace this:
if Robot.rect.left < display_width/4:
Robot.RobotPos.x = Robot.RobotPos.x - abs(Robot.vel.x)
with this (the minus sign switched over to the plus sign):
if Robot.rect.left < display_width/4:
Robot.RobotPos.x = Robot.RobotPos.x + abs(Robot.vel.x)
Just a couple things I found while playing around with the game.
Update
There is also an issue with rounding. Pygame rectangles take integers. Your calculation of velocity yields a float and you are trying to add that to the x of the rectangle here:
for plat in platforms:
plat.rect.x = plat.rect.x - abs(Robot.vel.x)
This causes issues with rounding that show up in the display (platforms) moving in peculiar ways. You can make them ints:
for plat in platforms:
plat.rect.x = plat.rect.x - int(abs(Robot.vel.x))
Otherwise you will have to make the platforms like you do the Robot and deal in vec()
来源:https://stackoverflow.com/questions/43077272/pygame-scrolling