2012-03-03 18 views
1

私と私の友人は現在ゲームを作ろうとしています。このゲームでは、素晴らしい衝突検出が望まれます。しかし、whileループでマスクを更新する方法を見つけることはできません。 :S私たちは、さまざまな価値を持ち、本当に非論理的なものでさえ、時間の沢山をテストしました。Pythonでの衝突検出とマスク3.2.2

私たちがプレイヤーを移動するたびに、マスクと衝突するとゲームがクラッシュします。そのようなループは、マスクとバックグラウンドを動かすときに、プレイヤーとブッシュが互いに離れていくはずですが、永遠に続きます。

def check_collision(): 
    while pygame.sprite.collide_mask(player, rock): 
     bg.x -= 1 #the x-value of the background 
     rock.x -=1 #the x-value of the object 
  • これは、ボタン "A" を使用して左に行くときだけ、衝突です。
  • また、プレーヤの代わりに背景とすべてのスプライトを移動します。
  • マスクを使用する必要があります。
  • 衝突をチェックすることはわかっていますが、マスクはbg.xとrock.xの後に更新されません。
  • これは、画像が画面上を移動しないためと考えられます。したがって、私たちはwhileループの中にblitを入れようとしました。それでも動作しません。

ご協力いただきありがとうございます。最後に、手動でマスク/オブジェクトを移動する方法はありますか?

答えて

1

まず、マスクを使用した衝突検出は非常に時間がかかります。ゲームが無限ループに入ってもいなくても、ビットマスクとビットマスクのオーバーラップチェックの処理要件によって、ゲームの実行が非常に遅くなります。

いくつかの最大の大きさを持たなければならないものと衝突することができる任意のオブジェクト - つまり、あなたは常にあなたのプレーヤーが含まれています四角形を見つけることができ、そして、あなたの岩のことができます。

簡単な最適化は、しかし、存在します別のものの中に収まる。したがって、あなたのプレイヤーの箱がボルダーの箱に衝突しなければ、それらはおそらく重なり合うことはできません。衝突マスキング(ピクセルマッチゲームに現実感を追加することができます)を主張しているので、バウンディングボックスが衝突するたびに(そしてのみのみ)ピクセルごとの衝突を計算することができます。

今、あなたのコーディングスタイルの上:>:O

理想的インスタント衝突チェックを計算する必要がある関数内の潜在的無限ループを置くことをお勧めことはありません。最良の場合のシナリオ(確かに達成可能)では、2つのオブジェクトが衝突するかどうかをチェックし、より有用な情報(他のオブジェクトとの相対的な位置など)を示す1つの関数を持ちます。移動するすべてのオブジェクトの別個のメソッドが衝突を修正します。

このようなものに変換します:オブジェクト管理の基本の実装に依存

あなたcolisionチェックが行われている場所については
class CollidingObject: 
    #This class controls an object which can move and fix collisions 

    def __init__(self): 
     self.x = 0 #add relevant initialization code here 
     self.y = 0 
     self.xVel = 0 # X and Y velocity (for movement) 
     self.yVel = 0 
     self.xSize = 0 # the width of the object in pixels 
     self.ySize = 0 # the height of the object in pixels 

    def iscolliding(self, other): 
     # using x and y as the center of the object, 
     # this returns an empty tuple if they don't collide 
     if ((self.xSize + other.xSize)/2 <= abs(self.x - other.x)) and 
      ((self.ySize + other.ySize)/2 <= abs(self.y - other.y)): return() 
     """ 
     use pygame collidemask here to compute whether they collide. 
     if they do, return a vector of 'other's' position relative to self. 
     (this can be used to decide how to separate the objects) 
     """ 

    def restitute(self, overlaps_with, distances): 
     """ 
     Given some objects which overlap, and a list of 2D vectors of their 
     relative distances, this separates them however much you like. 
     """ 
     pass 

