2 ****PCD-2013 GameScriptCoreLibrary****
3 Tokyo Gakugei University Senior High School.
6 Mac OSX: Safari, Chrome
7 Windows: Chrome, IE(9 or later)
21 mainManager = new GameManager();
29 var loc = document.location.href;
31 var URL_PCD_Root = loc.slice(0, loc.lastIndexOf("/") + 1);
33 //var URL_PCD_Root = "http://localhost/pcd2013dev/www/";
34 //var URL_PCD_Root = "http://192.168.6.242/pcd2013dev/www/";
35 //var URL_PCD_Root = "http://192.168.0.3/PCD2013GSCL/www/";
36 //var URL_PCD_Root = "http://192.168.6.242/pcd2013hikarupsp/pcd2013dev/www/";
37 var URL_PCD_Auth = URL_PCD_Root + "auth.php";
38 var URL_PCD_Audio = URL_PCD_Root + "audio/";
39 var URL_PCD_Stage = URL_PCD_Root + "stage/";
41 // ゲームを呼び出す関数 適切なdiv要素で呼び出すとゲームを初期化できる。
43 // audio, corelib, images, stageの各フォルダをコピーしたdirにhtmlを置き、<div>.InitGameManager() と実行するスクリプトを書く
44 // stageName == nullだとステージを開始しない。指定する時は.jsおよびパスを省く
48 var CollideBottom = 4;
52 HTMLDivElement.prototype.InitGameManager = function(stageName)
54 if(this instanceof HTMLDivElement)
56 var man = new GameManager(this, null);
57 if(stageName) man.loadStageFromNetwork.apply(man, [stageName]);
61 throw new TypeError("InitGameManager はdiv要素にしか実行できません");
69 function GameManager(parent, debugTextName){
72 if(debugTextName == undefined) debugTextName = "DebugText";
73 if(parent == undefined) parent = document.getElementById("MainArea");
76 if(parent.style.position != 'absolute') parent.style.position = 'relative';
80 this.networkManager = new NetworkManager(this);
81 this.UIManager = new UIManager(this);
82 this.userManager = new UserManager(this);
83 this.mainArea = parent;
84 //必要最低限のCanvasとコンテキストの設定
85 this.mainCanvas = createCanvas("MainCanvas", 640, 480, 0, 0, 1, parent);
86 this.mainCanvas.style.border = "solid 1px";
87 this.mainContext = this.mainCanvas.getContext('2d');
88 this.debugText = document.getElementById(debugTextName); //要素が存在しないとnullになり、デバッグが無効になる
89 if(!this.debugText) this.debugText = null;
93 if(!this.isAvailableBrowser()){
97 this.mainContext.fillStyle = "rgba(200,255,200,0.5)";
98 this.mainContext.strokeStyle = "rgba(0, 0, 0, 0.5)";
99 this.mainContext.font = "normal 20px sans-serif";
100 //実行中のGameStageオブジェクトを格納
101 this.runningStage = null;
102 this.runningStageName = null;
103 //現在存在しているWidghetのリストを格納
104 this.runningWidghets = [];
108 //タイマーカウントの秒あたりの回数を設定
109 this.tickPerSecond = 60;
110 // pauseStage()が呼ばれたときにnullじゃなくなる
111 this.stagePausedFunction = null;
113 this.backgroundMusic = null;
114 this.addWidget(new UserStateWidgetClass(this));
116 //コールバックを行うために、イベントリスナーのmanagerプロパティにGameManagerのインスタンスを代入する。
118 timerTickEventListener.manager = this;
119 window.setInterval(timerTickEventListener, 1000/this.tickPerSecond);
121 GameManager.prototype = {
122 timerTick: function(){
123 //各オブジェクトの単位時間ごとの動作と再描画を行う
126 if(this.stagePausedFunction == null){
128 if(this.runningStage){
130 this.runningStage.timerTick();
133 // runningStage.timerTick() 内でpauseStage()された時、ここで再度判定しないとWidghetのtickが実行されてしまう
134 if(this.stagePausedFunction == null){
136 for(var i = 0; i < this.runningWidghets.length; i++){
137 var w = this.runningWidghets[i];
139 // Widghetのtick()からfalseで帰ってきたらWidghetを開放
140 this.removeWidget(w);
146 this.stagePausedFunction();
150 if(this.runningStage){
152 this.runningStage.draw();
155 for(var i = 0; i < this.runningWidghets.length; i++){
156 var w = this.runningWidghets[i];
160 //各オブジェクトの走査が終わってから、死亡判定およびステージ再読み込みを行う。
161 if(this.userManager.HP == 0){
163 this.UIManager.clearInput();
164 if(this.runningStageName){
165 this.loadStageFromNetwork(this.runningStageName);
167 //ローカルモード時は動作を停止させるだけ
170 this.userManager.HP = this.userManager.max_HP;
173 addWidget: function(w){
175 this.runningWidghets.push(w);
177 removeWidget: function(w){
178 removeObjectFromArray(this.runningWidghets, w);
181 runStage: function(stage){
183 //実行中のステージがあれば終了処理を行わせる。
184 if(this.runningStage){
188 //GameManager側の情報をGameStageに渡す。
189 stage.manager = this;
190 stage.mainCanvas = this.mainCanvas
191 stage.debugCanvas = this.debugCanvas
192 stage.mainContext = this.mainContext
193 stage.debugContext = this.debugContext
194 //GameStage側の初期化処理を行わせる。
197 this.networkManager.joinStage(stage);
198 //runningStageに登録することで、イベントの通知が開始され、GameStageは実行状態に入る。
199 this.runningStage = stage;
201 pauseStage: function(func){
202 //ステージの実行を一時停止する。一時停止中、funcに指定された関数が毎tick毎に呼ばれる
203 if(this.stagePausedFunction == null){
204 this.stagePausedFunction = func;
207 //ステージが一時停止中のfunc()の中から二重にpauseStage()を呼んではいけない
211 resumeStage: function(){
213 if(this.stagePausedFunction != null) {
214 //必ずpauseStage()の引数に指定したfunc()の中から呼ばれる・・・はず。
215 this.stagePausedFunction = null;
221 stopStage: function(){
223 if(this.runningStage){
224 //runningStageから設定解除することで、イベントの通知は行われなくなる。
225 var aGameStage = this.runningStage;
226 this.runningStage = null;
227 //GameStage側の終了処理を行わせる。
228 aGameStage.stopStage();
229 //GameStageインスタンスからGameManagerの情報を削除する。
230 aGameStage.manager = null;
231 aGameStage.mainCanvas = null;
232 aGameStage.debugCanvas = null;
233 aGameStage.mainContext = null;
234 aGameStage.debugContext = null;
237 loadStageFromLocal: function(code){
240 URL_PCD_Auth = URL_PCD_Root + "auth.php";
241 URL_PCD_Audio = URL_PCD_Root + "audio/";
242 URL_PCD_Stage = URL_PCD_Root + "stage/";
244 var stage = eval(code);
245 mainManager.runStage(stage);
247 loadStageFromNetwork: function(name){
248 //URL_PCD_Stage/name.jsを利用してステージを作成する。
249 request = this.networkManager.CreateRequestObject();
251 request.open('GET', URL_PCD_Stage + name + ".js", false);
252 this.networkManager.RequestObjectDisableCache(request);
255 if(request.status == 0){
256 alert("ネットワークにアクセスできません。" + request.status + ":" + request.statusText);
257 }else if((200 <= request.status && request.status < 300) || (request.status == 304)){
258 var stage = eval(request.responseText);
259 this.runStage(stage);
260 this.runningStageName = name;
262 alert("サーバーがエラーを返しました。" + request.status + ":" + request.statusText);
265 debugOut: function(str){
266 if(this.debugText != null)
271 this.debugText.value = str.replace(/\n/g,"\r\n") + this.debugText.value;
274 this.debugText.innerHTML = str + this.debugText.value;
278 isAvailableBrowser: function(){
279 //ブラウザの判別を行う。実行不可能な場合はfalseを返す。
280 //http://d.hatena.ne.jp/Naotsugu/20110927/1317140891
281 var userAgent = window.navigator.userAgent.toLowerCase();
282 var appVersion = window.navigator.appVersion.toLowerCase();
284 if (userAgent.indexOf('opera') != -1) {
286 this.debugOut("Browser:Opera\n");
287 } else if (userAgent.indexOf('msie') != -1) {
288 if (appVersion.indexOf("msie 9.") != -1) {
290 this.debugOut("Browser:IE9\n");
291 } else if (appVersion.indexOf("msie 8.") != -1) {
293 this.debugOut("Browser:IE8\n");
294 } else if (appVersion.indexOf("msie 7.") != -1) {
296 this.debugOut("Browser:IE7\n");
297 } else if (appVersion.indexOf("msie 6.") != -1) {
299 this.debugOut("Browser:IE6\n");
301 this.debugOut("Browser:IE?\n");
304 } else if (userAgent.indexOf('chrome') != -1) {
306 this.debugOut("Browser:Chrome\n");
307 } else if (userAgent.indexOf('safari') != -1) {
309 this.debugOut("Browser:Safari\n");
310 } else if (userAgent.indexOf('gecko') != -1) {
312 this.debugOut("Browser:Gecko\n");
315 this.debugOut("Browser:Unknown\n");
317 //描画コンテキストからHTML5対応チェック
318 if(!this.mainCanvas || !this.mainCanvas.getContext){
320 alert("このゲームを遊ぶためには、HTML5に対応しているブラウザ(Google Chrome等)でアクセスしてください...。");
325 setBackgroundMusic: function(name){
326 if(this.backgroundMusic){
328 this.backgroundMusic.pause();
329 this.backgroundMusic = null;
332 //引数がnullでなければaudioオブジェクトを取得
333 this.backgroundMusic = createAudio(name);
334 if(this.backgroundMusic){
336 this.backgroundMusic.loop = true;
337 this.backgroundMusic.play();
346 //イベントリスナーにおけるthisは、イベントリスナーを登録したオブジェクトまたはwindowになり、通常とは異なるので注意。
348 function timerTickEventListener(event)
350 timerTickEventListener.manager.timerTick(event);