Python pygame noob 关于动画的问题 [英] Python pygame noob question about animation

查看:56
本文介绍了Python pygame noob 关于动画的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你能帮我解决一个问题吗?我是编程方面的新手,并指导我使用这本书:如何像计算机科学家一样思考第 3 版.并且它无法解决第17章的练习2. 这表示单击精灵右侧的任何帧时发生错误,导致动画开始,理论上它应该只做动画,如果是你直接点击精灵,我尝试了很多方法都解决不了,你能帮我吗?,我认为错误发生在这部分

could you help me with a problem I have? I am a new person with regard to programming and to guide me I am using the book: How to think like a computer scientist 3rd edition. And it could not solve exercise 2 of chapter 17. This says that an error occurs when clicking on any frame that is on the right side of the sprite, which causes the animation to start, in theory it should only do the animation if it is you click directly on the sprite, I tried to solve it in many ways but I couldn't, could you help me ?, I think the error occurs in this part

 return ( x >= my_x and x + my_width and y >= my_y and y < my_y + my_height)

但我不确定,我给你留下了我所有的代码

but I'm not sure, for anything I leave you all the code I have

import pygame
gravity = 0.025
my_clock = pygame.time.Clock()
class QueenSprite:

    def __init__(self, img, target_posn):
        self.image = img
        self.target_posn = target_posn
        (x, y) = target_posn
        self.posn = (x, 0)     # Start ball at top of its column
        self.y_velocity = 0    #    with zero initial velocity

    def update(self):
        self.y_velocity += gravity
        (x, y) = self.posn
        new_y_pos = y + self.y_velocity
        (target_x, target_y) = self.target_posn   # Unpack the position
        dist_to_go = target_y - new_y_pos         # How far to our floor?
        if dist_to_go < 0:                        # Are we under floor?
            self.y_velocity = -0.65 * self.y_velocity     # Bounce
            new_y_pos = target_y + dist_to_go     # Move back above floor
        self.posn = (x, new_y_pos)                # Set our new position.

    def draw(self, target_surface):      # Same as before.
        target_surface.blit(self.image, self.posn)
    def contains_point(self, pt):
      """ Return True if my sprite rectangle contains point pt """
      (my_x, my_y) = self.posn
      my_width = self.image.get_width()
      my_height = self.image.get_height()
      (x, y) = pt
      return ( x >= my_x and x < my_x + my_width and
               y >= my_y and y < my_y + my_height)   
    def handle_click(self):
        self.y_velocity += -2   # Kick it up
        
class DukeSprite:

    def __init__(self, img, target_posn):
        self.image = img
        self.posn = target_posn
        self.anim_frame_count = 0
        self.curr_patch_num = 0

    def update(self):
        if self.anim_frame_count > 0:
           self.anim_frame_count = (self.anim_frame_count + 1 ) % 60
           self.curr_patch_num = self.anim_frame_count // 6

    def draw(self, target_surface):
        patch_rect = (self.curr_patch_num * 50, 0,
                       50, self.image.get_width())
        target_surface.blit(self.image, self.posn, patch_rect)

    def contains_point(self, pt):
         """ Return True if my sprite rectangle contains  pt """
         (my_x, my_y) = self.posn
         my_width = self.image.get_width()
         my_height = self.image.get_height()
         (x, y) = pt
         return ( x >= my_x and x + my_width and y >= my_y and y < my_y + my_height)

    def handle_click(self):
         if self.anim_frame_count == 0:
            self.anim_frame_count = 5

def draw_board(the_board):
    """ Draw a chess board with queens, as determined by the the_board. """

    pygame.init()
    colors = [(255,0,0), (0,0,0)]    # Set up colors [red, black]

    n = len(the_board)         # This is an NxN chess board.
    surface_sz = 480           # Proposed physical surface size.
    sq_sz = surface_sz // n    # sq_sz is length of a square.
    surface_sz = n * sq_sz     # Adjust to exactly fit n squares.

    # Create the surface of (width, height), and its window.
    surface = pygame.display.set_mode((surface_sz, surface_sz))

    ball = pygame.image.load("ball.png")

    # Use an extra offset to centre the ball in its square.
    # If the square is too small, offset becomes negative,
    #   but it will still be centered :-)
    ball_offset = (sq_sz-ball.get_width()) // 2
    all_sprites = []      # Keep a list of all sprites in the game

    # Create a sprite object for each queen, and populate our list.
    for (col, row) in enumerate(the_board):
        a_queen = QueenSprite(ball,
                   (col*sq_sz+ball_offset, row*sq_sz+ball_offset))
        all_sprites.append(a_queen)
    # Load the sprite sheet
    duke_sprite_sheet = pygame.image.load("duke_spritesheet.png")
    
    # Instantiate two duke instances, put them on the chessboard
    duke1 = DukeSprite(duke_sprite_sheet,(sq_sz*2, 0))
    duke2 = DukeSprite(duke_sprite_sheet,(sq_sz*5, sq_sz))
    
    # Add them to the list of sprites which our game loop manages
    all_sprites.append(duke1)
    all_sprites.append(duke2)
    while True:

    # Look for an event from keyboard, mouse, etc.
        ev = pygame.event.poll()
        if ev.type == pygame.QUIT:
            break;
        if ev.type == pygame.KEYDOWN:
            key = ev.dict["key"]
            if key == 27:                  # On Escape key ...
                break                      #   leave the game loop.
            if key == ord("r"):
                colors[0] = (255, 0, 0)    # Change to red + black.
            elif key == ord("g"):
                colors[0] = (0, 255, 0)    # Change to green + black.
            elif key == ord("b"):
                colors[0] = (0, 0, 255)    # Change to blue + black.
        if ev.type == pygame.MOUSEBUTTONDOWN: # Mouse gone down?
            posn_of_click = ev.dict["pos"]    # Get the coordinates.
            for sprite in all_sprites:
                if sprite.contains_point(posn_of_click):
                    sprite.handle_click()
                    break    
        
        for sprite in all_sprites:
            sprite.update()
          
        # Draw a fresh background (a blank chess board)
        for row in range(n):           # Draw each row of the board.
            c_indx = row % 2           # Alternate starting color
            for col in range(n):       # Run through cols drawing squares
                the_square = (col*sq_sz, row*sq_sz, sq_sz, sq_sz)
                surface.fill(colors[c_indx], the_square)
                # Now flip the color index for the next square
                c_indx = (c_indx + 1) % 2
          
        # Ask every sprite to draw itself.
        for sprite in all_sprites:
            sprite.draw(surface)
        my_clock.tick(60)  # Waste time so that frame rate becomes 60 fps
   
        pygame.display.flip()
    
    pygame.quit()

if __name__ == "__main__":
    draw_board([0, 5, 3, 1, 6, 4, 2])    # 7 x 7 to test window size

推荐答案

<类 DukeSprite 的方法 contains_point 的比较表达式中缺少 my_x:

There is < my_x missing in the comparisons expression in the method contains_point of the class DukeSprite:

return ( x >= my_x and x + my_width and y >= my_y and y < my_y + my_height)

return ( x >= my_x and x < my_x + my_width and y >= my_y and y < my_y + my_height)

无论如何在 python 中你应该使用链式比较::>

Anyway in python you should use chained comparisons:

return my_x <= x < my_x + my_width and my_y <= y < my_y + my_height

在 pygame 中你应该使用 pygame.Rectcollidepoint().您可以从 pygame.Surface 获得的对象的矩形 使用方法 get_rect 并且可以通过关键字参数设置位置:

In pygame you should use pygame.Rect and collidepoint(). The rectangle of the object you can get from the pygame.Surface with the method get_rect and the position can be set by an keyword argument:

def contains_point(self, pt):
    """ Return True if my sprite rectangle contains  pt """
    my_rect = self.image.get_rect(topleft = self.posn)
    return my_rect.collidepoint(pt)

这篇关于Python pygame noob 关于动画的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