-
Notifications
You must be signed in to change notification settings - Fork 0
/
sample_createjs.js
315 lines (279 loc) · 10 KB
/
sample_createjs.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
"use strict";
// グローバルに「world」インスタンスを用意しなければならない
var world = null;
/** LiquidFunの単位はメートル。px換算の数値を設定します。 */
var METER = 100;
/** 時間のステップを設定します。60FPSを示します。 */
var TIME_STEP = 1.0 / 60.0;
/** 速度の計算回数です。回数が多いほど正確になりますが、計算負荷が増えます。 */
var VELOCITY_ITERATIONS = 1;
/** 位置の計算回数です。回数が多いほど正確になりますが、計算負荷が増えます。 */
var POSITION_ITERATIONS = 1;
/** パーティクルのサイズです。 */
var SIZE_PARTICLE = 4;
/** ドラッグボールのサイズです。 */
var SIZE_DRAGBLE = 25;
/** 画面のサイズ(横幅)です。 */
var windowW = window.innerWidth;
/** 画面のサイズ(高さ)です。 */
var windowH = window.innerHeight;
/** DPIです。 */
var dpi = window.devicePixelRatio || 1.0;
/** [CreateJS] ステージです。 */
var stage;
/** [CreateJS] ドラッグボールの表示オブジェクトです。 */
var _cjsDragBall;
/** [CreateJS] 粒子の表示オブジェクトの配列です。 */
var _cjsParticles = [];
/** [LiquidFun] パーティクルシステムです。 */
var _b2ParticleSystem;
/** [LiquidFun] ドラッグボール用のインスタンスです。 */
var _b2DragBallFixutre;
/** [LiquidFun] マクスジョイントです。 */
var _b2MouseJoint;
/** [LiquidFun] ドラッグボール制御用のインスタンスです。 */
var _b2GroundBody;
/** 端末ごとにパフォーマンスを調整するための変数です。 */
var performanceLevel;
switch (navigator.platform) {
case "Win32": // Windowsだったら
case "MacIntel": // OS Xだったら
performanceLevel = "high";
break;
case "iPhone": // iPhoneだったら
default:
// その他の端末も
performanceLevel = "low";
}
// ページが読み込み終わったら初期化する
window.addEventListener("DOMContentLoaded", init);
function init() {
// 重力の設定
var gravity = new b2Vec2(0, 10);
// Box2D(LiquidFun)の世界を作成
world = new b2World(gravity);
// グランドの作成
_b2GroundBody = world.CreateBody(new b2BodyDef());
// Box2Dのコンテンツを作成
createPhysicsWalls();
createPhysicsParticles();
createPhysicsBall();
// CreateJSのコンテンツを作成
createCreatejsWorld();
// 定期的に呼び出す関数(エンターフレーム)を設定
createjs.Ticker.timingMode = createjs.Ticker.RAF;
createjs.Ticker.frameRate = 60;
createjs.Ticker.on("tick", handleTick);
setupDragEvent();
}
/** LiquidFunの世界で「壁」を生成します。 */
function createPhysicsWalls() {
var density = 0;
var bdDef = new b2BodyDef();
var bobo = world.CreateBody(bdDef);
// 壁の生成 (地面)
var wg = new b2PolygonShape();
wg.SetAsBoxXYCenterAngle(
windowW / METER / 2, // 幅
5 / METER, // 高さ
new b2Vec2(
windowW / METER / 2, // X座標
windowH / METER + 0.05
), // Y座標
0
);
bobo.CreateFixtureFromShape(wg, density);
// 壁の生成 (左側)
var wgl = new b2PolygonShape();
wgl.SetAsBoxXYCenterAngle(
5 / METER, // 幅
windowH / METER / 2, // 高さ
new b2Vec2(
-0.05, // X座標
windowH / METER / 2
), // Y座標
0
);
bobo.CreateFixtureFromShape(wgl, density);
// 壁の生成 (右側)
var wgr = new b2PolygonShape();
wgr.SetAsBoxXYCenterAngle(
5 / METER, // 幅
windowH / METER / 2, // 高さ
new b2Vec2(
windowW / METER + 0.05, // X座標
windowH / METER / 2
), // Y座標
0
);
bobo.CreateFixtureFromShape(wgr, density);
}
/** LiquidFunの世界で「粒子」を生成します。 */
function createPhysicsParticles() {
// 粒子の作成 (プロパティーの設定)
var psd = new b2ParticleSystemDef();
psd.radius = SIZE_PARTICLE / METER; // 粒子の半径
psd.pressureStrength = 4.0; // Increases pressure in response to compression Smaller values allow more compression
_b2ParticleSystem = world.CreateParticleSystem(psd);
// 粒子の発生領域
var box = new b2PolygonShape();
var w = performanceLevel === "high" ? 128 : 128;
var h = performanceLevel === "high" ? 128 : 64;
box.SetAsBoxXYCenterAngle(
w / METER, // 幅
h / METER, // 高さ
new b2Vec2(
windowW / 2 / METER, // 発生X座標
-windowH / 2 / METER
), // 発生Y座標
0
);
var particleGroupDef = new b2ParticleGroupDef();
particleGroupDef.shape = box; // 発生矩形を登録
_b2ParticleSystem.CreateParticleGroup(particleGroupDef);
}
function createPhysicsBall() {
// 属性を設定
var bd = new b2BodyDef();
bd.type = b2_dynamicBody;
bd.position.Set(
windowW / 2 / METER, // 発生X座標
(-windowH * 2) / METER // 発生Y座標
);
// 形状を設定
var circle = new b2CircleShape();
circle.radius = SIZE_DRAGBLE / METER;
// 実態を作成
var body = world.CreateBody(bd);
_b2DragBallFixutre = body.CreateFixtureFromShape(circle, 8); //鉄:7.9、アルミニウム:2.6、ゴム:0.4、木:1.4、コンクリート:2.4、氷:1;
_b2DragBallFixutre.friction = 0.1; // 鉄:0.6、アルミニウム:0.6、ゴム:0.9、木:0.5、コンクリート:0.7、氷:0
_b2DragBallFixutre.restitution = 0.1; // 鉄:0.2、アルミニウム:0.3、ゴム:0.9、木:0.3、コンクリート:0.1、氷:0.1
}
function createCreatejsWorld() {
// CreateJSの世界を作成
stage = new createjs.Stage("myCanvas");
stage.enableMouseOver(); // マウスオーバーを有効化
stage.canvas.width = windowW * dpi; // 実Pixel数を画面のPixel数に調整
stage.canvas.height = windowH * dpi;
stage.scaleX = stage.scaleY = dpi;
// タッチ操作をサポートしているブラウザーならば
if (createjs.Touch.isSupported() === true) {
// タッチ操作を有効にします。
createjs.Touch.enable(stage);
}
// パーティクルの作成
var length = _b2ParticleSystem.GetPositionBuffer().length / 2;
for (var i = 0; i < length; i++) {
var shape = new createjs.Shape(); // シェイプを作成
shape.mouseEnabled = false;
shape.compositeOperation = Math.random() < 0.5 ? "normal" : "lighter";
var hue = (i / length) * 100 + 180; // 色相
var satuation = 40 * Math.random() + 60;
shape.graphics
.beginFill(createjs.Graphics.getHSL(hue, satuation, 70, 0.5)) // 色指定
.drawCircle(0, 0, 12 * Math.random() * Math.random()); // 大きさを指定
stage.addChild(shape); // 画面に追加
_cjsParticles[i] = shape; // 配列に格納
}
// ドラッグボールの作成
_cjsDragBall = new createjs.Shape();
_cjsDragBall.cursor = "pointer";
_cjsDragBall.graphics
.beginFill("black") // 色指定
.setStrokeStyle(3)
.beginStroke("white")
.drawCircle(0, 0, SIZE_DRAGBLE); // 大きさを指定
stage.addChild(_cjsDragBall); // 画面に追加
}
/** 時間経過で指出される関数です。 */
function handleTick() {
// 物理演算エンジンを更新
world.Step(TIME_STEP, VELOCITY_ITERATIONS, POSITION_ITERATIONS);
// パーティクルシステムの計算結果を取得
var particlesPositions = _b2ParticleSystem.GetPositionBuffer();
// 粒子表現 : 物理演算エンジンとCreateJSの座標を同期
for (var i = 0; i < _cjsParticles.length; i++) {
var shape = _cjsParticles[i]; // 配列から要素を取得
// LiquidFunの配列から座標を取得
var xx = particlesPositions[i * 2] * METER;
var yy = particlesPositions[i * 2 + 1] * METER;
// 座標を表示パーツに適用
shape.x = xx;
shape.y = yy;
}
// ドラッグボール : 物理演算エンジンとCreateJSの座標を同期
_cjsDragBall.x = _b2DragBallFixutre.body.GetPosition().x * METER;
_cjsDragBall.y = _b2DragBallFixutre.body.GetPosition().y * METER;
// 残像効果の演出
// 詳細 ⇛ https://plus.google.com/102594170131511973965/posts/ZA6QadXfjzX
stage.autoClear = false;
var context = stage.canvas.getContext("2d");
context.fillStyle = "rgba(0, 0, 0, 0.1)";
context.fillRect(0, 0, stage.canvas.width, stage.canvas.height);
// 画面を更新する
stage.update();
}
/** ドラッグイベントを設定します。 */
function setupDragEvent() {
_cjsDragBall.on("mousedown", function(event) {
var p = getMouseCoords(event);
var aabb = new b2AABB();
aabb.lowerBound.Set(p.x - 0.001, p.y - 0.001);
aabb.upperBound.Set(p.x + 0.001, p.y + 0.001);
var queryCallback = new QueryCallback(p);
world.QueryAABB(queryCallback, aabb);
if (queryCallback.fixture) {
var body = queryCallback.fixture.body;
var md = new b2MouseJointDef();
md.bodyA = _b2GroundBody;
md.bodyB = body;
md.target = p;
md.maxForce = 1000 * body.GetMass();
// マウスジョイントを作成
_b2MouseJoint = world.CreateJoint(md);
body.SetAwake(true);
}
});
_cjsDragBall.on("pressmove", function(event) {
var p = getMouseCoords(event);
if (_b2MouseJoint) {
// マウスジョイントの対象座標を更新
_b2MouseJoint.SetTarget(p);
}
});
_cjsDragBall.on("pressup", function(event) {
if (_b2MouseJoint) {
// マウスジョイントを破棄
world.DestroyJoint(_b2MouseJoint);
_b2MouseJoint = null;
}
});
}
/**
* マウス座標を取得します。
* @return b2Vec2 マウス座標のベクター情報です。
*/
function getMouseCoords(event) {
var p = new b2Vec2(stage.mouseX / dpi / METER, stage.mouseY / dpi / METER);
return p;
}
/**
* LiquidFun の衝突判定に使うクラスです。
* @constructor
*/
function QueryCallback(point) {
this.point = point;
this.fixture = null;
}
/**@return bool 当たり判定があれば true を返します。 */
QueryCallback.prototype.ReportFixture = function(fixture) {
var body = fixture.body;
if (body.GetType() === b2_dynamicBody) {
var inside = fixture.TestPoint(this.point);
if (inside) {
this.fixture = fixture;
return true;
}
}
return false;
};