Python: How to get score board on canvas - python

I want the score to show on the canvas but so far to no avail. I thought I could just use:
self.canvas.create_text(200, 60, fill="darkblue", font="Times 15 italic bold", text="Your score is:",self.score)
Didn't work unfortunately, so how do I get the score to show on the canvas? Also wondering how to get a message box to pop up saying "You won!" when the score = 10. And lastly, how to get a message box to pop up saying "You lost if the score < 10 AND there is no even numbers on the canvas.
Code so far using python 3.3:
def click(self, event):
if self.canvas.find_withtag(CURRENT):
item_uid = event.widget.find_closest(event.x, event.y)[0]
is_even = False
try: # clicked oval
self.bubbles[item_uid]
except KeyError: # clicked the text
for key, value in self.bubbles.iteritems():
if item_uid == value[5]: # comparing to text_id
if value[4] % 2 == 0:
is_even = True
self.canvas.delete(key) # deleting oval
self.canvas.delete(item_uid) # deleting text
else:
if self.bubbles[item_uid][4] % 2 == 0:
is_even = True
self.canvas.delete(item_uid) # deleting oval
self.canvas.delete(self.bubbles[item_uid][5]) # deleting text
if is_even:
self.score += 1
else:
self.score -= 1
if self.score == 10:
print ("You won")
print (self.score)

That is a fun game! The script I gave below shows you how to do everything you want (display the current score and show messages). The lines with ## above them are what I added:
from tkinter import *
import random
##
from tkinter.messagebox import showinfo
class BubbleFrame:
def __init__(self, root):
root.title("Math Bubbles")
self.bubbles = {}
self.score = 0
Button(root, text="Start", width=8, command=self.initialize_bubbles).pack() # This button starts the game, making the bubbles move across the screen
Button(root, text="Quit", width=8, command=quit).pack()
self.canvas = Canvas(root, width=800, height=650, bg='#afeeee')
self.canvas.create_text(400, 30, fill="darkblue", font="Times 20 italic bold", text="Click the bubbles that are multiples of two.")
##
self.current_score = self.canvas.create_text(200, 60, fill="darkblue", font="Times 15 italic bold", text="Your score is:")
self.canvas.pack()
def initialize_bubbles(self):
for each_no in range(1, 21):
xval = random.randint(5, 765)
yval = random.randint(5, 615)
oval_id = self.canvas.create_oval(xval, yval, xval + 30, yval + 30,fill="#00ffff", outline="#00bfff", width=5, tags="bubble")
text_id = self.canvas.create_text(xval + 15, yval + 15, text=each_no, tags="bubble")
self.canvas.tag_bind("bubble", "<Button-1>", lambda x: self.click(x))
self.bubbles[oval_id] = (xval, yval, 0, 0, each_no, text_id)
def click(self, event):
if self.canvas.find_withtag(CURRENT):
item_uid = event.widget.find_closest(event.x, event.y)[0]
is_even = False
try:
self.bubbles[item_uid]
except KeyError:
for key, value in self.bubbles.iteritems():
if item_uid == value[5]:
if value[4] % 2 == 0:
is_even = True
self.canvas.delete(key)
self.canvas.delete(item_uid)
else:
if self.bubbles[item_uid][4] % 2 == 0:
is_even = True
self.canvas.delete(item_uid)
self.canvas.delete(self.bubbles[item_uid][5])
if is_even:
self.score += 1
else:
self.score -= 1
if self.score == 10:
##
showinfo("Winner", "You won!")
##
self.canvas.delete(self.current_score)
##
self.current_score = self.canvas.create_text(200, 60, fill="darkblue", font="Times 15 italic bold", text="Your score is: %s"%self.score)
def loop(self, root):
for oval_id, (x, y, dx, dy, each_no, text_id) in self.bubbles.items():
dx += random.randint(-1, 1)
dy += random.randint(-1, 1)
dx, dy = max(-5, min(dx, 5)), max(-5, min(dy, 5))
if not 0 < x < 770:
dx = -dx
if not 0 < y < 620:
dy = -dy
self.canvas.move(oval_id, dx, dy)
self.canvas.move(text_id, dx, dy)
self.bubbles[oval_id] = (x + dx, y + dy, dx, dy, each_no, text_id)
root.after(100, self.loop, root)
if __name__ == "__main__":
root = Tk()
frame = BubbleFrame(root)
frame.loop(root)
root.mainloop()

from http://www.tutorialspoint.com/python/tk_messagebox.htm
import tkMessageBox
tkMessageBox.showinfo("Winner", "You won!")
you can use place instead of pack to put elements above the canvas in the same Frame or Tk.
Label(root, text="Quit").place()
place()
relx, rely : Horizontal and vertical offset as a float between 0.0 and 1.0, as a fraction of the height and width of the parent widget.
x, y : Horizontal and vertical offset in pixels.
from http://www.tutorialspoint.com/python/tk_place.htm

Related

Unable to record the score and high score properly

I'm tryin to make a snake game, but I am unable to record the score and high-score properly. Whenever the snake collects an item, all that happens is that the high score increases, but not the general score.
from tkinter import *
from settings import *
import random
import turtle
import pygame as pg
import keyboard
from os import path
global game_state
class Snake:
def __init__(self):
self.body_size = BODY_PARTS
self.coordinates = []
self.squares = []
for i in range(0, BODY_PARTS):
self.coordinates.append([0, 0])
for x, y in self.coordinates:
square = canvas.create_rectangle(x, y, x + SPACE_SIZE, y + SPACE_SIZE, fill=SNAKE_COLOR, tag="snake")
self.squares.append(square)
class Food:
def __init__(self):
x = random.randint(0, (GAME_WIDTH / SPACE_SIZE)-1) * SPACE_SIZE
y = random.randint(0, (GAME_HEIGHT / SPACE_SIZE) - 1) * SPACE_SIZE
self.coordinates = [x, y]
canvas.create_oval(x, y, x + SPACE_SIZE, y + SPACE_SIZE, fill=FOOD_COLOR, tag="food")
class TryAgain:
def __init__(self):
x = (GAME_WIDTH / SPACE_SIZE)-1 * SPACE_SIZE
y = (GAME_HEIGHT / SPACE_SIZE) - 1 * SPACE_SIZE
self.coordinates = [x, y]
def show_title_screen():
canvas.create_text(canvas.winfo_width()/2, canvas.winfo_height()/4,
font=('times new roman',70), text="SNAKE!", fill="Green", tag="title")
canvas.create_text(canvas.winfo_width()/2, canvas.winfo_height()/2,
font=('times new roman',22), text="Use the arrow keys to move", fill="Green", tag="title")
def next_turn(snake, food):
x, y = snake.coordinates[0]
if direction == "up":
y -= SPACE_SIZE
elif direction == "down":
y += SPACE_SIZE
elif direction == "left":
x -= SPACE_SIZE
elif direction == "right":
x += SPACE_SIZE
snake.coordinates.insert(0, (x, y))
square = canvas.create_rectangle(x, y, x + SPACE_SIZE, y + SPACE_SIZE, fill=SNAKE_COLOR)
snake.squares.insert(0, square)
if x == food.coordinates[0] and y == food.coordinates[1]:
global score
global high_score
score += 1
label.config(text="Score:{}".format(score))
if score >= high_score:
high_score = score
label.config(text="High Score:{}".format(high_score))
canvas.delete("food")
food = Food()
else:
del snake.coordinates[-1]
canvas.delete(snake.squares[-1])
del snake.squares[-1]
if check_collisions(snake):
game_over()
else:
window.after(SPEED, next_turn, snake, food)
def change_direction(new_direction):
global direction
if new_direction == 'left':
if direction != 'right':
direction = new_direction
elif new_direction == 'right':
if direction != 'left':
direction = new_direction
elif new_direction == 'up':
if direction != 'down':
direction = new_direction
elif new_direction == 'down':
if direction != 'up':
direction = new_direction
def check_collisions(snake):
x, y = snake.coordinates[0]
if x < 0 or x >= GAME_WIDTH:
return True
elif y < 0 or y >= GAME_HEIGHT:
return True
for body_part in snake.coordinates[1:]:
if x == body_part[0] and y == body_part[1]:
return True
return False
def game_over():
canvas.delete(ALL)
canvas.create_text(canvas.winfo_width()/2, canvas.winfo_height()/4,
font=('times new roman',70), text="GAME OVER", fill="orange", tag="gameover")
button = TryAgain()
def load_data(self):
self.dir = path.dirname(__dirname__)
with open(path.join(self.dir, HS_FILE), 'w') as f:
try:
self.highscore = int(f.read())
except:
self.highscore = 0
window = Tk()
window.title("Snake game")
window.resizable(False, False)
score = 0
high_score = 0
direction = 'down'
label = Label(window, text="Score:{}".format(score), font=('times new roman', 40))
label.pack()
label = Label(window, text="High Score:{}".format(high_score), font=('times new roman', 40))
label.pack()
canvas = Canvas(window, bg=BACKGROUND_COLOR, height=GAME_HEIGHT, width=GAME_WIDTH)
canvas.pack()
window.update()
window_width = window.winfo_width()
window_height = window.winfo_height()
screen_width = window.winfo_screenwidth()
screen_height = window.winfo_screenheight()
x = int((screen_width/2) - (window_width/2))
y = int((screen_height/2) - (window_height/2))
window.geometry(f"{window_width}x{window_height}+{x}+{y}")
show_title_screen()
window.bind('<Left>', lambda event: change_direction('left'))
window.bind('<Right>', lambda event: change_direction('right'))
window.bind('<Up>', lambda event: change_direction('up'))
window.bind('<Down>', lambda event: change_direction('down'))
snake = Snake()
food = Food()
next_turn(snake, food)
window.mainloop()
In one instance, I tried to rearrange the canvas codes that involved "score" and "high score", and tried to make it so that when the high score is greater than the score, it would start counting, but that still doesn't work.
I don't know anything about tkinter. But I think the problem is due to this:
label = Label(window, text="Score:{}".format(score), font=('times new roman', 40))
label.pack()
label = Label(window, text="High Score:{}".format(high_score), font=('times new roman', 40))
label.pack()
You're using the same variable name for both labels.
And then when you update the scores:
score += 1
label.config(text="Score:{}".format(score))
if score >= high_score:
high_score = score
label.config(text="High Score:{}".format(high_score))
The variable name label refers only to the high score label.
I think you can fix this by using different variable names for the two labels, i.e. something like score_label and high_score_label.

tkinter: How to make timer run in a background

I have a game - catching coins into a bowl. However, one of the criteria is to make it limited by entering time in seconds - how long will the game last. The time user enters is from tkinter.Entry, and I have no idea how to execute a timer and a function at the same time. Code progress:
import tkinter, random, time
from threading import Thread
window = tkinter.Tk()
window.title("Dukaty")
canvas = tkinter.Canvas(window, height = 400, width = 800)
canvas.pack()
timeLabel = tkinter.Label(text = "Time:", font = "Helvetica 15")
timeLabel.pack()
timeEntry = tkinter.Entry(bd = 1)
timeEntry.pack()
mistakesLabel = tkinter.Label(text = "Allowed mistakes:", font = "Helvetica 15")
mistakesLabel.pack()
mistakesEntry = tkinter.Entry(bd = 1)
mistakesEntry.pack()
timeEntry.insert(0, "0")
mistakesEntry.insert(0, "0")
speed = 250
score = 0
mistakes = 0
allowedTime = ""
def countdown(t):
while t:
mins, secs = divmod(t, 60)
timer = '{:02d}:{:02d}'.format(mins, secs)
allowedTime = timer
print(allowedTime)
time.sleep(1)
t -= 1
print("Time's up!")
def timedGame():
time = int(timeEntry.get())
canvas.after(time * 1000)
end()
def movingCoin():
global speed, score, mistakes, allowedTime
time = int(timeEntry.get())
coin = canvas.create_image(random.randint(15, 585), 18, image=coinImg, tags="coin")
canvas.create_text(700, 50, text = str(score), font = "Helvetica 20", fill = "green", tags = "score")
canvas.create_text(700, 80, text = str(mistakes), font = "Helvetica 20", fill = "red", tags = "mistakes")
# ENDLESS
if timeEntry.get() == "0" and mistakesEntry.get() == "0":
while True:
if canvas.coords(coin)[1] < 360:
canvas.move(coin, 0, 5)
canvas.after(speed)
canvas.update()
elif canvas.coords(coin)[1] >= 360 and (canvas.coords(coin)[0] > (canvas.coords(bowl)[0] - 40) and canvas.coords(coin)[0] < (canvas.coords(bowl)[0] + 40)):
canvas.delete("score")
score += 1
canvas.create_text(700, 50, text=str(score), font="Helvetica 20", fill="green", tags="score")
canvas.delete(coin)
coin = canvas.create_image(random.randint(15, 585), 18, image=coinImg, tags="coin")
speed -= 10
else:
canvas.delete("mistakes")
mistakes += 1
canvas.create_text(700, 80, text=str(mistakes), font="Helvetica 20", fill="red", tags="mistakes")
canvas.delete(coin)
coin = canvas.create_image(random.randint(15, 585), 18, image=coinImg, tags="coin")
speed -= 10
# TIME - not done yet
elif timeEntry.get() != "0" and mistakesEntry.get() == "0":
while str(allowedTime) != "00:00":
if canvas.coords(coin)[1] < 360:
canvas.move(coin, 0, 5)
canvas.after(speed)
canvas.update()
elif canvas.coords(coin)[1] >= 360 and (canvas.coords(coin)[0] > (canvas.coords(bowl)[0] - 40) and canvas.coords(coin)[0] < (canvas.coords(bowl)[0] + 40)):
score += 1
print(score)
canvas.delete(coin)
coin = canvas.create_image(random.randint(15, 585), 18, image=coinImg, tags="coin")
speed -= 10
else:
mistakes += 1
print(mistakes)
canvas.delete(coin)
coin = canvas.create_image(random.randint(15, 585), 18, image=coinImg, tags="coin")
speed -= 10
# MISTAKES
elif timeEntry.get() == "0" and mistakesEntry != "0":
allowedMistakes = int(mistakesEntry.get())
print("Allowed mistakes: " + str(allowedMistakes))
while True:
if canvas.coords(coin)[1] < 360:
canvas.move(coin, 0, 5)
canvas.after(speed)
canvas.update()
elif canvas.coords(coin)[1] >= 360 and (canvas.coords(coin)[0] > (canvas.coords(bowl)[0] - 40) and canvas.coords(coin)[0] < (canvas.coords(bowl)[0] + 40)):
canvas.delete("score")
score += 1
canvas.create_text(700, 50, text=str(score), font="Helvetica 20", fill="green", tags="score")
canvas.delete(coin)
coin = canvas.create_image(random.randint(15, 585), 18, image=coinImg, tags="coin")
speed -= 10
else:
if allowedMistakes > mistakes:
canvas.delete("mistakes")
mistakes += 1
canvas.create_text(700, 80, text=str(mistakes), font="Helvetica 20", fill="red", tags="mistakes")
canvas.delete(coin)
coin = canvas.create_image(random.randint(15, 585), 18, image=coinImg, tags="coin")
speed -= 10
elif allowedMistakes == mistakes:
print("ending the program")
break
def end():
window.destroy()
def tap():
Thread(target=countdown(int(timeEntry.get()))).start()
Thread(target=movingCoin).start()
endButton = tkinter.Button(text = "End", command = end)
endButton.pack(side = "right")
startButton = tkinter.Button(text = "Start", command = tap)
startButton.pack(side = "left")
window.mainloop()
What this does, is that it starts the timer, and when it comes to end, THEN it executes the movingCoin function.
What I want to achieve is to make the timer start (when in Entry is value greater than 0) and at the same time execute the movingCoin - which then drops to the time section and the while breaks when the time is up.
You can use this method
window.after(1000,<function_name>)
It means the function call after 1 sec. If you are use recursion with this method then you can create timer.
I hope it works for you, cheer.
import time
# time.time() return in second
game_duration = float(input('duration: ')) + time.time()
game_is_running = True
while game_is_running:
if game_duration == time.time(): # this means: if now equal to game_duration
game_is_running = False
# note: it is quite critical where you place time.time()
One more example:
# I used the following technique to build an explosion animation for 30 seconds, then it will do something else.
class Explosion(pygame.sprite.Sprite):
def __init__(self, center):
pygame.sprite.Sprite.__init__(self)
self.image = explosion_animation[0]
self.rect = self.image.get_rect()
self.rect.center = center
self.frame = 0
self.last_update = pygame.time.get_ticks()
self.duration = 30
def update(self):
now = pygame.time.get_ticks()
if now - self.last_update > self.duration:
self.last_update = now
self.frame += 1
if self.frame == len(explosion_animation):
self.kill()
else:
center = self.rect.center
self.image = explosion_animation[self.frame]
self.rect = self.image.get_rect()
self.rect.center = center

How to make the square change direction and move in the right direction when you press the "w, a, s, d" buttons

How to make the square change direction and move in the right direction when you press the "w, a, s, d" buttons
(So that he moves himself, after a single press of the button that sets the direction)
Without using classes
from tkinter import *
root = Tk()
root.title('Snake')
root["width"] = 400
root["height"] = 400
field = Canvas(root)
rectangle = field.create_rectangle(10, 20, 30, 40)
field.grid(row=0, column=0)
def w(y):
field.move(rectangle, 0, y)
y += 1
root.after(5)
def s(y):
field.move(rectangle, 0, y)
y -= 1
root.after(5)
def a(x):
field.move(rectangle, x, 0)
x -= 1
root.after(5)
def d(x):
field.move(rectangle, x, 0)
x += 10
root.after(5)
x=0
y=0
def snake(event):
if event.char == 'w':
w(y)
elif event.char == 'a':
a(x)
elif event.char == 's':
s(y)
elif event.char == 'd':
d(x)
field.move(rectangle, x, y)
root.bind("<Key>", snake)
root.mainloop()
You need to declare two global variables for the x and y directions, for example dx and dy.
Then if you want the rectangle keep moving, you need to use .after() loop.
from tkinter import *
root = Tk()
root.title('Snake')
root["width"] = 400
root["height"] = 400
field = Canvas(root)
rectangle = field.create_rectangle(10, 20, 30, 40)
field.grid(row=0, column=0)
def move_snake():
field.move(rectangle, dx, dy)
# change the delay value 30 (ms) to other value to suit your case
root.after(30, move_snake)
# initial directions for x and y
dx = 0
dy = 0
def change_direction(event):
global dx, dy
if event.char in 'wasd':
dx = dy = 0
if event.char == 'w':
dy = -1 # move up
elif event.char == 'a':
dx = -1 # move left
elif event.char == 's':
dy = 1 # move down
elif event.char == 'd':
dx = 1 # move right
root.bind("<Key>", change_direction)
move_snake() # start the moving loop
root.mainloop()
Instead of incrementing and decrementing the x,y, have a default value, which you change as per the direction -
from tkinter import *
root = Tk()
root.title('Snake')
root["width"] = 400
root["height"] = 400
field = Canvas(root)
rectangle = field.create_rectangle(10, 20, 30, 40)
field.grid(row=0, column=0)
x = 0 # Default
y = 0
speed = 10 # Set your speed. The lesser the value, the more fast
def pos(event):
global x, y
x = 0
y = 0
if event.char == 'w':
y = -1 # Changes the default values
elif event.char == 'a':
x = -1
elif event.char == 's':
y = 1
elif event.char == 'd':
x = 1
def snake():
field.move(rectangle, x, y)
root.after(speed, snake)
root.bind("<Key>", pos)
snake()
root.mainloop()

