Les mecs. J'essaye de créer ma propre version d'un jeu de cartes. J'ai rencontré le problème suivant en essayant de déplacer mes cartes vers le centre du canevas lors d'un événement de clic. Voici un exemple de mon code
import tkinter as tk
class gui(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.canvas = tk.Canvas(parent, bg="blue", highlightthickness=0)
self.canvas.pack(fill="both", expand=True)
self.img = PhotoImage(file="card.gif")
self.card = self.canvas.create_image(10, 10, image=self.img)
self.canvas.tag_bind(self.card, '<Button-1>', self.onObjectClick1)
def onObjectClick1(self, event):
if self.canvas.find_withtag("current"):
x = 400
y = 400
self.canvas.coords("current", x, y)
self.canvas.tag_raise("current")
if __name__ == "__main__":
root = tk.Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry("%dx%d+0+0" % (w, h))
gui(root)
root.mainloop()
Ce que je veux, c'est déplacer ma carte, mais pas simplement passer d'une coordonnée à une autre mais lui donner un effet de ralenti.
3 réponses
L'idée de base est d'écrire une fonction qui déplace légèrement un objet, puis se planifie pour être appelée à nouveau après un court délai. Il le fait jusqu'à ce qu'il atteigne sa destination.
Voici un exemple très simple qui déplace quelques éléments indépendamment. Vous pouvez ajuster la vitesse en modifiant le paramètre speed
ou en modifiant les valeurs de delta_x
et delta_y
.
Il s'agit d'un algorithme très simpliste qui augmente simplement les coordonnées x et y d'une quantité fixe. Vous pouvez à la place calculer des points également espacés le long d'une courbe ou d'une ligne droite. Quoi qu'il en soit, la technique d'animation reste la même.
import Tkinter as tk
def move_object(canvas, object_id, destination, speed=50):
dest_x, dest_y = destination
coords = canvas.coords(object_id)
current_x = coords[0]
current_y = coords[1]
new_x, new_y = current_x, current_y
delta_x = delta_y = 0
if current_x < dest_x:
delta_x = 1
elif current_x > dest_x:
delta_x = -1
if current_y < dest_y:
delta_y = 1
elif current_y > dest_y:
delta_y = -1
if (delta_x, delta_y) != (0, 0):
canvas.move(object_id, delta_x, delta_y)
if (new_x, new_y) != (dest_x, dest_y):
canvas.after(speed, move_object, canvas, object_id, destination, speed)
root = tk.Tk()
canvas = tk.Canvas(root, width=400, height=400)
canvas.pack()
item1 = canvas.create_rectangle(10, 10, 30, 30, fill="red")
item2 = canvas.create_rectangle(360, 10, 380, 30, fill="green")
move_object(canvas, item1, (200, 180), 25)
move_object(canvas, item2, (200, 220), 50)
root.mainloop()
Afin d '«animer» vos cartes en mouvement, un système de décomposition de la distance totale à déplacer, puis de déplacement / mise à jour par des distances plus petites sur une période de temps fonctionnerait.
Par exemple, si vous souhaitez déplacer une carte de 400 unités en x & y, quelque chose comme ceci pourrait fonctionner:
total_time = 500 #Time in milliseconds
period = 8
dx = 400/period
dy = 400/period
for i in range(period):
self.canvas.move(chosen_card, dx, dy)
root.after(total_time/period) #Pause for time, creating animation effect
root.update() #Update position of card on canvas
Cela pourrait être une prémisse de base pour une animation. Bien sûr, vous devrez modifier les variables total_time
et period
dans mon exemple pour créer ce que vous pensez être juste.
Ce code ci-dessous (prêt à copier / coller et à exécuter tel quel) donne un joli mouvement fluide sur ma boîte:
import tkinter as tk
import time
class gui(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.canvas = tk.Canvas(parent, bg="blue", highlightthickness=0)
self.canvas.pack(fill="both", expand=True)
self.img = tk.PhotoImage(file="card.gif")
self.card = self.canvas.create_image(10, 10, image=self.img)
self.canvas.tag_bind(self.card, '<Button-1>', self.onObjectClick1)
def onObjectClick1(self, event):
if self.canvas.find_withtag("current"):
x = 400
y = 400
self.canvas.coords("current", x, y)
self.canvas.tag_raise("current")
total_time = 500 #Time in milliseconds
period = 400
dx = 400/period
dy = 400/period
for i in range(period):
self.canvas.move(self.card, dx, dy) # chosen_card
time.sleep(0.01)
# root.after(total_time/period) #Pause for time, creating animation effect
root.update() #Update position of card on canvas
if __name__ == "__main__":
root = tk.Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry("%dx%d+0+0" % (w, h))
gui(root)
root.mainloop()
Questions connexes
De nouvelles questions
python-3.x
Pour les questions sur la programmation Python qui sont spécifiques à la version 3+ du langage. Utilisez la balise [python] plus générique sur toutes les questions Python et ajoutez celle-ci uniquement si votre question est spécifique à la version. Utilisez les balises [python-2.x] pour les questions Python 2.