ジョイントは、物体と物体を繋げて動かしたりもできる機能。
回転・距離・直動・滑車・歯車・マウスの6種類があります。
ここでは、回転ジョイントと距離ジョイントについてのメモ。
回転ジョイント(RevoluteJoint)
- 物体と物体をピンで繋げるようなジョイント。
- ピンを中心にくるくる回る。
- モーターを使って回すことができる。
- 回る角度の制限もできる。
使い方
- 繋げる2つの物体(b2Body)を指定
- 繋げる場所(座標)(b2Vec2)を1ヶ所指定
- ジョイントの性質(b2RevoluteJointDef)を設定(モーター使用・角度制限等)/li>
- ジョイントの初期化→ジョイント登録
距離ジョイント(DistanceJoint)
- 物体と物体をロープで繋げるようなジョイント。
- ロープに引っ張られながらそれぞれ勝手に動く。
- 繋ぐ場所が2箇所あるのが、回転ジョイントと違う。
使い方
- 繋げる2つの物体(b2Body)を指定
- 繋げる場所(座標)(b2Vec2)を2ヶ所指定
- ジョイントの性質(b2DistanceJointDef)を設定(振動数?均衡等??ここの設定はわからないです…。)/li>
- ジョイントの初期化→ジョイント登録
サンプルコード
※Box2Dのまとめたクラス(Box2DBase)を作って、基本クラスで使ってます。ソースは物理エンジンライブラリ Box2DFlashAS3(基本)にあります。
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 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 |
public class StudyB2Joint1 extends B2Base { private var m_screen_width:int = 600; private var m_screen_height:int = 500; //ぐるぐるきのこ private var m_b2_guru_kinoko1:b2Body; private var m_b2_guru_kinoko2:b2Body; private var m_b2_guru_kinoko3:b2Body; private var m_b2_guru_kinoko4:b2Body; //ゆらゆら棒 private var m_b2_yura_bar:b2Body; private var m_b2_yura_kinoko1:b2Body; private var m_b2_yura_kinoko2:b2Body; //表示用のMCを入れる private var m_display_blocks:Sprite; //落ちてくるきのこ発生装置 private var m_kinokoL:Sprite; private var m_kinokoS:Sprite; public function StudyB2Joint1() : void{ super(24, 10, 10); //表示用設定 this.m_display_blocks = new Sprite; this.addChild(m_display_blocks); this.makeGake(); //ガケ作成 //橋(距離ジョイント) this.makeBridge(); //ぐるぐるきのこ(回転ジョイント+距離ジョイント) this.makeGuruguruKinoko(); //ゆらゆら棒(回転ジョイント+距離ジョイント) this.makeYurayuraBar(); this.initKinokoS(); //小さいきのこ this.initKinokoL(); //大きいきのこ //this.setDebugDraw(); this.addEventListener(Event.ENTER_FRAME, this.update, false, 0, true); } //ガケ作成 private function makeGake():void { this.makeB2BodyBox(120, 120, 60, 440, 0, 0, 0.5, 0.5); this.makeB2BodyBox(120, 120, 540, 440, 0, 0, 0.5, 0.5); } //橋(真ん中のやつ)作成 //:距離Joint private function makeBridge():void { var x:Number; var y:Number = 390; var i:int; //カウンタ var rack:b2Body = this.m_b2_world.GetGroundBody(); //橋の岸 var boards:Array = new Array(); //橋の板 for (i = 0; i <= 5; i++){ x = i * 60 + 150; //配置場所X var borad_display:Sprite = new board_60_mc as Sprite; //橋板(表示用) var board:b2Body = this.makeB2BodyBox(60, 10, x, y, 0, 1, 1.5, 0.5, borad_display, m_display_blocks); boards[i] = board; } //Joint var body1:b2Body; //距離Joint 繋ぐ物体1つ目 var body2:b2Body; //距離Joint 繋ぐ物体2つ目 var anc1:b2Vec2; //距離Joint 繋ぎ場所1つ目 var anc2:b2Vec2; //距離Joint 繋ぎ場所2つ目 var dj_def:b2DistanceJointDef; //距離Joint //左岸と板 x = 120; //繋げる場所 body1 = rack; body2 = boards[0]; anc1 = this.createB2Vec(x - 5, y); anc2 = this.createB2Vec(x + 5, y); dj_def = new b2DistanceJointDef(); //dj_def.length = 0; dj_def.Initialize(body1, body2, anc1, anc2); this.m_b2_world.CreateJoint(dj_def); //板と板 for (i = 0; i <= 4; i++){ //板の左側を繋げる x = (i * 60) + 210; //繋げる場所 body1 = boards[i]; body2 = boards[i + 1]; anc1 = this.createB2Vec(x - 5, y); anc2 = this.createB2Vec(x + 5, y); dj_def = new b2DistanceJointDef(); dj_def.Initialize(body1, body2, anc1, anc2); this.m_b2_world.CreateJoint(dj_def); } //板と右岸 //板の右側を繋げる x = 510; //繋げる場所 body1 = boards[5]; body2 = rack; anc1 = this.createB2Vec(x - 5, y); anc2 = this.createB2Vec(x + 5, y); dj_def = new b2DistanceJointDef(); dj_def.Initialize(body1, body2, anc1, anc2); this.m_b2_world.CreateJoint(dj_def); } //ぐるぐるきのこ(左側のポールに繋がってる回ってる円盤)作成 //:回転ジョイント+距離ジョイント private function makeGuruguruKinoko():void { //表示用 var kinoko1_display:kinoko_kurukuru_green_mc = new kinoko_kurukuru_green_mc; var kinoko2_display:kinoko_kurukuru_red_mc = new kinoko_kurukuru_red_mc; var kinoko3_display:kinoko_kurukuru_yellow_mc = new kinoko_kurukuru_yellow_mc; var kinoko4_display:kinoko_kurukuru_green_mc = new kinoko_kurukuru_green_mc; kinoko2_display.width = 30; kinoko2_display.height = 30; kinoko4_display.width = 30; kinoko4_display.height = 30; //位置 var bura_x:int = 150; var bura_y:int = 100; var kinoko1:b2Body = this.makeB2BodyCircle(60, bura_x, bura_y, 1, 0.5, 0.5, kinoko1_display, this.m_display_blocks); var kinoko2:b2Body = this.makeB2BodyCircle(30, bura_x, bura_y + 90, 1, 0.5, 0.5, kinoko2_display, this.m_display_blocks); var kinoko3:b2Body = this.makeB2BodyCircle(30, bura_x, bura_y + 180, 1, 0.5, 0.5, kinoko3_display, this.m_display_blocks); var kinoko4:b2Body = this.makeB2BodyCircle(30, bura_x, bura_y + 270, 1, 0.5, 0.5, kinoko4_display, this.m_display_blocks); //回転ジョイント //きのこ1はぐるぐる回る var rj_def:b2RevoluteJointDef = new b2RevoluteJointDef; rj_def.enableMotor = true; rj_def.motorSpeed = 2.0; rj_def.maxMotorTorque = 300000; rj_def.Initialize(this.m_b2_world.GetGroundBody(), kinoko1, kinoko1.GetPosition()); this.m_b2_world.CreateJoint(rj_def); //距離ジョイント //きのこ1と2(回るきのこ1の中心からずれた位置ときのこ2の中心を繋ぐ) var anc1:b2Vec2 = this.createB2Vec(bura_x + 20, bura_y); // var dj_def1:b2DistanceJointDef = new b2DistanceJointDef; dj_def1.Initialize(kinoko1, kinoko2, anc1, kinoko2.GetPosition()); this.m_b2_world.CreateJoint(dj_def1); //きのこ2と3(中心同士で繋ぐ) var dj_def2:b2DistanceJointDef = new b2DistanceJointDef; dj_def2.Initialize(kinoko2, kinoko3, kinoko2.GetPosition(), kinoko3.GetPosition()); this.m_b2_world.CreateJoint(dj_def2); //きのこ3と4(中心同士で繋ぐ) var dj_def3:b2DistanceJointDef = new b2DistanceJointDef; dj_def2.Initialize(kinoko3, kinoko4, kinoko3.GetPosition(), kinoko4.GetPosition()); this.m_b2_world.CreateJoint(dj_def2); //後から使えるように this.m_b2_guru_kinoko1 = kinoko1; this.m_b2_guru_kinoko2 = kinoko2; this.m_b2_guru_kinoko3 = kinoko3; this.m_b2_guru_kinoko4 = kinoko4; } //ゆらゆら棒(右側のポールに繋がってるモビールっぽいやつ)作成:回転ジョイント+距離ジョイント private function makeYurayuraBar():void { //表示用 var bar_display:board_100_mc = new board_100_mc; var kinoko1_display:kinoko_kurukuru_yellow_mc = new kinoko_kurukuru_yellow_mc; var kinoko2_display:kinoko_kurukuru_red_mc = new kinoko_kurukuru_red_mc; kinoko1_display.width = 40; kinoko1_display.height = 40; kinoko2_display.width = 40; kinoko2_display.height = 40; var yura_x:int = 450; var yura_y:int = 100; var bar:b2Body = this.makeB2BodyBox(100, 10, yura_x, yura_y, 0, 1, 0.5, 0.5, bar_display, this.m_display_blocks); //棒 var kinoko1:b2Body = this.makeB2BodyCircle(40, yura_x + 100, yura_y + 150, 1, 0.5, 0.5, kinoko1_display, this.m_display_blocks); //きのこ1 var kinoko2:b2Body = this.makeB2BodyCircle(40, yura_x - 100, yura_y + 150, 1, 0.5, 0.5, kinoko2_display, this.m_display_blocks); //きのこ2 //回転ジョイント ゆれる棒 var rj_def:b2RevoluteJointDef = new b2RevoluteJointDef; rj_def.enableLimit = true; //角度制限付ける rj_def.lowerAngle = -30 * Math.PI / 180; rj_def.upperAngle = 30 * Math.PI / 180; rj_def.Initialize(this.m_b2_world.GetGroundBody(), bar, bar.GetPosition()); this.m_b2_world.CreateJoint(rj_def); //距離ジョイント ゆれる棒ときのこ繋ぐ //きのこ1 var anc1:b2Vec2 = this.createB2Vec(yura_x + 50, yura_y); var dj_def1:b2DistanceJointDef = new b2DistanceJointDef; dj_def1.Initialize(bar, kinoko1, anc1, kinoko1.GetPosition()); this.m_b2_world.CreateJoint(dj_def1); //きのこ2 var anc2:b2Vec2 = this.createB2Vec(yura_x - 50, yura_y); var dj_def2:b2DistanceJointDef = new b2DistanceJointDef; dj_def2.Initialize(bar, kinoko2, anc2, kinoko2.GetPosition()); this.m_b2_world.CreateJoint(dj_def2); //後から使えるように this.m_b2_yura_bar = bar; this.m_b2_yura_kinoko1 = kinoko1; this.m_b2_yura_kinoko2 = kinoko2; } //演算 private function update(e:Event):void{ var self:StudyB2Joint1 = this; //距離ジョイントで繋げてる紐を描く //Body位置から描画位置移動する関数 var moveTo_Pos:Function = function(graphics:Graphics, body:b2Body, offset_x:Number = 0, offset_y:Number = 0):void { var x:Number = body.GetPosition().x * self.m_b2_physcale + offset_x; var y:Number = body.GetPosition().y * self.m_b2_physcale + offset_y; graphics.moveTo(x, y); } //Body位置へ線を引く関数 var lineTo_Pos:Function = function(graphics:Graphics, body:b2Body):void { var x:Number = body.GetPosition().x * self.m_b2_physcale; var y:Number = body.GetPosition().y * self.m_b2_physcale; graphics.lineTo(x, y); } this.m_display_blocks.graphics.clear(); this.m_display_blocks.graphics.lineStyle(1, 0x9FD06F); //ぐるぐるぐきのこ moveTo_Pos(this.m_display_blocks.graphics, this.m_b2_guru_kinoko1); lineTo_Pos(this.m_display_blocks.graphics, this.m_b2_guru_kinoko2); lineTo_Pos(this.m_display_blocks.graphics, this.m_b2_guru_kinoko3); lineTo_Pos(this.m_display_blocks.graphics, this.m_b2_guru_kinoko4); //ゆらゆら棒 //棒は斜めになるので、角度から繋ぐ位置取得 var angle:Number = this.m_b2_yura_bar.GetAngle(); var offset_x:Number = Math.cos(angle) * 50; var offset_y:Number = Math.sin(angle) * 50; moveTo_Pos(this.m_display_blocks.graphics, this.m_b2_yura_bar, offset_x, offset_y); lineTo_Pos(this.m_display_blocks.graphics, this.m_b2_yura_kinoko1); moveTo_Pos(this.m_display_blocks.graphics, this.m_b2_yura_bar, -offset_x, -offset_y); lineTo_Pos(this.m_display_blocks.graphics, this.m_b2_yura_kinoko2); //B2Boxの時間進める this.m_b2_world.Step(this.m_b2_timeStep, this.m_b2_iterations); //各B2BoxのBodyの動きにあわせて中のSpriteを動かす for (var bb:b2Body = this.m_b2_world.m_bodyList; bb; bb = bb.m_next){ var bb_x:Number = bb.GetPosition().x * m_b2_physcale; var bb_y:Number = bb.GetPosition().y * m_b2_physcale; //画面外に出て行ったきのこ削除 if (bb_x < -100 || bb_x > 700 || bb_y < -100 || bb_y > 600) { this.m_b2_world.DestroyBody(bb); if(bb.m_userData != null){ this.m_kinokoS.removeChild(bb.m_userData); bb.m_userData = null; } } //演算結果にあわせて表示用データ移動 if (bb.m_userData is Sprite){ //メートルからピクセル単位に変換 bb.m_userData.x = bb_x; bb.m_userData.y = bb_y; bb.m_userData.rotation = bb.GetAngle() * (180/Math.PI); } } } //-----きのこを降らす(ここは、基本と同じもの使用)----- //大きいきのこ作る private function initKinokoL():void { var self:StudyB2Joint1 = this; //これはMC配置するだけ var kinoko:kinoko_L_MC = new kinoko_L_MC; kinoko.x = 555; kinoko.y = 350; kinoko.width = 60; kinoko.height = 65; kinoko.buttonMode = true; kinoko.addEventListener(MouseEvent.MOUSE_OVER, function(e:Event):void { kinoko.gotoAndPlay("frm_hover"); }); kinoko.addEventListener(MouseEvent.MOUSE_UP, function(e:Event):void { kinoko.gotoAndPlay("frm_action"); self.makeKinokoS(Math.random() * 550 + 50, 0); }); this.m_kinokoL = kinoko; this.addChild(this.m_kinokoL); } //小さいきのこ入れるのを作って、小さいきのこ配置 private function initKinokoS():void { //小さいきのこを入れる this.m_kinokoS = new Sprite(); this.addChild(this.m_kinokoS); //最初の小さいきのこ配置 for (var i:int = 0; i < 5 ;i++){ this.makeKinokoS(Math.random() * 550 + 50, 0); } } //小さいきのこ作成 private function makeKinokoS(x:Number, y:Number):void { var kinoko:Sprite; var land = Math.random(); if (land >= 0.6) { //普通のきのこ kinoko = new kinoko_S1_MC as Sprite; } else if(land >= 0.3){ //怪しいきのこ kinoko = new kinoko_S2_MC as Sprite; } else { //しめじ kinoko = new kinoko_S3_MC as Sprite; } this.makeB2BodyCircle(30, x, y, 1.0, 0.5, 0.5, kinoko, this.m_kinokoS); } } |