리듬킹1(개인 프로젝트)
아래 코드를 이용해 설명문 이미지 및 게임화면을 보여준다.
rythmking.jsp
...
<body>
...
<div id='body-content'>
<div id="canvas-container" style="text-align:center">
<table style="border-right:hidden; border-left:hidden; border-top:hidden;
border-bottom:hidden; margin-left:auto; margin-right:auto;">
<tr>
<td>
<img src='shared/h_t_p/h_t_p_r.png', width="700" height="700">
</td>
<td>
<canvas id='menu' width='565' height='810' style='display: inline;'>
Canvas not supported
</canvas>
</td>
</tr>
</table>
</div>
</div>
<script id ="game" type="module" src='Menu17.js' ></script>
...
</body>
Menu17.js
var canvas = document.getElementById('menu'),
context = canvas.getContext('2d', { willReadFrequently: true }),
...
menu_image = new Image(),
...
menu_image.src = 'shared/images/selecting_menu_1.png';
menu_image.onload = function()
{
showing_menu(true);
}
...
selecting_menu_1.png이미지 사진
페이지에서 조작을 위한 버튼들을 만들어 준다.
Menu17.js
...
//cur_status값에 따른 상태 표시
//0 => menu, 1=> playing, 2=> game over, 3=> result
cur_status,
...
C_P_MODE,
start_button = new Image(),
challenge = new Image(),
practice = new Image(),
up = new Image(),
down = new Image(),
...
start_button.src = 'shared/images/Start_button.png';
challenge.src = 'shared/images/Challenge mode_button.png';
practice.src = 'shared/images/Practice mode_button.png';
up.src = 'shared/images/up.png';
down.src = 'shared/images/down.png';
...
function showing_menu(begining)
{
pic_path = pic_list[cur_num+(cur_page-1)*8];
pic.src = pic_path;
context.drawImage(menu_image,0,0,565,810);
//맨처음 실행시
if(begining)
{
start_button.onload = function()
{
context.drawImage(start_button,270,700,240,100);
}
challenge.onload = function()
{
context.drawImage(challenge,10,690,240,50);
}
practice.onload = function()
{
context.drawImage(practice,10,750,240,50);
context.drawImage(up,510,260,40,40);
context.drawImage(down,510,640,40,40);
cur_status = 0;
}
}
else
{
...
}
//challenge, practice모드 중 선택된걸 노란색 테두리를 이용해 표시한다.
context.save();
context.strokeStyle = "yellow"
context.lineWidth = 5;
context.strokeRect(5,687,250,55);
context.restore();
context.save();
context.strokeStyle = "black"
context.lineWidth = 5;
context.strokeRect(5,747,250,55);
context.restore();
//C_P_MODE가 0 => challnege 모드
//C_P_MODE가 1 => practice 모드
C_P_MODE = 0;
...
}
...
Menu17.js
...
pic = new Image(),
...
cur_page = 1,
cur_num = 0,
...
pic_list = ["shared/images/Beethoven Virus.png",
"shared/images/Beethoven Virus.png",
"shared/images/Fantaisie.png",
"shared/images/Fantaisie.png",
"shared/images/piano concerto1.png",
"shared/images/piano concerto1.png",
"shared/images/Swan:Black.png",
"shared/images/Swan:Black.png",
"shared/images/Swan:White.png",
"shared/images/Swan:White.png",
"shared/images/Flight_of_the bumblebee.png",
"shared/images/Flight_of_the bumblebee.png",
"shared/images/toccata and fuga.png",
"shared/images/toccata and fuga.png",
];
...
function showing_menu(begining)
{
pic_path = pic_list[cur_num+(cur_page-1)*8];
pic.src = pic_path;
...
//곡에 해당하는 이미지를 보여준다.
pic.onload = function()
{
context.drawImage(pic,175,30,215,190);
}
context.save();
context.fillStyle = "white"
context.font = "30px NotoKR";
//현제 페이지의 곡 리스트를 보여준다.
for(var i=0; i<8; i++)
{
if(song_list[i+(cur_page-1)*8] == undefined)
{
break;
}
//선택된 곡은 배경은 하얗게, 글자는 검게 만들어 준다.
if(i == cur_num)
{
context.save();
context.fillStyle = "white"
context.fillRect(30, (280+i*50), 465, 30);
context.fillStyle = "black"
context.fillText(song_list[i+(cur_page-1)*8],35,(305+i*50));
context.restore();
}
else
{
context.fillText(song_list[i+(cur_page-1)*8],35,(305+i*50));
}
}
context.restore();
}
...
Challange Mode, Practice Mode버튼에 마우스를 가져가면 포인터가 손가락 모양으로 바뀌고, 버튼의 크기도 작게 표현해 준다.
Menu17.js
...
//canvas안에서 마우스를 움직였을 때 이벤트들이 발생한다.
canvas.addEventListener("mousemove" , function (e)
{
X_loc=e.offsetX;
Y_loc=e.offsetY;
context.canvas.style.cursor = "auto";
/*
이전 커서 위치에 따른 prev_button의 값
challenge => prev_button = 0
practice => prev_button = 1
start => prev_button = 2
up => prev_button = 3
down => prev_button = 4
retry = > prev_button = 5
quit => prev_button = 6
이전에 커서의 위치가 위의 7개 버튼에 없었던 경우
prev_button값은 -1이다.
*/
//cur_status값에 따른 상태 표시
//0=>menu, 1=>playying, 2=>gameover, 3=> result
if(cur_status == 0)
{
if(10 <= X_loc
&& X_loc <=250)
{
//Challange Mode버튼에 커서 위치(아직 클릭전)
if(690 <= Y_loc && Y_loc <= 740 )
{
context.save();
context.fillStyle = "black"
context.fillRect(10,690,240,50);
context.restore();
//커서 위치전보다 작게 Challange Mode버튼을 그려준다.
context.drawImage(challenge,15,695,230,40);
context.canvas.style.cursor = "pointer";
prev_button = 0;
}
//Practice Mode버튼에 커서 위치(아직 클릭전)
else if(750 <= Y_loc && Y_loc <= 800 )
{
context.save();
context.fillStyle = "black"
context.fillRect(10,750,240,50);
context.restore();
//커서 위치전보다 작게 Practice Mode버튼을 그려준다.
context.drawImage(practice,15,755,230,40);
context.canvas.style.cursor = "pointer";
prev_button = 1;
}
}
...
}
...
}
현재 마우스 커서가 Practice Mode버튼 위에 올려져 있는 상태다. 자세히 보면 Challenge Mode버튼보다, Practice Mode버튼이 작다느것을 알 수 있다.
아래 코드를 통해 Challange Mode, Practice Mode버튼을 클릭시 수행할 작업(노란색 테두리 위치 변경 및 클릭음 재생)들을 정의해준다.
Menu17.js
...
canvas.addEventListener('mousedown', function(e)
{
X_loc=e.offsetX;
Y_loc=e.offsetY;
if(cur_status == 0)
{
//challeng, practice mode
if(10 <= X_loc
&& X_loc <=250)
{
//challenge mode선택
if(690 <= Y_loc && Y_loc <= 740)
{
context.save();
context.strokeStyle = "yellow"
context.lineWidth = 5;
context.strokeRect(5,687,250,55);
context.restore();
context.save();
context.strokeStyle = "black"
context.lineWidth = 5;
context.strokeRect(5,747,250,55);
context.restore();
context.save();
context.fillStyle = "black"
context.fillRect(10,690,240,50);
context.restore();
if(prev_button == 0)
{
context.drawImage(challenge,15,695,230,40);
}
else
{
context.drawImage(challenge,10,690,240,50);
}
C_P_MODE = 0;
reacting_sound();
}
//practice mode선택
else if(750 <= Y_loc && Y_loc <= 800 )
{
context.save();
context.strokeStyle = "black"
context.lineWidth = 5;
context.strokeRect(5,687,250,55);
context.restore();
context.save();
context.strokeStyle = "yellow"
context.lineWidth = 5;
context.strokeRect(5,747,250,55);
context.restore();
context.save();
context.fillStyle = "black"
context.fillRect(10,750,240,50);
context.restore();
if(prev_button == 1)
{
context.drawImage(practice,15,755,230,40);
}
else
{
context.drawImage(practice,10,750,240,50);
}
C_P_MODE = 1;
reacting_sound();
}
}
...
}
...
}
...
Menu17.js
...
click_sounds = [],
...
// 10개의 Audio객체를 배열에 담아둔다.
// 버튼을 빠르게 연타할때 클릭소리를 내기위해선 여러개의 오디오 객체가 있어야 한다.
for(let i = 0; i < 10; i++)
{
var click_sound = new Audio();
click_sound.src = 'sound/click_audio.mp4';
click_sounds.push(click_sound);
...
}
...
//Challange Mode, Practice Mode, Retry버튼 및 곡 제목 클릭시 소리 재생
function reacting_sound()
{
for(let i = 0; i < click_sounds.length; i++)
{
if(click_sounds[i].paused)
{
//재생중이 아닌 Audio객체를 찾아서 1회만 재생한다.
click_sounds[i].play();
break;
}
}
}
...
다른 곡을 선택하고 싶다면 키보드의 상,하 버튼을 누르거나 원하는 곡에 마우스 커서를 가져다가 클릭하면 된다
Menu17.js
...
pic = new Image(),
...
cur_page = 1,
cur_num = 0,
...
pic_list = ["shared/images/Beethoven Virus.png",
"shared/images/Beethoven Virus.png",
"shared/images/Fantaisie.png",
"shared/images/Fantaisie.png",
"shared/images/piano concerto1.png",
"shared/images/piano concerto1.png",
"shared/images/Swan:Black.png",
"shared/images/Swan:Black.png",
"shared/images/Swan:White.png",
"shared/images/Swan:White.png",
"shared/images/Flight_of_the bumblebee.png",
"shared/images/Flight_of_the bumblebee.png",
"shared/images/toccata and fuga.png",
"shared/images/toccata and fuga.png",
];
...
//키눌림 감지
window.addEventListener('keydown', function(e)
{
if(cur_status == 0)
{
//Arrow Up => 38
//Arrow Down => 40
if(e.key == 38 || e.keyCode == 38)
{
div = cur_num - 1;
//이전 페이지에서 마지막 곡 선택
if(div == -1)
{
if(cur_page > 1)
{
cur_page = cur_page - 1;
cur_num = 7;
shifting_sound();
page_move(cur_page, cur_num);
}
}
//현재 페이지에서 이전곡 선택
else
{
reacting_sound();
selecting_song();
}
}
...
}
...
}
...
canvas.addEventListener('mousedown', function(e)
{
X_loc=e.offsetX;
Y_loc=e.offsetY;
if(cur_status == 0)
{
...
//곡선택
if(280 <= Y_loc
&& Y_loc<= 660)
{
if(25 <= X_loc
&& X_loc <=510)
{
div = Math.floor((Y_loc-280)/50);
reacting_sound(); //=>바로 위의 코드 보자
selecting_song();
}
}
...
}
...
}
...
//Challange Mode, Practice Mode, Retry버튼 및 곡 제목 클릭시 소리 재생
function reacting_sound()
{
for(let i = 0; i < click_sounds.length; i++)
{
if(click_sounds[i].paused)
{
click_sounds[i].play();
break;
}
}
}
...
//곡이 선택된 것을 나타내는 함수
function selecting_song()
{
//한페이지 보여질 곡이 8개 이하인 경우를 위해 아래의 조건문을 이요한다.
if(song_list[div+(cur_page-1)*8] != undefined)
{
//이전에 선택된 곡의 배경을 검게, 글짜는 희게 표현한다.
context.save();
context.fillStyle = "black"
context.fillRect(30, (280+cur_num*50),465,30);
context.fillStyle = "white"
context.font = "30px NotoKR";
context.fillText(song_list[cur_num+(cur_page-1)*8],35,(305+cur_num*50));
context.restore();
//새로이 선택된 곡의 배경을 희게, 글짜는 검게 표현한다.
context.save();
context.fillStyle = "white"
context.fillRect(30, (280+div*50), 465, 30);
context.fillStyle = "black"
context.font = "30px NotoKR";
context.fillText(song_list[div+(cur_page-1)*8],35,(305+div*50));
context.restore();
//현재 페이지에서의 순서를 갱신한다.
cur_num = div;
pic_path = pic_list[cur_num+(cur_page-1)*8];
pic.src = pic_path;
pic.onload = function()
{
context.drawImage(pic,175,30,215,190);
}
}
}
...
상하 화살표 클릭하면 다음페이지에 있는 곡들을 볼 수 있다. 이전에 버튼들과 마찬가지로, 마우스가 상하 화살표에 위치하면 버튼 크기가 작아지고, 커서가 손가락 모양으로 변한다.
Menu17.js
...
shift_sounds = [],
...
// 10개의 Audio객체를 배열에 담아둔다.
// 버튼을 빠르게 연타할때 소리를 내기위해선 여러개의 오디오 객체가 있어야 한다.
for(let i = 0; i < 10; i++)
{
...
var shift_sound = new Audio();
shift_sound.src = 'sound/shift_audio.mp4';
shift_sounds.push(shift_sound);
}
...
//song_list는 따로 정의해둔 값이다. 뒤에서 자세히 다룬다.
max_page_n = Math.floor((song_list.length) / 8);
if(song_list.length % 8 >0)
{
max_page_n +=1;
}
...
//위,아랫방향 화살표 누를때 재생된다.
function shifting_sound()
{
for(let i = 0; i < shift_sounds.length; i++)
{
if(shift_sounds[i].paused)
{
// 재생중이 아닌 Audio객체를 찾아서 1회만 재생한다.
shift_sounds[i].play();
break;
}
}
}
...
//현재 페이지에 해당하는 곡을 표시한다.
function song_list_writer()
{
context.save();
context.fillStyle = "white"
context.font = "30px NotoKR";
for(var i=0; i<8; i++)
{
if(song_list[i+(cur_page-1)*8] == undefined)
{
break;
}
if(i == cur_num)
{
context.save();
context.fillStyle = "white"
context.fillRect(30, (280+i*50), 465, 30);
context.fillStyle = "black"
context.fillText(song_list[i+(cur_page-1)*8],35,(305+i*50));
context.restore();
}
else
{
context.fillText(song_list[i+(cur_page-1)*8],35,(305+i*50));
}
}
context.restore();
}
//페이지 이동시 실행된다.
function page_move(c_p, c_n)
{
context.save();
context.fillStyle = "black";
//25 250 485 430
context.fillRect(30,260,465,410);
context.restore();
song_list_writer();
pic_path = pic_list[c_n+(c_p-1)*8];
pic.src = pic_path;
pic.onload = function()
{
context.drawImage(pic,175,30,215,190);
}
}
//캔버스에서 마우스 누르는것 감지
canvas.addEventListener('mousedown', function(e)
{
X_loc=e.offsetX;
Y_loc=e.offsetY;
if(cur_status == 0)
{
...
//화살표
if(510 <= X_loc
&& X_loc <=550)
{
//윗방향 화살표
if(260 <= Y_loc && Y_loc <= 300)
{
context.save();
context.fillStyle = "black"
context.fillRect(510,260,40,300);
context.restore();
if(prev_button == 3)
{
context.drawImage(up,515,265,30,30);
}
else
{
context.drawImage(up,510,260,40,40);
}
if(cur_page > 1)
{
cur_page = cur_page - 1;
cur_num = 0;
shifting_sound();
page_move(cur_page, cur_num);
}
}
//아랫방향 화살표
else if(640 <= Y_loc && Y_loc <= 680)
{
context.save();
context.fillStyle = "black"
context.fillRect(510, 640, 40,40);
context.restore();
if(prev_button == 4)
{
context.drawImage(down,515,645,30,30);
}
else
{
context.drawImage(down,510,640,40,40);
}
if(cur_page < max_page_n)
{
cur_page = cur_page + 1;
cur_num = 0;
shifting_sound();
page_move(cur_page, cur_num);
}
}
}
...
}
...
}
////canvas안에서 마우스를 움직였을 때 이벤트들이 발생한다.
canvas.addEventListener("mousemove" , function (e)
{
X_loc=e.offsetX;
Y_loc=e.offsetY;
context.canvas.style.cursor = "auto";
/*
이전 커서 위치에 따른 prev_button의 값
challenge => prev_button = 0
practice => prev_button = 1
start => prev_button = 2
up => prev_button = 3
down => prev_button = 4
retry = > prev_button = 5
quit => prev_button = 6
이전에 커서위 위치가 위의 7개 버튼에 없었던 경우
prev_button값은 -1이다.
*/
...
prev_button = -1;
//context.canvas.style.cursor = "pointer";
//=> 마우스 커서를 화살표가 아닌 손가락 모양으로 바꾼다.
if(cur_status == 0)
{
...
//화살표
if(510 <= X_loc
&& X_loc <=550)
{
//윗방향 화살표
if(260 <= Y_loc && Y_loc <= 300)
{
context.save();
context.fillStyle = "black"
context.fillRect(510,260,40,300);
context.restore();
context.drawImage(up,515,265,30,30);
context.canvas.style.cursor = "pointer";
prev_button = 3;
}
//아랫방향 화살표
else if(640 <= Y_loc && Y_loc <= 680)
{
context.save();
context.fillStyle = "black"
context.fillRect(510,640,40,40);
context.restore();
context.drawImage(down,515,645,30,30);
context.canvas.style.cursor = "pointer";
prev_button = 4;
}
}
...
}
...
});
...
댓글남기기