Home > OS >  How do i move multiple objects at the same time but every object by different distance in tkinter py
How do i move multiple objects at the same time but every object by different distance in tkinter py

Time:05-27

I have a game that generates multiple objects and which object comes to other side of canvas wins. When you press button every object moves a different random distance forward. The problem is that firts object moves the least and last object moves the most. So last object always wins. How do i made it that random object will win and not always the last one.

import tkinter
import random
canvas=tkinter.Canvas(width=400, height=400)
canvas.pack()

label=tkinter.Label(text='set amout of cars')
label.pack()

entry=tkinter.Entry()
entry.pack()

def car():
    global move
    move=0
    canvas.delete('all')
    p=int(entry.get())
    for i in range(p):
        canvas.create_rectangle(20,20 i*20,40,30 i*20, fill='coral')

move=0

def race():
    global move
    canvas.delete('all')
    p=int(entry.get())
    for i in range(p):
        rand=random.randint(5,20)
        move=move rand
        canvas.create_rectangle(20 move,20 i*20,40 move,30 i*20, fill='coral')
    
    
        
button=tkinter.Button(text='start', command=car)
button.pack()
button2=tkinter.Button(text='forward', command=race)
button2.pack()

CodePudding user response:

As described in the comments, every object shares the same move variable, so each object starts where the last one stopped.

The better solution is to call the move method on the canvas for each of the objects. You can either save a list of objects or just ask the canvas to give you the objects. You can then use randint to decide how much to move each item.

The race function would look something like this:

def race():
    for car in canvas.find("all"):
        delta_x = random.randint(5,20)
        delta_y = 0
        canvas.move(car, delta_x, delta_y)

CodePudding user response:

All your objects use the same variable move - so in every execution of race they use the same position. But in every loop you add new values to move - so first object use distance move rand1, second move rand1 rand2, third move rand1 rand2 rand3, etc - and this makes problem.

Every object should have own variable with position.

So it would need to use list with positions.


Or better create object only once and get ID

car_id = canvas.create_rectangle(...)

and later use ID to move this object

canvas.move(car_id, ...)

and this way every car will use own position.

And of course it also need to use list to keep all IDs


def restart():
    canvas.delete('all')
    all_cars.clear()

    number = int(entry.get())

    for i in range(number):
        car_id = canvas.create_rectangle(20, 20 i*20, 40, 30 i*20, fill='coral')
        all_cars.append( car_id )

def race():
    for car_id in all_cars:
        distance_x = random.randint(5,20)
        distance_y = 0
        canvas.move(car_id, distance_x, distance_y)

# --- main ---

all_cars = []

EDIT:

Full working code:

I also used

  • after(100, race) - so it automatically repeate function after 100ms and you don't have to click button race again and again.

  • canvas.corrds() to get current position and check if it end of race.

  • create_line to show finish line

import tkinter as tk
import random

# --- functions ---

def restart():
    canvas.delete('all')
    all_cars.clear()

    number = int(entry.get())

    for i in range(number):
        car_id = canvas.create_rectangle(20, 20 i*20, 40, 30 i*20, fill='coral')
        all_cars.append( car_id )

    # finish line
    canvas.create_line(360, 10, 360, 30 (number-1)*20   10, fill='red')
    
def race():
    winner = False
    
    for car_id in all_cars:
        distance_x = random.randint(5, 20)
        distance_y = 0
        canvas.move(car_id, distance_x, distance_y)

        x1, y1, x2, y2 = canvas.coords(car_id)
        
        if x1 >= 360:
            winner = True
            canvas.moveto(car_id, 360, y1-1)
            canvas.itemconfig(car_id, fill='green')

    if not winner:
        root.after(100, race)
    
# --- main ---

all_cars = []  # list for all IDs

root = tk.Tk()

canvas = tk.Canvas(root, width=400, height=400)
canvas.pack()

label = tk.Label(root, text='set amout of cars')
label.pack()

entry = tk.Entry(root)
entry.pack()

button = tk.Button(root, text='start', command=restart)
button.pack()

button2 = tk.Button(root, text='forward', command=race)
button2.pack()

root.mainloop()

enter image description here

  • Related