ユーザーがマウスをウィンドウの外に移動すると、相対位置 (event.rel) を返すことができる機能を Pygame に実装しようとしています。マウス入力で左右に曲がり続けるゲームを作りたくてやってみました。
ドキュメントからこれが可能であることを知っています:
マウス カーソルが非表示になっていて、入力が現在のディスプレイに取り込まれている場合、マウスは仮想入力モードに入り、マウスの相対的な動きが画面の境界によって停止されることはありません。これを構成するには、関数 pygame.mouse.set_visible() および pygame.event.set_grab() を参照してください。
このため、これらの行をコードに実装しました
pygame.mouse.set_visible(False)
pygame.event.set_grab(True)
ただし、これは役に立ちません。実際の動作は次のとおりです。
- マウスがウィンドウ内を移動すると、event.rel がコンソールに出力されます (予想)。
- マウスがウィンドウの外に移動すると、event.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()