由于我的程序生成,我的平台覆盖了我的退出块,有人知道如何解决这个问题吗

My platform covers my exit block due to my procedural generation, does anybody know how to solve this

我一直在使用 pygame 制作 2d 平台游戏,并在我的代码中引入了程序生成,但是我发现有时,我的平台覆盖了我的出口块,导致无法完成关卡,我有尝试移动出口块以减少发生这种情况的可能性,但这仍然不能解决问题,而是将其扫到地毯下。有人有解决办法吗?

import pygame    #imports pygame
import time    #imports the timer so I can use the tick function to make game 60fps
import math    #imports maths
import sys    #imports system
import random
from random import *
from time import *    #imports all modules from time
from pygame import *    #imports all pygame files
from pygame.math import *
from pygame.mixer import *

win_height = 750    #height of window is 750 pixles
win_width = 1050    #height of window is 1050 pixels
half_win_width = int(win_width / 2)    #will be used to centre camera
half_win_height = int(win_height / 2)

white=(255, 255, 255)
black=(0, 0, 0)
gray=(50, 50, 50)
red=(255, 0, 0)
green=(0, 255, 0)
blue=(0, 0, 255)
yellow=(255, 255, 0)

display = (win_width, win_height)    #creates the window as 500*500 pixels
depth = 32    #prevents infinate recursion
flags = 0    #message to Les: I don't really know what this does, however I have seen it in many places being used, therefore I assumed that it was important
camera_slack = 30    #how many pixels the player can move before the camera moves with them

pygame.init()
mixer.init()
pygame.mixer.music.load('Caravan Palace - Lone Digger [Clip officiel].mp3')    #plays music within my game folder
#pygame.mixer.music.load('Toby Fox - Megalovania [Electro Swing Remix].mp3')    #plays music within my game folder
pygame.mixer.music.play(-1)    #loops music infinately

myfont = pygame.font.SysFont('Comic Sans MS', 30)

def main_menu():
    pygame.init()
    screen = pygame.display.set_mode(display, flags, depth)
    pygame.display.set_caption("Super Castlevania Man")
    timer = pygame.time.Clock()


def main():    #main game function
    global cameraX, cameraY
    pygame.init()
    screen = pygame.display.set_mode(display, flags, depth)
    pygame.display.set_caption("Super Castlevania Man")
    timer = pygame.time.Clock()

    move_cameraX = 0
    move_cameraY = 0

    up = down = left = right = running = False
    background = pygame.Surface((32,32))    #the background takes up space on the screen
    background.convert()
    background.fill(pygame.Color("#000000"))    #background is black
    entities = pygame.sprite.Group()
    player = Player_class(32, 32*15)    #the player is 32*32 pixels large
    platforms = []

    x = y = 0
    blank_level = [
        "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "P                               P",
        "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP"]
    def print_level(level):
        for row in level:
            print(row)

    new_level = blank_level

    #Randomly Generate levels
    #First do the platforms
    #Pick a random number of platforms (6 - 12)
    #For those then pick a row which doesn't have one on (I.e. only has two Ps in), and pick a start cell and a length (3-7) -> ensure it cuts off @ wall
    #Pick a random empty cell for E to go into
    new_level[5] = new_level[5][0:4]+"E"+new_level[5][5:]
    #Replacing the string with string before position, putting letter in, then string after
    for z in range (0,15):
        plat_len = (randint(1, 7))
        plat_start = (randint(3, 29))
        row = (randint(3, 19))
        new_level[row] = new_level[row][0:plat_start]+("P"*plat_len)+new_level[row][plat_start+plat_len:]



    for row in blank_level:
        for col in row:
            if col == "P":
                p = Platform(x, y)    #makes P a solid object
                platforms.append(p)
                entities.add(p)
            if col == "E":
                e = Exit_block(x, y)
                platforms.append(e)
                entities.add(e)
            x += 32
        y += 32
        x = 0

    entities.add(player)
    enemy = Enemy(60, 200, player)    #Spawns enemy
    enemy_list = pygame.sprite.Group()    #creates an enemy group
    enemy_list.add(enemy)    #Add an enemy to the group

    while 1:
        timer.tick(60)    #makes game run at 60 frames per second

        for e in pygame.event.get():    #shortens event to e
            if e.type == QUIT:
                return
            if e.type == KEYDOWN and e.key == K_ESCAPE:
                return
            if e.type == KEYDOWN and e.key == K_UP:
                up = True
                move_cameraY = -10
            if e.type == KEYDOWN and e.key == K_DOWN:
                down = True
                move_cameraY = 10
            if e.type == KEYDOWN and e.key == K_LEFT:
                left = True
                move_cameraX = -10
            if e.type == KEYDOWN and e.key == K_RIGHT:
                right = True
                move_cameraX = 10
            if e.type == KEYDOWN and e.key == K_SPACE:
                running = True

            if e.type == KEYUP and e.key == K_UP:
                up = False
                move_cameraY = 0
            if e.type == KEYUP and e.key == K_DOWN:
                down = False
                move_cameraY = 0
            if e.type == KEYUP and e.key == K_RIGHT:
                right = False
                move_cameraX = 0
            if e.type == KEYUP and e.key == K_LEFT:
                left = False
                move_cameraX = 0
            if e.type == KEYUP and e.key == K_RIGHT:
                right = False        

        # Update the game.
        for e in enemy_list:
            e.update(platforms)
        player.update(up, down, left, right, running, platforms)

        # Draw everything.
        for y in range(32):    #draws the background
            for x in range(32):
                screen.blit(background, (x * 32, y * 32))
        entities.draw(screen)
        enemy_list.draw(screen)
        pygame.display.flip()  # You need only one flip or update call per frame.


