2017-11-20 4 views
1

나는 공간 침략자/총알 지옥 게임 인 파이 게임 코드에서 나의 적 샷 중 하나를 지연 시키려고합니다. 불행히도, 나는 적의 총을 늦추는 것에 문제가있는 것 같다.적을 지연

import pygame 
import random 
import time 
import os 
import threading 

pygame.time.set_timer (pygame.USEREVENT , 450) 
event_500ms = pygame.USEREVENT + 1 
pygame.time.set_timer(event_500ms, 500) 

class Alien2 (pygame.sprite.Sprite): 
    def __init__(self): 
     # Call the parent class (Sprite) constructor 
     super().__init__() 

     self.image = pygame.Surface([20, 15]) 
     self.image = pygame.image.load("alien3.png").convert() 
     self.image.set_colorkey(WHITE) 


     self.rect = self.image.get_rect() 
    def update(self): 

     pos = pygame.mouse.get_pos() 

     dx = pos[0] - self.rect.x + 18 
     dx *= .05 
     self.rect.x += dx 
def BossPowers(): 
    bullet3 = Bullet3() 
    # Set the bullet so it is where the player is 
    bullet3.rect.x = alien2.rect.x + 47 
    bullet3.rect.y = alien2.rect.y + 57 
    # Add the bullet to the lists 
    all_sprites_list.add(bullet3) 
    bullet2_list.add(bullet3) 

def BossPowers2(): 
    bullet4 = Bullet4() 
    # Set the bullet so it is where the player is 
    bullet4.rect.x = alien2.rect.x + 47 
    bullet4.rect.y = alien2.rect.y + 57 
    # Add the bullet to the lists 
    all_sprites_list.add(bullet4) 
    bullet2_list.add(bullet4) 


def delay(): 
    #threading.Timer(5.0, delay).start() 
    bullet2 = Bullet2() 
    # Set the bullet so it is where the player is 
    bullet2.rect.x = alien2.rect.x + 47 
    bullet2.rect.y = alien2.rect.y + 57 
    # Add the bullet to the lists 
    all_sprites_list.add(bullet2) 
    bullet2_list.add(bullet2) 
    BossPowers() 
    BossPowers2() 

내가

while not done: 
    # --- Event Processing 
    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      done = True 
    if level % 2 == 0: 
     all_sprites_list.add(alien2) 
     alien2_list.add(alien2) 
     for block in block_list: 
      block_list.remove(block) 
      all_sprites_list.remove(block) 
     #t = threading.Timer(2, delay) 
     #t.start()  
     #if event.type == event_500ms: 
      #delay() 



    if level % 2 == 1: 
     block_list.add(block) 
     all_sprites_list.add(block) 

괜찮아 그래서 여기 내 문제는 내 마음 효율적으로 미끄러 져되고 때로는 조금이 게임에 노력하고 봤는데, 여기 내 스파게티 코드를 무시합니다. 적의 배가 발사를 지연 시키지만, 배가 움직이는 경우에만 발사가 중지됩니다. 배가 움직이는 것을 멈 추면 하나의 총알이 아닌 여러 개의 시냇물이 발사됩니다. 나는 발사를 지연시키고, 1 초에 1 발의 총알을 발사하고, 실제로 우주선이 움직이는 동안 발사해야합니다. 지금 당장 적의 적을 거의 쓸모가 없다. 마치 약간 움직이면 발사되지 않을 것이고, 실제로는 쉽다. 도움을 주시면 감사하겠습니다.

+1

내가 사용하는 것'next_fire = pygame.time.get_ticks() + N * 1000'는 다음 총알을 촬영 할 수 있습니다 시간을 설정 한 후 나는'확인 할 pygame.time.get_ticks()의 경우> = next_fire :'화재 전. 나는 다시 설정하겠다. next_fire = pygame.time.get_ticks() + n * 1000' – furas

+0

코드에 올바른 들여 쓰기가 있는지 확실하지 않다. 올바르게 포맷하려면 '{}'버튼을 사용한다. – furas

+0

BTW : 우주선이 움직일 때 우주선이 멈 추면 잘못된 들여 쓰기가 발생하여 일부 코드가 잘못된 경우 'if/else/for'에 있습니다. – furas

답변

1

