JavaScript로 Slither.io를 만드는 법 : Part 5 - Snake Eyes


이것은 JavaScript 및 Phaser로 Slither.io를 만드는 튜토리얼 시리즈의 다섯 번째 부분입니다! 

예제를 살펴보고 이 부분의 소스 코드를 살펴보십시오.

눈 개념
튜토리얼 시리즈의 이 파트에서는 뱀 헤드에 눈을 보게 될 것입니다. 이제 우리가 바라는 것들을 살펴 보겠습니다.

첫째, 우리는 눈의 뒷부분에 흰색 원이 필요합니다. 이 흰색 원은 잠금 제한을 사용하여 뱀 머리에 고정됩니다. 다음으로, 우리는 눈 앞부분에 검은 색 동그라미가 필요합니다. 이 검은 색 동그라미는 눈동자처럼 움직일 수 있도록 흰색 원 안에 있어야합니다. 이 검은 색 원은 거리 제한을 사용하여 흰색 원의 중심 근처에 유지합니다. 즉, 원 중심에서 특정 거리 만 이동할 수 있습니다. 이 검은 색 원을 마우스 포인터쪽으로 보이게 하려면 머리에서 마우스 방향으로 작은 힘을 가할 것입니다.

구조
구조적으로는 두 가지 새로운 클래스 인 Eye and EyePair를 만들겠습니다. Eye 클래스는 머리에 대한 단일 눈에 대한 제한을 처리하고 EyePair 클래스는 두 눈의 위치를 처리합니다.

뱀의 다른 부분과 마찬가지로, 눈은 크기를 조정하고 파괴해야 합니다. 눈을 제어하는 뱀 클래스에서 호출 할수 있는 눈 클래스에서 이 방법이 필요합니다.

코딩을 시작합시다. eye.js 소스에, 먼저 Eye 함수를 만듭니다.
Eye = function(game, head, scale) {
    this.game = game;
    this.head = head;
    this.scale = scale;
    this.eyeGroup = this.game.add.group();
    this.collisionGroup =    
        this.game.physics.p2.createCollisionGroup();
    this.debug = false;

    // 원을 고정 할 제약 조건은 머리에 흰 원을 고정하고 
    // 거리 제한 (dist)이 흰색 원 안에 검은 원을 유지합니다.
    this.lock = null;
    this.dist = null;

    // 원의 스프라이트를 초기화 한다.
    this.whiteCircle = this.game.add.sprite(
        this.head.body.x, this.head.body.y, "eye-white"
    );
    this.whiteCircle = this.initCircle(this.whiteCircle);

    this.blackCircle = this.game.add.sprite(
        this.whiteCircle.body.x, 
        this.whiteCircle.body.y, "eye-black"
    );
    this.blackCircle = this.initCircle(this.blackCircle);
    this.blackCircle.body.mass = 0.01;
}
우리는 몇 개의 그룹을 생성 한 다음 잠금과 거리 제한에 대한 속성을 생성합니다. 그러나 아직 실제로 제약 조건을 생성하지는 않습니다. 흑백 원을 만든 다음 initCircle을 호출하여 이 원 스프라이트에 기본 물리 속성을 추가합니다. asset 폴더를 보면 우리가 사용하고있는 새로운 원 이미지를 볼 수 있습니다.

이제 Eye 프로토타입의 initCircle을 살펴 보겠습니다.
initCircle: function(circle) {
    circle.scale.setTo(this.scale);
    this.game.physics.p2.enable(circle, this.debug);
    circle.body.clearShapes();
    //give the circle a circular physics body
    circle.body.addCircle(circle.width*0.5);
    circle.body.setCollisionGroup(this.collisionGroup);
    circle.body.collides([]);
    this.eyeGroup.add(circle);
    return circle;
}
여기서 우리는 단순히 원을 물리 원형 몸체에 주고, 이들 몸체에 대한 충돌을 제거하고, 원을 그룹에 추가합니다. 이제 제약 조건을 추가하는 방법이 필요합니다.

제약 조건
제약 조건을 추가하기 위해 적어도 한 번 호출해야하는 updateConstraints 메소드를 살펴 보겠습니다.
updateConstraints: function(offset) {
    // 이미 존재하는 경우 흰색 원의 잠금 제약 조건을 변경합니다.
    if (this.lock) {
        this.lock.localOffsetB = [
            this.game.physics.p2.pxmi(offset[0]),
            this.game.physics.p2.pxmi(Math.abs(offset[1]))
        ];
    }
    // 이미 존재하지 않는 경우 잠금 제약 조건을 만듭니다.
    else {
        this.lock = this.game.physics.p2.createLockConstraint(
            this.whiteCircle.body, this.head.body, offset, 0
        );
    }

    // 이미 존재하는 경우 검은 색 원에 대한 거리 구속 조건의 거리를 
    // 변경합니다.
    if (this.dist) {
        this.dist.distance = 
              this.game.physics.p2.pxm(this.whiteCircle.width*0.25);
    }
    // 이미 존재하지 않으면 거리 제약 조건을 만듭니다.
    else {
        this.dist = this.game.physics.p2.createDistanceConstraint(
            this.blackCircle.body, this.whiteCircle.body, 
            this.whiteCircle.width*0.25
        );
    }
}
이 메소드는 [x, y] 형식의 Array 인 매개 변수 오프셋을 취하여 머리 중심에서 눈을 오프셋 할 위치를 알려주고 그 위치에 자금 제한을 배치합니다. 제약 조건이 존재하는지 여부를 확인하는 이유는 무엇일까요? 이미 존재한다면 우리는 아마도 눈의 크기를 변화시킬 것이므로 눈이 어디에서 상쇄되고 검은 색 원이 흰색 원 안에 얼마나 멀리 갈 수 있는지를 간단히 변경해야합니다.

