Pokemon_SL
Pokemon_SL

Reputation: 327

How to get multiple ovals moving around the canvas?

My question is how do I get multiple "bubbles" moving around the screen with random numbers?

Would I have to do heaps of def bubble(): or is there a simpler way to do it? Also Moving the "bubbles" randomly across the canvas baffles me.

Coding so far:

from tkinter import *
import random

def quit():
    root.destroy()


def bubble():
    xval = random.randint(5,765)
    yval = random.randint(5,615)
    canvas.create_oval(xval,yval,xval+30,yval+30, fill="#00ffff",outline="#00bfff",width=5)
    canvas.create_text(xval+15,yval+15,text=number)
    canvas.update()

def main():
    global root
    global tkinter
    global canvas
    root = Tk()
    root.title("Math Bubbles")
    Button(root, text="Quit", width=8, command=quit).pack()
    Button(root, text="Start", width=8, command=bubble).pack()
    canvas = Canvas(root, width=800, height=650, bg = '#afeeee')
    canvas.pack()
    root.mainloop()

# Create a sequence of numbers to choose from. CAPS denotes a constant variable
NUMBERS = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)

# Pick numbers randomly from the sequence with the help of a random.choice function
number = random.choice(NUMBERS)

# Create a variable to use later to see if the guess is correct
correct = number

main()

Upvotes: 1

Views: 838

Answers (1)

tobias_k
tobias_k

Reputation: 82949

This should get you going:

import Tkinter, random

class BubbleFrame:

    def __init__(self, root):
        root.title("Math Bubbles")
        Tkinter.Button(root, text="Add Bubbles", width=8, command=self.bubble).pack()
        Tkinter.Button(root, text="Quit", width=8, command=quit).pack()
        self.canvas = Tkinter.Canvas(root, width=800, height=650, bg = '#afeeee')
        self.canvas.pack()
        self.bubbles = {} # this will hold bubbles ids, positions and velocities

    def bubble(self):
        # add bubbles for numbers from 1 to 20
        for number in range(1, 20+1):
            xval = random.randint(5,765)
            yval = random.randint(5,615)
            s1 = self.canvas.create_oval(xval,yval,xval+30,yval+30, fill="#00ffff",outline="#00bfff",width=5)
            s2 = self.canvas.create_text(xval+15,yval+15, text=number)
            self.bubbles[(s1, s2)] = (xval, yval, 0, 0) # add bubbles to dictionary

    def loop(self, root):
        for (s1, s2), (x, y, dx, dy) in self.bubbles.items():
            # update velocities and positions
            dx += random.randint(-1, 1)
            dy += random.randint(-1, 1)
            # dx and dy should not be too large
            dx, dy = max(-5, min(dx, 5)), max(-5, min(dy, 5))
            # bounce off walls
            if not 0 < x < 770: dx = -dx
            if not 0 < y < 620: dy = -dy
            # apply new velocities
            self.canvas.move(s1, dx, dy)
            self.canvas.move(s2, dx, dy)
            self.bubbles[(s1, s2)] = (x + dx, y + dy, dx, dy)
        # have mainloop repeat this after 100 ms
        root.after(100, self.loop, root)

if __name__ == "__main__":
    root = Tkinter.Tk()
    frame = BubbleFrame(root)
    frame.loop(root)
    root.mainloop()

Note that I've restructured the code a bit, using a class for wrapping those methods and attributes, but that's entirely up to you. Also note, that I've done this with Python 2.7, so there may be some small adaptions to make, e.g., the name of the Tkinter package.

You do not need to define another bubble function for each bubble to add -- in fact your code already adds many bubbles to the canvas, so this part is fine. The tricky bit is moving the bubbles around.

For this I've first added the self.bubbles dictionary, mapping the IDs of the bubbles and their labels (returned by the canvas.create... methods) to their current positions and velocities. Finally, the loop method updates the positions and velocities of the bubbles and redraws the canvas. At the end, this method will schedule it's next execution using the after method.

Upvotes: 1

Related Questions