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

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

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

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

JavaScript

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

Q&A

解決済

2回答

133閲覧

任意の形の領域内でオブジェクトが跳ね返る動作の実現方法

merry

総合スコア15

canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

JavaScript

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

0グッド

1クリップ

投稿2024/04/19 13:52

編集2024/04/22 11:11

実現したいこと

html, css, jsで作成されたウェブサイトでの実装です
クオータービューの背景絵があり
その中に柵で囲われたひし形に近い庭のエリアがあります
その庭内のみで複数のオブジェクト(人や生き物)が動き回り、端まで来たらランダムな角度に跳ね返らせたいです
ルートは直線的で良く、端まで来たら向きを変えて動く形です

発生している問題・分からないこと

主に考え方についてアドバイスをいただきたいです

クオータービューでの7 * 6マスの長方形(実際の見た目は左右非対称のひし形に近い)内で跳ね返り判定を行う場合、
どのように判定するのがいいでしょうか

いくつかサンプルコードを検索し候補を見つけました
これらのような方法で判定するのがよいでしょうか
さらに簡易に判別する方法があればご教示お願い致します。

  • 跳ね返り判定用のラインを引いてそれと計算して判定する
  • リストこちらのアルゴリズムのように内外判定を行い外判定が出たら跳ね返りを行う

https://www.sojudo.net/programming/gamealgorithm/anglebounce
https://tori29.jp/blog/export_9
https://qiita.com/ykob/items/6118b8e2e7ddcd8b6355

該当のソースコード

こちらの参考サイトをもとに自分なりにコードに落とし込めるか試してみました
試しにコード化してみた自作のデモ

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

いくつかサンプルコードを検索し候補を見つけました
これらのような方法で判定するのがよいでしょうか
さらに簡易に判別する方法があればご教示お願い致します。

  • 跳ね返り判定用のラインを引いてそれと計算して判定する
  • リストこちらのアルゴリズムのように内外判定を行い外判定が出たら跳ね返りを行う

https://tori29.jp/blog/export_9
https://qiita.com/ykob/items/6118b8e2e7ddcd8b6355

補足

座標変換の方法がいまいち分からなかったのでこちらの参考サイトをもとに自分なりにコードに落とし込めるか試してみました
試しにコード化してみた自作のデモ

しかし、マップチップ座標などの概念がいまいち理解できておらず下記のメソッドでのアイソメ座標とマップ座標(上面図?)の相互の変換が出来ませんでした。
mapToIsoisoToMapの2つのメソッド内で参照するオフセットや幅のデータが間違っていそうです。
これら相互の変換をできるようにし、対象がエリア外に出たらランダムな角度で直線状に跳ね返ってエリア内を動き回る挙動を作成したいです。
また、この変換処理を利用して画面に対して右方向(上面図においては斜め方向)に動いているときは対象の向きを変えたい(左右どちらかの2パターン)です。

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

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

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

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

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

TakaiY

2024/04/20 01:31

「検索し候補を見つけました」とありますが、見つけた方法に問題があるということだと思いますが、どのような問題があるのでしょうか。
merry

2024/04/22 11:13

コメントありがとうございます。座標変換処理を試しましたがまだ解決できていません。 試した結果とでもコードを質問に追記しました。
TakaiY

2024/04/22 11:25

やはり、質問の内容が具体的ではありません。 「これらのような方法で判定するのがよいでしょうか」とか「さらに簡易に判別」などと聞かれても答えられる人は少ないでしょう。 すでに実装しているようですから、困っていることやわからないことを「具体的」に、ピンポイントでコードを示したほうがいいでしょう。あれこれコードを並べられても、全て読む気にはなりません。
guest

回答2

0

雑ですがSVGでサンプル作ってみました

javascript

