Skip to content

Instantly share code, notes, and snippets.

@mr-linch
Created June 8, 2014 10:19
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mr-linch/f6dacd2a069887a47fbc to your computer and use it in GitHub Desktop.
Save mr-linch/f6dacd2a069887a47fbc to your computer and use it in GitHub Desktop.
First person camera for pyglet
# -*- coding: utf-8 -*-
import math
import collections
import pyglet
class FirstPersonCamera(object):
"""First person camera implementation
Usage:
import pyglet
from pyglet.gl import *
from camera import FirstPersonCamera
window = pyglet.window.Window(fullscreen=True)
window.set_exclusive_mouse(True)
camera = FirstPersonCamera(window)
@window.event
def on_draw():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
camera.draw()
# Your draw code here
return pyglet.event.EVENT_HANDLED
def on_update(delta_time):
camera.update(delta_time)
# Your update code here
if __name__ == '__main__':
pyglet.clock.schedule(on_update)
pyglet.app.run()
"""
DEFAULT_MOVEMENT_SPEED = 10.0
DEFAULT_MOUSE_SENSITIVITY = 0.25
DEFAULT_KEY_MAP = {
'forward': pyglet.window.key.W,
'backward': pyglet.window.key.S,
'left': pyglet.window.key.A,
'right': pyglet.window.key.D,
'up': pyglet.window.key.SPACE,
'down': pyglet.window.key.LSHIFT
}
class InputHandler(object):
def __init__(self):
self.pressed = collections.defaultdict(bool)
self.dx = 0
self.dy = 0
def on_key_press(self, symbol, modifiers):
self.pressed[symbol] = True
def on_key_release(self, symbol, modifiers):
self.pressed[symbol] = False
def on_mouse_motion(self, x, y, dx, dy):
self.dx = dx
self.dy = dy
def __init__(self, window, position=(0, 0, 0), key_map=DEFAULT_KEY_MAP, movement_speed=DEFAULT_MOVEMENT_SPEED, mouse_sensitivity=DEFAULT_MOUSE_SENSITIVITY, y_inv=True):
"""Create camera object
Arguments:
window -- pyglet window which camera attach
position -- position of camera
key_map -- dict like FirstPersonCamera.DEFAULT_KEY_MAP
movement_speed -- speed of camera move (scalar)
mouse_sensitivity -- sensitivity of mouse (scalar)
y_inv -- inversion turn above y-axis
"""
self.__position = list(position)
self.__yaw = 0.0
self.__pitch = 0.0
self.__input_handler = FirstPersonCamera.InputHandler()
window.push_handlers(self.__input_handler)
self.y_inv = y_inv
self.key_map = key_map
self.movement_speed = movement_speed
self.mouse_sensitivity = mouse_sensitivity
def yaw(self, yaw):
"""Turn above x-axis"""
self.__yaw += yaw * self.mouse_sensitivity
def pitch(self, pitch):
"""Turn above y-axis"""
self.__pitch += pitch * self.mouse_sensitivity * ((-1) if self.y_inv else 1)
def move_forward(self, distance):
"""Move forward on distance"""
self.__position[0] -= distance * math.sin(math.radians(self.__yaw))
self.__position[2] += distance * math.cos(math.radians(self.__yaw))
def move_backward(self, distance):
"""Move backward on distance"""
self.__position[0] += distance * math.sin(math.radians(self.__yaw))
self.__position[2] -= distance * math.cos(math.radians(self.__yaw))
def move_left(self, distance):
"""Move left on distance"""
self.__position[0] -= distance * math.sin(math.radians(self.__yaw - 90))
self.__position[2] += distance * math.cos(math.radians(self.__yaw - 90))
def move_right(self, distance):
"""Move right on distance"""
self.__position[0] -= distance * math.sin(math.radians(self.__yaw + 90))
self.__position[2] += distance * math.cos(math.radians(self.__yaw + 90))
def move_up(self, distance):
"""Move up on distance"""
self.__position[1] -= distance
def move_down(self, distance):
"""Move down on distance"""
self.__position[1] += distance
def update(self, delta_time):
"""Update camera state"""
self.yaw(self.__input_handler.dx)
self.__input_handler.dx = 0
self.pitch(self.__input_handler.dy)
self.__input_handler.dy = 0
if self.__input_handler.pressed[self.key_map['forward']]:
self.move_forward(delta_time * self.movement_speed)
if self.__input_handler.pressed[self.key_map['backward']]:
self.move_backward(delta_time * self.movement_speed)
if self.__input_handler.pressed[self.key_map['left']]:
self.move_left(delta_time * self.movement_speed)
if self.__input_handler.pressed[self.key_map['right']]:
self.move_right(delta_time * self.movement_speed)
if self.__input_handler.pressed[self.key_map['up']]:
self.move_up(delta_time * self.movement_speed)
if self.__input_handler.pressed[self.key_map['down']]:
self.move_down(delta_time * self.movement_speed)
def draw(self):
"""Apply transform"""
pyglet.gl.glRotatef(self.__pitch, 1.0, 0.0, 0.0)
pyglet.gl.glRotatef(self.__yaw, 0.0, 1.0, 0.0)
pyglet.gl.glTranslatef(*self.__position)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment