【问题标题】:I am trying to move my character but instead of that the player wont move我正在尝试移动我的角色,但玩家不会移动
【发布时间】:2020-09-14 16:22:38
【问题描述】:

我正在尝试移动我的角色。我就像在教程中一样写了它(https://www.youtube.com/watch?v=FfWpgLFMI7w)。它不起作用。我的角色就​​是动弹不得。我也没有看到任何错误!我是否忘记在我的代码中添加一些内容 - 在 KEYDOWN 部分?所以整个代码都在这里,但问题可能出在KEYDOWN 部分或玩家坐标中。代码如下:

import pygame
from pygame.locals import *

pygame.init()

WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600

SURFACE = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE
win = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT), SURFACE)
win.fill((0, 180, 210))

pygame.display.set_caption("Baloon War!")
icon = pygame.image.load("Baloon war icon.png")
pygame.display.set_icon(icon)

centre_point = (WINDOW_WIDTH//2, WINDOW_HEIGHT//2)

playerImg = pygame.image.load("RobiS.png")
playerX = 370
playerY = 500
playerX_change = 0

def player(x,y):
    win.blit(playerImg, (x, y))

class button():
    def __init__(self, color, x, y, width, height, text=''):
        self.color = color
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.text = text

    def draw(self, win, outline=None):
        # Call this method to draw the button on the screen
        if outline:
            pygame.draw.rect(win, outline, (self.x - 2, self.y - 2, self.width + 4, self.height + 4), 0)

        pygame.draw.rect(win, self.color, (self.x, self.y, self.width, self.height), 0)

        if self.text != '':
            font = pygame.font.SysFont('comicsans', 60)
            text = font.render(self.text, 1, (0, 0, 0))
            win.blit(text, (self.x + (self.width / 2 - text.get_width() / 2), self.y + (self.height / 2 - text.get_height() / 2)))

    def isOver(self, pos):
        # Pos is the mouse position or a tuple of (x,y) coordinates
        if pos[0] > self.x and pos[0] < self.x + self.width:
            if pos[1] > self.y and pos[1] < self.y + self.height:
                return True

        return False

    def rescale(self):
        new_size = int(WINDOW_WIDTH * self.scale_factor)
        x, y = self.rect.center
        self.image = pygame.transform.smoothscale(self.original, (new_size, new_size))
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)

    def resize_button(self, WINDOW_WIDTH, WINDOW_HEIGHT, x, y):
        self.width = WINDOW_WIDTH
        self.height = WINDOW_HEIGHT
        self.x = x
        self.y = y


def redrawMenuWindow():
    win.fill((0, 255, 110))
    greenButton.draw(win, (0, 0, 0))
    redButton.draw(win, (0, 0, 0))
    cyanButton.draw(win, (0, 0, 0))

def redrawGameWindow():
    win.fill((0, 150, 210))
    pygame.draw.rect(win, (0, 250, 110), (0, 450, 800, 250))
    win.blit(playerImg, (370, 400))


def redrawShopWindow():
    win.fill((200, 100, 30))

greenButton = button((0, 255, 0), 275, 285, 250, 80, "Start")
redButton = button((255, 0, 0), 275, 475, 250, 80, "Quit")
cyanButton = button((20, 210, 180), 275, 380, 250, 80, "Shop")

