// Forest example (Diablo-style camera) for lance3d // Fixed 3/4 camera, WASD movement // Press ESC to exit. var time_mod = use('time') var lance3d = use('core') var math = use('math/radians') // Meshes var ground_mesh = null var trunk_mesh = null var canopy_mesh = null var player_mesh = null // Materials var ground_mat = null var trunk_mat = null var canopy_mat_a = null var canopy_mat_b = null var player_mat = null // Player state var player = { x: 0, y: 0.5, z: 0, yaw: 0, speed: 6.0 } // Trees: array of {x, z, trunk_h, trunk_r, canopy_s, canopy_mat} var trees = [] var num_trees = 80 var cam_offset = { x: 10, y: 12, z: 10 } var last_time = 0 function _init() { log.console("lance3d Forest (Diablo camera) Example") log.console("WASD move, ESC exit") lance3d.set_style("ps1") lance3d.seed(1337) lance3d.set_lighting({ sun_dir: [0.4, 1.0, 0.2], sun_color: [1.0, 0.95, 0.9], ambient: [0.35, 0.35, 0.40] }) lance3d.set_fog({ enabled: true, color: [0.55, 0.70, 0.90], near: 40, far: 160 }) // Create meshes ground_mesh = lance3d.make_plane(220, 220) trunk_mesh = lance3d.make_cube(1, 1, 1) canopy_mesh = lance3d.make_cube(1, 1, 1) player_mesh = lance3d.make_cube(1, 1, 1) // Create materials ground_mat = { paint: [0.12, 0.22, 0.10, 1.0], coverage: "opaque", face: "single", lamp: "lit" } trunk_mat = { paint: [0.35, 0.23, 0.14, 1.0], coverage: "opaque", face: "single", lamp: "lit" } canopy_mat_a = { paint: [0.11, 0.40, 0.18, 1.0], coverage: "opaque", face: "single", lamp: "lit" } canopy_mat_b = { paint: [0.09, 0.33, 0.14, 1.0], coverage: "opaque", face: "single", lamp: "lit" } player_mat = { paint: [0.85, 0.25, 0.20, 1.0], coverage: "opaque", face: "single", lamp: "lit" } // Generate trees var i = null var x = null var z = null for (i = 0; i < num_trees; i++) { x = (lance3d.rand() - 0.5) * 90 z = (lance3d.rand() - 0.5) * 90 trees.push({ x: x, z: z, trunk_h: lance3d.rand() * 3 + 2, trunk_r: lance3d.rand() * 0.25 + 0.25, canopy_s: lance3d.rand() * 1.0 + 1.5, canopy_mat: lance3d.rand() < 0.5 ? canopy_mat_a : canopy_mat_b }) } last_time = time_mod.number() frame() } function _update(dt) { if (lance3d.key('escape')) { $stop() return } // Movement input var forward = 0 var right = 0 var fx = null var fz = null var len = null if (lance3d.key('w')) forward += 1 if (lance3d.key('s')) forward -= 1 if (lance3d.key('d')) right -= 1 if (lance3d.key('a')) right += 1 if (forward != 0 || right != 0) { // Update yaw based on movement direction player.yaw = math.arc_tangent(forward, -right) fx = math.sine(player.yaw) fz = math.cosine(player.yaw) len = math.sqrt(fx * fx + fz * fz) if (len > 0) { fx /= len fz /= len } player.x += fx * player.speed * dt player.z += fz * player.speed * dt } } function _draw() { var i = null var tree = null var trunk_transform = null var canopy_transform = null var q = null var player_transform = null lance3d.clear(0.55, 0.70, 0.90, 1.0) // Set up camera following player lance3d.camera_perspective(55, 0.1, 300) lance3d.camera_look_at( {x: player.x + cam_offset.x, y: cam_offset.y, z: player.z + cam_offset.z}, {x: player.x, y: 0, z: player.z} ) // Draw ground lance3d.draw_mesh(ground_mesh, null, ground_mat) // Draw tree trunks for (i = 0; i < length(trees); i++) { tree = trees[i] trunk_transform = lance3d.trs_matrix( [tree.x, tree.trunk_h / 2, tree.z], [0, 0, 0, 1], [tree.trunk_r, tree.trunk_h, tree.trunk_r] ) lance3d.draw_mesh(trunk_mesh, trunk_transform, trunk_mat) } // Draw tree canopies for (i = 0; i < length(trees); i++) { tree = trees[i] canopy_transform = lance3d.trs_matrix( [tree.x, tree.trunk_h + tree.canopy_s / 2, tree.z], [0, 0, 0, 1], [tree.canopy_s, tree.canopy_s, tree.canopy_s] ) lance3d.draw_mesh(canopy_mesh, canopy_transform, tree.canopy_mat) } // Draw player q = lance3d.euler_to_quat(0, player.yaw, 0) player_transform = lance3d.trs_matrix( [player.x, player.y, player.z], [q.x, q.y, q.z, q.w], [0.7, 1.0, 0.7] ) lance3d.draw_mesh(player_mesh, player_transform, player_mat) } function frame() { lance3d._begin_frame() if (!lance3d._process_events()) { log.console("Exiting...") $stop() return } var now = time_mod.number() var dt = now - last_time last_time = now _update(dt) _draw() lance3d._end_frame() $delay(frame, 1/60) } _init()