Я пытаюсь реализовать функцию в Pygame, где, если пользователь перемещает мышь за пределы окна, относительная позиция (event.rel) может быть возвращена. Я пытаюсь сделать это, потому что я хочу сделать игру, в которой вы можете продолжать поворачивать влево или вправо от ввода мышью.
Я знаю, что это возможно из документов:
Если курсор мыши скрыт и ввод захватывается текущим дисплеем, мышь переходит в режим виртуального ввода, при котором относительные движения мыши никогда не будут останавливаться на границах экрана. См. Функции pygame.mouse.set_visible () и pygame.event.set_grab (), чтобы настроить это.
По этой причине я реализовал эти строки в своем коде
pygame.mouse.set_visible(False)
pygame.event.set_grab(True)
Однако это не помогает. Фактическое поведение:
- , когда мышь перемещается в окне, event.rel печатает на консоль (ожидается)
- , когда мышь перемещается за пределы окна, событие. rel не печатает на консоль (не ожидается)
Другое странное поведение:
- Первоначально для event.rel установлено значение (300, 300), которое является центром моего экрана 600x600. В идеале начальный event.rel должен быть (0,0)
Возможная причина:
- Я запускаю приведенный ниже код в trinket.io или repl.it . Поскольку это браузер, демонстрационное окно может вызвать проблемы. Может быть, это решается загрузкой python локально, но я не хочу этого делать, так как это занимает слишком много места (мой ноутбук отстой), а также было бы хорошо иметь онлайн-демонстрацию, чтобы легко показывать слишком ленивым работодателям вставить код в их IDE.
Аналогичная проблема: у этого парня на reddit была очень похожая проблема, но я думаю, что его решение не связано с моей ситуацией
Этот блок кода был тем, что я спрашивал изначально, но он не демонстрирует вопрос так же, как последний блок. Пожалуйста, прокрутите вниз, чтобы увидеть последний блок кода:)
import pygame
pygame.init()
# screen
X = 600 # width
Y = 600 # height
halfX = X/2
halfY = Y/2
screen = pygame.display.set_mode((X, Y), pygame.FULLSCREEN)
clock = pygame.time.Clock()
# Colors
WHITE = (255, 255, 255)
RED = (255, 0, 0)
# From the docs:
# "If the mouse cursor is hidden, and input is grabbed to the
# current display the mouse will enter a virtual input mode, where
# the relative movements of the mouse will never be stopped by the
# borders of the screen."
pygame.mouse.set_visible(False)
pygame.event.set_grab(True)
def drawCross(point, size, color):
pygame.draw.line(screen, color, (point[0]-size,point[1]-size), (point[0]+size,point[1]+size), 2)
pygame.draw.line(screen, color, (point[0]+size,point[1]-size), (point[0]-size,point[1]+size), 2)
canvas_rel = (halfX,halfY)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.MOUSEMOTION:
print('event.rel = ' + str(event.rel))
canvas_rel = [10 * event.rel[0] + halfX, 10 * event.rel[1] + halfY]
print(' canvas_rel = ' + str(canvas_rel))
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
print('escape')
running = False
break
screen.fill(WHITE)
# Red sight to represent pygame mouse event.rel
drawCross(canvas_rel, 10, RED)
pygame.display.flip()
clock.tick(20)
pygame.quit()
РЕДАКТИРОВАТЬ:
Приведенный выше код не полностью демонстрирует мою проблему. Я добавил лучший пример ниже, чтобы облегчить понимание вопроса. Этот образец нарисует треугольник в центре экрана. Треугольник будет вращаться с относительным горизонтальным движением мыши. Обратите внимание на попытку использовать pygame.mouse.set_pos
import pygame
from math import pi, cos, sin
pygame.init()
# screen
X = 600 # width
Y = 600 # height
halfX = X/2
halfY = Y/2
screen = pygame.display.set_mode((X, Y), pygame.FULLSCREEN)
clock = pygame.time.Clock()
# for getting relative mouse position when outside the screen
pygame.mouse.set_visible(False)
pygame.event.set_grab(True)
# Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
# sensitivity
senseTheta = 0.01
# player
stand = [halfX, halfY]
t = 0 # angle in radians from positive X axis to positive x axis anticlockwise about positive Z
# draws a white cross in the screen center for when shooting is implemented :)
def drawPlayer():
p = stand
d = 50
a1 = 0.25*pi-t
a2 = 0.75*pi-t
P = (p[0],p[1])
A1 = (p[0] + d*cos(a1), p[1] + d*sin(a1)) # P + (d*cos(a1), d*sin(a1))
A2 = (p[0] + d*cos(a2), p[1] + d*sin(a2)) # P + (d*cos(a2), d*sin(a2))
pygame.draw.line(screen, BLACK, P, A1, 2)
pygame.draw.line(screen, BLACK, A1, A2, 2)
pygame.draw.line(screen, BLACK, A2, P, 2)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.MOUSEMOTION:
mouseMove = event.rel
print('mouseMove = ' + str(mouseMove))
t -= mouseMove[0] * senseTheta
# "Fix" the mouse pointer at the center
# pygame.mouse.set_pos((screen.get_width()//2, screen.get_height()//2))
# But I think set_pos triggers another MOUSEMOTION event as moving in positive x
# seems to move backward the same amount in x (i.e. the triangle doesn't
# rotate). See the console log.
# If you uncomment this line it works ok (the triangle rotates) but still
# glitches when the mouse leaves the window.
# uncommented or not I still cant get the mouse to work outside the window
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
break
screen.fill(WHITE)
drawPlayer()
pygame.display.flip()
clock.tick(40)
pygame.quit()