How to make that when the cube touches the circle, the circle moves to a random place on the field?

How to make that when touching (when the coordinates of two objects coincide) the cube to the circle, the circle moves to a random place on the field? Without using classes.
import random
from tkinter import *
root = Tk()
root.title('Snake')
root["width"] = 400
root["height"] = 400
field = Canvas(root)
oval = field.create_oval(10, 20, 30, 40)
field.grid(row=0, column=0)
rectangle = field.create_rectangle(10, 20, 30, 40)
field.grid(row=0, column=0)
x = 0
y = 0
food_x = random.randrange(0, 300, 20)
food_y = random.randrange(0, 300, 20)
field.move(oval, food_x, food_y)
def food():
global food_x
global food_y
if x == food_x and y == food_y:
food_x = random.randrange(0, 300, 20)
food_y = random.randrange(0, 300, 20)
field.move(oval, food_x, food_y)
root.after(250, food)
food()
def position(event):
global x, y
if event.char in 'wasd':
x = 0
y = 0
if event.char == 'w':
y = -20
elif event.char == 'a':
x = -20
elif event.char == 's':
y = 20
elif event.char == 'd':
x = 20
def snake():
field.move(rectangle, x, y)
root.after(250, snake)
root.bind("<Key>", position)
snake()
food()
root.mainloop()
I think this shows how to do what you want. I've changed the name of your functions and variables to better reflect what they do or represent to make the code clearer. To detect whether the cube and circle are touching is accomplished by first retrieving the coordinates of their corresponding bounding-boxes via the coords() method common to all Canvas objects, before comparing them to determine whether any overlap exists.
I also changed how the food circle is move to a new positions because what you had was capable of moving it very far away from its current location, frequently completely off the field. The replacement code only moves it by the difference between where it currently is and a new position that's within the boundaries of the field.
import random
from tkinter import *
root = Tk()
root.title('Snake')
root["width"] = 400
root["height"] = 400
DELAY = 250
field = Canvas(root)
field.grid(row=0, column=0)
food_obj = field.create_oval(10, 20, 30, 40)
snake_obj = field.create_rectangle(10, 20, 30, 40)
x, y = 0, 0
def move_food():
"""Move food to random location."""
food_coords = field.coords(food_obj)
x1 = random.randrange(0, 300, 20)
y1 = random.randrange(0, 300, 20)
field.move(food_obj, x1-food_coords[0], y1-food_coords[1])
def check_collision():
"""If bounding box of snake and food overlap, move food to new position."""
a_x1, a_y1, a_x2, a_y2 = field.coords(food_obj)
b_x1, b_y1, b_x2, b_y2 = field.coords(snake_obj)
# Determine of bounding boxes overlap.
if a_x1 <= b_x2 and b_x1 <= a_x2 and a_y1 <= b_y2 and b_y1 <= a_y2:
move_food()
root.after(DELAY, check_collision)
def on_keypress(event):
global x, y
if event.char in 'wasd ':
x, y = 0, 0
if event.char == 'w':
y = -20
elif event.char == 'a':
x = -20
elif event.char == 's':
y = 20
elif event.char == 'd':
x = 20
def slither():
field.move(snake_obj, x, y)
root.after(DELAY, slither)
root.bind("<Key>", on_keypress)
move_food()
slither()
check_collision()
root.mainloop()