game_state = "menu"
run = True
while run:
    if game_state == "menu":
        redrawMenuWindow()
    elif game_state == "game":
        redrawGameWindow()
    elif game_state == "shop":
        redrawShopWindow()
        pygame.display.update()

    for event in pygame.event.get():
        pos = pygame.mouse.get_pos()

        if event.type == pygame.QUIT:
            run = False
            pygame.quit()
            quit()
        elif event.type == pygame.VIDEORESIZE:
            WINDOW_WIDTH = event.w
            WINDOW_HEIGHT = event.h
            win = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT), SURFACE)
            greenButton.resize_button(event.w*0.3, event.h*0.3, event.w/2, event.h/2)

        if event.type == pygame.MOUSEBUTTONDOWN:
            if greenButton.isOver(pos):
                print("clicked the button")
                game_state = "game"
            if redButton.isOver(pos):
                print("clicked the 2button")
                run = False
                pygame.quit()
                quit()
            if cyanButton.isOver(pos):
                print("clicked the 3button")
                game_state = "shop"


        if event.type == pygame.MOUSEMOTION:
            if greenButton.isOver(pos):
                greenButton.color = (105, 105, 105)
            else:
                greenButton.color = (0, 255, 0)
            if redButton.isOver(pos):
                redButton.color = (105, 105, 105)
            else:
                redButton.color = (255, 0, 0)
            if cyanButton.isOver(pos):
                cyanButton.color = (105, 105, 105)
            else:
                cyanButton.color = (20, 210, 180)

        if event.type == pygame.KEYDOWN:
            playerX_change = -0.3
            print("Left arrow is pressed")
            if event.key == pygame.K_RIGHT:
                 playerX_change = 0.3
                 print("Right arrow is pressed")
         if event.type == pygame.KEYUP:
            if event.key == pygame.K_a or event.key == pygame.K_d:
                playerX_change = 0.1
                print("Keystroke has been released")

    pygame.display.update()

    playerX += playerX_change
    player(playerX, playerY)

pygame.display.update()

请告诉我代码。如果你只是告诉我问题是什么,我可能不知道如何解决它。最好能告诉我哪里出了问题,然后编写正确的代码(不一定是整个代码,只是我需要的部分)。如果真正的问题是我因为我忘记了什么或打错了,那么我很抱歉问这个问题。

【问题讨论】:

  • 玩家只能向右移动吗?看起来您缺少playerX_change = -0.3 上方的 if 语句。像if event.key == pygame.K_LEFT: 这样的东西你有可能同时左右移动角色(-0.3 + 0.3 == 0.0)
  • 您能否解释一下您遇到了哪些错误,以及您想用这段代码实现什么?
  • 你有错误的缩进并且你在if event.type == pygame.MOUSEMOTION:里面有if event.type == pygame.KEYDOWN:。所以它仅在您移动鼠标时检查key,但此时event.type 不能是KEYDOWN,因为它是MOUSEMOTIONKEYUP 也有同样的问题。您必须使用较小的缩进将KEYDOWN/KEYUP 移出if event.type == pygame.MOUSEMOTION:
  • 我现在编辑了它。也许它更好地解释,请回答,不要评论。如果你回答它,请重写整个代码。
  • 别指望我们会为你编写所有代码。

标签: python pygame resize window character


【解决方案1】:

第一个问题是你在update() 之后在主循环中绘制player,所以它会在你绘制player 之前更新监视器上的图像。最后它在fill() 之前绘制玩家,将其从Surface 中删除,update() 在监视器上显示Surface 而没有此player

您在redrawGameWindow 中绘制第二个玩家(在update() 之前,并且该玩家在屏幕上可见,但该玩家使用(370, 400),因此它永远不会移动。


包含其他更改的完整代码。

基于PEP 8 -- Style Guide for Python Code的一些改动

import pygame
#from pygame.locals import * # PEP8: `import *` is not preferred (but you don't even need it

# --- constants --- (UPPER_CASE_NAMES) # PEP8

WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600
SURFACE = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE


# --- classes --- (CamerCaseNames) # PEP8

class Button():

    def __init__(self, color, x, y, width, height, text=''):
        self.color = color
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.text = text

    def draw(self, win, outline=None):
        # Call this method to draw the button on the screen
        if outline:
            pygame.draw.rect(win, outline, (self.x - 2, self.y - 2, self.width + 4, self.height + 4), 0)

        pygame.draw.rect(win, self.color, (self.x, self.y, self.width, self.height), 0)

        if self.text != '':
            font = pygame.font.SysFont('comicsans', 60)
            text = font.render(self.text, 1, (0, 0, 0))
            win.blit(text, (self.x + (self.width / 2 - text.get_width() / 2), self.y + (self.height / 2 - text.get_height() / 2)))

    def is_over(self, pos):
        # Pos is the mouse position or a tuple of (x,y) coordinates
        if pos[0] > self.x and pos[0] < self.x + self.width:
            if pos[1] > self.y and pos[1] < self.y + self.height:
                return True

        return False

    def rescale(self):
        new_size = int(WINDOW_WIDTH * self.scale_factor)
        x, y = self.rect.center
        self.image = pygame.transform.smoothscale(self.original, (new_size, new_size))
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)

    def resize_button(self, WINDOW_WIDTH, WINDOW_HEIGHT, x, y):
        self.width = WINDOW_WIDTH
        self.height = WINDOW_HEIGHT
        self.x = x
        self.y = y

