This is a common arcade game, the goal is to hit all targets as many times as you can to earn the highest score. Every time the ball hits a "stone" you earn 1 point, and if it hits 2 you earn 2 points, respectively. If the player fails to catch the ball on the bar or "pole" then the game is over.
My assignment is to turn this game written in object-oriented programming into functional programming.
import time
class Ball:
def __init__(self, cvs, pole, stones, scre):
self.stones = stones
self.cvs = cvs
self.pole = pole
self.scre = scre
self.bottom_hit = False
self.hit = 0
self.id = canvas.create_oval(10, 10, 25, 25, fill="cadetblue", width=1)
self.cvs.move(self.id, 230, 461)
self.a = 3
self.b = -3
self.cvs.move(self.id, self.a, self.b)
self.cvs_height = canvas.winfo_height()
self.cvs_width = canvas.winfo_width()
def stone_strike(self, push):
for stone_line in self.stones:
for stone in stone_line:
stone_push = self.cvs.coords(stone.id)
try:
if push[2] >= stone_push[0] and push[0] <= stone_push[2]:
if push[3] >= stone_push[1] and push[1] <= stone_push[3]:
canvas.bell()
self.hit = 1
self.scre.configure(text="Score: " str(self.hit))
self.cvs.delete(stone.id)
return True
except:
continue
return False
def pole_strike(self, push):
pole_push = self.cvs.coords(self.pole.id)
if push[2] >= pole_push[0] and push[0] <= pole_push[2]:
if push[3] >= pole_push[1] and push[1] <= pole_push[3]:
return True
return False
def draw(self):
self.cvs.move(self.id, self.a, self.b)
push = self.cvs.coords(self.id)
if self.stone_strike(push):
self.b = 3
if push[1] <= 0:
self.b = 3
if push[3] >= self.cvs_height:
self.bottom_hit = True
if push[0] <= 0:
self.a = 3
if push[2] >= self.cvs_width:
self.a = -3
if self.pole_strike(push):
self.b = -3
class Pole:
def __init__(self, cvs):
self.cvs = cvs
self.id = canvas.create_rectangle(0, 0, 100, 10, fill="darkgoldenrod")
self.cvs.move(self.id, 200, 485)
self.a = 0
self.cvs_width = canvas.winfo_width()
self.cvs.bind_all("<Left>", self.turn_left)
self.cvs.bind_all("<Right>", self.turn_right)
def draw(self):
push = self.cvs.coords(self.id)
if push[0] self.a <= 0:
self.a = 0
if push[2] self.a >= self.cvs_width:
self.a = 0
self.cvs.move(self.id, self.a, 0)
def turn_left(self, event):
self.a = -5
def turn_right(self, event):
self.a = 5
class Stone:
def __init__(self):
self.id = canvas.create_rectangle(5, 5, 25, 25, fill="firebrick")
def start_game(event):
score.configure(text="Score: 00")
canvas.delete("all")
pole = Pole(canvas)
stones = []
for i in range(0, 5):
b = []
for j in range(0, 19):
tmp = Stone()
b.append(tmp)
stones.append(b)
for i in range(0, 5):
for j in range(0, 19):
canvas.move(stones[i][j].id, 25 * j, 25 * i)
ball = Ball(canvas, pole, stones, score)
root.update()
time.sleep(1)
while 1:
if not ball.bottom_hit:
ball.draw()
pole.draw()
root.update()
time.sleep(0.01)
if ball.hit == 95:
canvas.create_text(250, 250, text="YOU WON!!", fill="darkolivegreen", font="Calibri 24")
break
else:
canvas.create_text(250, 250, text="GAME OVER!!", fill="darkolivegreen", font="Calibri 24")
break
root = Tk()
root.title("Bounce Ball Game")
root.geometry("500x570")
root.resizable(0, 0)
canvas = Canvas(root, width=500, height=500, bd=0, bg="black")
canvas.pack(padx=10, pady=10)
canvas.create_text(250, 250, text="Press Enter to start Game!!", fill="darkolivegreen", font="Calibri 18")
score = Label(height=50, width=80, text="Score: 00", font="Calibri 14 italic")
score.pack(side="left")
root.bind_all("<Return>", start_game)
root.mainloop()
Here is the code I have written.. There must be logical errors since it's not working. Any ideas??
import time
def startgame(event):
score.configure(text="score:00")
canvas.delete("all")
canvas_width = canvas.winfo_width()
canvas_height = canvas.winfo_height()
pole = canvas.create_rectangle(0, 0, 100, 10, fill="darkgoldenrod")
canvas.move(pole, 200, 425)
pa = 0
def turn_left(event):
pa = -5
def turn_right(event):
pa = 5
def stone_strike(push):
for stone_line in stones:
for stone in stone_line:
stone_push = canvas.coords(stone)
try:
if push[2] >= stone_push[0] and push[0] <= stone_push[2]:
if push[3] >= stone_push[1] and push[1] <= stone_push[3]:
canvas.bell()
hit = 1
score.configure(text="score:" str(hit))
stonaki.delete()
return True
except:
continue
return False
def pole_strike(push_b):
pole_push = canvas.coords(pole)
if push_b[2] >= pole_push[0] and push_b[0] <= pole_push[2]:
if push_b[3] >= pole_push[1] and push_b[1] <= pole_push[3]:
return True
return False
canvas.bind_all("<Left>", turn_left)
canvas.bind_all("<Right>", turn_right)
push_p = canvas.coords(pole)
if push_p[0] pa <= 0:
pa = 0
if push_p[2] pa >= canvas_width:
pa = 0
stones = []
for i in range(0, 5):
lista = []
for j in range(0, 19):
stonaki = canvas.create_rectangle(5, 5, 25, 25, fill="firebrick")
lista.append(stonaki)
stones.append(lista)
for i in range(0, 5):
for j in range(0, 19):
canvas.move(stones[i][j], 25 * j, 25 * i)
root.update()
bottom_hit = False
hit = 0
ball = canvas.create_oval(10, 10, 25, 25, fill="cadetblue", width=1)
canvas.move(ball, 230, 461)
ba = 3
bb = -3
canvas.move(ball, ba, bb)
push_b = canvas.coords(ball)
if stone_strike(push_b):
bb = 3
if push_b[1] <= 0:
bb = 3
if push_b[3] >= canvas_height:
bottom_hit = True
if push_b[0] <= 0:
ba = 3
if push_b[2] >= canvas_width:
ba = -3
if pole_strike(push_b):
bb = -3
time.sleep(1)
while 1:
if not bottom_hit:
root.update()
time.sleep(0.01)
if hit == 95:
canvas.create_text(250, 250, text="YOU WON!!", fill="darkolivegreen", font="Calibri 24")
break
else:
canvas.create_text(250, 250, text="GAME OVER!!", fill="darkolivegreen", font="Calibri 24")
break
root = Tk()
root.title("Bounce Ball Game")
root.geometry("500x570")
root.resizable(0, 0)
canvas = Canvas(root, width=500, height=500, bd=0, bg="black")
canvas.pack(padx=10, pady=10)
canvas.create_text(250, 250, text="Press Enter to start Game!!", fill="darkolivegreen", font="Calibri 18")
score = Label(height=50, width=80, text="Score: 00", font="Calibri 14 italic")
score.pack(side="left")
root.bind_all("<Return>", startgame)
root.mainloop()
CodePudding user response:
In the process of turning this game written in object-oriented programming into functional programming, we need to take care of variables/widgets which are being used by every function. If we are making changes to some variable in a local function and want to retain the changes made after the function call ends, so I will be making those variables/widgets global.
Also, in the OOP code, changes are being made every time in the canvas using functions draw()
for both "ball" and "pole". Hence making two functions for the same drawB()
and drawP()
:
from tkinter import *
import time
def startgame(event):
score.configure(text="score:00")
canvas.delete("all")
canvas_width = canvas.winfo_width()
canvas_height = canvas.winfo_height()
global pole,pa, ba,bb,bottom_hit, hit,ball
pole = canvas.create_rectangle(0, 0, 100, 10, fill="darkgoldenrod")
canvas.move(pole, 200, 425)
pa = 0
def turn_left(event):
global pa
pa = -5
def turn_right(event):
global pa
pa = 5
def stone_strike(push):
global stones, hit
for stone_line in stones:
for stone in stone_line:
stone_push = canvas.coords(stone)
try:
if push[2] >= stone_push[0] and push[0] <= stone_push[2]:
if push[3] >= stone_push[1] and push[1] <= stone_push[3]:
canvas.bell()
hit = 1
score.configure(text="score:" str(hit))
canvas.delete(stone) #what to delete
return True
except:
continue
return False
def pole_strike(push_b):
global pole
pole_push = canvas.coords(pole)
if push_b[2] >= pole_push[0] and push_b[0] <= pole_push[2]:
if push_b[3] >= pole_push[1] and push_b[1] <= pole_push[3]:
return True
return False
canvas.bind_all("<Left>", turn_left)
canvas.bind_all("<Right>", turn_right)
def drawP():
global pa,pole
push_p = canvas.coords(pole)
if push_p[0] pa <= 0:
pa = 0
if push_p[2] pa >= canvas_width:
pa = 0
canvas.move(pole, pa, 0)
global stones
stones = []
for i in range(0, 5):
lista = []
for j in range(0, 19):
stonaki = canvas.create_rectangle(5, 5, 25, 25, fill="firebrick")
lista.append(stonaki)
stones.append(lista)
for i in range(0, 5):
for j in range(0, 19):
canvas.move(stones[i][j], 25 * j, 25 * i)
bottom_hit = False
hit = 0
ball = canvas.create_oval(10, 10, 25, 25, fill="cadetblue", width=1)
canvas.move(ball, 230, 461)
ba = 3
bb = -3
root.update()
def drawB():
global ba,bb,bottom_hit, hit,ball,pole
canvas.move(ball, ba, bb)
push_b = canvas.coords(ball)
if stone_strike(push_b):
bb = 3
if push_b[1] <= 0:
bb = 3
if push_b[3] >= canvas_height:
bottom_hit = True
if push_b[0] <= 0:
ba = 3
if push_b[2] >= canvas_width:
ba = -3
if pole_strike(push_b):
bb = -3
time.sleep(1)
while 1:
if not bottom_hit:
drawB()
drawP()
root.update()
time.sleep(0.01)
if hit == 95:
canvas.create_text(250, 250, text="YOU WON!!", fill="darkolivegreen", font="Calibri 24")
break
else:
canvas.create_text(250, 250, text="GAME OVER!!", fill="darkolivegreen", font="Calibri 24")
break
root = Tk()
root.title("Bounce Ball Game")
root.geometry("500x570")
root.resizable(0, 0)
canvas = Canvas(root, width=500, height=500, bd=0, bg="black")
canvas.pack(padx=10, pady=10)
canvas.create_text(250, 250, text="Press Enter to start Game!!", fill="darkolivegreen", font="Calibri 18")
score = Label(height=50, width=80, text="Score: 00", font="Calibri 14 italic")
score.pack(side="left")
root.bind_all("<Return>", startgame)
root.mainloop()
You may further optimize this code.