1

我正在制作一款类似于 Space Invaders 的游戏。有没有办法检查拍摄频率较低的事件?现在,如果你足够快地按下空格键,顶部镜头会在它到达屏幕顶部之前消失。我想知道你是否可以检查像 2/(到达顶部需要多长时间)这样的射击事件。

这是我的代码:

#-----!!!!SPACE INVADERS!!!!-----
import pygame, sys
from pygame.locals import *
#-----MAIN FUNCTIONS-----
def movement(move_x):
    if event.type == KEYDOWN:
        if event.key == K_LEFT:
            move_x = -5
        if event.key == K_RIGHT:
            move_x = 5
    if event.type == KEYUP:
        if event.key == K_LEFT:
            move_x = 0
        if event.key == K_RIGHT:
            move_x = 0
    return move_x


#-----FFRAME RAEE / SCREEN SIZE-----
clock = pygame.time.Clock()
w,h = 800,800
screen = pygame.display.set_mode((w,h))

#-----SETTING IMAGES-----
pygame.mouse.set_visible(0)

ship = pygame.image.load("spaceship.png")
ship = pygame.transform.scale(ship,(100,50))
ship_top = screen.get_height() - ship.get_height()
ship_left = screen.get_width()/2 - ship.get_width()/2

screen.blit(ship, (ship_left,ship_top))

shot1 = pygame.image.load("SingleBullet.png")
shot1 = pygame.transform.scale(shot1,(25,25))
shot2 = shot1
shot_count = 0
shot_y = 0
shot_y_2 = 0

#-----GLOBAL VARIABLES-----
x = 0
resetShot = 0
move_x = 0
#-----MAIN GAME LOOP-----
while True:
    clock.tick(60)
    screen.fill((0,0,0))
    #x,y = pygame.mouse.get_pos()
    screen.blit(ship, (x-ship.get_width()/2,ship_top))

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

        move_x = movement(move_x)

        if event.type == KEYDOWN:
            if event.key == K_SPACE and shot_count == 0:
                shot_y = h-50
                shot_x = x
            elif event.type == K_SPACE and shot_count == 1:
                shot_y_2 = h-50
                shot_x_2 = x
            print(h, ' ', shot_y, shot_count)
        if event.type == KEYUP:
            if event.key == K_SPACE and shot_count == 0:
                resetShot = 0 
            elif event.type == K_SPACE and shot_count == 1:
                resetShot = 0


    if shot_y > 0:
        screen.blit(shot1, (shot_x-shot1.get_width()/2,shot_y))
        shot_y -= 15
    if shot_y_2 > 0:
        screen.blit(shot2, (shot_x_2-shot1.get_width()/2,shot_y_2))
        shot_y_2 -= 15

    x+=move_x
    pygame.display.update()
4

2 回答 2

3

您可以使用计数器来计算自上次拍摄以来主循环中的循环 - 如果它大于(例如)10 比您清除计数器并拍摄 - 在更复杂的游戏中,您可以使用pygame.time.get_ticks()以毫秒为单位计算时间自上次拍摄以来

另一种方法是仅在屏幕上的射击少于 2 发时才进行射击。

编辑:

您的代码将如下所示 - 简单示例。使用键:LEFT、RIGHT、SPACE、P(暂停)。

还有很多事情要做。例如更好的碰撞检测 - pygame.sprite.collide_rect()

我在最后附上了我的位图

#-----!!!!SPACE INVADERS!!!!-----

import pygame
from pygame.locals import *

#----------------------------------------------------------------------

class Ship():

    def __init__(self, screen_rect):

        #self.image = pygame.image.load("spaceship.png")
        self.image = pygame.image.load("ball1.png")
        self.image = pygame.transform.scale(self.image, (100,50))

        self.rect = self.image.get_rect()

        # put ship bottom, center x 
        self.rect.bottom = screen_rect.bottom 
        self.rect.centerx = screen_rect.centerx

        self.move_x = 0

        self.shots = []
        self.shots_count = 0

        self.max_shots = 2

    #--------------------

    def event_handler(self, event):

        #print "debug: Ship.event_handler"

        if event.type == KEYDOWN:
            if event.key == K_LEFT:
                self.move_x = -5
            elif event.key == K_RIGHT:
                self.move_x = 5
            elif event.key == K_SPACE:
                if len(self.shots) < self.max_shots:
                    self.shots.append(Bullet(self.rect.centerx, self.rect.top))

        if event.type == KEYUP:
            if event.key in (K_LEFT, K_RIGHT):
                self.move_x = 0

    def update(self):

        #print "debug: Ship.update: move_x", self.move_x
        self.rect.x += self.move_x

        for s in self.shots:
            s.update()

        for i in range(len(self.shots)-1, -1, -1):
            print "debug: Ship.update: testing bullet ", i
            if not self.shots[i].is_alive:
                print "debug: Ship.update: removing bullet ", i
                del self.shots[i]

    #--------------------

    def draw(self, screen):

        #print "debug: Ship.draw"

        screen.blit(self.image, self.rect.topleft)

        for s in self.shots:
            s.draw(screen)

    def bullet_detect_collison(self, enemy_list):

        for s in self.shots:
            for e in enemy_list:
                if pygame.sprite.collide_circle(s, e):
                    s.is_alive = False
                    e.is_alive = False

