split apart modules

This commit is contained in:
2025-12-14 01:36:35 -06:00
parent a223d3d2b3
commit 828db06c74
13 changed files with 2212 additions and 2941 deletions

View File

@@ -1,156 +0,0 @@
// Billboard Test for retro3d
// Usage: cell run examples/billboard_test.ce <sprite_path>
// sprite_path should be without extension, e.g. "assets/goblin"
// Creates two rows of billboards going off into the distance like alongside a road
// Colors shift through hues as they get further away
var time_mod = use('time')
var retro3d = use('core')
var sprite_path = args[0]
if (!sprite_path) {
log.console("Usage: cell run examples/billboard_test.ce <sprite_path>")
log.console(" sprite_path: path without extension (e.g. 'assets/goblin')")
$_.stop()
}
var sprite = null
var last_time = 0
var cam_angle = 0
function hsv_to_rgb(h, s, v) {
var c = v * s
var x = c * (1 - Math.abs((h / 60) % 2 - 1))
var m = v - c
var r = 0, g = 0, b = 0
if (h < 60) { r = c; g = x; b = 0 }
else if (h < 120) { r = x; g = c; b = 0 }
else if (h < 180) { r = 0; g = c; b = x }
else if (h < 240) { r = 0; g = x; b = c }
else if (h < 300) { r = x; g = 0; b = c }
else { r = c; g = 0; b = x }
return [r + m, g + m, b + m, 1]
}
function _init() {
log.console("retro3d Billboard Test")
log.console("Loading sprite: " + sprite_path)
retro3d.set_style("ps1")
sprite = retro3d.load_sprite(sprite_path)
if (!sprite) {
log.console("Error: Could not load sprite: " + sprite_path)
$_.stop()
return
}
log.console("Sprite loaded: " + text(sprite.width) + "x" + text(sprite.height))
log.console("Controls:")
log.console(" A/D - Rotate camera")
log.console(" ESC - Exit")
retro3d.set_ambient(0.4, 0.4, 0.5)
retro3d.set_light_dir(0.5, 1.0, 0.3, 1.0, 0.95, 0.9, 1.0)
last_time = time_mod.number()
frame()
}
function _update(dt) {
if (retro3d._state.keys_held['escape']) {
$_.stop()
}
if (retro3d._state.keys_held['a']) {
cam_angle = cam_angle - 1.5 * dt
}
if (retro3d._state.keys_held['d']) {
cam_angle = cam_angle + 1.5 * dt
}
}
function _draw() {
retro3d.clear(0.2, 0.3, 0.4, 1.0)
if (!sprite) return
// Set up perspective camera
retro3d.camera_perspective(60, 0.1, 100)
// Camera orbits around origin
var cam_dist = 8
var cam_x = Math.sin(cam_angle) * cam_dist
var cam_z = Math.cos(cam_angle) * cam_dist
var cam_y = 2
retro3d.camera_look_at(cam_x, cam_y, cam_z, 0, 1, 0)
// Draw ground plane
retro3d.push_state()
var ground_mat = retro3d.make_material("lit", {
color: [0.3, 0.4, 0.3, 1]
})
retro3d.set_material(ground_mat)
var ground = retro3d.make_plane(20, 20)
var ground_transform = retro3d.make_transform()
retro3d.draw_model(ground, ground_transform)
retro3d.pop_state()
// Draw two rows of billboards going into the distance
// Left row at x = -2, right row at x = 2
var num_billboards = 10
var spacing = 2.0
var start_z = -2
for (var i = 0; i < num_billboards; i++) {
var z = start_z - i * spacing
var distance_norm = i / (num_billboards - 1) // 0 to 1
// Hue shifts from 0 (red) to 270 (purple) as distance increases
var hue = distance_norm * 270
var color = hsv_to_rgb(hue, 0.9, 1.0)
// Left row
retro3d.draw_billboard(sprite, -2, 0, z, {
color: color,
mode: "cutout",
face: "y"
})
// Right row (slightly different hue offset)
var hue_right = (hue + 30) % 360
var color_right = hsv_to_rgb(hue_right, 0.9, 1.0)
retro3d.draw_billboard(sprite, 2, 0, z, {
color: color_right,
mode: "cutout",
face: "y"
})
}
}
function frame() {
retro3d._begin_frame()
if (!retro3d._process_events()) {
log.console("Exiting...")
$_.stop()
return
}
var now = time_mod.number()
var dt = now - last_time
last_time = now
_update(dt)
_draw()
retro3d._end_frame()
$_.delay(frame, 1/60)
}
_init()

