質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
CreateJS

CreateJSは、HTML5でリッチコンテンツを制作できるJavaScriptライブラリ群です。JavaScriptの知識があれば、HTML5のCanvasをコントロールしコンテンツを作ることができます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1279閲覧

CreateJSで複数のシェイプを作成したときの当たり判定やドラッグ&ドロップの書き方

退会済みユーザー

退会済みユーザー

総合スコア0

CreateJS

CreateJSは、HTML5でリッチコンテンツを制作できるJavaScriptライブラリ群です。JavaScriptの知識があれば、HTML5のCanvasをコントロールしコンテンツを作ることができます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2019/01/21 10:22

編集2019/01/21 10:30

前提・実現したいこと

私は、今までHTML・CSSを中心に1年間程コーディングしてきて、javascriptはjqueryなどライブラリを使用して簡単な実装をするくらいしか、使ってこなかったのですが、最近javascriptの学習をし始めている者です。

CreateJSというライブラリを使用して、以下のようなことを実現させたいと思っているのですが、複数のシェイプを作成したときの書き方がわからず困っております。
コードは色々なサイトで説明されているのを調べたりして書きました。

ー実現させたいこと(すべてを満たしたい条件)ー
・テキストを重ねた円のシェイプを複数(2つ以上)
・それぞれドラッグ&ドロップができる
・上下左右の端に壁があるようにしたい(canvasの枠の中にシェイプの全体がいつでも収まる状態?)
・当たり判定で、シェイプ同士が衝突したときに弾き合うようにしたい
・マウス操作での勢いに基づいて速さをつけたい(現段階でのコードだと、ドラッグしたところとドロップしたところの距離に比例してドロップ時の速さが決まってしまっていると思います。)

javascriptの基本もまだまだわかっておらず、見当違いのことを書いているかもしれませんが、どなたかご教示いただけますと幸いです。

発生している問題

現段階でのコードは「該当のソースコード」の通りです。

シェイプとテキストはセットで1つのコンテナに入れています。

・ドラッグ&ドロップでそれぞれ動かせるようにしたい
のですが、コンテナ1とコンテナ2のドラッグ時(クリック時)に取得する、それぞれの座標がうまく切り分けられていない?せいか、コンテナ1とコンテナ2が一緒に移動してしまう状況です。
おそらく、stage.mouseXとstage.mouseYをコンテナ1でもコンテナ2にも
書いているからだとは思っているのですが、どのように書けばよいか分かりません。

・当たり判定で、シェイプ同士が衝突したときに弾き合うようにしたい
のですが、以下のやり方で、できると調べてでてきたのですが、あたっているときの処理はどのように書けばシェイプ同士が衝突したとき弾くようになるのかが分かりません。

javascript

1// ●と△の相対座標を求める 2var point =.localToLocal(0, 0,); 3// △と●があたっているかを調べる 4var isHit =.hitTest(point.x, point.y); 5 6if(isHit == true){ 7 // あたっている時の処理 8}else{ 9 // 離れている時の処理 10}

・マウス操作での勢いに基づいて速さをつけたい
のですが、ここはどう書けばよいのでしょうか。

javascript

1vx = (stage.mouseX - old1X) / 8; 2vy = (stage.mouseY - old1Y) / 8;

上記のコードは元々は、

javascript

1vx = stage.mouseX - old1X; 2vy = stage.mouseY - old1Y;

でしたが、速度を落としたいと思い、「/ 8」を加えました。

該当のソースコード

