HTML5 Canvas 이동 및 회전변환 예제
translate()의 효과 : 호출될 때마다 이동변환의 량은 내부에서 사용되는 변환행렬에 저장되고 유지됨
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>이동</title> <script type="text/javascript"> var canvas; var ctx; window.addEventListener('load', function() { canvas = document.getElementById("gameCanvas"); ctx = canvas.getContext("2d"); setInterval(gameLoop,30); }); function gameLoop() { draw_test(); } function draw_test(){ ctx.beginPath(); ctx.translate(10,10); // 반복실행되면 이동량이 누적된다(변환행렬에 저장됨) ctx.fillStyle = 'black'; ctx.fillRect(0, 0, 5, 40); ctx.closePath(); //ctx.setTransform(1,0,0,1,0,0); // 변환행렬을 초기화한다 } </script> </head> <body> <canvas id="gameCanvas" width="300" height="200" style="border:1px solid black;"> </canvas> </body> </html>
위의 코드에서 ctx.setTransform(1,0,0,1,0,0)을 사용하면 내부에서 사용되는 변환행렬을 초기화하므로 translate(), rotate() 등을 사용하여 적용한 변환이 해제되어 초기화된다
위와 동일한 코드에 rotate()를 사용한 예
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>회전</title> <script type="text/javascript"> var canvas; var ctx; window.addEventListener('load', function() { canvas = document.getElementById("gameCanvas"); ctx = canvas.getContext("2d"); setInterval(gameLoop,30); }); function gameLoop() { draw_test(); } function draw_test(){ ctx.beginPath(); ctx.rotate(20 * Math.PI/180); // 반복실행되면 회전량이 누적된다(변환행렬에 저장됨) ctx.fillStyle = 'black'; ctx.fillRect(0, 0, 5, 40); ctx.closePath(); //ctx.setTransform(1,0,0,1,0,0); // 변환행렬을 초기화한다 } </script> </head> <body> <canvas id="gameCanvas" width="300" height="200" style="border:1px solid black;"> </canvas> </body> </html>
위의 코드를 실행한 결과
translate(), rotate()를 동시에 사용하는 예 (이동변환량은 고정하고 회전변환량은 누적함)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>회전</title> <script type="text/javascript"> var canvas; var ctx; var angle = 0;window.addEventListener('load', function() { canvas = document.getElementById("gameCanvas"); ctx = canvas.getContext("2d"); setInterval(gameLoop,30); }); function gameLoop() { draw_test(); } function draw_test(){
var x = canvas.width/2; var y = canvas.height/2; ctx.beginPath(); ctx.translate(x,y); angle += 15; ctx.rotate(angle*Math.PI/180); ctx.fillStyle = 'black'; ctx.fillRect(0, 0, 5, 40); ctx.closePath(); ctx.setTransform(1,0,0,1,0,0); } </script> </head> <body> <canvas id="gameCanvas" width="300" height="200" style="border:1px solid black;"> </canvas> </body> </html>
위의 코드 실행결과
방향키로 방향을 지시하고 그 방향으로 포탄을 발사(직선이동)하는 예제
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>발사</title> <script type="text/javascript"> var canvas; var ctx; var launcherX=0, launcherY=0; var bulletX=0.0, bulletY=0.0; var isFire = false; window.addEventListener('load', function() { window.addEventListener('keydown', onKeyDown); canvas = document.getElementById("gameCanvas"); ctx = canvas.getContext("2d"); launcherX = canvas.width/2; launcherY = canvas.height - 50; setInterval(gameLoop,30); }); function gameLoop() { drawLauncher(); fire(); } /* 발사각을 이용하여 탄도의 기울기(cos, sin)를 구하고 발사체에 적용한다 */ function fire() { if(!isFire) return; ctx.beginPath(); ctx.fillStyle = 'black'; var dx = 0.0; var dy = 0.0; var _angle = 0.0; if(angle<0) { _angle = 180+angle-90; dy = Math.sin(_angle*Math.PI/180); dx = -Math.cos(_angle*Math.PI/180); }else { _angle = angle-90; dy = -Math.sin(_angle*Math.PI/180); dx = Math.cos(_angle*Math.PI/180); } // 속도 증폭 dx *= 5; dy *= 5; ctx.translate(bulletX+=dx,bulletY-=dy); ctx.rotate(angle*Math.PI/180); ctx.fillRect(-3,-40,5,5); ctx.closePath(); ctx.setTransform(1,0,0,1,0,1); if(bulletY < 0) isFire = false; } /*방향키로 발사각을 조정하고 스페이스키를 누르면 발사된다*/ var angle = 0; function onKeyDown(evt) { if(evt.keyCode==37) { // 왼쪽으로 회전 angle--; }else if(evt.keyCode==39){ // 오른쪽으로 회전 angle++; }else if(evt.keyCode==32) { // 발사 bulletX = launcherX; bulletY = launcherY; isFire = true; } } /* 작은 사각형의 하단을 중심으로 좌우로 회전하여 발사방향을 지시한다*/ function drawLauncher(){ ctx.beginPath(); ctx.fillStyle = 'white'; ctx.fillRect(0,0,canvas.width, canvas.height); // 캔바스 지움 ctx.closePath(); ctx.beginPath(); ctx.translate(launcherX,launcherY); ctx.rotate(angle*Math.PI/180); ctx.fillStyle = 'black'; ctx.fillRect(-3, -40, 5, 40); ctx.closePath(); ctx.setTransform(1,0,0,1,0,0); } </script> </head> <body> <canvas id="gameCanvas" width="500" height="400" style="border:1px solid black;"> </canvas> </body> </html>
위의 코드를 실행한 결과
포물선 궤적을 따라 이동하면서 이동방향으로 기수 회전하기
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>포물선과 비행방향으로 회전하기</title> <script type="text/javascript"> var canvas; var ctx; var launcherX=0, launcherY=0; var bulletX=0.0, bulletY=0.0; var isFire = false; window.addEventListener('load', function() { window.addEventListener('keydown', onKeyDown); canvas = document.getElementById("gameCanvas"); ctx = canvas.getContext("2d"); launcherX = canvas.width/2; launcherY = canvas.height - 50; setInterval(gameLoop,30); }); function gameLoop() { drawLauncher(); fire(); } /* 발사각을 이용하여 탄도의 기울기(cos, sin)를 구하고 발사체에 적용한다 */ var g = 0.1; var xSpeed = 4.0; var ySpeed = 4.0; var prevPos; var currPos; function fire() { if(!isFire) return; ctx.beginPath(); ctx.fillStyle = 'black'; var dx = 0.0; var dy = 0.0; var _angle = 0.0; if(angle<0) { _angle = 180+angle-90; dy = Math.sin(_angle*Math.PI/180); dx = -Math.cos(_angle*Math.PI/180); }else { _angle = angle-90; dy = -Math.sin(_angle*Math.PI/180); dx = Math.cos(_angle*Math.PI/180); } // 속도 증폭 dx *= xSpeed; dy *= ySpeed; ySpeed -= g; // 중력가속도를 적용하여 포물선 이동 구현 currPos = new Position(bulletX+=dx, bulletY-=dy); ctx.translate(currPos.x, currPos.y); // 발사체의 비행방향으로 기수를 회전한다 // 비행궤적의 기울기를 구하여 각도 계산하여 발사체에 적용한다 var rad = 0.0; // 비행각도 if(prevPos!=null){ var dx = currPos.x - prevPos.x; var dy = currPos.y - prevPos.y; rad = Math.atan2(dy, dx); rad -= Math.PI/2; } ctx.rotate(rad); // 비행방향으로 기수를 회전한다 ctx.fillRect(-3,0,5,15); ctx.closePath(); ctx.setTransform(1,0,0,1,0,1); if(bulletY < 0 || bulletY>=canvas.height) { isFire = false; ySpeed = 4.0; prevPos = null; currPos = null; } prevPos = currPos; } /*방향키로 발사각을 조정하고 스페이스키를 누르면 발사된다*/ var angle = 0; function onKeyDown(evt) { if(evt.keyCode==37) { // 왼쪽으로 회전 angle--; }else if(evt.keyCode==39){ // 오른쪽으로 회전 angle++; }else if(evt.keyCode==32) { // 발사 bulletX = launcherX; bulletY = launcherY; isFire = true; } } /* 작은 사각형의 하단을 중심으로 좌우로 회전하여 발사방향을 지시한다*/ function drawLauncher(){ ctx.beginPath(); ctx.fillStyle = 'white'; ctx.fillRect(0,0,canvas.width, canvas.height); // 캔바스 지움 ctx.closePath(); ctx.beginPath(); ctx.translate(launcherX,launcherY); ctx.rotate(angle*Math.PI/180); ctx.fillStyle = 'black'; ctx.fillRect(-3, -40, 5, 40); ctx.closePath(); ctx.setTransform(1,0,0,1,0,0); } function Position(x,y){ this.x = x; this.y = y; } </script> </head> <body> <canvas id="gameCanvas" width="500" height="400" style="border:1px solid black;"> </canvas> </body> </html>
위의 코드를 실행하여 방향키로 발사각을 지정하고 스페이스 키를 눌러 포탄을 발사하여 포물선 운동을 테스트한 결과