
やっぱりゲームを作るのは楽しいな〜と、つぶやいている、ユゲタです。
gameを構築するイメージがまあまあ見えてきたんですが、少し規模の大きいgameを作る時に、
フレームワークを使ってgameを作ってもいいんですが、できるだけ無駄とブラックボックス箇所を無くしたいので、
フルスクラッチでcanvasを使って構築をしたいと思った時に、いろいろなライブラリが必要になる事もイメージできます。
そんなライブラリを作り込んで行きたいと思って、小さなゲームプログラムを作り重ねていき、最終的に自分ライブラリを作ってみたいと思います。
ブログでは、そんなプログラムの解説をしつつ、Githubで都度のバージョンを公開して行く予定です。
本日のIT謎掛け
「ゲームライブラリ」と、かけまして・・・
「公園の遊具」と、ときます。
そのココロは・・・
遊ぶ時に、無いとまあまあ困るもの。
本日の目的
以前に作った三目並べのcanvasライブラリを参照しつつ、データ管理や、表示まわりの効率的な書き方などがまとまっていないので、とりあえず、今回はまだ手を付けていなかった、アニメーションに関するかんたんなライブラリを作ってみたいと思います。
そこで、BASICを学習した時の一番最初に作った「壁打ちテニス」にTRYします。
仕様は、三方壁に囲まれたbox内で直線的に動くボールを、手前のラケット(棒)で、返すだけですが、以下のような処理が必要になります。
・基本描画処理
・開始時の「start」ボタンのクリックイベント処理
・ボールと、ラケットが動くアニメーション描画処理(全体書き換え)
・マウス動作によるラケット移動
・ボールが壁に当たって跳ね返る当たり判定
・ボールがラケットに当たって跳ね返るコリジョン処理
・ボールが画面外に言ってしまった時のGameOver処理
これを簡易仕様として、構築していきます。
基本描画処理
まず始めに、基本の画面表示をしてみます。
画面サイズを決めて、3方の壁の表示です。
初期構築という事で、htmlも含めたソースコードも合わせて掲載しておきます。
ソースコード
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>TicTacToe</title>
  <style>
    #mycanvas{
      display:block;
      margin:10px auto;
    }
  </style>
  <script src="common.js"></script>
</head>
<body>
  <canvas id="mycanvas">not canvas</canvas>
</body>
</html> 
 
 
(function(){
  var __options = {
    canvas : "#mycanvas",
    width  : 400,
    height : 600,
    wall   : { w : 400 , h : 600 , color_stroke : "transparent" , color_fill : "#382B8C" , size : 20 },
    ball   : { r : 10 , color_stroke : "transparent" , color_fill : "#F2B5A7" },
    bar    : { w: 50 , h: 10 , color_stroke : "transparent" , color_fill : "#958ABF" },
    $:0
  };
  var MAIN = function(){
    if(!this.check()){
      alert("htmlに指定のcanvasがありません。");
      return;
    }
    this.init();
    this.draw();
  };
  MAIN.prototype.getCanvas = function(){
    if(typeof this.canvas === "undefined"){
      this.canvas = document.querySelector(__options.canvas);
    }
    return this.canvas;
  };
  MAIN.prototype.getContext = function(){
    if(typeof this.ctx === "undefined"){
      var canvas = this.getCanvas();
      if(!canvas){return null;}
      this.ctx = canvas.getContext("2d");
    }
    return this.ctx;
  };
  MAIN.prototype.check = function(){
    var ctx = this.getContext();
    if(ctx){
      return true;
    }
    else{
      return false;
    }
  };
  MAIN.prototype.init = function(){
    // 画面サイズ調整
    var canvas = this.canvas;
    canvas.setAttribute("width"  , __options.wall.w);
    canvas.setAttribute("height" , __options.wall.h);
  };
  MAIN.prototype.draw = function(){
    this.draw_wall();
    this.draw_bar();
    this.draw_ball();
  };
  MAIN.prototype.draw_wall = function(){
    var ctx = this.ctx;
    ctx.strokeStyle = __options.wall.color_stroke;
    ctx.strokeWidth = __options.wall.color_stroke === "transparent" ? 0 : 1;
    ctx.fillStyle   = __options.wall.color_fill;
    ctx.beginPath();
    ctx.moveTo(0,0);
    ctx.lineTo(__options.wall.w , 0);
    ctx.lineTo(__options.wall.w , __options.wall.h);
    ctx.lineTo(__options.wall.w - __options.wall.size , __options.wall.h);
    ctx.lineTo(__options.wall.w - __options.wall.size , __options.wall.size);
    ctx.lineTo(__options.wall.size , __options.wall.size);
    ctx.lineTo(__options.wall.size , __options.wall.h);
    ctx.lineTo(0 , __options.wall.h);
    ctx.lineTo(0 , 0);
    ctx.stroke();
    ctx.fill();
  };
  MAIN.prototype.draw_bar = function(){
    var ctx = this.ctx;
    ctx.strokeStyle = __options.bar.color_stroke;
    ctx.strokeWidth = __options.bar.color_stroke === "transparent" ? 0 : 1;
    ctx.fillStyle   = __options.bar.color_fill;
    ctx.fillRect(__options.wall.size + 10 , __options.wall.h - __options.bar.h - 30 , __options.bar.w , __options.bar.h);
  };
  MAIN.prototype.draw_ball = function(){
    var ctx = this.ctx;
    ctx.strokeStyle = __options.ball.color_stroke;
    ctx.strokeWidth = __options.ball.color_stroke === "transparent" ? 0 : 1;
    ctx.fillStyle   = __options.ball.color_fill;
    ctx.beginPath();
    ctx.arc(__options.wall.w / 2, __options.wall.h / 2, __options.ball.r, 0, Math.PI * 2);
    ctx.fill();
  };
  var LIB  = function(){};
  LIB.prototype.event = function(target, mode, func , flg){
    flg = (flg) ? flg : false;
    if (target.addEventListener){target.addEventListener(mode, func, flg)}
    else{target.attachEvent('on' + mode, function(){func.call(target , window.event)})}
  };
  LIB.prototype.construct = function(){
    switch(document.readyState){
      case "complete"    : new MAIN();break;
      case "interactive" : this.event(window , "DOMContentLoaded" , (function(){new MAIN()}).bind(this));break;
      default            : this.event(window , "load"             , (function(){new MAIN()}).bind(this));break;
    }
  };
  new LIB().construct();
})();
 
Github
https://github.com/yugeta/game_block
今回は初期表示のみのバージョンなので、あまり面白くないですが、今後バージョンアップさせていく予定なので、楽しんでもらえる方は引き続き読んでくださいませ。
 
0 件のコメント:
コメントを投稿