a = scene.addSignalListener("ray_angle_in", (_, r) => {if (observable_world ==0) return; viewof ray_angle_in.value=Math.round(r.ray_angle_in*100)/100; viewof ray_angle_in.dispatchEvent(newCustomEvent('input'), {bubbles:true});// I might never understand how to make this always work})aa = { level.addSignalListener("xy", (_, r) => { // this didn't improve perf a lot vs event listener: nearly every mousemove is a signal change, I supposeconsole.log('hi')if (observable_world ==0) return;console.log(r) viewof ray_angle_in.value=Math.round(Math.atan2((r.level_y_in[0] - player_y_in) , (r.level_x_in[0] - player_x_in))*100)/100; viewof ray_angle_in.dispatchEvent(newCustomEvent('input'), {bubbles:true});})}
Source Code
---title: "3D World 🧱🔫"order: 3#author: # - name: "Declan Naughton 🧮👨💻" # url: "https://calcwithdec.dev/about.html"#description: "some raycasting"format: html: echo: false resources: - '../../models/raycasting/*.js' - '../../models/raycasting/*.js.map' - '../../models/raycasting/*.json'---```{ojs}actions = trueimport {viewof keys} from 'd/867e1424e1d093ab'viewof keys//time_in = keys.lengthfov = pos[2].valuepos = calcudata({ models: [controls], input_cursors: [{time_in,data_table_in:keys.map(d => d.key), speed_in:3, fov_0_in:[-1-Math.PI/2,1-Math.PI/2]}], input_domains:[], outputs: ['player_x','player_y','fov']})md`### keys: ${keys.length == 0 ? '⌛' : keys.map(d => d.key).reverse().slice(0,10).map(d => d == 'ArrowUp' ? '⬆️' : d == 'ArrowDown' ? '⬇️' : d == 'ArrowLeft' ? '⬅️' : d == 'ArrowRight' ? '➡️' : d).join(' ')}`clamped_ray_angle_in = { if (ray_angle_in <= fov[1] && ray_angle_in >= fov[0]) return ray_angle_in else return undefined }//_.clamp(ray_angle_in,fov2[0],fov2[1])player_y_in = pos[1].valueplayer_x_in = pos[0].valueviewof scene = embed( calcuvizspec({ models: [main], input_cursors: [{player_x_in:pos[0].value,player_y_in,fov_in:fov}], mark: {type:'bar', point:false, clip:true, tooltip:false}, encodings: { //row: {name: 'formula', type:'nominal', domain: ['inverse_ray_length','negative_inverse_ray_length']}, x: {grid: false, name: 'ray_angle_in', /*sort:'descending',*/type: 'quantitative', domain: [clamped_ray_angle_in, ..._.range(fov[0],fov[1],ray_angle_in_step_size)], nice:false, ticks:2}, color: {name: 'ray_hit_color', type:'nominal', legend:false}, y: {grid: false, name: 'inverse_ray_length', type: 'quantitative'}, opacity: {name: 'inverse_ray_length', type: 'quantitative', legend:false}, }, width: 500, height:200, spec_post_process: spec => { spec.encoding.y.scale = {domain:[0,0.3],}; spec.encoding.x.axis = labels ? {tickCount:2, grid:false} : null spec.encoding.y.axis = labels ? {grid:false, orient: 'right'} : null spec.params = [{"name": "ray_angle_in", "value": { "ray_angle_in": 0}, "select": { "type": "point", "on": "mouseover", "nearest": true, "encodings": ["x"], toggle:false}}]; spec.encoding.color.condition = {"test": `datum.ray_angle_in==${clamped_ray_angle_in || 999}`,"value": "red"} spec.encoding.opacity.condition = {"test": `datum.ray_angle_in==${clamped_ray_angle_in || 999}`,"value": 1} //spec.encoding.color.condition = {"param": "ray_angle_in", "empty":false, "value": "yellow"} // condition opacity also? return spec }}), {actions, config: {background:'#f9f5f8'}})viewof labels = Inputs.toggle({label: "labels", value: false})```<details><summary>🗺️</summary>```{ojs}viewof observable_world_v = Inputs.checkbox(["overlay field of view"], {value: [/*"overlay field of view"*/]})observable_world = observable_world_v.lengthviewof level = embed( calcuvizspec({ models: [main], input_cursors: [{player_x_in:pos[0].value,player_y_in:pos[1].value,fov_in:fov,ray_angle_in: clamped_ray_angle_in/*:(fov[0]+fov[1])/2*/}], mark: {type:'rect',tooltip:false}, encodings: { x: {grid: false, name: 'level_x_in', type:'nominal', domain: _.range(0,63.1,1)}, y: {grid: false, name: 'level_y_in', type: 'nominal', domain: _.range(0,63.1,1)}, color: {name: (observable_world ? 'level_player_ray_fov' : 'level_player'), type: 'quantitative', legend:false}, //row: {name: 'formula', type:'nominal', domain: ['level', 'level_plus_player', 'level_plus_player_plus_ray']}, }, width: 300, height:300, spec_post_process: spec => { spec.params = [{"name": "xy", "select": { "type": "point", "on": "mouseover", "nearest": true, "encodings": ["x", "y"], toggle:false}}]; let a = spec.encoding.x.axis; spec.encoding.x.axis = {...a, ticks:false, labels:false} a = spec.encoding.y.axis; spec.encoding.y.axis = {...a, ticks:false, labels:false} spec.encoding.color.scale = {scheme: 'turbo'} return spec; }}), {actions})```</details><details><summary>options</summary>```{ojs}viewof ray_angle_in_step_size = Inputs.select([0.01,0.02,0.04,0.03], {value:0.02, label: 'ray_angle_in steps'})viewof time_in = Inputs.range([0,keys.length],{step:1,value:keys.length,label:'Time travel ✨'})viewof ray_angle_in = Inputs.input(0)//((fov[0]+fov[1]) / 2)//range([-4,4], {step:0.01, value:(fov[0]+fov[1]) / 2, label:'angle for active ray'})```</details>```{ojs}import { calcuvizspec, calcudata } from "@declann/little-calcu-helpers"embed = require('vega-embed');main = require('https://calcy-quarty-vizys-online.pages.dev/models/raycasting/raycasting.js')controls = require('https://calcy-quarty-vizys-online.pages.dev/models/raycasting/raycasting-playable.js')introspection_fetch = await fetch(`https://calcy-quarty-vizys-online.pages.dev/models/raycasting/raycasting.introspection.json`)introspection = introspection_fetch.json({typed:true})introspection_nomemo_fetch = await fetch(`https://calcy-quarty-vizys-online.pages.dev/models/raycasting/raycasting-nomemo.introspection.json`)introspection_nomemo = introspection_nomemo_fetch.json({typed:true})inputs = Object.values(introspection.cul_functions).filter(d => d.reason == 'input definition').map(d => d.name).sort()formulae = Object.values(introspection.cul_functions).filter(d => d.reason == 'definition').map(d => d.name)// formulae excluding pure inputsformulae_not_inputs = Object.values(introspection.cul_functions).filter(d => d.reason == 'definition' && inputs.indexOf(d.name+'_in') == -1).map(d => d.name)``````{ojs}//| echo: false// COORDINATED VIEWS// performance on hover would be far far better if I vega changeset & signal update on ray_angle changes// & only when != existing signal value (or no good); currently no time for this// first step would = detaching variable names// ray angle coordinationa = scene.addSignalListener("ray_angle_in", (_, r) => { if (observable_world == 0) return; viewof ray_angle_in.value = Math.round(r.ray_angle_in*100)/100; viewof ray_angle_in.dispatchEvent(new CustomEvent('input'), {bubbles:true}); // I might never understand how to make this always work})aa = { level.addSignalListener("xy", (_, r) => { // this didn't improve perf a lot vs event listener: nearly every mousemove is a signal change, I supposeconsole.log('hi') if (observable_world == 0) return; console.log(r) viewof ray_angle_in.value = Math.round(Math.atan2((r.level_y_in[0] - player_y_in) , (r.level_x_in[0] - player_x_in))*100)/100; viewof ray_angle_in.dispatchEvent(new CustomEvent('input'), {bubbles:true});})}```