簡體   English   中英

Pyglet on_key_press 和 on_mouse_motion 非常不一致

[英]Pyglet on_key_press and on_mouse_motion are being very inconsistent

背景

當我偶然發現這個人的 Minecraft 克隆時,我一直在玩弄 pyglet。 Github 在這里: https://github.com/fogleman/Minecraft

我做了一些修改(針對 Python 3 和我自己的一些偏好),完整的代碼在這里: modified minecraft

問題

當我運行代碼時,它有時可能不會注冊任何鼠標移動或按鍵。 這種情況很少見,但偶爾會發生。 我會說10次,它會打破一次。

細節

我什至不知道罪魁禍首是什么,但我會提供一些代碼片段。

這是不可預測的,但有一些方法可以解決它。 目前唯一可靠的方法是強制退出(不僅僅是退出)應用程序,然后重新啟動它。

我不知道為什么,我已經嘗試了各種各樣的方法來嘗試修復它。

如果重要的話,我正在使用 macOS Mojave、Python 3.8.2 和 Pyglet 1.5.14

這是 window 的__init__ function:

def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Whether or not the window exclusively captures the mouse.
        self.exclusive = False

        # When flying gravity has no effect and speed is increased.
        self.flying = False

        # Strafing is moving lateral to the direction you are facing,
        # e.g. moving to the left or right while continuing to face forward.
        #
        # First element is -1 when moving forward, 1 when moving back, and 0
        # otherwise. The second element is -1 when moving left, 1 when moving
        # right, and 0 otherwise.
        self.strafe = [0, 0]

        # Current (x, y, z) position in the world, specified with floats. Note
        # that, perhaps unlike in math class, the y-axis is the vertical axis.
        self.position = (0, 0, 0)

        # First element is rotation of the player in the x-z plane (ground
        # plane) measured from the z-axis down. The second is the rotation
        # angle from the ground plane up. Rotation is in degrees.
        #
        # The vertical plane rotation ranges from -90 (looking straight down) to
        # 90 (looking straight up). The horizontal rotation range is unbounded.
        self.rotation = (0, 0)

        # Which sector the player is currently in.
        self.sector = None

        # The crosshairs at the center of the screen.
        self.reticle = None

        # Velocity in the y (upward) direction.
        self.dy = 0

        # A list of blocks the player can place. Hit num keys to cycle.
        self.inventory = [BRICK, GRASS, SAND]

        # The current block the user can place. Hit num keys to cycle.
        self.block = self.inventory[0]

        # Convenience list of num keys.
        self.num_keys = [
            key._1, key._2, key._3, key._4, key._5,
            key._6, key._7, key._8, key._9, key._0]

        # Instance of the model that handles the world.
        self.model = Model()

        # The label that is displayed in the top left of the canvas.
        self.label = pyglet.text.Label('', font_name='Arial', font_size=18,
            x=10, y=self.height - 10, anchor_x='left', anchor_y='top',
            color=(0, 0, 0, 255))

        # This call schedules the `update()` method to be called
        # TICKS_PER_SEC. This is the main game event loop.
        pyglet.clock.schedule_interval(self.update, 1.0 / TICKS_PER_SEC)

這是輸入處理程序:

def on_mouse_press(self, x, y, button, modifiers):
        """ Called when a mouse button is pressed. See pyglet docs for button
        amd modifier mappings.

        Parameters
        ----------
        x, y : int
            The coordinates of the mouse click. Always center of the screen if
            the mouse is captured.
        button : int
            Number representing mouse button that was clicked. 1 = left button,
            4 = right button.
        modifiers : int
            Number representing any modifying keys that were pressed when the
            mouse button was clicked.

        """
        if self.exclusive:
            vector = self.get_sight_vector()
            block, previous = self.model.hit_test(self.position, vector)
            if (button == mouse.RIGHT) or \
                    ((button == mouse.LEFT) and (modifiers & key.MOD_CTRL)):
                # ON OSX, control + left click = right click.
                if previous:
                    self.model.add_block(previous, self.block)
            if button == pyglet.window.mouse.LEFT and block:
                texture = self.model.world[block]
                self.model.remove_block(block)
        else:
            self.set_exclusive_mouse(True)

    def on_mouse_motion(self, x, y, dx, dy):
        """ Called when the player moves the mouse.

        Parameters
        ----------
        x, y : int
            The coordinates of the mouse click. Always center of the screen if
            the mouse is captured.
        dx, dy : float
            The movement of the mouse.

        """
        if self.exclusive:
            m = 0.15
            x, y = self.rotation
            x, y = x + dx * m, y + dy * m
            y = max(-90, min(90, y))
            self.rotation = (x, y)

    def on_key_press(self, symbol, modifiers):
        if symbol == key.W:
            self.strafe[0] -= 1
        if symbol == key.S:
            self.strafe[0] += 1
        if symbol == key.A:
            self.strafe[1] -= 1
        if symbol == key.D:
            self.strafe[1] += 1
        if symbol == key.SPACE:
            if self.dy == 0:
                self.dy = JUMP_SPEED
        if symbol == key.ESCAPE:
            self.set_exclusive_mouse(False)
        if symbol == key.TAB:
            self.flying = not self.flying
        if symbol in self.num_keys:
            index = (symbol - self.num_keys[0]) % len(self.inventory)
            self.block = self.inventory[index]

最后,這是設置:

    """ Configure the OpenGL fog properties.

    """
    # Enable fog. Fog "blends a fog color with each rasterized pixel fragment's
    # post-texturing color."
    glEnable(GL_FOG)
    # Set the fog color.
    glFogfv(GL_FOG_COLOR, (GLfloat * 4)(0.5, 0.69, 1.0, 1))
    # Say we have no preference between rendering speed and quality.
    glHint(GL_FOG_HINT, GL_DONT_CARE)
    # Specify the equation used to compute the blending factor.
    glFogi(GL_FOG_MODE, GL_LINEAR)
    # How close and far away fog starts and ends. The closer the start and end,
    # the denser the fog in the fog range.
    glFogf(GL_FOG_START, 50.0)
    glFogf(GL_FOG_END, 100.0)


def setup():
    """ Basic OpenGL configuration.

    """
    # Set the color of "clear", i.e. the sky, in rgba.
    glClearColor(0.5, 0.69, 1.0, 1)
    # Enable culling (not rendering) of back-facing facets -- facets that aren't
    # visible to you.
    glEnable(GL_CULL_FACE)
    # Set the texture minification/magnification function to GL_NEAREST (nearest
    # in Manhattan distance) to the specified texture coordinates. GL_NEAREST
    # "is generally faster than GL_LINEAR, but it can produce textured images
    # with sharper edges because the transition between texture elements is not
    # as smooth."
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    setup_fog()


def main():
    window = Window(width=800, height=600, caption='Minecraft', resizable=True)
    # Hide the mouse cursor and prevent the mouse from leaving the window.
    setup()

if __name__ == '__main__':
    main()
    pyglet.app.run()

這是texture.png

重命名為 texture.png

這是正在發生的事情的一個例子(黑色圓圈表示我點擊了鼠標,最后我快速按下了 W): gif

我做了什么

這是我到目前為止所做的:

  • 看了 Pyglet Docs
  • 用各種短語和關鍵字在谷歌上進行研究

聽起來這可能是與 Mac 相關的問題。 這是關於 Mac 發生類似情況的錯誤報告: https://github.com/pyglet/pyglet/issues/225

我會嘗試的一件事就是嘗試一個准系統設置,看看問題是否仍然存在於最少的代碼中。 如果仍然出現這種情況,則很可能是 Mac/Pyglet 交互中存在錯誤。 如果基本示例有效,則 Minecraft 示例中可能存在錯誤。

import pyglet

window = pyglet.window.Window()

@window.event
def on_draw():
    print('on_draw')
    window.clear()

@window.event
def on_mouse_motion(x, y, dx, dy):
    print('on_mouse_motion', x, y, dx, dy)

@window.event
def on_key_press(symbol, modifiers):
    print('on_key_press', symbol, modifiers)

pyglet.app.run()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM