This question already has answers here:
Using global variables in a function
(25 answers)
Closed 1 year ago.
I have been programming a python snake game using tkinter canvas and have been running into this error whilst trying to change the tickspeed for every apple eaten. Would be much appreciated if anyone could help as I am quite new to using tkinter and python in general.
File "c:\Users\Admin\Documents\pythonsnake.py", line 45, in main
root.after(Tickspeed, main)
UnboundLocalError: local variable 'Tickspeed' referenced before assignment
This is my code:
#Python Snake Game
from tkinter import Tk, Canvas
import random
import time
# Globals
WIDTH = 800
HEIGHT = 600
SEG_SIZE = 20
IN_GAME = True
Tickspeed = 100
# Helper functions
def create_block():
""" Creates an apple to be eaten """
global BLOCK
posx = SEG_SIZE * random.randint(1, (WIDTH-SEG_SIZE) / SEG_SIZE)
posy = SEG_SIZE * random.randint(1, (HEIGHT-SEG_SIZE) / SEG_SIZE)
BLOCK = c.create_oval(posx, posy,
posx+SEG_SIZE, posy+SEG_SIZE,
fill="red")
def main():
""" Handles game process """
global IN_GAME
if IN_GAME:
s.move()
head_coords = c.coords(s.segments[-1].instance)
x1, y1, x2, y2 = head_coords
# Check for collision with gamefield edges
if x2 > WIDTH or x1 < 0 or y1 < 0 or y2 > HEIGHT:
IN_GAME = False
# Eating apples
elif head_coords == c.coords(BLOCK):
s.add_segment()
c.delete(BLOCK)
if(Tickspeed>20):
Tickspeed = Tickspeed - 5
create_block()
# Self-eating
else:
for index in range(len(s.segments)-1):
if head_coords == c.coords(s.segments[index].instance):
IN_GAME = False
root.after(Tickspeed, main)
# Not IN_GAME -> stop game and print message
else:
set_state(restart_text, 'normal')
set_state(game_over_text, 'normal')
class Segment(object):
""" Single snake segment """
def __init__(self, x, y):
self.instance = c.create_rectangle(x, y,
x+SEG_SIZE, y+SEG_SIZE,
fill="white")
class Snake(object):
""" Simple Snake class convertable """
def __init__(self, segments):
self.segments = segments
# possible moves
self.mapping = {"Down": (0, 1), "Right": (1, 0),
"Up": (0, -1), "Left": (-1, 0)}
# initial movement direction
self.vector = self.mapping["Right"]
def move(self):
""" Moves the snake with the specified vector"""
for index in range(len(self.segments)-1):
segment = self.segments[index].instance
x1, y1, x2, y2 = c.coords(self.segments[index+1].instance)
c.coords(segment, x1, y1, x2, y2)
x1, y1, x2, y2 = c.coords(self.segments[-2].instance)
c.coords(self.segments[-1].instance,
x1+self.vector[0]*SEG_SIZE, y1+self.vector[1]*SEG_SIZE,
x2+self.vector[0]*SEG_SIZE, y2+self.vector[1]*SEG_SIZE)
def add_segment(self):
""" Adds segment to the snake """
last_seg = c.coords(self.segments[0].instance)
x = last_seg[2] - SEG_SIZE
y = last_seg[3] - SEG_SIZE
self.segments.insert(0, Segment(x, y))
def change_direction(self, event):
""" Changes direction of snake """
if event.keysym in self.mapping:
self.vector = self.mapping[event.keysym]
def reset_snake(self):
for segment in self.segments:
c.delete(segment.instance)
def set_state(item, state):
c.itemconfigure(item, state=state)
def clicked(event):
global IN_GAME
s.reset_snake()
IN_GAME = True
c.delete(BLOCK)
c.itemconfigure(restart_text, state='hidden')
c.itemconfigure(game_over_text, state='hidden')
start_game()
def start_game():
global s
create_block()
s = create_snake()
# Reaction on keypress
c.bind("<KeyPress>", s.change_direction)
main()
def create_snake():
# creating segments and snake
segments = [Segment(SEG_SIZE, SEG_SIZE),
Segment(SEG_SIZE*2, SEG_SIZE),
Segment(SEG_SIZE*3, SEG_SIZE)]
return Snake(segments)
# Setting up window cause fun yeah
root = Tk()
root.title("Python Snake Game By Amiel, Amitoj and Abdullah")
c = Canvas(root, width=WIDTH, height=HEIGHT, bg="#003344")
c.grid()
# catch keypressing
c.focus_set()
game_over_text = c.create_text(WIDTH/2, HEIGHT/2, text="GAME OVER!",
font='Calibi 30', fill='red',
state='hidden')
restart_text = c.create_text(WIDTH/2, HEIGHT-HEIGHT/3,
font='Arial 30',
fill='Black',
text=" Click here to restart" + '\n Made by Amiel & Amitoj & Abdullah',
state='hidden')
c.tag_bind(restart_text, "<Button-1>", clicked)
start_game()
root.mainloop()
Here is the fixed code my slime, The print(Tickspeed) is only for ease of dev - Tojinio:
from tkinter import Tk, Canvas
import random
# Globals
WIDTH = 800
HEIGHT = 600
SEG_SIZE = 20
IN_GAME = True
Tickspeed = float(input('Tickspeed: '))
# Helper functions
def create_block():
""" Creates an apple to be eaten """
global BLOCK
posx = SEG_SIZE * random.randint(1, (WIDTH-SEG_SIZE) / SEG_SIZE)
posy = SEG_SIZE * random.randint(1, (HEIGHT-SEG_SIZE) / SEG_SIZE)
BLOCK = c.create_oval(posx, posy,
posx+SEG_SIZE, posy+SEG_SIZE,
fill="red")
def main():
""" Handles game process """
global IN_GAME
global Tickspeed
if IN_GAME:
s.move()
head_coords = c.coords(s.segments[-1].instance)
x1, y1, x2, y2 = head_coords
# Check for collision with gamefield edges
if x2 > WIDTH or x1 < 0 or y1 < 0 or y2 > HEIGHT:
IN_GAME = False
# Eating apples
elif head_coords == c.coords(BLOCK):
s.add_segment()
c.delete(BLOCK)
float(Tickspeed)
# Ramping
if(Tickspeed > 20):
Tickspeed -= 5
Tickspeed1 = Tickspeed
str(Tickspeed1)
print('Your Tickspeed Is: ' + Tickspeed)
create_block()
# Self-eating
else:
for index in range(len(s.segments)-1):
if head_coords == c.coords(s.segments[index].instance):
IN_GAME = False
root.after(100, main)
# Not IN_GAME -> stop game and print message
else:
set_state(restart_text, 'normal')
set_state(game_over_text, 'normal')
class Segment(object):
""" Single snake segment """
def __init__(self, x, y):
self.instance = c.create_rectangle(x, y,
x+SEG_SIZE, y+SEG_SIZE,
fill="white")
class Snake(object):
""" Simple Snake class """
def __init__(self, segments):
self.segments = segments
# possible moves
self.mapping = {"Down": (0, 1), "Right": (1, 0),
"Up": (0, -1), "Left": (-1, 0)}
# initial movement direction
self.vector = self.mapping["Right"]
def move(self):
""" Moves the snake with the specified vector"""
for index in range(len(self.segments)-1):
segment = self.segments[index].instance
x1, y1, x2, y2 = c.coords(self.segments[index+1].instance)
c.coords(segment, x1, y1, x2, y2)
x1, y1, x2, y2 = c.coords(self.segments[-2].instance)
c.coords(self.segments[-1].instance,
x1+self.vector[0]*SEG_SIZE, y1+self.vector[1]*SEG_SIZE,
x2+self.vector[0]*SEG_SIZE, y2+self.vector[1]*SEG_SIZE)
def add_segment(self):
""" Adds segment to the snake """
last_seg = c.coords(self.segments[0].instance)
x = last_seg[2] - SEG_SIZE
y = last_seg[3] - SEG_SIZE
self.segments.insert(0, Segment(x, y))
def change_direction(self, event):
""" Changes direction of snake """
if event.keysym in self.mapping:
self.vector = self.mapping[event.keysym]
def reset_snake(self):
for segment in self.segments:
c.delete(segment.instance)
def set_state(item, state):
c.itemconfigure(item, state=state)
def clicked(event):
global IN_GAME
s.reset_snake()
IN_GAME = True
c.delete(BLOCK)
c.itemconfigure(restart_text, state='hidden')
c.itemconfigure(game_over_text, state='hidden')
start_game()
def start_game():
global Tickspeed
global s
Tickspeed = 100
create_block()
s = create_snake()
# Reaction on keypress
c.bind("<KeyPress>", s.change_direction)
main()
def create_snake():
# creating segments and snake
segments = [Segment(SEG_SIZE, SEG_SIZE),
Segment(SEG_SIZE*2, SEG_SIZE),
Segment(SEG_SIZE*3, SEG_SIZE)]
return Snake(segments)
# Setting up window
root = Tk()
root.title("py snakeĀ© by Amitoj, Amiel and Abdullah")
c = Canvas(root, width=WIDTH, height=HEIGHT, bg="#003344")
c.grid()
# catch keypressing
c.focus_set()
game_over_text = c.create_text(WIDTH/2, HEIGHT/2, text="GAME OVER!",
font='Arial 30', fill='red',
state='hidden')
restart_text = c.create_text(WIDTH/2, HEIGHT-HEIGHT/3,
font='Arial 30',
fill='black',
text=" Click here to restart" + '\n Made by Amitoj, Amiel ' + '\n and Abdullah',
state='hidden')
c.tag_bind(restart_text, "<Button-1>", clicked)
start_game()
root.mainloop()
Related
import time
from tkinter import *
import random
class SpaceField:
def __init__(self):
self.window = Tk()
self.window.title("Asteriods")
self.canvas = self.canvas_display() #creates canvas
self.asteriods = self.asteriod_creation_seperation() #creates asteroids
self.active = True
self.move_active() #Moves asteroids
self.canvas.update()
def asteriod_creation_seperation(self): #creation of multple asteriods
asteriod_spacingx = random.randint(1,800)
asteriod_spacingy = random.randint(1,800)
asteriod_list = list() # could list([])
for i in range(15):
asteriod = self.canvas.create_oval( 30, 50 , 80 , 100 , tags="asteriod", width=2, outline="white")
asteriod_list.append("asteriod")
self.canvas.move(asteriod, asteriod_spacingx, asteriod_spacingy)
asteriod_spacingx = random.randint(1,500)
asteriod_spacingy = random.randint(1,500)
print(asteriod_spacingy)
return asteriod_list
Asteroid Creation. Creates asteroids and gives them random positions.
def asteriod_update(self): #asteriods movement method #MAin problem
x12 = 1
self.canvas.move("asteriod", 3, x12)
pos = self.canvas.coords("asteriod")
print(pos)
if (pos)[2] > 500:
x12 *= 5
I think this is where I need to add the collision detection. I just have no idea how to combine the lists of the circles and the collisions.
def move_active(self): #Basically a true loop
if self.active:
self.asteriod_update()
self.window.after(40, self.move_active)
def canvas_display(self): #canvas
canvas = Canvas(self.window, width=500, height=400, background='black')
canvas.pack(expand=True, fill="both")
canvas.update()
return canvas
Canvas display nothing special
def run(self):
self.window.mainloop()
if __name__ == '__main__':
SpaceF = SpaceField()
SpaceF.run()
Asteroids is a classic game but there were a number of problems in your code. The main one was calling move_active during initialization. This prevented the code from completing its mainloop initialization.
The other problem was the asteroid_update method that basically didn't do anything, also using tags to control all asteroids didn't work either.
Everything else was OK, although you might consider using polygons.
Here is one way to produce a bouncing objects program. I've inserted remarks that describe the methods used.
Objects change the speed and direction when they hit the boundary so their trajectories are randomized.
from tkinter import *
from random import randint as rnd
class SpaceField:
def __init__(self):
self.window = Tk()
self.window.title("Asteriods")
# Define canvas size and active flag
self.wide, self.high, self.active = 500, 400, True
self.canvas_display()
self.asteriod_creation_seperation()
def asteriod_creation_seperation(self):
self.asteroids, self.speed = [], []
size, radius = 50, 25
for i in range(15):
spacex = rnd(size, self.wide - size)
spacey = rnd(size, self.high - size)
self.asteroids.append( # Store oval item id
self.canvas.create_oval(
spacex, spacey, spacex+size, spacey+size,
width=2, tags = "asteriod", outline = "white"))
self.speed.append((rnd(1,4),rnd(1,4))) # Store random speed x, y
def asteriod_update(self): # MAIN DRIVER: Work on ALL asteroids
for i, a in enumerate(self.asteroids):
xx, yy = self.speed[i] # get speed data
x, y, w, h = self.canvas.coords(a)
# check for boundary hit then change direction and speed
if x < 0 or w > self.wide:
xx = -xx * rnd(1, 4)
if y < 0 or h > self.high:
yy = -yy * rnd(1, 4)
# Limit max and min speed then store it
self.speed[i] = (max( -4, min( xx, 4)), max( -4, min( yy, 4 )))
self.canvas.move(a, xx, yy) # update asteroid position
def move_active(self):
if self.active:
self.asteriod_update()
self.window.after(40, self.move_active)
def canvas_display(self):
self.canvas = Canvas(
self.window, width = self.wide,
height = self.high, background = "black")
self.canvas.pack(expand = True, fill = "both")
def run(self): # Begin asteroids here so that mainloop is executed
self.window.after(200, self.move_active)
self.window.mainloop()
if __name__ == "__main__":
SpaceF = SpaceField()
SpaceF.run()
I'm making a basic game. I want the ball to bounce back up ONLY when it hits the platform. So far, I've written code that will make the ball bounce off the top and bottom screen, but I'm having trouble with getting the ball to bounce off the platform.
from tkinter import *
import time
import tkinter
tk = Tk()
canvas = Canvas(tk, bg="white",width=(900),height=(500))
canvas.pack()
platform = canvas.create_rectangle(400,400,500,410)
def ball():
xspeed = 2
yspeed = 2
ball = canvas.create_oval(430,10,470,50)
while True:
canvas.move(ball, xspeed, yspeed)
pos = canvas.coords(ball)
if pos[2] >=900 or pos[0] <0:
xspeed = -xspeed
tk.update()
time.sleep(0.01)
def board():
board_right()
board_left()
def board_right(event):
xspeed = 5
yspeed = 0
canvas.move(platform,xspeed,yspeed)
tk.update
time.sleep(0.01)
def board_left(event):
xspeed = 5
yspeed = 0
canvas.move(platform,-xspeed,yspeed)
tk.update()
time.sleep(0.01)
canvas.bind_all("<Right>",board_right)
canvas.bind_all("<Left>",board_left)
ball()
tk.mainloop()
Do not use time.sleep() as it will block the tkinter mainloop, use after() instead.
To check whether the ball hits the platform, you need to get the center x of the ball and the lower y of the ball. If center x is within the left and right of platform and the ball lower y is the platform upper y, then reverse the ball y speed. Otherwise game over!
Below is sample code based on yours:
import tkinter as tk
root = tk.Tk()
width = 900
height = 500
canvas = tk.Canvas(root, bg='white', width=width, height=height)
canvas.pack()
ball = canvas.create_oval(430, 10, 470, 50, fill='green')
platform_y = height - 20
platform = canvas.create_rectangle(width//2-50, platform_y, width//2+50, platform_y+10, fill='black')
# ball moving speed
xspeed = yspeed = 2
def move_ball():
global xspeed, yspeed
x1, y1, x2, y2 = canvas.coords(ball)
if x1 <= 0 or x2 >= width:
# hit wall, reverse x speed
xspeed = -xspeed
if y1 <= 0:
# hit top wall
yspeed = 2
elif y2 >= platform_y:
# calculate center x of the ball
cx = (x1 + x2) // 2
# check whether platform is hit
px1, _, px2, _ = canvas.coords(platform)
if px1 <= cx <= px2:
yspeed = -2
else:
canvas.create_text(width//2, height//2, text='Game Over', font=('Arial Bold', 32), fill='red')
return
canvas.move(ball, xspeed, yspeed)
canvas.after(20, move_ball)
def board_right(event):
x1, y1, x2, y2 = canvas.coords(platform)
# make sure the platform is not moved beyond right wall
if x2 < width:
dx = min(width-x2, 10)
canvas.move(platform, dx, 0)
def board_left(event):
x1, y1, x2, y2 = canvas.coords(platform)
# make sure the platform is not moved beyond left wall
if x1 > 0:
dx = min(x1, 10)
canvas.move(platform, -dx, 0)
canvas.bind_all('<Right>', board_right)
canvas.bind_all('<Left>', board_left)
move_ball()
root.mainloop()
New to programming. Working on a simple pong clone. Started the ball but want to make sure all sides of the window (500x500) will have the ball bounce off of it. How could I do this? Thanks!
P.S. This is my current code if needed.
import threading
import random
import time
import string
import os.path
from random import randint
from tkinter import *
class Pong:
Title = 'Pong'
Size = '500x500'
class Ball:
def __init__(self,canvas,x1,y1,x2,y2):
self.x1 =x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
self.canvas = canvas
self.ball = canvas.create_oval(self.x1, self.y1, self.x2, self.y2, fill="black")
def move_ball(self):
deltax = randint(0,5)
deltay = randint(0,5)
self.canvas.move(self.ball,deltax,deltay)
self.canvas.after(50,self.move_ball)
def PongGame():
print("Moved to PongGame.")
ball1 = Ball(canvas,10,10,30,30)
ball1.move_ball()
def titleButtonClicked(event):
print("Title screen button clicked.")
btn.pack_forget()
btn.place(x=600,y=600)
msg.pack_forget()
PongGame()
root = Tk()
root.geometry(Pong.Size)
root.title(Pong.Title)
root.resizable(False,False)
msg = Label(root, text = Pong.Title, font = ("", 50))
msg.pack()
canvas = Canvas(root, width = 500, height = 500)
canvas.pack()
btn=Button(root, text = "Start")
btn.bind('<Button-1>', titleButtonClicked)
btn.place(x=220,y=300)
root.mainloop()
Collisions are not trivial; the simplest is to reverse the x or the y velocity after checking which edge of the bounding box of the ball intersects with the boundaries of the canvas.
Maybe something like this:
import random
import tkinter as tk
WIDTH, HEIGHT = 500, 500
class Ball:
radius = 10
spawn_center = (250, 100)
def __init__(self, canvas):
self.canvas = canvas
self.id = None
self.create_ball()
self.velocity = None
self.assign_random_velocity()
self.keep_moving = True
self.move()
def create_ball(self):
xc, yc = self.spawn_center
x0, y0, = xc - self.radius, yc + self.radius
x1, y1, = xc + self.radius, yc - self.radius
self.id = self.canvas.create_oval(x0, y0, x1, y1)
def assign_random_velocity(self):
dx = random.randrange(1, 5) * random.choice((1, -1))
dy = random.randrange(1, 5) * random.choice((1, -1))
self.velocity = (dx, dy)
def move(self):
if self.keep_moving is None:
return
self.check_collision()
self.canvas.move(self.id, *self.velocity)
self.keep_moving = self.canvas.after(10, self.move)
def cancel_move(self):
if self.keep_moving is not None:
self.canvas.after_cancel(self.keep_moving)
self.keep_moving = None
def check_collision(self):
x0, y0, x1, y1 = self.canvas.coords(self.id)
dx, dy = self.velocity
if x0 < 0:
x0 = 0
dx = -dx
elif x1 > WIDTH:
x1 = WIDTH
dx = -dx
if y0 < 0:
y0 = 0
dy = -dy
elif y1 > HEIGHT:
y1 = HEIGHT
dy = -dy
self.velocity = dx, dy
class PongBoard(tk.Canvas):
def __init__(self, master):
self.master = master
super().__init__(self.master)
self.ball = None
self.spawn_new_ball()
def spawn_new_ball(self):
if self.ball is not None:
self.ball.cancel_move()
self.delete(self.ball.id)
self.ball = Ball(self)
root = Tk()
root.geometry(f'{WIDTH}x{HEIGHT+20}')
board = PongBoard(root)
new_ball_btn = tk.Button(root, text='spawn new ball', command=board.spawn_new_ball)
board.pack(expand=True, fill=tk.BOTH)
new_ball_btn.pack()
root.mainloop()
This will get you started, but you will have to implement the paddles, the paddles movement, the collision checking of the ball with the paddles, and keep the score by yourself.
created this game called snake.I was wondering if anyone can help me create a window before the game opens, which contains the start button, exit button and instructions manual so that when i click start, the game starts and when I click exit, the game is terminated. I would also like a try again button that loops the game when the player loses the game, and a quit button which terminates the program. Here is the code for my snake game
from tkinter import*
import random
#Globals
WIDTH = 800
HEIGHT = 600
SEG_SIZE = 20
IN_GAME = True
#Helper Functions
def create_block():
""" Creates an apple to be eaten """
global BLOCK
posx = SEG_SIZE * random.randint(1, (WIDTH-SEG_SIZE) / SEG_SIZE)
posy = SEG_SIZE * random.randint(1, (HEIGHT-SEG_SIZE) / SEG_SIZE)
BLOCK = c.create_oval(posx, posy,
posx+SEG_SIZE, posy+SEG_SIZE,
fill="blue")
def main():
""" Handles game process """
global IN_GAME
if IN_GAME:
s.move()
head_coords = c.coords(s.segments[-1].instance)
x1, y1, x2, y2 = head_coords
#Collision with borders
if x2 > WIDTH or x1 < 0 or y1 < 0 or y2 > HEIGHT:
IN_GAME = False
#Eating apples
elif head_coords == c.coords(BLOCK):
s.add_segment()
c.delete(BLOCK)
create_block()
#Self-eating
else:
for index in range(len(s.segments)-1):
if head_coords == c.coords(s.segments[index].instance):
IN_GAME = False
root.after(100, main)
# NOT IN_GAME -> stop game and print message
else:
c.create_text(WIDTH/2, HEIGHT/2,
text="GAME OVER!",
font="Arial 40",
fill="blue")
class Segment(object):
""" Single snake segment """
def __init__(self, x, y):
self.instance = c.create_rectangle(x, y,
x+SEG_SIZE, y+SEG_SIZE,
fill="black")
class Snake(object):
""" Simple Snake class """
def __init__(self, segments):
self.segments = segments
#possible moves
self.mapping = {"Down": (0, 1), "Right": (1, 0),
"Up": (0, -1), "Left": (-1, 0)}
#initial movement direction
self.vector = self.mapping["Right"]
def move(self):
""" Moves the snake with the specified vector """
for index in range(len(self.segments)-1):
segment = self.segments[index].instance
x1, y1, x2, y2 = c.coords(self.segments[index+1].instance)
c.coords(segment, x1, y1, x2, y2)
x1, y1, x2, y2 = c.coords(self.segments[-2].instance)
c.coords(self.segments[-1].instance,
x1+self.vector[0]*SEG_SIZE, y1+self.vector[1]*SEG_SIZE,
x2+self.vector[0]*SEG_SIZE, y2+self.vector[1]*SEG_SIZE)
def add_segment(self):
""" Adds segment to the snake """
last_seg = c.coords(self.segments[0].instance)
x = last_seg[2] - SEG_SIZE
y = last_seg[3] - SEG_SIZE
self.segments.insert(0, Segment(x, y))
def change_direction(self, event):
""" Changes direction of snake """
if event.keysym in self.mapping:
self.vector = self.mapping[event.keysym]
#Setting up window
root = Tk()
root.title("Snake")
c = Canvas(root, width=WIDTH, height=HEIGHT)
c.grid()
# catch keypressing
c.focus_set()
#creating segments and snake
segments = [Segment(SEG_SIZE, SEG_SIZE),
Segment(SEG_SIZE*2, SEG_SIZE),
Segment(SEG_SIZE*3, SEG_SIZE)]
s = Snake(segments)
#Reaction when key is pressed
c.bind("<KeyPress>", s.change_direction)
#Quitting the game
create_block()
main()
root.mainloop()
I have constructed a lattice of particles with tkinter and now I would like each particle in the lattice to move according to a list of x and y coordinates that I read into an array from two text files. I have tried to create a class with a function inside that defines movement with the canvas.move function but I get the error TclError: wrong # coordinates: expected 0 or 4, got 400. How to get around this?
from Tkinter import *
import random
import time
import csv
tk = Tk()
N = 100
T = 500
canvas = Canvas(tk, width=100, height=100)
tk.title("Test")
canvas.pack()
n = 5
t = 10
step1 = []
step2 = []
textFile1 = open('/Users/francislempp/Desktop/major project/C++ programs/Molecular Dynamics 2D/Molecular_Dynamics_2D-gupnvjunowwmjcfiyoursdhzytow/Build/Products/Debug/motionX', 'r')
lines = textFile1.readlines()
for line in lines:
step1.append(line.split(" "))
textFile2 = open('/Users/francislempp/Desktop/major project/C++ programs/Molecular Dynamics 2D/Molecular_Dynamics_2D-gupnvjunowwmjcfiyoursdhzytow/Build/Products/Debug/motionY', 'r')
lines = textFile2.readlines()
for line in lines:
step2.append(line.split(" "))
def moves(xspeed, yspeed):
canvas.move(xspeed, yspeed)
class Ball:
def __init__(self, x, y, color):
self.x = x
self.y = y
self.shape = canvas.create_oval((x,y,x,y), fill = color)
def move(self):
canvas.move(self.shape, self.x, self.y)
pos = canvas.coords(self.shape)
if pos[3] >= 100 or pos[1] <= 0:
self.y = -self.y
if pos[2] > 100 or pos[0] <= 0:
self.x = -self.x
def delete(self):
canvas.delete(self.shape)
balls = []
for x in range(4,100,10):
for y in range(4,100,10):
#canvas.create_oval((x,y,x,y), fill='red')
Ball(x,y,"red")
tk.update()
for i in step1:
for j in step2:
Ball(i,j,"red")
Ball.move()
tk.update()
tk.mainloop()
You have to save items on list and use this list to move
I copy example from previous question
import tkinter as tk
import random
# --- functions ---
def move():
for point_id in points:
x = random.randint(-1, 1)
y = random.randint(-1, 1)
canvas.move(point_id, x, y)
root.after(100, move)
# --- main ---
points = []
root = tk.Tk()
canvas = tk.Canvas(root, width=100, height=100)
canvas.pack()
for x in range(4, 100, 10):
for y in range(4, 100, 10):
point_id = canvas.create_oval(x, y, x, y, fill="red")
points.append(point_id)
move()
root.mainloop()
EDIT: with your class but without data from file.
I use random instead of data from files to show how to create particles and move them.
Every ball moves with own speed/direction which change when touch border.
import tkinter as tk
import random
# --- classes ---
class Ball:
def __init__(self, x, y, speed_x, speed_y, color):
self.speed_x = speed_x
self.speed_y = speed_y
self.shape = canvas.create_oval((x, y, x, y), fill=color)
def move(self):
canvas.move(self.shape, self.speed_x, self.speed_y)
pos = canvas.coords(self.shape)
# change speed/direction when touch border
if pos[3] >= 100 or pos[1] <= 0:
self.speed_y = -self.speed_y
if pos[2] > 100 or pos[0] <= 0:
self.speed_x = -self.speed_x
def delete(self):
canvas.delete(self.shape)
# --- functions ---
def move():
for ball in all_balls:
ball.move()
root.after(100, move)
# --- main ---
root = tk.Tk()
canvas = tk.Canvas(root, width=100, height=100)
canvas.pack()
all_balls = []
for x in range(4, 100, 10):
for y in range(4, 100, 10):
offset_x = random.randint(-2, 2)
offset_y = random.randint(-2, 2)
all_balls.append(Ball(x, y, offset_x, offset_y, "red"))
move()
root.mainloop()