+++ /dev/null
-/*
-****PCD-2013 GameScriptCoreLibrary****
-Tokyo Gakugei University Senior High School.
-
-<Usage>
-HTMLソース側に、
-<div id="MainArea">
-</div>
-<div id="Resources">
-</div>
-が必要。
-
-<Javascript Tips>
-document.getElementById("main").style.display = "none";
-(mainというIDが振られている要素の表示を消す)
-this.effectSound.pause();
-this.effectSound.currentTime = 0;
-this.effectSound.play();
-this.backgroundImage = new Image();
-this.backgroundMusic = document.getElementById('BGM006');
-this.effectSound = document.getElementById('SE_Select');
-画像読み込み
-this.backgroundImage.manager = this;
-this.backgroundImage.onload = this.backgroundLoaded;
-this.backgroundImage.src = "title.gif";
-
-音楽再生
-this.backgroundMusic.loop = true;
-this.backgroundMusic.play();
-
-MicrosoftInternetExplorerでは、ローカル変数でparentを使うとappendChildが使えなくなる…。
-
-<About collision checking>(このあたりはまだドラフト)
-ステージオブジェクトの最小単位を8x8とする。
-*/
-
-//
-//定数
-//
-var URL_PCD_Root = "http://192.168.6.242/";
-var URL_PCD_Auth = URL_PCD_Root + "auth.php";
-var URL_PCD_Stage = URL_PCD_Root + "stage/";
-
-//
-//ゲームマネージャー
-//
-
-function GameManager(){
- //****コンストラクタ****
- //**インスタンス変数宣言・初期化**
- //ユーザーID
- this.userID = 0;
- //ネットワークマネージャーの設定
- this.networkManager = new NetworkManager();
- //必要最低限のCanvasとコンテキストの設定
- this.mainCanvas = createCanvas("MainCanvas", 640, 480, 0, 0, 1, "MainArea");
- this.mainCanvas.style.border = "solid 1px";
- this.debugCanvas = createCanvas("DebugCanvas", 640, 480, 0, 480, 2, "MainArea");
- this.mainContext = this.mainCanvas.getContext('2d');
- this.debugContext = this.debugCanvas.getContext('2d');
- this.debugText = document.getElementById('DebugText');
- //実行中のGameStageオブジェクトを格納
- this.runningStage = null;
- //タイマーカウントを初期化
- this.tickCount = 0;
- this.timeStamp = 0;
- //タイマーカウントの秒あたりの回数を設定
- this.tickPerSecond = 60;
- //キーボード状態を格納するプロパティの設定
- this.keyState = new Object();
- this.keyState.upArrow = false;
- this.keyState.downArrow = false;
- this.keyState.leftArrow = false;
- this.keyState.rightArrow = false;
-
- //**描画コンテキスト取得、設定・HTML5対応チェック**
- if(!this.mainCanvas || !this.mainCanvas.getContext){
- //HTML5未対応の場合
- alert("このゲームを遊ぶためには、HTML5に対応しているブラウザでアクセスしてください...。");
- return false;
- }
-
- //**Canvas描画コンテキストの初期設定**
- //mainContext
- this.mainContext.fillStyle = "rgba(200,255,200,0.5)";
- this.mainContext.strokeStyle = "rgba(0, 0, 0, 0.5)";
- //debugContext
- this.debugContext.fillStyle = "rgb(255,255,255)";
- this.debugContext.strokeStyle = "rgb(0, 0, 0)";
- this.debugContext.font = "normal 20px sans-serif";
-
- //**イベントリスナー設定**
- //コールバックを行うために、イベントリスナーのmanagerプロパティにGameManagerのインスタンスを代入する。
- //keyDown
- keyDownEventListener.manager = this;
- window.addEventListener('keydown', keyDownEventListener, true);
- //keyUp
- keyUpEventListener.manager = this;
- window.addEventListener('keyup', keyUpEventListener, true);
- //timerTick
- timerTickEventListener.manager = this;
- window.setInterval(timerTickEventListener, 1000/this.tickPerSecond);
- timeStampTimerTickEventListener.manager = this;
- window.setInterval(timeStampTimerTickEventListener, 100);
-}
-GameManager.prototype = {
- //****プロトタイプ宣言****
- //prototype以下のプロパティは、新規インスタンスに参照が引き継がれる。
- keyDown: function(event){
- //****keyDown****
- //コールバックではなくコールバック関数(keyDownEventListener)から呼び出されるので、thisはGameManagerのインスタンスとなる。
- keyCode = event.keyCode;
- switch(event.keyCode){
- case 38:
- //上カーソル
- this.keyState.upArrow = true;
- event.preventDefault();
- break;
- case 40:
- //下カーソル
- this.keyState.downArrow = true;
- event.preventDefault();
- break;
- case 37:
- //左カーソル
- this.keyState.leftArrow = true;
- event.preventDefault();
- break;
- case 39:
- //右カーソル
- this.keyState.rightArrow = true;
- event.preventDefault();
- break;
- }
-
- this.debugOut("keyDw:" + keyCode + "\n");
- //実行中のステージに通知
- if(this.runningStage){
- this.runningStage.keyDown(event);
- }
- },
- keyUp: function(event){
- //****keyUp****
- //コールバックではなくコールバック関数(keyUpEventListener)から呼び出されるので、thisはGameManagerのインスタンスとなる。
- keyCode = event.keyCode;
- switch(event.keyCode){
- case 38:
- //上カーソル
- this.keyState.upArrow = false;
- break;
- case 40:
- //下カーソル
- this.keyState.downArrow = false;
- break;
- case 37:
- //左カーソル
- this.keyState.leftArrow = false;
- break;
- case 39:
- //右カーソル
- this.keyState.rightArrow = false;
- break;
- }
-
- this.debugOut("keyUp:" + keyCode + "\n");
- //実行中のステージに通知
- if(this.runningStage){
- this.runningStage.keyUp(event);
- }
- },
- timerTick: function(){
- //****timerTick****
- this.tickCount++;
- //実行中のステージに通知
- if(this.runningStage){
- this.runningStage.timerTick();
- }
- },
- timeStampTimerTick: function(){
- //サーバーとの同期カウンタ・タイマー
- this.timeStamp += 10;
- drawText(this.debugContext, "timeStamp:" + this.timeStamp, 0, 40);
- },
- runStage: function(stage){
- //****新たなステージを開始する****
- //実行中のステージがあれば終了処理を行わせる。
- if(this.runningStage){
- this.stopStage();
- }
- //**新たに開始するステージの初期化**
- //GameManager側の情報をGameStageに渡す。
- stage.manager = this;
- stage.mainCanvas = this.mainCanvas
- stage.debugCanvas = this.debugCanvas
- stage.mainContext = this.mainContext
- stage.debugContext = this.debugContext
- //GameStage側の初期化処理を行わせる。
- stage.runStage();
- //runningStageに登録することで、イベントの通知が開始され、GameStageは実行状態に入る。
- this.runningStage = stage;
- },
- stopStage: function(){
- //****現在実行中のステージを終了する****
- if(this.runningStage){
- //runningStageから解除することで、イベントの通知は行われなくなる。
- var aGameStage = this.runningStage;
- this.runningStage = null;
- //GameStage側の終了処理を行わせる。
- aGameStage.stopStage();
- //GameStageインスタンスからGameManagerの情報を削除する。
- aGameStage.manager = null;
- aGameStage.mainCanvas = null;
- aGameStage.debugCanvas = null;
- aGameStage.mainContext = null;
- aGameStage.debugContext = null;
- }
- },
- loadStageFromNetwork: function(name, onLoaded){
- //urlに存在するjavascriptファイルを利用してステージを作成する。
- request = this.networkManager.CreateRequestObject();
- request.onLoaded = onLoaded;
- request.onreadystatechange = this.loadStageFromNetwork_HTTPStateChange
- request.open('GET', URL_PCD_Stage + name + ".js");
- request.send(null);
- },
- loadStageFromNetwork_HTTPStateChange: function(){
- //requestコールバックなのでthisはrequest!
- switch(this.readyState){
- case 0:
- //console.log("XMLHttpRequest created.");
- break;
- case 1:
- //console.log("open() called.");
- break;
- case 2:
- //console.log("Response header received.");
- break;
- case 3:
- //console.log("Response body receiving.");
- break;
- case 4:
- //mainManager.debugOut("send() compleated.\n");
- //mainManager.debugOut("status:" + this.status + ":" + this.statusText + "\n");
- if(this.status == 0){
- alert("ネットワークにアクセスできません。" + this.status + ":" + this.statusText);
- }else if((200 <= this.status && this.status < 300) || (this.status == 304)){
- //console.log("ACK");
- stage = new GameStage();
- eval(this.responseText);
- if(this.onLoaded != null){
- this.onLoaded(stage);
- } else{
- mainManager.runStage(stage);
- }
- }else{
- alert("サーバーがエラーを返しました。" + this.status + ":" + this.statusText);
- }
- break;
- }
- },
- debugOut: function(str){
- if(!/*@cc_on!@*/false)
- {
- this.debugText.value = str.replace(/\n/g,"\r\n") + this.debugText.value;
- }
- else
- {
- this.debugText.innerHTML = str + this.debugText.value;
- }
- },
-};
-
-//
-//ゲームステージ
-//
-
-function GameStage(){
- //****コンストラクタ****
- //**インスタンス変数宣言・初期化**
- //タイマーカウントを初期化
- this.tickCount = 0;
- //GameManagerから渡されるプロパティ
- this.manager = null;
- this.mainCanvas = null;
- this.debugCanvas = null;
- this.mainContext = null;
- this.debugContext = null;
- //StageObjectのリスト
- this.stageObjectList = new Array();
- //オーバーライドされる可能性のある関数の保存
- //this.super = new Object();
- //上記の方法では、thisがsuperになってしまい動作しないので、同一階層に関数の参照を作成することになった。
- this.super_keyDown = this.keyDown;
- this.super_keyUp = this.keyUp;
- this.super_timerTick = this.timerTick;
- this.super_runStage = this.runStage;
- this.super_stopStage = this.stopStage;
- this.super_addStageObject = this.addStageObject;
- this.super_removeStageObject = this.removeStageObject;
- //衝突判定用canvas
- this.collisionMapCanvas = null;
- this.collisionMapContext = null;
-}
-GameStage.prototype = {
- //以下の関数をオーバーライドしてステージを作成する。
- keyDown: function(event){
- //キー入力
- },
- keyUp: function(event){
- //キー入力
- },
- timerTick: function(){
- //タイマー
-
- this.tickCount++;
- drawText(this.debugContext, "tick:" + this.tickCount, 0, 20);
-
- //キャンバスを全消去
- this.mainContext.clearRect(0, 0, this.mainCanvas.width, this.mainCanvas.height);
- this.collisionMapContext.clearRect(0, 0, this.collisionMapCanvas.width * 8, this.collisionMapCanvas.height * 8);
- //全てのオブジェクトを再描画
-
- for(i = 0; i < this.stageObjectList.length; i++){
- this.stageObjectList[i].display();
- }
- },
- runStage: function(){
- //ステージ初期化処理
- this.tickCount = 0;
- //衝突マップ初期化
- this.collisionMapCanvas = createCanvas("collisionMapCanvas", this.mainCanvas.width, this.mainCanvas.height, this.mainCanvas.width, 0, 1, "MainArea");
- this.collisionMapContext = this.collisionMapCanvas.getContext('2d');
- this.collisionMapContext.fillStyle = "rgba(0,0,0, 0.2)";
- this.collisionMapContext.strokeStyle = "rgba(0,0,0, 0.2)";
- this.collisionMapContext.scale(1, 1);
- },
- stopStage: function(){
- //ステージ終了処理
- destroyDOMObjectByID(this.collisionMapCanvas.id);
- this.collisionMapCanvas = null;
- this.collisionMapContext = null;
- this.stageObjectList = null;
- },
- addStageObject: function(aStageObject){
- //StageObject追加処理
- this.stageObjectList.push(aStageObject);
- },
- removeStageObject: function(aStageObject){
- //StageObject削除処理
- removeObjectFromArray(this.stageObjectList, aStageObject);
- }
-}
-
-//
-//キャラクター
-//
-
-function StageObject(aStage){
- this.stage = aStage;
- this.origin = new Point2D(10, 10);
- //originを中心とした座標でのオブジェクトの描画面のサイズ
- this.frame = new Rectangle(-8, -8, 16, 16);
- this.movingSpeed = new Point2D(0, 0);
- //2 * hysteresis >= movingFrictionであることを推奨する。
- //そうでない場合、摩擦での減速後に完全に停止できない可能性がある。
- this.movingFriction = 90;
- this.hysteresis = this.movingFriction / 2;
- //実体を持たない、つまり衝突判定が必要ない場合はtrue.
- this.isPhantom = false;
- //console.log("StageObject:Init");
-}
-StageObject.prototype = {
- display: function(){
- //再描画時に呼ばれる。
- this.computeTickMoving();
- this.computeTickFriction();
- this.computeTickBounding();
- //弧の描画
- this.stage.mainContext.save();
- this.stage.mainContext.fillStyle = "rgba(" + (((11*this.frame.size.x) & 0x7f) + 0x80) + "," + (((19*this.frame.size.x) & 0x7f) + 0x80) + "," + (((17*this.frame.size.x) & 0x7f) + 0x80) + ",0.5)";
- drawArcDegree(this.stage.mainContext, this.frame.size.x / 2, 0, 360, this.origin.x, this.origin.y, false);
- this.stage.mainContext.restore();
- //衝突マップに描画
- strokeRect(this.stage.collisionMapContext, this.origin.x + this.frame.origin.x, this.origin.y + this.frame.origin.y, this.frame.size.x, this.frame.size.y);
- },
- computeTickFriction: function(){
- //摩擦処理
- if(this.movingSpeed.x < -this.hysteresis){
- this.movingSpeed.x += this.movingFriction / this.stage.manager.tickPerSecond;
- } else if(this.movingSpeed.x > this.hysteresis){
- this.movingSpeed.x -= this.movingFriction / this.stage.manager.tickPerSecond;
- } else{
- this.movingSpeed.x = 0;
- }
- if(this.movingSpeed.y < -this.hysteresis){
- this.movingSpeed.y += this.movingFriction / this.stage.manager.tickPerSecond;
- } else if(this.movingSpeed.y > this.hysteresis){
- this.movingSpeed.y -= this.movingFriction / this.stage.manager.tickPerSecond;
- } else{
- this.movingSpeed.y = 0;
- }
- },
- computeTickMoving: function(){
- //運動処理
- this.origin.x += this.movingSpeed.x / this.stage.manager.tickPerSecond;
- this.origin.y += this.movingSpeed.y / this.stage.manager.tickPerSecond;
- },
- computeTickBounding: function(){
- //壁面跳ね返り処理
- if(this.origin.x < -this.frame.origin.x){
- //左壁面
- this.origin.x = -this.frame.origin.x;
- this.movingSpeed.x = -this.movingSpeed.x;
- } else if(this.origin.x > this.stage.mainCanvas.width - (this.frame.origin.x + this.frame.size.x)){
- //右壁面
- this.origin.x = this.stage.mainCanvas.width - (this.frame.origin.x + this.frame.size.x);
- this.movingSpeed.x = -this.movingSpeed.x;
- }
- if(this.origin.y < -this.frame.origin.y){
- //上壁面
- this.origin.y = -this.frame.origin.y;
- this.movingSpeed.y = -this.movingSpeed.y;
- } else if(this.origin.y > this.stage.mainCanvas.height - (this.frame.origin.y + this.frame.size.y)){
- //下壁面
- this.origin.y = this.stage.mainCanvas.height - (this.frame.origin.y + this.frame.size.y);
- this.movingSpeed.y = -this.movingSpeed.y;
- }
- },
-}
-
-//
-//その他のクラス
-//
-
-function Point2D(x, y){
- this.x = x;
- this.y = y;
-}
-Point2D.prototype = {
-
-}
-
-function Rectangle(x, y, width, height){
- this.origin = new Point2D(x,y);
- this.size = new Point2D(width,height);
-}
-Rectangle.prototype = {
-
-}
-
-function ResourceManager(){
- //Not implemented.
- this.resourceObjectList = new Array();
-
- this.ResourceTag.prototype = {
-
- }
-}
-ResourceManager.prototype = {
- //Not implemented.
- addAudioResource: function(id, src){
- dobj = document.createElement("audio");
- parent = document.getElementById("Resources");
- dobj.id = id;
- parent.appendChild(dobj);
-
- this.resourceObjectList.push(dobj);
-
- dobj.isLoaded = false;
- dobj.onload = this.resourceLoaded;
- dobj.src = src;
- },
- resourceLoaded: function(){
- //コールバック関数のthisはコールバック関数の設定先オブジェクト(DOMObject)となる。
- this.isLoaded = true;
- },
- waitForLoadResource: function(){
- for(;;){
- for(i = 0; i < resourceObjectList.length; i++){
- if(!resourceObjectList[i].isLoaded){
-
- break;
- }
- }
- if(i == resourceObjectList.length){
- return;
- }
- }
- },
-}
-
-function NetworkManager(){
-
-}
-NetworkManager.prototype = {
-//from http://hakuhin.jp/js/xmlhttprequest.html
- CreateRequestObject: function(){
- // XMLHttpRequest
- try{
- // XMLHttpRequest オブジェクトを作成
- return new XMLHttpRequest();
- }catch(e){}
- // Internet Explorer
- try{
- return new ActiveXObject('MSXML2.XMLHTTP.6.0');
- }catch(e){}
- try{
- return new ActiveXObject('MSXML2.XMLHTTP.3.0');
- }catch(e){}
- try{
- return new ActiveXObject('MSXML2.XMLHTTP');
- }catch(e){}
- // 未対応
- return null;
- },
- HTTPStateChange: function(){
- //requestコールバックなのでthisはrequest!
- switch(this.readyState){
- case 0:
- //console.log("XMLHttpRequest created.");
- break;
- case 1:
- //console.log("open() called.");
- break;
- case 2:
- //console.log("Response header received.");
- break;
- case 3:
- //console.log("Response body receiving.");
- break;
- case 4:
- //console.log("send() compleated.");
- //console.log("status:" + this.status + ":" + this.statusText);
- if(this.status == 0){
- console.log("Error");
- }else if((200 <= this.status && this.status < 300) || (this.status == 304)){
- console.log("ACK");
- }else{
- //console.log("NAK");
- }
- alert(this.responseText);
- break;
- }
- }
-}
-
-//
-//サブルーチン
-//
-
-function createCanvas(id, width, height, x, y, z, parent)
-{
- //識別名idで
- //width * heightの大きさのCanvasを
- //(x,y,z)に生成する。
- //parentには、Canvasタグを包含することになるDOMオブジェクトのidを指定する。
- canvas = document.createElement("canvas");
- parent = document.getElementById(parent);
-
- canvas.id = id;
-
- parent.appendChild(canvas);
-
- canvas.style.position = "absolute";
- canvas.style.top = y + "px";
- canvas.style.left = x + "px";
- canvas.style.zIndex = z;
-
- canvas.width = width;
- canvas.height = height;
-
- return canvas;
-}
-
-function createCanvas(id, width, height, x, y, z, parent)
-{
- //識別名idで
- //width * heightの大きさのCanvasを
- //(x,y,z)に生成する。
- //parentには、Canvasタグを包含することになるDOMオブジェクトのidを指定する。
- canvas = document.createElement("canvas");
- parent = document.getElementById(parent);
-
- canvas.id = id;
-
- parent.appendChild(canvas);
-
- canvas.style.position = "absolute";
- canvas.style.top = y + "px";
- canvas.style.left = x + "px";
- canvas.style.zIndex = z;
-
- canvas.width = width;
- canvas.height = height;
-
- return canvas;
-}
-
-function createDOMObject(typestr, idstr, parentidstr)
-{
- dobj = document.createElement(typestr);
- parentObj = document.getElementById(parentidstr);
-
- dobj.id = idstr;
- parentObj.appendChild(dobj);
-
- return dobj;
-}
-
-function destroyDOMObjectByID(id)
-{
- //識別名idのDOMオブジェクトを破棄する。
- object = document.getElementById(id);
- parentObj = object.parentNode;
-
- parentObj.removeChild(object);
-}
-
-function removeObjectFromArray(anArray, anObject)
-{
- //anArray中にある全てのanObjectを削除し、空いた部分は前につめる。
- for(i = 0; i < anArray.length; i++){
- if(anArray[i] == anObject){
- anArray.splice(i, 1);
- }
- }
-}
-
-//
-//イベントリスナー
-//
-//イベントリスナーにおけるthisは、イベントリスナーを登録したオブジェクトになり、通常とは異なるので注意。
-
-function keyDownEventListener(event)
-{
- keyDownEventListener.manager.keyDown(event);
-}
-
-function keyUpEventListener(event)
-{
- keyUpEventListener.manager.keyUp(event);
- event.preventDefault();
-}
-
-function timerTickEventListener(event)
-{
- timerTickEventListener.manager.timerTick(event);
-}
-
-function timeStampTimerTickEventListener(event)
-{
- timerTickEventListener.manager.timeStampTimerTick(event);
-}
-
-//
-//Canvas直接描画関連
-//
-
-function drawText(gcontext, text, x, y)
-{
- //背景をfillStyle
- //前景をstrokeStyleで塗りつぶした文字列を描画する
- //塗りつぶし高さは20px固定
- //fillTextの座標は文字列の左下!
- textsize = gcontext.measureText(text);
- gcontext.fillRect(x, y, textsize.width, 20);
- gcontext.save();
- gcontext.fillStyle = gcontext.strokeStyle;
- gcontext.fillText(text, x, y + 20 - 1);
- gcontext.restore();
-}
-
-function drawArcDegree(gcontext, radius, startAngleDegree, endAngleDegree, x, y, anticlockwise)
-{
- //半径radius, 中心座標(x,y)の円弧の、
- //startAngleDegreeからendAngleDegreeまでの範囲を、
- //(!anticlockwise)=時計回り
- //(anticlockwise) =反時計回り
- //に描画する。
- //角度は度を利用する。
- startAngleRadian = startAngleDegree * Math.PI / 180;
- endAngleRadian = endAngleDegree * Math.PI / 180;
-
- gcontext.beginPath();
- gcontext.arc(drawCoordinatesInInteger(x), drawCoordinatesInInteger(y), drawCoordinatesInInteger(radius), startAngleRadian, endAngleRadian, anticlockwise);
- gcontext.fill();
- gcontext.stroke();
- gcontext.closePath();
-}
-
-function fillRect(gContext, x, y, w, h)
-{
- gContext.fillRect(drawCoordinatesInInteger(x), drawCoordinatesInInteger(y), drawCoordinatesInInteger(w), drawCoordinatesInInteger(h));
-}
-
-function strokeRect(gContext, x, y, w, h)
-{
- gContext.strokeRect(drawCoordinatesInInteger(x), drawCoordinatesInInteger(y), drawCoordinatesInInteger(w), drawCoordinatesInInteger(h));
-}
-
-function drawCoordinatesInInteger(coordinateElement)
-{
- //from http://www.html5rocks.com/ja/tutorials/canvas/performance/
- // With a bitwise or.
- return ((0.5 + coordinateElement) | 0);
-}
-
-