【问题标题】:Rapid spawning in Pygame [closed]Pygame中的快速产卵[关闭]
【发布时间】:2015-02-07 16:15:30
【问题描述】:

好的,我一周前才开始使用 pygame,但我想我了解基础知识。我的游戏很简单,左右移动气球来躲避进来的螺丝。 我成功地让气球左右移动,但我对课程非常不熟悉,我不知道有什么其他方法可以在屏幕上快速产生多个螺丝。任何帮助将不胜感激。

这是我的代码:

import pygame
from pygame.locals import *
import sys
import time
pygame.init()

screen = pygame.display.set_mode((600,600))
pygame.display.set_caption('Baloon Pop')


baloon_size = (70,70)

white = (255,255,255)
cyan = (0,255,255)
red = (255,0,0)

screen.fill(cyan)

baloon = pygame.image.load('/users/Gaming/Desktop/rsz_baloon.png')
screw = pygame.image.load('/users/Gaming/Desktop/rsz_screw_png3029.png')



FPS = 30
fps_time = pygame.time.Clock()

baloonX = 280
baloonY = 500

import random
screwX = random.randint(0,600)
screwY = 20

LEFT = "left"
RIGHT = "right"
movement = "down"




while True:
    screwY = screwY+10
    screen.fill(cyan)
    screen.blit(screw, (screwX,screwY))
    screen.blit(baloon, (baloonX,baloonY))

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == KEYDOWN:
            if event.key == K_RIGHT:
                baloonX = baloonX+30
                if baloonX >= 580:
                    baloonX = baloonX -30
            elif event.key == K_LEFT:
                baloonX = baloonX -30
                if baloonX <=-30:
                    baloonX = baloonX+30






    pygame.display.update()
    fps_time.tick(FPS)

【问题讨论】:

  • 查找面向对象编程的教程(并阅读)。在这样一个广泛(和模糊)的问题上,您不太可能在这里得到太多帮助。

标签: python pygame spawning


【解决方案1】:

首先,我建议使用一个类来控制你的播放器。 这使得绘制和检测碰撞更容易。 一个简单的方法是:

class Player:

    def __init__(self, x, speed):
        self.x = x
        self.speed = speed
        self.moveright = 0
        self.moveleft = 0

    def update(self, time_passed):
        if self.moveright:
            self.x += self.speed * time_passed
        if self.moveleft:
            self.x -= self.speed * time_passed

然后,一个类似的类来控制你的敌人。

class Enemy:

    def __init__(self, x, speed):
        self.x = x
        self.y = 0
        self.speed = speed

    def update(self, time_passed):
        self.y += self.speed*time_passed

在这里, time_passed 是您的 Clock() 对象的刻度值。 screen 是你的 pygame.display 表面。

现在您已经将敌人物化了,您可以创建一个列表来存储敌人类的实例。

正如我所建议的,使用这种机制可以使您的游戏更加流畅。 不建议对每个 KEYDOWN 事件使用增量。

创建一个列表来存储敌人实例并创建玩家实例:

Enemylist = []
Player1 = Player(<SomeXValue>,0.1)

继续创建随机敌人。 如果你需要创建,比如说每 n 个循环一个螺丝钉(即一个 Enemy()), 您可以创建一个在该时间间隔内激活的标志。 你可以有一个变量“计数”,它决定了这一点。 初始值可以为 0,然后在每个循环中将其增加 1。 (例如:如果您希望每 5 个循环生成一个敌人,请将 n 替换为 5。)

if count % n == 0:    
    Enemylist.append(Enemy(random.randint(0,<YourScreenSize>),0.1))
if count > 1000:
    count = 0

也就是说,在屏幕的任意位置生成一个敌人,然后让他们向下移动。 0.1 只是一个采样速度。

现在,到循环部分... 你的 for 事件循环应该有一个 KEYDOWN 和一个 KEYUP 检查,以确保单次按键。 这里,Player1 是 Player 类实例的名称。

for event in pygame.event.get():

    if event.type == QUIT:
        pygame.quit()
        sys.exit()
    if event.type == KEYDOWN:
        if event.key == K_RIGHT:
            Player1.moveright = 1
        if event.key == K_LEFT:
            Player1.moveleft = 1
    if event.type == KEYUP:
        if event.key == K_RIGHT:
            Player1.moveright = 0
        if event.key == K_LEFT:
            Player1.moveleft = 0

添加检查以确保玩家不会离开屏幕。

玩家的动作现在已经完成,符合游戏的要求。

调用玩家、敌人的update()函数并翻转屏幕。

Player1.update(time_passed)
<blit background image or color here>
screen.blit(<image_name>, (Player1.x, <PlayerYPosition>))
for enemy in Enemylist:
    enemy.update(time_passed)
    screen.blit(<image_name>, (enemy.x, enemy.y))
count += 1
pygame.display.update()

现在,添加碰撞检查以完成您的游戏。 此外,您还可以移除已超出屏幕的实例以节省内存。

