본문 바로가기

블록체인기반 SW 개발자 과정(feat.경일게임아카데미)/2차 프로젝트

<2차 프로젝트 (22.06.27 ~ 22.07.15)> JAVASCRIPT 기반 게임 만들기 회고록 - 3 // 플레이어 이동 조작 구현하기

이전 글에 canvas를 선언하고 그 안에 객체를 생성해서 그리는 것까지 설명을 했다.

이번엔 플레이어 이동조작 구현한걸 설명할 건데 js로 함수를 짠거라 누구나 할 수 있을 것이다.

 

 

일단 코드 전문을 띄우고 밑에 설명을 적어두도록 하겠다.

 

< 코드전문 >

const canvas = document.querySelector('canvas');
const c = canvas.getContext('2d');

canvas.width = 1024;
canvas.height = 576;

c.fillRect(0, 0, canvas.width, canvas.height);
const gravity = 0.2;

// class 생성
class Sprite {
    // 이렇게 객체로 묶어서 하나로 초기값을 받아들임 나중에 인스턴스의 값에 직접 접근해서 설정해줄 수 있으니까 상관없음
    constructor({position, velocity}) {
        this.position = position;
        this.velocity = velocity; // 속도
        this.height = 150;
    }
    draw() {
        c.fillStyle = 'red';
        c.fillRect(this.position.x, this.position.y, 50, this.height)
    }
    update() {
        this.draw();
        //위치값에 속도만큼 더해줘서 매프레임 위치 변화시킴
        this.position.x += this.velocity.x;
        this.position.y += this.velocity.y;

        // 내려가는 애니메이션이 canvas의 bottom에 닿으면 속도를 0으로 만들어서 멈추게 함
        if (this.position.y + this.height + this.velocity.y >= canvas.height ) {
            this.velocity.y = 0;
        } else {
            //캔버스의 영역을 벗어나는게 아니면 항상 y축 움직임에 중력값을 더해줌
            this.velocity.y = 0;
        }

    }
}

// class로 인스턴스를 생성해주는데 파라미터로 position과 velocity의 x,y값을 넣어줌
const player = new Sprite({
    position: {
        x: canvas.width /2,
        y: canvas.height/2
    },
    velocity: {
        x: 0,
        y: 0
    }
});

// 객체 생성 (플레이어, 적)
const enermy = new Sprite({
    position: {
        x: 400,
        y: 100
    },
    velocity: {
        x: 0,
        y: 0
    }
})

//이동키 눌렀는지 안눌렀는지 판단위해 t/f 값 설정
const keys = {
    a: {
        pressed: false
    },
    d: {
        pressed: false
    },
    w: {
        pressed: false
    },
    s: {
        pressed: false
    }
}
//마지막으로 입력한 키보드의 값 넣어줌
let lastkey;

//콜백함수로 계속 매 프레임마다 판단하도록 함
function animation() {
    window.requestAnimationFrame(animation);
     c.clearRect(0, 0, canvas.width, canvas.height); 
     // 캔버스 화면 지우는 메소드
    c.fillStyle = 'black';
    c.fillRect(0, 0, canvas.width, canvas.height);
    player.update();
    enermy.update();
    console.log("애니메이션 실행된다");

    // 누르던 키를 안누를때에도 이전에 누른키가 pressed = true로 설정되어있기 때문에 조건 추가
    player.velocity.x = 0; // 매 프레임마다 유저 이동속도를 0으로 만들어서 이동하려면 계속 키눌러야함
    if (keys.a.pressed && lastkey === 'a') {
        player.velocity.x = -1;
    } else if (keys.d.pressed && lastkey === 'd') {
        player.velocity.x = 1;
    } else if (keys.w.pressed && lastkey === 'w'){
        player.velocity.y = -1;
    } else if(keys.s.pressed && lastkey === 's'){
        player.velocity.y = 1;
    }
}

//콜백함수 호출
animation();

