Posts: 3
Threads: 3
Joined: Nov 2017
Hello I would like some help on my game. My Score and Time limit do not work at all so I would like help fixing that. The digits underneath the Time limit and score spots don't even show up and I can't figure out why. Also tons of blue numbers show up on the shell side, is this normal? It looks like its processing the Ids. This is the block that gives the points when touched: (yblock) & at times (ybloc). Thank you.
My Code:
import os
from tkinter import *
from random import randint
from time import sleep, time
from math import sqrt
HEIGHT = 1000
WIDTH = 900
window = Tk()
window.title('Strange Game')
c = Canvas(window, width=WIDTH, height=HEIGHT, bg='black')
c.pack()
block_id = c.create_rectangle(0, 0, 40, 40, outline='red', fill='red')
BLOCK_R = 15
MID_X = WIDTH / 2
MID_Y = HEIGHT / 2
c.move(block_id, MID_X, MID_Y)
BLOCK_SPD = 15
yblock_id = list()
yblock_r = list()
yblock_speed = list()
MIN_YBLOCK_R = 5
MAX_YBLOCK_R = 10
MAX_YBLOCK_SPD = 2
GAP = 100
YBLOCK_CHANCE = 100
TIME_LIMIT = 30
BONUS_SCORE = 1000
score = 0
bonus = 0
end = time() + TIME_LIMIT
def move_block(event):
if event.keysym == 'Up':
c.move(block_id, 0, -BLOCK_SPD)
elif event.keysym == 'Down':
c.move(block_id, 0, BLOCK_SPD)
elif event.keysym == 'Left':
c.move(block_id, -BLOCK_SPD, 0)
elif event.keysym == 'Right':
c.move(block_id, BLOCK_SPD, 0)
def create_ybloc():
x = randint(0, WIDTH)
y = randint(0, 0)
r = randint(MIN_YBLOCK_R, MAX_YBLOCK_R)
id1 = c.create_rectangle(x - r, y - r, x + r, y + r, outline='yellow')
yblock_id.append(id1)
yblock_r.append(r)
yblock_speed.append(randint(1, MAX_YBLOCK_SPD))
def move_yblocs():
for i in range(len(yblock_id)):
c.move(yblock_id[i], 0, yblock_speed[i])
def get_coords(id_num):
pos = c.coords(id_num)
x = (pos[0] + pos[2])/2
y = (pos[1] + pos[3])/2
return x, y
def del_ybloc(i):
del yblock_r[i]
del yblock_speed[i]
c.delete(yblock_id[i])
del yblock_id[i]
def clean_up_yblocks():
for i in range(len(yblock_id)-1, -1, -1):
x, y = get_coords(yblock_id[i])
if x < -GAP:
del_ybloc(i)
def distance(id1, id2):
x1, y1 = get_coords(id1)
x2, y2 = get_coords(id2)
return sqrt((x2 - x1)**2 + (y2 - y1)**2)
def show_score(score):
c.itemconfig(score_text, text=str(score))
def show_time(time_left):
c.itemconfig(time_text, text=str(time_left))
def collision():
points = 0
for yblock in range(len(yblock_id)-1, -1, -1):
if distance(block_id, yblock_id[yblock]) < (BLOCK_R + yblock_r[yblock]):
points += (yblock_r[yblock] + yblock_speed[yblock])
del_ybloc(yblock)
return points
c.bind_all('<Key>', move_block)
c.create_text(50, 30, text='TIME', fill='white' )
c.create_text(150, 30, text='SCORE', fill='white' )
time_text = c.create_text(50, 50, fill='white' )
score_text = c.create_text(150, 50, fill='white' )
#MAIN GAME LOOP
while time() < end:
if randint(1, YBLOCK_CHANCE) == 1:
create_ybloc()
move_yblocs()
clean_up_yblocks
score += collision()
if (int(score / BONUS_SCORE)) > bonus:
bonus += 1
end += TIME_LIMIT
show_score(score)
show_time(int(end - time()))
print(score)
window.update()
sleep(0.01)
c.create_text(MID_X, MID_Y, \
text='GAME OVER', fill='white', font=('Helvetica',30))
c.create_text(MID_X, MID_Y + 30, \
text='Score: '+ str(score), fill='white')
c.create_text(MID_X, MID_Y + 45, \
text='Bonus time: '+ str(bonus*TIME_LIMIT), fill='white')
Posts: 544
Threads: 15
Joined: Oct 2016
Nov-16-2017, 10:13 PM
(This post was last modified: Nov-16-2017, 10:30 PM by Windspar.)
1. Code need better organize. Very hard to follow.
2. score has to be 1000 or better to show time or score. Because of this line.
if (int(score / BONUS_SCORE) > bonus: suggestion: take them out of if block.
3. errors that haven't show up yet.
score_text and time_text must be above function.
To make more readable
1. put all const together
2. make a function for main game.
this is where changable variables go.
3. use better variables names. Like c should be canvas. something readable.
just a suggestion like score_text to me should be score_id.
4. from tkinter import * It just bad to flood namespace. No matter what tutorials says.
use something like this instead
import tkinter as tk 5. Just because this bothers me. in create_ybloc() remove the y from everywhere. Just a waste of cpu cycles.
99 percent of computer problems exists between chair and keyboard.
Posts: 544
Threads: 15
Joined: Oct 2016
Here my example of your code. Still don't like how keypress works.
import tkinter as tk
from random import randint
WIDTH = 1000
HEIGHT = 700
MID_X = WIDTH / 2
MID_Y = HEIGHT / 2
class YellowBlock:
MAX_SPEED = 2
def __init__(self, canvas):
self.value = randint(5, 10)
x = randint(self.value + 1, WIDTH - self.value)
self.id = canvas.create_rectangle(x - self.value, -self.value, x + self.value, self.value, outline='yellow')
self.speed = randint(1, YellowBlock.MAX_SPEED)
def move(self, canvas):
canvas.move(self.id, 0, self.speed)
class Game:
def __init__(self):
self.score = 0
self.bonus = 0
self.time = 31
self.yblocks = {}
# tk stuff
self.window = tk.Tk()
self.canvas = tk.Canvas(self.window, width=WIDTH, height=HEIGHT, bg='black')
self.canvas.pack()
self.canvas.create_text(50, 30, text='TIME', fill='white' )
self.canvas.create_text(150, 30, text='SCORE', fill='white' )
self.time_id = self.canvas.create_text(50, 50, fill='white' )
self.score_id = self.canvas.create_text(150, 50, fill='white' )
self.block_id = self.canvas.create_rectangle(0, 0, 40, 40, fill='red')
self.canvas.move(self.block_id, MID_X, MID_Y)
self.speed = 15
self.window.bind_all('<Key>', self.keys_press)
# game over
self.game_over_id = None
self.game_score_id = None
# start time loops
self.loop_id = None
self.time_loop_id = None
self.loop()
self.time_loop()
def new_game(self):
self.score = 0
self.bonus = 0
self.time = 31
self.canvas.itemconfig(self.score_id, text='0')
# recenter player
x, y , w, h = self.canvas.coords(self.block_id)
self.canvas.move(self.block_id, MID_X - (x + w) / 2, MID_Y - (y + h) / 2)
# remove left over blocks
for key in self.yblocks.keys():
self.canvas.delete(key)
self.yblocks = {}
# reset game over
if self.game_over_id:
self.canvas.delete(self.game_over_id)
if self.game_score_id:
self.canvas.delete(self.game_score_id)
self.game_over_id = None
self.game_score_id = None
# stop timers
if self.time_loop_id:
self.window.after_cancel(self.time_loop_id)
if self.loop_id:
self.window.after_cancel(self.loop_id)
# start time loops
self.loop_id = None
self.time_loop_id = None
self.loop()
self.time_loop()
def keys_press(self, event):
if event.keysym == 'Up':
self.canvas.move(self.block_id, 0, -self.speed)
elif event.keysym == 'Down':
self.canvas.move(self.block_id, 0, self.speed)
elif event.keysym == 'Left':
self.canvas.move(self.block_id, -self.speed, 0)
elif event.keysym == 'Right':
self.canvas.move(self.block_id, self.speed, 0)
elif event.keysym == 'Escape':
self.window.destroy()
elif event.keysym == 'n':
self.new_game()
def collide(self, box):
x, y, w, h = self.canvas.bbox(self.block_id)
return ( (((x > box[0]) and (x < box[2])) or
((box[0] > x) and (box[0] < w))) and
(((y > box[1]) and (y < box[3])) or
((box[1] > y) and (box[1] < h))))
def loop(self):
if self.time < 0:
if self.time_loop_id:
self.window.after_cancel(self.time_loop_id)
if self.loop_id:
self.window.after_cancel(self.loop_id)
self.game_over_id = self.canvas.create_text(MID_X, MID_Y,
text='GAME OVER', fill='white', font=('Helvetica',30))
self.game_score_id = self.canvas.create_text(MID_X, MID_Y + 30,
text='Score: '+ str(self.score), fill='white')
# return for it can't assign another cycle
return
if randint(1, 50) == 1 or len(self.yblocks) < 2:
yellow_block = YellowBlock(self.canvas)
self.yblocks[yellow_block.id] = yellow_block
blocks_remove = []
for item_id, block in self.yblocks.items():
x, y, w, h = self.canvas.bbox(item_id)
# move block
block.move(self.canvas)
# object fell offscreen
if y > HEIGHT + 1:
blocks_remove.append(item_id)
# collision
else:
if self.collide((x,y,w,h)):
blocks_remove.append(item_id)
self.score += block.value
self.canvas.itemconfig(self.score_id, text=str(self.score))
for key in blocks_remove:
self.canvas.delete(key)
del self.yblocks[key]
# roughly 30 frames per second
self.loop_id = self.window.after(int(1000/30), self.loop)
def time_loop(self):
self.time -= 1
self.canvas.itemconfig(self.time_id, text=str(self.time))
self.time_loop_id = self.window.after(1000, self.time_loop)
def main():
game = Game()
game.window.mainloop()
main()
99 percent of computer problems exists between chair and keyboard.
Posts: 544
Threads: 15
Joined: Oct 2016
I perfer classes over function but here one without classes.
Here another example using function with some improvements and better tkinter code.
import tkinter as tk
from random import randint, choice
WIDTH = 1000
HEIGHT = 700
MID_X = WIDTH / 2
MID_Y = HEIGHT / 2
CHOICE = [1, 1, 1, 1] + [2 for n in range(150)] + [3, 4]
# globals
stop_game = 0
time_end = False
block_id = None
bonus_time = 0
# countdown
def time_loop(canvas, time_id, time):
global time_end, bonus_time
if bonus_time:
time += bonus_time
bonus_time = 0
time -= 1
if stop_game:
loop_stop(canvas)
return
if time < 0:
time_end = True
loop_stop(canvas)
return
canvas.itemconfig(time_id, text=str(time))
# 1000 milliseconds = 1 seconds
canvas.after(1000, time_loop, canvas, time_id, time)
def collide(canvas, box):
x, y, w, h = canvas.bbox(block_id)
return ( (((x > box[0]) and (x < box[2])) or
((box[0] > x) and (box[0] < w))) and
(((y > box[1]) and (y < box[3])) or
((box[1] > y) and (box[1] < h))))
def game_loop(canvas, score_id, score, yblocks):
global bonus_time
if time_end:
canvas.create_text(MID_X, MID_Y, text='GAME OVER', fill='white', font=('Helvetica',30))
canvas.create_text(MID_X, MID_Y + 30, text='Score: '+ str(score), fill='white')
# stop game_loop timer
loop_stop(canvas)
return
if stop_game:
loop_stop(canvas)
return
add_block = choice(CHOICE)
if add_block != 2 or len(yblocks) < 4:
value = randint(5, 10)
x = randint(value, WIDTH - value)
# pick a color from list.
color = [None, 'yellow', 'yellow', 'green', 'orange'][add_block]
square_id = canvas.create_rectangle(x - value, -value, x + value, value, outline=color)
if add_block == 4:
yblocks[square_id] = (value * 4, 7, 4)
elif add_block == 3:
yblocks[square_id] = (value + 1, 4, 3)
else:
yblocks[square_id] = (value, randint(1, 2), 1) # value of block , speed, block_choice
# remove block, collision , move block
remove_block = []
for item_id, values in yblocks.items():
box = canvas.bbox(item_id)
# move yellow block down
canvas.move(item_id, 0, values[1])
# yellow block off screen
if box[1] > HEIGHT:
remove_block.append(item_id)
# collision
else:
if(collide(canvas, box)):
remove_block.append(item_id)
score += values[0]
if values[2] == 3:
bonus_time += 2
canvas.itemconfig(score_id, text=str(score))
# remove yellow blocks
for key in remove_block:
canvas.delete(key)
del yblocks[key]
canvas.after(int(1000/30), game_loop, canvas, score_id, score, yblocks)
# stopping all loops
def loop_stop(canvas):
global stop_game
stop_game += 1
if stop_game == 3:
new_game(canvas)
def new_game(canvas):
global block_id, time_end, stop_game
stop_game = 0
time_end = False
# remove all items from canvas
canvas.delete('all')
canvas.create_text(50, 30, text='TIME', fill='white' )
canvas.create_text(150, 30, text='SCORE', fill='white' )
time_id = canvas.create_text(50, 50, fill='white' )
score_id = canvas.create_text(150, 50, fill='white', text='0')
block_id = canvas.create_rectangle(0, 0, 40, 40, fill='red')
canvas.move(block_id, MID_X, MID_Y)
# start timers
game_loop(canvas, score_id, 0, {})
time_loop(canvas, time_id, 31)
def main():
window = tk.Tk()
canvas = tk.Canvas(window, width=WIDTH, height=HEIGHT, bg='black')
canvas.pack()
new_game(canvas)
def keys_press(event):
speed = 15
if event.keysym == 'Up':
canvas.move(block_id, 0, -speed)
elif event.keysym == 'Down':
canvas.move(block_id, 0, speed)
elif event.keysym == 'Left':
canvas.move(block_id, -speed, 0)
elif event.keysym == 'Right':
canvas.move(block_id, speed, 0)
elif event.keysym == 'Escape':
window.destroy()
elif event.keysym == 'n':
loop_stop(canvas)
window.bind_all('<Key>', keys_press)
window.mainloop()
if __name__ == '__main__':
main()
99 percent of computer problems exists between chair and keyboard.
Posts: 544
Threads: 15
Joined: Oct 2016
Okay figure out keypress work smoothly. Enjoy.
import tkinter as tk
from random import randint, choice, shuffle
WIDTH = 1000
HEIGHT = 700
MID_X = WIDTH / 2
MID_Y = HEIGHT / 2
class FallingBlock:
CHOICE = [0,0,0,0,2,3] + [1 for n in range(170)]
def __init__(self, canvas, choice_id):
self.value = randint(5, 10)
x = randint(self.value + 1, WIDTH - self.value)
self.color_id = choice_id
color = ['yellow', 'yellow', 'green', 'orange'][self.color_id]
self.id = canvas.create_rectangle(x - self.value, -self.value, x + self.value, self.value, outline=color)
if self.color_id == 3:
self.speed = 8
self.value *= 5
elif self.color_id == 2:
self.speed = 4
self.value += 2
else:
self.speed = randint(1, 2)
def move(self, canvas):
canvas.move(self.id, 0, self.speed)
class Game:
def __init__(self):
self.window = tk.Tk()
self.canvas = tk.Canvas(self.window, width=WIDTH, height=HEIGHT, bg='black')
self.canvas.pack()
self.window.bind_all('<KeyPress>', self.keys_press)
self.window.bind_all('<KeyRelease>', self.keys_release)
self.speed = 10
self.loop_id = None
self.time_loop_id = None
self.new_game()
def new_game(self):
shuffle(FallingBlock.CHOICE)
self.falling_blocks = {}
self.keys = {}
self.score = 0
self.bonus = 0
self.time = 31
self.canvas.delete('all')
self.canvas.create_text(50, 30, text='TIME', fill='white' )
self.canvas.create_text(150, 30, text='SCORE', fill='white' )
self.time_id = self.canvas.create_text(50, 50, fill='white' )
self.score_id = self.canvas.create_text(150, 50, fill='white', text='0')
self.block_id = self.canvas.create_rectangle(0, 0, 40, 40, fill='red')
self.canvas.move(self.block_id, MID_X, MID_Y)
# stop timers
if self.time_loop_id:
self.window.after_cancel(self.time_loop_id)
if self.loop_id:
self.window.after_cancel(self.loop_id)
# start time loops
self.loop_id = None
self.time_loop_id = None
self.loop()
self.time_loop()
def keys_press(self, event):
if event.keysym in ['Up', 'Down', 'Left', 'Right']:
self.keys[event.keysym] = True
elif event.keysym == 'Escape':
self.window.destroy()
elif event.keysym == 'n':
self.new_game()
def keys_release(self, event):
if event.keysym in ['Up', 'Down', 'Left', 'Right']:
self.keys[event.keysym] = False
def collide(self, box):
x, y, w, h = self.canvas.bbox(self.block_id)
return ( (((x > box[0]) and (x < box[2])) or
((box[0] > x) and (box[0] < w))) and
(((y > box[1]) and (y < box[3])) or
((box[1] > y) and (box[1] < h))))
def loop(self):
if self.time < 0:
self.canvas.create_text(MID_X, MID_Y, text='GAME OVER', fill='white', font=('Helvetica',30))
self.canvas.create_text(MID_X, MID_Y + 30, text='Score: '+ str(self.score), fill='white')
# return for it can't assign another cycle
return
# Moving Player
if self.keys.get('Left', False):
self.canvas.move(self.block_id, -self.speed, 0)
if self.keys.get('Right', False):
self.canvas.move(self.block_id, self.speed, 0)
if self.keys.get('Up', False):
self.canvas.move(self.block_id, 0, -self.speed)
if self.keys.get('Down', False):
self.canvas.move(self.block_id, 0, self.speed)
falling_id = choice(FallingBlock.CHOICE)
if falling_id != 1 or len(self.falling_blocks) < 4:
fall_block = FallingBlock(self.canvas, falling_id)
self.falling_blocks[fall_block.id] = fall_block
blocks_remove = []
for item_id, block in self.falling_blocks.items():
box = self.canvas.bbox(item_id)
# move block
block.move(self.canvas)
# object fell offscreen
if box[1] > HEIGHT + 1:
blocks_remove.append(item_id)
# collision
else:
if self.collide(box):
if block.color_id == 2:
self.time += 2
blocks_remove.append(item_id)
self.score += block.value
self.canvas.itemconfig(self.score_id, text=str(self.score))
for key in blocks_remove:
self.canvas.delete(key)
del self.falling_blocks[key]
# roughly 30 frames per second
self.loop_id = self.window.after(int(1000/30), self.loop)
def time_loop(self):
self.time -= 1
if self.time < 0:
return
self.canvas.itemconfig(self.time_id, text=str(self.time))
self.time_loop_id = self.window.after(1000, self.time_loop)
def main():
game = Game()
game.window.mainloop()
main()
99 percent of computer problems exists between chair and keyboard.
Posts: 21
Threads: 3
Joined: Oct 2017
Dec-07-2017, 12:48 AM
(This post was last modified: Dec-07-2017, 12:49 AM by hammza.)
|