1

This is a cookie clicker game I have been working on in python with turtle:

import turtle

clicks = 0
num = 1


def main():
    screen = turtle.Screen()
    screen.title("Cookie Clicker by Homare and Jonathan")
    screen.bgcolor("#189df5")

    # Cookie
    cookie = turtle.Turtle()
    screen.addshape("cookie.gif")
    cookie.shape("cookie.gif")
    cookie.penup()
    cookie.backward(200)
    cookie.speed(0)

    # Upgrade 1 Button + draw
    upgrade = turtle.Turtle()
    upgrade.hideturtle()
    upgrade.speed(0)
    upgrade.penup()
    upgrade.goto(7, 94)
    upgrade.pendown()
    upgrade.fillcolor('white')
    upgrade.begin_fill()

    for i in range(2):
        upgrade.forward(340)
        upgrade.left(90)
        upgrade.forward(30)
        upgrade.left(90)

    upgrade.end_fill()

    upgrade.penup()
    upgrade.goto(7, 94)
    upgrade.write("+1 Cookie/Click: 15 Cookies", font=("Courier", 20, "normal"))



    # Upgrade 2 Button + draw
    upgrade2 = turtle.Turtle()
    upgrade2.hideturtle()
    upgrade2.speed(0)
    upgrade2.penup()
    upgrade2.goto(7, 54)
    upgrade2.pendown()
    upgrade2.fillcolor('white')
    upgrade2.begin_fill()

    for i in range(2):
        upgrade2.forward(340)
        upgrade2.left(90)
        upgrade2.forward(30)
        upgrade2.left(90)

    upgrade2.end_fill()

    upgrade2.penup()
    upgrade2.goto(7, 54)
    upgrade2.write("x2 Cookie/Click: 100 Cookies", font=("Courier", 20, "normal"))

    # Written Click Text
    write_text(0, 200, f"Cookies: {clicks}")

    cookie.onclick(clicked)

    turtle.onscreenclick(up2click, 1)
    turtle.onscreenclick(upgradeclick, 1)
    turtle.listen()

    screen.mainloop()


def upgradeclick(x, y):
    global clicks
    global num
    if clicks >= 15:
        if x > 0 and x < 341 and y > 94 and y < 124:
            clicks -= 15
            num += 1
            counter.clear()
            write_text(0, 200, f"Cookies: {clicks}")


def up2click(x, y):
    global clicks
    global num
    if clicks >= 100:
        if x > 0 and x < 341 and y > 54 and y < 84:
            clicks -= 100
            num *= 2
            counter.clear()
            write_text(0, 200, f"Cookies: {clicks}")



def clicked(x, y):
    global clicks
    global num
    clicks += num
    counter.clear()
    write_text(0, 200, f"Cookies: {clicks}")
    print(clicks)


def write_text(center_x, center_y, text):
    ''' Write text on the Screen '''
    counter.speed(0)
    counter.penup()
    counter.hideturtle()
    counter.goto(center_x, center_y)
    counter.write(text, align="center", font=("Courier New", 32, "normal"))


counter = turtle.Turtle()

main()

When I run it, only the first upgrade (+1 cookie/click) works when I click on it, but when I click the second upgrade (x2 cookie/click), nothing seems to happen. What's supposed to happen is that 100 cookies get subtracted, then the cookies per click multiply by two, such as if you had 50 cookies per click it would multiply to 100 cookies per click.

It probably won't work because you don't have the cookie.gif, but I will try to post it on here. Just download a cookie gif and put it inside the same directory. Don't forget to change the name. Here is the video I used to put the cookie image in.

https://www.youtube.com/watch?v=jXx3acg34S0

ggorlen
  • 44,755
  • 7
  • 76
  • 106
John_x
  • 11
  • 1
  • seems one problem might be related to the click event only happens when clicking on the `cookie.gif` image. are you expecting the click values to change when cliking on the white `+1` and `x2` texts ? if so , then the click event need to be assigned to those two white text locations, not the `cookie.gif` – chickity china chinese chicken Jan 17 '23 at 04:03
  • Why was this tagged [tag:java]? – ggorlen Jan 17 '23 at 23:33

1 Answers1

0

Here's the relevant code:

turtle.onscreenclick(up2click, 1)
turtle.onscreenclick(upgradeclick, 1)

You can only have one handler for onscreenclick, so this won't work. Try creating a minimal example to test the hypothesis:

import turtle

turtle.onscreenclick(lambda _, __: print("A"))
turtle.onscreenclick(lambda _, __: print("B"))
turtle.listen()
turtle.mainloop()

You'll see that when you click the screen, the console logs B only.

Anyway, these onscreenclicks set listeners on the whole screen, but it seems you want the text to be clickable as a button. There are two approaches:

  1. Use some_turtle.onclick to register a click handler for that turtle. Unfortunately, turtles overlap any text they've written, so they're a z-layering problem that makes this approach tricky for buttons with text. Workarounds include baking the text into an image gif, then setting the image as the turtle shape, or putting the button text outside the image.
  2. Use one onscreenclick and test coordinates to determine which button, if any, is being clicked.

Simple examples of these patterns exist elsewhere on the site:

But here's another example with a bit of reusable abstraction which you can modify for your button-based UI:

from collections import namedtuple
import turtle

turtle.tracer(0)

def add_button(x, y, w, h, text, click_handler):
    Button = namedtuple("Button", "turtle has_point handle_click")
    t = turtle.Turtle()
    t.hideturtle()
    t.penup()
    t.goto(x, y)
    t.pendown()

    for _ in range(2):
        t.forward(w)
        t.left(90)
        t.forward(h)
        t.left(90)

    t.penup()
    t.forward(w / 2)
    t.left(90)
    t.forward(h * 0.25)
    t.write(text, align="center")
    return Button(
        turtle=t,
        has_point=lambda cx, cy: (
            cx >= x and cx < x + w and cy >= y and cy < y + h
        ),
        handle_click=click_handler
    )

buttons = (
    add_button(-30, 0, 50, 25, "foo", lambda x, y: print("foo")),
    add_button(30, 0, 50, 25, "bar", lambda x, y: print("bar")),
    add_button(-30, -50, 50, 25, "baz", lambda x, y: print("baz")),
    add_button(30, -50, 50, 25, "quux", lambda x, y: print("quux")),
    add_button(100, 50, 50, 25, "quit", lambda x, y: turtle.bye()),
)

def handle_screen_click(x, y):
    for b in buttons:
        if b.has_point(x, y):
            b.handle_click(x, y)

turtle.onscreenclick(handle_screen_click)
turtle.listen()
turtle.mainloop()

If you want to add hovering on your buttons, check out turtle - How to get mouse cursor position in window?.

Many things that may seem easy in turtle often turn out to be pretty difficult.

ggorlen
  • 44,755
  • 7
  • 76
  • 106