、。あなたのゲーム内のオブジェクトはすべてイテラブル内に含まれていると私は今まで考えています。そしてそれはあなたが一度にそれらを移動するために、一度、レンダリングするために、あなたのオブジェクトを反復処理し、フレームごとに - このような何かの構造:この場合

while NOT_QUIT: 

    for object in objects: 
     object.draw_to_screen() 
     object.move() # moves the object -- collisions, etc in here 

    event_handling_stuff() # handles events 

、すべてのオブジェクトは、それを次のものをチェックし、衝突を計算することができますオブジェクト。そうすることで、各オブジェクトは、それぞれからどれだけ遠くに移動しなければならないかを収集することができます。その後、各オブジェクトは、可能な限り各コライダーから遠くに移動することができます。

私が書いたいくつかのゲームで

、私は、オブジェクトが遠く離れて移動する多くの衝突にも、非常にラフな反発アルゴリズムは非常にセクシーに見える弾性品質を与え、それらは重なっ作ると思います。一般的に、作業チェックをして、それがあなたの心配の中で最も少なくなると、定数で微妙に調整することができます。

うまくいけば、これはあなたに少し助けになりました(今私は接線上でちょっと離れましたが、間違ったことをより効率的に行う方法を尋ねていました:P)。

tl; dr:衝突チェック機能内で衝突を修正しようとしないでください。代わりに、他のオブジェクトへのすべての衝突を検出するものと、オブジェクトのすべての衝突を同時に修正するものに分離します。 他の質問を追加して、私は(更新されます:一般2 /)

:ぞんざいにTADを説明した"vector of other to self"ビット(上ここでは拡大


UPDATE 1

オブジェクトは、実際の生活の中で衝突し、彼らはどこから来た方向にやや立ち直る(あなたが床にゴムスーパーボールをドロップすると、それが出所から戻ってバウンス - それはちょうど床を通じてphazeしません)。ほとんどでプログラミングアプリケーションでは、弾みのついたボールを作りたい他の衝突のもの)(まあ、時にはあなたはボールが床もののphazeする場合がありますが、それは私見バウンスよりも簡単だと同じように動作:Pを)。オブジェクトが立ち直る必要がある方法を知っている

は、あなたはそれが来た方向を知っている必要があります。より厳密には、衝突した角度を知る必要があります。これは、衝突中に各オブジェクトの中心間の距離と方向を比較すると非常に簡単に見つかります。これは、使用している中心が質量中心に近い場合(ほとんどのゲームでは、オブジェクトの真ん中が簡単で近似している)、バウンスする2つのオブジェクトのかなり正確な表現を提供します。

だから、我々は質量の中心を心配する必要があり、すべてのことがないので、私たちは、オブジェクト位置の間のベクトル距離を測る:

#Continuing the previous example, we put some code like this in 'iscolliding' :) 
if they collide (pygame mask stuff) : 
    x_distance = self.x - other.x 
    y_distance = self.y - other.y 
    return (x_distance, y_distance) 

このコードは、あなたに沿って、各オブジェクトの行を与えることができますできるだけ速く衝突を解決するために移動すべきである。残りの部分は、このラインに沿って各オブジェクトを加速し、それらが互いに接近しないように(標識に注意を払う)、定数を微調整して現実的な効果を作り出すことです。

+0

こんにちは!どうもありがとうございました!これが私たちを大いに助けてくれました! しかし、まだいくつか質問があります。 :) 私はあなたに戻って来てみよう!私たちはそれを解決しようとしています:) – AimEffect

+0

私たちは自己に対する相対的位置のベクトルを返すことができますか? – AimEffect

+0

私たちは本当に一部を取得いけない:)私たちを助けてください。 「彼らが衝突するかどうかを計算するために、ここで」」 使用pygameのダウンロードcollidemask 彼らがしなければ、自己に 『相手の』相対位置のベクトルを返し (これはできます。 "" " – AimEffect