【讨论】:

    【解决方案2】:

    为了让您的程序不那么复杂,您需要为气球和螺丝设置一些类。假设您只从左向右移动,第一个类将是为您的播放器准备的,看起来像这样:

    class Player(pygame.sprite.Sprite):
        def __init__(self, image_file, location):
            pygame.sprite.Sprite.__init__(self)
            self.image = pygame.image.load(image_file)
            self.rect = pygame.image.get_rect()
            self.rect.top, self.rect.left = location
    

    这段代码将使您的气球成为一个精灵,准备好检测碰撞。你的螺丝类看起来很相似,只是在类的__init__ 部分中多了一个movelocation 函数和speed

    class Screws(pygame.sprite.Sprite):
        def __init__(self, image_file, left, speed):
            pygame.sprite.Sprite.__init__(self)
            self.image = pygame.image.load(image_file)
            self.rect = pygame.image.get_rect()
            self.rect.top = 50
            self.rect.left = left
            self.speed = speed
    
        def move(self):
            self.rect = self.rect.move(self.speed)
    

    这个类使螺丝精灵,也准备好检测。这完成了类部分。现在对这些精灵等进行分组:

    balloon = Player('/users/Gaming/Desktop/rsz_baloon.png', [a, b])     
    screw = Screws('/users/Gaming/Desktop/rsz_screw_png3029.png', random.randint(0, <ScreenSize>), c)
    ScrewGroup = pygame.sprite.Group()
    

    再一次,变量是可变的,但c 越高,螺丝掉的越快。 ab 将决定气球的位置,random.randint() 将决定螺丝的位置。 self.rect.top 是一种通过将其用作rect 的“顶部”侧的位置来查找位置的方法。在这种情况下,它保持不变。 self.rect.left 相同,但它是 rect 的“左侧”侧的位置。现在转到气球的移动部分,为了避免过度按下 UP 和 DOWN 键(以及疲劳),在后面添加这行代码:

    delay = 100
    interval = 50
    pygame.key.set_repeat(delay, interval)
    on = True
    screwy = 0
    

    delay 是每次激活 KEYDOWN 之间的毫秒数,interval 是等待开始重复 KEYDOWN 的毫秒数。这将帮助用户,让他只需按住 LEFT 或 RIGHT 箭头键,气球将继续朝所需方向前进。 onscrewy 变量将在下一节中讨论。接下来,while循环就差不多了:

    while True:
        screen.blit(balloon.image, balloon.rect)
        while int(screwy - 1) > -1:
            screen.blit(screw.image, screw.rect)
        pygame.display.flip()
    

    second while 循环会产生尽可能多的螺丝,只要 screwy - 1 的 小于 -1 (负 1)。这也会翻转屏幕以避免屏幕上留下任何“轨迹”。现在到气球的移动部分:

    for event in pygame.event.get():
        #Remember to do this : from pygame.locals import *#
        if event.type == QUIT:
            on = False
            #Remember to import sys!#
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key = K_LEFT:
                balloon.rect.left -= 30
            elif event.key == K_RIGHT:
                #This can only work if (width_of_the_picture - a) is equal to 30#
                balloon.rect.left += int(width_of_the_picture - a)
    

    这将允许您移动气球(您可以按住键保持气球移动,就像在真正的电子游戏中一样)。接下来是螺丝的继续产卵:

    if screwy < 10:
        ScrewGroup.append(Screws('/users/Gaming/Desktop/rsz_screw_png3029.png', random.randint(0, b), [0, 15]))
        screwy += 1
    

    这将在随机位置生成螺丝(相同的self.rect.top 值使其看起来更逼真)。在这种情况下,b 将等于屏幕的宽度。最后是精灵检测:

    if pygame.sprite.spritecollide(balloon, ScrewGroup, True):     
        on = False
        sys.exit()
        pass
    

    这会检测气球是否与螺钉发生碰撞。如果这是真的,那么你可以决定。您可以退出 while 循环并退出程序,这是一种方法。但是,如果您打算做类似print 'Game Over! 的事情,请在执行on = False/sys.exit() 之前添加该行,这将立即退出循环/程序。您将需要重新 blit 图像并让屏幕退出平滑 (pygame.quit):

        screen.fill([255, 255, 255])
        screen.blit(balloon.image, balloon.rect)
        while int(screwy - 1) > -1:
            screen.blit(screw) 
        pygame.display.flip()
    pygame.quit()
    

    记得将pygame.quit() 放在while 循环之外,否则屏幕将立即消失。当然,做一些代码来防止气球退出屏幕。将 KEYDOWN 部分更改为此应该可以:

    elif event.type == pygame.KEYDOWN:
        if event.key == K_LEFT:
            if int(balloon.rect.left) - 30 < 0:
                pass
            elif int(balloon.rect.left) - 30 >= 0:
                balloon.rect.left -= 30
        elif event.key == K_RIGHT:
            if int(balloon.rect.left) + (<Width_OF_Balloon> - a) > <Width_OF_Screen>:
                pass
            elif int(balloon.rect.left) + (<Width_OF_Balloon> - a) <= <Width_OF_Screen>:
                #This can only work if (<Width_OF_Balloon> - a) is equal to 30#
                baloon.rect.left + (<Width_OF_Balloon> - a)
    

    如果向左/向右移动一次使气球部分离开屏幕,则程序将不允许气球向左/向右移动,而不会对pass 执行任何操作。这应该会显着改善您的程序并回答您的问题。希望对你有帮助!

    【讨论】:

      猜你喜欢
      • 2020-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-13
      • 1970-01-01
      • 1970-01-01
      • 2011-07-29
      相关资源
      最近更新 更多