6

I am not writing a game but a scientific renderer using Pygame. I'd like the controls to work just like in a first-person shooter, so that a user can navigate using a familiar set of controls.

I have tried to write the code to have the same properties as the 'look' feature in e.g. Skyrim or Half-Life but the mouse doesn't move the cursor - it lets you look around and around, in infinite circles. Clicking should have no effect.

The first attempt for the controls:

(code inside a game loop)

delta_y, delta_x = pygame.mouse.get_rel()
rotation_direction.x = float(delta_x)
rotation_direction.y = float(delta_y)

(don't ask me why, but y and x need to be reversed like this to get the expected look directions; must be something to do with the camera transform implementation, which isn't mine.)

This, however, leads to a cursor sitting on top of the window, and when the cursor gets to the edge of the screen the window stops rotating; i.e. the code is reporting the actual position on the screen.

I tried to 'reset' the mouse position every game loop (and, incidentally, hide the mouse):

pygame.mouse.set_pos([150, 150])
pygame.mouse.set_visible(False)

But this generates a symmetrical 'move back to start' delta in the next loop, meaning that you couldn't 'look' anywhere.

To summarize, I want to:

  • detect actual mouse motion reported from the device
  • not move/show any OS cursor
  • not clip at the 'edge of a screen'

What is the best way to do this, using Pygame or other Python hacks?

fragilewindows
  • 1,394
  • 1
  • 15
  • 26
tehwalrus
  • 2,589
  • 5
  • 26
  • 33

3 Answers3

6

http://www.pygame.org/docs/ref/mouse.html :

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. See the functions pygame.mouse.set_visible - hide or show the mouse cursor and pygame.event.set_grab (docs) - control the sharing of input devices with other applications to get this configured.

tehwalrus
  • 2,589
  • 5
  • 26
  • 33
Ofir
  • 8,194
  • 2
  • 29
  • 44
  • In other words, also call pygame.event.set_grab(True) – Ofir Sep 23 '12 at 22:44
  • Aha, I looked in the docs for a mouse capture function but couldn't find it, hence the suggestion in my answer. – Kylotan Sep 23 '12 at 22:53
  • On my computer the order mattered, grabbing then hiding the mouse still got caught on the edges, whereas grabbing then hiding works fine. – cuppajoeman Aug 04 '23 at 02:47
1

Try calling pygame.mouse.get_rel() once more immediately after the set_pos call to 'throw away' whatever relative movement the set_pos call has performed.

Kylotan
  • 18,290
  • 7
  • 46
  • 74
0

Since you are using pyOpenGL, try gluLookAt() example: How do I use gluLookAt properly?

Community
  • 1
  • 1
ninMonkey
  • 7,211
  • 8
  • 37
  • 66
  • While this doesn't strictly answer the question (which is about mouse events capture,) `gluLookAt` is something I hadn't seen before, and looks very relevant to anyone trying to solve this problem - in my case, it would allow me to avoid using some python code (much slower) to do the same thing by hand. Thanks for the heads up! :) – tehwalrus Sep 24 '12 at 07:17