# --- functions --- (lower_case_names) # PEP8

def player(x,y):
    win.blit(playerImg, (x, y))

def redraw_menu_window():
    win.fill((0, 255, 110))
    green_button.draw(win, (0, 0, 0))
    red_button.draw(win, (0, 0, 0))
    cyan_button.draw(win, (0, 0, 0))

def redraw_game_window():
    win.fill((0, 150, 210))
    pygame.draw.rect(win, (0, 250, 110), (0, 450, 800, 250))
    win.blit(player_img, (player_x, player_y)) # use playerX, playerY

def redraw_shop_window():
    win.fill((200, 100, 30))

# --- main ---

pygame.init()

win = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT), SURFACE)
win.fill((0, 180, 210))

pygame.display.set_caption("Baloon War!")
icon = pygame.image.load("Baloon war icon.png")
pygame.display.set_icon(icon)

#centre_point = (WINDOW_WIDTH//2, WINDOW_HEIGHT//2)
center_point = win.get_rect().center 

player_img = pygame.image.load("RobiS.png")
player_x = 370
player_y = 500
player_x_change = 0

green_button = Button((0, 255, 0), 275, 285, 250, 80, "Start")
red_button = Button((255, 0, 0), 275, 475, 250, 80, "Quit")
cyan_button = Button((20, 210, 180), 275, 380, 250, 80, "Shop")

game_state = "menu"
run = True
while run:

    # --- draws ---

    if game_state == "menu":
        redraw_menu_window()
    elif game_state == "game":
        player_x += player_x_change
        redraw_game_window()
    elif game_state == "shop":
        redraw_shop_window()

    pygame.display.update()

    for event in pygame.event.get():
        pos = pygame.mouse.get_pos()

        if event.type == pygame.QUIT:
            run = False
            pygame.quit()
            quit()

        elif event.type == pygame.VIDEORESIZE:
            WINDOW_WIDTH = event.w
            WINDOW_HEIGHT = event.h
            win = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT), SURFACE)
            greenButton.resize_button(event.w*0.3, event.h*0.3, event.w/2, event.h/2)

        elif event.type == pygame.MOUSEBUTTONDOWN: # you can use `elif`
            if game_state == "menu":
                if green_button.is_over(pos):
                    print("clicked the button")
                    game_state = "game"
                if red_button.is_over(pos):
                    print("clicked the 2button")
                    run = False
                    pygame.quit()
                    quit()
                if cyan_button.is_over(pos):
                    print("clicked the 3button")
                    game_state = "shop"
            elif game_state == "shop": # it has to be `elif` because in previous line is `game_state = "shop"` which could run it at once.
                game_state = "menu"

        elif event.type == pygame.MOUSEMOTION: # you can use `elif`
            if game_state == "menu":
                if green_button.is_over(pos):
                    green_button.color = (105, 105, 105)
                else:
                    green_button.color = (0, 255, 0)
                if red_button.is_over(pos):
                    red_button.color = (105, 105, 105)
                else:
                    red_button.color = (255, 0, 0)
                if cyan_button.is_over(pos):
                    cyan_button.color = (105, 105, 105)
                else:
                    cyan_button.color = (20, 210, 180)

        elif event.type == pygame.KEYDOWN: # you can use `elif`
            if game_state == "game":
                if event.key == pygame.K_LEFT:
                    print("Left arrow is pressed")
                    player_x_change = -0.3
                if event.key == pygame.K_RIGHT:
                    player_x_change = 0.3
                    print("Right arrow is pressed")

        elif event.type == pygame.KEYUP: # you can use `elif`
            if game_state == "game":
                if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                    player_x_change = 0
                    print("Keystroke has been released")