View File

@@ -1,13 +1,8 @@
// Simple Cube Demo for retro3d
// Usage: cell run examples/cube.ce [style]
// style: ps1, n64, or saturn (default: ps1)
// Simple Cube Demo for lance3d
// Usage: cell run examples/cube.ce
var time_mod = use('time')
var retro3d = use('core')
// Parse command line arguments
var args = $_.args || []
var style = args[0] || "ps1"
var lance3d = use('core')
// Camera orbit state
var cam_distance = 5
@@ -15,36 +10,47 @@ var cam_yaw = 0
var cam_pitch = 0.4
var auto_rotate = true
// Model and transform
// Models and materials
var cube = null
var transform = null
var cube_mat = null
var ground = null
var ground_mat = null
// Timing
var last_time = 0
function _init() {
log.console("retro3d Cube Demo")
log.console("Style: " + style)
log.console("lance3d Cube Demo")
// Initialize retro3d with selected style
retro3d.set_style(style)
// Initialize lance3d with PS1 style
lance3d.set_style("ps1")
// Create a cube
cube = retro3d.make_cube(1, 1, 1)
// Create a cube mesh
cube = lance3d.make_cube(1, 1, 1)
cube_mat = {
color_map: null,
paint: [0.8, 0.3, 0.2, 1],
coverage: "opaque",
face: "single",
lamp: "lit"
}
// Create transform for the cube
transform = retro3d.make_transform()
transform.y = 0.5
// Create ground plane
ground = lance3d.make_plane(10, 10)
ground_mat = {
color_map: null,
paint: [0.3, 0.5, 0.3, 1],
coverage: "opaque",
face: "single",
lamp: "lit"
}
// Set up lighting
retro3d.set_ambient(0.3, 0.3, 0.35)
retro3d.set_light_dir(0.5, 1.0, 0.3, 1.0, 0.95, 0.9, 1.0)
// Set up a default material
var mat = retro3d.make_material("lit", {
color: [0.8, 0.3, 0.2, 1]
lance3d.set_lighting({
sun_dir: [0.5, 1.0, 0.3],
sun_color: [1.0, 0.95, 0.9],
ambient: [0.3, 0.3, 0.35]
})
retro3d.set_material(mat)
last_time = time_mod.number()
@@ -65,77 +71,62 @@ function _update(dt) {
}
// Handle input for camera orbit
if (retro3d._state.keys_held['a']) {
if (lance3d._state.keys_held['a']) {
cam_yaw -= 2.0 * dt
auto_rotate = false
}
if (retro3d._state.keys_held['d']) {
if (lance3d._state.keys_held['d']) {
cam_yaw += 2.0 * dt
auto_rotate = false
}
if (retro3d._state.keys_held['w']) {
if (lance3d._state.keys_held['w']) {
cam_pitch += 2.0 * dt
if (cam_pitch > 1.5) cam_pitch = 1.5
}
if (retro3d._state.keys_held['s']) {
if (lance3d._state.keys_held['s']) {
cam_pitch -= 2.0 * dt
if (cam_pitch < -1.5) cam_pitch = -1.5
}
// Toggle auto-rotate
if (retro3d._state.keys_pressed[' ']) {
if (lance3d._state.keys_pressed['space']) {
auto_rotate = !auto_rotate
}
// Exit on escape
if (retro3d._state.keys_held['escape']) {
if (lance3d._state.keys_held['escape']) {
$_.stop()
}
}
function _draw() {
// Clear with style-appropriate color
if (style == "ps1") {
retro3d.clear(0.1, 0.05, 0.15, 1.0)
} else if (style == "n64") {
retro3d.clear(0.0, 0.1, 0.2, 1.0)
} else {
retro3d.clear(0.05, 0.05, 0.1, 1.0)
}
// Clear
lance3d.clear(0.1, 0.05, 0.15, 1.0)
// Set up camera
retro3d.camera_perspective(60, 0.1, 100)
lance3d.camera_perspective(60, 0.1, 100)
// Calculate camera position from orbit
var cam_x = Math.sin(cam_yaw) * Math.cos(cam_pitch) * cam_distance
var cam_y = Math.sin(cam_pitch) * cam_distance + 0.5
var cam_z = Math.cos(cam_yaw) * Math.cos(cam_pitch) * cam_distance
retro3d.camera_look_at(cam_x, cam_y, cam_z, 0, 0.5, 0)
lance3d.camera_look_at(cam_x, cam_y, cam_z, 0, 0.5, 0)
// Draw the cube
retro3d.draw_model(cube, transform)
// Draw the cube with transform
var cube_transform = lance3d.translation_matrix(0, 0.5, 0)
lance3d.draw_mesh(cube, cube_transform, cube_mat)
// Draw ground plane
retro3d.push_state()
var ground_mat = retro3d.make_material("lit", {
color: [0.3, 0.5, 0.3, 1]
})
retro3d.set_material(ground_mat)
var ground = retro3d.make_plane(10, 10)
var ground_transform = retro3d.make_transform()
retro3d.draw_model(ground, ground_transform)
retro3d.pop_state()
lance3d.draw_mesh(ground, null, ground_mat)
}
function frame() {
// Begin frame
retro3d._begin_frame()
lance3d._begin_frame()
// Process events
if (!retro3d._process_events()) {
if (!lance3d._process_events()) {
log.console("Exiting...")
$_.stop()
return
@@ -152,8 +143,8 @@ function frame() {
// Draw
_draw()
// End frame (submit GPU commands)
retro3d._end_frame()
// End frame
lance3d._end_frame()
// Schedule next frame
$_.delay(frame, 1/60)

View File

@@ -1,117 +1,86 @@
// Forest example (Diablo-style camera) for retro3d
// Fixed 3/4 camera, WASD movement, player faces the mouse using a ground screen-cast.
// Forest example (Diablo-style camera) for lance3d
// Fixed 3/4 camera, WASD movement
// Press ESC to exit.
var time_mod = use('time')
var retro3d = use('core')
var lance3d = use('core')
var ground_model = null
var ground_transform = null
// Meshes
var ground_mesh = null
var trunk_mesh = null
var canopy_mesh = null
var player_mesh = null
// Materials
var ground_mat = null
var trunk_model = null
var trunk_mat = null
var canopy_model = null
var canopy_mat_a = null
var canopy_mat_b = null
var player_model = null
var player_mat = null
var marker_model = null
var marker_transform = null
var marker_mat = null
// Player state
var player = {
transform: null,
speed: 6.0,
yaw: 0
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
var last_hit = null
function _set_camera() {
var px = player.transform.x
var pz = player.transform.z
retro3d.camera_perspective(55, 0.1, 300)
retro3d.camera_look_at(
px + cam_offset.x,
cam_offset.y,
pz + cam_offset.z,
px, 0, pz
)
}
function _set_yaw(t, yaw) {
player.yaw = yaw
var half = yaw / 2
retro3d.transform_set_rotation_quat(t, 0, Math.sin(half), 0, Math.cos(half))
}
function _init() {
log.console("retro3d Forest (Diablo camera) Example")
log.console("WASD move")
log.console("Face mouse (ground cast)")
log.console("ESC exit")
log.console("lance3d Forest (Diablo camera) Example")
log.console("WASD move, ESC exit")
retro3d.set_style("ps1")
retro3d.seed(1337)
lance3d.set_style("ps1")
retro3d.set_ambient(0.35, 0.35, 0.40)
retro3d.set_light_dir(0.4, 1.0, 0.2, 1.0, 0.95, 0.9, 1.0)
retro3d.set_fog(40, 160, [0.55, 0.70, 0.90])
lance3d.seed(1337)
ground_model = retro3d.make_plane(220, 220)
ground_transform = retro3d.make_transform()
retro3d.transform_set_position(ground_transform, 0, 0, 0)
ground_mat = retro3d.make_material("lit", { color: [0.12, 0.22, 0.10, 1.0] })
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]
})
trunk_model = retro3d.make_cube(1, 1, 1)
canopy_model = retro3d.make_cube(1, 1, 1)
trunk_mat = retro3d.make_material("lit", { color: [0.35, 0.23, 0.14, 1.0] })
canopy_mat_a = retro3d.make_material("lit", { color: [0.11, 0.40, 0.18, 1.0] })
canopy_mat_b = retro3d.make_material("lit", { color: [0.09, 0.33, 0.14, 1.0] })
lance3d.set_fog({
enabled: true,
color: [0.55, 0.70, 0.90],
near: 40,
far: 160
})
player_model = retro3d.make_cube(1, 1, 1)
player_mat = retro3d.make_material("lit", { color: [0.85, 0.25, 0.20, 1.0] })
player.transform = retro3d.make_transform()
retro3d.transform_set_position(player.transform, 0, 0.5, 0)
retro3d.transform_set_scale(player.transform, 0.7, 1.0, 0.7)
_set_yaw(player.transform, 0)
// 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)
marker_model = retro3d.make_cube(1, 1, 1)
marker_mat = retro3d.make_material("unlit", { color: [1.0, 0.95, 0.2, 1.0] })
marker_transform = retro3d.make_transform()
retro3d.transform_set_scale(marker_transform, 0.15, 0.15, 0.15)
// 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
for (var i = 0; i < num_trees; i++) {
var x, z
x = (retro3d.rand() - 0.5) * 90
z = (retro3d.rand() - 0.5) * 90
var trunk_h = retro3d.rand() * 3 + 2
var trunk_r = retro3d.rand() * 0.25 + 0.25
var canopy_s = retro3d.rand() * 1.0 + 1.5
var trunk = retro3d.make_transform()
retro3d.transform_set_position(trunk, x, trunk_h / 2, z)
retro3d.transform_set_scale(trunk, trunk_r, trunk_h, trunk_r)
var canopy = retro3d.make_transform()
retro3d.transform_set_position(canopy, x, trunk_h + canopy_s / 2, z)
retro3d.transform_set_scale(canopy, canopy_s, canopy_s, canopy_s)
var x = (lance3d.rand() - 0.5) * 90
var z = (lance3d.rand() - 0.5) * 90
trees.push({
trunk: trunk,
canopy: canopy,
canopy_mat: retro3d.rand() < 0.5 ? canopy_mat_a : canopy_mat_b
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
})
}
@@ -120,123 +89,103 @@ function _init() {
}
function _update(dt) {
if (retro3d._state.keys_held['escape']) {
if (lance3d._state.keys_held['escape']) {
$_.stop()
return
}
_set_camera()
var mx = retro3d._state.mouse_x || 0
var my = retro3d._state.mouse_y || 0
var hit = retro3d.screen_cast_ground(mx, my, 0)
if (hit) {
last_hit = hit
retro3d.transform_set_position(marker_transform, hit.x, 0.05, hit.z)
var px = player.transform.x
var pz = player.transform.z
var dx = hit.x - px
var dz = hit.z - pz
if (dx * dx + dz * dz > 0.00001) {
var yaw = Math.atan2(dx, dz)
_set_yaw(player.transform, yaw)
}
}
// Movement input
var forward = 0
var right = 0
if (retro3d._state.keys_held['w']) forward += 1
if (retro3d._state.keys_held['s']) forward -= 1
if (retro3d._state.keys_held['d']) right -= 1
if (retro3d._state.keys_held['a']) right += 1
if (lance3d._state.keys_held['w']) forward += 1
if (lance3d._state.keys_held['s']) forward -= 1
if (lance3d._state.keys_held['d']) right -= 1
if (lance3d._state.keys_held['a']) right += 1
if (forward != 0 || right != 0) {
// Update yaw based on movement direction
player.yaw = Math.atan2(forward, -right)
var fx = Math.sin(player.yaw)
var fz = Math.cos(player.yaw)
var rx = Math.cos(player.yaw)
var rz = -Math.sin(player.yaw)
var vx = fx * forward + rx * right
var vz = fz * forward + rz * right
var len = Math.sqrt(vx * vx + vz * vz)
var len = Math.sqrt(fx * fx + fz * fz)
if (len > 0) {
vx /= len
vz /= len
fx /= len
fz /= len
}
var px = player.transform.x + vx * player.speed * dt
var pz = player.transform.z + vz * player.speed * dt
retro3d.transform_set_position(player.transform, px, 0.5, pz)
player.x += fx * player.speed * dt
player.z += fz * player.speed * dt
}
}
function _draw() {
retro3d.clear(0.55, 0.70, 0.90, 1.0)
lance3d.clear(0.55, 0.70, 0.90, 1.0)
_set_camera()
// Set up camera following player
lance3d.camera_perspective(55, 0.1, 300)
lance3d.camera_look_at(
player.x + cam_offset.x,
cam_offset.y,
player.z + cam_offset.z,
player.x, 0, player.z
)
retro3d.push_state()
retro3d.set_material(ground_mat)
retro3d.draw_model(ground_model, ground_transform)
retro3d.pop_state()
// Draw ground
lance3d.draw_mesh(ground_mesh, null, ground_mat)
retro3d.push_state()
retro3d.set_material(trunk_mat)
for (let i = 0; i < trees.length; i++) {
retro3d.draw_model(trunk_model, trees[i].trunk)
// Draw tree trunks
for (var i = 0; i < trees.length; i++) {
var tree = trees[i]
var 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)
}
retro3d.pop_state()
retro3d.push_state()
for (let i = 0; i < trees.length; i++) {
retro3d.set_material(trees[i].canopy_mat)
retro3d.draw_model(canopy_model, trees[i].canopy)
// Draw tree canopies
for (var i = 0; i < trees.length; i++) {
var tree = trees[i]
var 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)
}
retro3d.pop_state()
retro3d.push_state()
retro3d.set_material(player_mat)
retro3d.draw_model(player_model, player.transform)
retro3d.pop_state()
if (last_hit) {
retro3d.push_state()
retro3d.set_material(marker_mat)
retro3d.draw_model(marker_model, marker_transform)
retro3d.pop_state()
}
// Draw player
var q = lance3d.euler_to_quat(0, player.yaw, 0)
var 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() {
// Begin frame
retro3d._begin_frame()
lance3d._begin_frame()
// Process events
if (!retro3d._process_events()) {
if (!lance3d._process_events()) {
log.console("Exiting...")
$_.stop()
return
}
// Calculate delta time
var now = time_mod.number()
var dt = now - last_time
last_time = now
// Update
_update(dt)
// Draw
_draw()
// End frame (submit GPU commands)
retro3d._end_frame()
lance3d._end_frame()
// Schedule next frame
$_.delay(frame, 1/60)
}
// Start
_init()

View File

@@ -1,20 +1,16 @@
// Model Viewer for retro3d
// Usage: cell run examples/modelview.ce <model_path> [style]
// style: ps1, n64, or saturn (default: ps1)
// Controls: F1=PS1, F2=N64, F3=Saturn
// Model Viewer for lance3d
// Usage: cell run examples/modelview.ce <model_path>
// Controls: WASD orbit, Q/E zoom, R/F move target, SPACE toggle animation, 1-9 switch clip
// F1/F2/F3 - Switch style (PS1/N64/Saturn)
var io = use('fd')
var time_mod = use('time')
var retro3d = use('core')
var lance3d = use('core')
log.console(lance3d.key)
// Parse command line arguments
var model_path = args[0] || "Duck.glb"
var style = args[1] || "ps1"
// Available styles for cycling
var styles = ["ps1", "n64", "saturn"]
var current_style_idx = styles.indexOf(style)
if (current_style_idx < 0) current_style_idx = 0
// Camera orbit state
var cam_distance = 5
@@ -24,53 +20,52 @@ var cam_target_y = 0
var orbit_speed = 2.0
var zoom_speed = 0.5
// Model and transform
// Model
var model = null
var transform = null
// Animation state
var anim = null
var anim_playing = false
var animations = []
var current_anim = 0
var anim_time = 0
var anim_playing = true
var anim_speed = 1.0
// Current style
var style = "ps1"
// Timing
var last_time = 0
function _init() {
log.console("retro3d Model Viewer")
log.console("Style: " + style)
log.console("lance3d Model Viewer")
log.console("Loading: " + model_path)
// Initialize retro3d with selected style
retro3d.set_style(style)
// Initialize lance3d with PS1 style
lance3d.set_style(style)
// Load the model
model = retro3d.load_model(model_path)
model = lance3d.load_model(model_path)
if (!model) {
log.console("Error: Could not load model: " + model_path)
$_.stop()
return
}
log.console("Model loaded with " + text(model.meshes.length) + " mesh(es)")
log.console(" Nodes: " + text(model.nodes.length))
log.console(" Textures: " + text(model.textures.length))
log.console(" Animations: " + text(model.animation_count))
log.console(" Skins: " + text(model.skins ? model.skins.length : 0))
log.console("Model loaded with " + text(model.length) + " mesh(es)")
// Create transform for the model (this will be an extra parent transform)
transform = retro3d.make_transform()
// Set up animation if model has animations
if (model.animation_count > 0) {
anim = retro3d.anim_instance(model)
retro3d.anim_play(anim, 0, true)
anim_playing = true
log.console(" Playing animation: " + (retro3d.anim_clip_name(anim, 0) || "clip 0"))
// Get animation info
animations = lance3d.anim_info(model)
log.console(" Animations: " + text(animations.length))
for (var i = 0; i < animations.length; i++) {
log.console(" " + text(i) + ": " + animations[i].name + " (" + text(animations[i].duration) + "s)")
}
// Set up lighting
retro3d.set_ambient(0.3, 0.3, 0.35)
retro3d.set_light_dir(0.5, 1.0, 0.3, 1.0, 0.95, 0.9, 1.0)
lance3d.set_lighting({
sun_dir: [0.5, 1.0, 0.3],
sun_color: [1.0, 0.95, 0.9],
ambient: [0.3, 0.3, 0.35]
})
last_time = time_mod.number()
@@ -81,174 +76,145 @@ function _init() {
log.console(" R/F - Move target up/down")
log.console(" SPACE - Toggle animation")
log.console(" 1-9 - Switch animation clip")
log.console(" F1 - PS1 style (128x128 tex, 2000 tris)")
log.console(" F2 - N64 style (32x32 tex, 3000 tris)")
log.console(" F3 - Saturn style (64x64 tex, 1500 tris)")
log.console(" ESC - Exit")
log.console(" F1 - PS1 style")
log.console(" F2 - N64 style")
log.console(" F3 - Saturn style")
// Start the main loop
frame()
}
function _switch_to_style(idx) {
if (idx == current_style_idx) return
if (idx < 0 || idx >= styles.length) return
current_style_idx = idx
style = styles[idx]
if (retro3d.switch_style(style)) {
// Recalculate model textures for new platform
if (model) {
retro3d.recalc_model_textures(model)
}
log.console("Switched to " + style.toUpperCase() + " style")
}
}
function _update(dt) {
// Handle input for camera orbit
if (retro3d._state.keys_held['a']) {
if (lance3d.key('a')) {
cam_yaw -= orbit_speed * dt
}
if (retro3d._state.keys_held['d']) {
if (lance3d.key('d')) {
cam_yaw += orbit_speed * dt
}
if (retro3d._state.keys_held['w']) {
if (lance3d.key('w')) {
cam_pitch += orbit_speed * dt
if (cam_pitch > 1.5) cam_pitch = 1.5
}
if (retro3d._state.keys_held['s']) {
if (lance3d.key('s')) {
cam_pitch -= orbit_speed * dt
if (cam_pitch < -1.5) cam_pitch = -1.5
}
// Zoom
if (retro3d._state.keys_held['q']) {
if (lance3d.key('q')) {
cam_distance -= zoom_speed * dt * cam_distance
if (cam_distance < 0.5) cam_distance = 0.5
}
if (retro3d._state.keys_held['e']) {
if (lance3d.key('e')) {
cam_distance += zoom_speed * dt * cam_distance
if (cam_distance > 100) cam_distance = 100
}
// Move target up/down
if (retro3d._state.keys_held['r']) {
if (lance3d.key('r')) {
cam_target_y += zoom_speed * dt
}
if (retro3d._state.keys_held['f']) {
if (lance3d.key('f')) {
cam_target_y -= zoom_speed * dt
}
// Exit on escape
if (retro3d._state.keys_held['escape']) {
if (lance3d.key('escape')) {
$_.stop()
}
// Toggle animation with space
if (retro3d._state.keys_pressed['space'] && anim) {
if (anim_playing) {
retro3d.anim_stop(anim)
anim_playing = false
log.console("Animation paused")
} else {
anim.playing = true
anim_playing = true
log.console("Animation resumed")
}
if (lance3d.keyp('space') && animations.length > 0) {
anim_playing = !anim_playing
log.console(anim_playing ? "Animation resumed" : "Animation paused")
}
// Switch animation clips with number keys
if (anim && model.animation_count > 0) {
if (animations.length > 0) {
for (var i = 1; i <= 9; i++) {
if (retro3d._state.keys_pressed[text(i)]) {
if (lance3d.keyp(text(i))) {
var clip_idx = i - 1
if (clip_idx < model.animation_count) {
retro3d.anim_play(anim, clip_idx, true)
anim_playing = true
log.console("Playing clip " + text(clip_idx) + ": " + (retro3d.anim_clip_name(anim, clip_idx) || "unnamed"))
if (clip_idx < animations.length) {
current_anim = clip_idx
anim_time = 0
log.console("Playing clip " + text(clip_idx) + ": " + animations[clip_idx].name)
}
}
}
}
// Switch platform style with F1-F3
if (retro3d._state.keys_pressed['f1']) {
_switch_to_style(0) // PS1
if (lance3d.keyp('f1')) {
_switch_to_style("ps1")
}
if (retro3d._state.keys_pressed['f2']) {
_switch_to_style(1) // N64
if (lance3d.keyp('f2')) {
_switch_to_style("n64")
}
if (retro3d._state.keys_pressed['f3']) {
_switch_to_style(2) // Saturn
if (lance3d.keyp('f3')) {
_switch_to_style("saturn")
}
// Update animation
if (anim && anim_playing) {
retro3d.anim_update(anim, dt)
retro3d.anim_apply(anim)
// Update animation time
if (anim_playing && animations.length > 0) {
anim_time += dt * anim_speed
var duration = animations[current_anim].duration
if (duration > 0) {
while (anim_time > duration) {
anim_time -= duration
}
}
}
}
function _switch_to_style(new_style) {
if (style == new_style) return
style = new_style
lance3d.switch_style(style)
// Recalculate model textures for new style
if (model) {
lance3d.recalc_model_textures(model)
}
log.console("Switched to " + style + " style")
}
function _draw() {
// Clear with a nice gradient-ish color based on style
// Clear with a nice color based on style
if (style == "ps1") {
retro3d.clear(0.1, 0.05, 0.15, 1.0)
lance3d.clear(0.1, 0.05, 0.15, 1.0)
} else if (style == "n64") {
retro3d.clear(0.0, 0.1, 0.2, 1.0)
lance3d.clear(0.0, 0.1, 0.2, 1.0)
} else {
retro3d.clear(0.05, 0.05, 0.1, 1.0)
lance3d.clear(0.05, 0.05, 0.1, 1.0)
}
// Set up camera
retro3d.camera_perspective(60, 0.1, 100)
lance3d.camera_perspective(60, 0.1, 100)
// Calculate camera position from orbit
var cam_x = Math.sin(cam_yaw) * Math.cos(cam_pitch) * cam_distance
var cam_y = Math.sin(cam_pitch) * cam_distance + cam_target_y
var cam_z = Math.cos(cam_yaw) * Math.cos(cam_pitch) * cam_distance
retro3d.camera_look_at(cam_x, cam_y, cam_z, 0, cam_target_y, 0)
lance3d.camera_look_at(cam_x, cam_y, cam_z, 0, cam_target_y, 0)
// Draw the model
if (model) {
retro3d.draw_model(model, transform)
var pose = null
if (animations.length > 0) {
pose = lance3d.sample_pose(model, current_anim, anim_time)
}
lance3d.draw_model(model, null, pose)
}
return
// Draw a ground grid using immediate mode
retro3d.push_state()
var grid_mat = retro3d.make_material("unlit", {
color: [0.3, 0.3, 0.3, 1]
})
retro3d.set_material(grid_mat)
retro3d.begin_lines()
retro3d.color(0.3, 1, 0.3, 1)
var grid_size = 10
var grid_step = 1
for (var i = -grid_size; i <= grid_size; i += grid_step) {
// X lines
retro3d.vertex(i, 0, -grid_size)
retro3d.vertex(i, 0, grid_size)
// Z lines
retro3d.vertex(-grid_size, 0, i)
retro3d.vertex(grid_size, 0, i)
}
retro3d.end()
retro3d.pop_state()
}
function frame() {
// Begin frame
retro3d._begin_frame()
lance3d._begin_frame()
// Process events
if (!retro3d._process_events()) {
if (!lance3d._process_events()) {
log.console("Exiting...")
$_.stop()
return
@@ -265,8 +231,8 @@ function frame() {
// Draw
_draw()
// End frame (submit GPU commands)
retro3d._end_frame()
// End frame
lance3d._end_frame()
// Schedule next frame
$_.delay(frame, 1/240)

View File

@@ -1,117 +0,0 @@
// Sprite Test for retro3d
// Usage: cell run examples/sprite_test.ce <sprite_path>
// sprite_path should be without extension, e.g. "assets/goblin"
// Fills screen with sprites, hue-shifted based on normalized screen position
var time_mod = use('time')
var retro3d = use('core')
var sprite_path = args[0]
if (!sprite_path) {
log.console("Usage: cell run examples/sprite_test.ce <sprite_path>")
log.console(" sprite_path: path without extension (e.g. 'assets/goblin')")
$_.stop()
}
var sprite = null
var last_time = 0
function hsv_to_rgb(h, s, v) {
var c = v * s
var x = c * (1 - Math.abs((h / 60) % 2 - 1))
var m = v - c
var r = 0, g = 0, b = 0
if (h < 60) { r = c; g = x; b = 0 }
else if (h < 120) { r = x; g = c; b = 0 }
else if (h < 180) { r = 0; g = c; b = x }
else if (h < 240) { r = 0; g = x; b = c }
else if (h < 300) { r = x; g = 0; b = c }
else { r = c; g = 0; b = x }
return [r + m, g + m, b + m, 1]
}
function _init() {
log.console("retro3d Sprite Test")
log.console("Loading sprite: " + sprite_path)
retro3d.set_style("ps1")
sprite = retro3d.load_sprite(sprite_path)
if (!sprite) {
log.console("Error: Could not load sprite: " + sprite_path)
$_.stop()
return
}
log.console("Sprite loaded: " + text(sprite.width) + "x" + text(sprite.height))
log.console("Press ESC to exit")
last_time = time_mod.number()
frame()
}
function _update(dt) {
if (retro3d._state.keys_held['escape']) {
$_.stop()
}
}
function _draw() {
retro3d.clear(0.1, 0.1, 0.15, 1.0)
if (!sprite) return
var w = sprite.width
var h = sprite.height
// Fill from bottom to top with sprites
// Hue shifts based on normalized screen position
var y = 0
while (y < 240) {
var x = 0
while (x < 320) {
// Normalized position (0-1)
var nx = x / 320
var ny = y / 240
// Hue based on position (0-360 degrees)
var hue = (nx + ny) * 180 // Combined X and Y influence
hue = hue % 360
var color = hsv_to_rgb(hue, 0.8, 1.0)
retro3d.draw_sprite(sprite, x, y, {
color: color,
mode: "cutout"
})
x = x + w
}
y = y + h
}
}
function frame() {
retro3d._begin_frame()
if (!retro3d._process_events()) {
log.console("Exiting...")
$_.stop()
return
}
var now = time_mod.number()
var dt = now - last_time
last_time = now
_update(dt)
_draw()
retro3d._end_frame()
$_.delay(frame, 1/60)
}
_init()