<!DOCTYPE html> <html> <head> <title>サンプル</title> <meta http-equiv="content-type" charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="sample.css" rel="stylesheet"> <script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script> <script src="https://code.createjs.com/1.0.0/createjs.min.js"></script> </head> <body> <canvas id="myCanvas" width="1000" height="700" style="background-color: #ffe500;"></canvas> </body> <script> // 読み込みが終わってから初期化 window.addEventListener("load", init); function init() { // Stageオブジェクトを作成。 // 初期化 var stage = new createjs.Stage("myCanvas"); // 速度情報 var vx = 0; // 初期の速さ var vy = 0; var flag = false; var old1X; var old1Y; var old2X; var old2Y; var radius = 120; // 円の半径 // コンテナー1(グループの親)を作成 var container1 = new createjs.Container(); container1.x = 200; container1.y = 200; stage.addChild(container1); // 画面に追加 // コンテナー2(グループの親)を作成 var container2 = new createjs.Container(); container2.x = 800; container2.y = 400; stage.addChild(container2); // 画面に追加 // コンテナ1の円を作成します var circle1 = new createjs.Shape(); circle1.graphics.beginFill("darkorange"); // オレンジで描画するように設定 circle1.graphics.drawCircle(0, 0, radius); //半径120pxの円を描画 container1.addChild(circle1); // 表示リストに追加 // コンテナ2の円を作成します var circle2 = new createjs.Shape(); circle2.graphics.beginFill("darkorange"); // オレンジで描画するように設定 circle2.graphics.drawCircle(0, 0, radius); //半径120pxの円を描画 container2.addChild(circle2); // 表示リストに追加 // コンテナ1の円の中のテキストを作成します var text1 = new createjs.Text("CreateJS", "28px Gothic", "black"); text1.textAlign = "center"; text1.textBaseline = "middle"; container1.addChild(text1); // コンテナ2の円の中のテキストを作成します var text2 = new createjs.Text("プログラム言語", "28px Gothic", "black"); text2.textAlign = "center"; text2.textBaseline = "middle"; container2.addChild(text2); // コンテナ1のドラッグした場所を保存する変数 var dragPoint1X; var dragPoint1Y; // コンテナ1のインタラクティブの設定 container1.addEventListener("mousedown", handleDown); container1.addEventListener("pressmove", handleMove); container1.addEventListener("pressup", handleUp); // コンテナ1を押したときの処理です function handleDown(event) { // ドラッグを開始した座標を覚えておく dragPoint1X = stage.mouseX - container1.x; dragPoint1Y = stage.mouseY - container1.y; // マウスの位置を保存 old1X = stage.mouseX; old1Y = stage.mouseY; } // コンテナ1を押した状態で動かしたときの処理です function handleMove(event) { container1.x = stage.mouseX - dragPoint1X; container1.y = stage.mouseY - dragPoint1Y; } // コンテナ1からマウスを離したときの処理です function handleUp(event) { // コンテナ1の速度を有効にする(ドラッグした距離に応じて、速度を設定) vx = (stage.mouseX - old1X) / 8; vy = (stage.mouseY - old1Y) / 8; // コンテナ1の速度を無効にする flag = false; } // コンテナ2のドラッグした場所を保存する変数 var dragPoint2X; var dragPoint2Y; container2.addEventListener("mousedown", handleDown); container2.addEventListener("pressmove", handleMove); container2.addEventListener("pressup", handleUp); // コンテナ2を押したときの処理です function handleDown(event) { // ドラッグを開始した座標を覚えておく dragPoint2X = stage.mouseX - container2.x; dragPoint2Y = stage.mouseY - container2.y; // マウスの位置を保存 old2X = stage.mouseX; old2Y = stage.mouseY; } // コンテナ2を押した状態で動かしたときの処理です function handleMove(event) { container2.x = stage.mouseX - dragPoint2X; container2.y = stage.mouseY - dragPoint2Y; } // コンテナ2からマウスを離したときの処理です function handleUp(event) { // コンテナ2の速度を有効にする(ドラッグした距離に応じて、速度を設定) vx = (stage.mouseX - old2X) / 8; vy = (stage.mouseY - old2Y) / 8; // コンテナ2の速度を無効にする flag = false; } createjs.Ticker.addEventListener("tick", handleTick); function handleTick() { // 重力計算 vy += 0.01; // コンテナ1をドラッグ中でないときだけ物理演算 if (flag == false) { //重力 vy += 0.01; // 摩擦 vx *= 0.85; vy *= 0.85; // コンテナ1に物理演算を適用 container1.x += vx; container1.y += vy; // コンテナ1が画面の端からはみ出さないようにする処理 if (container1.x + radius > stage.canvas.width) { container1.x = stage.canvas.width - radius; vx *= -0.8; } else if (container1.x - radius < 0) { container1.x = radius; vx *= -0.8; } if (container1.y + radius > stage.canvas.height) { container1.y = stage.canvas.height - radius; vy *= -0.8; } else if (container1.y - radius < 0) { container1.y = radius; vy *= -0.8; } } else { if (container1.x + radius > stage.canvas.width) { container1.x = stage.canvas.width - radius; } else if (container1.x - radius < 0) { container1.x = radius; } if (container1.y + radius > stage.canvas.height) { container1.y = stage.canvas.height - radius; } else if (container1.y - radius < 0) { container1.y = radius; } } // コンテナ2をドラッグ中でないときだけ物理演算 if (flag == false) { //重力 vy += 0.01; // 摩擦 vx *= 0.85; vy *= 0.85; // コンテナ2に物理演算を適用 container2.x += vx; container2.y += vy; // コンテナ2が画面の端からはみ出さないようにする処理 if (container2.x + radius > stage.canvas.width) { container2.x = stage.canvas.width - radius; vx *= -0.8; } else if (container2.x - radius < 0) { container2.x = radius; vx *= -0.8; } if (container2.y + radius > stage.canvas.height) { container2.y = stage.canvas.height - radius; vy *= -0.8; } else if (container2.y - radius < 0) { container2.y = radius; vy *= -0.8; } } else { if (container2.x + radius > stage.canvas.width) { container2.x = stage.canvas.width - radius; } else if (container2.x - radius < 0) { container2.x = radius; } if (container2.y + radius > stage.canvas.height) { container2.y = stage.canvas.height - radius; } else if (container2.y - radius < 0) { container2.y = radius; } } // 画面更新 stage.update(); } } </script> </html>

