I. INTRO : 프로젝트관련
차근차근 성장을 위해서 하자
II. 게임개발
1. 폭파시키기
폭파는 누가 과연해야하는가?
터지는건 적이 터지는데, 누가 해야하는가?
함수는 시키는 것이다. 터지다는 것 명령어를 함수로 한다.
enemy에 터지라고 할 때...
1) 충돌시 폭파 이미지 그리기
export default class Enemy{
constructor(x = 0, y = 0){
// this.img = document.querySelector("#enemy");
// this.imgEplo = document.querySelector("#exposion");
// this.x = x;
// this.y = y;
// this.speed = 3;
// //이 변수에 함수의 참조값이 들어갔는지
// this.onOutofScreen = null;
//충돌여부로판단
this.ischungdol = false;
// //48 64
// this.sw = this.img.width/2;
// this.sh = this.img.height/2;
// // console.log(this.img.width);
// //폭파(e) 인덱스(i) x,y값
// this.eix = 0;
// this.eiy = 0;
// //이미지의 너비 높이
// this.esw = this.imgEplo.width / 4;
// this.esh = this.imgEplo.height/5;
}
chungdol(){
this.ischungdol = true;
}
this.ischungdol 을 최초에 false를 해준다.
아래의 함수 호출 시 this.ischungdol 의 값이 true로 바뀌주게끔 한다.
<boy,js>
update(){
//3번
if(d < r1r2){
enemy.chungdol();
console.log("충돌발생");
}
}
그 충돌은 접촉됐을 때 실항하게끔한다.
2)
충돌했다고 하면, 특정함수 실행하는 (콜백)함수 호출
적기 배열 얻어서 지우기 VS 얘좀 지워줄래요? 원래는 canvas 가 하는게 맞음 callback으로...
그런데 구현의 용의성을 위해서 선을 넘겠다.
왜 선을 넘는것?
코드의 책임성 가지는 애가 책임지게 해서 문제 해결 시 책임자 찾아서 해야한다.
제 각각이하면 이 코드가 어디있는지 찾기 어렵게 된다.
(예 : 교통부 장관의 지령이 문제면 교통부 장관의 서류 다찾음)
내일 해보자
2. 새로운 도화지 그리기
(1) 새로운 캔버스 그리기
1)
<rank-canvas.js> 만들기!
export default class RankCanvas{
constructor(){
this.dom = document.querySelector(".rank-canvas");
this.dom.focus();
//이미 캔버스라서 dom으로 하자
/**@type {CanvasRenderingContext2D};*/
/** @type {WebGLRenderingContext} */
this.ctx = this.dom.getContext("2d");
}
run(){
this.update();
this.draw();
setTimeout(() => {
this.run();
}, 17);
}
update(){
}
draw(){
this.ctx.strokeRect(0,0,this.dom.width-1,this.dom.height-1);
// this.ctx.stroke(45, 335, 490, 80);
}
}
이렇게 해서 사각형이 전체 canvas에 나오게끔 해보자
2)
+html에 엘리먼트 추가
<body>
<!-- <input tabindex="0">
<img>
<div tabindex = "0">
test
</div>
<input tabindex= "0">
<input tabindex= "0"> -->
<img src="./image/enemy.png" id = "enemy" style="display: none;">
<img src="./image/boy.png " id = "boy" style="display: none;">
<img src="./image/map.png " id = "bg" style="display: none;">
<img src="./image/explosion.jpg" id =exposion style="display: none;">
<canvas tabindex="0" class="game-canvas" width="700" height="700"></canvas>
<canvas tabindex="1" class="rank-canvas" width="700" height="700" sy></canvas>
</body>
차이를 위해서 tapindex를 1로 해주자
3) app.js 에 import 하기!
import Gamecanvas from './panel/game-canvas.js';
import RankCanvas from './panel/rank-canvas.js';
import newlec from './newlec.js';
window.addEventListener("load",function(){
const gamecanvas = new Gamecanvas();
gamecanvas.run();
//스스로 다른것을 가져오는게 바로 안된다.
//html에 요구해야한다
const rankcanvas = new RankCanvas();
rankcanvas.run();
// newlec.x++;
// console.log("x : "+ newlec.x);
//다른곳도 2나오는지 3이나오는지 알오보기
// gamecanvas.pause();
});
import 를 하고
인스턴스를 만든 뒤에 run()을 해주자
(2) boy의 신호로 캔버스 바꿔보기
1)
캔버스 두개 가렸다가 보였다가 하려면 야매가 조금 필요하다
document 객체 조작은 플랫폼이기 때문에 이것을 다루는것을 하면 언어 공부가 조금 밀린다.
그래서 야매를 예외적으로 써보자
canvas가 바뀌는 것은 application즉 app.js가 해야한다
boy 관리하는 도구가 필요하면 canvas관리이고, 그 canvas 관리는 그 위 application이다.
소년이 갑자기 단계를 뛰어넘어서 canvas 바꾸라고 하는것은 이상하다
canvas가 하는 것은 끝났다고만 말하기이다. 이렇게 하는것을 위에다 알리는것은 event이고
아래로 하는것은 명령 service이다.
여기서 boy가 위로 알리기 위한 event로 해야한다.
소년은 게임오버를 하는 주체가 아니라 소년은 그냥 알리기만 하면된다.
-우리가 생각하는게 변수명, 함수명, 패키지명이 아키텍처인데, 아키텍처 때 젤어려운게 명명이다.
구조에 대한 depth를 잘 정의하는것도 중요하다.
2)
if(d < r1r2){
enemy.chungdol();
console.log("충돌발생");
if(this.onNoLife)
this.onNoLife();
}
onNoLife()를 호출해준다.
이 함수 작성은 아래에...
★ 예상컨데 this.onNolife 함수는 존재하기 때문에 true를 호출하는것으로 볼수있다
즉 본함수의 작동전에 null?인지 확인하는것이 아닐까?
3)
export default class Gamecanvas{ //생성자 만들기
constructor(){
this.dom = document.querySelector(".game-canvas");
this.dom.focus();
//이미 캔버스라서 dom으로 하자
/**@type {CanvasRenderingContext2D};*/
/** @type {WebGLRenderingContext} */
this.ctx = this.dom.getContext("2d");
//boy
this.boy = new Boy(100,100);
this.boy.onNoLife = this.boyNoLifeHandler.bind(this);
callback 함수 방식으로 boyNoLifeHandler에대한 onNolife가 위임권을 가진다.
그래서 boyNoLifeHandler를 호출할 수있다.
4)
boyNoLifeHandler(){
console.log("소년의 생명이 없습니다.");
//게임 종료를 의미하는 애니메이션 실행하거나
//게임종료 또는 게속 위한 입력을 받거나
//바로 캔버ㅡ 전환허간
//등등
}
호출되면 실행시킬 함수 boyNoLifeHandler
(3) 게임 계속할지 창 만들어보기
<confirmDlg.js> 파일을 만든다.
대화 상자 띄우는 법
1)
export default ConfirmDlg;
class ConfirmDlg{
constructor(){
this.width = 400;
this.height = 200;
this.isvisible = false;
//함수로서 한다
this.onContinue = false;
this.onEnd = false;
}
show(){
this.isvisible = true;
this.is
}
update(){
}
draw(ctx){
}
기본은 안보이게끔 한다.
2)
fillstyle는 한번 설정하면 다시 설정하기 이전까지 그 색을 계속 가지고 있는다.
<confirm.js>
draw(ctx){
if(!this.isvisible)
return;
//사각형 칠하기
ctx.fillStyle = "#FFF";
ctx.fillRect(100,100, this.width, this.height);
//경계선 칠하기
ctx.fillStyle = "#000";
ctx.StrokeRect(100,100, this.width, this.height);
}
본 조건은 isvisible 이 false이면, return으로 아래의 fill이 작동 안되게끔 되어있는것이다.
3)
<game-canvas.js>
export default class Gamecanvas{ //생성자 만들기
constructor(){
this.dlg = new ConfirmDlg();
this.dlg.show();
}}
여기에 import 하고, 생성자에 인스턴스를 만든뒤 show()함수를 작성한다
4)
draw(){ //boy의 draw를 호출하는 함수
// this.bg.draw(this.ctx);
// for(let enemy of this.enemies)
// enemy.draw(this.ctx);
// this.boy.draw(this.ctx); //다시그리고
this.dlg.draw(this.ctx);
}
this.dlg 인스턴스에 draw() 메소드를 실행한다.
5)
ctx.fillStyle 로 투명도(#FFF5)도 조정이 가능하다.
ctx.fillStyle = "#FFF5";
뽀개기로 x,y 값 설정가능하다.
왜냐하면 배열이 아니면 같은 key값으로 판단하기 때문이다.
draw(ctx){
if(!this.isvisible)
return;
let {x , y} = this;
//사각형 칠하기
ctx.fillStyle = "#FFF5";
ctx.fillRect(x,y, this.width, this.height);
//경계선 칠하기
ctx.fillStyle = "#000";
ctx.strokeRect(x,y, this.width, this.height);
}
6)
확인창을 두개 만들어보자
draw(ctx){
if(!this.isvisible)
return;
let {x , y} = this;
//사각형 칠하기
ctx.fillStyle = "#FFF5";
ctx.fillRect(x,y, this.width, this.height);
//경계선 칠하기
ctx.fillStyle = "#000";
ctx.strokeRect(x,y, this.width, this.height);
ctx.font = '48px serif';
ctx.fillText('continue', x+110, y+75);
//yes 상자
ctx.fillStyle = "red";
ctx.fillRect(x+ 30, y +120, this.width -250, this.height-150);
ctx.fillStyle = "black";
ctx.font = '48px serif';
ctx.fillText('yes', x+ 60, y +160);
//no 상자
ctx.fillStyle = "green";
ctx.fillRect(x+ 230 ,y +120, this.width -250, this.height-150);
ctx.fillStyle = "black";
ctx.font = '48px serif';
ctx.fillText('no', x+ 275, y +160);
}
이렇게 하면되지만 버튼이 반복되면
이경우 개체로 분리하는것이 좋을까? 아니면 쭉 그리는게 바람직할까?
후자의경우 버튼마다 크기및 위치 값을 다 가지고있어야한다. 박스에서 버튼을 누른다.
그런데 버튼이 눌린것인지 알아야한다. 현재 마우스 클릭 감지는 window인데 그거는 canvas뿐이다
이제부터 그 클릭위치가 누가 차지하고있는지 찾아야한다.
센서를 따로만들수없고 찾아야한다.
버블링생각해보자
클릭됐네 너 맞아? 찾으면 반응을 보이면된다.
dlg는 button 자식에게 물어본다.
최종에 있는애가 물어본다.
7)
<game-canvas.js>
// ------event 핸들러---------------
clickHandler(e){
this.boy.moveTo(e.x, e.y);
//e.x e.y 이벤트 발생한 x,y 좌표가 나온다.
//좌표 주면서 여기있냐고 물어보기.
// this.boy.islocate(e.x,e.y);
// for(let enemy of this.enemies){
// enemy.islocate(e.x,e.y);
// }
if(this.dlg.islocate(e.x,e.y));
}
여기에다가 boy , enemy, dlg에게 여기있는지 물어보는게 필요하다
만약 각 개체가 자식이 있으면 그 개체가 자기 자식에게 물어본다.
export default class Gamecanvas{ //생성자 만들기
constructor(){
this.bg = new Background(0,0);
this.dlg = new ConfirmDlg();
//다이알로그 클릭은 위임을 받음
this.dlg.onclick =()=>{
console.log("clicked");
}
}
여기서 dlg가 눌렸는지에 대해서 이야기 해주는 것이다.
브라우저는 윈도우로 부터 클릭받았다고 전달받음 -> 이후 브라우저는 누구를 클릭 했는지 알아내야한다
브라우저는 모든 놈들에게 다 통지함
특히 통지하는데 그 div가 자식 div 있으면 또 통지함
내 영역아니면 무시하고 나영역이면 하고, 내 자식이면 내가 수신하고 자식들에게 물어본다
자체적으로 통지받을수있음
이벤트 혹시 자신에게 연결되어있는지 확인하고 호출한다.
---
통지받으면 클릭됐구나 내가 어떤 이벤트해야겠구나 실행하게 해준다.
우리가 통지할것은 dlg만인데, 윈도우라면 모든놈들에게 통지해야한다.
1. 보충
2. 회고
1) 버블링의 필요성이 크다
서둘러서 배우고싶다 왜냐하면 yes , no 를 클릭하면 키가 안먹는것은 차치하더라도, 캐틱터가 클릭한 위치로 움직여진다.
2)하나의 기능을 추가할때마다 특정 조건,사건,이벤트가 발생했을 때 콜백함수를 계속적으로 하나를 만드는데, 이런방식의 객체지향프로그래밍에서 콜백함수는 참 많이 쓰이겠구나 싶다. 조금 더 사고해보면서 해보아야지!
3) 사소하지만 confirlm dialogue 띄우는것을 만들 때 x,y축 하나씩 픽셀조정해가면서 그리는게 예전부터 누구는 짜증난다고 했으나... 나는 생각보다 재밌다. 그래서 프론트다 나에게는 좋은것 같다.
'배움 __IL > TIL 1기' 카테고리의 다른 글
TIL : 35번째- 230116 [1-3-월] (0) | 2023.01.16 |
---|---|
TIL : 34번째- 230113 [1-2-금] (0) | 2023.01.13 |
TIL : 32번째- 230111 [1-2-수] (0) | 2023.01.11 |
TIL : 31번째- 230110 [1-2-화] (0) | 2023.01.10 |
TIL : 30번째- 230109 [1-2-월] (0) | 2023.01.09 |