みかづきブログ その3

3ヶ月つづけてみました。

Canvas で Chrome の恐竜を描く

DEMO


HTML

<canvas id="canvas"></canvas>

JavaScript

(function(win) {

  "use strict";

  win.App = {};

})(this);



(function(win, doc, ns, $) {

  "use strict";

  function Stage(stgCtx, width) {
    var that       = this,
        canvas     = doc.createElement("canvas"),
        ctx        = canvas.getContext("2d"),
        isStart    = false,
        MIN_WIDTH  = 88,
        HEIGHT     = 38,
        TOP        = 263,
        LINE_WIDTH = 2;

    _init();

    function _init() {
      canvas.width  = width;
      canvas.height = HEIGHT;

      that.width     = {
        min : MIN_WIDTH,
        now : MIN_WIDTH,
        max : width
      };
      that.height    = HEIGHT;
      that.isStart   = isStart;
      that.canvas    = canvas;
      that.ctx       = ctx;
      that.stgCtx    = stgCtx;
      that.top       = TOP;
      that.lineWidth = LINE_WIDTH;
    }
  }

  Stage.prototype.draw = function() {
    this.ctx.save();
    this.ctx.lineWidth = this.lineWidth;
      this.ctx.beginPath();
      this.ctx.moveTo(0, 0);
      this.ctx.lineTo(this.width.max, 0);
      this.ctx.closePath();
      this.ctx.stroke();
    this.ctx.restore();

    if (!this.isStart) {
      this.stgCtx.drawImage(
        this.canvas,
        0,
        this.top,
        this.width.min,
        this.height + this.lineWidth
      );
    } else {
      this.stgCtx.drawImage(
        this.canvas,
        0,
        this.top,
        this.width.now,
        this.height + this.lineWidth
      );
    }
  };

  ns.Stage = Stage;

})(this, document, App, $);



(function(win, doc, ns, $) {

  "use strict";

  function Tyranno(stgCtx) {
    function Mask() {
      var that   = this,
          TOP    = 12,
          LEFT   = 72,
          WIDTH  = 40,
          HEIGHT = 2;

      _init();

      function _init() {
        that.top    = TOP;
        that.left   = LEFT;
        that.width  = WIDTH;
        that.height = HEIGHT; 
      }
    }

    function Direction() {
      var that       = this,
          DIRECTION  = ["left", "right"],
          INIT_INDEX = 0;

      _init();

      function _init() {
        that.DIRECTION = DIRECTION;
        that.type = DIRECTION[INIT_INDEX];
      }
    }

    Direction.prototype.change = function() {
      if (this.type === this.DIRECTION[0]) {
        this.type = this.DIRECTION[1];
      } else {
        this.type = this.DIRECTION[0];
      }
    };

    var that   = this,
        canvas = doc.createElement("canvas"),
        ctx    = canvas.getContext("2d"),
        isRun  = false,
        WIDTH  = 80,
        HEIGHT = 86,
        INIT_X = 4,
        INIT_Y = 190,
        INIT_DIRECTION = "r",
        STAGE_COLOR = "#f7f7f7",
        BODY_COLOR  = "#535353",
        EYE_COLOR   = "#fff";

    _init();

    function _init() {
      canvas.width  = WIDTH;
      canvas.height = HEIGHT;

      that.mask   = new Mask();
      that.canvas = canvas;
      that.color  = {
        stage : STAGE_COLOR,
        body  : BODY_COLOR,
        eye   : EYE_COLOR
      },
      that.position = {
        init : {
          x : INIT_X,
          y : INIT_Y
        },
        direction: new Direction(),
        x : INIT_X,
        y : INIT_Y
      };
      that.ctx    = ctx;
      that.stgCtx = stgCtx;
      that.isRun  = isRun;

      that.draw();
    }
  }

  Tyranno.prototype._drawHead = function(x, y) {
    this.ctx.rect(x + 4, y,      32, 4);
    this.ctx.rect(x,     y + 4,  40, 18);
    this.ctx.rect(x,     y + 22, 20, 4);
    this.ctx.rect(x,     y + 26, 32, 4);
  };

  Tyranno.prototype._drawBody = function(x, y) {
    this.ctx.rect(x,      y,      20, 26);
    this.ctx.rect(x - 6,  y + 4,  22, 28);
    this.ctx.rect(x - 6,  y + 4,  22, 28);
    this.ctx.rect(x - 12, y + 8,  22, 28);
    this.ctx.rect(x - 16, y + 12, 28, 24);
    this.ctx.rect(x - 16, y + 36, 24, 4);
  };

  Tyranno.prototype._drawHand = function(x, y) {
    this.ctx.rect(x,     y,     8, 4);
    this.ctx.rect(x + 4, y + 4, 4, 4);
  };

  Tyranno.prototype._drawFoot = function() {
    var now = Date.now();

    if (this.isRun) {
      if ((now / 100 | 0) % 2) {
        this._drawFootLeft(36, 58);
        this._drawFootRigth(20, 70);
      } else {
        this._drawFootLeft(36, 70);
        this._drawFootRigth(20, 58);
      }
    } else {
      this._drawFootLeft(36, 70);
      this._drawFootRigth(20, 70);
    }
  };

  Tyranno.prototype._drawMask = function() {
    this.ctx.save();
      this.fillStyle = this.color.stage;
      this.ctx.beginPath();
        this.ctx.rect(
          this.mask.top,
          this.mask.left,
          this.mask.width,
          this.mask.height  
        );
      this.ctx.fill();
    this.ctx.restore();
  };

  Tyranno.prototype._drawFootLeft = function(x, y) {
    this.ctx.rect(x,     y,      8, 4);
    this.ctx.rect(x + 4, y + 4,  4, 4);
    this.ctx.rect(x + 4, y + 8,  4, 4);
    this.ctx.rect(x + 4, y + 12, 8, 4);
  };

  Tyranno.prototype._drawFootRigth = function(x, y) {
    this.ctx.rect(x, y,      12, 4);
    this.ctx.rect(x, y + 4,  8,  4);
    this.ctx.rect(x, y + 8,  4,  4);
    this.ctx.rect(x, y + 12, 8,  4);
  };

  Tyranno.prototype._drawTail = function() {
    this.ctx.rect(0,  30, 4, 24);
    this.ctx.rect(4,  38, 4, 20);
    this.ctx.rect(8,  42, 4, 20);
    this.ctx.rect(12, 46, 4, 20);
    this.ctx.rect(16, 46, 4, 24);
  };

  Tyranno.prototype._drawEye = function() {
    this.ctx.rect(48, 6, 4, 4);
  };

  Tyranno.prototype.draw = function() {
    this.canvas.width  = this.canvas.width;
    this.canvas.height = this.canvas.height;

    this.ctx.save();
      this.ctx.fillStyle = this.color.stage;
      this.ctx.beginPath();
        this._drawMask();
      this.ctx.fill();
    this.ctx.restore();

    this.ctx.save();
      this.ctx.fillStyle = this.color.body;
      this.ctx.beginPath();
        this._drawHead(40, 0);
        this._drawBody(36, 30);
        this._drawHand(56, 38);
        this._drawFoot();
        this._drawTail();
      this.ctx.fill();
    this.ctx.restore();

    this.ctx.save();
      this.ctx.fillStyle = this.color.eye;
      this.ctx.beginPath();
        this._drawEye();
      this.ctx.fill();
    this.ctx.restore();

    this.stgCtx.drawImage(
      this.canvas,
      this.position.x,
      this.position.y
    );
  };

  ns.Tyranno = Tyranno;

})(this, document, App, $);




(function(win, doc, ns, $) {

  "use strict";

  var canvas        = doc.getElementById("canvas"),
      ctx           = canvas.getContext("2d"),
      CANVAS_WIDTH  = 300,
      CANVAS_HEIGHT = 300,
      START_EVENT   = "keypress";

  var stage          = new ns.Stage(ctx, CANVAS_WIDTH),
      tyranno        = new ns.Tyranno(ctx);

  _init();

  function _init() {
    _setCanvasSize();
    setInterval(_draw, 100);
  }

  function _setCanvasSize() {
    canvas.width         = CANVAS_WIDTH;
    canvas.height        = CANVAS_HEIGHT;
  }

  function _draw() {
    _setCanvasSize();

    stage.draw();
    tyranno.draw();
  }

})(this, document, App, $);

SCSS

body {
    background: #f7f7f7;
}

#canvas {
    position: absolute;
    top: 50%; left: 50%;
    margin: -150px;
}

つくりかけなんで使ってないメソッドがいくつかありますが、今回はこんな感じです。