class Entity(pygame.sprite.Sprite):    #makes player a sprite
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)    #sets sprite to initiate


class Player_class(Entity):    #defines player class
    def __init__(self, x, y):    #x is the player x coordinate, y is the player y coordinate
        Entity.__init__(self)    #the player is an entity
        self.xvel = 0    #how fast the player is moving left and right
        self.yvel = 0    #how fast the player is moving up and down
        self.onGround = False    #assumes the player is in the air
        self.image = pygame.Surface((32,32))    #the player is 32*32 pixels
        self.image.fill(pygame.Color("#0000FF"))    #makes the player blue
        self.rect = pygame.Rect(x, y, 32, 32)
        self.x = x
        self.y = y

    def update(self, up, down, left, right, running, platforms):
        if up:
            if self.onGround:
                self.yvel -= 10    #only jump if player is on the ground
        if down:
            pass
        if running:
            self.xvel = 12
        if left:
            self.xvel = -8
        if right:
            self.xvel = 8
        if not self.onGround:

            self.yvel += 0.3    #only accelerate with gravity if in the air

            if self.yvel > 100: self.yvel = 100    #terminal velocity = 100
        if not(left or right):
            self.xvel = 0

        self.rect.left += self.xvel    #falls or jumps

        self.collide(self.xvel, 0, platforms)    #creates collisions along the x axis

        self.rect.top += self.yvel    #creates collisions along the y axis

        self.onGround = False;    #assumes that the player is in the air
        # do y-axis collisions
        self.collide(0, self.yvel, platforms)

    def collide(self, xvel, yvel, platforms):
        for p in platforms:
            if pygame.sprite.collide_rect(self, p):
                if isinstance(p, Exit_block):
                    pygame.quit()
                    sys.exit()
                if xvel > 0:
                    self.rect.right = p.rect.left
                if xvel < 0:
                    self.rect.left = p.rect.right
                if yvel > 0:
                    self.rect.bottom = p.rect.top
                    self.onGround = True
                    self.yvel = 0
                if yvel < 0:
                    self.rect.top = p.rect.bottom


class Platform(Entity):
    def __init__(self, x, y):
        Entity.__init__(self)
        self.image = pygame.Surface((32, 32))
        self.image.fill(pygame.Color("#FFFFFF"))
        self.rect = pygame.Rect(x, y, 32, 32)


class Exit_block(Platform):
    def __init__(self, x, y):
        Platform.__init__(self, x, y)
        self.image.fill(pygame.Color("#00FF00"))#exit block is green


class Enemy(Entity):
    def __init__(self, x, y,player):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((32, 32))
        self.xvel = 0
        self.yvel = 0
        self.image.fill(pygame.Color("#FF0000"))    #Enemy is red
        self.rect = pygame.Rect(x, y, 32, 32)
        self.player = player

    def move(self, speed=5):    # chase movement
        if self.rect.x > self.player.rect.x:    # Movement along x direction 
            self.xvel = -speed
        elif self.rect.x < self.player.rect.x:
            self.xvel = speed
        if self.rect.y < self.player.rect.y:    # Movement along y direction
            self.yvel = speed
        elif self.rect.y > self.player.rect.y:
            self.yvel = -speed


    def collide(self, xvel, yvel, platforms):
        # Check if the enemy collides with the player.
        if self.rect.colliderect(self.player.rect):
            pygame.quit()
            sys.exit()
        for p in platforms:
            if pygame.sprite.collide_rect(self, p):
                if xvel > 0:
                    self.rect.right = p.rect.left
                if xvel < 0:
                    self.rect.left = p.rect.right
                if yvel > 0:
                    self.rect.bottom = p.rect.top
                if yvel < 0:
                    self.rect.top = p.rect.bottom

    def update(self, platforms):
        self.move()  # Set the velocity.

        self.rect.left += self.xvel
        self.collide(self.xvel, 0, platforms)    #creates collisions along the x axis

        self.rect.top += self.yvel    #creates collisions along the y axis
        self.collide(0, self.yvel, platforms)


if __name__ == "__main__":
    main()
    pygame.quit()

最简单的解决方案是在创建随机平台后创建退出块。

像这样:

#Randomly Generate levels
#First do the platforms
#Pick a random number of platforms (6 - 12)
#For those then pick a row which doesn't have one on (I.e. only has two Ps in), and pick a start cell and a length (3-7) -> ensure it cuts off @ wall
#Replacing the string with string before position, putting letter in, then string after
for z in range (0,15):
    plat_len = (randint(1, 7))
    plat_start = (randint(3, 29))
    row = (randint(3, 19))
    new_level[row] = new_level[row][0:plat_start]+("P"*plat_len)+new_level[row][plat_start+plat_len:]

#Pick a random empty cell for E to go into
new_level[5] = new_level[5][0:4]+"E"+new_level[5][5:]