rk_island/game/game.py
2022-12-31 19:16:44 +01:00

219 lines
8.1 KiB
Python

# 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 math import pi, tau, dist
from engine import *
from game import math
from game.time import Time
from game.events import Events
from game.mouse import Mouse
from game.keyboard import Keyboard
from game.generator import Generator
from game.resources import RuntimeArchive
from game.texture import Texture
from game.shader import Shader
from game.camera import Camera
from game.environment import Environment
from game.inputs import InputFloat
from game.batch import Batch
from game.scene import SceneNode, TextureNode, ShaderNode, InputNode, DrawNode, FuncNode
from game.triangles import SkyTriangles
from game import sea
proj_hfov = pi * 0.25
proj_ratio = 16.0 / 9.0
proj_near_z = 8.0
proj_far_z = 3000.0
sun_direction = math.vec3_normalize((1.0, 0.0, 0.5))
sun_power = 1.0
def update_camera(time, mouse, camera, environment):
camera_yaw = mouse.drag[0] * 0.001
camera_pitch = mouse.drag[1] * 0.001 + pi * 0.25
camera_distance = mouse.wheel * 20.0
camera.set_view(camera_yaw, camera_pitch, camera_distance)
environment.from_sun(camera.view, sun_direction, sun_power)
def update_tests(time, blob_translation, blob_spawn_translation, cube_translation, cube_spawn_translation, cube_orientation, clouds_orientation):
rotation = mat3()
mat3_rotation(rotation, vec3_up, (time.current * 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, (time.current * 0.43) % tau)
mat3_rotation(clouds_orientation, vec3_up, (time.current * -0.037) % tau)
def update_sea(time, camera, sea_phase):
camera.to_km()
sea_phase.update((time.current * 0.023) % 1.0)
def main():
print("Initializing...")
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(__debug__)
tiles_shader = Shader('terrain', 'common')
tests_shader = Shader('tests', 'common')
sky_shader = Shader('sky')
camera = Camera()
camera.set_projection(proj_hfov, proj_ratio, proj_near_z, proj_far_z)
environment = Environment()
sea_phase = InputFloat(sky_shader.u_sea_phase, 0.0)
print("Generating terrain...")
generated = Generator(256)
heightmap = Texture(
TEXTURE_FORMAT_FLOAT_32, 256, 256, 0, TEXTURE_FLAG_MIN_LINEAR | TEXTURE_FLAG_MAG_LINEAR,
generated.packed_heights)
normalmap = Texture(
TEXTURE_FORMAT_RGB10_A2, 256, 256, 0, TEXTURE_FLAG_MIN_LINEAR | TEXTURE_FLAG_MAG_LINEAR,
generated.packed_normals)
print("Loading resources...")
archive = RuntimeArchive.load('data/rk_island.rkar')
print("Building tiles...")
tiles_texture = archive.get_texture('tiles')
tiles_vertices = archive.get_vertices('tiles')
water_model = archive.get_model('water')
sand_model = archive.get_model('sand')
grass_model = archive.get_model('grass')
forest_model = archive.get_model('forest')
rock_model = archive.get_model('rock')
mud_model = archive.get_model('mud')
lava_model = archive.get_model('lava')
tiles_batch = Batch(tiles_vertices, generated.size ** 2, 8, translation = PARAM_FORMAT_VEC3_SHORT)
#TODO: generator & for real
vc = generated.volcano_c
vr = generated.volcano_r
for my, mx in generated.map_coords:
vd = dist((mx + 0.5, my + 0.5), vc)
nx, ny, nz, h = generated.unpack(my, mx)
r = generated.rivers[my * generated.size + mx]
if h == 0.0:
continue
if r > 0.0:
model = water_model
elif h < 2.0:
model = sand_model
elif h < 180:
if nz > 0.9:
if ny < -0.01 and nz > 0.93:
model = forest_model
else:
model = grass_model
else:
model = rock_model
elif vd < vr - 3.0 and nz > 0.999:
model = lava_model
elif vd < vr + 2.0:
model = mud_model
elif vd < vr + 6.0 and nz < 0.67:
model = mud_model
else:
model = rock_model
model.spawn(tiles_batch, vec3(float(((mx - 128) * 8) + 4), float(((127 - my) * 8) + 4), 0.0))
tests_texture = archive.get_texture('tests')
tests_vertices = archive.get_vertices('tests')
blob_model = archive.get_model('blob')
cube_model = archive.get_model('cube')
clouds_model = archive.get_model('clouds')
tests_batch = Batch(tests_vertices, 3, 3,
translation = PARAM_FORMAT_VEC3_FLOAT,
orientation = PARAM_FORMAT_MAT3_INT10 | PARAM_FORMAT_NORMALIZE)
blob_spawn_translation = vec3(-100.0, -500.0, 0.0)
blob_forward = math.vec3_normalize((sun_direction[0], sun_direction[1], 0.0))
blob_right = math.vec3_cross(blob_forward, math.vec3_up)
blob_spawn_orientation = mat3(vec3(*blob_right), vec3(*blob_forward), vec3_up)
blob_id = blob_model.spawn(tests_batch, blob_spawn_translation, blob_spawn_orientation)
blob_translation = tests_batch.translation[blob_id]
cube_spawn_translation = vec3(100.0, -500.0, 0.0)
cube_id = cube_model.spawn(tests_batch, cube_spawn_translation, mat3_identity)
cube_translation = tests_batch.translation[cube_id]
cube_orientation = tests_batch.orientation[cube_id]
clouds_id = clouds_model.spawn(tests_batch, vec3(0.0, 0.0, 32.0), mat3_identity)
clouds_orientation = tests_batch.orientation[clouds_id]
sea_polar_textures = sea.load_polar_textures(('data/sea_bump1.png', 'data/sea_bump2.png'))
sea_detail_texture = sea.load_detail_texture('data/sea_bump.png')
sky_triangles = SkyTriangles(64, proj_far_z - 0.1, proj_ratio)
scene = SceneNode(
FuncNode(update_camera, (mouse, camera, environment)),
TextureNode((tiles_texture, heightmap, normalmap),
ShaderNode(tiles_shader,
InputNode(tiles_shader, camera),
InputNode(tiles_shader, environment),
DrawNode(tiles_batch)
)
),
FuncNode(update_tests, (blob_translation, blob_spawn_translation, cube_translation, cube_spawn_translation, cube_orientation, clouds_orientation)),
TextureNode((tests_texture, heightmap, normalmap),
ShaderNode(tests_shader,
InputNode(tests_shader, camera),
InputNode(tests_shader, environment),
DrawNode(tests_batch)
)
),
FuncNode(update_sea, (camera, sea_phase)),
TextureNode((sea_polar_textures, sea_detail_texture),
ShaderNode(sky_shader,
InputNode(sky_shader, camera),
InputNode(sky_shader, environment),
InputNode(sky_shader, sea_phase),
DrawNode(sky_triangles)
)
)
)
print("Running... Ctrl+c to quit")
time = Time()
try:
while not keyboard.quit:
events.update()
begin_frame()
time.update()
scene.draw(time)
end_frame()
swap_buffers(display)
except KeyboardInterrupt:
pass
print("Quitting...")
del tests_batch
del tiles_batch
del sky_triangles
del sea_polar_textures
del sea_detail_texture
del heightmap
del normalmap
archive.destroy()
del tiles_shader
del tests_shader
del sky_shader
render_terminate()
del events
destroy_display(display)