// 키보드로 캐릭터 움직이도록 이벤트 추가
window.addEventListener('keydown', (event) => {
    switch (event.key) {

        case 'd':
            keys.d.pressed = true;
            lastkey = 'd';
            break;

        case 'a':
            keys.a.pressed = true;
            lastkey = 'a';
            break;

        case 'w':
            keys.w.pressed = true;
            lastkey = 'w';
            break;

        case 's':
            keys.s.pressed = true;
            lastkey = 's';
            break;

        default:
            break;
    }
    console.log(event.key);
})
window.addEventListener('keyup', (event) => {
    switch (event.key) {
        case 'd':
            keys.d.pressed = false;
            break;
        case 'a':
            keys.a.pressed = false;
            break;

        case 'w':
            keys.w.pressed = false;
            break;

        case 's':
            keys.s.pressed = false;
            break;

        default:
            break;
    }
})

 

 

 

코드가 좀 뒤죽박죽이지만ㅎㅎ  천천히 하나씩 정리해보겠다

< 플레이어의 이동을 구현한 부분 - 1 >

function animation() {
    window.requestAnimationFrame(animation);
     c.clearRect(0, 0, canvas.width, canvas.height); 
     // 캔버스 화면 지우는 메소드
    c.fillStyle = 'black';
    c.fillRect(0, 0, canvas.width, canvas.height);
    player.update();
    enermy.update();
    console.log("애니메이션 실행된다");

    // 누르던 키를 안누를때에도 이전에 누른키가 pressed = true로 설정되어있기 때문에 조건 추가
    player.velocity.x = 0; // 매 프레임마다 유저 이동속도를 0으로 만들어서 이동하려면 계속 키눌러야함
    if (keys.a.pressed && lastkey === 'a') {
        player.velocity.x = -1;
    } else if (keys.d.pressed && lastkey === 'd') {
        player.velocity.x = 1;
    } else if (keys.w.pressed && lastkey === 'w'){
        player.velocity.y = -1;
    } else if(keys.s.pressed && lastkey === 's'){
        player.velocity.y = 1;
    }
}

키를 눌렀을때 

 

 

 

 

< 플레이어의 이동을 구현한 부분 - 1 >



window.addEventListener('keydown', (event) => {
    switch (event.key) {

        case 'd':
            keys.d.pressed = true;
            lastkey = 'd';
            break;

        case 'a':
            keys.a.pressed = true;
            lastkey = 'a';
            break;

        case 'w':
            keys.w.pressed = true;
            lastkey = 'w';
            break;

        case 's':
            keys.s.pressed = true;
            lastkey = 's';
            break;

        default:
            break;
    }
    console.log(event.key);
})

 

keydown - 키를 눌렀을때 이벤트가 발생하도록 설정했다.

 

window.addEventListener('keydown', (event) => {

} )

 

JS 키보드 이벤트 참고 : 

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key 

 

KeyboardEvent.key - Web APIs | MDN

The KeyboardEvent interface's key read-only property returns the value of the key pressed by the user, taking into consideration the state of modifier keys such as Shift as well as the keyboard locale and layout.

developer.mozilla.org

 

 

 

그리고 어떤키를 눌렀을 때 어떤 이벤트가 발생할지는 switch 문으로 짰다.

 

이 부분을 구현하면서 코드를 좀더 보기 좋게 정돈하는 방법을 배웠다ㅎㅎ

switch문에 죽- 길게 적어놨으면 나도 나중에 봤을때 못알아 봤을 것이다.

 

//이동키 눌렀는지 안눌렀는지 판단위해 t/f 값 설정
const keys = {
    a: {
        pressed: false
    },
    d: {
        pressed: false
    },
    w: {
        pressed: false
    },
    s: {
        pressed: false
    }
}

나는 이동키를 a,w,s,d 로 설정하려고 했고 키를 누르고 있어야만 이동하도록 만들고 싶었다. 그래서

위에서 animation()안에

player.velocity = 0 // 이라는 코드를 추가해서 매 프레임당 이동속도를 0으로 만들어주었다. 그래서 키를 누르고 있는동안에만 이동할 수 있다.

 

그렇기 때문에 pressed에 기본값으로  false를 넣어주었다.

 

 

 

728x90