Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const SVGLoaded = importScripts('https://cdnjs.cloudflare.com/ajax/libs/svg.js/3.1.2/svg.min.js');
- console.log(SVGLoaded);
- Macro.add('SymmetryGame', {
- tags: [],
- async handler() {
- const wrapper = document.createElement('div');
- this.output.appendChild(wrapper);
- await SVGLoaded;
- /* This function is executed when your game is finished */
- const gameFinished = (numUserDrawn, numLinesOnGrid) => {
- State.setVar('_numUserDrawn', numUserDrawn);
- State.setVar('_numLinesOnGrid', numLinesOnGrid);
- jQuery(wrapper).wiki(this.payload[0].contents);
- };
- /* this is a prototype for a game, in which users are asked to 'draw' symmetric figures:
- At the start a grid with the with of n (n being an odd number) is constructed. An axis is drawn by
- calculating the horizontal center of the grid. Two containers are generated: The 'original container' holds the dots on top of the horizontal axis, the 'userContainer' holds the dots below. At the beginning, a series of lines is being calculated, the number of lines equals gridSize-3, e.g. in a 5-grid, two lines are drawn, in a 7-grid four lines, etc.
- The user can draw lines by clicking on two dots (below the axis), if the drawn line is symmetrical to the original drawing above the axis, one of the progress bars switches from white to green. Unwanted lines can be removed by clicking on them.
- My goal is to use this as a macro in SugarCube to call it conveniently from within a passage. It should report whether a puzzle was solved and how many lines were drawn before it was solved.
- Also, in a future version, (and this might be of greater use for other twine creators), it would be great if one could pass a drawing to the macro, e.g.
- -x--x--x--x--x--
- --x-xx-xx-xx-x--
- ---xx-xx-xx-xx--
- ----x--x--x--x--
- ----------------
- from which the original drawing is being created. This could prove useful for may puzzles I recon.
- */
- //set up grid, declare vars
- let gridSize = parseInt(this.args[0] || 7);
- if (gridSize%2 ==0){
- gridSize--;
- }
- let originalLineCount=gridSize-2;
- let foundLines = 0;
- let foundPoints = 0;
- let middle = (Math.ceil(gridSize/2))-1;
- let gridDimension = 600;
- let padding = Math.floor(gridDimension/(gridSize+1));
- console.log("padding: " + padding);
- let dot = {};
- let userLines = {};
- let userLineCounter = 0;
- var draw = SVG().addTo(wrapper).size(gridDimension, gridDimension);
- let progressBars = {}
- let vertices = {};
- let activeDots = {};
- //colors
- let green= '#00854d';
- let darkPurple = '#524f6d';
- let yellow = '#ffb100';
- let activePink = '#bb44a3';
- //function drawLine + check: ok
- function drawLine(startPoint, endPoint, color, id) {
- let x1 = (startPoint[0]+1)*padding;
- let y1 = (startPoint[1]+1)*padding;
- let x2 = (endPoint[0]+1)*padding;
- let y2 = (endPoint[1]+1)*padding;
- userLines[id] = draw.line([[x1,y1],[x2,y2]]).stroke({width:4, color:color}).attr({'id':id}).back();
- console.log(userLines[id]);
- userLines[id].node.dataset.p1 = startPoint.join(',');
- userLines[id].node.dataset.p2 = endPoint.join(',');
- if(id.slice(0, 8)=="userline"){
- userLines[id].on('click', () => deleteLine(id));
- }
- }
- //draw axis
- function drawAxis(gridSize) {
- drawLine([-1,middle],[gridSize, middle], 'darkslategrey', "symmetryAxis");
- }
- drawAxis(gridSize);
- //calculate vertical symmetry
- function calcSymmetry(point){
- let x1 = point[0];
- let y1 = point[1];
- let symx1 = x1
- let symy1 = middle + (middle-y1);
- return([symx1, symy1]);
- }
- //start drawing when interactive dot is clicked
- function startDraw(x, y) {
- let id = x + "-" + y;
- console.log(x, y);
- if (!dot[id].isActive) {
- console.log("inactive");
- dot[id].fill(activePink).stroke('transparent').radius(7);
- dot[id].isActive = true;
- activeDots[id] = [x,y];
- } else {
- console.log("active");
- dot[id].fill(yellow).stroke(green).radius(5);
- dot[id].isActive = false;
- delete activeDots[id];
- }
- console.log("ActiveDots: ", activeDots);
- console.log("activeDots.length: " + Object.keys(activeDots).length);
- const lineDots = Object.entries(activeDots).map(([key, value]) => ({key, value}));
- if(lineDots.length==2){
- // If this line already exists, cancel
- if (Object.values(userLines).some((userLine) => {
- if (userLine.node.dataset.p1 === lineDots[0].value.join(',') && userLine.node.dataset.p2 === lineDots[1].value.join(',')) return true;
- if (userLine.node.dataset.p2 === lineDots[0].value.join(',') && userLine.node.dataset.p1 === lineDots[1].value.join(',')) return true;
- return false;
- })) {
- Object.keys(activeDots).forEach(key => delete activeDots[key]);
- return;
- }
- let pointA = lineDots[0].value;
- let pointB = lineDots[1].value;
- let lineIdentifier = "userline" + userLineCounter;
- drawLine(pointA, pointB, '#ccc', lineIdentifier);
- userLineCounter++;
- //active Dots inaktiv stellen
- for (const lineDot of lineDots) {
- dot[lineDot.key].isActive = false;
- dot[lineDot.key].fill('#fff').stroke('#000').radius(5);
- }
- //check for matches
- checkSymmetry(pointA, pointB, lineIdentifier);
- //erase activeDots
- Object.keys(activeDots).forEach(key => delete activeDots[key]);
- }
- }
- //helper function for deleting lines
- let retrieveLineCoordinates = function(line){
- let lineToFind = document.getElementById(line);
- let x1 = (lineToFind.getAttribute('x1')/padding-1);
- let y1 = (lineToFind.getAttribute('y1')/padding-1);
- let x2 = (lineToFind.getAttribute('x2')/padding-1);
- let y2 = (lineToFind.getAttribute('y2')/padding-1);
- console.log("x1: " + x1, "y1: " + y1, "x2: " + x2, "y2: " + y2 )
- return [[x1, y1], [x2, y2]];
- }
- //delete line if clicked on
- let deleteLine = function(id) {
- //look for vertices
- retrieveLineCoordinates(id);
- //get dots x and y, reset dots
- let startDotId = retrieveLineCoordinates(id)[0][0] + "-" + retrieveLineCoordinates(id)[0][1];
- let endDotId = retrieveLineCoordinates(id)[1][0] + "-" + retrieveLineCoordinates(id)[1][1];
- dot[startDotId].fill(yellow).stroke(green).radius(5);
- dot[startDotId].fill(yellow).stroke(green);
- dot[endDotId].fill(yellow).stroke(green).radius(5);
- //remove line
- userLines[id].remove();
- }
- //define original container
- let originalContainer = {};
- for (let i=0;i<gridSize; i++){
- for(let j=0; j<Math.floor(gridSize/2);j++){
- let id = i + "-" + j
- originalContainer[id]=([i,j]);
- console.log("originalContainer: " + Object.keys(originalContainer));
- console.log("originalContainer: " + Object.values(originalContainer));
- }
- }
- let drawDots = function(container, interactive, fillColor, strokeColor){
- console.log("arrayLength: " + Object.keys(container).length);
- let startPoint = Object.values(container)[0];
- console.log("startPointY: " + startPoint[1]);
- for (let i=0; i<gridSize; i++){
- for (let j=startPoint[1]; j<(startPoint[1]+Math.floor(gridSize/2)); j++){
- let id = i + "-" + j;
- dot[id] = draw.circle(10).attr({
- 'fill':fillColor,
- 'stroke':strokeColor,
- }).cx(i*padding+padding).cy(j*padding+padding)
- dot[id].isActive = false;
- if(interactive){
- dot[id].on('click', () => startDraw(i, j)),
- dot[id].isActive = false;
- }}
- }
- }
- drawDots(originalContainer, false, 'white', '#525f6d');
- let userContainer = {};
- for (let i=0;i<gridSize; i++){
- for(let j=Math.ceil(gridSize/2); j<gridSize;j++){
- let id = i + "-" + j
- userContainer[id]=([i,j]);
- console.log("userContainer: " + Object.keys(userContainer));
- console.log("userContainer: " + Object.values(userContainer));
- console.log("userContainer: " + userContainer);
- }
- }
- drawDots(userContainer, true, yellow, green);
- //generate original lines
- let createOriginalLines = function(lineCount) {
- //chose random points from original container
- for(let g=0; g<lineCount; g++){
- let values = Object.values(originalContainer);
- let randomPoint = values[Math.floor(Math.random() * values.length)];
- console.log("randomPoint: " + randomPoint);
- vertices[g] = randomPoint;
- let index = randomPoint[0] + "-" + randomPoint[1];
- console.log("index: " + index);}
- //rerun function if duplicates found
- if( hasDuplicates(Object.values(vertices)) ){
- console.log("duplicates found, recalculate!");
- console.log("vertices:" + Object.values(vertices));
- for (const key in vertices) {
- delete vertices[key];}
- console.log("vertices after erasing:" + Object.values(vertices));
- console.log("vertices.length after erasing" + Object.values(vertices).length);
- createOriginalLines(lineCount);
- }
- console.log("vertices new: " + Object.keys(vertices));
- for(let z=0; z<Object.keys(vertices).length; z++){
- let indix = Object.values(vertices)[z][0] + "-" + Object.values(vertices)[z][1]
- console.log("indix" + indix);
- dot[indix].fill(darkPurple);
- }
- // draw original lines
- console.log("verticeskeys" + Object.keys(vertices));
- console.log("verticesvalues" + Object.values(vertices));
- for(let n=0; n<originalLineCount; n++){
- if(n<(originalLineCount-1)){
- console.log("drawing line Nr: " + n + " from " + Object.values(vertices)[n][0] + "/" + Object.values(vertices)[n][1] + "to " + Object.values(vertices)[n+1][0] + "/" + Object.values(vertices)[n+1][1]);
- let id='original' + "-" + Object.values(vertices)[n][0] + "-" + Object.values(vertices)[n][1] + "-" + Object.values(vertices)[n+1][0] + "-" + Object.values(vertices)[n+1][1];
- console.log("line id = " + id);
- drawLine( Object.values(vertices)[n], Object.values(vertices)[n+1], darkPurple, id);}
- }
- }
- createOriginalLines(originalLineCount);
- let checkSymmetry = function(pointA, pointB, lineIdentifier){
- console.log("pointA: " + pointA);
- console.log("pointB: " + pointB);
- console.log("vertices" + Object.values(vertices));
- console.log(vertices);
- let symA = calcSymmetry(pointA);
- console.log("symA: " + symA);
- let symB = calcSymmetry(pointB);
- console.log("symA: " + symB);
- let lineForth="original-"+symA[0]+"-"+symA[1]+"-"+symB[0]+"-"+symB[1];
- console.log("lineForth: " + lineForth);
- let lineBack="original-"+symB[0]+"-"+symB[1]+"-"+symA[0]+"-"+symA[1];
- console.log("lineBack: " + lineBack);
- if(userLines[lineForth] || userLines[lineBack]){
- console.log("lineForth or lineBack exists!");
- userLines[lineIdentifier].stroke(green);
- userLines[lineIdentifier].off('click');
- let pointAId = pointA[0]+"-"+pointA[1];
- let pointBId = pointB[0]+"-"+pointB[1];
- dot[pointAId].fill(green).stroke(green);
- dot[pointBId].fill(green).stroke(green);
- foundLines++;
- updateProgressBar(foundLines);
- console.log("Line " + foundLines + " of " + (originalLineCount-1) + " found");
- foundPoints=0;
- if (foundLines == (originalLineCount-1)){
- console.log("finished!");
- gameFinished(userLineCounter, (originalLineCount-1));
- }
- }
- }
- function hasDuplicates(arr) {
- return arr.some(x => arr.indexOf(x) !== arr.lastIndexOf(x));
- }
- function drawProgressBar() {
- let barCount = originalLineCount-1;
- let barHeight = gridDimension/40;
- let padding = gridDimension/40;
- let barWidth = ((gridDimension-padding*(barCount+1))/barCount);
- let barContainer = draw.group().attr({id:"barContainer"});
- let barBackground = draw.rect(gridDimension, barHeight*4).attr({fill:'#fff'}).y(gridDimension*.94);
- barContainer.add(barBackground);
- for (let s=1; s<=barCount; s++){
- let id=s;
- progressBars[id] = draw.rect(barWidth, barHeight).attr({
- 'fill':'#fff',
- 'stroke':'#ccc',
- }).x((s-1)*barWidth+padding*s).y(gridDimension*.96)
- barContainer.add(progressBars[id]);
- }
- }
- drawProgressBar();
- function updateProgressBar(progress){
- progressBars[progress].fill(green);
- }
- console.log(vertices);
- }
- });
Advertisement
Add Comment
Please, Sign In to add comment