HetaJs

Camera


https://www.glowscript.org/docs/GlowScriptDocs/canvas.html

Java Script

(function() {
  var Camera = function(context, settings) {
    settings = settings || {};
    this.distance = 1000.0;
    this.lookat = [0,0];
    this.context = context;
    this.fieldOfView = Math.tan(Math.PI / 4.0).toFixed(6);	//0.9999999 라서 거의 1입니다. 
    this.viewport = {
      left: 0,
      right: 0,
      top: 0,
      bottom: 0,
      width: 0,
      height: 0,
      scale: [1.0, 1.0]
    };
    this.updateViewport();
  };

  Camera.prototype = {
    begin: function() {
      this.context.save();
      this.applyScale();
      this.applyTranslation();
    },
    end: function() {
      this.context.restore();
    },
    applyScale: function() {
      this.context.scale(this.viewport.scale[0], this.viewport.scale[1]);
    },
    applyTranslation: function() {
      this.context.translate(-this.viewport.left, -this.viewport.top);
    },
    updateViewport: function() {
      this.aspectRatio = this.context.canvas.width / this.context.canvas.height;
      this.viewport.width = this.distance * this.fieldOfView;
      this.viewport.height = this.viewport.width / this.aspectRatio;
      this.viewport.left = this.lookat[0] - (this.viewport.width / 2.0);
      this.viewport.top = this.lookat[1] - (this.viewport.height / 2.0);
      this.viewport.right = this.viewport.left + this.viewport.width;
      this.viewport.bottom = this.viewport.top + this.viewport.height;
      this.viewport.scale[0] = this.context.canvas.width / this.viewport.width;
      this.viewport.scale[1] = this.context.canvas.height / this.viewport.height;
    },
    zoomTo: function(z) {
      this.distance = z;
      this.updateViewport();
    },
    moveTo: function(x, y) {
      this.lookat[0] = x;
      this.lookat[1] = y;
      this.updateViewport();
    },
    screenToWorld: function(x, y, obj) {
      obj = obj || {};
      obj.x = (x / this.viewport.scale[0]) + this.viewport.left;
      obj.y = (y / this.viewport.scale[1]) + this.viewport.top;
      return obj;
    },
    worldToScreen: function(x, y, obj) {
      obj = obj || {};
      obj.x = (x - this.viewport.left) * (this.viewport.scale[0]);
      obj.y = (y - this.viewport.top) * (this.viewport.scale[1]);
      return obj;      
    }
  };

  this.Camera = Camera;
  
}).call(this);







// ========================================= 객체 생성 관련 
// This file is for crap not relevant to this discussion
var findRequestAnimationFrame = function() {
    return window.requestAnimationFrame        || 
      window.webkitRequestAnimationFrame  || 
      window.mozRequestAnimationFrame     || 
      window.oRequestAnimationFrame       || 
      window.msRequestAnimationFrame      ||
      function(callback, element){
        window.setTimeout(callback, 1000 / 30);
      };
};

var Wall = function(x, y, width, height) {
  this.x = x;
  this.y = y;
  this.width = width;
  this.height = height;
};

Wall.prototype = {
  draw: function(context) {
    context.beginPath();
    context.moveTo(this.x, this.y);
    context.lineTo(this.x + this.width, this.y);
    context.lineTo(this.x + this.width, this.y + this.height);
    context.lineTo(this.x, this.y + this.height);
    context.lineTo(this.x, this.y);
    context.stroke();
  }
};

var Sprite = function(x, y, width, height, colour) {
  this.x = x;
  this.y = y;
  this.velx = Math.random() * 2.0 - 1.0;
  this.vely = Math.random() * 2.0 - 1.0;
  this.width = width;
  this.height = height;
  this.colour = colour;
};
Sprite.prototype = {
  tick: function() {
    this.x += this.velx;
    this.y += this.vely;
  },
  draw: function(context) {
    context.fillStyle = this.colour;
    context.fillRect(this.x, this.y, this.width, this.height);
  }
};

var ObjectPool = function(wall, numObjects) {
  this.objects = [];
  this.wall = wall;
  this.numObjects = numObjects;
  this.createObjects();
};

ObjectPool.prototype = {
  createObjects: function() {
    for(var i = 0; i < this.numObjects; i++) {
      var width = Math.random() * 50.0 + 10.0;
      var height = Math.random() * 50.0 + 10.0;
      var x = this.wall.x + (Math.random() * (this.wall.width - width));
      var y = this.wall.y + (Math.random() * (this.wall.height - height));
      this.objects.push(new Sprite(x, y, width, height, '#000'));
    }
  },
  tick: function() {
    this.objects.forEach(function(item) {
      item.tick();
    });
    this.collide();
  },
  draw: function(context) {
    this.objects.forEach(function(item) {
      item.draw(context);
    });
  },
  collide: function() {
    for(var i =0; i < this.objects.length; i++){
      this.collideWalls(this.objects[i]);
      for(var j = i ; j < this.objects.length; j++) {
        var obj1 = this.objects[i];
        var obj2 = this.objects[j];
        this.collideObjects(obj1, obj2);
      }
    }
  },
  collideObjects: function(one, two) {
    if(one.x + one.width < two.x)
      return;
    if(two.x + two.width < one.x)
      return;
    if(one.y + one.height < two.y)
      return;
    if(two.y + two.height < one.y)
      return;

    var tx = one.velx;
    var ty = one.vely;
    one.velx = two.velx;
    one.vely = two.vely;
    two.velx = tx;
    two.vely = ty;
  },
  collideWalls: function(obj) {
    if(obj.x < this.wall.x || obj.x + obj.width > this.wall.x + this.wall.width)
      obj.velx = -obj.velx;
    if(obj.y < this.wall.y || obj.y + obj.height > this.wall.y + this.wall.height)
      obj.vely = -obj.vely;
  }
};













// ========================================= 객체 생성 관련 

// start the game when page is loaded
$(document).ready(function() {
  var canvas = document.getElementById('target');
  var context = canvas.getContext('2d');
  var camera = new Camera(context);
  var renderFrame = findRequestAnimationFrame();
  var objects = [];

  var updateScene = function() {
    objects.forEach(function(item) {
      if(item.tick) item.tick();
    });
  };

  var drawScene = function() {
    context.clearRect(0, 0, canvas.width, canvas.height);
    camera.begin();
    objects.forEach(function(item) {
      if(item.draw) item.draw(context);
    });
    camera.end();
  };

  var tick = function() {
    updateScene();
    drawScene();
    renderFrame(tick);
  };

  var wall = new Wall(-300, -300, 600, 600);  
  objects.push(wall);
  objects.push(new ObjectPool(wall, 10));
  renderFrame(tick);
});