実現したいこと
- matter.jsの
collisionStart
などの衝突イベント内で、自前の配列にArray.findIndex
で検索したインデックスの次の要素を取得したい
前提
TypeScript, SolidStart, Matter.jsでスイカゲームを作っています。
同じフルーツが衝突して次のフルーツに進化する機能を実装中に以下の問題が発生しました。
発生している問題
進化順は本家?switch版と同じです。
進化前と進化後のフルーツ名をコンソールに出力するようにしているのですが、時折意図しないものが生成されてしまっています。
うまくいく時もあるので不安定な感じです。
//理想 old: orange new: kaki //問題 old: orange new: orange //問題2 old: kaki new: orange
レンダリングでは衝突後に消えて新しいフルーツが生成されるまでは正常に動作しています。
生成するフルーツの種類をArray.findIndex
で検索し、1を足して再度配列を参照するところでつまずいているみたいです。
該当のソースコード
実際はファイルを分けてexport
しています。
- データ定義
TypeScript
1type FruitData = { 2 name: string 3 point: number 4 radius: number 5 imageURL: string 6 } 7 8// データ自動生成 9const boxWidth = 300 10const maxRadius = boxWidth * (2 / 7) 11const fruitRadius = (num: number) => maxRadius / (1.2 ** num) 12 13// 定義 14const fruitList: FruitData[] = [ 15 { 16 name: 'cherry', 17 point: 1, 18 radius: fruitRadius(10), 19 imageURL: '' 20 }, 21//... 中略 22 { 23 name: 'watermelon', 24 point: 66, 25 radius: maxRadius, 26 imageURL: '' 27 } 28]
- 処理
TypeScript
1/* 前略 */ 2 3// 進化後のフルーツの情報を取得 4const newFruitData = (list: FruitData[], name: string) => { 5 6 console.log(`old: ${name}`) // 進化前のフルーツ 7 8 // 進化後のフルーツのインデックス 9 const newIndex = list.findIndex(e => e.name === name) + 1 10 11 // スイカの時は生成しない 12 if (newIndex === list.length) return undefined 13 14 // もしもの為 15 if (newIndex === -1) return undefined 16 17 // 進化後のフルーツ 18 const newData = list[newIndex] 19 console.log(`new: ${newData.name}`) 20 return newData 21} 22 23// フルーツのbodyを生成するための関数 24type FruitObject = (data: FruitData, x: number, y: number) => Matter.Body 25const fruitObject: FruitObject = (data, x, y) => Bodies.circle(x, y, data.radius, { 26 label: data.name 27}) 28 29/* 中略 */ 30 31Events.on(engine, 'collisionStart', e => { 32 e.pairs.forEach(pair => { 33 if (pair.bodyA.label === pair.bodyB.label) { 34 // 間の座標を算出 35 const halfXY = () => { 36 const halfGapX = (pair.bodyA.position.x - pair.bodyB.position.x) / 2 37 const halfGapY = (pair.bodyA.position.y - pair.bodyB.position.y) / 2 38 return {x: pair.bodyA.position.x + halfGapX, y: pair.bodyB.position.y + halfGapY} 39 } 40 const newPos = halfXY() 41 42 // 衝突した2つを削除 43 Composite.remove(fruitsComposite, pair.bodyA) 44 Composite.remove(fruitsComposite, pair.bodyB) 45 46 // 上で定義した関数で新しいフルーツの情報を取得 47 const data = newFruitData(fruitList, pair.bodyA.label) 48 if (!data) return 49 console.log(data) 50 51 // 追加 52 const newFruit = fruitObject(data, newPos.x, newPos.y) 53 54 Composite.add(fruitsComposite, newFruit) 55 } 56 }) 57 })
試したこと
vitestで関数を抽出してテストしたところ何回試しても一貫して正常でした。
TypeScript
1const newFruitData = (list: FruitData[], name: string) => { 2 3 console.log(`old: ${name}`) // 進化前のフルーツ 4 5 // 進化後のフルーツのインデックス 6 const newIndex = list.findIndex(e => e.name === name) + 1 7 8 // スイカの時は生成しない 9 if (newIndex === list.length) return undefined 10 11 // もしもの為 12 if (newIndex === -1) return undefined 13 14 // 進化後のフルーツ 15 const newData = list[newIndex] 16 console.log(`new: ${newData.name}`) 17 return newData 18} 19 20 21test.only('config', () => { 22 // ランダムにフルーツの名前を生成 23 const randomName = fruitList[Math.trunc(Math.random() * fruitList.length)].name 24 25 const data = newFruitData(fruitList, randomName) 26 if (!data) return 27 console.log(data) 28})
- 例
old: orange new: kaki { name: 'kaki', point: 15, radius: 28.705540858318642, imageURL: '' }
補足情報(FW/ツールのバージョンなど)
Node.js v18.16.0
"solid-js": "^1.7.12"
"vite": "^4.4.9"
"solid-start": "^0.3.6"
"vitest": "^0.26.3"
"matter-js": "^0.19.0"
回答1件
あなたの回答
tips
プレビュー