Scale
다음으로 scale 메소드가 있습니다.
setScale: function(scale) {
    this.scale = scale;
    for (var i = 0 ; i < this.eyeGroup.children.length ; i++) {
        var circle = this.eyeGroup.children[i];
        circle.scale.setTo(this.scale);
        // 순수한 p2 물리를 사용하여 원 본체의 반경 변경                  
        circle.body.data.shapes[0].radius = 
        this.game.physics.p2.pxm(circle.width*0.5);
    }
}
원을 반복하면서 스프라이트를 확대 한 다음 물리 구조를 확대합니다.

Update
마우스 위치에 따라 눈의 검은 부분을 이동하는 업데이트 방법이 필요합니다.
update: function() {
    var mousePosX = this.game.input.activePointer.worldX;
    var mousePosY = this.game.input.activePointer.worldY;
    var headX = this.head.body.x;
    var headY = this.head.body.y;
    var angle = Math.atan2(mousePosY-headY, mousePosX-headX);
    var force = 300;
    // 검은 색 원을 마우스쪽으로 움직입니다.
    this.blackCircle.body.moveRight(force*Math.cos(angle));
    this.blackCircle.body.moveDown(force*Math.sin(angle));
}

Destroy
마지막으로 destroy 메소드가 있습니다.
destroy: function() {
    this.whiteCircle.destroy();
    this.blackCircle.destroy();
    this.game.physics.p2.removeConstraint(this.lock);
    this.game.physics.p2.removeConstraint(this.dist);
}
우리는 제약 조건을 파괴해야합니다!

EyePair
이제 eyePair.js를 살펴보십시오. 이 클래스는 두 개의 눈을 생성 한 다음 해당 메서드를 호출하는 드라이버의 역할을 합니다.
EyePair = function(game, head, scale) {
    this.game = game;
    this.head = head;
    this.scale = scale;
    this.eyes = [];

    this.debug = false;

    //create two eyes
    var offset = this.getOffset();
    this.leftEye = new Eye(this.game, this.head, this.scale);
    this.leftEye.updateConstraints([-offset.x, -offset.y]);
    this.eyes.push(this.leftEye);

    this.rightEye = new Eye(this.game, this.head, this.scale);
    this.rightEye.updateConstraints([offset.x, -offset.y]);
    this.eyes.push(this.rightEye);
}
두 개의 눈을 만든 다음 getOffset이라는 메서드에서 가져온 오프셋을 사용하여 updateConstraints 메서드를 호출합니다. 이제 EyePair 프로토 타입에서 살펴 보겠습니다.
getOffset: function() {
    var xDim = this.head.width*0.25;
    var yDim = this.head.width*.125;
    return {x: xDim, y: yDim};
}
우리는 뱀 머리의 너비에 상대적인 눈의 위치를 정의 합니다. 그리고 헤드가 확대되면 헤드의 너비가 더 커지므로 오프셋이 달라집니다.

마지막으로 눈의 스케일링, 업데이트 및 파기 메서드를 호출하는 메서드가 있습니다.
/**
 * Set the scale of the eyes
 * @param  {Number} scale new scale
 */
setScale: function(scale) {
    this.leftEye.setScale(scale);
    this.rightEye.setScale(scale);
    //update constraints to place them at the right offset
    var offset = this.getOffset();
    this.leftEye.updateConstraints([-offset.x, -offset.y]);
    this.rightEye.updateConstraints([offset.x, -offset.y]);
},
/**
 * Call from snake update loop
 */
update: function() {
    for (var i = 0 ; i < this.eyes.length ; i++) {
        this.eyes[i].update();
    }
},
/**
 * Destroy this eye pair
 */
destroy: function() {
    this.leftEye.destroy();
    this.rightEye.destroy();
}

Snake
물론, 우리는 여전히 Snake 클래스 내에서 이 EyePair를 구현해야 합니다. snake.js를 열고, 먼저 EyePair 객체를 초기화합니다.
this.eyes = new EyePair(this.game, this.head, this.scale);

뱀의 업데이트 메서드에서 eyes 업데이트 메서드를 호출해야합니다.
this.eyes.update();

뱀 스케일 방법으로 눈을 스케일 합니다.
this.eyes.setScale(scale);

그리고 우리는 뱀 파괴 방법에 있는 눈을 파괴한다 :
this.eyes.destroy();

그리고 그것은 뱀 눈을 주기 위해 필요한 것입니다! Part 6에서는 뱀 아래에 그림자를 추가 할 것입니다.

댓글 없음:

댓글 쓰기