Reputation: 57
I'm having trouble getting these two objects to move on my canvas. Once one shot is fired it stops the movement of the other object. I'm pretty sure it's because I'm using two while loops and python can't handle that. Is there any way to get around that/ include it in the same loop?
Ive tried using the self.canvas.after () command, but every time i shoot the bullet it goes faster than the time before.
from tkinter import *
import time
class Game:
def __init__(self):
#creating the static canvas background
window = Tk()
window.title('Shoot your friends')
self.canvas = Canvas(width= 900,
height= 900,
cursor= 'circle')
self.canvas.pack()
self.canvas.create_line(450, 900,
450, 0,
dash = (10))
self.p1_ship = PhotoImage(file = "red_ship.gif")
self.p2_ship = PhotoImage(file = "blue_ship.gif")
self.p1_laser = PhotoImage(file = "red_laser.gif")
self.p2_laser = PhotoImage(file = "blue_laser.gif")
#Buttons at the bottom
frame = Frame(window)
frame.pack()
#Determining the state of edge teleporting and toggling it
self.etb = True
def et():
if self.etb == True:
self.etb = False
Et["text"] = "Turn On Edge Teleporting"
else:
self.etb = True
Et["text"] = "Turn Off Edge Teleporting"
print ("Edge Telepoting Toggled")
Et = Button(frame, text="Turn Off Edge Teleporting", command = et, cursor= 'double_arrow')
Et.grid(row=0,column=0)
self.Rfb = False
def rf():
if self.Rfb == True:
self.Rfb = False
Rf["text"] = "Turn On Rapid Fire "
else:
self.Rfb = True
Rf["text"] = "Turn Off Rapid Fire"
print ("Rapid Fire Toggled")
Rf = Button(frame, text="Turn On Rapid Fire", command = rf, cursor= 'cross')
Rf.grid(row=0,column=1)
def restart():
print ('restart')
restart_b = Button(frame, text="Restart Game", command = restart, fg='Blue', bg= 'red', cursor='exchange' )
restart_b.grid(row=0,column=2)
self.y_p1 = 400
self.y_p2 = 400
self.ship_p1 = self.canvas.create_image(40, 450, image=self.p1_ship)
self.ship_p2 = self.canvas.create_image(860, 450, image=self.p2_ship)
self.canvas.move(self.ship_p1,0,0)
self.canvas.move(self.ship_p2,0,0)
#For example If edge teleporting is ON the ship will teleport to the top of the screen if it is at the bottom and the down key is pressed and vice versa
#My implementation of this may not be the most efficient but I like the options it gives me for adding future features and it looks cool.
def p1_up(event):
if self.etb == True and self.y_p1 >= 100:
self.canvas.move(self.ship_p1,0,-100)
self.y_p1 += -100
elif self.etb == True:
self.canvas.move(self.ship_p1,0,+800)
self.y_p1 += +800
elif self.y_p1 >= 100:
self.canvas.move(self.ship_p1,0,-100)
self.y_p1 += -100
def p1_down(event):
if self.etb == True and self.y_p1 <= 799:
self.canvas.move(self.ship_p1,0,+100)
self.y_p1 += 100
elif self.etb == True:
self.canvas.move(self.ship_p1,0,-800)
self.y_p1 += -800
elif self.y_p1 <= 799:
self.canvas.move(self.ship_p1,0,+100)
self.y_p1 += 100
def p2_up(event):
if self.etb == True and self.y_p2 >= 100:
self.canvas.move(self.ship_p2,0,-100)
self.y_p2 += -100
elif self.etb == True:
self.canvas.move(self.ship_p2,0,+800)
self.y_p2 += +800
elif self.y_p2 >= 100:
self.canvas.move(self.ship_p2,0,-100)
self.y_p2 += -100
def p2_down(event):
if self.etb == True and self.y_p2 <= 799:
self.canvas.move(self.ship_p2,0,+100)
self.y_p2 += 100
elif self.etb == True:
self.canvas.move(self.ship_p2,0,-800)
self.y_p2 += -800
elif self.y_p2 <= 799:
self.canvas.move(self.ship_p2,0,+100)
self.y_p2 += 100
# Functions for shooting
#self.canvas.move(self.shot_p1,0,0)
#self.laser_p1 = self.canvas.create_image(50, self.y_p1 +50, image=self.p1_laser)
#self.laser_p2 = self.canvas.create_image(850, self.y_p2 +50, image=self.p2_laser)
self.p1_shot_out = False
self.p2_shot_out = False
def p1_shoot(event):
if self.p1_shot_out == True:
self.canvas.delete(self.laser_p1)
#draws the laser
self.laser_p1 = self.canvas.create_image(50, self.y_p1 +50, image=self.p1_laser)
self.x_p1_laser = 50
self.p1_shot_out = True
time.sleep(.009)
p1_shoot_move()
def p1_shoot_move():
#moves the laser until its outside the canvas
while self.x_p1_laser <= 900:
self.canvas.move(self.laser_p1,5,0)
self.x_p1_laser += 5
self.canvas.update()
time.sleep(.009)
def p2_shoot(event):
if self.p2_shot_out == True:
self.canvas.delete(self.laser_p2)
#draws the laser
self.laser_p2 = self.canvas.create_image(750, self.y_p2 +50, image=self.p2_laser)
self.x_p2_laser = 750
self.p2_shot_out = True
time.sleep(.009)
p2_shoot_move()
def p2_shoot_move():
#moves the laser until its outside the canvas
while self.x_p2_laser >= -100:
self.canvas.move(self.laser_p2,-5,0)
self.x_p2_laser += -5
self.canvas.update()
time.sleep(.009)
# Key bindings that trigger their respective functions
self.canvas.bind('w', p1_up)
self.canvas.bind('s', p1_down)
self.canvas.bind('<Up>', p2_up)
self.canvas.bind('<Down>', p2_down)
self.canvas.bind('<space>', p1_shoot)
self.canvas.bind('<Control_R>', p2_shoot)
self.canvas.focus_set()
# this mainloop thing is some sort of witchcraft! OH MY!!!
window.mainloop()
Game()
Any help is appreciated, Thanks!
Upvotes: 1
Views: 740
Reputation: 1269
You are correct, it is due to having 2 while
loops going at the same time, it causes one 'laser'/while
loop to stop until the other 'laser'/while
loop is finished, to solve this you could go into threading
etc., but as you mentioned there is the window.after()
method, which will perform the task sufficiently, then we can use an if/else
test rather than while
loops.
Here is you whole code, with some improvements, I made the window
and canvas
global, and got rid of time.sleep()
instead using self.window.after(1, function...)
and used if/else
rather than while
. It shoots rather slowly still, but you will be able to fix this no doubt :), if not I could help.
from tkinter import *
class Game:
def __init__(self):
#creating the static canvas background
self.window = Tk()
self.window.title('Shoot your friends')
self.canvas = Canvas(width= 900,
height= 700,
cursor= 'circle')
self.canvas.pack()
self.canvas.create_line(450, 900,
450, 0,
dash = (10))
self.p1_ship = PhotoImage(file = "rd.gif")
self.p2_ship = PhotoImage(file = "rd.gif")
self.p1_laser = PhotoImage(file = "rd.gif")
self.p2_laser = PhotoImage(file = "rd.gif")
#Buttons at the bottom
self.frame = Frame(self.window)
self.frame.pack()
#Determining the state of edge teleporting and toggling it
self.etb = True
def et():
if self.etb == True:
self.etb = False
Et["text"] = "Turn On Edge Teleporting"
else:
self.etb = True
Et["text"] = "Turn Off Edge Teleporting"
print ("Edge Telepoting Toggled")
Et = Button(self.frame, text="Turn Off Edge Teleporting", command = et, cursor= 'double_arrow')
Et.grid(row=0,column=0)
self.Rfb = False
def rf():
if self.Rfb == True:
self.Rfb = False
Rf["text"] = "Turn On Rapid Fire "
else:
self.Rfb = True
Rf["text"] = "Turn Off Rapid Fire"
print ("Rapid Fire Toggled")
Rf = Button(self.frame, text="Turn On Rapid Fire", command = rf, cursor= 'cross')
Rf.grid(row=0,column=1)
def restart():
print ('restart')
restart_b = Button(self.frame, text="Restart Game", command = restart, fg='Blue', bg= 'red', cursor='exchange' )
restart_b.grid(row=0,column=2)
self.y_p1 = 400
self.y_p2 = 400
self.ship_p1 = self.canvas.create_image(40, 450, image=self.p1_ship)
self.ship_p2 = self.canvas.create_image(860, 450, image=self.p2_ship)
self.canvas.move(self.ship_p1,0,0)
self.canvas.move(self.ship_p2,0,0)
#For example If edge teleporting is ON the ship will teleport to the top of the screen if it is at the bottom and the down key is pressed and vice versa
#My implementation of this may not be the most efficient but I like the options it gives me for adding future features and it looks cool.
def p1_up(event):
if self.etb == True and self.y_p1 >= 100:
self.canvas.move(self.ship_p1,0,-100)
self.y_p1 += -100
elif self.etb == True:
self.canvas.move(self.ship_p1,0,+800)
self.y_p1 += +800
elif self.y_p1 >= 100:
self.canvas.move(self.ship_p1,0,-100)
self.y_p1 += -100
def p1_down(event):
if self.etb == True and self.y_p1 <= 799:
self.canvas.move(self.ship_p1,0,+100)
self.y_p1 += 100
elif self.etb == True:
self.canvas.move(self.ship_p1,0,-800)
self.y_p1 += -800
elif self.y_p1 <= 799:
self.canvas.move(self.ship_p1,0,+100)
self.y_p1 += 100
def p2_up(event):
if self.etb == True and self.y_p2 >= 100:
self.canvas.move(self.ship_p2,0,-100)
self.y_p2 += -100
elif self.etb == True:
self.canvas.move(self.ship_p2,0,+800)
self.y_p2 += +800
elif self.y_p2 >= 100:
self.canvas.move(self.ship_p2,0,-100)
self.y_p2 += -100
def p2_down(event):
if self.etb == True and self.y_p2 <= 799:
self.canvas.move(self.ship_p2,0,+100)
self.y_p2 += 100
elif self.etb == True:
self.canvas.move(self.ship_p2,0,-800)
self.y_p2 += -800
elif self.y_p2 <= 799:
self.canvas.move(self.ship_p2,0,+100)
self.y_p2 += 100
# Functions for shooting
self.p1_shot_out = False
self.p2_shot_out = False
def p1_shoot(event):
if self.p1_shot_out == True:
self.canvas.delete(self.laser_p1)
#draws the laser
self.laser_p1 = self.canvas.create_image(50, self.y_p1 +50, image=self.p1_laser)
self.x_p1_laser = 50
self.p1_shot_out = True
self.window.after(1, p1_shoot_move)
def p1_shoot_move():
#moves the laser until its outside the canvas
if self.x_p1_laser >= 930:
pass
else:
self.canvas.move(self.laser_p1,5,0)
self.x_p1_laser += 5
self.canvas.update()
self.window.after(1, p1_shoot_move)
def p2_shoot(event):
if self.p2_shot_out == True:
self.canvas.delete(self.laser_p2)
#draws the laser
self.laser_p2 = self.canvas.create_image(750, self.y_p2 +50, image=self.p2_laser)
self.x_p2_laser = 750
self.p2_shot_out = True
self.window.after(1, p2_shoot_move)
def p2_shoot_move():
#moves the laser until its outside the canvas
if self.x_p2_laser <= -110:
pass
else:
self.canvas.move(self.laser_p2,-5,0)
self.x_p2_laser += -5
self.canvas.update()
self.window.after(1, p2_shoot_move)
# Key bindings that trigger their respective functions
self.canvas.bind('w', p1_up)
self.canvas.bind('s', p1_down)
self.canvas.bind('<Up>', p2_up)
self.canvas.bind('<Down>', p2_down)
self.canvas.bind('<space>', p1_shoot)
self.canvas.bind('<Control_R>', p2_shoot)
self.canvas.focus_set()
Game()
hope that helps you out
Upvotes: 1