Как заставить черепашку Python распознавать, когда я щелкаю фон? - PullRequest
0 голосов
/ 09 июня 2018

Я пытаюсь создать игру, в которой вы выбираете несколько случайных кругов и получаете счет, однако я также хочу, чтобы он вычитался из вашего счета, когда вы пропускаете круг.Я пытался использовать screen.onclick(), но вместо того, чтобы вычитать счет по ошибке, кажется, что он вычитает счет каждую секунду без причины.Что я делаю не так?

import turtle
from random import random, randint
import time

CURSOR_SIZE = 20
score=0

def addscore():
    global score
    score += 1

def deletescore():
    global score
    score -= 1

def my_circle(color):

    radius = (15)

    circle = turtle.Turtle('circle', visible=False)
    circle.shapesize(radius / CURSOR_SIZE)
    circle.color(color)
    circle.penup()

    while True:
        nx = randint(2 * radius - width // 2, width // 2 - radius * 2)
        ny = randint(2 * radius - height // 2, height // 2 - radius * 2)

        circle.goto(nx, ny)

        for other_radius, other_circle in circles:
            if circle.distance(other_circle) < 2 * max(radius, other_radius):
                break
        else:
            break

    circle.showturtle()
    circle.onclick(lambda x,y,t=circle: (circle.hideturtle(), addscore()))
    screen.onclick(deletescore())


    return radius, circle

username=str(input("Set your username: "))

screen = turtle.Screen()
screen.bgcolor("lightgreen")
screen.title("Speed Clicker")

width, height = screen.window_width(), screen.window_height()

circles = []

gameLength = 30
difficulty = 20
startTime = time.time()
while True:
    time.sleep(1/difficulty)

    rgb = (random(), random(), random())

    timeTaken = time.time() - startTime

    circles.append(my_circle(rgb))
    screen.title('SCORE: {}, TIME LEFT: {}'.format(score,int(round(gameLength - timeTaken,0))))

    if time.time() - startTime > gameLength: 
        break

screen.title('GG! FINAL SCORE: {}'.format(score))


screen.mainloop()

1 Ответ

0 голосов
/ 09 июня 2018

Проблема в этой строке:

screen.onclick(deletescore())

Она не в том месте (нужно вызывать только один раз, а не в цикле), а аргумент неверен, он должен передавать функцию, не вызывающуюit:

screen.onclick(deletescore)

Исправление является многократным: сначала переместите измененный оператор непосредственно перед вашим оператором while True:.Затем исправьте определение deletescore(), чтобы принимать x и y аргументы, которые мы не будем использовать, но которые необходимы для обработки кликов.(Или оберните его в lambda, как при вызове addscore())

Однако щелчок на черепахе также можно пропустить как щелчок на экране.Чтобы противостоять этому, мы можем добавить 2 в addscore() вместо 1, так как deletescore() также будет вызываться.Этого должно быть достаточно, чтобы все заработало.

Однако мы действительно должны исключить цикл while True: и вызов sleep(), которые не имеют места в программе, управляемой событиями.Вместо этого мы используем ontimer(), чтобы держать вещи в движении и не блокировать другие события.Переформулированный кодекс будет больше похож на:

from turtle import Turtle, Screen
from random import random, randint
from time import time

CURSOR_SIZE = 20

def addscore():
    global score
    score += 2  # add 2 as this will also count as a -1 screen click!

def deletescore():
    global score
    score -= 1

def my_circle(color):

    circle = Turtle('circle', visible=False)
    circle.shapesize(radius / CURSOR_SIZE)
    circle.color(color)
    circle.penup()

    while True:
        nx = randint(2 * radius - width // 2, width // 2 - radius * 2)
        ny = randint(2 * radius - height // 2, height // 2 - radius * 2)

        circle.goto(nx, ny)

        for other_radius, other_circle in circles:
            if circle.distance(other_circle) < 2 * max(radius, other_radius):
                break
        else:
            break

    circle.onclick(lambda x, y: (circle.hideturtle(), addscore()))
    circle.showturtle()

    return radius, circle

def play():
    rgb = (random(), random(), random())

    timeTaken = time() - startTime

    circles.append(my_circle(rgb))

    screen.title('SCORE: {}, TIME LEFT: {}'.format(score, int(round(gameLength - timeTaken, 0))))

    if time() - startTime > gameLength:
        screen.title('FINAL SCORE: {}'.format(score))
        screen.onclick(None)
        screen.clear()
    else:
        screen.ontimer(play, 1000 // difficulty)

screen = Screen()
screen.bgcolor("lightgreen")
screen.title("Speed Clicker")

width, height = screen.window_width(), screen.window_height()

score = 0

circles = []

radius = 15
difficulty = 20
gameLength = 30

screen.onclick(lambda x, y: deletescore())

startTime = time()

play()

screen.mainloop()
...