xxxxxxxxxx
1797
let audioThemes = ['none','space','cartoon','fantasy'];
let animationFunctionsNames =
[ "zoomSin","zoomOutIn","wiggle","upDown", "leftRight"];
let project;
let ON = 1,
CLICK = 2,
OFF = 3,
WIN = 1,
LOSE = 2;
let currentDetail;
let selected = null;
let selectedInRule = null; // before or after? -> 'left'/'right'
let selectedIndex = -1;
let currentWindow1 = null,
currentWindow2 = null;
let images = {};
let bkgds = [], bkgdsName=null;
let previewMode = true; // false;
let popupActive = false;
let justStarted;
let globalCloseButton = null; // used in the global keyPressed funct
let songs = [];
function preload() {
bkgds.push( loadImage('empty-room-background.jpg') );
bkgds.push( loadImage('room-topview.jpg') );
bkgds.push( loadImage('game_background.png') );
bkgds.push( loadImage('game_background2.jpg') );
bkgdsName = ['No Bkgr','Bkgr 1','Bkgr 2','Bkgr 3','Bkgr 4'];
songs.push( loadSound('audio1.mp3') ); // space
songs.push( loadSound('audio2.mp3') ); // cartoon
songs.push( loadSound('audio3.mp3') ); // fantasy
}
let stickerSelectionLastIndex = 0; // sticker A
let sNcLogo;
function setup() {
textSize(16);
sNcLogo = createImg('sNc_logo.jpg');
createCanvas(displayWidth*4/5,displayHeight*4/5);
currentDetail = -1; // layout
// initialize project
project = {
stickers: [],
markers: ['a','b','c'],
room: {
layout: [],
rules: []
},
needsRefresh: true,
backgroundId: -1,
backgroundMusicId: -1,
atlasInfo: [],
intro: 'A game made with Stick&Click',
name: 'newProject'
};
/*
project.stickers.push('A', 'B', 'C', 'D', 'E','F');
project.markers.push('a', 'b', 'c','d','e');*/
justStarted = true; // forces to show the splash screen
localStorage.removeItem('currentProject');
}
function doubleClicked(){
if (popupActive) return;
//console.log(' double click on the canvas, at ',mouseX,mouseY);
if (selected!=null){
//console.log(selected);
if (currentDetail == -1){
showPopupLayout();
} else {
if (selectedInRule=='left')
showPopupRuleLeft();
if (selectedInRule=='right')
showPopupRuleRight();
}
}
}
function draw() {
if (justStarted){
if (project.needsRefresh){
project.needsRefresh = false;
showSplashScreen();
}
}
if (project.needsRefresh) {
//console.log('draw()!' + currentDetail);
strokeWeight(1);
background(0);
// --- panels ----------------------------- start
// main panel
fill(220); stroke(0);
rect(0,0,width/2+width*11/48-1,height/2+height*2/12-1);
// rules panel
fill(200); stroke(0);
rect(width/2+width*11/48,0,width*13/48-1,height-1);
// bottom panel
text('Stickers Palette', width/2-60, height*4/12);
fill(240); stroke(0);
rect(0,height*4/6,width/2+width*11/48-1,height*2/6-1);
// --- panels ----------------------------- stop
textSize(18);
strokeWeight(1);
fill(50);
stroke(0);
text('-Stickers Palette-', width/4, height*8/12+height/48+5);
// bb.position(15+width * 0 / 24, height*8/12+height/48);
textSize(16);
if (currentDetail == -1) {
translate(width / 12, height / 12);
drawRoomLayout();
resetMatrix();
// label ------------------------------------------
textSize(18);
strokeWeight(1);
fill(50);
stroke(0);
text('-Layout-', width/8-60, height*1/12-10);
textSize(16);
currentWindow1 = [width / 12, height / 12,
width / 2, height / 2
];
currentWindow2 = null;
} else {
textSize(18);
fill(50);
strokeWeight(1);
stroke(0);
text('-Rule '+(currentDetail+1)+'-', width/8-60, height*1/12-10);
textSize(16);
//console.log('rule ' + currentDetail);
drawRule(currentDetail);
currentWindow1 = [width * 1 / 12 / 4, height / 12,
2 / 3 * width / 2, 2 / 3 * height / 2
];
currentWindow2 = [width * 1 / 3 + width * 1 / 12 / 2, height / 12,
2 / 3 * width / 2, 2 / 3 * height / 2
];
}
// draw buttons
removeElements();
let textInput = createInput(project.name);
textInput.input(_ => {
project.name = textInput.value();
return false;
});
textInput.position(width*2/24, 2);
textInput.style('color: darkgreen');
let btn;
btn = createButton('Load');
btn.mousePressed(_ => {
showPopupLoad();
});
btn.position(width*5/24, 2);
btn.style('color: darkgreen');
btn = createButton('Save');
btn.position(width*6/24, 2);
btn.style('color: darkgreen');
btn.mousePressed(_ => {
saveAtlas();
});
/*
btn = createButton('<u>▼</u>');
btn.position(width*7/24, 2);
btn.style('color: black');
btn.attribute('title','export to\nPaperToy');
btn.mousePressed(_ => {
showExportPopup();
});*/
btn = createButton('⯮');
btn.position(width*7/24, 2);
btn.style('color: black');
btn.attribute('title','run and the test\ncurrent game.');
btn.mousePressed(_ => {
showExportPopup();
});
btn = createButton('info');
btn.attribute('title','write a description for this game');
btn.position(width*8/24, 2);
btn.style('color: green');
btn.mousePressed(_ => {
showIntroPopup();
});
btn = createCheckbox('Prev', previewMode);
btn.position(width*9/24, 2);
btn.attribute('id','preview');
btn.style('color: darkgreen');
btn.changed(_ => {
//console.log('!', select('#preview').checked() );
previewMode = select('#preview').checked();
project.needsRefresh = true;
});
// draw right-side buttons
let d = createButton('Layout');
d.style('color: blue');
let dW = d.size().width;
let dHeight = height*2/15/2; //d.size().height + 5;
d.position(width * 9 / 12, 0 * dHeight + 5);
d.mousePressed(_ => f(-1));
d.attribute('id', 'btn' + 0);
project.room.rules.forEach((elem, index) => {
d = createButton('Rule ' + ++index);
d.position(width * 9 / 12, index * dHeight + 5);
d.style('color: blue');
d.mousePressed(_ => f(index - 1));
d.attribute('id', 'btn' + index);
drawRuleIconAt(index - 1, width * 10 / 12, index * dHeight);
});
// mark the selected button as "selected"
fill('#000000');
text('->', width * 9 / 12 - 16, (currentDetail + 1) * dHeight + 5 + 12);
let b = createButton('+');
b.attribute('title','new/copy of\nselected rule');
b.position(width * 21 / 24, 5);
b.mouseClicked(_ => {
// if rule selected, clone that one! otherwise create an "empty" one
selected = null; // no green rectangle!
addRule(currentDetail);
});
b = createButton('>');
b.attribute('title','next from\nselected rule');
b.position(width * 22/24-15, 5);
b.mouseClicked(_ => {
// the next rule has the same after-part than the selected
selected = null; // no green rectangle!
addNextRule(currentDetail);
});
b = createButton('-');
b.position(width * 23 / 24, 5);
b.mouseClicked(_ => {
removeRule();
});
if (currentDetail == -1) { // layout mode
// add (with selection), and remove a sticker in layout mode
let selection = createSelect();
selection.position(15+width*3/96, height*1/12);
selection.id('stickerSelection');
project.stickers.forEach(s=>{
selection.option(s);
});
project.markers.forEach(m=>{
selection.option(m);
});
selection
.child()[stickerSelectionLastIndex]
.setAttribute('selected','true');
selection.changed(_=>{
let v = selection.value();
let idx = project.stickers.indexOf(v);
if (idx==-1)
idx = project.markers.indexOf(v) + project.stickers.length;
stickerSelectionLastIndex = idx;
//console.log( v , stickerSelectionLastIndex);
});
let b = createButton('+');
b.attribute('title','add a sticker or placeholder\nto the layout');
b.position(15+width * 0 / 12, height*1/12);
b.mouseClicked(_ => {
addLayoutRect(selection.value());
});
b = createButton('-');
b.attribute('title','delete a sticker or placeholder\nfrom the layout');
b.id('remove-rect');
b.attribute('disabled','true');
b.position(15+width * 0 / 12, height*2/12);
b.mouseClicked(_ => {
removeSelected();
});
b = createButton('Edit');
b.position(15+width * 0 / 12, height*3/12);
b.id('edit-btn');
b.attribute('disabled','true');
b.mouseClicked(_ => {
showPopupLayout();
});
// background cycling button
let backgroundSelection = createSelect();
backgroundSelection.attribute('title','set the background image\nfor this game');
backgroundSelection.position(15+width * 0 / 12, height*4/12);
bkgdsName.forEach(bName=>{
backgroundSelection.option(bName);
});
backgroundSelection
.child()[project.backgroundId+1]
.setAttribute('selected','true');
backgroundSelection.changed(_=>{
selected = null; // no green rectangle!
let v = backgroundSelection.value();
let idx = bkgdsName.indexOf(v);
//DEGUB console.log( v , ' ' , idx);
if (project.backgroundId!=idx-1){
// user changed the selection of the background
project.backgroundId = idx-1;
project.needsRefresh = true;
}
//DEGUB console.log( project.backgroundId );
});
/*
b = createButton('');
let text = 'Bkgr ';
if (project.backgroundId==-1) text+='None';
else text += project.backgroundId;
b.html(text);
b.id('background-btn');
b.attribute('data-b',project.backgroundId);
b.position(15+width * 0 / 12, height*4/12);
b.mouseClicked(_ => {
// throttle this action, if too fast -> blocks the GUI :(
let btn = select('#background-btn');
let a = btn.attribute('data-b');
a++; if (a==bkgds.length) a=-1;
btn.attribute('data-b',a);
project.backgroundId = a;
//console.log( 'project.backgroundId', project.backgroundId);
project.needsRefresh = true;
}); */
// background cycling button for audio background theme
b = createButton('');
b.attribute('title','set the background music\nfor this game');
b.html( '♫ '+audioThemes[project.backgroundMusicId+1] );
b.id('backgroundMusicBtn');
b.attribute('data-m',project.backgroundMusicId);
b.position(15+width*0/12, height*5/12);
b.mouseClicked(_ => {
let btn = select('#backgroundMusicBtn');
let a = btn.attribute('data-m');
a++; if (a==audioThemes.length-1) a=-1;
btn.attribute('data-m',a);
project.backgroundMusicId = a;
// refresh button text
btn.html( '♫ '+audioThemes[project.backgroundMusicId+1] );
if (project.backgroundMusicId!=-1){
// audio preview...
// 1. stop all songs
songs.forEach((song,i)=>{
song.stop();
});
// 2. play current sound
songs[project.backgroundMusicId].play();
// 3. stop it after a bit...
setTimeout(_=>{
// stop all songs
songs.forEach((song,i)=>{
song.stop();
});
}, 3000);
}
// project.needsRefresh = true; // no need, just audio change
});
} else { // a rule is displayed
b = createButton(); // 'Nothing/Win/Lose'
let text = 'nothing';
if (project.room.rules[currentDetail][3]==WIN) text='WIN';
if (project.room.rules[currentDetail][3]==LOSE) text='LOSE';
b.html('and then... '+text);
b.style('background-color', 'red' );
b.style('color', 'white' );
b.position(width * 7/12, height*7/12);
b.mouseClicked(_ => {
switch (project.room.rules[currentDetail][3]){
case null: project.room.rules[currentDetail][3] = WIN; break;
case WIN: project.room.rules[currentDetail][3] = LOSE; break;
case LOSE: project.room.rules[currentDetail][3] = null; break;
}
project.needsRefresh = true;
});
if (selected != null) {
let b = createButton('Edit');
b.position(width * 0 / 12, 5);
b.mouseClicked(_ => {
if (selectedInRule=='left')
showPopupRuleLeft();
if (selectedInRule=='right')
showPopupRuleRight();
});
}
}
// generate stickers and placeholders
let bb = createButton('+');
bb.attribute('title','add sticker image\nto the palette');
bb.position(15+width * 0 / 24, height*8/12+height/48);
bb.style('background-color', 'blue' );
bb.style('color', 'white' );
bb.mouseClicked(_ => {
let letter = String.fromCharCode(64+project.stickers.length+1);
project.stickers.push(letter);
images[letter] = loadImage('boy face.png',
img=>{
project.needsRefresh = true;
}); // some default image
project.needsRefresh = true;
});
bb = createButton('-');
bb.attribute('title','delete sticker image\nfrom the palette');
bb.position(15+width * 1 / 24, height*8/12+height/48);
bb.style('background-color', 'blue' );
bb.style('color', 'white' );
bb.mouseClicked(_ => {
let l = String.fromCharCode(64+project.stickers.length);
let letter = prompt(`Which STICKER do you want to remove[A..${l}]?`,l);
if (letter!=null){
// remove the letter chosen by the user
project.stickers = project.stickers.filter( (elem,index)=> elem!=letter );
delete images[letter];
project.needsRefresh = true;
} else {
alert('No STICKER will be removed.');
}
});
const kx = 60;
const r = Math.min(width * 1 / 12, height * 1 / 12,kx);
project.stickers.forEach((elem, index) => {
if (images[elem]) {
image(images[elem], index * kx, height * 9 / 12,
r, r);
}
fill('#0000FF');
let btn = createButton(elem);
btn.attribute('title','click to upload a different image\nfor this sticker');
btn.position(15 + index * kx, height * 9 / 12);
btn.mousePressed(_=>{
selected = null;
project.needsRefresh = true;
console.log('!',index);
// fileInput -> change image
let fi = createFileInput(file=>{
if (file.type === 'image') {
} else {
alert('Error: please open an image.');
}
let img = createImg(file.data,_=>{
//console.log(' createImg -> ' , img, img.width, img.height);
let M = Math.max(img.width,img.height);
if (M>180){
const ratio = 180/M;
const w = ~~(img.width*ratio);
const h = ~~(img.height*ratio);
// resize img:
// 1. create hidden canvas, draw html IMG to canvas
let hiddenCanv = createGraphics(w,h); // not enough!!
hiddenCanv.attribute('width',w); // do this!!!
hiddenCanv.attribute('height',h); // do this too!!!
hiddenCanv.image(img,0,0,w,h);
// 2. create an offscreen IMG, draw the hidden canvas onto it
let graphics = createGraphics(w,h);
graphics.image(hiddenCanv, 0, 0);
// 3. pretend the original img is not the offscreen IMG ;)
img = graphics;
}
images[elem] = img;
project.needsRefresh = true;
});
img.hide();
});
fi.elt.click();
});
});
// placeholders
bb = createButton('+');
bb.attribute('title','add placeholder\nfrom the palette');
bb.position(15+width * 0 / 24, height*10/12+height/48);
bb.style('background-color', 'navy' );
bb.style('color', 'white' );
bb.mouseClicked(_ => {
let letter = String.fromCharCode(97+project.markers.length+1);
project.markers.push(letter);
project.needsRefresh = true;
});
bb = createButton('-');
bb.attribute('title','delete placeholder\nfrom the palette');
bb.position(15+width * 1 / 24, height*10/12+height/48);
bb.style('background-color', 'navy' );
bb.style('color', 'white' );
bb.mouseClicked(_ => {
let l = String.fromCharCode(97+project.markers.length);
let letter = prompt(`Which PLACEHOLDER do you want to remove[a..${l}]?`,l);
if (letter!=null){
// remove the letter chosen by the user
project.markers = project.markers.filter( (elem,index)=> elem!=letter );
delete project.markers[letter];
project.needsRefresh = true;
} else {
alert('No PLACEHOLDER will be removed.');
}
});
project.markers.forEach((elem, index) => {
fill('#0000FF');
text(elem, 15 + index * kx/2, height * 11 / 12);
});
project.needsRefresh = false;
}
if (selected != null) {
let btn = select('#remove-rect');
if(btn) btn.removeAttribute('disabled');
btn = select('#edit-btn');
if(btn) btn.removeAttribute('disabled');
noFill();
stroke('#00FF00');
strokeWeight(3);
rect(selected[0], selected[1], selected[2], selected[3]);
//console.log( 'selected: ' + selected[4] , selectedIndex );
if(dragging){
noFill();
stroke('#00FF00');
strokeWeight(3);
circle(mouseX,mouseY,3,3);
//project.needsRefresh = true; // force redraw
}
}
}
let dragging = false;
let draggingInitPos = null;
function mousePressed() {
if (popupActive) return;
draggingInitPos = [mouseX,mouseY];
let oldSelected= selected;
if (currentDetail == -1) {
let wind = currentWindow1;
if (isInside(mouseX, mouseY, wind)) {
let clickedRects = project.room.layout.filter((r) => {
return isInside(mouseX - wind[0], mouseY - wind[1], r);
});
selected = null;
selectedInRule = null;
selectedIndex = -1;
if (clickedRects.length) {
let [a, b, c, d, id] = clickedRects[0];
selected = [a + wind[0], b + wind[1], c, d, id];
selectedIndex = project.room.layout.indexOf(clickedRects[0]);
}
}
} else { // it's a rule!
let wind = currentWindow1; // check left-part of rule
let found = false;
if (isInside(mouseX, mouseY, wind)) {
//console.log('rule-left');
selectedInRule = 'left';
selected = null;
selectedIndex = -1;
let clickedRects = project.room.layout.filter((r) => {
let [a, b, c, d] = r;
a = a * 2 / 3;
b = b * 2 / 3;
c = c * 2 / 3;
d = d * 2 / 3;
r = [a, b, c, d];
return isInside(mouseX - wind[0],
mouseY - wind[1], r);
});
if (clickedRects.length) {
let [a, b, c, d, id] = clickedRects[0];
a = a * 2 / 3;
b = b * 2 / 3;
c = c * 2 / 3;
d = d * 2 / 3;
selected = [a + wind[0], b + wind[1], c, d, id];
selectedIndex = project.room.layout.indexOf(clickedRects[0]);
found = true;
}
}
if (!found) { // check right-part of rule
let wind = currentWindow2;
if (isInside(mouseX, mouseY, wind)) {
//console.log('rule-right');
selectedInRule = 'right';
selected = null;
selectedIndex = -1;
let clickedRects = project.room.layout.filter((r) => {
let [a, b, c, d] = r;
a = a * 2 / 3;
b = b * 2 / 3;
c = c * 2 / 3;
d = d * 2 / 3;
r = [a, b, c, d];
return isInside(mouseX - wind[0],
mouseY - wind[1], r);
});
if (clickedRects.length) {
let [a, b, c, d, id] = clickedRects[0];
a = a * 2 / 3;
b = b * 2 / 3;
c = c * 2 / 3;
d = d * 2 / 3;
selected = [a + wind[0], b + wind[1], c, d, id];
selectedIndex = project.room.layout.indexOf(clickedRects[0]);
}
}
}
}
if (oldSelected != selected)
project.needsRefresh = true;
}
function mouseDragged() {
if (popupActive) return;
if (currentDetail == -1){ // can only drag if layout is detailed!
if (selected!=null){
if (!dragging){
//console.log('startedDragging');
}
//console.log('Dragging layout rect #',selectedIndex);
if ((!dragging)&&(dist(draggingInitPos[0],draggingInitPos[1],
mouseX,mouseY)>5))
dragging = true;
}
}
return false;
}
function mouseReleased() {
if (popupActive) return;
if (currentDetail == -1){ // can only drag if layout is detailed!
if (dragging){
//console.log('dragging ended');
let [a,b,c,d,e] = project.room.layout[selectedIndex];
a-=(draggingInitPos[0]-mouseX);
b-=(draggingInitPos[1]-mouseY);
project.room.layout[selectedIndex] = [a,b,c,d,e];
selected = [a+ currentWindow1[0],b+ currentWindow1[1],c,d,e];
project.needsRefresh = true;
}
}
dragging = false;
}
function isInside(x, y, rectangle) {
if (rectangle==null) return false;
let [rx, ry, rw, rh] = rectangle;
return (x >= rx) && (x <= rx + rw) &&
(y >= ry) && (y <= ry + rh);
}
// a rule button has been clicked
function f(id) {
currentDetail = id;
selected = null;
selectedIndex = -1;
project.needsRefresh = true;
}
function drawRoomLayout(mask, type, letters) {
fill('#F0F0F0');
stroke('#000000');
rect(0, 0, width / 2, height / 2);
if (project.backgroundId!=-1)
image(bkgds[project.backgroundId],
0,0,
width / 2, height / 2);
project.room.layout.forEach((elem, index) => {
let [x, y, w, h, id] = elem;
let name = id;
if (letters) name = letters[index];
//console.log('name:',name);
if ((!mask) || (mask[index] == ON) || (mask[index] == CLICK)) {
if (images[name]){
fill('#A0A0A0');
stroke('#000000');
rect(x, y, w, h);
fill('#000000');
noStroke();
text(name, x + w * 1 / 3, y + h * 2 / 3);
} else { // name is one of the PlaceHolders
fill('#FFFFFF');
noStroke();
const k = 3;
rect(x - k, y - k, w + k * 2, h + k * 2);
strokeWeight(k);
stroke('red');
line(x,y,x+w,y+h);
strokeWeight(1);
fill('#000000');
noStroke();
text(name, x + w * 1 / 3, y + h * 2 / 3);
}
if ((type == 'before') &&
((mask) && (mask[index] == CLICK))) {
//console.log('clicked!');
noFill();
stroke('#00F');
const k = 3;
strokeWeight(k);
rect(x - k, y - k, w + k * 2, h + k * 2);
strokeWeight(1);
}
} else if (mask[index] == OFF) {
fill('#F0D0D0');
noStroke();
rect(x, y, w, h);
}
if (previewMode){
if (images[name])
image(images[name],x, y, w, h);
else if ((mask)&&(mask[index] != OFF)){
fill('#FFFFFF');
noStroke();
const k = 3;
rect(x - k, y - k, w + k * 2, h + k * 2);
strokeWeight(k);
stroke('red');
line(x,y,x+w,y+h);
strokeWeight(1);
fill('#000000');
noStroke();
text(name, x + w * 1 / 3, y + h * 2 / 3);
}
}
});
}
function drawRule(index) {
let [mask, before, after] = project.room.rules[index];
translate(width * 1 / 12 / 4, height / 12);
scale(2 / 3, 2 / 3);
drawRoomLayout(mask, 'before', before);
resetMatrix();
translate(width * 1 / 3 + width * 1 / 12 / 2, height / 12);
scale(2 / 3, 2 / 3);
drawRoomLayout(mask, 'after', after);
resetMatrix();
}
// size: 1/5*(2/3) both -> 2/15
function drawRuleIconAt(index, px, py) {
const sk = 1 / 5;
let [mask, before, after] = project.room.rules[index];
translate(px, py);
scale(sk, sk);
translate(width * 1 / 12 / 4, height / 12);
scale(2 / 3, 2 / 3);
drawRoomLayout(mask, 'before', before);
resetMatrix();
translate(px, py);
scale(sk, sk);
translate(width * 1 / 3 + width * 1 / 12 / 2, height / 12);
scale(2 / 3, 2 / 3);
drawRoomLayout(mask, 'after', after);
resetMatrix();
}
// ruleIndex is -1 if we are in layout-mode,
// otherwise it is in [0..length of rules-1]
function addRule(ruleIndex) {
//console.log( 'ruleIndex' , ruleIndex );
if (ruleIndex==-1){ // no rule selected, layout-mode
let a = new Array(project.room.layout.length);
project.room.rules.push([a.slice().fill(OFF), // mask
a.slice().fill(null), // before
a.slice().fill(null), // after
null,
a.slice().fill(null), // animations
]); // WIN/LOSE
} else { // rule _ruleIndex_ selected -> clone the current rule!
let a = JSON.parse(
JSON.stringify(
project.room.rules[ruleIndex]
)
);
project.room.rules.push(a);
}
// put new rule in focus
currentDetail = project.room.rules.length-1;
project.needsRefresh = true;
}
// Create the "next rule" of the selected one
// the next rule has the same after-part than the selected
function addNextRule(ruleIndex){
// if in layout-mode...
if (ruleIndex==-1){
// OLD:
addRule(ruleIndex);
/*
// *** TO DO copy the state of the layout instead ***
let a = new Array(project.room.layout.length);
let layoutClone1 = project.room.layouta.slice(); // cloned
layoutClone1 = layoutClone1.map( e=>e[4] );
let layoutClone2 = layoutClone1.slice(); // cloned
// create an "identity" rule, based on layout
project.room.rules.push([
a.fill(ON), // mask -> all ON
layoutClone1, // before
layoutClone2, // after , same as the before
null , // WIN/LOSE -> not specified, so nothing
a.fill(null) // no animations
]);
// put new rule in focus
currentDetail = project.room.rules.length-1;
project.needsRefresh = true;
*/
} else {
//console.log( 'addNextRule -> ', ruleIndex );
let clonedRule = JSON.parse(
JSON.stringify(
project.room.rules[ruleIndex]
)
);
let newBefore = JSON.parse(JSON.stringify( clonedRule[2] ));
let newAfter = JSON.parse(JSON.stringify( clonedRule[2] ));
let a = new Array(project.room.layout.length);
project.room.rules.push([
clonedRule[0], // mask
newBefore, // before
newAfter, // after
clonedRule[3], // WIN/LOSE
clonedRule[4] // same animations
]);
// put new rule in focus
currentDetail = project.room.rules.length-1;
project.needsRefresh = true;
}
}
function removeRule() {
let currentRuleId = currentDetail;
const l = project.room.rules.length;
if (currentDetail==-1) currentRuleId = l-1;
if (l>0){
let i = prompt(`Which rule do you want to remove[1..${l}]?`,
currentRuleId+1);
if (i!=null){
i--;
project.room.rules.splice(i,1);
currentDetail=-1; // back to layout
project.needsRefresh = true;
}
} else {
alert('No rules to remove.');
}
}
let addLayoutRectX = 0; // auto-placement left-to-right
let addLayoutRectY = 0;
function addLayoutRect(selectionLetter) {
//console.log( 'adding:',selectionLetter );
let im = images[selectionLetter];
if (addLayoutRectX > (width/2-width*1/12)){
addLayoutRectX = ~~random(10);
addLayoutRectY+=100;
}
if (addLayoutRectY > (height*2/3-height*1/4)){
addLayoutRectY = ~~random(10);
}
if (im!=null) { // when the letter is a sticker
project.room.layout.push([addLayoutRectX+10, addLayoutRectY+10,
im.width, im.height,
selectionLetter]);
} else { // marker
project.room.layout.push([addLayoutRectX+10, addLayoutRectY+10,
40,40,
selectionLetter]);
}
addLayoutRectX+=100;
// propagate to all existing rules
project.room.rules.map( (rule)=>{
let [mask,before,after] = rule;
mask .push(OFF);
before.push( null );
after .push( null );
return [mask,before,after];
});
selected = null;
project.needsRefresh = true;
}
function removeSelected(){
project.room.layout.splice(selectedIndex,1);
// propagate REMOVE from all existing rules
project.room.rules.map( (rule)=>{
let [mask,before,after] = rule;
mask .splice(selectedIndex,1);
before.splice(selectedIndex,1);
after .splice(selectedIndex,1);
return [mask,before,after];
});
selected = null;
project.needsRefresh = true;
}
// modal popup generators ***************** start
function showPopupLayout(){
popupActive = true;
let transp = createDiv();
transp.style('background-color', color(255,255,255,150));
transp.size(width,height);
transp.position(0,0);
let d = createDiv('<b>--------- Edit Layout ---------</b><br>');
d.style('background-color', '#A0A0D0');
d.size(width*3/4,height*3/4);
d.position(width*1/8,height*1/8);
// ****** Sticker
let elem = project.room.layout[selectedIndex];
let rectangle = createDiv();
rectangle.style('background-color', '#909090');
rectangle.id('rectangle-div');
rectangle.position(width*2/4-5,
height*3/16+5);
rectangle.size(elem[2],elem[3]);
let inp;
let plus,minus,half,double;
d.child( createSpan( 'W ' ));
d.child( inp=createInput(elem[2]) );
inp.id('inp1');
d.child( createSpan(' ') );
d.child( plus=createButton(' + ') );
d.child( createSpan(' ') );
d.child( minus=createButton(' - ') );
// for both dimensions
d.child( createSpan('         ') );
d.child( half=createButton(' 1/2 ') );
d.child( createSpan(' ') );
d.child( double=createButton(' x2 ') );
d.child( createSpan('<br><br>') );
plus.mouseClicked(_=>{
let e = select('#inp1');
e.value( ~~e.value()+5 );
elem[2] = ~~e.value();
rectangle.size(elem[2],elem[3]);
});
minus.mouseClicked(_=>{
let e = select('#inp1');
e.value( ~~e.value()-5 );
elem[2] = ~~e.value();
rectangle.size(elem[2],elem[3]);
});
half.mouseClicked(_=>{
let e1 = select('#inp1');
let e2 = select('#inp2');
e1.value( ~~e1.value()/2 );
elem[2] = ~~e1.value();
e2.value( ~~e2.value()/2 );
elem[3] = ~~e2.value();
rectangle.size(elem[2],elem[3]);
});
double.mouseClicked(_=>{
let e1 = select('#inp1');
let e2 = select('#inp2');
e1.value( ~~e1.value()*2 );
elem[2] = ~~e1.value();
e2.value( ~~e2.value()*2 );
elem[3] = ~~e2.value();
rectangle.size(elem[2],elem[3]);
});
d.child( createSpan( 'H ' ));
d.child( inp=createInput(elem[3]) );
inp.id('inp2');
d.child( createSpan(' ') );
d.child( plus=createButton(' + ') );
d.child( createSpan(' ') );
d.child( minus=createButton(' - ') );
d.child( createSpan('<br><br>') );
d.child( createSpan('<br><br>') );
plus.mouseClicked(_=>{
let e = select('#inp2');
e.value( ~~e.value()+5 );
elem[3] = ~~e.value();
rectangle.size(elem[2],elem[3]);
});
minus.mouseClicked(_=>{
let e = select('#inp2');
e.value( ~~e.value()-5 );
elem[3] = ~~e.value();
rectangle.size(elem[2],elem[3]);
});
// stickers and markers
d.child( createSpan('Sticker ') );
d.child( inp = createSelect() );
inp.id('inp3');
let currentIndex = -1;
let index = 0;
project.stickers.forEach(s=>{
inp.option(s);
if (s==elem[4]) currentIndex = index;
index++;
});
project.markers.forEach(m=>{
inp.option(m);
if (m==elem[4]) currentIndex = index;
index++;
});
// -> currently selected:
if (currentIndex==-1) throw 'IMPOSSIBLE!';
inp.child()[ currentIndex ].setAttribute('selected','true');
//console.log( inp.child() );
// ******
let b=createButton('(X)'); // close button
globalCloseButton = b;
b.position(width*3/4+width*1/8-b.size().width-5,height*1/8+5);
b.mouseClicked(_ => {
rectangle.hide();
ok.hide();
b.hide();
d.hide();
transp.hide();
popupActive = false;
});
let ok=createButton(' OK '); // submit button
ok.position(width*2/4-ok.size().width-5,
height*3/4+ok.size().height-5);
ok.mouseClicked(_ => {
// save data to model
let A = ~~select('#inp1').value();
let B = ~~select('#inp2').value();
let C = select('#inp3').value();
//console.log(A,B,C );
project.room.layout[selectedIndex][2] = A;
project.room.layout[selectedIndex][3] = B;
project.room.layout[selectedIndex][4] = C;
// if the image is too much up or left, fix it!
let x = project.room.layout[selectedIndex][0];
let y = project.room.layout[selectedIndex][1];
x = Math.max(0,x);
y = Math.max(0,y);
project.room.layout[selectedIndex][0] = x;
project.room.layout[selectedIndex][1] = y;
// then close
rectangle.hide();
ok.hide();
b.hide();
d.hide();
transp.hide();
popupActive = false;
selected = null;
project.needsRefresh = true;
});
}
function showPopupRuleLeft(){
popupActive = true;
let transp = createDiv();
transp.style('background-color', color(255,255,255,150));
transp.size(width,height);
transp.position(0,0);
let d = createDiv('<b>--------- Edit Rule (before) ---------</b><br>');
d.style('background-color', '#A0D0A0');
d.size(width*3/4,height*3/4);
d.position(width*1/8,height*1/8);
// ****** properties
const state = project.room.rules[currentDetail][0][selectedIndex];
let letter = project.room.rules[currentDetail][1][selectedIndex];
let used = true;
let clickTarget = false;
if (state==ON) used = true;
if (state==OFF) used = false;
if (state==CLICK) clickTarget = true;
///console.log(state,used,clickTarget,letter);
let inp;
d.child( inp=createCheckbox( 'in use (or not in use).\n This sticker counts for this rule (or it does not count).', true ) );
d.child( createSpan('<br>') );
inp.attribute('id','inp1');
let f = _=> {
if (!select('#inp1').checked()){
select('#inp2').checked(false);
select('#inp2').attribute('disabled','true');
select('#inp3').attribute('disabled','true');
select('#inp3').value(null);
} else {
select('#inp2').removeAttribute('disabled');
select('#inp3').removeAttribute('disabled');
//select('#inp3').value(letter);
}
}
d.changed(f);
d.child( inp=createCheckbox( 'activates when clicked (or not).\n This sticker activates this rule, when it is clicked on (or it does not).', clickTarget ) );
d.child( createSpan('<br>') );
inp.attribute('id','inp2');
// stickers and markers
d.child( createSpan('Sticker ') );
d.child( inp = createSelect() );
/*
inp.changed(_=>{
ok.removeAttribute('disabled');
});*/
inp.id('inp3');
let currentIndex = -1;
let index = 0;
project.stickers.forEach(s=>{
inp.option(s);
if (s==letter) currentIndex = index;
index++;
});
project.markers.forEach(m=>{
inp.option(m);
if (m==letter) currentIndex = index;
index++;
});
// -> currently selected:
if (currentIndex==-1){
select('#inp3').value(null); // no selection
} else
inp.child()[ currentIndex ].setAttribute('selected','true');
d.child( createSpan(' or transparent Placeholder (like a,b,c ...)') );
f();// to disable some of the fields depending on state
// ******
let b=createButton('(X)'); // close button
globalCloseButton = b;
b.position(width*3/4+width*1/8-b.size().width-5,height*1/8+5);
b.mouseClicked(_ => {
ok.hide();
b.hide();
d.hide();
transp.hide();
popupActive = false;
project.needsRefresh = true;
});
let ok=createButton(' OK '); // submit button
//ok.attribute('disabled',true);
ok.position(width*2/4-ok.size().width-5,
height*3/4+ok.size().height-5);
ok.mouseClicked(_ => {
// save data to model
let A = select('#inp1').checked();
let B = select('#inp2').checked();
let C = select('#inp3').value();
if (C=='') C=null;
//console.log('A,B,C:',A,B,C);
// decide+set state and stickerId for the left-hand of the rule
let state;
if (A==true) state=ON;
if (A==false) state=OFF;
if ((A==true)&&(B==true)) state=CLICK;
//console.log('state',state);
//console.log( selected,selectedIndex );
if (state==CLICK)
removeClickedFromRule(project.room.rules[currentDetail]);
project.room.rules[currentDetail][0][selectedIndex] = state;
project.room.rules[currentDetail][1][selectedIndex] = C;
project.room.rules[currentDetail][2][selectedIndex] = C;
// then close
ok.hide();
b.hide();
d.hide();
transp.hide();
popupActive = false;
project.needsRefresh = true;
});
}
// BEFORE-part of a rule
function showPopupRuleRight(){
popupActive = true;
let transp = createDiv();
transp.style('background-color', color(255,255,255,150));
transp.size(width,height);
transp.position(0,0);
let d = createDiv('<b>--------- Edit Rule (after) ---------</b><br>');
d.style('background-color', '#80B080');
d.size(width*3/4,height*3/4);
d.position(width*1/8,height*1/8);
// ****** properties
if (project.room.rules[currentDetail][0][selectedIndex]!=OFF){
const letter = project.room.rules[currentDetail][2][selectedIndex];
d.child( createSpan('Sticker ') );
d.child( inp = createSelect() );
inp.id('inp3');
let currentIndex = -1;
let index = 0;
project.stickers.forEach(s=>{
inp.option(s);
if (s==letter) currentIndex = index;
index++;
});
project.markers.forEach(m=>{
inp.option(m);
if (m==letter) currentIndex = index;
index++;
});
// -> currently selected:
if (currentIndex==-1)
inp.child()[ 0 ].setAttribute('selected','true'); //throw 'IMPOSSIBLE!';
else
inp.child()[ currentIndex ].setAttribute('selected','true');
/*
console.log( 'L->',letter );
console.log( currentIndex );
*/
let animationName = project.room.rules[currentDetail][4][selectedIndex];
let animationIndex = animationFunctionsNames.indexOf(animationName);
d.child( createSpan('<br>') );
d.child( createSpan('<br>') );
d.child( createSpan('Animation ') );
d.child( inp = createSelect() );
inp.id('inp1');
inp.option( '-noAnimation-' );
animationFunctionsNames.forEach((name,index)=>{
inp.option( name );
});
console.log( 'animationIndex' , animationIndex);
if (animationIndex==-1)
inp.child()[ 0 ].setAttribute('selected','true');// default
else
inp.child()[ animationIndex+1 ].setAttribute('selected','true');
} else {
d.child( createSpan( 'Please make this place "used" first.' ));
}
// ******
let b=createButton('(X)'); // close button
globalCloseButton = b;
b.position(width*3/4+width*1/8-b.size().width-5,height*1/8+5);
b.mouseClicked(_ => {
ok.hide();
b.hide();
d.hide();
transp.hide();
popupActive = false;
project.needsRefresh = true;
});
let ok=createButton(' OK '); // submit button
ok.position(width*2/4-ok.size().width-5,
height*3/4+ok.size().height-5);
ok.mouseClicked(_ => {
// save data to model
if (project.room.rules[currentDetail][0][selectedIndex]!=OFF){
let C = select('#inp3').value();
if (C=='') C=null;
if (C!=null){
project.room.rules[currentDetail][2][selectedIndex] = C;
let animationName = select('#inp1').value();
if (animationName==="-noAnimation-")
animationName = null;
project.room.rules[currentDetail][4][selectedIndex] = animationName;
console.log( animationName );
}
}
// then close
ok.hide();
b.hide();
d.hide();
transp.hide();
popupActive = false;
project.needsRefresh = true;
});
}
// modal popup generators ***************** stop
// modal popup save Atlas ***************** start
function saveAtlas(){
//console.log('Size:', width, height);
let projectName = project.name; //'sNc-project';
let n = prompt('Saving... project name:',projectName);
if (n==null) // the prompt popup was closed by the user
return;
if ((n!=null)&&(n!=''))
projectName = n;
project.name = projectName;
// 1 create the atlas image
let maxW = -1;
let imageOffsetY = 0;
Object.values(images).forEach(img=>{
//console.log( img );
if(img.width>maxW) maxW=img.width;
imageOffsetY += img.height;
});
pg = createGraphics(maxW,imageOffsetY); // not enough!!
pg.attribute('width',maxW); // do this too!!!
pg.attribute('height',imageOffsetY); // do this too!!!
//DEGUB console.log('pg = ' , maxW,imageOffsetY);
//DEGUB console.log('pg = ' , pg);
// 2 copy all images to the atlas image
// ... insert atlas data in the project object
imageOffsetY = 0;
project.atlasInfo = []; // reset the atlas, just in case of multiple saves!
Object.values(images).forEach((info,index)=>{
//console.log( info );
project.atlasInfo.push([imageOffsetY,info.width,info.height]);
pg.image(info,
0,imageOffsetY,
info.width,info.height);
imageOffsetY += info.height;
});
// 3 save
pg.save(projectName+'_atlas.png');
// make all measures relative (one-thousand-ds) to the width and height
// must multiply by 2 because layout is 1/2 screen size
let clonedProject = JSON.parse(JSON.stringify(project));
clonedProject.room.layout = clonedProject.room.layout.map(elem=>{
//console.log( elem );
let [A,B,C,D,E] = elem;
A = ~~(A*1000/width*2);
B = ~~(B*1000/height*2);
C = ~~(C*1000/width*2);
D = ~~(D*1000/height*2);
return [A,B,C,D,E];
});
createStringDict(clonedProject).saveJSON(projectName+'_data.json');
}
let atlasData;
function showPopupLoad() {
localStorage.removeItem('currentProject');
popupActive = true;
let transp = createDiv();
transp.style('background-color', color(255, 255, 255, 150));
transp.size(width, height);
transp.position(0, 0);
atlasData = {
bothLoaded: 0,
atlasInfo: null,
atlas: null,
images: []
};
let d = createDiv('<b>--------- Load Stick-N-Click project ---------</b><br><br><br><br><br><br><br><br>');
d.style('background-color', '#AFAFFF'); // F000F0
d.style('border', '5px solid black');
d.size(width*3/4,height*3/4);
d.position(width * 1 / 8, height * 1 / 8);
d.child( sNcLogo );
sNcLogo.size(width*4/16,height*4/16);
sNcLogo.position(width*15/32,height*2/16);
// ****** properties
d.child(createSpan('Select an atlas image (*_atlas.png):'));
d.child(fileSelect1 = createFileInput(gotFile1)); // project1_atlas.png
fileSelect1.style('background-color', 'green');
fileSelect1.style('color', 'white');
fileSelect1.style('font-size', '120%');
d.child(createSpan('<br><br><br><br>Select a *_data.json file:'));
d.child(fileSelect2 = createFileInput(gotFile2)); // project1_data.json
fileSelect2.style('background-color', 'green');
fileSelect2.style('color', 'white');
fileSelect2.style('font-size', '120%');
// ******
let b = createButton('(X)'); // close button
globalCloseButton = b;
b.position(width * 3 / 4 + width * 1 / 8 - b.size().width - 5, height * 1 / 8 + 5);
b.mouseClicked(_ => {
ok.hide();
b.hide();
d.hide();
transp.hide();
popupActive = false;
});
let ok = createButton(' OK '); // submit button
ok.position(width*3/8-ok.width/2,height*3/4);
ok.size(width*1/4,height*1/12);
ok.style('background-color', 'green');
ok.style('color', 'white');
ok.style('font-size', '150%');
ok.mouseClicked(_ => {
// load atlas and data, get the images
if (atlasData.bothLoaded == 2) {
let graphics = createGraphics(atlasData.atlas.width, atlasData.atlas.height);
graphics.image(atlasData.atlas, 0, 0);
atlasData.images = [];
atlasData.atlasInfo.forEach((e, i) => {
atlasData.images.push(graphics.get(0, e[0],e[1],e[2]));
});
// replace the stickers A,B,... with the loaded images
atlasData.images.forEach((img, i) => {
let letter = project.stickers[i];
images[letter] = img;
});
// make all measures relative to the current width and height
// must multiply by 2 because layout is 1/2 screen size
project.room.layout = project.room.layout.map(elem=>{
//console.log( elem );
let [A,B,C,D,E] = elem;
A = (A/1000*width/2);
B = (B/1000*height/2);
C = (C/1000*width/2);
D = (D/1000*height/2);
return [A,B,C,D,E];
});
stickerSelectionLastIndex = 0;
}
// then close
ok.hide();
b.hide();
d.hide();
transp.hide();
popupActive = false;
project.needsRefresh = true;
});
}
// atlas
function gotFile1(file) {
if (file.type === 'image') {
console.log('loaded: ' + file.name + ' ' + file.type + ' ' + file.size + ' bytes');
let img = createImg(file.data, _ => {
atlasData.atlas = img;
});
img.hide();
atlasData.bothLoaded++;
} else {
alert('select a *_atlas.png image file please!');
}
}
// atlas info
function gotFile2(file) {
if (file.type === 'application') {
console.log('loaded: ' + file.name + ' ' + file.type + ' ' + file.size + ' bytes');
//console.log( file.data.substr(29) );
//console.log( window.atob( file.data.substr(29) ) );
project = JSON.parse(window.atob(file.data.substr(29)));
//console.log(project);
atlasData.bothLoaded++;
projectInitialLayout =
JSON.parse(JSON.stringify(project.room.layout));
// then: load atlas data
atlasData.atlasInfo = project.atlasInfo;
} else {
alert('select a *_data.json file please!');
}
}
// modal popup load Atlas ***************** stop
// change CLICK to ON
function removeClickedFromRule(rule){
rule[0].forEach((elem,index)=>{
if(elem==CLICK)
rule[0][index] = ON;
});
}
// ------------------
function showIntroPopup() {
popupActive = true;
let transp = createDiv();
transp.style('background-color', color(0, 200, 0, 150));
transp.size(width, height);
transp.position(0, 0);
let d = createDiv('<b>--------- Edit intro for this game ---------</b><br><br><br><br>');
d.style('background-color', color(200, 220, 200));
d.size(width * 3 / 4, height * 3 / 4);
d.position(width * 1 / 8, height * 1 / 8);
// fields
let inp;
d.child( inp = createElement('textarea') );
inp.id('inp1');
inp.attribute('rows','10');
inp.attribute('cols','50');
inp.value( project.intro );
inp.position(width*1/48,height*1/24);
inp.size(width*5/8,height*5/8);
let b = createButton('(X)'); // close button
globalCloseButton = b;
b.position(width * 3 / 4 + width * 1 / 8 - b.size().width - 5,
height * 1 / 8 + 5);
b.mouseClicked(_ => {
ok.hide();
b.hide();
d.hide();
transp.hide();
popupActive = false;
});
let ok = createButton(' OK '); // submit button
ok.position(width*2/4-ok.size().width-5,
height*3/4+ok.size().height+15);
ok.mouseClicked(_ => {
// change information about the current game
project.intro = select('#inp1').value();
// console.log( project.intro );
// then close
ok.hide();
b.hide();
d.hide();
transp.hide();
popupActive = false;
project.needsRefresh = true;
});
}
// ********************************
function showSplashScreen(){
popupActive = true;
let transp = createDiv();
transp.style('background-color', color(255,255,255,150));
transp.size(width,height);
transp.position(0,0);
let d = createDiv('<center><h1>Stick\'N\'Click</h1></center><br>');
d.style('background-color', '#FFFFFF'); // F000F0
d.style('border', '5px solid black');
d.size(width*3/4,height*3/4);
d.position(width*1/8,height*1/8);
d.child( sNcLogo );
sNcLogo.size(width*8/16,height*7/16);
sNcLogo.position(width*2/16,height*2/16);
let newProject=createButton('New Project');
newProject.style('background-color', 'green');
newProject.style('color', 'white');
newProject.style('font-size', '150%');
newProject.size(width*1/4,height*1/12);
newProject.position(width*2/4-newProject.width/2,
height*3/4);
newProject.mouseClicked(_ => {
// DEBUG console.log('!new project!');
// then close
newProject.hide();
d.hide();
transp.hide();
popupActive = false;
justStarted = false;
project.needsRefresh = true;
});
}
function keyPressed() {
// DEBUG console.log('you pressed ' + keyCode );
if (keyCode === ESCAPE) {
if ((popupActive) && (globalCloseButton!=null)){
// DEGUB console.log('you pressed ESC while a popup is open!');
globalCloseButton.elt.click();
}
}
}
function showExportPopup(){
let pg;
// 1 create the atlas image
let maxW = -1;
let imageOffsetY = 0;
Object.values(images).forEach(img=>{
//console.log( img );
if(img.width>maxW) maxW=img.width;
imageOffsetY += img.height;
});
pg = createGraphics(maxW,imageOffsetY); // not enough!!
pg.attribute('width',maxW); // do this too!!!
pg.attribute('height',imageOffsetY); // do this too!!!
//DEGUB console.log('pg = ' , maxW,imageOffsetY);
//DEGUB console.log('pg = ' , pg);
// 2 copy all images to the atlas image
// ... insert atlas data in the project object
imageOffsetY = 0;
project.atlasInfo = []; // reset the atlas, just in case of multiple saves!
Object.values(images).forEach((info,index)=>{
//console.log( info );
project.atlasInfo.push([imageOffsetY,info.width,info.height]);
pg.image(info,
0,imageOffsetY,
info.width,info.height);
imageOffsetY += info.height;
});
// make all measures relative (one-thousand-ds) to the width and height
// must multiply by 2 because layout is 1/2 screen size
let clonedProject = JSON.parse(JSON.stringify(project));
clonedProject.room.layout = clonedProject.room.layout.map(elem=>{
//console.log( elem );
let [A,B,C,D,E] = elem;
A = ~~(A*1000/width*2);
B = ~~(B*1000/height*2);
C = ~~(C*1000/width*2);
D = ~~(D*1000/height*2);
return [A,B,C,D,E];
});
let canvasContents = pg.elt.toDataURL();
let data = { atlas: canvasContents, project: clonedProject , timeStamp: new Date() };
let stringCanvas= JSON.stringify(data);
localStorage.setItem('currentProject', stringCanvas);
window.open('https://editor.p5js.org/andrea270872/present/chgF2ZeNP','s&c_player');
/*
console.log( 'exporting ' + project.name);
// TO DO
// ****** PAGE 1 *************************************
// Layout
pg = createGraphics(1000,800); // not enough!!
pg.attribute('width',1000); // do this too!!!
pg.attribute('height',800); // do this too!!!
pg.fill(255); pg.rect(0,0,1000,800); // paint white
if (project.backgroundId!=-1){
pg.image(bkgds[project.backgroundId],
0,0,
1000,800);
}
// TO DO draw layout rectangles
pg.save( project.name +'_page1.png');
// ****** PAGE 2 *************************************
// Stickers and Placeholders
pg = createGraphics(1000,800); // not enough!!
pg.attribute('width',1000); // do this too!!!
pg.attribute('height',800); // do this too!!!
pg.fill(255); pg.rect(0,0,1000,800); // paint white
let imageOffsetX = 0;
Object.values(images).forEach(img=>{
project.stickers.forEach((elem, index) => {
if (images[elem]) {
pg.image(images[elem], index * 100,10,
100,100);
}
});
project.markers.forEach((elem, index) => {
pg.fill('#0000FF');
pg.text(elem, 15 + index*100,500);
});
});
pg.save( project.name +'_page2.png');
// ****** PAGE 3 *************************************
// Rules
pg = createGraphics(1000,800); // not enough!!
pg.attribute('width',1000); // do this too!!!
pg.attribute('height',800); // do this too!!!
pg.fill(255); pg.rect(0,0,1000,800); // paint white
project.room.rules.forEach((rule, index) => {
pg.fill('#000000');
pg.text( 'RULE '+(index+1)+': IF ... THEN', 20, 15+ index*200);
console.log(rule);
});
pg.save( project.name +'_page3.png');
*/
}