여러분이 사용하고 계신 브라우저는 HTML5를 지원하지 않기 때문에 몇몇 요소가 제대로 보이도록 JScript를 사용하고 있습니다. 하지만 여러분의 브라우저 설정에서 스크립트 기능이 꺼져있으므로, 현재 페이지를 제대로 확인하시려면 스크립트 기능을 켜주셔야 합니다. HTML 게임 - 이미지

HTML 게임 – 이미지

4일전 작성

HTML Canvas 게임 이미지

HTML Canvas 게임에서 이미지를 사용하는 방법을 알아본다. 단순한 색상 사각형 대신 이미지를 사용하여 게임의 시각적 품질을 향상시키는 다양한 기법을 설명한다.

기본 이미지 컴포넌트

게임 컴포넌트에 이미지를 사용하는 기본적인 방법을 구현해보자.

<canvas id="myCanvas1" width="480" height="270" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var myGamePiece;
var myGameArea = {
canvas: document.getElementById("myCanvas1"),
start: function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
this.interval = setInterval(updateGameArea, 20);
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
if (type == "image") {
this.image = new Image();
this.image.src = color;
}
this.update = function() {
ctx = myGameArea.context;
if (this.type == "image") {
ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
} else {
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
}
function startGame() {
myGamePiece = new component(50, 50, "red", 10, 120);
myGameArea.start();
}
function updateGameArea() {
myGameArea.clear();
myGamePiece.speedX = 1;
myGamePiece.newPos();
myGamePiece.update();
}
startGame();
</script>

이미지 타입 컴포넌트는 Image 객체를 생성하고 drawImage() 메서드를 사용하여 렌더링한다. color 매개변수에 이미지 파일의 URL을 전달한다.

이미지 로딩 처리

이미지가 완전히 로드된 후에 게임을 시작하도록 개선해보자.

<canvas id="myCanvas2" width="480" height="270" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var myGamePiece;
var imagesLoaded = 0;
var totalImages = 1;
var myGameArea = {
canvas: document.getElementById("myCanvas2"),
start: function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
this.interval = setInterval(updateGameArea, 20);
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.imageLoaded = false;
if (type == "image") {
this.image = new Image();
this.image.onload = function() {
imagesLoaded++;
this.imageLoaded = true;
if (imagesLoaded >= totalImages) {
startGameLoop();
}
}.bind(this);
this.image.src = color;
}
this.update = function() {
ctx = myGameArea.context;
if (this.type == "image" && this.imageLoaded) {
ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
} else if (this.type != "image") {
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
}
function startGame() {
myGamePiece = new component(60, 60, "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHZpZXdCb3g9IjAgMCA2MCA2MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGNpcmNsZSBjeD0iMzAiIGN5PSIzMCIgcj0iMjgiIGZpbGw9IiNGRjAwMDAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSI0Ii8+CjwvZXZnPgo=", 10, 120, "image");
}
function startGameLoop() {
myGameArea.start();
}
function updateGameArea() {
myGameArea.clear();
myGamePiece.speedX = 1;
myGamePiece.newPos();
myGamePiece.update();
}
startGame();
</script>

onload 이벤트를 사용하여 이미지가 로드된 후에 게임 루프를 시작한다. 여러 이미지를 사용할 때는 모든 이미지가 로드될 때까지 기다린다.

배경 이미지

게임에 배경 이미지를 추가해보자.

<canvas id="myCanvas3" width="480" height="270" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var myGamePiece;
var myBackground;
var myGameArea = {
canvas: document.getElementById("myCanvas3"),
start: function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
this.interval = setInterval(updateGameArea, 20);
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
if (type == "image" || type == "background") {
this.image = new Image();
this.image.src = color;
}
this.update = function() {
ctx = myGameArea.context;
if (this.type == "background") {
ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
} else if (this.type == "image") {
ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
} else {
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
}
function startGame() {
myBackground = new component(480, 270, "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgwIiBoZWlnaHQ9IjI3MCIgdmlld0JveD0iMCAwIDQ4MCAyNzAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSI0ODAiIGhlaWdodD0iMjcwIiBmaWxsPSIjODdDRUVCIi8+Cjwvc3ZnPgo=", 0, 0, "background");
myGamePiece = new component(50, 50, "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIHZpZXdCb3g9IjAgMCA1MCA1MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGNpcmNsZSBjeD0iMjUiIGN5PSIyNSIgcj0iMjMiIGZpbGw9IiNGRjAwMDAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSI0Ii8+CjwvZXZnPgo=", 10, 120, "image");
myGameArea.start();
}
function updateGameArea() {
myGameArea.clear();
myBackground.update();
myGamePiece.speedX = 1;
myGamePiece.newPos();
myGamePiece.update();
}
startGame();
</script>

배경 이미지는 가장 먼저 그려져야 다른 요소들이 그 위에 나타난다. 배경은 캔버스 전체 크기로 설정한다.

스크롤링 배경

무한히 스크롤되는 배경 효과를 만들어보자.

<canvas id="myCanvas4" width="480" height="270" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var myGamePiece;
var myBackground;
var myGameArea = {
canvas: document.getElementById("myCanvas4"),
start: function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
this.interval = setInterval(updateGameArea, 20);
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
if (type == "image" || type == "background") {
this.image = new Image();
this.image.src = color;
}
this.update = function() {
ctx = myGameArea.context;
if (this.type == "background") {
ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
ctx.drawImage(this.image, this.x + this.width, this.y, this.width, this.height);
} else if (this.type == "image") {
ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
} else {
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
if (this.type == "background") {
if (this.x <= -this.width) { this.x = 0; } } } } function startGame() { myBackground = new component(480, 270, "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgwIiBoZWlnaHQ9IjI3MCIgdmlld0JveD0iMCAwIDQ4MCAyNzAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSI0ODAiIGhlaWdodD0iMjcwIiBmaWxsPSIjODdDRUVCIi8+CjxjaXJjbGUgY3g9IjEwMCIgY3k9IjEwMCIgcj0iMjAiIGZpbGw9IiNGRkZGRkYiLz4KPGNpcmNsZSBjeD0iMzAwIiBjeT0iNTAiIHI9IjE1IiBmaWxsPSIjRkZGRkZGIi8+CjxjaXJjbGUgY3g9IjQwMCIgY3k9IjE1MCIgcj0iMjUiIGZpbGw9IiNGRkZGRkYiLz4KPC9zdmc+Cg==", 0, 0, "background"); myGamePiece = new component(50, 50, "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIHZpZXdCb3g9IjAgMCA1MCA1MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGNpcmNsZSBjeD0iMjUiIGN5PSIyNSIgcj0iMjMiIGZpbGw9IiNGRjAwMDAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSI0Ii8+CjwvZXZnPgo=", 200, 120, "image"); myGameArea.start(); } function updateGameArea() { myGameArea.clear(); myBackground.speedX = -1; myBackground.newPos(); myBackground.update(); myGamePiece.update(); } startGame(); </script>[/code]

배경 이미지를 두 개 연속으로 그리고 왼쪽으로 이동시킨다. 첫 번째 이미지가 완전히 사라지면 위치를 리셋하여 무한 스크롤 효과를 만든다.

스프라이트 애니메이션

여러 프레임으로 구성된 스프라이트 애니메이션을 구현해보자.

[code lang="markup"]<canvas id="myCanvas5" width="480" height="270" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var myGamePiece;
var myGameArea = {
canvas: document.getElementById("myCanvas5"),
start: function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
this.frameNo = 0;
this.interval = setInterval(updateGameArea, 20);
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.frameIndex = 0;
this.tickCount = 0;
this.ticksPerFrame = 10;
this.numberOfFrames = 4;
if (type == "sprite") {
this.image = new Image();
this.image.src = color;
this.frameWidth = this.width / this.numberOfFrames;
}
this.update = function() {
ctx = myGameArea.context;
if (this.type == "sprite") {
this.tickCount += 1;
if (this.tickCount > this.ticksPerFrame) {
this.tickCount = 0;
if (this.frameIndex < this.numberOfFrames - 1) { this.frameIndex += 1; } else { this.frameIndex = 0; } } ctx.drawImage( this.image, this.frameIndex * this.frameWidth, 0, this.frameWidth, this.height, this.x, this.y, this.frameWidth, this.height ); } else { ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } } this.newPos = function() { this.x += this.speedX; this.y += this.speedY; } } function startGame() { myGamePiece = new component(200, 50, "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjUwIiB2aWV3Qm94PSIwIDAgMjAwIDUwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cmVjdCB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIGZpbGw9IiNGRjAwMDAiLz4KPHJlY3QgeD0iNTAiIHdpZHRoPSI1MCIgaGVpZ2h0PSI1MCIgZmlsbD0iIzAwRkYwMCIvPgo8cmVjdCB4PSIxMDAiIHdpZHRoPSI1MCIgaGVpZ2h0PSI1MCIgZmlsbD0iIzAwMDBGRiIvPgo8cmVjdCB4PSIxNTAiIHdpZHRoPSI1MCIgaGVpZ2h0PSI1MCIgZmlsbD0iI0ZGRkYwMCIvPgo8L3N2Zz4K", 140, 110, "sprite"); myGameArea.start(); } function updateGameArea() { myGameArea.clear(); myGameArea.frameNo += 1; myGamePiece.update(); } startGame(); </script>[/code]

스프라이트 시트에서 각 프레임을 순차적으로 표시하여 애니메이션 효과를 만든다. tickCount와 ticksPerFrame을 사용하여 애니메이션 속도를 조절한다.

이미지 회전

이미지를 회전시키는 효과를 구현해보자.

[code lang="markup"]<canvas id="myCanvas6" width="480" height="270" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var myGamePiece;
var myGameArea = {
canvas: document.getElementById("myCanvas6"),
start: function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
this.interval = setInterval(updateGameArea, 20);
window.addEventListener('keydown', function (e) {
myGameArea.key = e.keyCode;
})
window.addEventListener('keyup', function (e) {
myGameArea.key = false;
})
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.angle = 0;
if (type == "image") {
this.image = new Image();
this.image.src = color;
}
this.update = function() {
ctx = myGameArea.context;
if (this.type == "image") {
ctx.save();
ctx.translate(this.x + this.width/2, this.y + this.height/2);
ctx.rotate(this.angle);
ctx.drawImage(this.image, -this.width/2, -this.height/2, this.width, this.height);
ctx.restore();
} else {
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
}
function startGame() {
myGamePiece = new component(50, 50, "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIHZpZXdCb3g9IjAgMCA1MCA1MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBvbHlnb24gcG9pbnRzPSIyNSw1IDQ1LDQwIDUsNDAiIGZpbGw9IiNGRjAwMDAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIyIi8+CjwvZXZnPgo=", 215, 110, "image");
myGameArea.start();
}
function updateGameArea() {
myGameArea.clear();
myGamePiece.speedX = 0;
myGamePiece.speedY = 0;
myGamePiece.angle = 0;
if (myGameArea.key && myGameArea.key == 37) {
myGamePiece.speedX = -2;
myGamePiece.angle = -Math.PI / 2;
}
if (myGameArea.key && myGameArea.key == 39) {
myGamePiece.speedX = 2;
myGamePiece.angle = Math.PI / 2;
}
if (myGameArea.key && myGameArea.key == 38) {
myGamePiece.speedY = -2;
myGamePiece.angle = 0;
}
if (myGameArea.key && myGameArea.key == 40) {
myGamePiece.speedY = 2;
myGamePiece.angle = Math.PI;
}
myGamePiece.newPos();
myGamePiece.update();
}
startGame();
</script>

save()와 restore()를 사용하여 변환 상태를 관리하고, translate()와 rotate()로 이미지를 회전시킨다. 이동 방향에 따라 이미지가 회전한다.

이미지 크기 조절

게임 중에 이미지 크기를 동적으로 변경하는 효과를 구현해보자.

<canvas id="myCanvas7" width="480" height="270" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var myGamePiece;
var myGameArea = {
canvas: document.getElementById("myCanvas7"),
start: function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
this.frameNo = 0;
this.interval = setInterval(updateGameArea, 20);
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component(width, height, color, x, y, type) {
this.type = type;
this.originalWidth = width;
this.originalHeight = height;
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.scale = 1;
this.scaleDirection = 1;
if (type == "image") {
this.image = new Image();
this.image.src = color;
}
this.update = function() {
ctx = myGameArea.context;
if (this.type == "image") {
this.scale += this.scaleDirection * 0.01;
if (this.scale >= 1.5 || this.scale <= 0.5) { this.scaleDirection *= -1; } this.width = this.originalWidth * this.scale; this.height = this.originalHeight * this.scale; ctx.drawImage(this.image, this.x, this.y, this.width, this.height); } else { ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } } this.newPos = function() { this.x += this.speedX; this.y += this.speedY; } } function startGame() { myGamePiece = new component(60, 60, "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHZpZXdCb3g9IjAgMCA2MCA2MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHN0YXIgcG9pbnRzPSIzMCw1IDM3LDIwIDU1LDIwIDQxLDMxIDQ4LDQ2IDMwLDM3IDEyLDQ2IDE5LDMxIDUsMjAgMjMsMjAiIGZpbGw9IiNGRkQ3MDAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIyIi8+Cjwvc3ZnPgo=", 210, 105, "image"); myGameArea.start(); } function updateGameArea() { myGameArea.clear(); myGameArea.frameNo += 1; myGamePiece.speedX = 1; myGamePiece.newPos(); myGamePiece.update(); } startGame(); </script>[/code]

scale 속성을 사용하여 이미지 크기를 주기적으로 변경한다. 원본 크기를 기준으로 0.5배에서 1.5배까지 크기가 변한다.

이미지 투명도 효과

이미지의 투명도를 조절하는 효과를 구현해보자.

[code lang="markup"]<canvas id="myCanvas8" width="480" height="270" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var myGamePiece;
var myObstacle;
var myGameArea = {
canvas: document.getElementById("myCanvas8"),
start: function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
this.frameNo = 0;
this.interval = setInterval(updateGameArea, 20);
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.alpha = 1;
this.alphaDirection = -1;
if (type == "image") {
this.image = new Image();
this.image.src = color;
}
this.update = function() {
ctx = myGameArea.context;
if (this.type == "image") {
this.alpha += this.alphaDirection * 0.02;
if (this.alpha <= 0.3 || this.alpha >= 1) {
this.alphaDirection *= -1;
}
ctx.save();
ctx.globalAlpha = this.alpha;
ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
ctx.restore();
} else {
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
}
function startGame() {
myGamePiece = new component(50, 50, "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIHZpZXdCb3g9IjAgMCA1MCA1MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGNpcmNsZSBjeD0iMjUiIGN5PSIyNSIgcj0iMjMiIGZpbGw9IiMwMEZGMDAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSI0Ii8+CjwvZXZnPgo=", 50, 110, "image");
myObstacle = new component(30, 150, "red", 300, 60);
myGameArea.start();
}
function updateGameArea() {
myGameArea.clear();
myGameArea.frameNo += 1;
myObstacle.speedX = -2;
myObstacle.newPos();
myObstacle.update();
myGamePiece.speedX = 1;
myGamePiece.newPos();
myGamePiece.update();
}
startGame();
</script>

globalAlpha 속성을 사용하여 이미지의 투명도를 조절한다. 투명도가 주기적으로 변하여 깜빡이는 효과를 만든다.

💡 게임 이미지 활용 팁:
• 이미지는 게임의 시각적 품질을 크게 향상시키지만 로딩 시간도 고려해야 한다
• 스프라이트 시트를 사용하면 HTTP 요청 수를 줄이고 애니메이션을 효율적으로 관리할 수 있다
• Base64 인코딩된 이미지는 작은 아이콘이나 간단한 그래픽에 유용하다
• 이미지 변환(회전, 크기 조절, 투명도)은 성능에 영향을 줄 수 있으므로 적절히 사용하자

이미지 충돌 감지

이미지 컴포넌트 간의 충돌 감지를 구현해보자.

<canvas id="myCanvas9" width="480" height="270" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var myGamePiece;
var myObstacle;
var myGameArea = {
canvas: document.getElementById("myCanvas9"),
start: function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
this.interval = setInterval(updateGameArea, 20);
window.addEventListener('keydown', function (e) {
myGameArea.key = e.keyCode;
})
window.addEventListener('keyup', function (e) {
myGameArea.key = false;
})
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
stop: function() {
clearInterval(this.interval);
}
}
function component(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
if (type == "image") {
this.image = new Image();
this.image.src = color;
}
this.update = function() {
ctx = myGameArea.context;
if (this.type == "image") {
ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
} else {
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
this.crashWith = function(otherobj) {
var myleft = this.x;
var myright = this.x + (this.width);
var mytop = this.y;
var mybottom = this.y + (this.height);
var otherleft = otherobj.x;
var otherright = otherobj.x + (otherobj.width);
var othertop = otherobj.y;
var otherbottom = otherobj.y + (otherobj.height);
var crash = true;
if ((mybottom < othertop) || (mytop > otherbottom) || (myright < otherleft) || (myleft > otherright)) {
crash = false;
}
return crash;
}
}
function startGame() {
myGamePiece = new component(40, 40, "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGNpcmNsZSBjeD0iMjAiIGN5PSIyMCIgcj0iMTgiIGZpbGw9IiMwMEZGMDAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSI0Ii8+CjwvZXZnPgo=", 10, 115, "image");
myObstacle = new component(40, 40, "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjRkYwMDAwIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iNCIvPgo8L3N2Zz4K", 300, 115, "image");
myGameArea.start();
}
function updateGameArea() {
if (myGamePiece.crashWith(myObstacle)) {
myGameArea.stop();
alert("게임 오버!");
} else {
myGameArea.clear();
myObstacle.speedX = -2;
myObstacle.newPos();
myObstacle.update();
myGamePiece.speedX = 0;
myGamePiece.speedY = 0;
if (myGameArea.key && myGameArea.key == 37) {myGamePiece.speedX = -2; }
if (myGameArea.key && myGameArea.key == 39) {myGamePiece.speedX = 2; }
if (myGameArea.key && myGameArea.key == 38) {myGamePiece.speedY = -2; }
if (myGameArea.key && myGameArea.key == 40) {myGamePiece.speedY = 2; }
myGamePiece.newPos();
myGamePiece.update();
}
}
startGame();
</script>

이미지 컴포넌트도 일반 컴포넌트와 동일한 방식으로 충돌 감지가 가능하다. 녹색 원과 빨간 사각형이 충돌하면 게임이 종료된다.

HTML5 Canvas 게임에서 이미지를 활용하면 게임의 시각적 품질을 크게 향상시킬 수 있다. 기본적인 이미지 표시부터 복잡한 애니메이션과 효과까지 다양한 기법을 통해 매력적인 게임을 만들 수 있다.

참고
Mingg`s Diary
밍구
공부 목적 블로그