【问题标题】:Zigzag Movement of an object in PygamePygame中对象的曲折运动
【发布时间】:2021-09-09 12:39:18
【问题描述】:

我希望外星人以之字形移动。

目前他们正在直线下降。

游戏目前处于横盘状态。

这是外星人类

class Alien(Sprite):

    def __init__(self,ss_game):
        super().__init__()

        self.screen = ss_game.screen
        self.settings = ss_game.settings
        self.screen_rect = ss_game.screen.get_rect()

        self.image = pygame.image.load('images/alien_2.bmp')
        self.rect = self.image.get_rect()

        self.rect.x = self.rect.height
        self.rect.y = self.rect.width

        self.x = float(self.rect.x)
        self.y = float(self.rect.y)


    def _check_edges(self):

        screen_rect = self.screen.get_rect()
        if self.rect.top >= screen_rect.top or self.rect.bottom <= self.screen_rect.bottom:
            return True


    def update(self):
        self.rect.x += (self.settings.alien_speed * self.settings.fleet_direction) 

这些是几行代码,它们决定/创建一定数量的外星人并在那里移动。

    def _create_fleet(self):

        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        ship_width, ship_height = self.ship.rect.size
        space_y = self.settings.screen_height +(alien_height) - ship_height
        number_y = space_y // (2*alien_height) 
        space_x = self.settings.screen_width + (alien_width) - 5 * ship_width
        rows = space_x // (2*alien_height)
        for row in range(rows):
            for number in range(number_y):
                self._create_aliens(number, row)

    def _create_aliens(self,number,row):

        alien = Alien(self)
        alien_width,alien_height = alien.rect.size
        alien.x = alien_width + (1.5*alien_width) * row
        alien.rect.x = alien.x
        alien.rect.y = alien_width + (2*alien_width) * number
        self.aliens.add(alien) 

    def update_aliens(self):

        self.aliens.update()
        self._check_fleet_edges()

    def _check_fleet_edges(self):
        for alien in self.aliens.sprites():
            if alien._check_edges():
                self._change_fleet_direction()
                break

    def _change_fleet_direction(self):
        for alien in self.aliens.sprites():
            alien.rect.x += self.settings.fleet_drop_speed
        self.settings.fleet_direction *= -1

这是当前游戏的图片,外星人右边和外星人左边都有空格

由于更改/实验,代码可能有点混乱, 有什么不明白的可以问我。

目前外星人以直线运动移动,而且速度很快(旁注)。

我希望外星人以曲折的方式移动。

