Si c'est "bien" pourquoi en parler!
Et sinon ou est le code?
- W
Version imprimable
Je me suis mal exprimé x)
La personne me demandée si c’était le faite que la fenêtre ne s'affiche pas du tout ou juste pas en premier plan.
J'ai alors dis que c’était bien le fait que la fenêtre ne s'affiche pas en premier plan et pas le fait qu'elle ne s'affiche pas du tout.
Donc la j'essaye de mieux gérer les collisions sur les paroies.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 from tkinter import * import tkinter as tk import random # Constantes WIDTH, HEIGHT = 500, 400 RADIUS = 8 COLORS = ["Red","Yellow","Gray","White","Black","Blue","Green","Orange","Pink"] # Variables globales canvas = None balles = [] deltas = [] positions = [] def balle_create(): randint = random.randint x = randint(RADIUS, WIDTH-RADIUS) y = randint(RADIUS, HEIGHT-RADIUS) color = random.choice(COLORS) iid = canvas.create_oval(x - RADIUS, y - RADIUS, x + RADIUS, y + RADIUS, fill = random.choice(COLORS), outline='black', tag='balle') d = RADIUS//2 deltas.append( (randint(-d, d), randint(-d, d)) ) positions.append( (x, y) ) balles.append(iid) DELAY = 50 def motion(): x_min, x_max = RADIUS, WIDTH - RADIUS y_min, y_max = RADIUS, HEIGHT - RADIUS for n, iid, in enumerate(balles): dx, dy = deltas[n] canvas.move(iid, dx, dy) x, y = positions[n] if not (x_min < x < x_max): dx = -dx if not(y_min < y < y_max): dy = -dy positions[n] = (x + dx, y + dy) deltas[n] = (dx, dy) canvas.after(DELAY, motion) if __name__ == '__main__': nb_balles = int(input('nombre de balles: ')) root = tk.Tk() root.title('Boules & Billes') canvas = tk.Canvas(width=WIDTH, height=HEIGHT, bg='white') canvas.pack(fill=BOTH) for _ in range(nb_balles): balle_create() motion() tk.mainloop()
En modifiant ceci,
En ceci,Code:
1
2
3 x_min, x_max = RADIUS, WIDTH - RADIUS y_min, y_max = RADIUS, HEIGHT - RADIUS
J'avais essayé cela:Code:
1
2
3 x_min, x_max = RADIUS, WIDTH y_min, y_max = RADIUS, HEIGHT
et pareil pour l'autre coté :Code:
1
2
3
4
5
6 if x + dx > x_max - RADIUS : dx = (x_max - x - RADIUS) canvas.move(iid, dx, dy) positions[n] = (x + dx, y + dy) dx = -dx
Mais lorsque les balles touchent les parois, elles s'embarquent dans la boucle et ainsi, le dx switch entre -dx et dx a chaque tour de boucle.Code:
1
2
3
4
5
6 if x + dx < RADIUS : dx = x - RADIUS canvas.move(iid, dx, dy) positions[n] = (x + dx, y + dy) dx = -dx
Salut,
Avant de code, il faut réfléchir à ce qu'on veut faire! Si vous vous contentez d’essayer des trucs, sans vous assurez avant de coder qu'ils ont quelques chances de faire ce que vous attendez vous allez vous épuiser en essais/erreurs construire quoi que ce soit.
Dans votre truc, il y a des abstractions pas évidentes à capter.
Prenez juste:
Si on veut avoir l'impression que les balles bougent de façon "smooth", il va falloir calculer la position suivante et déplacer les balles tous les 1/30 s.Code:
1
2
3
4 def motion(): # calcul de la position suivante en prenant compte des collisions # affichage des balles dans leur nouvelle position canvas.after(DELAY, motion)
Avec un petit nombre de balles, on pourra supposer que le temps de calcul sera négligeable garder DELAY constant (ou éviter de calculer les affichages en dehors de la boucle).
Prendre en compte les collisions commence par les rebonds sur les murs.
Pour chaque balle, les tableaux positions et deltas donnent:
- x, y : la position
- dx, dy: le déplacement
le déplacement est à appliquer à chaque itération pour calculer la nouvelle position.
Baladons nous sur l'axe des X:
soit u = x + dx la position espérée.
si u >= x_max:
la position future sera x = x_max + (x_max - u) = 2 * x_max -u
si u <= x_min:
x sera x_min + (x_min - u) = 2 * x_min - u
dans les deux cas, on inverse dx pour calculer le coup suivant.
Pour l'axe des Y, l'algo sera semblable.
Reste à s'assurer que la chose fonctionne aussi pour les "coins" i.e. la balle rebondit sur un bord puis sur l'autre dans la même étape.
Une fois que vous aurez fait des petits dessins, que vous serez convaincu que çà mérite d'être codé, il va falloir définir comment tester les différents cas.
nota: le but des tests sera d'assurer que vous avez codé proprement votre algo et non que l'algo fait ce que vous attendez.
Alors et alors seulement, vous pourrez commencer à coder.
- W
Si je prends pour exemple un x a 494, un dx a 5 et un x_max a 500 - 5Citation:
soit u = x + dx la position espérée.
si u >= x_max:
la position future sera x = x_max + (x_max - u) = 2 * x_max -u
si u <= x_min:
x sera x_min + (x_min - u) = 2 * x_min - u
dans les deux cas, on inverse dx pour calculer le coup suivant.
u = 494 + 5 = 499
499 >= 495
donc x = 2*495 - 499 = 491
Déplacement de la balle en x = 491
Nouvelle Itération, le x passe de 494 a 491 ?
Il reculerait donc ?
Même s'il se déplace de dx = 5 après, il arriverait a 496, et donc dépasserait de l’écran car 496 + rayon = 501, non ?
Oui, pour rendre compte du "rebond" elastique sur le bord.
Si le déplacement à appliquer à chaque itération était dx = 5, il deviendra -5 après le rebond. A l'itération suivante la position serait 491 - 5 = 486. Et on appliquera -5 jusqu'à ce que la contrainte x_min fasse repasser à +5.Citation:
Même s'il se déplace de dx = 5 après, il arriverait a 496, et donc dépasserait de l’écran car 496 + rayon = 501, non ?
Après, il faut voir si on veut faire des calculs justes ou si on veut simplement avoir un rendu pas trop faux.
Ce que je veux dire par là, c'est que si les déplacement sont "petits" et que le delay entre itération est "court", l’œil pourra se faire bluffer si on ignore ce détail dans le rebond.
- étape n: la collision se contente d'inverse dx et positionne la balle en 499 (on passe à travers le "mur".
- étape n+1: la balle ira en 494
Côté animation, çà se défend, mais si le sujet est de faire des mathématiques vous aurez un "0" pointé.
- W
Apres avoir fait les calcules sur s'que tu m'as montré, j'ai essayé ceci :
Relever de x :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 def motion(): x_min, x_max = RADIUS, WIDTH - RADIUS y_min, y_max = RADIUS, HEIGHT - RADIUS for n, iid, in enumerate(balles): x, y = positions[n] dx, dy = deltas[n] u = x + dx print(x) if u >= x_max : print(x) x = 2 * x_max - u dx = -dx positions[n] = (2 * x_max - u , y) print(x) if u <= x_min : print(x) x = 2 * x_min - u dx = -dx positions[n] = (2 * x_min - u , y) print(x) dx, dy = deltas[n] canvas.move(iid, dx, dy) positions[n] = (x + dx, y + dy) canvas.after(DELAY, motion)
Donc le x va stagner entre 488 et 493,Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 458 461 464 467 470 473 476 479 482 485 488 491 491 490 493 493 488 491
Si je comprend bien, ce qu'il se passe c'est qu’après l'inversion dx, a l’itération suivante, la condition u >= x_max est de nouveau validées et par conséquent, dx s'inverse a nouveau
EDIT : Enfaite ca fonctionne =)
Je vais essayer d'attaquer les collisions entres les balles maintenant.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 def motion(): x_min, x_max = RADIUS, WIDTH - RADIUS y_min, y_max = RADIUS, HEIGHT - RADIUS for n, iid, in enumerate(balles): x, y = positions[n] dx, dy = deltas[n] u = x + dx if u >= x_max : x = 2 * x_max - u dx = -dx positions[n] = (2 * x_max - u , y) if u <= x_min : x = 2 * x_min - u dx = -dx positions[n] = (2 * x_min - u , y) u = y + dy if u >= y_max : y = 2 * y_max - u dy = -dy positions[n] = (x , 2 * y_max - u) if u <= y_min : y = 2 * y_min - u dy = -dy positions[n] = (x , 2 * y_min - u) deltas[n] = dx, dy canvas.move(iid, dx, dy) positions[n] = (x + dx, y + dy) canvas.after(DELAY, motion)
Je pensais faire un test de collision de la balle de l’itération actuelle, sur toutes les autres balles une a une, il y a un moyen de faire plus simple ?
Salut,
Pas du tout!Citation:
EDIT : Enfaite ca fonctionne =)
Si on fait tout ces calculs pour canvas.move(iid, dx, dy) l'oeil est content mais pourquoi les avoir fait?
- W
Tu peux mémoriser les pixels de ton plateau de jeu et, chaque fois qu'une balle se déplace, positionner les pixels adéquats avec le n° de la balle qui s'y trouve. Et si un pixel n'est pas vide quand la balle y arrive, c'est qu'il y a collision et tu sais de suite avec quelle balle...
La je ne comprend pas, sur le papier ça devrait fonctionner ...Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 for n, iid, in enumerate(balles): x, y = positions[n] dx, dy = deltas[n] u = x + dx if u >= x_max : print(dx) print(positions[n]) canvas.move(iid, x_max - x , dy) positions[n] = (x + (x_max - x) , y) print(positions[n]) dx = -dx if u <= x_min : canvas.move(iid, x_min - x , dy) positions[n] = (x + (x_min - x) , y) dx = -dx u = y + dy if u >= y_max : canvas.move(iid, dx , y_max - y) positions[n] = (x , y + (y_max - y)) dy = -dy if u <= y_min : canvas.move(iid, dx , y_min - y) positions[n] = (x , y + (y_min - y)) dy = -dy deltas[n] = dx, dy canvas.move(iid, dx, dy) positions[n] = (x + dx, y + dy)
Si je prend x = 488 et dx = 5
u = 488 + 5 = 493
u >= x_max (492)
move de x_max - x = 492 - 488 = 4
pos = x + (x_max - x) = 492
dx = - dx
Donc l'illusion devrait être bonne ? Ce n'est pas le cas :X
Pourtant sur mes schémas/calculs, ça donne le rendu voulu
Salut,
Faites marcher le truc sans essayez d'entrelacer calculs et mises à jours du graphique. et canvas.move(iid, x_max - x , dy) c'est archi faux ca, non?
- WCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 for n, iid, in enumerate(balles): x, y = old_positions[n] dx, dy = deltas[n] u = x + dx if not (x_min < u < x_max): dx = -dx if u >= x_max : u = 2 * x_max - u if u <= x_min : u = 2 * x_min - u v = y + dx ... # ici on a les anciens x, y et les nouveaux u, v, dx, dy deltas[n] = dx, dy positions[n] = (u, v) canvas.move(iid, u - x, v - y)
C"est archi faux, c'est a dire ?