문제는 스파게티 코드가 스파게티라는 것입니다. :-)

나 자신이 원하는 것을 정확히 알아낼 수 없다. 모든 글 머리 기호 기능이 동일한 글 머리 기호를 만들거나 실제로 다른 경우 등등.

주요 문제의 원인이되는 두 가지 문제가 있습니다. 그러나 코드를 그대로 같은 형식으로 유지할 수는 있지만 스파게티보다는 뇨키 접근법을 사용하여 코드를 다시 작성하는 것이 좋습니다.).

문제의 주된 원인은 500ms 후 해고 될 하나의 이벤트를 등록하면 이에 대응하고 delay 함수를 호출하는 것입니다. 그런 다음이 함수는 BossPower 함수를 호출하여 지연없이 다른 글 머리표를 시작합니다.

아니요, 다른 게임을 일시 중단하는 기능을 호출하기 전에 지연 내에서 time.sleep 또는 pygame.time.delay으로 전화를 걸 수 없습니다.

그래서 한 가지 방법은 지연을 호출하여 다른 사용자 지정 이벤트를 등록하여 다음 글 머리 기호를 발생시키고 함수에서 반환하는 것입니다. 메인 루프는 그 사건을 발견하면 다음 총알을 발사합니다.

이 코드에서 두 번째 큰 문제가 발생합니다. 각 프레임에서 사용 가능한 모든 이벤트를 가져 오지만 모든 이벤트에 대해 수행 할 작업은 pygame.QUIT입니다. 우연히 각 프레임에서 가져온 마지막 이벤트가 event 변수에 의해 참조되고 사용자 정의 이벤트 (if event.type == event_500ms:)를 확인하는 라인에서 사용할 수 있습니다. 같은 프레임에 도착한 다른 이벤트는 단순히 버려집니다. 이것은 또한 사용자 정의 이벤트가 버려 질 수 있음을 의미합니다.

그래서 코드의 한 지점에서만 각 프레임의 모든 이벤트를 가져오고 모든 이벤트 관련 작업 또는 비교가 동일한 지점에서 이루어져야합니다.

이제 Pygame을 사용하면 최소한의 사용자 정의 이벤트를 사용할 수 있습니다 (기본 빌드에서는 단지 8 개만 사용할 수 있으므로 이벤트는 pygame.USEREVENT 사이의 이벤트 만 사용하는 것이 좋습니다). 당신이 발사하고자하는 각각의 총알 클래스에 대해 하나의 이벤트 유형을 사용한다면, 게임이 3 레벨이되기 전에 이벤트 번호를 다 썼을 것입니다.

그래서 총알을 발사하는 코드가 정확히 같고 총알 클래스를 변경하기 만하면 총알 클래스 시퀀스를 실행하여 항상 다음 글 머리 기호 유형을 가져 오는 itertools.cycle을 사용할 수 있습니다.

... 
import itertools 


fire_bullet_event = pygame.USEREVENT + 1 

... 

