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

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

新規登録して質問してみよう
ただいま回答率
85.46%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

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

Q&A

解決済

4回答

1691閲覧

for文の高速化の為にするべきこととは?

退会済みユーザー

退会済みユーザー

総合スコア0

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

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

0グッド

1クリップ

投稿2020/05/05 02:21

前提・実現したいこと

node.jsでブラウザゲームを作っています。今回はサーバー側の処理についてです。

プレイヤーや敵などのエンティティの処理はfor文でエンティティの数分をループしているのですが、
エンティティ同士のあたり判定最短距離のエンティティの取得などでは、
さらにfor文でエンティティの数分をループしています。
自分のゲームではエンティティの数は推定でも1,000以上は出ると思うので、
仮に1,000回ループを行うと、1,000×1,000=1,000,000回ループしなければならない計算になります。

そこで、for文の高速化の為にするべきことを教えてほしいです。
簡潔に言えばコードの最適化、でしょうか?よろしくお願いします。

該当のソースコード

javascript

1let entities = /*エンティティの情報*/; 2for (let key in entities) { // 1000回(仮定)の処理 3 for (let _key in entities) { // 1000回の処理 を 1000回 行う 4 if (_key != key) { 5 /* あたり判定などの処理 */ 6 } 7 } 8}

試したこと

######エンティティの数:50
→ FPS:5560前後
→ ループ回数:250
######エンティティの数:500
→ FPS:56前後
→ ループ回数:25,000
######エンティティの数:1000
→ ほぼ動いてない
→ ループ回数:1,000,000

######※FPS・・・サーバー側のFPS

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

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

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

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

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

guest

回答4

0

まず考えることは、すべてチェックしなければいけないかどうかです。遠く離れたエンティティ同士は当たり判定の必要がないので、それを省くことでループ回数が減らせます。

空間分割をしよう - Qiita

それと質問のアルゴリズムでは、エンティティ同士の無駄な比較を何度も行っています。例えばエンティティが A B C の三種類だとして、A と A の衝突判定、B と B の衝突判定は不要なはずです。また、A と B を比較した後、B と A を比較する意味もありません。1000 個のエンティティをすべて比較しなければならないとしても比較回数は 1000 × 1000 = 1,000,000 回ではなく、999 + 998 + 997 + ... + 1 = 499,500 回で済むはずです。

次に考えるのは、JavaScript でループしなければならないかどうかです。スクリプトでループするよりも、集合を扱うメソッドを使う方が一般に高速です。実際に高速になるかどうかはやってみなければわかりませんが、filter メソッドを使うことを検討してみてください。

Array.prototype.filter() - JavaScript | MDN

追記

参考:

JavaScriptで大量のオブジェクトの当たり判定を効率的にとる
衝突判定(JavaScript)

投稿2020/05/05 02:36

編集2020/05/05 04:45
Zuishin

総合スコア28662

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

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

退会済みユーザー

退会済みユーザー

2020/05/05 02:57

確かによく考えてみたら無駄な比較がありますね。 ありがとうございます。
guest

0

ベストアンサー

特にゲームに詳しくはありませんが、例えば、「グラディウス」のようなSTGを考える場合。

まず、第一に考えるべきは**「当てる方」と「当てられる方」のどちらで判定させるか**、です。
全てのエンティティに判定処理を持たせようとしているようですが、自機が敵弾で被弾する場合、「敵弾の当たり判定」と「自機の当たり判定」を2回こなす必要はありません。
例えば、次のロジックを組んだ場合、

  • 自機が他と接触した場合、敵弾or敵機ならダメージ処理を行う(被弾処理)
  • 自機が放った弾道に敵が存在したら、ダメージ処理を行う(攻撃処理)

当たり判定を持たせるのは「自機」と「自機が放つ弾道」だけで、他は不要になります。

重要なのはロジックの最適化で、「コードの最適化」はその後で考えるべきかと思います。

Re: CantRunRiver さん

投稿2020/05/05 02:56

think49

総合スコア18170

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

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

0

真っ正直に「ループを高速化する」という発想では、おそらく解決できません。アルゴリズムから変える必要があります。

投稿2020/05/05 02:30

maisumakun

総合スコア145208

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

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

退会済みユーザー

退会済みユーザー

2020/05/05 02:59

アルゴリズムから変える必要があるということは、計算処理の高速化ということですかね? 効率を求める為にもコードを計算処理部分を一度見直した方がいいですね。 ありがとうございます。
guest

0

「本当にforを使わなければ実現できないか」を検討するところからだと思います。
ループは便利ですが条件にそって全てループさせます。
それだけ遅いです。必要な情報を必要なだけ操作するように考え直した方が高速化につながると思います。

投稿2020/05/05 02:37

m.ts10806

総合スコア80859

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

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

退会済みユーザー

退会済みユーザー

2020/05/05 02:58

自分的にはループは必要だと思っていましたが、まずはそこから考えたほうがいいですね。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問