【问题讨论】:

    标签: python pygame


    【解决方案1】:

    你可以让它们沿着罪恶波移动。在你的情况下,它可能看起来像这样:

    class Alien(Sprite):
        def __init__(self,ss_game):
            #...
            self.frequency = 2
            self.ySpeed = 0.01
            self.overallY = self.rect.y
            self.amplitude = 30
    
     def update(self):
            t = pygame.time.get_ticks() * self.ySpeed % 500
            self.rect.x += (self.settings.alien_speed * self.settings.fleet_direction * self.frequency)
            self.rect.y = (self.amplitude * math.sin(t)) + self.overallY
    

    这是一个独立的例子。

    import pygame
    import math
    
    ySpeed = 0.01
    xVel = 0.1
    x = 0
    y = 250
    
    amplitude = 20
    frequency = 2
    
    window = pygame.display.set_mode((600, 600))
    pygame.init()
    
    while True:
    
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
    
        #stuff to do with x direction
        x += xVel * frequency
        if (x < 0 or x > 600 - 30):
             xVel *= -1
    
        #generate the zigzag y
        t = pygame.time.get_ticks() * ySpeed % 500
        zigzagY = (amplitude * math.sin( t )) + y
    
        #draw
        window.fill((0, 0, 0))
        pygame.draw.rect(window, (255, 255, 255), (x, zigzagY, 30, 30))
        pygame.display.flip()
    

    您的整个更新代码:

    import pygame
    import math
    from pygame.locals import *
    
    class Settings:
        def __init__(self):
    
            self.screen_width = 1200
            self.screen_height = 800
            self.bg_color = (230, 230, 230)
            self.ship_speed = 1.5
    
            self.bullet_speed = 1.5
            self.bullet_width = 15
            self.bullet_height = 3
            self.bullet_color = (60, 60, 60)
            self.bullet_allowed = 3
    
            self.alien_speed = 1
            self.fleet_drop_speed = 10
            self.fleet_direction = 1
    
    class Ship:
        def __init__(self, ai_game):
            self.screen = ai_game.screen
    
            self.settings = ai_game.settings
    
            self.screen_rect = ai_game.screen.get_rect()
    
            self.image = pygame.image.load('images/ship_2.bmp')
            self.rect = self.image.get_rect()
    
            self.rect.midright = self.screen_rect.midright
    
            self.y = float(self.rect.y)
    
            self.moving_up = False
            self.moving_down = False
    
        def update(self):
            if self.moving_down and self.y < 750:
                self.y += self.settings.ship_speed
            if self.moving_up and self.y > 0:
                self.y -= self.settings.ship_speed
            self.rect.y = self.y
            
        def blitme(self):
            self.screen.blit(self.image, self.rect)
    
    
    
    class Bullet(pygame.sprite.Sprite):
        def __init__(self,ai_game):
            super().__init__()
    
            self.screen = ai_game.screen
            self.settings = ai_game.settings
            self.color = self.settings.bullet_color 
    
            self.rect = pygame.Rect(0,0, self.settings.bullet_width, self.settings.bullet_height)
            self.rect.midright = ai_game.ship.rect.midright
            self.x = float(self.rect.x)
    
        def update(self):
            self.x -= self.settings.bullet_speed
            self.rect.x = self.x
    
        def draw_bullet(self):
            pygame.draw.rect(self.screen, self.color, self.rect)
    
    
    class Alien(pygame.sprite.Sprite):
        def __init__(self, ai_game):
            super().__init__()
            self.screen = ai_game.screen
            self.settings = ai_game.settings
    
            self.image = pygame.image.load('images/alien_2.bmp')
            self.rect = self.image.get_rect()
    
            # Start each new alien near the top left of the screen.
            self.rect.y = self.rect.width
            self.rect.x = self.rect.height
    
            # Store the alien's exact horizontal position.
            self.y = float(self.rect.y)
    
            self.frequency = 1
            self.ySpeed = 0.09
            self.overallY = self.rect.y
            self.amplitude = 4
    
        def check_edges(self):
            screen_rect = self.screen.get_rect()
            if self.rect.top <= screen_rect.top or self.rect.bottom >= 800:
                return True
    
        def update(self):
            self.rect.x += (self.settings.alien_speed * self.settings.fleet_direction * self.frequency)
    
            #you can either comment out the one bellow and use the next two lines
            #or you can leave it as it is.
            #You might also want to change the frequency, ySpeed, amplitude and
            #self.settings.alien_speed values to get it to zigzag exactly how you
            #want it.
            
            self.rect.y = self.overallY + (self.amplitude * math.sin(self.ySpeed * self.rect.x))
    
    ##        t = pygame.time.get_ticks() * self.ySpeed % 500
    ##        self.rect.y = (self.amplitude * math.sin(t)) + self.overallY
    
    class SideShooter:
    
        def __init__(self):
            pygame.init()
            self.settings = Settings()
    
            self.screen = pygame.display.set_mode((self.settings.screen_width,self.settings.screen_height))
            pygame.display.set_caption("Alien Invasion")
    
            self.ship = Ship(self)
            self.bullets = pygame.sprite.Group()
            self.aliens = pygame.sprite.Group()
    
            self._create_fleet()
    
        def run_game(self):
            """Start the main loop for the game."""
            while True:
                self._check_events()
                self.ship.update()
                self._update_bullets()
                self._update_aliens()
                self._update_screen()
    
        def _check_events(self):
            """Respond to keypresses and mouse events."""
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit()
                elif event.type == pygame.KEYDOWN:
                    self._check_keydown_events(event)
                elif event.type == pygame.KEYUP:
                    self._check_keyup_events(event)
    
        def _check_keydown_events(self, event):
            """Respond to keypresses."""
            if event.key == pygame.K_UP:
                self.ship.moving_up = True
            elif event.key == pygame.K_DOWN:
                self.ship.moving_down = True
            elif event.key == pygame.K_q:
                sys.exit()
            elif event.key == pygame.K_SPACE:
                self._fire_bullet()
    
        def _check_keyup_events(self, event):
            """Respond to key releases."""
            if event.key == pygame.K_UP:
                self.ship.moving_up = False
            elif event.key == pygame.K_DOWN:
                self.ship.moving_down = False
    
        def _fire_bullet(self):
            if len(self.bullets) < self.settings.bullet_allowed:
                new_bullet = Bullet(self)
                self.bullets.add(new_bullet)
    
        def _update_bullets(self):
            self.bullets.update()
    
            for bullet in self.bullets.copy():
                if bullet.rect.right <= self.screen.get_rect().left:
                    self.bullets.remove(bullet)
            self._check_bullet_detection()         
    
        def _check_bullet_detection(self):
            collisions = pygame.sprite.groupcollide(self.bullets, self.aliens, True, True)   
    
            if not self.aliens:
                self.bullets.empty()
                self._create_fleet()
    
    
        def _update_aliens(self):
            self._check_fleet_edges()
            self.aliens.update()
    
        def _create_fleet(self):
            alien = Alien(self)
            alien_width, alien_height = alien.rect.size
            available_space_x = self.settings.screen_width - (2* alien_width)
            number_aliens_x = available_space_x // (3*alien_width)
            
    
            ship_height = self.ship.rect.height
            available_space_y = (self.settings.screen_height -
                                    (3 * alien_height) - ship_height)
            number_rows = available_space_y // (2 * alien_height)
            
            for row_number in range(number_rows):
                for alien_number in range(number_aliens_x):
                    self._create_alien(alien_number, row_number)
    
        def _create_alien(self, alien_number, row_number):
            alien = Alien(self)
            alien_width, alien_height = alien.rect.size
            alien.overallY = alien_width + 2 * alien_width * alien_number
            #alien.rect.y = alien.y
            #self.overallY = alien.y
            alien.rect.x = alien.rect.height + 2 * alien.rect.height * row_number
            self.aliens.add(alien)
    
        def _check_fleet_edges(self):
            for alien in self.aliens.sprites():
                if alien.check_edges():
                    self._change_fleet_direction()
                    break
                
        def _change_fleet_direction(self):
            for alien in self.aliens.sprites():
                alien.rect.x += self.settings.fleet_drop_speed
            self.settings.fleet_direction *= -1
    
        def _update_screen(self):
            self.screen.fill(self.settings.bg_color)
            self.ship.blitme()
            for bullet in self.bullets.sprites():
                bullet.draw_bullet()
            self.aliens.draw(self.screen)
    
            pygame.display.flip()
    
    ss = SideShooter()
    ss.run_game()  
    

    【讨论】:

    • 您好先生/女士,我得到了预期的结果,但外星人正在移出屏幕。有没有办法解决这个问题? @user16038533
    • @help 在 y 方向?它不应该在 x - 我不认为。尝试降低幅度
    • 我想我没有理解正确,你说什么,我实现了你的行“self.frequency = 2 self.ySpeed = 0.01 self.zigzagY = 0 self.amplitude = 30 def update(self ): t = pygame.time.get_ticks() * self.ySpeed % 500 self.rect.x += (self.settings.alien_speed * self.settings.fleet_direction * self.frequency) self.zigzagY = (self.amplitude * math.sin(t)) + self.rect.y"
    • 但是不明白如何用 self.zigzagY 改变 self.rect.y / 加上我改变了所有外星人在屏幕右上角都被挤在一起的幅度 @ user16038533
    • 非常感谢!我真的很喜欢你的示例代码。
    【解决方案2】:

    如果我理解你所说的“之字形”是什么意思,有点像锯齿状运动(反复上下移动,同时不断向一侧移动),每个外星人都会沿着这样的路径(结束于 . ):

    /\  /\  /\  /\  .
      \/  \/  \/  \/
    

    如果是这种情况,除了 x 轴之外,外星人还需要更新他们的 y 轴。

    另一方面,如果您希望 y 坐标保持不变并沿 x 轴向左、向右、向左等移动,那么从您共享的代码中并不清楚这将如何发生。

    看起来就像你写的那样,只要一个外星人超出屏幕空间,整个舰队就会改变方向。这可能是需要的,但您可以通过针对每个外星人执行此检查和方向更改来潜在地简化您的代码。

    例如,您可以向 Alien 类添加 direction 参数,而不是更改 fleet_direction,并单独更改每个外星人的方向。

    这将允许您像这样编写 update_aliens 函数:

    for alien in aliens:
      if alien.check_edges():
        alien.direction *= -1
      alien.update()
    

    [编辑]

    根据您的 cmets,您可以尝试向您的 Alien.update 函数添加一些额外的 y-update,如下所示:

    def __init__(self):
      #...
      self.y_direction = 1
      self.y_counter = 1
    
    
    def update(self):
      self.rect.x += #...
      self.rect.y += 1
      if self.y_counter == 10: # zig size is 10
        self.y_counter = 0
        self.y_direction *= -1 # change y direction only
      self.y_counter += 1
    

    这类似于另一个答案的正弦建议,但您应该检查边界,以便您的外星人在碰到屏幕边缘时会反转方向。

    或者,您可以在精灵接触屏幕边缘时应用方向变化:

    class Alien(Sprite):
      def __init__(self):
        # ...
        self.x_direction = 1
        self.y_direction = 1
    
      def _check_edges(self):
        # ...
        if self.rect.y > screen_rect.top or self.rect.y < screen_rect.botttom:
          self.y_direction *= -1
        if self.rect.x > screen_rect.right or self.rect.x < screen_rect.left:
          self.x_direction *= -1
    
      def update(self):
        # ...
        self.rect.x += self.settings.alien_speed * self.x_direction
        self.rect.y += self.settings.alien_speed * self.y_direction
    

    【讨论】:

    • 您好先生,首先我想让外星人向右/向左移动,然后我设置了一个条件,如果外星人在屏幕的右上角或左角,外星人应该向下移动,我的代码确实写得不完美,因为我不知道该怎么做,但我已经尝试过(我只能向左/向右或向上或向下移动)。 @Alex Shroyer
    • 在这种情况下,此处的另一个答案建议以正弦波形状更新 x 和 y,也许这就是您想要的。
    • 我看到了,但是外星人正在移出屏幕。
    • @Alex Shroyer 我使用了替代代码,这是否准确:“ def update_aliens(self): self.aliens.update() self._check_fleet_edges() def _check_fleet_edges(self): for alien in self.aliens.sprites(): if alien._check_edges(): self._change_fleet_xdirection() break def _change_fleet_xdirection(self): for alien in self.aliens.sprites(): alien.rect.x += self.settings.fleet_drop_speed self.settings.x_direction *= -1 "
    • 我不太确定,因为格式很难理解。假设fleet_direction 适用于整个“舰队”,请确保您只为整个舰队调用一次_change_fleet_xdirection,而不是每个外星人调用一次。否则,如果你调用它偶数次,舰队方向将与开始时相同。
    【解决方案3】:

    代码应该按预期工作:

    导入系统 导入pygame from pygame.sprite 导入精灵

    类设置:

    def __init__(self):
    
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (230, 230, 230)
        self.ship_speed = 1.5
    
        self.bullet_speed = 1.5
        self.bullet_width = 15
        self.bullet_height = 3
        self.bullet_color = (60, 60, 60)
        self.bullet_allowed = 3
    
        self.alien_speed = 1
        self.fleet_drop_speed = 10
        self.fleet_direction = 1
        
        
    

    级船:

    def __init__(self, ai_game):
        self.screen = ai_game.screen
    
        self.settings = ai_game.settings
    
        self.screen_rect = ai_game.screen.get_rect()
    
        self.image = pygame.image.load('images/ship_2.bmp')
        self.rect = self.image.get_rect()
    
        self.rect.midright = self.screen_rect.midright
    
        self.y = float(self.rect.y)
    
        self.moving_up = False
        self.moving_down = False
    
    def update(self):
        if self.moving_down and self.y < 750:
            self.y += self.settings.ship_speed
        if self.moving_up and self.y > 0:
            self.y -= self.settings.ship_speed
        self.rect.y = self.y     
    def blitme(self):
        self.screen.blit(self.image, self.rect) 
       
    

    类子弹(精灵):

    def __init__(self,ai_game):
        super().__init__()
    
        self.screen = ai_game.screen
        self.settings = ai_game.settings
        self.color = self.settings.bullet_color 
    
        self.rect = pygame.Rect(0,0, self.settings.bullet_width, self.settings.bullet_height)
        self.rect.midright = ai_game.ship.rect.midright
        self.x = float(self.rect.x)
    
    def update(self):
        self.x -= self.settings.bullet_speed
        self.rect.x = self.x
    
    def draw_bullet(self):
        pygame.draw.rect(self.screen, self.color, self.rect)
    

    类外星人(Sprite):

    def __init__(self, ai_game):
        super().__init__()
        self.screen = ai_game.screen
        self.settings = ai_game.settings
    
        self.image = pygame.image.load('images/alien_2.bmp')
        self.rect = self.image.get_rect()
    
        # Start each new alien near the top left of the screen.
        self.rect.y = self.rect.width
        self.rect.x = self.rect.height
    
        # Store the alien's exact horizontal position.
        self.y = float(self.rect.x)
    
    def check_edges(self):
        screen_rect = self.screen.get_rect()
        if self.rect.top <= screen_rect.top or self.rect.bottom >= 800:
            return True
    
    def update(self):
        self.y += (self.settings.alien_speed *
                        self.settings.fleet_direction)
        self.rect.y = self.y
    

    类 SideShooter:

    def __init__(self):
        pygame.init()
        self.settings = Settings()
    
        self.screen = pygame.display.set_mode((self.settings.screen_width,self.settings.screen_height))
        pygame.display.set_caption("Alien Invasion")
    
        self.ship = Ship(self)
        self.bullets = pygame.sprite.Group()
        self.aliens = pygame.sprite.Group()
    
        self._create_fleet()
    
    def run_game(self):
        """Start the main loop for the game."""
        while True:
            self._check_events()
            self.ship.update()
            self._update_bullets()
            self._update_aliens()
            self._update_screen()
    
    def _check_events(self):
        """Respond to keypresses and mouse events."""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                self._check_keydown_events(event)
            elif event.type == pygame.KEYUP:
                self._check_keyup_events(event)
    
    def _check_keydown_events(self, event):
        """Respond to keypresses."""
        if event.key == pygame.K_UP:
            self.ship.moving_up = True
        elif event.key == pygame.K_DOWN:
            self.ship.moving_down = True
        elif event.key == pygame.K_q:
            sys.exit()
        elif event.key == pygame.K_SPACE:
            self._fire_bullet()
    
    def _check_keyup_events(self, event):
        """Respond to key releases."""
        if event.key == pygame.K_UP:
            self.ship.moving_up = False
        elif event.key == pygame.K_DOWN:
            self.ship.moving_down = False
    
    def _fire_bullet(self):
        if len(self.bullets) < self.settings.bullet_allowed:
            new_bullet = Bullet(self)
            self.bullets.add(new_bullet)
    
    def _update_bullets(self):
        self.bullets.update()
    
        for bullet in self.bullets.copy():
            if bullet.rect.right <= self.screen.get_rect().left:
                self.bullets.remove(bullet)
        self._check_bullet_detection()         
    
    def _check_bullet_detection(self):
        collisions = pygame.sprite.groupcollide(self.bullets, self.aliens, True, True)   
    
        if not self.aliens:
            self.bullets.empty()
            self._create_fleet()
    
    
    def _update_aliens(self):
        self._check_fleet_edges()
        self.aliens.update()
    
    def _create_fleet(self):
    
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        available_space_x = self.settings.screen_width - (2* alien_width)
        number_aliens_x = available_space_x // (3*alien_width)
        
    
        ship_height = self.ship.rect.height
        available_space_y = (self.settings.screen_height -
                                (3 * alien_height) - ship_height)
        number_rows = available_space_y // (2 * alien_height)
        
        for row_number in range(number_rows):
            for alien_number in range(number_aliens_x):
                self._create_alien(alien_number, row_number)
    
    def _create_alien(self, alien_number, row_number):
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        alien.y = alien_width + 2 * alien_width * alien_number
        alien.rect.y = alien.y
        alien.rect.x = alien.rect.height + 2 * alien.rect.height * row_number
        self.aliens.add(alien)
    
    def _check_fleet_edges(self):
        for alien in self.aliens.sprites():
            if alien.check_edges():
                self._change_fleet_direction()
                break
            
    def _change_fleet_direction(self):
        for alien in self.aliens.sprites():
            alien.rect.x += self.settings.fleet_drop_speed
        self.settings.fleet_direction *= -1
    
    def _update_screen(self):
        self.screen.fill(self.settings.bg_color)
        self.ship.blitme()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()
        self.aliens.draw(self.screen)
    
        pygame.display.flip()
    

    如果 name == 'ma​​in':

    ss = SideShooter()
    
    ss.run_game()          
         
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-26
      • 1970-01-01
      • 2012-02-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多