#----------------------------------------------------------------------

class Bullet():

    def __init__(self, x, y):

        #self.image = pygame.image.load("SingleBullet.png")
        self.image = pygame.image.load("ball2.png")
        self.image = pygame.transform.scale(self.image, (25,25))

        self.rect = self.image.get_rect()
        self.rect.centerx = x
        self.rect.centery = y

        self.is_alive = True

    #--------------------

    def update(self):

        self.rect.y -= 15

        if self.rect.y < 0:
            self.is_alive = False

    #--------------------

    def draw(self, screen):

        screen.blit(self.image, self.rect.topleft)

#----------------------------------------------------------------------

class Enemy():

    def __init__(self, x, y):

        self.image = pygame.image.load("ball3.png")

        self.rect = self.image.get_rect()
        self.rect.centerx = x
        self.rect.centery = y

        self.is_alive = True

    #--------------------

    def update(self):

        self.rect.y += 1

        #~ if self.rect.y < 0:
            #~ self.is_alive = False

    #--------------------

    def draw(self, screen):

        screen.blit(self.image, self.rect.topleft)

#----------------------------------------------------------------------

class Game():

    def __init__(self):

        pygame.init()

        w, h = 800, 800
        self.screen = pygame.display.set_mode((w,h))

        pygame.mouse.set_visible(False)

        self.ship = Ship(self.screen.get_rect())

        self.enemies = []

        for i in range(100, 800, 100):
            self.enemies.append(Enemy(i, 100))

        font = pygame.font.SysFont("", 72)
        self.text_paused = font.render("PAUSED", True, (255, 0, 0))
        self.text_paused_rect = self.text_paused.get_rect(center=self.screen.get_rect().center)

    #-----MAIN GAME LOOP-----

    def run(self):

        clock = pygame.time.Clock()

        RUNNING = True
        PAUSED = False

        while RUNNING:

            clock.tick(30)

            #--- events ---

            for event in pygame.event.get():

                if event.type == pygame.QUIT:
                    RUNNING = False

                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        RUNNING = False

                    if event.key == K_p:
                        PAUSED = not PAUSED

                if not PAUSED:
                    self.ship.event_handler(event)

            #--- changes ---
            if not PAUSED:

                self.ship.update()

                for e in self.enemies:
                    e.update()

                self.ship.bullet_detect_collison(self.enemies)

                for i in range(len(self.enemies)-1, -1, -1):
                    print "debug: Ship.update: testing bullet ", i
                    if not self.enemies[i].is_alive:
                        print "debug: Ship.update: removing bullet ", i
                        del self.enemies[i]

            #--- draws ---

            self.screen.fill((0,0,0))

            self.ship.draw(self.screen)

            for e in self.enemies:
                e.draw(self.screen)

            if PAUSED:
                self.screen.blit(self.text_paused, self.text_paused_rect)

            pygame.display.update()

        #--- quit ---

        pygame.quit()

#---------------------------------------------------------------------

Game().run()

在此处输入图像描述 球1.png 在此处输入图像描述 球 2.png 球3.png 在此处输入图像描述

截屏 在此处输入图像描述

于 2013-11-13T23:30:13.930 回答
2

一些提示:你的第一个 blit 是没有意义的。因为您已经开始在 while 循环中进行 bliting。

您可以将 ship_left 和 ship_top 存储在一个元组中,这样代码中的混乱就会减少。

使用函数,并给它们起有意义的名字,这样你和其他阅读你的代码的人会更容易。

还有一件事——你的运动函数接受一个参数,但不做任何事情。它确实使用了一个事件,因此您应该改为传递它。

回到你的问题。这就是在此类游戏中通常解决的方法。

你列出了导弹清单。每个 KEYDOWN 事件都会创建一个新的导弹,并将其附加到列表中。如果假设列表中有 10 枚导弹,则不会创建导弹。

最好创建一个单独的导弹类。对于列表中的每个对象,您应该执行以下操作:

  1. 根据其位置绘制。
  2. 更新 - 将导弹移近顶部。
  3. 检查是否有任何导弹在屏幕外,如果是,则将其移除。

这样,就不需要计时器,并且您可以限制击球次数,以便玩家不会在键盘上发送垃圾邮件。如果你真的想根据时间来限制它,你可以使用的返回值pygame.Clock.tick()来增加一个 time_since_last_shot 变量。每次按键都会检查该值是否足够大,如果是,则拍摄并将变量重置为 0。

于 2013-11-13T23:42:20.933 回答