top drop menu

Recent Post

토요일, 11월 24

P5.js : 우주 슈팅게임(5)–게임패드 연결

asteroid-1477065_1280
사실 지금까지 해 왔던게 바로 이 게임패드를 연결해 보려고 했던것이었다.  게임패드 용도에 맞게 하나의 게임이 필요해서 P5.js로 만드는 게임을 지금 까지 해 봤던 것이다. 최신 웹 브라우저에서는 게임패드를 인식하고 사용할 수 있도록 기본으로 되어 있는데, 물론 브라우저마다 안되거나 약간 다른 용법을 사용한것 같기도 하다. 아직 지원하지 않기도 하는 모양이다. 여기서는 윈도우10에서 크롬브라우저를 기준으로 예제를 만들었다. 다른 환경에서 테스트는 해 보지 않았다.  제일 먼저 html 문서를 보자.
-------------------index.html-----------------
<!doctype html>
<html lang="ko">
  <head>
   <meta name="viewport" content="width=device-width, user-scalable=no">
   <meta charset="UTF-8">
   <meta name="Description" content="">
   <title>P5.JS 연습</title>
   <link href="https://fonts.googleapis.com/css?family=Orbitron" rel="stylesheet">
   <style type="text/css">
        body{
       text-align: center;
       margin: 0px;
       padding: 0px;
     }
      p{
       font-size: .8em;
      }
      #defaultCanvas0{
     }
   </style>
   <!--공통-->
   <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.min.js"></script>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/addons/p5.sound.min.js"></script>
   <!--프로젝트 스크립트-->
   <script src="sketch19-final.js"></script>
   <script src="ship3.js"></script>
   <script src="asteroid.js"></script>
   <script src="laser.js"></script>
   <script src="particle2.js"></script>
   <script src="explode.js"></script>
   <script src="firework.js"></script>
</head>
  <body>
   <h1>P5.js Example 19-final(Simple Game)</h1>
   <audio autoplay controls preload="auto" loop  id="myAudio">
      <source src="http://soundimage.org/wp-content/uploads/2014/04/Game-Menu.mp3">
      Your browser does not support the audio element. 
  </audio>
  <p>게임패드 이동: 왼편 스틱, 슈팅: 오른쪽 R2,  재시작 : F5, BGM : Music by Eric Matyas www.soundimage.org</p>
  
  </body>
</html>
---------------------------------------------
필요한 자바스크립들은 별도의 파일로 만들고 링크해서 사용하도록 하였다. 이문서는 간단하다.
-----------------sketch.js-----------------
var ship;
var asteroids = [];
var lasers = [];
var font, fontsize = 15;
var health = 100;
var shoot;
var bomb;
let particles = [];//var와 let의 차이를 모르겠음? let이 더 엄격하다 정도만.
var fireworks = [];
function preload(){
     shoot = loadSound('sound/laser_shoot.mp3');
     bomb = loadSound('sound/bom.wav');
}

