var imageCacher = new function(){
  var onLoadCache = {}, imageCache = {};
  var thisObj;
//-------------------------------------
//  載入圖片
//-------------------------------------
  function loadImage(url, callback){
    var image = imageCache[url];
    if (image == undefined){ //還沒有開始載入圖片
      imageCache[url] = (image = new Image());
      image.crossOrigin = "anonymous"; //use CORS //https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes
      onLoadCache[url] = (callback ? [callback] : []);
      image.onload = function(){
        onLoadCache[url].forEach(function(s){ s(image); });
        delete onLoadCache[url];
      };
      image.src = url;
    }else if (onLoadCache[url] == undefined){ //已經開始載入圖片，且已經載入完成了
      if (callback) callback(image);
    }else{ //已經開始載入圖片，但還沒有載入好
      if (callback) onLoadCache[url].push(callback);
    }
  }
  return thisObj = {
    onload: function(url, callback){
      if (url == undefined) return; //missing assets
      if (url.getKey){ //sprite
      	alert('not support');
        //loadSprite(url, callback);
      }else{
        loadImage(url, callback);
      }
    },
    ifloaded: function(url, callback){
      var image = imageCache[url];
      if (image == undefined){
        thisObj.onload(url);
      }else if (onLoadCache[url] == undefined){
        callback(image);
      }
    },
    loadBy: function(url, onMissFunc){
      if (imageCache[url] == undefined) imageCache[url] = onMissFunc();
      return imageCache[url];
    }
  };
};
//-------------------------------------
//  requestAnimFrame
//-------------------------------------
window.requestAnimFrame = function(){
  return (
    window.requestAnimationFrame       ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame    ||
    window.oRequestAnimationFrame      ||
    window.msRequestAnimationFrame     ||
    function(callback){
      window.setTimeout(callback, 1000 / 60);
    }
  );
}();
//-------------------------------------
//  main
//-------------------------------------
var Input = new function(){
	var statuses = {}, counter = {};
	function getCount(key){
		var count = counter[key];
		return (count == undefined ? 0 : count);
	}
	return {
		KEYS: {
			ENTER: 13,
			SPACE: 32
		},
		onKeyPressed: function(key){
			statuses[key] = true;
		},
		update: function(){
			_.each(Input.KEYS, function(key){
				if (statuses[key]){
					counter[key] = (counter[key] || 0) + 1;
				}else{
					delete counter[key];
				}
			});
			statuses = {};
			//console.log(counter); //DEBUG
		},
		pressed: function(key){
			return (getCount(key) > 0);
		},
		triggered: function(key){
			return (getCount(key) == 1);
		}
	};
};
var sceneManager = new function(){
	var scenes = [];
	return {
		goto: function(scene){
			scenes.unshift(scene);
		},
		back: function(){
			return scenes.shift();
		},
		update: function(){
			var scene = scenes[0];
			if (scene) scene.update();
		},
		render: function(canvas){
			var scene = scenes[0];
			if (scene) scene.render(canvas);
		}
	};
}
$(function(){
  $(window).keypress(function(e){ Input.onKeyPressed(e.which) });
  var canvas = $('#game_canvas')[0];
  var ctx = canvas.getContext("2d");
  sceneManager.goto(new MenuScene()); //first scene //TODO game menu scene
  ;(function(fps){
    var interval = 1000 / fps;
    var prevTime = Date.now();
    ;(function loop(){
      window.requestAnimFrame(loop);
      var now = Date.now();
      var delta = now - prevTime;
      if (delta < interval) return;
      var deltaRatio = delta / interval; //經過的時間與預計的時間的比例。數字越高代表越LAG。
      prevTime += delta - (delta % interval); //若requestAnimFrame是60FPS時，delta會是16ms的倍數。要減掉delta % interval否則會多算時間。
			Input.update();
      sceneManager.update(deltaRatio);
      ctx.clearRect(0, 0, canvas.width, canvas.height);
			sceneManager.render(canvas);
    })();
  }(40));
});
//-------------------------------------
//  MenuScene
//-------------------------------------
function MenuScene(){
	return {
		update: function(deltaRatio){
			if (Input.pressed(Input.KEYS.ENTER)){
				//TODO sound && animation?
				sceneManager.goto(new MapScene());
			} 
		},
		render: function(canvas){
			var ctx = canvas.getContext("2d");
			imageCacher.ifloaded('images/menu.jpg', function(image){
				ctx.drawImage(image, 0, 0, canvas.width, canvas.height);	
			});
		}
	};
}
//-------------------------------------
//  MapScene
//-------------------------------------
function MapScene(){
	var playerX = 0;
	return {
		update: function(deltaRatio){
			playerX += 8; //keep running
		},
		render: function(canvas){
			var ctx = canvas.getContext("2d");
			imageCacher.ifloaded('images/background.jpg', function(image){
				var ratio = 0.08;
				var width = Math.floor(image.width * (canvas.height / image.height));
				var dx = -Math.floor(playerX * ratio) % width;
				while(dx < canvas.width){
					ctx.drawImage(image, dx, 0, width, canvas.height);	
					dx += width;
				}
			});
			imageCacher.ifloaded('images/ground.png', function(image){
				var width = Math.floor(image.width * (canvas.height / image.height));
				var dx = -playerX % width;
				while(dx < canvas.width){
					ctx.drawImage(image, dx, 0, width, canvas.height);	
					dx += width;
				}
			});
		}
	};
}











@@ -4719,10 +4719,9 @@
 = 0.
-08
+1
 ;%0A%09%09
@@ -4730,35 +4730,24 @@
 var width = 
-Math.floor(
 image.width 
@@ -4770,33 +4770,32 @@
  / image.height)
-)
 ;%0A%09%09%09%09var dx = -
@@ -4794,26 +4794,16 @@
 r dx = -
-Math.floor
 (playerX
@@ -5021,19 +5021,8 @@
 h = 
-Math.floor(
 imag
@@ -5061,17 +5061,16 @@
 .height)
-)
 ;%0A%09%09%09%09va

deal with float point render