# -- end ---

顺便说一句:你应该看到pygame.Rect(),它用于保持位置和大小,它有rect.right,你可以使用它来代替x + width。它具有检查碰撞的功能,如果鼠标悬停在按钮上,您可以使用它。


编辑:有更多变化的代码。

我使用pygame.Rect 来保持位置和大小,并在Button 中检查碰撞。我还创建了Player 类,并在ButtonPlayer 类中检查了events。类也有方法update()draw()handle_events,因此您可以将它们保留在列表中或pygame.sprite.Group 并使用for-loop 为所有对象执行这些函数。

import pygame

# --- constants --- (UPPER_CASE_NAMES) # PEP8

WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600
SURFACE = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE

# --- classes --- (CamerCaseNames) # PEP8

class Button():

    def __init__(self, color, hover_color, x, y, width, height, text='', outline=None, action=None):
        self.normal_color = color
        self.hover_color = hover_color

        self.color = self.normal_color

        self.rect = pygame.Rect(x, y, width, height)
        self.text = text

        self.rect_outline = self.rect.copy()
        self.rect_outline.x -= 2
        self.rect_outline.y -= 2
        self.rect_outline.width  += 4
        self.rect_outline.height += 4

        self.font = pygame.font.SysFont('comicsans', 60)
        self.text_image = self.font.render(self.text, 1, (0, 0, 0))
        self.text_rect = self.text_image.get_rect(center=self.rect.center)

        self.outline = outline
        self.action = action

    def draw(self, win):
        # Call this method to draw the button on the screen
        if self.outline:
            pygame.draw.rect(win, self.outline, self.rect_outline, 0)

        pygame.draw.rect(win, self.color, self.rect, 0)

        if self.text != '':
            win.blit(self.text_image, self.text_rect)

    def is_over(self, pos):
        return self.rect.collidepoint(pos)

    def rescale(self):
        new_size = int(WINDOW_WIDTH * self.scale_factor)
        x, y = self.rect.center
        self.image = pygame.transform.smoothscale(self.original, (new_size, new_size))
        self.rect = self.image.get_rect(center=(x, y))

    def resize_button(self, WINDOW_WIDTH, WINDOW_HEIGHT, x, y):
        self.rect.width = WINDOW_WIDTH
        self.rect.height = WINDOW_HEIGHT
        self.rect.x = x
        self.rect.y = y

    def handle_event(self, event):
        if event.type == pygame.MOUSEBUTTONDOWN:
            if self.rect.collidepoint(event.pos):
                if self.action:
                    self.action() # execute callback fuction
        if event.type == pygame.MOUSEMOTION:
            if self.is_over(event.pos):
                self.color = self.hover_color
            else:
                self.color = self.normal_color


class Player():

    def __init__(self, x, y):
        #self.image = pygame.image.load("RobiS.png")
        self.image = pygame.image.load("Obrazy/images/square-1.png")
        self.rect = self.image.get_rect(x=x, y=y)
        self.player_x_change = 0
        # you need because you use float values to move player but `self.rect` can keep only int values
        self.x = x
        self.y = y
        self.x_change = 0

    def draw(self, win):
        self.rect.x = int(self.x)
        self.rect.y = int(self.y)
        win.blit(self.image, self.rect)

    def update(self):
        self.x += self.x_change

    def handle_event(self, event):
        if event.type == pygame.KEYDOWN: # you can use `elif`
            if event.key == pygame.K_LEFT:
                print("Left arrow is pressed")
                self.x_change = -0.3
            elif event.key == pygame.K_RIGHT:
                self.x_change = 0.3
                print("Right arrow is pressed")

        elif event.type == pygame.KEYUP: # you can use `elif`
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                self.x_change = 0
                print("Keystroke has been released")

