OSDN Git Service

久しぶりにコミット。
[html5test/HTML5Test.git] / html5test0006.htm
1 <!DOCTYPE html>
2 <html>
3 <head>
4   <title>HTML5 Test</title>
5   <link rel="stylesheet" href="http://sfpg.seesaa.net/styles-index.css" type="text/css" />
6   <script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script>
7   <style type="text/css">
8     #disp01 {margin:10px;}
9   </style>
10 <!--<script type="text/javascript" src="http://sfpg.up.seesaa.net/scripts/jquery-1.4.4.min.js"></script>-->
11 <!--<script type="text/javascript">
12
13   var _gaq = _gaq || [];
14   _gaq.push(['_setAccount', 'UA-15457703-1']);
15   _gaq.push(['_setDomainName', '.seesaa.net']);
16   _gaq.push(['_trackPageview']);
17
18   (function () {
19     var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
20     ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
21     var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
22   })();
23
24 </script>-->
25 </head>
26 <body>
27 <div>
28 <canvas id="disp01" width="320" height="240" ></canvas>
29 </div>
30 <div>
31 <button type="button" id="start" disabled="true">開始</button>
32 <button type="button" id="stop" disabled="true" >停止</button>
33 </div>
34 <script type="text/javascript">
35   
36   var sx = 80;
37   var sy = 60;
38   var width = 320;
39   var height = 240;
40
41
42   var ctx_main = $("#disp01")[0].getContext("2d");
43   var screenWidth = $("#disp01")[0].width;
44   var screenHeight = $("#disp01")[0].height;
45   var img;
46
47   var backBuffer = $("<canvas>")[0];
48   backBuffer.width = width + 160;
49   backBuffer.height = height + 120;
50   var ctx = backBuffer.getContext("2d");
51   var t = 0;
52   var renderTimerId = undefined;
53   var mainTimerId = undefined;
54
55   
56   // ボールオブジェクト
57   function Ball(x, y, radius, xSpeed, ySpeed,index,color) {
58     this.x = x;
59     this.y = y;
60     this.xSpeed = xSpeed;
61     this.ySpeed = ySpeed;
62     this.radius = radius;
63     this.index = index;
64     this.color = color;
65     this.enable = false;
66     return this;
67   };
68
69 //  Ball.prototype.init = function (x, y, radius,xSpeed,ySpeed,index) {
70 //    this.x = x;
71 //    this.y = y;
72 //    this.xSpeed = xSpeed;
73 //    this.ySpeed = ySpeed;
74 //    this.radius = radius;
75 //    this.index = index;
76 //    this.enable = true;
77 //  }
78
79   Ball.prototype.move = function () {
80
81     this.ySpeed += 0.25;
82     this.x += this.xSpeed;
83
84     if ((this.x + this.radius) > width) {
85       this.x = width - this.radius;
86       this.xSpeed = -(this.xSpeed);
87     }
88
89     if (this.x < this.radius) {
90       this.x = this.radius; // -this.x;
91       this.xSpeed = -(this.xSpeed);
92     }
93
94     this.y += this.ySpeed;
95
96     if ((this.y + this.radius) > height) {
97       this.y = height - this.radius;
98       this.ySpeed = -this.ySpeed ;
99     }
100
101     if (this.y < this.radius) {
102       this.y = this.radius;
103       this.ySpeed = -this.ySpeed ;
104     }
105   };
106
107   Ball.prototype.draw = function (pctx) {
108     var fillStyle = pctx.fillStyle;
109     //pctx.globalAlpha = 0.7;
110     pctx.fillStyle = this.color;
111     pctx.beginPath();
112     pctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
113     pctx.closePath();
114     pctx.fill();
115     pctx.fillStyle = fillStyle;
116     //pctx.globalAlpha = 1.0;
117   };
118
119   Ball.prototype.checkCollision = function (other) {
120     if (Math.pow(this.x - other.x, 2) + Math.pow(this.y - other.y, 2) < Math.pow(this.radius + other.radius, 2)) {
121       // 衝突しているので反発させる。
122       return true;
123     }
124     return false;
125   };
126
127   // ボール配列
128   var balls = new Array(0);
129    
130   // コンストラクタ
131   function Tasks() {
132     this.array = new Array(0);
133     return this;
134   }
135
136
137   Tasks.prototype = {
138     // indexの位置のタスクを置き換える
139     setNextTask: function (index, func) {
140       this.array[index] = func;
141     },
142
143     pushTask : function (func) 
144     {
145       for (var i = 0; i < this.length; ++i) {
146         if (this.array[i] == null) {
147           this.array[i] = func;
148           return;
149         }
150       }
151       this.array.push(func);
152     },
153     // 配列を取得する
154     getArray: function () {
155       return this.array;
156     },
157     // タスクをクリアする
158     clear: function () {
159       this.array.length = 0;
160     }
161   };
162
163   var tasks = new Tasks();
164   var img = new Image();
165
166
167   $(window).ready(function () {
168     ctx.fillStyle = "blue";
169     ctx.fillRect(0, 0, backBuffer.width, backBuffer.height);
170     ctx.setTransform(1, 0, 0, 1, sx, sy);
171     ctx.fillStyle = "white";
172
173     ctx.font = "12px 'MS ゴシック'";
174     ctx.fillText("なんちゃってボール反発です。", 0, 20, 240);
175     ctx.fillText("クリックするとボールが追加されます。", 0, 40, 240);
176     img.src = "images/Font.png";
177     ctx_main.drawImage(backBuffer, sx, sy, width, height, 0, 0, screenWidth, screenHeight);
178     var color = ["#0030ff", "#0060ff", "#0090ff", "#00c0ff"];
179
180     // 開始ボタンをクリックした時の処理
181     $("#start").click(function () {
182       //      renderTimerId = setInterval(render, 100);
183       tasks.pushTask(init);
184       balls.length = 0;
185       for (var i = 0; i < 100; ++i) {
186         var rad = 1 + Math.random() * 10;
187         balls.push(
188         new Ball(
189           Math.random() * (width - rad * 2) + rad,
190           Math.random() * (height - rad * 2) + rad,
191           rad,
192           (Math.random() * 5 + 5) * (Math.random() >= 0.5 ? -1 : 1),
193           Math.random() * 4 + 9,
194           i,
195           color[(Math.random() * 4) | 0]
196           )
197         );
198       }
199       mainTimerId = setTimeout(processMain, 50);
200       $("#stop")[0].disabled = false;
201       $("#start")[0].disabled = true;
202     });
203
204     // 停止ボタンをクリックしたときの処理
205     $("#stop").click(function () {
206       //      if (renderTimerId != undefined) {
207       //        clearInterval(renderTimerId);
208       //        renderTimerId = undefined;
209       //      }
210       if (mainTimerId != undefined) {
211         clearTimeout(mainTimerId);
212         mainTimerId = undefined;
213       }
214
215       tasks.clear();
216
217       $("#stop")[0].disabled = true;
218       $("#start")[0].disabled = false;
219     });
220
221     // マウスクリックした時の処理
222     $("#disp01").click(function (e) {
223       if ($("#start")[0].disabled && balls.length < 300) {
224         var color = ["#ff3000", "#ff6000", "#ff9000", "#ffc000"];
225         var x = e.pageX - this.offsetLeft;
226         var y = e.pageY - this.offsetTop;
227         var rad = 1 + Math.random() * 10;
228         balls.push(
229         new Ball(
230           x,
231           y,
232           rad,
233           (Math.random() * 9) * (Math.random() >= 0.5 ? -1 : 1),
234           Math.random() * -12,
235           balls.length,
236           color[(Math.random() * 4) | 0]
237           )
238         );
239       }
240     });
241
242     $("#disp01").keydown
243
244     // 
245     //$("#disp01").
246     // 準備ができたので開始ボタンを押せるようにする
247     $("#start")[0].disabled = false;
248
249
250
251   });
252
253   var r = 0;
254
255   // 描画処理
256   function render() {
257     ctx_main.drawImage(backBuffer, sx, sy, width, height, 0, 0, screenWidth, screenHeight);
258   }
259
260   // 処理メイン
261   // バックバッファの描画
262   var period = 0;
263   var ellapsedTime  = 0;
264   function processMain() {
265     var startTime = new Date().getTime();
266    
267     // メインに描画
268     $(tasks.getArray()).each(function (taskIndex) {
269       if (this != null) {
270         this(taskIndex);
271       }
272     }
273     );
274     render();
275     ctx.fillStyle = "black";
276     ctx.fillRect(0, 0, width, height);
277     var endTime = new Date().getTime();
278     ellapsedTime = endTime - startTime;
279     period = 33 - (ellapsedTime) % 33;
280     mainTimerId = setTimeout(processMain, period);
281   }
282
283   // 初期化タスク
284   function init(taskIndex) {
285     
286     ctx.fillStyle = "black";
287     ctx.fillRect(0, 0, width, height);
288     tasks.setNextTask(taskIndex, ballAction);
289     tasks.pushTask(addCount);
290   }
291
292   // 処理時間を表示する。
293   function addCount() {
294 //    var txt = "処理時間:" + ellapsedTime + "ms";
295 //    ctx.textBaseline = "top";
296 //    var textWidth = ctx.measureText(txt);
297 //    ctx.fillStyle = "black";
298 //    ctx.fillRect(0, 0, textWidth.width, 12);
299 //    ctx.fillStyle = "white";
300     //    ctx.fillText(txt, 0, 0, textWidth.width);
301     var txt = "Process Time: " + ellapsedTime + "ms";
302     print(0, 0, txt);
303   }
304    
305   // ボール初期化タスク
306   function ballAction() {
307     for (var i = 0, last = balls.length; i < last; ++i) {
308       var srcBall = balls[i];
309       srcBall.move();
310       srcBall.draw(ctx);
311       for (var j = i + 1; j < last; ++j) {
312         if (srcBall.checkCollision(balls[j])) {
313           bound(srcBall, balls[j]);
314         }
315       }
316     }
317   }
318
319   // 衝突時の処理
320   function bound(src, dest) {
321     // 半径を質量と見立てる。
322     var srcMass = src.radius ;
323     var destMass = dest.radius ;
324     var totalMass = srcMass + destMass;
325     var boundRate = 1.95;
326     var c = { x: dest.x - src.x, y: dest.y - src.y };
327
328     // 正規化
329     var vs = Math.sqrt(c.x * c.x + c.y * c.y);
330     c.x = c.x / vs;
331     c.y = c.y / vs;
332
333     // 内積
334     var dot = (src.xSpeed - dest.xSpeed) * c.x + (src.ySpeed - dest.ySpeed) * c.y;
335
336     // めり込みを補正する。
337     if ((src.radius + dest.radius) > vs) {
338       var a = src.radius + dest.radius - vs;
339
340 //      var m = (src.radius + dest.radius) / vs;
341       var ax = (c.x * a) / 2;
342       var ay = (c.y * a) / 2;
343       dest.x = dest.x + ax;
344       dest.y = dest.y + ay;
345       src.x = src.x - ax;
346       src.y = src.y - ay;
347 //          while ((Math.pow(dest.x - src.x, 2) + Math.pow(dest.y - src.y, 2)) <= Math.pow(src.radius + dest.radius, 2)) {
348 //            dest.x += c.x/2;
349 //            dest.y += c.y/2;
350 //            src.x -= c.x/2;
351 //            src.y -= c.y/2;
352 //          }  
353 //         
354
355     }
356
357
358     // 定数ベクトル
359     var v = { x: boundRate * dot / totalMass * c.x, y: boundRate * dot / totalMass * c.y };
360     src.xSpeed = -destMass * v.x + src.xSpeed;
361     src.ySpeed = -destMass * v.y + src.ySpeed;
362
363     dest.xSpeed = srcMass * v.x + dest.xSpeed;
364     dest.ySpeed = srcMass * v.y + dest.ySpeed;
365
366 //    src.x += src.xSpeed;
367 //    src.y += src.ySpeed;
368
369 //    dest.x += dest.xSpeed;
370 //    dest.y += dest.ySpeed;
371
372   }
373
374   function print(x, y, str) {
375     for (var i = 0; i < str.length; ++i) {
376       var c = str.charCodeAt(i) - 0x20;
377       var ypos = parseInt(c / 16) * 8;
378       var xpos = (c % 16) * 8;
379       ctx.drawImage(img, xpos, ypos, 8, 8, x, y, 8, 8);
380       x += 8;
381     }
382   }
383
384 </script>
385 </body>
386 </html>