function setup() {
     createCanvas(800, 480);
     //createCanvas(windowWidth,windowHeight);
     font="Orbitron";
     textFont(font);
     textSize(fontsize);
     //우주선 생성
     ship = new Ship();
     //소행성 생성
     for(let i =0; i < 10; i++){
         asteroids.push(new Asteroid());
     }
}
function draw() {
     background(0);
    // Gamepad
     pads = navigator.getGamepads();
     pad0 = pads[0];
    if(pad0){
         // 오른쪽 R2 버튼(앞면 큰 버튼)
         if (pad0.buttons[7].value > 0.6 && pad0.buttons[7].pressed == true){
             lasers.push(new Laser(ship.pos, ship.heading));//너무 연속적으로 추가 되는 문제
             shoot.play();
         }
         // 스틱
         if(pad0.axes[0] >= .5 ){
             ship.boosting(true);
         } else if(pad0.axes[0] <= -.5) {
             ship.boosting(true);
         } else if (pad0.axes[1] < -.5){
             ship.boosting(true);
         } else if (pad0.axes[1] > .5){
             ship.boosting(true);
         }
     }
    ship.c = color(100, 255, 100,  255);
     // Backgroud Particle
     let p = new Particle();
     particles.push(p);//draw()에 동작해서 계속해서 객체를 만들어 추가한다.
     for(let i = particles.length-1; i >= 0; i--){
         particles[i].update();
         particles[i].show();
         if(particles[i].finished()){
             particles.splice(i, 1);
         }
     }
    
     // Explosion
     for(var i = 0; i < fireworks.length; i++){
         fireworks[i].run();   
         if(fireworks.length>10){
             fireworks.splice(0, 1);
         }
     }
    //소행성
     for (var i = 0; i < asteroids.length; i++){
         //소행성과 우주선이 충돌하면
         if(ship.hits(asteroids[i])){
             //console.log("hit");
             ship.c = color(255, 0, 0,  255);
             health = health - asteroids[i].r * 0.05;
         }
        asteroids[i].update();
         asteroids[i].render();
         asteroids[i].edges();
     }
    // 레이저
     for (var i = lasers.length -1; i >= 0; i--){
         lasers[i].update();
         lasers[i].render();
         // 화면을 벗어나면 제거 해줌
         if(lasers[i].offscreen()){
             lasers.splice(i, 1);
         } else {
             // 충돌 감지
             for(var j = asteroids.length-1; j >= 0; j--){
                 if(lasers[i].hits(asteroids[j])){
                     //console.log('hit');
                     health = health + asteroids[j].r * 0.1;
                     if(asteroids[j].r > 10) {
                             var newAsteroids = asteroids[j].breakup();// 충돌된 소행성을 쪼갠다.
                             asteroids = asteroids.concat(newAsteroids);
                     }
                     fireworks.push(new Firework(lasers[i].pos.x, lasers[i].pos.y));
                     asteroids.splice(j, 1); //j번째 1개를 제거한다.
                     lasers.splice(i, 1);
                     bomb.play();
                    break;
                 }
             }
        }
     }
    // 우주선
     ship.render();
     ship.turn();
     ship.update();
     ship.edges();
    // Score
     drawScore();
}
// Score and Health
function drawScore(){
     fill(255);
     if(health <= 0){
         text("Game Over", 30, 30);
     } else {
         text(Math.ceil(health), 30, 30);
     }
     if (asteroids.length <= 0){
         text("You Win", 30, 50);   
     }
}
----------------------------
메인 스케치 파일이다. 키보드 조작기능은 제거를 했다. 게임패드와 키보드 조작을 다 같이 사용하게 할려면 설정 코드가 더 필요한데 귀찮다. 원래 목적대로 게임패드만 사용하게 해 주자.  이 메인 스케치 이외에 우주선, 소행성, 레이저, 폭발효과를 위한 객체 클래스들이 필요하다. 이걸 다 일일히 여기 적기는 힘들고 자바스크립트 이니 소스가 다 보인다. 찾아서 참고 하면 될듯 하다. ^^;
기본 게임 만드는 유튜브로 만든 것에 필요한 기능 몇가지를 추가해 준것이다. 사운드 효과를 주면 더 게임 다워 진다.
이미지 130
게임패드의 왼쪽 조이스틱(맞나 용어가?)를 이용해서 우주선을 움직이게 하는데 이게 키보드 이동키로 단순히 회전하고 전진하고 하는 것과는 좀 다르게 해 줄 필요가 있었다. 상하좌우 아무곳으로나 이동이 가능하게 해주고 해당 방향으로 움직이면 그 방향으로 우주선 헤드가 돌아 가도록 해줘야 했다. 이것을 구현하는게 난감하게 생각되었는데 의외로 간단히 구현 할 수 있었다.
---------------ship.js-------------------
this.turn = function(){
         //this.heading += this.rotation;
         this.heading  = this.vel.heading();
     }
--------------------------------------------
vel 벡터의 heading() 을 적용하니 쉽게 구현이 되었다. 좋아~  스틱의 움직임에 따라 우주선이 자유롭게 조정이 가능했다. 정밀하게 제어하기는 힘들지만 이정도면 충분해 보인다.  마지막 최종 결과는 아래 링크에서 확인해 보자. 물론 호환이 되는 기본형 게임패드가 있어야 게임이 가능하다. 없는 사람에게는 아무것도 해 볼 수 업다. ^^; 데모 영상은 차후 만들어서 추가해 볼 예정이다.

http://visualssing.dothome.co.kr/p5js/p5js_exam19-final.html


Blogger Widget