I. 게임만들기
1. 적기관련
(1)움직이기
<Enemy.js>
update(){
this.y += this.speed;
// if(this.y == 700){
// this.y = 0;
// // this.x += 100;
// }
}
export default class Gamecanvas{ //생성자 만들기
constructor(){
//enemy
this.enemies = [new Enemy(10,0),new Enemy(30,0),new Enemy(300,0),new Enemy(500,0),new Enemy(556,0)
,new Enemy(800,10),new Enemy(700,20),new Enemy(60,0),new Enemy(300,30),new Enemy(700,0)];
}
update()함수에 적기의 y값을 조정해주어서 위에서 아래로 움직이게끔 한다.
composiotion 방식이다. Enemy 의 인스턴스가 처음부터 일체형으로 다 지정되어서 나온다.
이 경우 enemies 배열에 10개의 인스턴스를 만들어준다. (처음부터 다 지정해줌)
(2) onOutOfScreen : 적기 없어지기
1)
캐릭터 캔버스 밖에 나갔을 때 그냥 그대로 두면 메모리낭비 함
캔버스 밖에 나갔을 때 제거 하는 것이 필요함
스크린 밖에 가는 이벤트 발생시 특정함수 발생 시키기
적에게 스크린밖에 나간것을 자기가 감지할수 있게끔
영역 밖에 나간 것에 호출은 내가 아니라 캔버스가 하게한다.
인덱스 알때는 splice(), [https://mdlg.tistory.com/66}
인덱스 모를때는 스스로 찾아서 지우게, 불가능하다면 인덱스 알아내기
2)
<호출 전>
export default class Enemy{
constructor(x = 0, y = 0){
this.img = document.querySelector("#enemy");
console.log(this.img);
this.x = x;
this.y = y;
this.speed = 20;
//이 변수에 함수의 참조값이 들어갔는지
this.onOutofScreen = null;
//48 64
this.sw = 48;
this.sh = 64;
}
onOutofScreen 의 멤버변수를 설정해준다.
처음에는 함수 참조값을 넣지않고, null값을 넣어준다.
왜? ★??
<call back위한 함수 호출조건>
update(){
this.y += this.speed;
// if(this.y == 700){
// this.y = 0;
// // this.x += 100;
// }
if(this.y > 500)
//null이 아닐 때, 조건발생
if(this.onOutofScreen != null)
this.onOutofScreen(this);
//나를 보낸다.
}
setTimeout 이 특정시간마다 함수가 호출되는 것처럼
y값이 500이상일 때 onOutofScreen 에 자신(인스턴스 : this) 을 호출한다
export default class Gamecanvas{ //생성자 만들기
constructor(){
//enemy
this.enemies = [new Enemy(10,0),new Enemy(30,0),new Enemy(300,0),new Enemy(500,0),new Enemy(556,0)
,new Enemy(800,10),new Enemy(700,20),new Enemy(60,0),new Enemy(300,30),new Enemy(700,0)];
for(let enemy of this.enemies){
enemy.onOutofScreen = (en)=>{
//this.enemies.splice(this.enemies.indexOf(en),1);
//좀더 이해가 쉬운 방법
let idx = this.enemies.indexOf(en);
this.enemies.splice(idx,1);
};
//화살표 함수 없이 씀 (이 경우 this 조심)
// enemy.onOutofScreen = function(en){
// let idx = this.enemies.indexOf(en);
// this.enemies.splice(idx,1);
// }
}
enemies 배열 각 인덱스 마다 값(개개 인스턴스들)들을 enemy에 반복하면서 대입한다
앞서 y가 500이상(back) [수신가능상태] 일 때
개개 인스턴스(enemy)는 Enemy.js의 update()에서 자신을 인스턴스로 받은 인수(en)로 받는 형태의 함수를 호출(call)한다 [발신함]
3)
이 경우 enemies 배열에서 indexOf메소드를 이용해서 en(인스턴스)의 배열 인덱스값(idx)을 알아낸다
알아낸 idx값으로 하나를 삭제한다.
그러나, 빈배열상태로 그 공간이 그대로 남아있게된다.
(3) 적기는 그때마다 만들어져야해
랜덤한 시간으로 나타나야한다.
즉 일정하지않고, 서있지않고 적극적으로 움직여야한다.
어떤것은 인근으로 어떤것은 안가게
1) 우선 Aggregation 방식으로 무작위로 적기 생성하자
방금까지 방식은 composition 방식이다.
enemies 라는 배열에 push로 인스턴스를 넣어주기
update(){ //boy 의 update 호출하는 함수
this.boy.update(); //상태바뀌고
for(let enemy of this.enemies)
enemy.update();
//애그리게이션
{
let min = Math.ceil(-50);
let max = Math.floor(600);
let rand = Math.floor(Math.random() * (max - min)) + min
console.log(rand);
let x = rand; //-50 ~this.dom.width +50
let y = -50;
this.enemies.push(new Enemy(x,y));
}
}
난수값을 생성해주는데 최댓값 최솟값방식으로 적기가 생성되는 위치를 지정해준다.
JS는 실수값이 기본적으로 나와야하는데, 값 자르는 과정을 거쳐야한다.
1.7을 반올림 하고싶으면 Math.round()를 쓰면된다 반올림하면 2가된다.
1.7을 자르고(내림) 싶으면 floor (바닥) /1.7보다 무조건 높은(올림) 값 2 원하면 ceil(천장)
아쉽지만 이 랜덤은 real random이 아니다
그리고 나오는 속도를 delay 하는것이 필요하다.
처음에 1초에 하나씩 나오게 하자
2) 1초에 하나씩 나오게
this.enemyAppearDelay--;
//애그리게이션
if(this.enemyAppearDelay == 0){
// let max = this.dom.width - 50;
// // console.log(min);
// let min = 50;
// let rand = Math.floor(Math.random() * (max - min)) + min
// // console.log(rand);
// let x = rand; //-50 ~this.dom.width +50
// let y = -50;
// this.enemies.push(new Enemy(x,y));
let max2 = 60; //
let min2 = 30; //0.5초
let rand2 = Math.floor(Math.random() * (max2 - min2)) + min2
console.log(rand2);
this.enemyAppearDelay = rand2;
}
또 문제가 또있다
아까 y가 500일때 적기가 사라지도록했는데 안없어진다.
얘는 왜냐하면 onoutOfscreen은 다 null이고, 함수 참조값을 받지 못했다
aggregation 방식은 upate할때 인스턴스가 만들어지는데,
인스턴스가 만들어진 update에 만들어지자마자 onoutOfscreen에 함수참조값을 넣어준다.
이렇게 하면 만들자 마자 바로 넣을 수 있다.
그러나 이렇게 하면 매번 onoutOfscreen에 함수가 만들어진다.
한번만 정의하자. 멤버함수로 만들어주자
3) onoutOfscreen을 멤버함수로 만들기
이러면 이제 화살표함수를 쓸 수가없어진다.
update(){ //boy 의 update 호출하는 함수
this.boy.update(); //상태바뀌고
for(let enemy of this.enemies)
enemy.update();
this.enemyAppearDelay--;
//애그리게이션
if(this.enemyAppearDelay == 0){
let max = this.dom.width - 50;
// console.log(min);
let min = 50;
let rand = Math.floor(Math.random() * (max - min)) + min
// console.log(rand);
let x = rand; //-50 ~ this.dom.width ~ +50
let y = -50;
let enemy = new Enemy(x,y);
//함수 호출해주기
enemy.onOutofScreen = this.enemyOutofScreenHandler.bind(this);
this.enemies.push(enemy);
let max2 = 60; //
let min2 = 30; //0.5초
let rand2 = Math.floor(Math.random() * (max2 - min2)) + min2
console.log(rand2);
this.enemyAppearDelay = rand2;
}
}
enemyOutofScreenHandler(en){
let idx = this.enemies.indexOf(en);
this.enemies.splice(idx,1);
}
이렇게 멤버함수로 만들어서 할수있다
(-나의 경우 push를 없애서 작동되지않았다.)
4)충돌대해서 -> 죽었거나
(웹소켓을 하면은 같이 게임할 수있다.)
비행기 터지게 하려면 당사자간 거리가 어느정도인지
방법으로
1. boy가 업데이트 될때마다 적기를 다 훑고 지나가거나, 2. 적기들이 boy가 있는지 본다.
전자의 경우 한걸음마다 적기 10번 / 적기 각각이 10번 => 둘다 같음
적기만 검사하든 소년만 검사하든 하자
1. 소년만을 검사하기위해서 적기들의 상황파악을 해야한다
2. 적기 쉽게알수있게 하는 상황파악해야한다
---
충돌이란
R1 R2 두 중심거리가 크거나 같으면 충돌난 것으로 볼 수있다
중심간 거리(d)
두 점사이 거리 공식으로 구하기가 가능하다
부딪혔다고 하기위해서는 적기에게 다물어보아야한다.
아니면 원을 작게 할수도있다.
--
boy입장에서 적기를 알수있게끔해야한다 boy 가 canvas 참조하면은 서로 참조하게되버림 그래서 필요한 자원만 호출하는 방법이있다.
update에다가 enemy
싱글통 이것은 전역으로 있으면서 절대로 2개이상생성 될 수없으면서,
아무곳이나 접근할수있는 전역상태이어야한다.
우리가 공통으로 사용하는 객체집합을 문맥객체라고 한다
객체사이 공유하는 전역객체가 필요하다 이것이 더 바람직하게 이용이가능하다
얘가 캔버스 참조하기보다는 자료들을 공유하는 것을 모아두고 전역으로 할 수있다.
1. 보충
(1) 싱글톤 패턴
What (정의) : 전체 시스템에서 클래스에 하나의 인스턴스만 존재하는 패턴이다.
Why (존재이유) : 고정된 메모리 영역이 생김,요청이 많은 곳에서 사용시 효율적으로 이용(메모리에 고정되서 바로 접근, 값 공유)하기 위해서
하나의 인스턴스는 다른 클래스의 인스턴스와 값을 공유를 용이하게 하기위해서
How (방법) : 일반객체의 경우 볼수 있고, 비공개 프로퍼티나 메소드의 경우 클로저를 이용한다.
2. 회고
1) splice() 가 순간 무엇인지 잊고있었다. 처음듣는 단어처럼 반응했는데, 역시 망각은 빠른것같다
2) callback 함수가 참 많이쓰이구나 싶다. 무섭다
3) onOutofScreen에 함수를 생성자에 바로 넣는것은 바람직하지 않는 것일까? 그래서 꼭 콜백을 써야할까?
생각해보면 enemy.js에서 this를 보내야지 특정인스턴스를 특정할수있어서 그럴수도있겠다 즉 목적은 인스턴스 특정하기
그리고 인스턴스를 만들고, 제거하는것은 결국 gameCanvas에서 종합적으로 통제한다.
어쩔 수 없긴하다.
만약에 생성자에 있었다면은 우선 500인지 여부에 대해서 update()로 매번 확인이 어렵다.
그리고 인스턴스 제거도 곤란하다.
4) 콜백함수 매개변수넣는 곳이 내 통념과 달라서 낯설다.
'배움 __IL > TIL 1기' 카테고리의 다른 글
TIL : 33번째- 230112 [1-2-목] (0) | 2023.01.12 |
---|---|
TIL : 32번째- 230111 [1-2-수] (0) | 2023.01.11 |
TIL : 30번째- 230109 [1-2-월] (0) | 2023.01.09 |
TIL : 29번째- 230106 [1-1-금] (0) | 2023.01.06 |
TIL : 28번째- 230105 [1-1-목] (0) | 2023.01.05 |