{"id":7205,"date":"2021-06-24T07:54:01","date_gmt":"2021-06-24T07:54:01","guid":{"rendered":"https:\/\/www.marincas.net\/puzzle\/?page_id=7205"},"modified":"2021-06-24T19:01:38","modified_gmt":"2021-06-24T19:01:38","slug":"adelie-penguin-easy-demo","status":"publish","type":"page","link":"https:\/\/www.marincas.net\/puzzle\/adelie-penguin-easy-demo\/","title":{"rendered":"Adelie Penguin Easy Demo"},"content":{"rendered":"<p><script>\n\/*\n  MIT License\nCopyright (c) 2019 Dan Zen\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and\/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n  *\/\nconst frame = new Frame(\"fit\", 1366, 768, light, darker, \"https:\/\/www.marincas.net\/puzzle\/wp-content\/uploads\/2020\/12\/Adelie-Penguin.jpg\", \"assets\/\");\nframe.on(\"ready\", () => {\n    const stage = frame.stage;\n    let stageW = frame.width;\n    let stageH = frame.height;\n    \/\/ put your code here\n     const mob = mobile();\n    \/\/ ~~~~~~~~~~~~~~~~~~~~~\n    \/\/ CLASS to make JigSaw piece with bumps out or in or no bump on any four edges\n    class Piece extends Shape {\n        \/\/ format is 1 for bump out, -1 for bump in and 0 for no bump\n        constructor(w=100,h=100,format=[1,1,1,1],s=black,ss=1,f=white) {\n            super(w,h);\n            const p = Piece.part; \/\/ static property - defined below class\n            const g = Piece.gap;\n            this.s(s).ss(ss).f(f).mt(0,0);\n            if (format[0]==0) this.lt(w,0); \/\/ top left-right\n            else {\n                this.lt(w*p,0);\n                let s = format[0]==1?-1:1; \/\/ sign                \n                this.ct(w*(p-g\/2), s*w*g, w\/2, s*w*g); \/\/ curve left to middle\n                this.ct(w*(p+g+g\/2), s*w*g, w*(1-p), 0); \/\/ curve middle to right           \n                this.lt(w,0)\n            }            \n            if (format[1]==0) this.lt(w,h); \/\/ right top-bottom\n            else {\n                this.lt(w,h*p);\n                let s = format[1]==1?1:-1; \n                this.ct(w+s*w*g, h*(p-g\/2), w+s*w*g, h\/2);\n                this.ct(w+s*w*g, h*(p+g+g\/2), w, h*(1-p));                \n                this.lt(w,h)\n            }            \n            if (format[2]==0) this.lt(0,h); \/\/ bottom right-left\n            else {\n                this.lt(w*(1-p),h);\n                let s = format[2]==1?1:-1;           \n                this.ct(w*(p+g+g\/2), h+s*w*g, w\/2, h+s*w*g);\n                this.ct(w*(p-g\/2), h+s*w*g, w*p, h+0);                \n                this.lt(0,h)\n            }            \n            if (format[3]==0) this.lt(0,0); \/\/ left bottom-top\n            else {\n                this.lt(0,h*(1-p));\n                let s = format[3]==1?-1:1;             \n                this.ct(s*w*g, h*(p+g+g\/2), s*w*g, h\/2);\n                this.ct(s*w*g, h*(p-g\/2), 0, h*p);             \n                this.lt(0,0)\n            }\n            this.cp(); \/\/ close path\n        }        \n    }\n    Piece.part = .37; \/\/ part of the edge with no gap ratio\n    Piece.gap = 1-Piece.part*2; \/\/ gap ratio of edge\n\/\/ MENU \n  \/* \u00bb *\/\nvar label = new Label({\n   text:\"\u00bb\",\n   size:25,\n   backgroundColor:\"#3FA5EA\",\n  color:white     \n});\nvar button = new Button({\n   label:label,\n   width:75,\n   height:50,\n   backgroundColor:\"#3FA5EA\",\n   borderWidth:0,  \n   corner:0,  \n});\nbutton.pos(280,20);\n  button.on(\"click\", function(){zgo(\"https:\/\/www.marincas.net\/puzzle\/anime-cosplay-pose-easy\");});  \n   \/* \u21ba *\/\nvar label = new Label({\n   text:\"\u21ba\",\n   size:25,\n   backgroundColor:\"#3FA5EA\",\n  color:white,   \n});\nvar button = new Button({\n   label:label,\n   width:75,\n   height:50,\n   backgroundColor:\"#3FA5EA\",\n   borderWidth:0,  \n   corner:0\n});\nbutton.pos(380,20);\n  button.on(\"click\", function(){zgo(\"https:\/\/www.marincas.net\/puzzle\/adelie-penguin-easy-demo\");});  \n     \/* MEDIUM *\/\nvar label = new Label({\n   text:\"Medium\",\n   size:20,\n   backgroundColor:\"#3FA5EA\",\n  color:white,   \n});\nvar button = new Button({\n   label:label,\n   width:100,\n   height:50,\n   backgroundColor:\"#3FA5EA\",\n   borderWidth:0,  \n   corner:0\n});\nbutton.pos(480,20);\n  button.on(\"click\", function(){zgo(\"https:\/\/www.marincas.net\/puzzle\/adelie-penguin-medium\");});  \n     \/* HARD *\/\nvar label = new Label({\n   text:\"Hard\",\n   size:20,\n   backgroundColor:\"#3FA5EA\",\n  color:white,   \n});\nvar button = new Button({\n   label:label,\n   width:100,\n   height:50,\n   backgroundColor:\"#3FA5EA\",\n   borderWidth:0,  \n   corner:0\n});\nbutton.pos(605,20);\n  button.on(\"click\", function(){zgo(\"https:\/\/www.marincas.net\/puzzle\/adelie-penguin-hard\");});\n    \/* Puzzles *\/\nvar label = new Label({\n   text:\"Puzzles\",\n   size:20,\n   backgroundColor:\"#3FA5EA\",\n  color:white,   \n});\nvar button = new Button({\n   label:label,\n   width:100,\n   height:50,\n   backgroundColor:\"#3FA5EA\",\n   borderWidth:0,  \n   corner:0\n});\nbutton.pos(730,20);\n  button.on(\"click\", function(){zgo(\"https:\/\/www.marincas.net\/puzzle\/all-puzzles\");});  \n   \/* Account *\/\nvar label = new Label({\n   text:\"Account\",\n   size:20,\n   backgroundColor:\"#3FA5EA\",\n  color:white,   \n});\nvar button = new Button({\n   label:label,\n   width:100,\n   height:50,\n   backgroundColor:\"#3FA5EA\",\n   borderWidth:0,  \n   corner:0\n});\nbutton.pos(855,20);\n  button.on(\"click\", function(){zgo(\"https:\/\/www.marincas.net\/puzzle\/membership-account\");});    \n    \/* Logout *\/\nvar label = new Label({\n   text:\"Register\",\n   size:20,\n   backgroundColor:\"#3FA5EA\",\n  color:white,   \n});\nvar button = new Button({\n   label:label,\n   width:100,\n   height:50,\n   backgroundColor:\"#3FA5EA\",\n   borderWidth:0,  \n   corner:0\n});\nbutton.pos(980,20);\n  button.on(\"click\", function(){zgo(\"https:\/\/www.marincas.net\/puzzle\/membership-account\/membership-levels\");});  \n    \/\/ ~~~~~~~~~~~~~~~~~~~~~\n    \/\/ PUZZLE SIZE    \n    let numX = 4;\n    let numY = 3;\n    const obj = getQueryString(); \/\/ note, getQueryString returns {} now if no query string    \n    if (obj.col) numX = Math.min(14, Number(obj.col)); \/\/ or we would have to start chaching things...\n    if (obj.row) numY = Math.min(10, Number(obj.row));    \n    \/\/ ~~~~~~~~~~~~~~~~~~~~~\n    \/\/ PICTURE    \n    const pic = asset(\"https:\/\/www.marincas.net\/puzzle\/wp-content\/uploads\/2020\/12\/Adelie-Penguin.jpg\").clone().center().alp(0.5).vis(false); \/\/ checkbox later to turn on\n    const w = pic.width\/numX;\n    const h = pic.height\/numY;       \n    \/\/ chop the picture into bitmaps\n    \/\/ false is for an array rather than the default Tile output \n    \/\/ extra is because bumps go outside the width and height\n    const extra = Math.max(w,h)*Piece.gap; \n    const pics = chop(asset(\"https:\/\/www.marincas.net\/puzzle\/wp-content\/uploads\/2020\/12\/Adelie-Penguin.jpg\"), numX, numY, false, extra);         \n    \/\/ ~~~~~~~~~~~~~~~~~~~~~\n    \/\/ PIECES    \n    \/\/ makePieces gets called from Tile - for each piece\n    let count=0;\n    let lastX = rand()>.5?1:-1; \/\/ 1 or -1 for out or in horizontally\n    let lastYs = []; \/\/ 1 or -1 vertically - remember with array and modulus\n    loop(numX, i=>{lastYs.push(rand()>.5?1:-1);});\n    function makePiece() {           \n        \/\/ prepare format for jigsaw piece [1,0,-1,0] \n        \/\/ 1 bump out, 0 no bump, -1 bump in, etc.\n        let currentX = lastX*-1; \/\/ opposite of last x\n        let currentY = lastYs[count%numX]*-1; \/\/ opposite of last y\n        let nextX = rand()>.5?1:-1; \/\/ randomize the next 1 or -1 for out or in horizontally\n        let nextY = rand()>.5?1:-1; \/\/ and vertically\n        \/\/ top, right, bottom, left\n        let format = [currentY, nextX, nextY, currentX]; \n        lastX = nextX;\n        lastYs[count%numX] = nextY;          \n        \/\/ override edges to 0\n        if (count < numX) format[0] = 0;\n        else if (count >= numX*numY-numX) format[2] = 0;\n        if (count%numX==0) format[3] = 0;\n        else if ((count-numX+1)%numX==0) format[1] = 0;        \n        \/\/ make a container to hold jigsaw shape and later picture part\n        let piece = new Container(w,h).centerReg({add:false});\n        piece.puzzle = new Piece(w, h, format).addTo(piece);      \n        piece.mouseChildren = false;  \n        count++;\n        return piece;\n    }        \n    const pieces = new Tile({\n        obj:makePiece, \n        cols:numX, \n        rows:numY,\n        clone:false \/\/ otherwise makes clone of piece\n    })\n        .center()\n        .drag(stage).animate({\n            props:{alpha:1},\n            time:.1,\n            sequence:.05\n        });    \n    \/\/ ~~~~~~~~~~~~~~~~~~~~~\n    \/\/ HINT AND SNAP HIT BOX    \n    \/\/ tidy up alpha setting on hint around border\n    const outline = new Rectangle(pic.width,pic.height,clear,mist,4).center().ord(-1) \/\/ under pieces    \n    const hint = pieces.clone(true) \/\/ exact\n        .center()\n        .ord(-1) \/\/ under pieces     \n        .cache(-5,-5,pic.width+10,pic.height+10) \/\/ cache by default does not include outside border \n        .alp(.2)\n        .vis(0); \/\/ checkbox below to show    \n    \/\/ make a little box to do hit test to see if in right place\n    const snap = 50; \/\/ pixel distance considered correct\n    loop(hint, h=>{\n        h.box = new Rectangle(snap,snap).centerReg(h).vis(0); \/\/ do not use alpha=0 as that will make it not hittable        \n    });    \n    \/\/ ~~~~~~~~~~~~~~~~~~~~~\n    \/\/ ADD PICTURE TO PIECES, ADD EVENTS, ROTATE AND SCRAMBLE    \n    const padding = 50;\n    const rotate = true;\n    loop(pieces, (piece,i)=>{\n        piece.alp(0); \/\/ sequence animation above will animate in alpha\n        pics[i].addTo(piece).setMask(piece.puzzle);  \n       \/\/ test on mobile and see if you need to cache...\t\n        \/\/ usually this is just cache() but the bumps are outside the piece \t\n        \/\/ and the cache size really does not make a difference if rest is background transparent \t\n        if (mob) piece.cache(-100,-100,piece.width+200,piece.width+200);\n        if (rotate) {\n            piece.rotation = shuffle([0,90,180,270])[0];\n            piece.tap({\n                time:.5, \/\/ within .5 seconds\n                call:() => {   \n                    pieces.noMouse(); \/\/ do not let anything happen while animating until done\n                    piece.animate({\n                        props:{rotation:String(frame.shiftKey?-90:90)}, \/\/ string makes relative\n                        time:.2,\n                        call:() => {\n                            pieces.mouse();\n                            test(piece);\n                        }\n                    });                \n                    stage.update();\n                }, \n                call2:() => { \/\/ if no tap\n                    test(piece);   \n                }                \n            }); \n        } else {\n            piece.on(\"pressup\", () => {\n                test(piece); \n            });\n        }        \n        piece.on(\"pressdown\", () => {\n            \/\/ shadows are expensive on mobile\t\n            \/\/ could add it to container so shadow inside container \t\n            \/\/ then cache the container but might not be worth it\t\n            if (!mob) piece.sha(\"rgba(0,0,0,.4)\",5,5,5);\n        });        \n        \/\/ scramble location     \n        piece.loc(padding+w\/2+rand(stageW-w-padding*2)-pieces.x, padding+h\/2+rand(stageH-h-padding*2)-pieces.y);        \n    });     \n    \/\/ ~~~~~~~~~~~~~~~~~~~~~\n    \/\/ EMITTER    \n    const emitter = new Emitter({\n        obj:new Poly({min:10, max:17}, [5,6], .5, [blue, yellow, red]),\n        num:2,\n        force:6,\n        startPaused:true\n    });        \n    \/\/ ~~~~~~~~~~~~~~~~~~~~~\n    \/\/ MESSAGE LABEL    \n    const num = numX*numY;\n    let placed = 0;\n    STYLE = {color:\"#000\"}\n    const stats = new Label({        \n        text:`Easy: Adelie Penguin ${placed}\/${num}`,        \n        align:CENTER,\n        size:20,        \n    }).centerReg().pos(0,30,CENTER,BOTTOM);    \n    \/\/ ~~~~~~~~~~~~~~~~~~~~~\n    \/\/ TEST FOR PIECE IN RIGHT PLACE AND END     \n    function test(piece) {\n        piece.sha(-1);\n        let box = hint.items[piece.tileNum].box;\n        if (piece.rotation%360==0 && box.hitTestReg(piece)) {\n            piece.loc(box).bot().noMouse();\n            emitter.loc(box).spurt(30);\n            placed++;\n            if (placed==num) {\n                stats.text = `Well done! Look how beautiful I am :)`;\n                timeout(1, function () {\n                    emitter.emitterForce = 8;\n                    emitter.center().mov(0,-170).spurt(100)\n                })\n                timeout(2, function () {\n                    hintCheck.removeFrom();\n                    picCheck.removeFrom();\n                    picCheck.checked = true;                    \n                    pieces.animate({alpha:0}, .7);\n                    outline.animate({alpha:0}, .7);\n                    hint.animate({alpha:0}, .7);\n                    pic.alp(0).animate({alpha:1}, .7);                   \n                    new Button({\n                        label:\"\", \n                        color:white, \n                        corner:[0],\n                        backgroundColor:blue.darken(.2), \n                        rollBackgroundColor:blue\n                    })                 \n                        .sca(0)\n                        .pos(150,30,LEFT,BOTTOM)\n                        .alp(0)\n                        .animate({alpha:1})\n                        .tap(()=>{zgo(\"#\")})\n                });                             \n            } else stats.text = `Easy: Adelie Penguin ${placed}${placed==1?\"\":\"\"}\/${num}`;\n        } else stage.update();    \n    }     \n    \/\/ ~~~~~~~~~~~~~~~~~~~~~\n    \/\/ CHECK BOX AND FINISHING TOUCHES    \n    Style.addType(\"CheckBox\", {borderColor:\"#3FA5EA\".darken(.1)});    \n    const hintCheck = new CheckBox(25, \"hint\").alp(.8).pos(50,23,LEFT,BOTTOM).wire({target:hint, prop:\"visible\", input:\"checked\"});\n    const picCheck = new CheckBox(25, \"picture\").alp(.8).pos(130,23,LEFT,BOTTOM).wire({target:pic, prop:\"visible\", input:\"checked\"});\n      \/*  \n    new Label(\"ZIM JigSaw - tap or shift tap to rotate\").pos(0,30,CENTER);\n    new Label(\"Image from Brave \u00a9 Pixar\").sca(.5).pos(77,32,RIGHT,BOTTOM);   \n    frame.madeWith().sca(.8).pos(20,12,RIGHT);\n    *\/\n    pieces.top(); \/\/ add pieces above everything    \n    stage.update(); \/\/ needed to view changes\n});         \n    <\/script><\/p>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"pmpro_default_level":"","footnotes":""},"class_list":["post-7205","page","type-page","status-publish","hentry","pmpro-has-access","entry"],"_links":{"self":[{"href":"https:\/\/www.marincas.net\/puzzle\/wp-json\/wp\/v2\/pages\/7205","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.marincas.net\/puzzle\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.marincas.net\/puzzle\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.marincas.net\/puzzle\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.marincas.net\/puzzle\/wp-json\/wp\/v2\/comments?post=7205"}],"version-history":[{"count":5,"href":"https:\/\/www.marincas.net\/puzzle\/wp-json\/wp\/v2\/pages\/7205\/revisions"}],"predecessor-version":[{"id":7210,"href":"https:\/\/www.marincas.net\/puzzle\/wp-json\/wp\/v2\/pages\/7205\/revisions\/7210"}],"wp:attachment":[{"href":"https:\/\/www.marincas.net\/puzzle\/wp-json\/wp\/v2\/media?parent=7205"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}