bullets = itertools.cycle([Bullet2, Bullet3, Bullet4) 

def fire_bullet(): 
    bullet_type = next(bullets) 
    bullet2 = bullet_type() 

    # Set the bullet so it is where the player is 
    bullet2.rect.x = alien2.rect.x + 47 
    bullet2.rect.y = alien2.rect.y + 57 
    # Add the bullet to the lists 
    all_sprites_list.add(bullet2) 
    bullet2_list.add(bullet2) 

    delay = 500 
    # Schedule to call this function again in 500ms. 
    # use an "if" to change the 500 to another number like: 
    # if bullet_type == Bullet4: 
    #  delay = 2000 
    pygame.time.set_timer(fire_bullet_event, delay) 


... 

# Schedule the first bullet close to entering the loop - 
# it is easier to see than putting it with the game setup code: 
pygame.time.set_timer(fire_bullet_event, 500) 

while not done: 
    # --- Event Processing 
    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      done = True 
     # all code dealing with events must be inside this `for` loop. 
     if event.type == fire_bullet_event: 
      fire_bullet() 
    if level % 2 == 0: 
     all_sprites_list.add(alien2) 
     alien2_list.add(alien2) 
     for block in block_list: 
      block_list.remove(block) 
      all_sprites_list.remove(block) 
+0

흠 좋습니다. 그렇기 때문에 이것이 내가 원하는 것 같지만 해결할 수없는 간단한 문제가 있습니다. 적의 배는 "산란"하기 전과 죽은 후에 계속 발사됩니다. 총알은 올바른 순서로 움직이지만, while 루프 앞에있는 pygame.time.set_timer (fire_bullet_event, 500)가이 문제를 일으키는 것으로 보입니다. 그러나 이상하게도 프로그램은 fire_bullet() 명령에서 pygame.time.set_timer (fire_bullet_event, delay)를 인식하지 못하는 것 같습니다. 그래서 기본적으로, 그것은 전혀 발사되지 않을 것입니다, 또는 그것은 마치 서있는 것처럼 생기고 살아 있습니다. 그러나이 답변을 주셔서 감사합니다! –

+0

질문에 적함의 코드가 없으므로 조언을하기가 어렵지만 발포시기와 발사 시간은 각 적의 우주선 인스턴스의 속성이어야합니다. 당신은 단지'pygame.time.get_ticks()'를 사용하고 그 값에 500을 더하고, 이벤트에 의존하는 대신 적 함의 update 메소드에서이 값을 "get_ticks"와 비교할 수 있습니다. 배가 존재하지 않으면 해당 업데이트 방법이 실행되지 않으므로 실행되지 않습니다. – jsbueno

1

는 평소 clock.tick(fps) 의해 반환 (tick 지난 이후 시간 경과) 델타 시간을 사용하여 증가 또는 타이머 변수를 감소 스프라이트의 update 메소드로 전달. 타이머가 0보다 작 으면 Bullet 클래스의 인스턴스를 만들고이를 스프라이트 그룹에 추가하고 타이머를 재설정합니다.

import pygame as pg 
from pygame.math import Vector2 


pg.init() 
ALIEN_IMAGE = pg.Surface((20, 15)) 
ALIEN_IMAGE.fill((40, 200, 90)) 
BULLET_IMAGE = pg.Surface((5, 5)) 
BULLET_IMAGE.fill((240, 120, 0)) 


class Alien(pg.sprite.Sprite): 

    def __init__(self, pos, all_sprites, bullets): 
     super().__init__() 
     self.image = ALIEN_IMAGE 
     self.rect = self.image.get_rect(center=pos) 
     self.vel = Vector2(1, 0) 
     self.pos = Vector2(pos) 
     self.bullet_timer = 1 # 1 second. 
     self.all_sprites = all_sprites 
     self.bullets = bullets 

    def update(self, dt): 
     self.pos += self.vel 
     self.rect.center = self.pos 

     # Decrease the countdown timer. 
     self.bullet_timer -= dt 
     if self.bullet_timer < 0: # Time is up so create a bullet. 
      bullet = Bullet(self.rect.center, Vector2(0, 5)) 
      # Add the bullet to the sprite groups. 
      self.all_sprites.add(bullet) 
      self.bullets.add(bullet) 
      self.bullet_timer = 1 # Reset timer after firing. 


class Bullet(pg.sprite.Sprite): 

    def __init__(self, pos, velocity): 
     super().__init__() 
     self.image = BULLET_IMAGE 
     self.rect = self.image.get_rect(center=pos) 
     self.vel = velocity 
     self.pos = Vector2(pos) 

    def update(self, dt): 
     self.pos += self.vel 
     self.rect.center = self.pos 


def main(): 
    screen = pg.display.set_mode((640, 480)) 
    clock = pg.time.Clock() 

    all_sprites = pg.sprite.Group() 
    bullets = pg.sprite.Group() 
    alien = Alien((0, 30), all_sprites, bullets) 
    alien2 = Alien((60, 30), all_sprites, bullets) 
    all_sprites.add(alien, alien2) 

    done = False 

    while not done: 
     # dt = delta time (passed time since last clock.tick call). 
     dt = clock.tick(30)/1000 #/1000 to convert to seconds. 

     for event in pg.event.get(): 
      if event.type == pg.QUIT: 
       done = True 

     all_sprites.update(dt) 
     screen.fill((30, 30, 30)) 
     all_sprites.draw(screen) 
     pg.display.flip() 


if __name__ == '__main__': 
    main() 
    pg.quit()