Resetting a variable increases it instead of resetting it - Tkinter

I am creating a game of Pong using tkinter as a small project. I have written the game and it works fully. However I have encountered a weird bug where upon the game ending, when one player reaches a score of 3, when the game is restarted the velocity of the ball appears to double, and this happens every time the game is reset. the startgame function should set the variable dx (x movement of the ball) to 2 when it is called, so I am not sure why it appears to get faster by 2 everytime, as there are no additions present.
I have posted the whole code block below and am completely lost as to why this happens, any help would be much appreciated!
from tkinter import *
root = Tk()
#size of window
w = 600
h = 400
sw = root.winfo_screenwidth()
sh = root.winfo_screenheight()
x = (sw - w)/2
y = (sh - h)/2
root.geometry('%dx%d+%d+%d' % (w, h, x, y))
#playing frame, with Canvas inside
canvframe = Frame(relief=SUNKEN, width=600, height = 350, background="black")
canvframe.pack()
canv = Canvas(canvframe, background="black", width=600, height = 350)
canv.pack(fill=NONE)
# Objects in canvas
ball = canv.create_oval(300,160,310,170, outline="white", fill="white", width=2, tags=('ball'))
paddle1 = canv.create_rectangle(0,200,10,120, outline="white", fill="white", width=2, tags=('paddle1'))
paddle2 = canv.create_rectangle(590,200,600,120, outline="white", fill="white", width=2)
#Paddle movement
def moveUp1(event):
canv.move(paddle1, 0, -10)
pass
def moveUp2(event):
canv.move(paddle2, 0, -10)
pass
def moveDown1(event):
canv.move(paddle1, 0, 10)
pass
def moveDown2(event):
canv.move(paddle2, 0, 10)
pass
#InitialVelocity
dx = 0
dy = 0
#initial score
Player1score = 0
Player2score = 0
#start game - what happens when you push start button (reset velocity and scores)
def startgame():
global dy, dx, Player1score, Player2score
canv.coords(paddle1, 0,200,10,120)
canv.coords(paddle2, 590,200,600,120)
dx = 2
dy = 0
Player1score = 0
Player2score = 0
Player1scoreLabel.configure(text="Score: "+ str(Player1score))
Player2scoreLabel.configure(text="Score: "+ str(Player2score))
moveBall()
#Ball Movement
def moveBall():
global dy, dx, Player1score, Player2score
# to make ball bounce off paddle 1
if canv.coords(ball)[0]<=canv.coords(paddle1)[2] and canv.coords(paddle1)[1]<= canv.coords(ball)[1] <= canv.coords(paddle1)[3]:
dx = -dx
if canv.coords(paddle1)[1] <= canv.coords(ball)[1] <= (int((canv.coords(paddle1)[1] + canv.coords(paddle1)[3])) / 2 ):
dy -=1
canv.move(ball, dx, dy)
elif (int(canv.coords(paddle1)[1] + canv.coords(paddle1)[3]) / 2 ) <= canv.coords(ball)[3] <= canv.coords(paddle1)[3]:
dy += 1
canv.move(ball, dx, dy)
else:
canv.move(ball, dx, dy)
# to make ball bounce off paddle 2
elif canv.coords(ball)[2]>=canv.coords(paddle2)[0] and canv.coords(paddle2)[1]<= canv.coords(ball)[3] <= canv.coords(paddle2)[3]:
dx = -dx
if canv.coords(paddle2)[1] <= canv.coords(ball)[1] <= (int((canv.coords(paddle2)[1] + canv.coords(paddle2)[3])) / 2 ):
dy -= 1
canv.move(ball, dx, dy)
elif (int(canv.coords(paddle2)[1] + canv.coords(paddle2)[3])/ 2 ) <= canv.coords(ball)[3] <= canv.coords(paddle2)[3]:
dy += 1
canv.move(ball, dx, dy)
else:
canv.move(ball, dx, dy)
# to make ball bounce off roof
elif canv.coords(ball)[1]<=0:
dy = -dy
canv.move(ball, dx, dy)
# to mkae ball bounce of floor
elif canv.coords(ball)[1]>=325:
dy = -dy
canv.move(ball, dx, dy)
# if player 2 scores
elif canv.coords(ball)[2]<=0:
Player2score += 1
Player2scoreLabel.configure(text="Score: "+ str(Player2score))
canv.coords(ball, 300,160,310,170)
canv.coords(paddle1, 0,200,10,120)
canv.coords(paddle2, 590,200,600,120)
dx=2
dy=0
# if player1 scores
elif canv.coords(ball)[0]>=600:
Player1score += 1
Player1scoreLabel.configure(text="Score: "+ str(Player1score))
canv.coords(ball, 300,160,310,170)
canv.coords(paddle1, 0,200,10,120)
canv.coords(paddle2, 590,200,600,120)
dx=-2
dy=0
# end game if player 1 wins
elif Player1score==3:
dx=0
dy=0
# end game if player 2 wins
elif Player2score==3:
dx=0
dy=0
# move ball if nothign happens
else:
canv.move(ball, dx, dy)
canv.after(10, moveBall)
#buttons
Butframe = Frame(relief=SUNKEN, width=200, height = 150, background="white")
Butframe.pack()
startButton = Button(Butframe, text="Start", command = startgame)
startButton.pack(side=LEFT)
quitButton = Button(Butframe, text="Quit", command=root.destroy)
quitButton.pack(side=LEFT)
#scores
Score1frame = Frame(relief=SUNKEN, width=200, height = 150, background="white")
Score1frame.pack(side=LEFT)
Player1scoreLabel = Label(Score1frame, text="Score: "+ str(Player1score), background="green")
Player1scoreLabel.pack()
Score2frame = Frame(relief=SUNKEN, width=200, height = 150, background="white")
Score2frame.pack(side=RIGHT)
Player2scoreLabel = Label(Score2frame, text="Score: "+ str(Player2score), background="green")
Player2scoreLabel.pack()
#binding of movement keys
root.bind("<Up>", moveUp2)
root.bind("<w>", moveUp1)
root.bind("<Down>", moveDown2)
root.bind("<s>", moveDown1)
root.mainloop()
Your apparent speed increase is due to overlapping calls to the .after() method.
When one of the players wins, you should stop the loop in moveBall(), for example using a global variable called gameover like below:
# Initialize gameover variable
gameover = False
# (...) (Reset gameover to False in startgame() as well)
def moveBall():
global dy, dx, Player1score, Player2score, gameover
# (...)
# end game if player 1 or 2 wins
elif Player1score==3 or Player2score==3:
dx=0
dy=0
gameover = True
# move ball if nothing happens
else:
canv.move(ball, dx, dy)
# Repeat until game is over
if not gameover:
canv.after(10, moveBall)

Categories

Resources