web-dev-qa-db-ja.com

衝突チェック方法はどこに実装すればよいですか?

私はpygameでポケモンのぼったくりを作っており、プレイヤーが背の高い草の中にいるかどうかをテストする方法を作りました。ただし、メソッドをどこに呼び出せばよいかわかりません。プレイヤーのmoveメソッド、ゲームループメソッド、およびupdateメソッドを試しました。私がこのようにすると、草の外に移動した後でチェックされます。つまり、初めて草の中に移動したときは機能しません。また、草の外に初めて移動したときは機能します(機能しないとき)。 。

in_grass(self)メソッド:

_def in_grass(self):
        for g in self.game.grass:
            if pygame.Sprite.collide_rect(self, g):
                print(random.randint(1, 10000))
                if random.randint(1, 180) <= 25:
                    self.battle()
_

プレーヤーmove(self)メソッド:

_def move(self, x_change, y_change):
        if x_change > 0:
            self.dir = 'RIGHT'
        if x_change < 0:
            self.dir = 'LEFT'
        if y_change > 0:
            self.dir = 'DOWN'
        if y_change < 0:
            self.dir = 'UP'

        if not self.collide(x_change, y_change):
            self.x += x_change
            self.y += y_change

            image_list = None
            if self.dir == 'UP':
                image_list = self.image_up
            Elif self.dir == 'LEFT':
                image_list = self.image_left
            Elif self.dir == 'RIGHT':
                image_list = self.image_right
            Elif self.dir == 'DOWN':
                image_list = self.image_down

            if image_list:
                if self.walkcount >= len(image_list):
                    self.walkcount = 0
                self.image = image_list[self.walkcount]
                self.walkcount += 1
                self.image.set_colorkey(BLACK)
_

メインループ:

_ def events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_w:
                    self.player.move(0, -1)
                if event.key == pygame.K_a:
                    self.player.move(-1, 0)
                if event.key == pygame.K_s:
                    self.player.move(0, 1)
                if event.key == pygame.K_d:
                    self.player.move(1, 0)

            if event.type == pygame.KEYUP:
                self.player.image = self.player.default_images[self.player.dir]
                self.player.image.set_colorkey(BLACK)
_

編集:私はついにそれを機能させました!自分に賞金を与えることはできないので、ただそこに座っているだけだと思います。

プレーヤーの__init__メソッド呼び出しself.checked = Falseにブール値を作成します。次に、in_grassメソッドで、最後にself.checked = Trueを設定します。 updateメソッドでは、if not self.checked: self.in_grass。最後にmoveメソッドで、最初にself.checked = Falseを設定しました。ようやく機能しました。

だからここに考えるためのいくつかの食べ物があります。

少しの免責事項、私は決してゲーム開発者ではないし、私は非常に経験豊富な開発者でもありません。

大規模なゲームでは、どこで何が起こっているのかをよく把握したい場合があります。ここで、エンティティでいっぱいのゲームがあるとします(画面に表示されるエンティティがゲームに何らかの影響を与えると考えてください)。これらすべてのエンティティをゲームループのフレームごとに更新します。

エンティティは、レンダリング、移動、衝突チェック、プレーヤー入力の影響、アニメーションなど、ゲームで必要な機能に影響する可能性があります。これを行う順序はゲームにとって重要です。エンティティのリストがあるとします。

entities = []

次に、ゲームループ内の各敵をループして行動関数を実行する、このようなことを行うことができます。すべてのエンティティをcheck_collision関数に渡して、このコードをもう少しわかりやすくします。

バージョン1

entities = []
def game_loop:
    while(true):
        for entity in entities:
            entity.gather_input()
            entity.move()
            entity.check_collision(entities)
            entity.animate()
            entity.render()

これを見てみましょう:

バージョン2

entities = []
def game_loop:
    while(true):
        for entity in entities:
            entity.gather_input()
        for entity in entities:
            entity.move()
        for entity in entities:
            entity.check_collision(entities)
        for entity in entities:
            entity.animate()
        for entity in entities:
            entity.render()

エンティティの実行順序が変更されました。これで動作がグループ化されました。ゲームループの更新方法を定義したと言えます。すべての衝突をチェックする前に、エンティティのすべての動きが更新されることがわかりました。

一方、バージョン1では、1つのエンティティに対して最初にすべてのロジックを実行し、次に次のロジックを実行します。バージョン1を使用すると、1つのフレームで関連データが失われる可能性があります。これは、1つのエンティティが移動して、すべてのエンティティが移動するまで実際に待機する必要がある衝突をチェックする可能性があるためです。

これがsparkゲームデザイン/アーキテクチャであるウサギの穴についてのもう少しの調査であることを願っています。

1