Forked from: hidetaro7's 画像を三角分割でユラユラ View Diff (85) forked: 画像を三角分割でユラユラ y.kurage Follow 2017-02-06 20:23:32 License: MIT License Fork1 Fav0 View740 Play Stop Reload Fullscreen Smart Phone Fork tree Readme JavaScript 232 lines HTML 8 lines CSS 37 lines 画像を三角分割でユラユラと物理エンジンMatter.jsを組み合わせてみた。 適当に作ったのでY方向に隙間ができちゃった…… forked: 画像を三角分割でユラユラ jQuery v1.6.2 // 三角形分割による、独学テクスチャMapping // by Hidetaro7 // これの元となった、シンプル三角形分割の考え方はブログに上げてます。 // http://akibahideki.com/blog/html5-canvas-1/canvas.html // 独学のため、もっと効率のよい方法があればぜひお教えください。(数学はとても苦手です,JSも苦手ですが…) var ctx, canvas, img; var w = 0, h = 0, seg = 10, meshToggle = false; var cn = new Coordinates(); var cloth = null; var small_body_size = 2; jQuery(function ($){ canvas = $("canvas#canvas"); ctx = $(canvas).get(0).getContext("2d"); img = new Image(); img.src = "http://jsdo.it/img/common/side/bnr_html5_01.png"; img.onload = function (){ w = img.width / seg; h = img.height / seg; cn.setOrigin(40, 40); cn.init(); wave(); } $("p#switch a").click(function (){ if(meshToggle) { meshToggle = false; $(this).text("メッシュ表示"); }else{ meshToggle = true; $(this).text("メッシュ非表示"); } }); }); //ready function wave () { var mesh = cn.getMesh(), deg = 0, step = Math.floor(360/seg); ctx.strokeStyle = "green"; var enterframe = setInterval(function () { for (var i=0; i<cloth.bodies.length; i++) { mesh[i].x = cloth.bodies[i].position.x; mesh[i].y = cloth.bodies[i].position.y; } cn.drawMesh(); }, 1000/100); } function Mesh (_x, _y, _corner) { //個別管理用 this.x = _x; this.y = _y; this.corner = _corner; this.pivotX = _x; this.pivotY = _y; } function Coordinates() { // 全体管理用 var pivot = {x: 0, y: 0}; var _this = this; var getVertices = function (){ var results = []; for (var i=0, l=_this.meshes.length; i<l; i++) { results.push({"x":_this.meshes[i].x, "y":_this.meshes[i].y}) } return results; } this.getMesh = function (){ return _this.meshes; } this.init = function () { this.matterInit(); var len = Math.pow( seg, 2 ) + seg*2 + 1; var _x = _y = 0; for (var i=0; i<cloth.bodies.length; i++) { var mx = cloth.bodies[i].position.x, my = cloth.bodies[i].position.y, corner = false; if(my >= img.height) {corner = true;} if(mx >= img.width) { _x = 0; _y++; corner = true; } else { _x++; } cn.addPoint(mx, my, corner); } cn.drawMesh(); } this.geometry = []; this.addPoint = function (_x, _y, corner) { ctx.beginPath(); ctx.fillRect((_x+pivot.x)-this.pointSize*.5, (_y+pivot.y)-this.pointSize*.5, this.pointSize, this.pointSize); ctx.closePath(); var p = new Mesh((_x+pivot.x), (_y+pivot.y) , corner); this.meshes.push(p); } this.setOrigin = function (_x, _y) { pivot.x = _x; pivot.y = _y; } this.getOrigin = function () { return {"x":pivot.x, "y":pivot.y} } this.drawMesh = function (){ ctx.clearRect(0,0, canvas.width(), canvas.height()); var l = this.meshes.length; v = this.meshes; for( var i=0; i<l; i++ ) { if(!v[i].corner) { //segment1 ctx.save(); ctx.beginPath(); ctx.moveTo(v[i].x, v[i].y); ctx.lineTo(v[i+1].x, v[i+1].y); ctx.lineTo(v[i+seg+2].x, v[i+seg+1].y); //追加 ctx.lineTo(v[i+seg+1].x, v[i+seg+1].y); ctx.closePath(); ctx.clip(); var t1 = (v[i+1].x - v[i].x)/w; var t2 = (v[i+1].y - v[i].y)/w; var t3 = (v[i+seg+1].x - v[i].x)/h; var t4 = (v[i+seg+1].y - v[i].y)/h; ctx.setTransform(t1,t2,t3,t4, v[i].x, v[i].y); ctx.drawImage(img, v[i].pivotX-_this.getOrigin().x, v[i].pivotY-_this.getOrigin().y ,w, h, 0, 0 ,w, h); ctx.restore(); if (meshToggle) ctx.stroke(); //segment2 ctx.save(); ctx.beginPath(); ctx.lineTo(v[i+1].x, v[i+1].y); ctx.lineTo(v[i+seg+1].x, v[i+seg+1].y); ctx.lineTo(v[i+seg+2].x+10, v[i+seg+2].y+10); ctx.closePath(); t1 = (v[i+seg+2].x - v[i+seg+1].x)/w; t2 = (v[i+seg+2].y - v[i+seg+1].y)/w; t3 = (v[i+seg+2].x - v[i+1].x)/h; t4 = (v[i+seg+2].y - v[i+1].y)/h; ctx.setTransform(t1,t2,t3,t4, v[i+seg+1].x, v[i+seg+1].y); if(!v[i+1].corner) { //端っこ以外 ctx.clip(); ctx.drawImage(img, v[i].pivotX-_this.getOrigin().x, v[i].pivotY-_this.getOrigin().y ,w+10, h, 0, -h ,w+10, h); }else{ ctx.clip(); ctx.drawImage(img, v[i].pivotX-_this.getOrigin().x, v[i].pivotY-_this.getOrigin().y ,w, h, 0, -h ,w, h); } ctx.restore(); if (meshToggle) ctx.stroke(); } } } this.matterInit = function () { var Engine = Matter.Engine, Render = Matter.Render, Runner = Matter.Runner, Body = Matter.Body, Events = Matter.Events, Composites = Matter.Composites, World = Matter.World, Bodies = Matter.Bodies; // create engine var engine = Engine.create(), world = engine.world; /* // create renderer var render = Render.create({ element: document.body, engine: engine, options: { width: Math.min(document.documentElement.clientWidth, 800), height: Math.min(document.documentElement.clientHeight, 600), showAngleIndicator: false } }); Render.run(render); */ // create runner var runner = Runner.create(); Runner.run(runner, engine); // add bodies var particleOptions = { friction: 0.05, frictionStatic: 0.1, render: { visible: true } }; // add bodies group = Body.nextGroup(true); cloth = Composites.stack(0, 0, seg+1, seg+1, w - small_body_size, h - small_body_size, function(x, y) { return Bodies.rectangle(x, y, small_body_size, small_body_size, { collisionFilter: { group: group } }); }); Composites.mesh(cloth, seg+1, seg+1, false, { stiffness: 0.8 }); for (var i = 0; i < 11; i++) { cloth.bodies[i].isStatic = true; } cloth.bodies[ cloth.bodies.length-1 ].isStatic = true; World.add(world, [cloth]); Events.on(engine, 'beforeUpdate', function(event) { var py = 201 + 50 * Math.sin(engine.timing.timestamp * 0.002); var last_body = cloth.bodies[ cloth.bodies.length-1 ]; Body.setVelocity(last_body, { x: py - last_body.position.x, y: 0 }); Body.setPosition(last_body, { x: py , y:201}); }); } } Coordinates.prototype.meshes = []; Coordinates.prototype.pointSize = 10; <!-- matter.js v0.11.0 --> <script src="http://jsrun.it/assets/G/U/9/Q/GU9Qf"></script> <div id="wrapper"> <canvas id="canvas" width="300" height="300"></canvas> <p id="switch"><a href="javascript:void(0);">メッシュ表示</a></p> </div> forked: 画像を三角分割でユラユラ * { padding: 0; margin: 0; } canvas { } #wrapper { width: 500px; text-align: center; } p#switch { text-align: center; } p#switch a { font-family: "ヒラギノ角ゴ Pro W3", "Hiragino Kaku Gothic Pro", "メイリオ", Meiryo, Osaka, "MS Pゴシック", "MS PGothic", sans-serif; font-size: 16px; font-weight: bold; display: inline-block; padding: 8px 10px; line-height: 1; border-radius: 4px; background: -webkit-gradient(linear, left top, left bottom, color-stop(1.00, #ff7400), color-stop(0.00, #ffa443)); background: -webkit-linear-gradient(top, #ffa443 0%, #ff7400 100%); background: -moz-linear-gradient(top, #ffa443 0%, #ff7400 100%); background: -o-linear-gradient(top, #ffa443 0%, #ff7400 100%); background: -ms-linear-gradient(top, #ffa443 0%, #ff7400 100%); background: linear-gradient(top, #ffa443 0%, #ff7400 100%); text-decoration: none; color: white; text-shadow: 0 -1px 0px rgba(0,0,0,.4); -webkit-font-smoothing: antialiased; } 画像を三角分割でユラユラと物理エンジンMatter.jsを組み合わせてみた。 適当に作ったのでY方向に隙間ができちゃった…… // 三角形分割による、独学テクスチャMapping // by Hidetaro7 // これの元となった、シンプル三角形分割の考え方はブログに上げてます。 // http://akibahideki.com/blog/html5-canvas-1/canvas.html // 独学のため、もっと効率のよい方法があればぜひお教えください。(数学はとても苦手です,JSも苦手ですが…) var ctx, canvas, img; var w = 0, h = 0, seg = 10, meshToggle = false; var cn = new Coordinates(); var cloth = null; var small_body_size = 2; jQuery(function ($){ canvas = $("canvas#canvas"); ctx = $(canvas).get(0).getContext("2d"); img = new Image(); img.src = "http://jsdo.it/img/common/side/bnr_html5_01.png"; img.onload = function (){ w = img.width / seg; h = img.height / seg; cn.setOrigin(40, 40); cn.init(); wave(); } $("p#switch a").click(function (){ if(meshToggle) { meshToggle = false; $(this).text("メッシュ表示"); }else{ meshToggle = true; $(this).text("メッシュ非表示"); } }); }); //ready function wave () { var mesh = cn.getMesh(), deg = 0, step = Math.floor(360/seg); ctx.strokeStyle = "green"; var enterframe = setInterval(function () { for (var i=0; i<cloth.bodies.length; i++) { mesh[i].x = cloth.bodies[i].position.x; mesh[i].y = cloth.bodies[i].position.y; } cn.drawMesh(); }, 1000/100); } function Mesh (_x, _y, _corner) { //個別管理用 this.x = _x; this.y = _y; this.corner = _corner; this.pivotX = _x; this.pivotY = _y; } function Coordinates() { // 全体管理用 var pivot = {x: 0, y: 0}; var _this = this; var getVertices = function (){ var results = []; for (var i=0, l=_this.meshes.length; i<l; i++) { results.push({"x":_this.meshes[i].x, "y":_this.meshes[i].y}) } return results; } this.getMesh = function (){ return _this.meshes; } this.init = function () { this.matterInit(); var len = Math.pow( seg, 2 ) + seg*2 + 1; var _x = _y = 0; for (var i=0; i<cloth.bodies.length; i++) { var mx = cloth.bodies[i].position.x, my = cloth.bodies[i].position.y, corner = false; if(my >= img.height) {corner = true;} if(mx >= img.width) { _x = 0; _y++; corner = true; } else { _x++; } cn.addPoint(mx, my, corner); } cn.drawMesh(); } this.geometry = []; this.addPoint = function (_x, _y, corner) { ctx.beginPath(); ctx.fillRect((_x+pivot.x)-this.pointSize*.5, (_y+pivot.y)-this.pointSize*.5, this.pointSize, this.pointSize); ctx.closePath(); var p = new Mesh((_x+pivot.x), (_y+pivot.y) , corner); this.meshes.push(p); } this.setOrigin = function (_x, _y) { pivot.x = _x; pivot.y = _y; } this.getOrigin = function () { return {"x":pivot.x, "y":pivot.y} } this.drawMesh = function (){ ctx.clearRect(0,0, canvas.width(), canvas.height()); var l = this.meshes.length; v = this.meshes; for( var i=0; i<l; i++ ) { if(!v[i].corner) { //segment1 ctx.save(); ctx.beginPath(); ctx.moveTo(v[i].x, v[i].y); ctx.lineTo(v[i+1].x, v[i+1].y); ctx.lineTo(v[i+seg+2].x, v[i+seg+1].y); //追加 ctx.lineTo(v[i+seg+1].x, v[i+seg+1].y); ctx.closePath(); ctx.clip(); var t1 = (v[i+1].x - v[i].x)/w; var t2 = (v[i+1].y - v[i].y)/w; var t3 = (v[i+seg+1].x - v[i].x)/h; var t4 = (v[i+seg+1].y - v[i].y)/h; ctx.setTransform(t1,t2,t3,t4, v[i].x, v[i].y); ctx.drawImage(img, v[i].pivotX-_this.getOrigin().x, v[i].pivotY-_this.getOrigin().y ,w, h, 0, 0 ,w, h); ctx.restore(); if (meshToggle) ctx.stroke(); //segment2 ctx.save(); ctx.beginPath(); ctx.lineTo(v[i+1].x, v[i+1].y); ctx.lineTo(v[i+seg+1].x, v[i+seg+1].y); ctx.lineTo(v[i+seg+2].x+10, v[i+seg+2].y+10); ctx.closePath(); t1 = (v[i+seg+2].x - v[i+seg+1].x)/w; t2 = (v[i+seg+2].y - v[i+seg+1].y)/w; t3 = (v[i+seg+2].x - v[i+1].x)/h; t4 = (v[i+seg+2].y - v[i+1].y)/h; ctx.setTransform(t1,t2,t3,t4, v[i+seg+1].x, v[i+seg+1].y); if(!v[i+1].corner) { //端っこ以外 ctx.clip(); ctx.drawImage(img, v[i].pivotX-_this.getOrigin().x, v[i].pivotY-_this.getOrigin().y ,w+10, h, 0, -h ,w+10, h); }else{ ctx.clip(); ctx.drawImage(img, v[i].pivotX-_this.getOrigin().x, v[i].pivotY-_this.getOrigin().y ,w, h, 0, -h ,w, h); } ctx.restore(); if (meshToggle) ctx.stroke(); } } } this.matterInit = function () { var Engine = Matter.Engine, Render = Matter.Render, Runner = Matter.Runner, Body = Matter.Body, Events = Matter.Events, Composites = Matter.Composites, World = Matter.World, Bodies = Matter.Bodies; // create engine var engine = Engine.create(), world = engine.world; /* // create renderer var render = Render.create({ element: document.body, engine: engine, options: { width: Math.min(document.documentElement.clientWidth, 800), height: Math.min(document.documentElement.clientHeight, 600), showAngleIndicator: false } }); Render.run(render); */ // create runner var runner = Runner.create(); Runner.run(runner, engine); // add bodies var particleOptions = { friction: 0.05, frictionStatic: 0.1, render: { visible: true } }; // add bodies group = Body.nextGroup(true); cloth = Composites.stack(0, 0, seg+1, seg+1, w - small_body_size, h - small_body_size, function(x, y) { return Bodies.rectangle(x, y, small_body_size, small_body_size, { collisionFilter: { group: group } }); }); Composites.mesh(cloth, seg+1, seg+1, false, { stiffness: 0.8 }); for (var i = 0; i < 11; i++) { cloth.bodies[i].isStatic = true; } cloth.bodies[ cloth.bodies.length-1 ].isStatic = true; World.add(world, [cloth]); Events.on(engine, 'beforeUpdate', function(event) { var py = 201 + 50 * Math.sin(engine.timing.timestamp * 0.002); var last_body = cloth.bodies[ cloth.bodies.length-1 ]; Body.setVelocity(last_body, { x: py - last_body.position.x, y: 0 }); Body.setPosition(last_body, { x: py , y:201}); }); } } Coordinates.prototype.meshes = []; Coordinates.prototype.pointSize = 10; <!-- matter.js v0.11.0 --> <script src="http://jsrun.it/assets/G/U/9/Q/GU9Qf"></script> <div id="wrapper"> <canvas id="canvas" width="300" height="300"></canvas> <p id="switch"><a href="javascript:void(0);">メッシュ表示</a></p> </div> * { padding: 0; margin: 0; } canvas { } #wrapper { width: 500px; text-align: center; } p#switch { text-align: center; } p#switch a { font-family: "ヒラギノ角ゴ Pro W3", "Hiragino Kaku Gothic Pro", "メイリオ", Meiryo, Osaka, "MS Pゴシック", "MS PGothic", sans-serif; font-size: 16px; font-weight: bold; display: inline-block; padding: 8px 10px; line-height: 1; border-radius: 4px; background: -webkit-gradient(linear, left top, left bottom, color-stop(1.00, #ff7400), color-stop(0.00, #ffa443)); background: -webkit-linear-gradient(top, #ffa443 0%, #ff7400 100%); background: -moz-linear-gradient(top, #ffa443 0%, #ff7400 100%); background: -o-linear-gradient(top, #ffa443 0%, #ff7400 100%); background: -ms-linear-gradient(top, #ffa443 0%, #ff7400 100%); background: linear-gradient(top, #ffa443 0%, #ff7400 100%); text-decoration: none; color: white; text-shadow: 0 -1px 0px rgba(0,0,0,.4); -webkit-font-smoothing: antialiased; } use an iframe compat browser, deer Play on jsdo.it games Author Share ブログに埋め込む QR Tag Download Complete! Description What kind of game? 画像を三角分割でユラユラと物理エンジンMatter.jsを組み合わせてみた。 適当に作ったのでY方向に隙間ができちゃった…… Control Device Smartphone Controllerjsdo.it WebSocket Controller» Mouse Keyboard Touch Device Fullscreen Activated Inactivated jsdo.it games から削除する Submit Author y.kurage Tweet Default Panel Auto play Screenshot Readme JavaScript HTML CSS Size Width: px Height: px code <script type="text/javascript" src="http://jsdo.it/blogparts/ScZa/js"></script> art&design animation canvas, triangle, Discussion Questions on this code? Tags animation art&design canvas, triangle, Forked sort by latest page views favorite forked forked: 画像を三角分割でユラユラ Surya 00 471 233/8/37 animation art&design canvas, triangle,