I'm creating a Snake game. When I lower the cooldown of the Timer I want the snake to move faster.
It's actually working, but only if I change the number of the game speed before starting the project. If I start the project and change the timer in game, by a function, then var for the timer gets lower (printed it in different situations) but the speed doesn't change.
game_speed = 100
SCRREEN_UPDATE = pygame.USEREVENT
pygame.time.set_timer(SCRREEN_UPDATE, game_speed)
while go:
events = pygame.event.get()
if not game_over:
screen.fill((0,90,10))
snake.draw_grass()
for event in events:
main_game.Quit(event)
if event.type == SCRREEN_UPDATE:
main_game.update()
self.list.append(self.user_input)
self.user_input = int(self.user_input)
if isinstance(self.user_input,str):
self.list = [0]
self.user_input = "0"
game_speed -= int(self.list[-1])
self.list = [0]
self.user_input = "0"
print(game_speed)
return game_speed
The timer event and the game_speed variable are not tied. The timer interval doesn't magically change when you change the value of game_speed. You have to restart the timer with the new interval. So after changing game_speed, pygame.time.set_timer needs to be called again:
game_speed -= int(self.list[-1])
pygame.time.set_timer(SCRREEN_UPDATE, game_speed)
Related
I can't figure out how to move sideways and jump at the same time, only one or the other.
I have tried asyncio and multithreading/multiprocessing and couldn't get it to work. I am all out of ideas and can't find anymore online. I also have another issue where I can jump and if I reach the apex of the jump and hold a or d I can move side to side floating.
class Player():
def __init__(self,health,boosts,height,width):
self.health = health
self.booosts = boosts
self.height = height
self.width = width
def jump():
global gravtest, press
press.remove("'w'")
gravtest = False
y = player[0].ycor()
for i in range (1, 10):
player[0].sety(y+(i*5))
time.sleep(0.05)
#while player[0]
gravtest = True
# def powers(self, boosts):
import turtle as t
import time, random
from pynput.keyboard import Key, Listener
t.ht()
press = []
gravtest = True
wn = t.Screen()
wn.title("Jump Man")
wn.bgcolor("white")
wn.screensize(250, 250)
wn.setup(width=1.0, height=1.0)
player = [t.Turtle(), Player(100, [], 25, 25)]
player[0].speed(0)
player[0].shapesize(0.5)
player[0].shape("square")
player[0].color("black")
player[0].up()
player[0].goto(0, 0)
floor = t.Turtle()
floor.speed(0)
floor.shape("square")
floor.shapesize(100)
floor.color("black")
floor.up()
floor.goto(0, -1150)
def gravity():
global gravtest
if gravtest == True:
grav = 0
while player[0].distance(floor) > 1007:
y = player[0].ycor()
player[0].sety(y + grav)
if grav > -5:
grav -= 1
player[0].sety(y + grav)
gravtest = False
if player[0].distance(floor) < 1045:
player[0].sety(-145)
def show(key):
global press
if not(format(key) in press):
press.append(format(key))
print(key)
def rem(key):
global press
if format(key) in press:
press.remove(format(key))
def move():
global press
while "'a'" in press:
player[0].setx(player[0].xcor()-2)
while "'d'" in press:
player[0].setx(player[0].xcor()+2)
if press == '\'s\'':
print()
gravity()
if "'w'" in press:
jump()
with Listener(on_press = show, on_release = rem) as listener:
while 1:
move()
Your problem with moving and jumping is that you have separate loops for each that try to handle one kind of movement of the movement in one place. That won't work properly if other stuff (like jumping while moving, or moving while falling under gravity) are supposed to be possible.
Instead, you need to have just one main loop. On each run of that loop, you should do one frame worth of movement of whatever kinds is appropriate (e.g. moving horizontally, falling or jumping). This may require some bookkeeping to keep track of how long the vertical acceleration from a jump lasts.
I'd make the main loop something like this:
on_the_ground = True
jumping = False
while True:
horizontal_movement() # this is always possible if the buttons are pressed
if on_the_ground or jumping:
jump() # can start or continue a jump if a button is pressed
else:
gravity() # fall, if you're not grounded or accelerating in a jump
handle_collisions_etc()
time.sleep(1/FRAMERATE)
Note, I've made some assumptions about the game logic you want. If you don't want to be able to move horizontally while in the air (as you can in many platformer games), you'll need to change this a little bit.
The jump function will need to keep track of how long you've been jumping for, since you probably want the player to be limited in how high they can go. I'm not exactly sure I understand the logic of your current code, so I'll leave it up to you to figure out exactly what to track.
A final suggestion is to move some of the global variables into the Player class. Even the turtle object you're using to draw things could be stored as an attribute on the instance you create.
import sys
import pygame
from pygame.locals import *
pygame.init()
class Game:
def __init__(self):
self.width = 800
self.height = 900
self.win = pygame.display.set_mode([self.width, self.height])
self.caption = pygame.display.set_caption('Clicker Game','Game')
self.money = 0
self.moneyperclick = 0
def moneytracker(self):
self.money = self.money + self.moneyperclick
print(self.money)
def mousestuff(self):
self.mousepos = pygame.mouse.get_pos()
self.clicked = pygame.mouse.get_pressed()
def mainloop(self):
self.mousestuff()
for event in pygame.event.get():
if event.type == MOUSEBUTTONDOWN:
self.moneytracker()
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
while True:
Game().mainloop()
I'm still somewhat new to coding but I am very confused as to why the self.money variable isn't updating even though I call for it to update. I've done some tests and I know that it is looping the code where I set self.money = 0 but I don't know how to get around this. Thanks
It looks like the problem is here:
while True:
Game().mainloop()
This creates a new Game object in every iteration of the loop, which means all the values are initialized for the first time, because it's a new object.
Alternatives are to move the while True loop inside mainloop(), or try something like:
game = Game()
while True:
game.mainloop()
This creates a single Game object as game, whose mainloop() method is called repeatedly. Because the object is only created once, the attributes of the object (e.g. money, accessed as self.money) that are modified as a result of player actions will keep their values between iterations of the loop.
In the original loop structure, a new Game object was created each time, which means that a player's actions were only performed once before the object was abandoned and replaced by a new one, with newly initialized attributes.
This question already has answers here:
Countdown timer in Pygame
(8 answers)
How do I use a PyGame timer event? How to add a clock to a pygame screen using a timer?
(1 answer)
Closed 2 years ago.
I am attempting to make the dino jump, but when I use time.sleep(0.1) in between the dino jumping and falling, the whole game stops for 0.1 seconds.
I have tried using time.sleep and that's it as I can't find any other useful info online.
def jump():
dino.y -= 100
time.sleep(0.1)
dino.y += 100
def on_key_up(key):
jump()
When I press the up arrow, the entire game freezes for 0.1 seconds.
I recommend to use a timer event. When the player jumps, then start a timer by pygame.time.set_timer(). When the timer event occurs, then finish the jump:
jump_delay = 100 # 100 milliseconds == 0.1 seconds
jump_event = pygame.USEREVENT + 1
def jump():
dino.y -= 100
# start a timer event which just appear once in 0.1 seconds
pygame.time.set_timer(jump_event, jump_delay, True)
def on_key_up(key):
jump()
# event loop
for event in pygame.event.get():
# jump timer event
if event.type == jump_event:
dino.y += 100
# [...]
Note, in pygame customer events can be defined. Each event needs a unique id. The ids for the user events have to start at pygame.USEREVENT. In this case pygame.USEREVENT+1 is the event id for the timer event, which finishes the jump.
Pygame is not Pygame Zero.
Anyway, if you use Pygame Zero, then you can use the elapsed time parameter of the update callback:
def uptate(dt):
The elapsed time parameter (dt) give the time which is passed since the lat frame in seconds.
Create a state (jump) which indicates if the dino is jumping. And a time (jump_time), which states how long the jump has to be continued:
jump = False
jump_time = 0.0
Set the state and the time in jump:
def jump():
global jump, jump_time
dino.y -= 100
jump = True
jump_time = 0.1 # 0.1 seconds
Decrement the time in update and finish the jump respectively rest the jump state, if the jump_time is less than 0.0:
def uptate(dt):
if jump:
jump_time -= dt
if jump_time < 0:
dino.y += 100
jump = False
I'm trying to create a program where balloons appear for the user to pop, however balloons are appearing so fast it becomes unmanageable. I took a screenshot about half a second into running the program:
Here is the code for time between balloons appearing:
timeTillNextBalloon = random.randint(100000, 200000)
while done == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if pygame.time.get_ticks() > timeTillNextBalloon:
timeTillNextBalloon = random.randint(30000, 250000)
yCoord = random.randint(50,350)
balloonType = random.randint(1,4)
balloon = Balloon(0, yCoord, "right", balloonType)
if balloonType >= 1 and balloonType <= 3:
otherBalloons.add(balloon)
else:
blueBalloons.add(balloon)
allBalloons.add(balloon)
I've tried to increase the timeTillNextBaloon variable, but it just shows a black screen if I try to make it any bigger than this.
Get_ticks gets the current time, timeTillNextBalloon should be the current to + the random value. Now every the loop repeats a balloon is added:
timeTillNextBalloon = pygame.time.get_ticks() + random.randint(30000, 250000)
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.
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:
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.
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:
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.
Having never player "Cookie Clicker" before, I may have confused the logic. Correct me if something doesn't make sense.
I'm assuming self.grandma is None/falsey if the player doesn't have the upgrade.
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()
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)