2016-04-23 9 views
0

私のキャンバスにはグリッドがあり、いくつかのセルにはサークルがあります。私の目標は、サークルをグリッドの周りに移動させることですが、別のサークルには移動させないことです。だから、私がサークルを動かすときに、何かがあるかどうかを確認します。もしそうなら、動きをキャンセルします。まず、動きの終わりに衝突をチェックしようとしましたが、動作させることができませんでした。だから私は移動中にチェックしようとしていますが、キャンバスラインもオブジェクトであることに気がついたので、衝突があります。 これらの行の衝突を無視する "単純な"方法はありますが、円の衝突は無視していませんか?いくつかのTkinterの衝突を無視するには?

class Deplacement: 
def __init__(self, canvas, event): 
    self.x = event.x 
    self.y = event.y 
    self.canvas = canvas 
    self.obj = "à déterminer" 
    self.obj2 = "à déterminer" 
    self.couleur = "à déterminer" 
    self.couleur2 = "à déterminer" 
    self.collision = "à déterminer" 
    canvas.bind("<ButtonPress-1>", self.StartMove) 
    canvas.bind("B1-Motion", self.OnMotion) 
    canvas.bind("<ButtonRelease-1>", self.StopMove) 

def StartMove(self, event): #Getting the object I want to move 
    self.x = event.x 
    self.y = event.y 
    self.obj = self.canvas.find_overlapping(self.x - 15, self.y - 15, self.x + 15, self.y + 15) 

def OnMotion(self, event): #This is where I struggle 
    #Trying to get the second circle if it exists 
    self.obj2 = self.canvas.find_overlapping(event.x - 15, event.y - 15, event.x + 15, event.y + 15) 
    if not self.obj2: 
     self.collision = False 
    else: 
     self.collision = True 

def StopMove(self, event): #This works fine, in context, checking items colors to move them or not 
#And objects must be moved by one axis 
    self.couleur = self.canvas.itemcget(self.obj, "fill") 
    if not self.collision: 
     if self.couleur == 'black' or self.couleur == 'white' or self.couleur == 'red': 
      if event.x > self.x and self.y - 10 <= event.y <= self.y + 10: 
       self.move(event, self.obj) 
      elif event.x < self.x and self.y - 10 <= event.y <= self.y + 10: 
       self.move(event, self.obj) 
      elif event.y > self.y and self.x - 10 <= event.x <= self.x + 10: 
       self.move(event, self.obj) 
      elif event.y < self.y and self.x - 10 <= event.x <= self.x + 10: 
       self.move(event, self.obj) 

def move(self, event, obj): #Finally moving objects, works nicely aswell 
    self.x = (event.x - 20) // 50 + 1 
    self.y = (event.y - 20) // 50 + 1 
    self.obj = obj 
    if event.x < 20: 
     self.x = 1 
     self.canvas.coords(self.obj, self.x * 50 - 25, self.y * 50 - 25, self.x * 50 + 15, self.y * 50 + 15) 
    elif event.y < 20: 
     self.y = 1 
     self.canvas.coords(self.obj, self.x * 50 - 25, self.y * 50 - 25, self.x * 50 + 15, self.y * 50 + 15) 
    elif event.x > 470: 
     self.x = 9 
     self.canvas.coords(self.obj, self.x * 50 - 25, self.y * 50 - 25, self.x * 50 + 15, self.y * 50 + 15) 
    elif event.y > 470: 
     self.y = 9 
     self.canvas.coords(self.obj, self.x * 50 - 25, self.y * 50 - 25, self.x * 50 + 15, self.y * 50 + 15) 
    else: 
     self.canvas.coords(self.obj, self.x * 50 - 25, self.y * 50 - 25, self.x * 50 + 15, self.y * 50 + 15) 

PS:フランス語を無視します。

答えて

0

canvasという名前の変数がTkinters 'Canvasクラスのインスタンスであると仮定します。キャンバスに埋め込まれたコードは表示されませんでしたが、canvas.create_line()canvas.create_oval()などのメソッド呼び出しを実装すると仮定します。これらのメソッドのそれぞれは、作成されたシェイプのIDである整数を返します。あなたがしなければならないことは、無視したい形状のIDを格納することです。つまり、衝突を構成すべきでない形状IDのセットを作成することです。それらをignore_theseという名前のセットに入れるとしましょう。

メソッドfind_overlappingは、指定された矩形と重なる図形のタプルを返します。この戻り値をpossible_collisionsとします。これは、2つの段階のプロセスがある

if any(s not in ignore_these for s in possible_collisions): 
    # handle the collision 
else: 
    # go ahead and make the move 

(非衝突形状のセットを作成し、その結果を分析するためにそれを使用する:あなたはあなただけのようなコードに何かのラインを必要とする衝突を持っているのであれば伝えるためにfind_overlapping)。あなたはこれを行う簡単な方法を求めましたが、これらの2つのステップを回避する方法があるかどうかは疑問です。 Tkinterは、少なくとも必要なロジックを書くために必要なフックを与えました。

マニュアル参照:http://effbot.org/tkinterbook/canvas.htm#Tkinter.Canvas

+0

このコレクションで衝突テストを実行して実行するシェイプのセットを維持する方が簡単です。これは、単純化され、繰り返されるフィルタリング操作を回避します。 –

+0

なぜ簡単なのか、それがフィルタリングの量を変更する理由がわかりません。それはあなたのロジックに真実か偽であるかどうかという唯一の疑問です。どちらの場合でも、あなたは動かすたびにフィルターをかけなければなりません。問題はいくつかの衝突を "無視する"方法だったので、私は、無視されないオブジェクトの集合ではなく、無視されるオブジェクトの集合に関して答えを書いた。 –

+0

いいえ、2つのコレクションを維持し、衝突するアイテムを含むコレクションのコリジョンのみをチェックする必要があります。 –

0

キャンバスに項目を追加すると、使用される方法は、(整数)、これらのオブジェクトの一意のIDを返します。これらのIDは、コレクション内で収集し、衝突するアイテムのIDのコレクションを追加する必要があります。

def create_canvas_objects(self): 
    id = canvas.create_object() 
    self.all_canvas_objects_ids.append(id) 
    if object_collides: 
     self.colliding_objects.append(id) 

def check_collisions(self): 
    for object in self.colliding_objects: 
     check the collision 

この方法で、あなたはフィルタリング:(あなたが衝突しない項目を分離できますが、あなたがそれらを使用すると、衝突検出部分を実行するたびにフィルタを適用する必要があります)

これは、擬似コードであります各フレームではなく、非衝突オブジェクトと非衝突オブジェクトの作成時に1回だけ衝突します。

+0

私はあなたが何を意味したのか理解していると思いますが、アイテムは作成時に衝突しないため、プロセス内に衝突するオブジェクトはありません。 [リンク](http://i.imgur.com/aSFQBxs.png?1) これは見た目のようなものなので、開始時の衝突はありません – Hedowas

+0

はい、開始時に衝突はありませんが、衝突(円)を追跡するアイテムのタイプと、そうでないアイテムのタイプです。すべてのオブジェクトIDを 'all_canvas_objects_ids'に、サークルを' colliding_objects'コレクションにも追加します。これで、すべてのオブジェクトではなく、衝突のためにサークルを追跡するだけで済みます。 –

+0

したがって、重複しているオブジェクトがcolliding_objectsコレクション内にある場合、OnMotion関数内のすべてのイベントをチェックする必要があります。しかし、私がそうした場合、ポインタが円で非衝突セルに移動すると、その動きは許されますか? – Hedowas

関連する問題