OSDN Git Service

StageObject の記述を分割
[h58pcdgame/GameScriptCoreLibrary.git] / corelib / core.js
1 /*
2 ****PCD-2013 GameScriptCoreLibrary****
3 Tokyo Gakugei University Senior High School.
4
5 <Usage>
6 HTMLソース側に、
7 <div id="MainArea">
8 </div>
9 <div id="Resources">
10 </div>
11 が必要。
12
13 <Javascript Tips>
14 document.getElementById("main").style.display = "none";
15 (mainというIDが振られている要素の表示を消す)
16 this.effectSound.pause();
17 this.effectSound.currentTime = 0;
18 this.effectSound.play();
19 this.backgroundImage = new Image();
20 this.backgroundMusic = document.getElementById('BGM006');
21 this.effectSound = document.getElementById('SE_Select');
22 画像読み込み
23 this.backgroundImage.manager = this;
24 this.backgroundImage.onload = this.backgroundLoaded;
25 this.backgroundImage.src = "title.gif";
26
27 音楽再生
28 this.backgroundMusic.loop = true;
29 this.backgroundMusic.play();
30
31 MicrosoftInternetExplorerでは、ローカル変数でparentを使うとappendChildが使えなくなる…。
32
33 <About collision checking>(このあたりはまだドラフト)
34 ステージオブジェクトの最小単位を8x8とする。
35 */
36
37 //
38 //定数
39 //
40 var URL_PCD_Root = "http://192.168.6.242/";
41 var URL_PCD_Auth = URL_PCD_Root + "auth.php";
42 var URL_PCD_Stage = URL_PCD_Root + "stage/";
43
44 //
45 //ゲームマネージャー
46 //
47
48 function GameManager(){
49         //****コンストラクタ****
50         //**インスタンス変数宣言・初期化**
51         //ユーザーID
52         this.userID = 0;
53         //ネットワークマネージャーの設定
54         this.networkManager = new NetworkManager();
55         //必要最低限のCanvasとコンテキストの設定
56         this.mainCanvas = createCanvas("MainCanvas", 640, 480, 0, 0, 1, "MainArea");
57         this.mainCanvas.style.border = "solid 1px";
58         this.debugCanvas = createCanvas("DebugCanvas", 640, 480, 0, 480, 2, "MainArea");
59         this.mainContext = this.mainCanvas.getContext('2d');
60         this.debugContext = this.debugCanvas.getContext('2d');
61         this.debugText = document.getElementById('DebugText');
62         //実行中のGameStageオブジェクトを格納
63         this.runningStage = null;
64         //タイマーカウントを初期化
65         this.tickCount = 0;
66         this.timeStamp = 0;
67         //タイマーカウントの秒あたりの回数を設定
68         this.tickPerSecond = 60;
69         //キーボード状態を格納するプロパティの設定
70         this.keyState = new Object();
71         this.keyState.upArrow = false;
72         this.keyState.downArrow = false;
73         this.keyState.leftArrow = false;
74         this.keyState.rightArrow = false;
75         
76         //**描画コンテキスト取得、設定・HTML5対応チェック**
77         if(!this.mainCanvas || !this.mainCanvas.getContext){
78                 //HTML5未対応の場合
79                 alert("このゲームを遊ぶためには、HTML5に対応しているブラウザでアクセスしてください...。");
80                 return false;
81         }
82         
83         //**Canvas描画コンテキストの初期設定**
84         //mainContext
85         this.mainContext.fillStyle = "rgba(200,255,200,0.5)";
86         this.mainContext.strokeStyle = "rgba(0, 0, 0, 0.5)";
87         //debugContext
88         this.debugContext.fillStyle = "rgb(255,255,255)";
89         this.debugContext.strokeStyle = "rgb(0, 0, 0)";
90         this.debugContext.font = "normal 20px sans-serif";
91         
92         //**イベントリスナー設定**
93         //コールバックを行うために、イベントリスナーのmanagerプロパティにGameManagerのインスタンスを代入する。
94         //keyDown
95         keyDownEventListener.manager = this;
96         window.addEventListener('keydown', keyDownEventListener, true);
97         //keyUp
98         keyUpEventListener.manager = this;
99         window.addEventListener('keyup', keyUpEventListener, true);
100         //timerTick
101         timerTickEventListener.manager = this;
102         window.setInterval(timerTickEventListener, 1000/this.tickPerSecond);
103         timeStampTimerTickEventListener.manager = this;
104         window.setInterval(timeStampTimerTickEventListener, 100);
105 }
106 GameManager.prototype = {
107         //****プロトタイプ宣言****
108         //prototype以下のプロパティは、新規インスタンスに参照が引き継がれる。
109         keyDown: function(event){
110                 //****keyDown****
111                 //コールバックではなくコールバック関数(keyDownEventListener)から呼び出されるので、thisはGameManagerのインスタンスとなる。
112                 keyCode = event.keyCode;
113                 switch(event.keyCode){
114                         case 38:
115                                 //上カーソル
116                                 this.keyState.upArrow = true;
117                                 event.preventDefault();
118                                 break;
119                         case 40:
120                                 //下カーソル
121                                 this.keyState.downArrow = true;
122                                 event.preventDefault();
123                                 break;
124                         case 37:
125                                 //左カーソル
126                                 this.keyState.leftArrow = true;
127                                 event.preventDefault();
128                                 break;
129                         case 39:
130                                 //右カーソル
131                                 this.keyState.rightArrow = true;
132                                 event.preventDefault();
133                                 break;
134                 }
135
136                 this.debugOut("keyDw:" + keyCode + "\n");
137                 //実行中のステージに通知
138                 if(this.runningStage){
139                         this.runningStage.keyDown(event);
140                 }
141         },
142         keyUp: function(event){
143                 //****keyUp****
144                 //コールバックではなくコールバック関数(keyUpEventListener)から呼び出されるので、thisはGameManagerのインスタンスとなる。
145                 keyCode = event.keyCode;
146                 switch(event.keyCode){
147                         case 38:
148                                 //上カーソル
149                                 this.keyState.upArrow = false;
150                                 break;
151                         case 40:
152                                 //下カーソル
153                                 this.keyState.downArrow = false;
154                                 break;
155                         case 37:
156                                 //左カーソル
157                                 this.keyState.leftArrow = false;
158                                 break;
159                         case 39:
160                                 //右カーソル
161                                 this.keyState.rightArrow = false;
162                                 break;
163                 }
164
165                 this.debugOut("keyUp:" + keyCode + "\n");
166                 //実行中のステージに通知
167                 if(this.runningStage){
168                         this.runningStage.keyUp(event);
169                 }
170         },
171         timerTick: function(){
172                 //****timerTick****
173                 this.tickCount++;
174                 //実行中のステージに通知
175                 if(this.runningStage){
176                         this.runningStage.timerTick();
177                 }
178         },
179         timeStampTimerTick: function(){
180                 //サーバーとの同期カウンタ・タイマー
181                 this.timeStamp += 10;
182                 drawText(this.debugContext, "timeStamp:" + this.timeStamp, 0, 40);
183         },
184         runStage: function(stage){
185                 //****新たなステージを開始する****
186                 //実行中のステージがあれば終了処理を行わせる。
187                 if(this.runningStage){
188                         this.stopStage();
189                 }
190                 //**新たに開始するステージの初期化**
191                 //GameManager側の情報をGameStageに渡す。
192                 stage.manager = this;
193                 stage.mainCanvas = this.mainCanvas
194                 stage.debugCanvas = this.debugCanvas
195                 stage.mainContext = this.mainContext
196                 stage.debugContext = this.debugContext
197                 //GameStage側の初期化処理を行わせる。
198                 stage.runStage();
199                 //runningStageに登録することで、イベントの通知が開始され、GameStageは実行状態に入る。
200                 this.runningStage = stage;
201         },
202         stopStage: function(){
203                 //****現在実行中のステージを終了する****
204                 if(this.runningStage){
205                         //runningStageから解除することで、イベントの通知は行われなくなる。
206                         var aGameStage = this.runningStage;
207                         this.runningStage = null;
208                         //GameStage側の終了処理を行わせる。
209                         aGameStage.stopStage();
210                         //GameStageインスタンスからGameManagerの情報を削除する。
211                         aGameStage.manager = null;
212                         aGameStage.mainCanvas = null;
213                         aGameStage.debugCanvas = null;
214                         aGameStage.mainContext = null;
215                         aGameStage.debugContext = null;
216                 }
217         },
218         loadStageFromNetwork: function(name, onLoaded){
219                 //urlに存在するjavascriptファイルを利用してステージを作成する。
220                 request = this.networkManager.CreateRequestObject();
221                 request.onLoaded = onLoaded;
222                 request.onreadystatechange = this.loadStageFromNetwork_HTTPStateChange
223                 request.open('GET', URL_PCD_Stage + name + ".js");
224                 request.send(null);
225         },
226         loadStageFromNetwork_HTTPStateChange: function(){
227                 //requestコールバックなのでthisはrequest!
228                 switch(this.readyState){
229                         case 0:
230                                 //console.log("XMLHttpRequest created.");
231                                 break;
232                         case 1:
233                                 //console.log("open() called.");
234                                 break;
235                         case 2:
236                                 //console.log("Response header received.");
237                                 break;
238                         case 3:
239                                 //console.log("Response body receiving.");
240                                 break;
241                         case 4:
242                                 //mainManager.debugOut("send() compleated.\n");
243                                 //mainManager.debugOut("status:" + this.status + ":" + this.statusText + "\n");
244                                 if(this.status == 0){
245                                         alert("ネットワークにアクセスできません。" + this.status + ":" + this.statusText);
246                                 }else if((200 <= this.status && this.status < 300) || (this.status == 304)){
247                                         //console.log("ACK");
248                                         stage = new GameStage();
249                                         eval(this.responseText);
250                                         if(this.onLoaded != null){
251                                                 this.onLoaded(stage);
252                                         } else{
253                                                 mainManager.runStage(stage);
254                                         }
255                                 }else{
256                                         alert("サーバーがエラーを返しました。" + this.status + ":" + this.statusText);
257                                 }
258                                 break;
259                 }
260         },
261         debugOut: function(str){
262                 if(!/*@cc_on!@*/false)
263                 {
264                         this.debugText.value = str.replace(/\n/g,"\r\n") + this.debugText.value;
265                 }
266                 else
267                 {
268                         this.debugText.innerHTML = str + this.debugText.value;
269                 }
270         },
271 };
272
273 //
274 //ゲームステージ
275 //
276
277 function GameStage(){
278         //****コンストラクタ****
279         //**インスタンス変数宣言・初期化**
280         //タイマーカウントを初期化
281         this.tickCount = 0;
282         //GameManagerから渡されるプロパティ
283         this.manager = null;
284         this.mainCanvas = null;
285         this.debugCanvas = null;
286         this.mainContext = null;
287         this.debugContext = null;
288         //StageObjectのリスト
289         this.stageObjectList = new Array();
290         //オーバーライドされる可能性のある関数の保存
291         //this.super = new Object();
292         //上記の方法では、thisがsuperになってしまい動作しないので、同一階層に関数の参照を作成することになった。
293         this.super_keyDown = this.keyDown;
294         this.super_keyUp = this.keyUp;
295         this.super_timerTick = this.timerTick;
296         this.super_runStage = this.runStage;
297         this.super_stopStage = this.stopStage;
298         this.super_addStageObject = this.addStageObject;
299         this.super_removeStageObject = this.removeStageObject;
300         //衝突判定用canvas
301         this.collisionMapCanvas = null;
302         this.collisionMapContext = null;
303 }
304 GameStage.prototype = {
305         //以下の関数をオーバーライドしてステージを作成する。
306         keyDown: function(event){
307                 //キー入力
308         },
309         keyUp: function(event){
310                 //キー入力
311         },
312         timerTick: function(){
313                 //タイマー
314                 
315                 this.tickCount++;
316                 drawText(this.debugContext, "tick:" + this.tickCount, 0, 20);
317                 
318                 //キャンバスを全消去
319                 this.mainContext.clearRect(0, 0, this.mainCanvas.width, this.mainCanvas.height);
320                 this.collisionMapContext.clearRect(0, 0, this.collisionMapCanvas.width * 8, this.collisionMapCanvas.height * 8);
321                 //全てのオブジェクトを再描画
322                 
323                 for(i = 0; i < this.stageObjectList.length; i++){
324                         this.stageObjectList[i].display();
325                 }
326         },
327         runStage: function(){
328                 //ステージ初期化処理
329                 this.tickCount = 0;
330                 //衝突マップ初期化
331                 this.collisionMapCanvas = createCanvas("collisionMapCanvas", this.mainCanvas.width, this.mainCanvas.height, this.mainCanvas.width, 0, 1, "MainArea");
332                 this.collisionMapContext = this.collisionMapCanvas.getContext('2d');
333                 this.collisionMapContext.fillStyle = "rgba(0,0,0, 0.2)";
334                 this.collisionMapContext.strokeStyle = "rgba(0,0,0, 0.2)";
335                 this.collisionMapContext.scale(1, 1);
336         },
337         stopStage: function(){
338                 //ステージ終了処理
339                 destroyDOMObjectByID(this.collisionMapCanvas.id);
340                 this.collisionMapCanvas = null;
341                 this.collisionMapContext = null;
342                 this.stageObjectList = null;
343         },
344         addStageObject: function(aStageObject){
345                 //StageObject追加処理
346                 this.stageObjectList.push(aStageObject);
347         },
348         removeStageObject: function(aStageObject){
349                 //StageObject削除処理
350                 removeObjectFromArray(this.stageObjectList, aStageObject);
351         }
352 }
353
354 //
355 //キャラクター
356 //
357
358 function StageObject(aStage){
359         this.stage = aStage;
360         this.origin = new Point2D(10, 10);
361         //originを中心とした座標でのオブジェクトの描画面のサイズ
362         this.frame = new Rectangle(-8, -8, 16, 16);
363         this.movingSpeed = new Point2D(0, 0);
364         //2 * hysteresis >= movingFrictionであることを推奨する。
365         //そうでない場合、摩擦での減速後に完全に停止できない可能性がある。
366         this.movingFriction = 90;
367         this.hysteresis = this.movingFriction / 2;
368         //実体を持たない、つまり衝突判定が必要ない場合はtrue.
369         this.isPhantom = false;
370         //console.log("StageObject:Init");
371 }
372 StageObject.prototype = {
373         display: function(){
374                 //再描画時に呼ばれる。
375                 this.computeTickMoving();
376                 this.computeTickFriction();
377                 this.computeTickBounding();
378                 //弧の描画
379                 this.stage.mainContext.save();
380                 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)";
381                 drawArcDegree(this.stage.mainContext, this.frame.size.x / 2, 0, 360, this.origin.x, this.origin.y, false);
382                 this.stage.mainContext.restore();
383                 //衝突マップに描画
384                 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);
385         },
386         computeTickFriction: function(){
387                 //摩擦処理
388                 if(this.movingSpeed.x < -this.hysteresis){
389                         this.movingSpeed.x += this.movingFriction / this.stage.manager.tickPerSecond;
390                 } else if(this.movingSpeed.x > this.hysteresis){
391                         this.movingSpeed.x -= this.movingFriction / this.stage.manager.tickPerSecond;
392                 } else{
393                         this.movingSpeed.x = 0;
394                 }
395                 if(this.movingSpeed.y < -this.hysteresis){
396                         this.movingSpeed.y += this.movingFriction / this.stage.manager.tickPerSecond;
397                 } else if(this.movingSpeed.y > this.hysteresis){
398                         this.movingSpeed.y -= this.movingFriction / this.stage.manager.tickPerSecond;
399                 } else{
400                         this.movingSpeed.y = 0;
401                 }
402         },
403         computeTickMoving: function(){
404                 //運動処理
405                 this.origin.x += this.movingSpeed.x / this.stage.manager.tickPerSecond;
406                 this.origin.y += this.movingSpeed.y / this.stage.manager.tickPerSecond;
407         },
408         computeTickBounding: function(){
409                 //壁面跳ね返り処理
410                 if(this.origin.x < -this.frame.origin.x){
411                         //左壁面
412                         this.origin.x = -this.frame.origin.x;
413                         this.movingSpeed.x = -this.movingSpeed.x;
414                 } else if(this.origin.x > this.stage.mainCanvas.width - (this.frame.origin.x + this.frame.size.x)){
415                         //右壁面
416                         this.origin.x = this.stage.mainCanvas.width - (this.frame.origin.x + this.frame.size.x);
417                         this.movingSpeed.x = -this.movingSpeed.x;
418                 }
419                 if(this.origin.y < -this.frame.origin.y){
420                         //上壁面
421                         this.origin.y = -this.frame.origin.y;
422                         this.movingSpeed.y = -this.movingSpeed.y;
423                 } else if(this.origin.y > this.stage.mainCanvas.height - (this.frame.origin.y + this.frame.size.y)){
424                         //下壁面
425                         this.origin.y = this.stage.mainCanvas.height - (this.frame.origin.y + this.frame.size.y);
426                         this.movingSpeed.y = -this.movingSpeed.y;
427                 }
428         },
429 }
430
431 //
432 //その他のクラス
433 //
434
435 function Point2D(x, y){
436         this.x = x;
437         this.y = y;
438 }
439 Point2D.prototype = {
440         
441 }
442
443 function Rectangle(x, y, width, height){
444         this.origin = new Point2D(x,y);
445         this.size = new Point2D(width,height);
446 }
447 Rectangle.prototype = {
448         
449 }
450
451 function ResourceManager(){
452         //Not implemented.
453     this.resourceObjectList = new Array();
454     
455         this.ResourceTag.prototype = {
456         
457     }
458 }
459 ResourceManager.prototype = {
460         //Not implemented.
461     addAudioResource: function(id, src){
462         dobj = document.createElement("audio");
463         parent = document.getElementById("Resources");
464         dobj.id = id;
465         parent.appendChild(dobj);
466         
467         this.resourceObjectList.push(dobj);
468         
469         dobj.isLoaded = false;
470         dobj.onload = this.resourceLoaded;
471         dobj.src = src;
472     },
473     resourceLoaded: function(){
474         //コールバック関数のthisはコールバック関数の設定先オブジェクト(DOMObject)となる。
475         this.isLoaded = true;
476     },
477     waitForLoadResource: function(){
478         for(;;){
479             for(i = 0; i < resourceObjectList.length; i++){
480                 if(!resourceObjectList[i].isLoaded){
481                     
482                     break;
483                 }
484             }
485             if(i == resourceObjectList.length){
486                 return;
487             }
488         }
489     },
490 }
491
492 function NetworkManager(){
493
494 }
495 NetworkManager.prototype = {
496 //from http://hakuhin.jp/js/xmlhttprequest.html
497         CreateRequestObject: function(){
498                 // XMLHttpRequest
499                 try{
500                         // XMLHttpRequest オブジェクトを作成
501                         return new XMLHttpRequest();
502                 }catch(e){}
503                 // Internet Explorer
504                 try{
505                         return new ActiveXObject('MSXML2.XMLHTTP.6.0');
506                 }catch(e){}
507                 try{
508                         return new ActiveXObject('MSXML2.XMLHTTP.3.0');
509                 }catch(e){}
510                 try{
511                         return new ActiveXObject('MSXML2.XMLHTTP');
512                 }catch(e){}
513                 // 未対応
514                 return null;
515         },
516         HTTPStateChange: function(){
517                 //requestコールバックなのでthisはrequest!
518                 switch(this.readyState){
519                         case 0:
520                                 //console.log("XMLHttpRequest created.");
521                                 break;
522                         case 1:
523                                 //console.log("open() called.");
524                                 break;
525                         case 2:
526                                 //console.log("Response header received.");
527                                 break;
528                         case 3:
529                                 //console.log("Response body receiving.");
530                                 break;
531                         case 4:
532                                 //console.log("send() compleated.");
533                                 //console.log("status:" + this.status + ":" + this.statusText);
534                                 if(this.status == 0){
535                                         console.log("Error");
536                                 }else if((200 <= this.status && this.status < 300) || (this.status == 304)){
537                                         console.log("ACK");
538                                 }else{
539                                         //console.log("NAK");
540                                 }
541                                 alert(this.responseText);
542                                 break;
543                 }
544         }
545 }
546
547 //
548 //サブルーチン
549 //
550
551 function createCanvas(id, width, height, x, y, z, parent)
552 {
553         //識別名idで
554         //width * heightの大きさのCanvasを
555         //(x,y,z)に生成する。
556         //parentには、Canvasタグを包含することになるDOMオブジェクトのidを指定する。
557         canvas = document.createElement("canvas");
558         parent = document.getElementById(parent);
559
560         canvas.id = id;
561
562         parent.appendChild(canvas);
563
564         canvas.style.position = "absolute";
565         canvas.style.top = y + "px";
566         canvas.style.left = x + "px";
567         canvas.style.zIndex = z;
568
569         canvas.width = width;
570         canvas.height = height;
571
572         return canvas;
573 }
574
575 function createCanvas(id, width, height, x, y, z, parent)
576 {
577         //識別名idで
578         //width * heightの大きさのCanvasを
579         //(x,y,z)に生成する。
580         //parentには、Canvasタグを包含することになるDOMオブジェクトのidを指定する。
581         canvas = document.createElement("canvas");
582         parent = document.getElementById(parent);
583
584         canvas.id = id;
585
586         parent.appendChild(canvas);
587
588         canvas.style.position = "absolute";
589         canvas.style.top = y + "px";
590         canvas.style.left = x + "px";
591         canvas.style.zIndex = z;
592
593         canvas.width = width;
594         canvas.height = height;
595
596         return canvas;
597 }
598
599 function createDOMObject(typestr, idstr, parentidstr)
600 {
601         dobj = document.createElement(typestr);
602         parentObj = document.getElementById(parentidstr);
603         
604         dobj.id = idstr;
605         parentObj.appendChild(dobj);
606         
607         return dobj;
608 }
609
610 function destroyDOMObjectByID(id)
611 {
612         //識別名idのDOMオブジェクトを破棄する。
613         object = document.getElementById(id);
614         parentObj = object.parentNode;
615
616         parentObj.removeChild(object);
617 }
618
619 function removeObjectFromArray(anArray, anObject)
620 {
621         //anArray中にある全てのanObjectを削除し、空いた部分は前につめる。
622         for(i = 0; i < anArray.length; i++){
623                 if(anArray[i] == anObject){
624                         anArray.splice(i, 1);
625                 }
626         }
627 }
628
629 //
630 //イベントリスナー
631 //
632 //イベントリスナーにおけるthisは、イベントリスナーを登録したオブジェクトになり、通常とは異なるので注意。
633
634 function keyDownEventListener(event)
635 {
636         keyDownEventListener.manager.keyDown(event);
637 }
638
639 function keyUpEventListener(event)
640 {
641         keyUpEventListener.manager.keyUp(event);
642         event.preventDefault();
643 }
644
645 function timerTickEventListener(event)
646 {
647         timerTickEventListener.manager.timerTick(event);
648 }
649
650 function timeStampTimerTickEventListener(event)
651 {
652         timerTickEventListener.manager.timeStampTimerTick(event);
653 }
654
655 //
656 //Canvas直接描画関連
657 //
658
659 function drawText(gcontext, text, x, y)
660 {
661         //背景をfillStyle
662         //前景をstrokeStyleで塗りつぶした文字列を描画する
663         //塗りつぶし高さは20px固定
664         //fillTextの座標は文字列の左下!
665         textsize = gcontext.measureText(text);
666         gcontext.fillRect(x, y, textsize.width, 20);
667         gcontext.save();
668         gcontext.fillStyle = gcontext.strokeStyle;
669         gcontext.fillText(text, x, y + 20 - 1);
670         gcontext.restore();
671 }
672
673 function drawArcDegree(gcontext, radius, startAngleDegree, endAngleDegree, x, y, anticlockwise)
674 {
675         //半径radius, 中心座標(x,y)の円弧の、
676         //startAngleDegreeからendAngleDegreeまでの範囲を、
677         //(!anticlockwise)=時計回り
678         //(anticlockwise) =反時計回り
679         //に描画する。
680         //角度は度を利用する。
681         startAngleRadian = startAngleDegree * Math.PI / 180;
682         endAngleRadian = endAngleDegree * Math.PI / 180;
683         
684         gcontext.beginPath();
685         gcontext.arc(drawCoordinatesInInteger(x), drawCoordinatesInInteger(y), drawCoordinatesInInteger(radius), startAngleRadian, endAngleRadian, anticlockwise);
686         gcontext.fill();
687         gcontext.stroke();
688         gcontext.closePath();
689 }
690
691 function fillRect(gContext, x, y, w, h)
692 {
693         gContext.fillRect(drawCoordinatesInInteger(x), drawCoordinatesInInteger(y), drawCoordinatesInInteger(w), drawCoordinatesInInteger(h));
694 }
695
696 function strokeRect(gContext, x, y, w, h)
697 {
698         gContext.strokeRect(drawCoordinatesInInteger(x), drawCoordinatesInInteger(y), drawCoordinatesInInteger(w), drawCoordinatesInInteger(h));
699 }
700
701 function drawCoordinatesInInteger(coordinateElement)
702 {
703         //from http://www.html5rocks.com/ja/tutorials/canvas/performance/
704         // With a bitwise or.
705         return ((0.5 + coordinateElement) | 0);
706 }
707
708