Twine Version: 2.3.13
Story Format: 2.34.1
Hey all! first post here, and very green when it comes to all things Twine/code. I want to take this piece of javascript/CSS and have it be the background to a passage (JS/CSS copied below). I’ve put the CSS in my Story Stylesheet, the JS in my story Javascript, and the HTML content into the desired passage. Every time I try and play my story I get this error:
Error: [tw-user-script-0] bad evaluation: Cannot read properties of null (reading 'getContext')
I’m not sure what could be going wrong here as the script seems to run fine on the Codepen site.
Any help would be appreciated. Let me know if there’s anything else I can provide.
HTML:
<html>
<head />
<body>
<div id="container">
<div id="canvas">
<canvas id="maincanvas" width="200" height="200" />
</div>
<div id="panel">
<button id="startstop">Start/Stop</button>
<button id="reset">Reset</button>
<div>Frames: <div id="counter">0</div></div>
</div>
</div>
</body>
</html>
CSS
body
{
background-color: rgb(29,31,32);
color: white;
font-weight: normal;
font-family: arial;
font-size: 0.9em;
}
#container
{
margin: 0 auto;
width: 500px;
}
#canvas
{
width: 200px;
height: 200px;
background-color: rgb(32,34,35);
}
#panel
{
width: 180px;
margin-top: 10px;
}
button
{
color: white;
background-color: rgb(29,31,32);
border: 1px solid grey;
border-radius: 10px;
height: 20px;
min-width: 80px;
display: inline-block;
margin-bottom: 10px;
}
button:active
{
border: 1px solid white;
}
button:focus
{
outline: 0px;
}
#counter
{
display: inline-block;
}
Javascript:
// get canvas drawing context
var canvas = document.getElementById("maincanvas");
var context = canvas.getContext('2d');
// dimensions of simulation grid are taken from canvas
var dimX = canvas.offsetWidth;
var dimY = canvas.offsetHeight;
// get the pixel data from the canvas for faster rendering
var pixelData = context.getImageData(0, 0, dimX, dimY);
// variables to handle the start/stop/reset state of the simulation
var isRunning = false;
var theSim = null;
var currentCount = 0;
var dt = 40;
// function to perform an iteration of the algorithm, draw
// the results and schedule another iteration
var draw = function()
{
theSim.draw();
currentCount++;
$('#counter').html(currentCount);
if (isRunning) {
setTimeout(function() { draw(); }, dt);
}
};
var reset = function()
{
theSim.reset();
currentCount = 0;
};
// add button handlers
$('#startstop').click(function() {
if (!isRunning) {
isRunning = true;
draw();
}
else {
isRunning = false;
}
});
$('#reset').click(reset);
// main class for the simulation data and algorithm
var simulation = function()
{
var createArray = function()
{
var array = new Array(dimX);
for (var i = 0; i < dimX; i++)
{
array[i] = new Array(dimY);
}
return array;
};
// arrays for the values of A, B and C
var a = [createArray(), createArray()];
var b = [createArray(), createArray()];
var c = [createArray(), createArray()];
// the above arrays connsist of 2 buffers that are
// flipped over after each iteration - one buffer contains
// the input data to the algorithm and the other contains
// the output at the end of the iteration
var readBuffer = 0;
var writeBuffer = 1;
var resetOnNextDraw = false;
this.reset = function()
{
resetOnNextDraw = true;
};
var doReset = function()
{
for (var x = 0; x < dimX; x++)
{
for (var y = 0; y < dimY; y++)
{
a[readBuffer][x][y] = Math.random();
b[readBuffer][x][y] = Math.random();
c[readBuffer][x][y] = Math.random();
}
}
};
doReset();
// BIZARRE!!! If this empty loop is removed, performance decreases dramatically!!!
for (var asd = 0; asd < 0; asd++)
{
}
// function to perform 1 iteration of the algorithm and render the results to canvas
this.draw = function()
{
if (resetOnNextDraw)
{
doReset();
resetOnNextDraw = false;
}
var aRead = a[readBuffer];
var bRead = b[readBuffer];
var cRead = c[readBuffer];
var aWrite = a[writeBuffer];
var bWrite = b[writeBuffer];
var cWrite = c[writeBuffer];
var xPlus, xMinus, yPlus, yMinus;
var aVal, bVal, cVal;
var aValNew, bValNew, cValNew;
var pixelIndex, x, y;
var pixelArray = pixelData.data;
for (x = 0; x < dimX; x++)
{
xMinus = (x === 0) ? dimX - 1 : x - 1;
xPlus = (x === dimX - 1) ? 0 : x + 1;
var aReadxMinus = aRead[xMinus];
var bReadxMinus = bRead[xMinus];
var cReadxMinus = cRead[xMinus];
var aReadx = aRead[x];
var bReadx = bRead[x];
var cReadx = cRead[x];
var aReadxPlus = aRead[xPlus];
var bReadxPlus = bRead[xPlus];
var cReadxPlus = cRead[xPlus];
for (y = 0; y < dimY; y++)
{
yMinus = (y === 0) ? dimY - 1 : y - 1;
yPlus = (y === dimY - 1) ? 0 : y + 1;
aVal = aReadxMinus[yMinus]
+ aReadxMinus[y]
+ aReadxMinus[yPlus]
+ aReadx[yMinus]
+ aReadx[y]
+ aReadx[yPlus]
+ aReadxPlus[yMinus]
+ aReadxPlus[y]
+ aReadxPlus[yPlus];
bVal = bReadxMinus[yMinus]
+ bReadxMinus[y]
+ bReadxMinus[yPlus]
+ bReadx[yMinus]
+ bReadx[y]
+ bReadx[yPlus]
+ bReadxPlus[yMinus]
+ bReadxPlus[y]
+ bReadxPlus[yPlus];
cVal = cReadxMinus[yMinus]
+ cReadxMinus[y]
+ cReadxMinus[yPlus]
+ cReadx[yMinus]
+ cReadx[y]
+ cReadx[yPlus]
+ cReadxPlus[yMinus]
+ cReadxPlus[y]
+ cReadxPlus[yPlus];
aVal *= 0.111111111;
bVal *= 0.111111111;
cVal *= 0.111111111;
aValNew = aVal*(1.0 + bVal - cVal);
bValNew = bVal*(1.0 + cVal - aVal);
cValNew = cVal*(1.0 + aVal - bVal);
aValNew = Math.min(1.0, Math.max(aValNew, 0.0));
aWrite[x][y] = aValNew;
bWrite[x][y] = Math.min(1.0, Math.max(bValNew, 0.0));
cWrite[x][y] = Math.min(1.0, Math.max(cValNew, 0.0));
pixelIndex = (y * dimX + x) * 4;
var r1 = 32, g1 = 34, b1 = 35;
var r2 = 81, g2 = 226, b2 = 65;
pixelArray[pixelIndex] = r1 - Math.floor(aValNew * (r1 - r2));
pixelArray[pixelIndex + 1] = g1 - Math.floor(aValNew * (g1 - g2));
pixelArray[pixelIndex + 2] = b1 - Math.floor(aValNew * (b1 - b2));
pixelArray[pixelIndex + 3] = 255;
}
}
context.putImageData(pixelData, 0, 0);
if (readBuffer === 0)
{
readBuffer = 1;
writeBuffer = 0;
}
else
{
readBuffer = 0;
writeBuffer = 1;
}
};
};
theSim = new simulation();