# --- functions --- (lower_case_names) # PEP8

def redraw_menu_window():
    win.fill((0, 255, 110))
    green_button.draw(win)
    red_button.draw(win)
    cyan_button.draw(win)

def redraw_game_window():
    win.fill((0, 150, 210))
    pygame.draw.rect(win, (0, 250, 110), (0, 450, 800, 250))
    player.draw(win)
    back_to_menu_button.draw(win)

def redraw_shop_window():
    win.fill((200, 100, 30))
    back_to_menu_button.draw(win)

def callback_green_button():
    global game_state

    print("clicked the button")
    game_state = "game"

def callback_red_button():
    global run

    print("clicked the 2button")
    run = False

def callback_cyan_button():
    global game_state

    print("clicked the 3button")
    game_state = "shop"

def callback_back_button():
    global game_state

    print("back button")
    game_state = "menu"

# --- main ---

pygame.init()

win = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT), SURFACE)
win.fill((0, 180, 210))

pygame.display.set_caption("Baloon War!")
#icon = pygame.image.load("Baloon war icon.png")
icon = pygame.image.load("Obrazy/images/ball.png")
pygame.display.set_icon(icon)

#centre_point = (WINDOW_WIDTH//2, WINDOW_HEIGHT//2)
center_point = win.get_rect().center 

player = Player(370, 500)

green_button = Button((0, 255, 0), (105, 105, 105), 275, 285, 250, 80, "Start", (0, 0, 0), callback_green_button)
red_button = Button((255, 0, 0), (105, 105, 105), 275, 475, 250, 80, "Quit", (0, 0, 0), callback_red_button)
cyan_button = Button((20, 210, 180), (105, 105, 105), 275, 380, 250, 80, "Shop", (0, 0, 0), callback_cyan_button)

back_to_menu_button = Button((20, 210, 180), (105, 105, 105), 275, 380, 250, 80, "BACK", (0, 0, 0), callback_back_button)

game_state = "menu"
run = True
while run:

    # --- draws ---

    if game_state == "menu":
        redraw_menu_window()
    elif game_state == "game":
        redraw_game_window()
    elif game_state == "shop":
        redraw_shop_window()

    pygame.display.update()

    # --- events ---

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

        elif event.type == pygame.VIDEORESIZE:
            WINDOW_WIDTH = event.w
            WINDOW_HEIGHT = event.h
            win = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT), SURFACE)
            green_button.resize_button(event.w*0.3, event.h*0.3, event.w/2, event.h/2)

        if game_state == "menu":
            green_button.handle_event(event)
            red_button.handle_event(event)
            cyan_button.handle_event(event)
        elif game_state == "game":
            player.handle_event(event)
            back_to_menu_button.handle_event(event)
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    game_state = "menu"
        elif game_state == "shop":
            back_to_menu_button.handle_event(event)
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    game_state = "menu"

    # --- updates ---

    if game_state == "menu":
        #green_button.update()
        #red_button.update()
        #cyan_button.update()
        pass
    elif game_state == "game":
        player.update()
    elif game_state == "shop":
        pass

# -- end ---
pygame.quit()
quit()

【讨论】:

  • 感谢您的回答。问题是我忘记在KEYDOWN 部分添加+0.3 或-0.3。非常感谢你向我展示了这一点,我很感激你花时间很好地回答了我这个问题并写了整个代码:)。所以忘记代码中的东西是我的错
猜你喜欢
  • 1970-01-01
  • 2021-06-22
  • 1970-01-01
  • 2021-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-01
  • 2023-02-25
相关资源
最近更新 更多