1<style> 2svg{background-Color:lightgray;} 3</style> 4<script> 5 6window.addEventListener('DOMContentLoaded', ()=>{ 7 const svgNS = svg.namespaceURI; 8 const points=[[100,100],[500,100],[400,300],[0,300]]; 9 const createContainer=(points=[],fill=null)=>{ 10 const container=document.createElementNS(svgNS,"polygon"); 11 container.setAttributeNS(null,'fill',fill); 12 const pointsStr=points.map(x=>x.join(",")).join(" "); 13 container.setAttributeNS(null,"points",pointsStr); 14 return container; 15 } 16 const container=createContainer(points,"yellow"); 17 svg.appendChild(container); 18 const lines=points.reduce((x,y,z,w)=>(x.push([y,w[z==w.length-1?0:z+1]]),x),[]); 19 const createMember=(options)=>{ 20 const position=[options.x,options.y,null] 21 const member=document.createElementNS(svgNS,'rect'); 22 member.setAttribute('x',options.x); 23 member.setAttribute('y',options.y); 24 member.setAttribute('width',options.width); 25 member.setAttribute('height',options.height); 26 member.setAttribute('fill',options.fill); 27 const path=document.createElementNS(svgNS,'path'); 28 path.setAttributeNS(null,'id',options.id); 29 const motion=document.createElementNS(svgNS,'animateMotion'); 30 motion.setAttributeNS(null,'fill','freeze'); 31 const mpath=document.createElementNS(svgNS,'mpath'); 32 mpath.setAttributeNS('http://www.w3.org/1999/xlink','xlink:href',`#${options.id}`); 33 svg.appendChild(member); 34 member.appendChild(path); 35 member.appendChild(motion); 36 motion.appendChild(mpath); 37 let timerId; 38 let timer; 39 let delay; 40 const callback=()=>{ 41 timer=new Date().getTime(); 42 motion.endElement(); 43 let rnd=parseInt(Math.random()*lines.length); 44 while(rnd==position[2]){ 45 rnd=parseInt(Math.random()*lines.length);//再抽選 46 } 47 position[2]=rnd; 48 let ratio=Math.random(); 49 let x=parseInt((lines[rnd][1][0]-lines[rnd][0][0])*ratio+lines[rnd][0][0]); 50 let y=parseInt((lines[rnd][1][1]-lines[rnd][0][1])*ratio+lines[rnd][0][1]); 51 let w=options.width; 52 let h=options.height; 53 path.setAttributeNS(null,"d",`M${position[0]},${position[1]} L${x-w/2},${y-h}`); 54 //path.setAttributeNS(null,"stroke","black"); 55 const distance=((position[0]-x)**2+(position[1]-y)**2)**.5; 56 position[0]=x; 57 position[1]=y; 58 motion.setAttributeNS(null,"dur",parseInt(options.speed*distance/10)/100); 59 motion.beginElement(); 60 delay=options.speed*distance; 61 timerId=setTimeout(()=>callback(),delay); 62 } 63 btn_start.addEventListener('click',()=>{ 64 member.removeAttributeNS(null,'x'); 65 member.removeAttributeNS(null,'y'); 66 callback(); 67 btn_stop.disabled=false; 68 btn_start.disabled=true; 69 }); 70 btn_stop.addEventListener('click',()=>{ 71 clearTimeout(timerId); 72 const past=new Date().getTime()-timer; 73 const d=path.getAttributeNS(null,'d'); 74 const reg=/^M(\d+),(\d+) +L(\d+),(\d+)/; 75 if(reg.test(d)){ 76 const matches=d.match(reg); 77 const x=parseInt((Number(matches[1])+(matches[3]-matches[1])*past/delay)*100)/100; 78 const y=parseInt((Number(matches[2])+(matches[4]-matches[2])*past/delay)*100)/100; 79 position[0]=x; 80 position[1]=y; 81 } 82 motion.endElement(); 83 btn_start.disabled=false; 84 btn_stop.disabled=true; 85 }); 86 motion.beginElement(); 87 return member; 88 } 89 const m=createMember({x:150,y:200,width:10,height:10,fill:'red',id:'path1',speed:3}); 90 createMember({x:250,y:200,width:20,height:20,fill:'blue',id:'path2',speed:2}); 91 createMember({x:350,y:200,width:10,height:15,fill:'green',id:'path4',speed:1}); 92 console.log(m); 93}); 94</script> 95<svg width=500 height=400 id="svg"> 96</svg> 97<input type="button" value="start" id="btn_start"> 98<input type="button" value="stop" id="btn_stop" disabled>

投稿2024/04/22 04:22

yambejp

総合スコア114883

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

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

merry

2024/04/22 11:15

回答ありがとうございます。SVGという方法もあるのですね。 座標変換処理で進めることにしましたが試作のコードでうまく落とし込めませんでした
guest

0

ベストアンサー

クオータービューでの長方形

であれば、長方形のままで座標と速度ベクトルを管理して、表示するときだけ座標を菱形にマップすれば簡単そうです。

投稿2024/04/19 15:03

int32_t

総合スコア20909

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

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

merry

2024/04/22 11:24

回答ありがとうございます。 おっしゃる通り座標変換処理で進めるのがよさそうなので試作でデモを作成してみました。 1マス、幅40高さ20のひし型でグリッドを作成してみましたがこれの上面図での幅がどうなるのか理解できておらず座標変換メソッドにうまく落とし込めませんでした。 参考にしたサイト(https://2dgames.jp/how-to-make-isometric-view/)だとトップビューのタイル画像が正方形ですが描画用の情報はひし形のサイズしかないので混乱してしまいました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問