Python Forum
Need help fixing Time and Score issues
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Need help fixing Time and Score issues
#1
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')
Reply
#2
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.
Reply
#3
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.
Reply
#4
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.
Reply
#5
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.
Reply
#6
Perfect
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Time limit and Score not working Coding help Kingrocket10 1 2,880 Nov-09-2017, 03:20 PM
Last Post: heiner55

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020