0

I am creating a clicker game, very similar to cookie clicker. My question is, how do I increase a variable by an amount every second?

Here, prepare for a new game.

def new(self):
    # set cookies/multipliers for a new game
    self.cookie_count = 0
    self.grandma = 10 # grandma bakes 10 cookies/second

Then, if a grandma is purchased, add 10 cookies/second to self.cookie_count for every grandma purchased. Example: If 2 grandmas are purchased, self.cookie_count += 20 cookies/second. Yet, as I have it now, everytime I purchase a grandma I just get 10 cookies.

if self.rect2.collidepoint(self.mouse_pos) and self.pressed1:
   self.cookie_count += self.grandma

I know that it has something to do with time, but other than that I'm not quite sure where to start.

martineau
  • 119,623
  • 25
  • 170
  • 301
Josh Parkinsons
  • 33
  • 1
  • 2
  • 4

3 Answers3

1

Instead of incrementing the cookies once per second, you can make the cookie count just how many seconds have passed since the start. This may cause problem in certain scenarios (this will complicate pausing, for example), but will work for simple games.

My Python is a tad rusty, so sorry if this isn't entirely idiomatic:

import time

self.start_time = time.time()

# When you need to know how many cookies you have, subtract the current time
#  from the start time, which gives you how much time has passed
# If you get 1 cookie a second, the elapsed time will be your number of cookies
# "raw" because this is the number cookies before Grandma's boost 
self.raw_cookies = time.time() - self.start_time

if self.grandma:
    self.cookies += self.raw_cookies * self.grandma

else:
    self.cookies += raw.cookies

self.raw_cookies = 0

This may look more complicated than just using time.sleep, but it has two advantages:

  1. Using sleep in games is rarely a good idea. If you sleep on the animation thread, you'll freeze the entire program for the duration of the sleep, which is obviously not a good thing. Even if that's not an issue in simple games, the use of sleep should be limited for habit's sake. sleep should really only be used in tests and simple toys.

  2. sleep isn't 100% accurate. Over time, the error of the sleep time will accumulate. Whether or not this is a problem though is entirely dependant on the application. By just subtracting the time, you know exactly (or at least with high precision) how much time has passed.

Note:

  1. With the code above, cookies will be a floating point number, not an integer. This will be more accurate, but may not look nice when you display it. Convert it to an integer/round it before displaying it.

  2. Having never player "Cookie Clicker" before, I may have confused the logic. Correct me if something doesn't make sense.

  3. I'm assuming self.grandma is None/falsey if the player doesn't have the upgrade.

Carcigenicate
  • 43,494
  • 9
  • 68
  • 117
1

The way to do this in pygame is to use pygame.time.set_timer() and have an event generated every given number of milliseconds. This will allow the event to be handled in the script's main loop like any other.

Here's a somewhat boring, but runnable, example of doing something like that:

import pygame

pygame.init()

SIZE = WIDTH, HEIGHT = 720, 480
FPS = 60
BLACK = (0,0,0)
WHITE = (255,255,255)
GREEN = (0,255,0)
RED = (255,0,0)
BLUE = (0,0,255)
BACKGROUND_COLOR = pygame.Color('white')

screen = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()
font = pygame.font.SysFont('', 30)

COOKIE_EVENT = pygame.USEREVENT
pygame.time.set_timer(COOKIE_EVENT, 1000)  # periodically create COOKIE_EVENT

class Player(pygame.sprite.Sprite):

    def __init__(self, position):
        super(Player, self).__init__()

        self.cookie_count = 0
        self.grandma = 10 # grandma bakes 10 cookies/second

        text = font.render(str(self.cookie_count), True, RED, BLACK)
        self.image = text

        self.rect = self.image.get_rect(topleft=position)

        self.position = pygame.math.Vector2(position)
        self.velocity = pygame.math.Vector2(0, 0)
        self.speed = 3

    def update_cookies(self):
        self.cookie_count += self.grandma  # 10 cookies per grandma
        if self.cookie_count > 499:
            self.cookie_count = 0
        text = font.render(str(self.cookie_count), True, RED, BLACK)
        self.image = text

player = Player(position=(350, 220))

running = True
while running:

    clock.tick(FPS)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == COOKIE_EVENT:
            player.update_cookies()

        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            player.velocity.x = -player.speed
        elif keys[pygame.K_RIGHT]:
            player.velocity.x = player.speed
        else:
            player.velocity.x = 0

        if keys[pygame.K_UP]:
            player.velocity.y = -player.speed
        elif keys[pygame.K_DOWN]:
            player.velocity.y = player.speed
        else:
            player.velocity.y = 0

        player.position += player.velocity
        player.rect.topleft = player.position

    screen.fill(BACKGROUND_COLOR)
    screen.blit(player.image, player.rect)

    pygame.display.update()
martineau
  • 119,623
  • 25
  • 170
  • 301
0

You'll need to use time module. You can capture period of time with time.time().

import time

grandma = 3
cookie_count = 0
timeout = 1

while True:
    cookie_count += grandma * 10
    print 'cookie count: {}'.format(cookie_count)
    time.sleep(timeout)

Another option is to validate the expression now - start > timeout. They will both do the same, but incase your timeout is larger than 1 this would be the solution. The first code above won't work.

import time

grandma = 3
cookie_count = 0
timeout = 1
start = time.time()

while True:
    if time.time() - start > timeout:    
        cookie_count += grandma * 10
        print 'cookie count: {}'.format(cookie_count)
        time.sleep(timeout)
Chen A.
  • 10,140
  • 3
  • 42
  • 61