# 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 . 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)