補足情報(FW/ツールのバージョンなど)

OS: windows

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

javascript

1<!DOCTYPE html> 2<title></title> 3<meta charset="utf-8"> 4 5<style> 6canvas { background: #fd0; } 7</style> 8 9<body> 10 <canvas width="700" height="700"></canvas> 11 12<script> 13{ 14 const 15 GAIN = 0.99, 16 PI2 = Math.PI * 2, 17 DEF_COLOR = 'rgba(255,0,0,.5)'; 18 19 //__ 20 class Point { 21 constructor (x = 0, y = 0) { 22 this.x = x; this.y = y; 23 } 24 } 25 26 //__ 27 class Vector extends Point { 28 constructor (x, y) { 29 super (x, y); 30 } 31 } 32 33 34 //__ 35 class Ball extends Point { 36 constructor (name, x, y, r = 100, color = DEF_COLOR, direction = new Vector) { 37 super (x, y); 38 this.name = name; 39 this.r = r; 40 this.color = color; 41 this.direction = direction; 42 this.touched = false; 43 this.offset = null; 44 } 45 46 setTouch ({x: px, y: py}) { 47 let {x, y, r} = this; 48 if ((px - x)**2 + (py - y)**2 < r**2) { 49 this.touched = true; 50 this.offset = new Point (x - px, y - py); 51 this.direction = new Vector; 52 } 53 } 54 55 isCollision ({x: px, y: py, r: pr}) { 56 let {x, y, r} = this; 57 return (x - px)**2 + (y - py)**2 <= (r + pr)**2; 58 } 59 } 60 61 62 //__ 63 class Mouse extends Point { 64 constructor (target = document, ary = [ ]) { 65 super (0, 0); 66 this.target = target; 67 this.ary = ary; 68 this.mx = 0; 69 this.my = 0; 70 71 ['mousedown', 'mousemove', 'mouseup'] 72 .forEach (etype => target.addEventListener (etype, this, false)); 73 } 74 75 handleEvent (event) { 76 this[event.type](event); 77 } 78 79 mousedown (event) { 80 this.ary.forEach (b => b.setTouch (this)); 81 } 82 83 mousemove (event) { 84 let {x, y, ary} = this; 85 86 ary.forEach (b => { 87 if (b.touched) { 88 let o = b.offset; 89 b.x = x + o.x; 90 b.y = y + o.y; 91 b.direction = new Vector; 92 } 93 }); 94 95 this.mx = x; 96 this.my = y; 97 this.x = event.clientX; 98 this.y = event.clientY; 99 } 100 101 mouseup (event) { 102 let 103 {mx, my, ary} = this, 104 v = new Vector (event.clientX - mx, event.clientY - my); 105 106 ary.forEach (b => { 107 if (b.touched) { 108 b.touched = false; 109 b.direction = v; 110 b.offset = null; 111 } 112 }); 113 } 114 115 } 116 117 118 //__ 119 class Field { 120 constructor (target, ary = [ ]) { 121 this.target = target; 122 this.ary = ary; 123 this.w = target.width; 124 this.h = target.height; 125 } 126 127 add (obj) { 128 this.ary.push (obj); 129 } 130 131 progress () { 132 let { w, h, ary } = this; 133 134 ary.forEach (b => { 135 let 136 {x, y, r} = b, 137 d = b.direction; 138 139 x += d.x *= GAIN; 140 y += d.y *= GAIN; 141 142 if (x < r) { 143 x = r; 144 d.x *= -1; 145 } 146 else if (w - r < x) { 147 x = w - r; 148 d.x *= -1; 149 } 150 151 if (y < r) { 152 y = r; 153 d.y *= -1; 154 } 155 else if (h - r < y) { 156 y = h - r; 157 d.y *= -1; 158 } 159 160 //当り判定後が雑すぎる 161 let tmp = new Ball ('tmp', x, y, r); 162 ary.forEach (tb => { 163 if (tb != b) { 164 if (tmp.isCollision (tb)) { 165 d.x *= -1; 166 d.y *= -1; 167 x = b.x; 168 y = b.y; 169 } 170 } 171 }) 172 173 b.x = x; 174 b.y = y; 175 }); 176 } 177 178 } 179 180 181 //__ 182 class Canvas { 183 constructor (canvas) { 184 this.canvas = canvas; 185 this.ctx = canvas.getContext ('2d'); 186 this.w = canvas.width; 187 this.h = canvas.height; 188 } 189 190 cls () { 191 this.ctx.clearRect (0, 0, this.w, this.h); 192 } 193 194 draw (balls) { 195 let ctx = this.ctx; 196 197 balls.forEach (b => { 198 let {name, x, y, r, color} = b; 199 200 ctx.fillStyle = color; 201 ctx.beginPath (); 202 ctx.arc (x, y, r, 0, PI2, false); 203 ctx.fill (); 204 205 ctx.font = "18px 'MS Pゴシック'"; 206 ctx.fillStyle = 'rgba(0,0,0,.5)'; 207 ctx.textAlign = 'center'; 208 ctx.textBaseline = 'middle'; 209 ctx.fillText (name, x, y); 210 }); 211 } 212 } 213 214 215 //__ 216 this.Point = Point; 217 this.Vector = Vector; 218 this.Ball = Ball; 219 this.Field = Field; 220 this.Mouse = Mouse; 221 this.Canvas = Canvas; 222} 223 224 225 226const 227 target = document.querySelector ('canvas'), 228 canvas = new Canvas (target), 229 balls = [ 230 new Ball ('Hello', 200, 300), 231 new Ball ('こんにちは', 500, 300, 80), 232 new Ball ('当り判定が雑', 700, 500, 70, 'rgba(0,255,255,.5)') 233 ], 234 field = new Field (target, balls), 235 ctrl = new Mouse (target, balls); 236 237function demo () { 238 field.progress (); 239 canvas.cls (); 240 canvas.draw (balls); 241 window.requestAnimationFrame (demo); 242} 243 244demo (); 245 246</script> 247 248</html> 249

投稿2019/01/21 21:59

編集2019/01/23 09:51
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/01/23 04:21

ご回答ありがとうございます!! コードを理解するところから頑張ります。。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問