Compare commits
2 Commits
1ac12ea9ea
...
758ed8c7f4
Author | SHA1 | Date | |
---|---|---|---|
758ed8c7f4 | |||
850a254abc |
2
engine
2
engine
@ -1 +1 @@
|
||||
Subproject commit 269d7821c82757cf994370f9ed4b2a6d36e34983
|
||||
Subproject commit 33abfd834ad5c9541796ef3f8a4999539a2f91f8
|
@ -13,13 +13,7 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from engine import (
|
||||
vec3, vec3_mul_vec3,
|
||||
mat3, mat3_rotation, mat3_mul_vec3,
|
||||
mat4, mat4_projection, mat4_lookat,
|
||||
resolve_input, set_input_mat4)
|
||||
|
||||
_m2km = vec3(0.001, 0.001, 0.001)
|
||||
from engine import vec3_origin, mat4, mat4_projection, mat4_orbit, resolve_input, set_input_mat4
|
||||
|
||||
class _Inputs:
|
||||
__slots__ = 'projection', 'view'
|
||||
@ -29,30 +23,26 @@ class _Inputs:
|
||||
self.view = resolve_input(shader, view)
|
||||
|
||||
class Camera:
|
||||
__slots__ = 'origin', 'lookat', 'rotation', 'projection', 'view'
|
||||
__slots__ = 'yaw', 'pitch', 'distance', 'projection', 'view'
|
||||
|
||||
def __init__(self):
|
||||
self.origin = vec3()
|
||||
self.lookat = vec3()
|
||||
self.rotation = mat3()
|
||||
self.yaw = 0.0
|
||||
self.pitch = 0.0
|
||||
self.distance = 0.0
|
||||
self.projection = mat4()
|
||||
self.view = mat4()
|
||||
|
||||
def set_projection(self, half_fov, ratio, near_z, far_z):
|
||||
mat4_projection(self.projection, half_fov, ratio, near_z, far_z)
|
||||
|
||||
def set_view(self, origin, lookat, axis, angle):
|
||||
self.origin.set(*origin)
|
||||
self.lookat.set(*lookat)
|
||||
mat3_rotation(self.rotation, axis, angle)
|
||||
mat3_mul_vec3(self.origin, self.rotation, self.origin)
|
||||
mat3_mul_vec3(self.lookat, self.rotation, self.lookat)
|
||||
mat4_lookat(self.view, self.origin, self.lookat)
|
||||
def set_view(self, yaw, pitch, distance):
|
||||
self.yaw = yaw
|
||||
self.pitch = pitch
|
||||
self.distance = distance
|
||||
mat4_orbit(self.view, vec3_origin, yaw, pitch, distance)
|
||||
|
||||
def to_km(self):
|
||||
vec3_mul_vec3(self.origin, _m2km, self.origin)
|
||||
vec3_mul_vec3(self.lookat, _m2km, self.lookat)
|
||||
mat4_lookat(self.view, self.origin, self.lookat)
|
||||
mat4_orbit(self.view, vec3_origin, self.yaw, self.pitch, self.distance * 0.001)
|
||||
|
||||
def resolve_inputs(self, shader, projection = b'u_projection', view = b'u_view'):
|
||||
return _Inputs(shader, projection, view)
|
||||
|
54
game/events.py
Normal file
54
game/events.py
Normal file
@ -0,0 +1,54 @@
|
||||
# Copyright (C) 2022 RozK
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from engine import (
|
||||
buffer,
|
||||
EVENT_FOCUS_IN, EVENT_FOCUS_OUT,
|
||||
EVENT_KEY_PRESS, EVENT_KEY_RELEASE,
|
||||
EVENT_BUTTON_PRESS, EVENT_BUTTON_RELEASE,
|
||||
EVENT_MOTION,
|
||||
Event, create_events, destroy_events, consume_events)
|
||||
|
||||
_max_type = max(
|
||||
EVENT_FOCUS_IN, EVENT_FOCUS_OUT,
|
||||
EVENT_KEY_PRESS, EVENT_KEY_RELEASE,
|
||||
EVENT_BUTTON_PRESS, EVENT_BUTTON_RELEASE,
|
||||
EVENT_MOTION)
|
||||
|
||||
_max_events = 64
|
||||
|
||||
class Events:
|
||||
__slots__ = '_display', '_events', '_buffer', '_handlers'
|
||||
|
||||
def __init__(self, display):
|
||||
self._display = display
|
||||
self._events = create_events(display)
|
||||
self._buffer = buffer(Event, _max_events)
|
||||
self._handlers = [[] for _ in range(_max_type + 1)]
|
||||
|
||||
def __del__(self):
|
||||
destroy_events(self._display, self._events)
|
||||
|
||||
def register(self, type, handler):
|
||||
assert type <= _max_type
|
||||
self._handlers[type].append(handler)
|
||||
|
||||
def update(self):
|
||||
nevents = consume_events(self._events, self._buffer, _max_events)
|
||||
if nevents:
|
||||
for event in self._buffer[:nevents]:
|
||||
data = event.data
|
||||
for handler in self._handlers[event.type]:
|
||||
handler(data)
|
63
game/game.py
63
game/game.py
@ -28,15 +28,15 @@ from game.resources import RuntimeArchive
|
||||
from game.batch import Batch
|
||||
from game.camera import Camera
|
||||
from game.environment import Environment
|
||||
from game.events import Events
|
||||
from game.mouse import Mouse
|
||||
from game.keyboard import Keyboard
|
||||
|
||||
proj_hfov = pi * 0.25
|
||||
proj_ratio = 16.0 / 9.0
|
||||
proj_near_z = 8.0
|
||||
proj_far_z = 3000.0
|
||||
|
||||
camera_origin = (0.0, -1200.0, 500.0)
|
||||
camera_lookat = (0.0, 500.0, -500.0)
|
||||
|
||||
sun_direction = math.vec3_normalize((1.0, 0.0, 1.0))
|
||||
sun_power = 1.0
|
||||
|
||||
@ -48,8 +48,10 @@ def main():
|
||||
print("Done: ", round(gen_end - gen_begin, 2), "seconds")
|
||||
|
||||
print("Initializing...")
|
||||
display = create_display(b'RK Island', 1600, 900)
|
||||
events = create_events(display)
|
||||
display = create_display(b'RK Island - Drag to rotate, wheel to zoom, q to quit', 1600, 900)
|
||||
events = Events(display)
|
||||
mouse = Mouse(events, wheel = 60, wheel_min = 20)
|
||||
keyboard = Keyboard(events)
|
||||
render_initialize()
|
||||
terrain_shader = shader.load('terrain', 'common')
|
||||
tests_shader = shader.load('tests', 'common')
|
||||
@ -157,7 +159,7 @@ def main():
|
||||
cube_orientation = tests_batch.params[cube_id].orientation
|
||||
clouds_orientation = tests_batch.params[clouds_id].orientation
|
||||
|
||||
print("Running... Click or press q to quit")
|
||||
print("Running... Ctrl+c to quit")
|
||||
start_time = time.monotonic()
|
||||
current_time = 0.0
|
||||
frame_min = 10000.0
|
||||
@ -167,22 +169,21 @@ def main():
|
||||
draw_max = 0.0
|
||||
draw_avg = 0.0
|
||||
perf_count = 0
|
||||
events_buffer = buffer(Event, 16)
|
||||
try:
|
||||
for frame in range(10000):
|
||||
current_time = time.monotonic() - start_time
|
||||
|
||||
begin_frame()
|
||||
frame_begin = time.thread_time()
|
||||
|
||||
rotation = mat3()
|
||||
mat3_rotation(rotation, vec3_up, (current_time * 0.21) % tau)
|
||||
mat3_mul_vec3(blob_translation, rotation, blob_spawn_translation)
|
||||
mat3_mul_vec3(cube_translation, rotation, cube_spawn_translation)
|
||||
mat3_rotation(cube_orientation, vec3_up, (current_time * 0.43) % tau)
|
||||
mat3_rotation(clouds_orientation, vec3_up, (current_time * -0.037) % tau)
|
||||
events.update()
|
||||
if keyboard.quit:
|
||||
break
|
||||
|
||||
camera.set_view(camera_origin, camera_lookat, vec3_up, (current_time * 0.05) % tau)
|
||||
begin_frame()
|
||||
|
||||
camera_distance = mouse.wheel * 20.0
|
||||
camera_yaw = mouse.drag[0] * 0.001
|
||||
camera_pitch = mouse.drag[1] * 0.001 + pi * 0.25
|
||||
camera.set_view(camera_yaw, camera_pitch, camera_distance)
|
||||
environment.from_sun(camera.view, sun_direction, sun_power)
|
||||
|
||||
select_shader(terrain_shader)
|
||||
@ -201,6 +202,13 @@ def main():
|
||||
unselect_texture(2, normalmap)
|
||||
unselect_shader(terrain_shader)
|
||||
|
||||
rotation = mat3()
|
||||
mat3_rotation(rotation, vec3_up, (current_time * 0.21) % tau)
|
||||
mat3_mul_vec3(blob_translation, rotation, blob_spawn_translation)
|
||||
mat3_mul_vec3(cube_translation, rotation, cube_spawn_translation)
|
||||
mat3_rotation(cube_orientation, vec3_up, (current_time * 0.43) % tau)
|
||||
mat3_rotation(clouds_orientation, vec3_up, (current_time * -0.037) % tau)
|
||||
|
||||
select_shader(tests_shader)
|
||||
camera.update_inputs(tests_camera_inputs)
|
||||
environment.update_inputs(tests_environment_inputs)
|
||||
@ -243,23 +251,6 @@ def main():
|
||||
frame_avg += frame_ms
|
||||
perf_count += 1
|
||||
|
||||
stop = False
|
||||
while True:
|
||||
nevents = consume_events(events, events_buffer, len(events_buffer))
|
||||
if not nevents:
|
||||
break
|
||||
for event in events_buffer[:nevents]:
|
||||
if event.type == EVENT_FOCUS_IN:
|
||||
print("EVENT_FOCUS_IN")
|
||||
elif event.type == EVENT_FOCUS_OUT:
|
||||
print("EVENT_FOCUS_OUT")
|
||||
elif event.type == EVENT_KEY_PRESS and event.data.key.character == 'q':
|
||||
stop = True
|
||||
elif event.type == EVENT_BUTTON_RELEASE:
|
||||
stop = True
|
||||
if stop:
|
||||
break
|
||||
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
@ -274,10 +265,6 @@ def main():
|
||||
", avg =", round((frame_avg / perf_count) * 1000.0, 2), "ms")
|
||||
|
||||
# seed 666
|
||||
# camera_origin = vec3((0.0, -1200.0, 500.0))
|
||||
# camera_lookat = vec3((0.0, 500.0, -500.0))
|
||||
# for x in range(10000)
|
||||
# current_time = 0
|
||||
|
||||
# Draw * 9999 : min = 0.2 , max = 1.32 , avg = 0.27 ms
|
||||
# Draw * 9999 : min = 0.2 , max = 1.34 , avg = 0.27 ms
|
||||
@ -300,5 +287,5 @@ def main():
|
||||
destroy_shader(tests_shader)
|
||||
destroy_shader(sky_shader)
|
||||
render_terminate()
|
||||
destroy_events(display, events)
|
||||
del events
|
||||
destroy_display(display)
|
||||
|
27
game/keyboard.py
Normal file
27
game/keyboard.py
Normal file
@ -0,0 +1,27 @@
|
||||
# Copyright (C) 2022 RozK
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from engine import EVENT_KEY_PRESS
|
||||
|
||||
class Keyboard:
|
||||
__slots__ = 'quit'
|
||||
|
||||
def __init__(self, events):
|
||||
self.quit = False
|
||||
events.register(EVENT_KEY_PRESS, self.key_press_handler)
|
||||
|
||||
def key_press_handler(self, data):
|
||||
if data.key.character == 'q':
|
||||
self.quit = True
|
52
game/mouse.py
Normal file
52
game/mouse.py
Normal file
@ -0,0 +1,52 @@
|
||||
# Copyright (C) 2022 RozK
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from engine import (
|
||||
EVENT_BUTTON_PRESS, EVENT_BUTTON_RELEASE, EVENT_MOTION, BUTTON_LEFT, BUTTON_WHEEL_UP, BUTTON_WHEEL_DOWN)
|
||||
|
||||
class Mouse:
|
||||
__slots__ = 'buttons', 'wheel', 'wheel_min', 'position', 'drag'
|
||||
|
||||
def __init__(self, events, wheel = 0, wheel_min = None):
|
||||
self.buttons = 0
|
||||
self.wheel = wheel
|
||||
self.wheel_min = wheel_min
|
||||
self.position = None
|
||||
self.drag = (0, 0)
|
||||
events.register(EVENT_BUTTON_PRESS, self.button_press_handler)
|
||||
events.register(EVENT_BUTTON_RELEASE, self.button_release_handler)
|
||||
events.register(EVENT_MOTION, self.motion_handler)
|
||||
|
||||
def button_press_handler(self, data):
|
||||
button = data.button.index
|
||||
self.buttons |= 1 << button
|
||||
if button == BUTTON_WHEEL_UP:
|
||||
self.wheel -= 1
|
||||
if self.wheel_min is not None and self.wheel < self.wheel_min:
|
||||
self.wheel = self.wheel_min
|
||||
elif button == BUTTON_WHEEL_DOWN:
|
||||
self.wheel += 1
|
||||
|
||||
def button_release_handler(self, data):
|
||||
self.buttons &= ~(1 << data.button.index)
|
||||
|
||||
def motion_handler(self, data):
|
||||
new_x = data.motion.x
|
||||
new_y = data.motion.y
|
||||
if self.position and (self.buttons & (1 << BUTTON_LEFT)):
|
||||
prev_x, prev_y = self.position
|
||||
prev_dx, prev_dy = self.drag
|
||||
self.drag = (prev_dx + (new_x - prev_x), prev_dy + (new_y - prev_y))
|
||||
self.position = (new_x, new_y)
|
Loading…
Reference in New Issue
Block a user