HTML5/Pixel Destroy2
HTML5 Particle effects
Soul-Learner
2015. 3. 10. 19:19
HTML5 Particle Effects (HTML 5 파티클 효과 구현) 예
마우스로 이미지를 클릭하면 해당 영역의 픽셀들이 파편(파티클)이 되어 사방으로 날리는 효과를 구현해 본 것이며 파티클의 이동방향과 속도를 결정하기 위해 Vector2D 오브젝트를 정의하고 벡터연산에 사용했다
<!DOCTYPE HTML> <html> <head> <style> body { margin: 0px; padding: 20px; } canvas { background:url(bg.png) } </style> <script type="text/javascript"> var canvas; var offCanvas; var offContext; var mainLevel; var timer; var particles; window.onload = function() { init(); } function init() { offCanvas = document.createElement('canvas'); offCanvas.height = 500; offCanvas.width = 500; offContext = offCanvas.getContext('2d'); var imageObj = new Image(); imageObj.onload = function() { mainLevel = this; offContext.drawImage(this,0,0); timer = setInterval( gameLoop, 60); }; imageObj.src = 'wall.png'; canvas = document.getElementById('myCanvas'); canvas.addEventListener('mousedown', function(evt){ var rect = canvas.getBoundingClientRect(); var cx = evt.clientX-rect.left; var cy = evt.clientY-rect.top; //파티클 생성, 배열에 저장 if(!particles) particles = []; var idx = 0; for(var i=0;i<4;i++) { for(var j=0;j<4;j++) { var vp = Math.round(Math.random()*10)%5+5; //파티클 속도 var vr = Math.round(Math.random()*100)%20+10;//파티클 회전속도 if(Math.round(Math.random()*10)%2==0) vr=-vr; var targetV = new Vector2D(cx,cy);// 마우스 클릭 위치 var particlePos = new Vector2D(cx-20+(i*10),cy-20+(j*10));//파티클 위치 var directionV = particlePos.sub(targetV); // 파티클 비산 방향 결정 if(directionV.x==0 && directionV.y==0) directionV.y=1; // 방향이 없는 파티클 방지 var particleNormV = directionV.normalize(); // 방향정보만 사용하기 위한 단위벡터 var particleV = particleNormV.multiply(vp); // 방향정보에 속도를 곱해서 파티클의 방향과 속도를 완성 //particles배열에 추가 particles[idx++] = new Particle(cx-20+(i*10), cy-20+(j*10), particleV.x, particleV.y, vr); } } //백버퍼에 그려진 메인 이미지에 투명한 구멍을 낸다. 백버퍼는 메인 캔바스에 그릴 때 복사된다 transOffRegion(cx,cy); }); } function gameLoop(){ drawScene(); if(particles && particles.length>0) { for(var i=0;i<particles.length;i++) { if(particles[i]) particles[i].draw(); } } } // 캔바스에 이미지를 그린다 function drawScene() { if(!canvas) canvas = document.getElementById('myCanvas'); var context = canvas.getContext('2d'); context.clearRect(0,0,canvas.width,canvas.height); //백버퍼에 그려진 이미지를 복사해서 메인 캔바스에 그린다 context.drawImage(offCanvas,0,0); } // 백버퍼 이미지에 구멍을 낸다. 백버퍼는 메인 캔바스에 복사하여 그릴때 사용한다 function transOffRegion(cx,cy) { if(!offCanvas) { offCanvas = document.createElement('canvas'); } var offCtx = offCanvas.getContext('2d'); offCtx.globalCompositeOperation = 'destination-out'; offCtx.beginPath(); offCtx.moveTo(cx-15, cy-10); offCtx.lineTo(cx, cy-15); offCtx.lineTo(cx+15, cy-10); offCtx.lineTo(cx+20, cy); offCtx.lineTo(cx+15, cy+10); offCtx.lineTo(cx, cy+15); offCtx.lineTo(cx-15, cy+10); offCtx.lineTo(cx-20, cy); offCtx.closePath(); offCtx.fill(); } // 파티클을 표현한 생성자 함수 function Particle(x, y, vx, vy, vr){ this.x = x; this.y = y; this.vx = vx; this.vy = vy; this.rotDeg = 0; this.vr = vr; this.startTime = new Date(); this.tmpCanvas; //메인 캔바스에서 지정된 위치의 이미지 데이터(파편)를 가져와서 임시 캔바스에 그린다 if(!canvas) canvas = document.getElementById('myCanvas'); var ctx = canvas.getContext('2d'); var imgData = ctx.getImageData(this.x,this.y, 10,10); this.tmpCanvas = document.createElement('canvas'); this.tmpCanvas.height = imgData.height; this.tmpCanvas.width = imgData.width; var tmpCtx = this.tmpCanvas.getContext('2d'); tmpCtx.putImageData(imgData,0,0); //게임루프에서 매 프레임마다 호출되어 화면에 현재 파티클을 그린다 this.draw = function(){ if(!canvas) canvas = document.getElementById('myCanvas'); var ctx = canvas.getContext('2d'); if(this.y>canvas.height || this.x>canvas.width || this.x<0) { var idx = particles.indexOf(this); particles.splice(idx,1); delete particles[idx]; return; } if(new Date()-this.startTime>2000) { var idx = particles.indexOf(this); particles.splice(idx,1); delete particles[idx]; return; } this.vx *= 0.9; this.vy += 0.5; ctx.save(); ctx.translate(this.x+=this.vx, this.y+=this.vy); ctx.rotate((this.rotDeg+=vr)*Math.PI/180); ctx.drawImage(this.tmpCanvas,0,0); ctx.restore(); } } // 파티클의 이동 방향과 속도를 표현하며 벡터 연산에 사용될 생성자 함수 function Vector2D(x,y) { this.x = x; this.y = y; this.add = function(v2d) { return new Vector2D(this.x + v2d.x, this.y + v2d.y); } this.sub = function(v2d) { return new Vector2D(this.x - v2d.x, this.y - v2d.y); } this.multiply = function(len) { return new Vector2D(this.x * len, this.y * len); } this.normalize = function() { var len = Math.sqrt((this.x * this.x + this.y * this.y)); return new Vector2D(this.x/len, this.y/len); } } </script> </head> <body> <canvas id="myCanvas" width="500" height="500"></canvas> </body> </html>