오늘은 오후에 만들 게임을 위해 어제 마지막에 만들었던 이벤트 함수로 시작해서 여러가지 다양한 함수를 다루었다.
■ 본격적으로 토끼 슈팅 게임 만들기 시작! (엉망진창이었다고 한다!)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RabbitShoot.html</title>
<style>
canvas{
border:1px solid green;
}
</style>
</head>
<body>
<canvas width="800" height="500" id="myCanvas"></canvas>
<script>
let canvas=document.querySelector("#myCanvas");
//canvas 요소에 그림을 그릴 수 있는 도구의 참조값얻어오기
let context=canvas.getContext("2d");
//스나이퍼 이미지 로딩하기
var snipeImg=new Image();
snipeImg.src="images/snipe.png";
//스나이프 이미지의 초기 좌표
let snipeX=400;
let snipeY=250;
//배경이미지 로딩
let backImg= new Image();
backImg.src="images/background.jpg";
//효과음 로딩
let fireSound=new Audio("sounds/fire.wav");
let screamSound=new Audio("sounds/birddie.mp3");
// 총알 구멍 이미지 로딩
let holeImg=new Image();
holeImg.src="Images/hole.png";
/*총알 구멍의 임시 좌표를 확인하여 조준경과 일치 시키기 위한 임시 좌표)
let holeX=400;
let holeY=250; */
//총알 구멍의 정보를 누적시킬 배열 준비하기
let holes = [];
//토끼 이미지 2개를 로딩해서 배열에 담아두기
let rabbitImg1=new Image();
rabbitImg1.src="images/rabbit_1.png";
let rabbitImg2=new Image();
rabbitImg2.src="images/rabbit2.png";
let rabbitImgs= [rabbitImg1, rabbitImg2];
//파편 이미지를 저장할 배열
let fragmentImgs = [];
//토끼 파편 이미지
for(let i=0; i<5; i++){
let tmp = new Image();
tmp.src="images/r"+i+".png";
fragmentImgs.push(tmp);
}
//토끼 파편 하나하나의 정보(object)를 저장할 배열
let fragments=[];
/*//토끼 파편이미지 로딩하기 위에 세줄짜리랑 같은거임
let r0=new Image();
let r1=new Image();
let r2=new Image();
let r3=new Image();
let r4=new Image();
r0.src="images/r0.png";
r1.src="images/r1.png";
r2.src="images/r2.png";
r3.src="images/r3.png";
r4.src="images/r4.png";
//배열에 이미지 객체의 참조값 저장하기
let fragmentImgs=[r0, r1, r2, r3, r4];
*/
//토끼의 초기 좌표
let rabbitX=400;
let rabbitY=250;
//토끼 이미지 인덱스를 담을 변수 선언하고 초기값 0 대입하기
let rabbitIndex=0;
//화면이 다시 그려지는 횟수를 카운트할 변수
let count=0;
let dead = 0;
context.font="30px consolas";
context.fillStyle = "yellow";
//초당 100번 호출되는 함수 등록
setInterval(function(){
//4각형 영역을 설정해서 canvas를 지우기
//context.clearRect(0,0,800,500); -> 이건 배경을 클리어하는 명령어인데 이 명령어를 지운거는 배경 이미지를 계속 주기적으로 연산하기 때문에
//canvas의 정중앙에 테스트로 snipe 이미지를 그려보기(좌표 숫자 2개 크기 숫자 2개)
//context로 이미지 위치를 정할 때는 기준이 이미지의 좌 상단의 좌표라서 이미지의 폭과 높이의 반만큼 빼줘야 함
//배경 이미지를 cavas 크기에 맞게 그리기
context.drawImage(backImg, 0, 0, 800, 500);
/*context.drawImage(holeImg, holeX-10, holeY-10, 20, 20) 총알 구멍 이미지 1개씩 만 그릴 때*/
for(let i=0; i<holes.length; i++){
//총알 구멍의 정보를 담고 있는 object를 불러온다.
let tmp=holes[i];
context.drawImage(holeImg, tmp.x-10, tmp.y-10, 20,20);
};
//토끼 파편 그리기
for(let i=0; i<fragments.length; i++){
//토끼 파편의 정보를 담고 있는 i번째 object를 불러온다.
let tmp=fragments[i];
context.drawImage(fragmentImgs[tmp.type], tmp.x-50, tmp.y-50, 100,100);
}
//토끼 파편 움직이기
for(let i=0; i<fragments.length; i++){
//토끼 파편의 정보를 담고 있는 i번째 object를 불러온다.
let tmp=fragments[i];
//speedX. speedY 값 만큼 x,y 좌표를 변경하기
tmp.x = tmp.x + tmp.speedX;
tmp.y = tmp.y+ tmp.speedY;
}
//반복문을 역순으로 돌면서 배열에서 제거할 파편 객체는 제거하기
for(let i=fragments.length-1 ; i>=0; i--){
//위에 줄은 i번째 파편 객체를 불러내서
let tmp = fragments[i];
//제거할지 여부를 알아내서
let isOut = tmp.x<-50 ||
tmp.y<-50 ||
tmp.y>550 ||
tmp.y>850;
//만일 제거해야 한다면 제거한다.
if(isOut){
//i번째 인덱스에 저장된 object를 fragments 배열에서 제거하기
fragments.splice(i,1);
}
};
//토끼 이미지 그리기
context.drawImage(rabbitImgs[rabbitIndex],rabbitX-50, rabbitY-50, 100,100);
count++; // 1초에 100씩 증가, 화면을 1초에 100번 세니까 //초당 100번 실행
//초당 10번만 실행 = 10의 배수에서만 실행
if(count%10==0){
//인덱스 증가 시키기
rabbitIndex=rabbitIndex+1;
//만일 존재하는 인덱스가 아니라면
if(rabbitIndex==2){
//다시 0번 인덱스로 변경한다.
rabbitIndex=0;
}
/* 나의 시도는 망했다
if(rabbitIndex=0){
context.drawImage(rabbitImgs[rabbitIndex],rabbitX-50, rabbitY-50, 100,100);
rabbitIndex=rabbitIndex+1;
}else{rabbitIndex=1;
context.drawImage(rabbitImgs[rabbitIndex],rabbitX-50, rabbitY-50, 100,100);
rabbitIndex=0;
}
*/
}
if(count%100 == 0){
//토끼를 랜덤한 위치로 이동시킨다
rabbitX = Math.random()*800;
rabbitY = Math.random()*500;
};
//점수 출력하기(글자는 좌하단에 X좌표가 자동 배정됨)
context.fillText("Point:"+dead, 10,40);
//아래 코드는 조준경 이미지를 나타내는 코드이기 때문에
context.drawImage(snipeImg, snipeX-50, snipeY-50, 100, 100);
//로딩 시점에서 좌표를 계산을 한 다음에 실행되어야 하는게 맞다
}, 10);
//매개변수 e는 이름을 아무렇게나 지어도 된다
document.querySelector("#myCanvas").addEventListener("mousemove", function(e){
snipeX= e.offsetX;
snipeY= e.offsetY;
});
document.querySelector("#myCanvas").addEventListener("mousedown", function(e){
//강제로 재생 위치를 처음으로 변경한 다음
fireSound.currentTime=0;
//play를 하면 연속 재생이 가능하다
fireSound.play();
/* 총알 구멍 한개일 때 처음 좌표 열어 놓고
holeX=e.offsetX;
holeY=e.offsetY;이것도 열어 놔야 함*/
//총알의 위치를 object에 담기
let hole = {x:e.offsetX, y:e.offsetY};
//object를 배열에 누적 시키다.
holes.push(hole);
//토끼가 총에 맞았는지 여부를 알아내서
let isShooted = rabbitX-50<e.offsetX &&
rabbitX+50>e.offsetX &&
rabbitY-30<e.offsetY &&
rabbitY+50>e.offsetY;
//만일 토끼가 맞았다면? 필요한 동작을 실행한다.
if(isShooted){
screamSound.currentTime=0;
screamSound.play(); //비명지르기
dead++; //죽었을때 점수 올리기
//토끼 파편 5개 만들어서 fragments 배열에 누적 시키기
for (let i=0; i<5; i++){
//빈 object를 만들어서
let tmp = {};
//토끼의 현재 좌표를 파편의 초기 좌표로 부여한다
tmp.x=rabbitX;
tmp.y=rabbitY;
//파편의 속도를 random하게 부여한다(음수도 나올 수 있도록)
tmp.speedX= Math.random()*10 -5;
tmp.speedY= Math.random()*10 -5;
//파편의 type을 부여
tmp.type = i;
//fragments 배열에 누적시키기
fragments.push(tmp);
}
};
});
</script>
</body>
</html>
'공부의 기록 > 프리스쿨 : 수업내용정리' 카테고리의 다른 글
프리스쿨 (2일 오후/3일) (1) | 2024.11.13 |
---|---|
프리스쿨 (2일 오전/3일) (0) | 2024.11.13 |
프리스쿨 (1 일 오후/3일) (0) | 2024.11.12 |
프리스쿨 (1 일 오전/3일) (3) | 2024.11.12 |