So, in my previous question, I received an answer that helped orient the platforms the way I wanted. However, there's a new issue that I cannot get around. How do make the platforms appear with sufficient space between them?
(press 1 to start the game)
# For the program, it was necessary to import the following.
import pygame, sys, random
import pygame.locals as GAME_GLOBALS
import pygame.event as GAME_EVENTS
import pygame.time as GAME_TIME
pygame.init() # To initialise the program, we need this command. Else nothing will get started.
StartImage = pygame.image.load("Assets/Start-Screen.png")
GameOverImage = pygame.image.load("Assets/Game-Over-Screen.png")
# Window details are here
windowWidth = 1000
windowHeight = 400
surface = pygame.display.set_mode((windowWidth, windowHeight))
pygame.display.set_caption('GAME NAME HERE')
oneDown = False
gameStarted = False
gameEnded = False
gamePlatforms = []
platformSpeed = 2
platformDelay = 2000
lastPlatform = 0
gameBeganAt = 0
timer = 0
player = {
"x": 10,
"y": 200,
"height": 25,
"width": 10,
"vy": 5
}
def drawingPlayer():
pygame.draw.rect(surface, (248, 255, 6), (player["x"], player["y"], player["width"], player["height"]))
def movingPlayer():
pressedKey = pygame.key.get_pressed()
if pressedKey[pygame.K_UP]:
player["y"] -= 5
elif pressedKey[pygame.K_DOWN]:
player["y"] += 5
def creatingPlatform():
global lastPlatform, platformDelay
platformX = windowWidth
gapPosition = random.randint(0, windowWidth)
verticalPosition = random.randint(0, windowHeight)
gamePlatforms.append({"pos": [platformX, verticalPosition], "gap": gapPosition}) # creating platforms
lastPlatform = GAME_TIME.get_ticks()
if platformDelay > 800:
platformDelay -= 50
def movingPlatform():
for idx, platform in enumerate(gamePlatforms):
platform["pos"][0] -= platformSpeed
if platform["pos"][0] < -10:
gamePlatforms.pop(idx)
def drawingPlatform():
global platform
for platform in gamePlatforms:
pygame.draw.rect(surface, (214, 200, 253), (platform["pos"][0], platform["pos"][1], 20, 80))
def gameOver():
global gameStarted, gameEnded, platformSpeed
platformSpeed = 0
gameStarted = False
gameEnded = True
def quitGame():
pygame.quit()
sys.exit()
def gameStart():
global gameStarted
gameStarted = True
while True:
surface.fill((95, 199, 250))
pressedKey = pygame.key.get_pressed()
for event in GAME_EVENTS.get():
if event.type == pygame.KEYDOWN:
# Event key for space should initiate sound toggle
if event.key == pygame.K_1:
oneDown = True
gameStart()
if event.type == pygame.KEYUP:
if event.key == pygame.K_1:
oneDown = False
#KEYUP for the space bar
if event.type == GAME_GLOBALS.QUIT:
quitGame()
if gameStarted is True:
drawingPlayer()
movingPlayer()
creatingPlatform()
movingPlatform()
drawingPlatform()
elif gameEnded is True:
surface.blit(GameOverImage, (0, 0))
else:
surface.blit(StartImage, (0, 0))
pygame.display.update()
I have tried increasing the value of the platformDelay variable, with no avail. I have also tried tinkering around with creatingPlatform(). No matter what I do, they always appear in clumps! I would like it to be a game where the platforms come towards the player in regular intervals so it's actually playable, but then the speed of the platforms approaching will increase over time to increase the difficulty of the game. How would I go about doing this? Thank you! :)
I recommend to use pygame.time.get_ticks() to get the number of milliseconds the program is running. Note, since the time is given in milliseconds, a value of 1000 would be 1 second.
Initialize a variable newPlatformTimePoint by 0 and define an interval between an interval in which new platforms appear
newPlatformTimePoint = 0
newPlatformInterval = 200 # 0.2 seconds
When the game was startedGet the current time point in the main loop and set the time point for the first platform when the game was started:
timePoint = pygame.time.get_ticks()
if event.key == pygame.K_1:
oneDown = True
gameStart()
newPlatformTimePoint = timePoint + 1000 # 1 second after start
Add a new platform when the time point exceeded and increment set the next time point, by incrementing it by newPlatformInterval. Not the interval can be changed (speeded up) during the game.
if gameStarted is True:
drawingPlayer()
movingPlayer()
if timePoint > newPlatformTimePoint:
newPlatformTimePoint = timePoint + newPlatformInterval
creatingPlatform()
movingPlatform()
drawingPlatform()
Main loop code, with the applied suggestions:
newPlatformTimePoint = 0
newPlatformInterval = 200 # 0.2 seconds
while True:
timePoint = pygame.time.get_ticks()
surface.fill((95, 199, 250))
pressedKey = pygame.key.get_pressed()
for event in GAME_EVENTS.get():
if event.type == pygame.KEYDOWN:
# Event key for space should initiate sound toggle
if event.key == pygame.K_1:
oneDown = True
gameStart()
newPlatformTimePoint = timePoint + 1000 # 1 second after start
if event.type == pygame.KEYUP:
if event.key == pygame.K_1:
oneDown = False
#KEYUP for the space bar
if event.type == GAME_GLOBALS.QUIT:
quitGame()
if gameStarted is True:
drawingPlayer()
movingPlayer()
if timePoint > newPlatformTimePoint:
newPlatformTimePoint = timePoint + newPlatformInterval
creatingPlatform()
movingPlatform()
drawingPlatform()
elif gameEnded is True:
surface.blit(GameOverImage, (0, 0))
else:
surface.blit(StartImage, (0, 0))
pygame.display.update()
Related
im building a game in pygame in which a hot air balloon is constantly going up and spikes are coming down and hot air balloon has to dodge them. However i dont know how to randomly generate nicely spaced spikes which constantly moving downwards im having issue with randomly generating downward moving spikes.
here is the code:
import pygame
import random
import math
pygame.init()
clock = pygame.time.Clock()
screenwid = 400
screenhigh = 500
screen = pygame.display.set_mode((screenwid, screenhigh))
grey = (240,240,240)
black = (0,0,0)
initvel = 3
player_x = 100
player_y = 250
spikex= -100
spikey = -100
xchange = 0
ychange = 0
baloon = pygame.image.load('C:/Users/aliab/Downloads/hotair balloom.png')
baloon = pygame.transform.scale(baloon,(300, 300))
spike = pygame.image.load('C:/Users/aliab/Downloads/spikes.png')
spike = pygame.transform.scale(spike,(300, 300))
bg = pygame.image.load('E:/bgparacute.jpg')
def balloon(x,y):
screen.blit(baloon,(x,y ))
def spikee(x,y):
screen.blit(spike,(x,y ))
y = 0
run = True
while run:
rel_y = y % bg.get_rect().height
screen.blit(bg,(0,rel_y - bg.get_rect().height))
if rel_y < screenhigh:
screen.blit(bg, (0, rel_y))
y +=1
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
xchange = -initvel
ychange = 0
if event.key == pygame.K_RIGHT:
xchange = initvel
ychange = 0
if event.key == pygame.K_UP:
ychange = -initvel
xchange = 0
if event.key == pygame.K_DOWN:
ychange = initvel
xchange = 0
if spikey == 100:
print('hihiohug')
spikex = random.randint(0, 400)
spikey = random.randint(-20, 10)
spikey += 2
player_x += xchange
player_y += ychange
balloon(player_x,player_y)
spikee(spikex, spikey)
clock.tick(60)
pygame.display.update()
pygame.quit()
I tried out your program. If you are looking to only have a few spikes on your screen, theoretically, you could just individually define the spikes and then randomly generate their starting position as in your code with some simple tweaks.
import pygame
import random
import math
pygame.init()
clock = pygame.time.Clock()
screenwid = 400
screenhigh = 500
screen = pygame.display.set_mode((screenwid, screenhigh))
grey = (240,240,240)
black = (0,0,0)
initvel = 2
player_x = 100
player_y = 250
spikex1 = -100
spikey1 = -100
spikex2 = -40
spikey2 = -100
xchange = 0
ychange = 0
baloon = pygame.image.load('Balloon.png')
baloon = pygame.transform.scale(baloon,(240, 240))
spike1 = pygame.image.load('Mine.png') # Multiple spike definitions (very simplistic)
spike1 = pygame.transform.scale(spike1,(30, 30))
spike2 = pygame.image.load('Mine.png')
spike2 = pygame.transform.scale(spike2,(30, 30))
bg = pygame.image.load('background-day.png')
def balloon(x,y):
screen.blit(baloon,(x,y ))
def spikee(x,y):
screen.blit(spike1,(x,y ))
screen.blit(spike2,(x,y ))
y = 0
run = True
while run:
rel_y = y % bg.get_rect().height
screen.blit(bg,(0,rel_y - bg.get_rect().height))
if rel_y < screenhigh:
screen.blit(bg, (0, rel_y))
y +=1
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
xchange = -initvel
ychange = 0
if event.key == pygame.K_RIGHT:
xchange = initvel
ychange = 0
if event.key == pygame.K_UP:
ychange = -initvel
xchange = 0
if event.key == pygame.K_DOWN:
ychange = initvel
xchange = 0
if event.type == pygame.KEYUP: # Allow for a little more control of the balloon
xchange = 0
ychange = 0
if spikey1 == 280:
print('hihiohug')
spikex1 = random.randint(0, 300)
spikey1 = random.randint(-100, 10) # Adjust the random start above the screen for the spike
if spikey2 == 280:
print('hihiohug')
spikex2 = random.randint(0, 300)
spikey2 = random.randint(-100, 10) # Adjust the random start above the screen for the spike
spikey1 += 1
spikey2 += 1
player_x += xchange
player_y += ychange
balloon(player_x,player_y)
spikee(spikex1, spikey1)
spikee(spikex2, spikey2)
clock.tick(60)
pygame.display.update()
pygame.quit()
This produced randomly generated spikes (mines in my test).
However, you might want to define an array of spikes that are randomly placed just off of the display. As an example of that, I am including a link to GitHub for you to pull down a simple game I call "Submarine".
Submarine Game
It is an arcade like game where the submarine tries to avoid hitting underwater mines. It effectively is running in a horizontal fashion as opposed to your vertical action, but the underlying premises are alike. It has an array set up for storing underwater mine images that then appear on the screen.
Give that a try and see if that moves you forward in your game.
I've been trying to make a Chrome Dino Game, however, I'm struggling with this problem:
On every frame, it should draw a new one at the new position and delete the previous one to make it look as if it's moving. HOWEVER, it remains at its previous position and a new image appears on its next position. I did write the pygame.display.update() code at the end of my maintop.
In the last time I ran into a similar problem, I managed to make it work by drawing a background image, but this time, it doesn't work.
following are my codes:
import pygame
import os
from random import randint
import schedule
pygame.init()
assets = os.path.join(os.path.dirname(__file__), "Assets")
screen_size = (screen_width, screen_height) = (1280, 720)
screen = pygame.display.set_mode(screen_size)
clock = pygame.time.Clock()
fps = 120
bg = pygame.image.load(os.path.join(assets, "IMG_15.png"))
ground = 700
running = True
spacebaridx = 0
gamestart = False
tick_on_start = 0
obs1 = pygame.image.load(os.path.join(assets, "colourmat/light_green.png"))
pygame.transform.scale(obs1, (100, 200))
obs2 = pygame.image.load(os.path.join(assets, "colourmat/light_green.png"))
pygame.transform.scale(obs2, (120, 200))
obs3 = pygame.image.load(os.path.join(assets, "colourmat/light_green.png"))
pygame.transform.scale(obs3, (150, 200))
ls_obs = []
def create_obs():
k = randint(1, 3)
if k == 1:
info = {"type":1, "img":obs1, "x":screen_width, "y":ground - 200, "tox":2}
ls_obs.append(info)
if k == 2:
info = {"type":2, "img":obs2, "x":screen_width, "y":ground - 200, "tox":2}
ls_obs.append(info)
else:
info = {"type":3, "img":obs3, "x":screen_width, "y":ground - 200, "tox":2}
ls_obs.append(info)
schedule.every(3).seconds.do(create_obs)
while running:
dt = clock.tick(fps)
if gamestart == True:
game_ticks = pygame.time.get_ticks() - tick_on_start
schedule.run_pending()
else:
game_ticks = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT: running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if spacebaridx == 0: # Press space to start / to tell whether it's the first press
spacebaridx += 1
gamestart = True
tick_on_start = pygame.time.get_ticks()
else:
pass # Jump
for o in ls_obs:
o["x"] += o["tox"] * -1
screen.blit(bg, (0, 0))
for o in ls_obs:
screen.blit(o["img"], (o["x"], o["y"]))
pygame.display.update()
pygame.quit()
This issue is occurring because you aren't clearing the display within each frame. In pygame, in order to clear the display, we need to use the fill method. So in your code, at the top of your game loop before the event loop, add screen.fill((0, 0, 0)). This will fill your screen in the color black. Don't worry, the black won't be shown if you draw the background on top of it. Now, when you add a new image, the previous images won’t be displayed.
Modified Game Loop
while running:
screen.fill((0, 0, 0))
dt = clock.tick(fps)
if gamestart == True:
game_ticks = pygame.time.get_ticks() - tick_on_start
schedule.run_pending()
else:
game_ticks = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT: running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if spacebaridx == 0: # Press space to start / to tell whether it's the first press
spacebaridx += 1
gamestart = True
tick_on_start = pygame.time.get_ticks()
else:
pass # Jump
for o in ls_obs:
o["x"] += o["tox"] * -1
screen.blit(bg, (0, 0))
for o in ls_obs:
screen.blit(o["img"], (o["x"], o["y"]))
pygame.display.update()
pygame.quit()
I want to have my background alternate between night and day (sprites) every 15 seconds or so, but I want this to happen only while the game is running (True), I've placed it in every place in my while loop, can't seem to get it going. The code we're looking at is the following:
if event.type == BACKCHANGE:
screen.blit(back_change,(0,0))
else:
screen.blit(bg_image,(0,0))
Here's how it fits into my game:
import pygame, sys, time, random
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((500, 800))
pygame.display.set_caption('FALLING MAN')
#Game elements
gravity = 0.15
mov_of_man_x = 0
mov_of_man_y = 0
right_mov = 50
left_mov = 50
game_active = True
#day background
bg_image = pygame.image.load("/Users/apple/Downloads/Python Projects/Climbing_Game/bckwall.jpg").convert()
bg_image = pygame.transform.scale(bg_image,(500, 900))
#night background
bg_image2 = pygame.image.load("/Users/apple/Downloads/Python Projects/Climbing_Game/bckwall2.jpg").convert()
bg_image2 = pygame.transform.scale(bg_image2,(500, 900))
#background swap
back_changer = [bg_image, bg_image2]
back_change = random.choice(back_changer)
#the player
man = pygame.image.load("/Users/apple/Downloads/Python Projects/Climbing_Game/man.png").convert_alpha()
man = pygame.transform.scale(man, (51, 70))
man_rec = man.get_rect(center = (250, -500))
#the platforms player moves on
platform = pygame.image.load("/Users/apple/Downloads/Python Projects/Climbing_Game/platform.png").convert_alpha()
platform = pygame.transform.scale(platform,(300,60))
platform_rec = platform.get_rect(center = (250,730))
#game over screen
game_over_screen = pygame.image.load("/Users/apple/Downloads/Python Projects/Climbing_Game/End_screen.png").convert_alpha()
game_over_screen = pygame.transform.scale(game_over_screen,(500,800))
#moving platforms
def create_plat():
random_plat_pos = random.choice(plat_pos)
new_plat = platform.get_rect(center = (random_plat_pos, 800))
return new_plat
def mov_plat(plats):
for plat in plats:
plat.centery -= 4
return plats
def draw_plat(plats):
for plat in plats:
screen.blit(platform, plat)
#collison detection
def detect_plat(plats):
for plat in plats:
if man_rec.colliderect(plat):
global mov_of_man_y
mov_of_man_y = -4
return
def detect_man(mans):
for man in mans:
if man_rec.top <= -700 or man_rec.bottom >= 900:
return False
if man_rec.left <= -100 or man_rec.right >= 500:
return False
else:
return True
#score
def display_score():
pass
#moving platforms
plat_list = []
PLATMOV = pygame.USEREVENT
pygame.time.set_timer(PLATMOV, 1200)
plat_pos = [100,200,300,400]
#back change
BACKCHANGE = pygame.USEREVENT
pygame.time.set_timer(BACKCHANGE, 1200)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
mov_of_man_x += right_mov
man_rec.centerx += mov_of_man_x
mov_of_man_x -= 50
if event.key == pygame.K_LEFT:
mov_of_man_x += left_mov
man_rec.centerx -= mov_of_man_x
mov_of_man_x -= 50
if event.type == PLATMOV:
plat_list.append(create_plat())
#surfaces
screen.blit(bg_image,(0,0))
if game_active == True:
#gravity
mov_of_man_y += gravity
man_rec.centery += mov_of_man_y
#plats
plat_list = mov_plat(plat_list)
draw_plat(plat_list)
detect_plat(plat_list)
game_active = detect_man(man_rec)
#character
screen.blit(man, man_rec)
"""
if event.type == BACKCHANGE:
screen.blit(back_change,(0,0))
else:
screen.blit(bg_image,(0,0))
"""
else:
screen.blit(game_over_screen, (0,0))
pygame.display.update()
clock.tick(120)
Add a variable that indicates which background to draw:
bg_images = [bg_image, bg_image2]
bg_index = 0
Change the background index when the BACKCHANGE event occurs:
for event in pygame.event.get():
if event.type == BACKCHANGE:
bg_index += 1
if bg_index >= len(bg_images):
bg_index = 0
blit the current background in the application loop:
while True:
# [...]
screen.blit(bg_images[bg_index], (0,0))
# [...]
Application loop:
bg_images = [bg_image, bg_image2]
bg_index = 0
# [...]
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
# [...]
if event.type == pygame.KEYDOWN:
# [...]
if event.type == PLATMOV:
# [...]
if event.type == BACKCHANGE:
bg_index += 1
if bg_index >= len(bg_images):
bg_index = 0
if game_active == True:
screen.blit(bg_images[bg_index], (0,0))
# [...]
else:
screen.blit(game_over_screen, (0,0))
pygame.display.update()
clock.tick(120)
my code shows no errors but right now my flappy bird cosde should be printing the word pipe every 1.2 seconds but it does not i do not know how to fix it and have checked every word in my code and i haev even re written it onec can anyone please help me
code:
import pygame, sys
def draw_floor():
screen.blit(floor_surface, (floor_animation, 400))
screen.blit(floor_surface, (floor_animation + 275,400))
pygame.init()
screen = pygame.display.set_mode((275,512))
clock = pygame.time.Clock()
gravity = 0.25
bird_movement = 0
bg_surface = pygame.image.load('C:/Users/cuerv/Downloads/flappy-bird-assets-master/flappy-bird-assets-master/sprites/background-day.png').convert()
floor_surface = pygame.image.load('C:/Users/cuerv/Downloads/flappy-bird-assets-master/flappy-bird-assets-master/sprites/base.png').convert()
floor_animation = 0
bird_surface = pygame.image.load('C:/Users/cuerv/Downloads/flappy-bird-assets-master/flappy-bird-assets-master/sprites/bluebird-midflap.png').convert()
bird_rect = bird_surface.get_rect(center = (100,256))
pipe_surface = pygame.image.load('C:/Users/cuerv/Downloads/flappy-bird-assets-master/flappy-bird-assets-master/sprites/pipe-green.png').convert()
pipe_list = []
SPAWNPIPE = pygame.USEREVENT
pygame.time.set_timer(SPAWNPIPE,1200)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bird_movement = 0
bird_movement -= 7
if event.type == SPAWNPIPE:
print("pipe")
screen.blit(bg_surface, (0, 0))
bird_movement += gravity
bird_rect.centery += bird_movement
screen.blit(bird_surface, (bird_rect))
floor_animation -= 1
draw_floor()
if floor_animation <= -275: #if floor = if the left surface is too to the left we are going to do soamething
floor_animation = 0
screen.blit(floor_surface, (floor_animation, 400))
pygame.display.update()
clock.tick(120)
This occurs because your check of the SPAWNPIPE event is within the check of the KEYDOWN event. This can be solved with the following:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
bird_movement = 0
bird_movement -= 7
if event.type == SPAWNPIPE:
print("pipe")
I am wondering why is it that when I execute the file,
the arrow control and movement of the left rectangle will not continuously move up or down, even though I am holding down on the arrow keys for a long time.
import pygame
black = ( 0, 0, 0)
white = ( 255, 255, 255)
green = ( 0, 255, 0)
red = ( 255, 0, 0)
pygame.init()
size = [700,500]
screen = pygame.display.set_mode(size)
fonto = pygame.font.SysFont("algerian", 100)
font = pygame.font.SysFont("algerian", 12)
text = fonto.render("Game Over", True, (0, 128, 10))
pygame.display.set_caption("Vasanths First Legit Game")
done = False
pygame.mouse.set_visible(0)
clock = pygame.time.Clock()
score = 1
rect_x = 50
rect_y = 50
rect_xp = 10
rect_yp = 10
rect_change_x = 10
rect_change_y = 10
rect_change_xp = 10
rect_change_yp = 3
while done == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done=True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN:
rect_yp = rect_change_yp+rect_yp
if event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN:
rect_yp = 0+rect_yp
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
rect_yp=-3+rect_yp
if event.key == pygame.K_RIGHT:
rect_yp=3+rect_yp
if event.key == pygame.K_UP:
rect_yp=-3+rect_yp
if event.key == pygame.K_DOWN:
rect_yp=3+rect_yp
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
rect_yp=0+rect_yp
if event.key == pygame.K_RIGHT:
rect_yp=0+rect_yp
if event.key == pygame.K_UP:
rect_yp=0+rect_yp
if event.key == pygame.K_DOWN:
rect_yp=0+rect_yp
pos = pygame.mouse.get_pos()
x = pos[0]
y = pos[1]
screen.fill(black)
pygame.draw.rect(screen,white,[rect_x,rect_y,10,10])
pygame.draw.rect(screen,green,[x,490,50,10])
pygame.draw.rect(screen,green,[10,rect_yp,10,50])
# Move the rectangle starting point
rect_x += rect_change_x
rect_y += rect_change_y
if rect_y == 0:
rect_change_x=rect_change_x*1
rect_change_y=rect_change_y*-1
if rect_y == 490:
if rect_x < x + 50 :
scoref = font.render(score, True, (0, 128, 0))
screen.blit(scoref,
(20 - scoref.get_width() // 10, 20 - scoref.get_height() // 10))
rect_change_x=rect_change_x*1
rect_change_y=rect_change_y*-1
if rect_x < x:
rect_change_y = 0
rect_change_x = 0
#dont do this , it will go bizzonkes
score = str(score)
score = int(score)
if rect_y == 490:
if rect_x < x + 50 :
if rect_change_x !=0:
if rect_change_y !=0:
score=int(score)
score = score + 1
score=str(score)
if rect_change_x == 0:
if rect_change_y == 0:
screen.blit(text,
(320 - text.get_width() // 2, 240 - text.get_height() // 2))
if rect_x == 700:
rect_change_x = rect_change_x*-1
rect_change_y = rect_change_y*1
if rect_x == 0:
rect_change_x = rect_change_x*0
rect_change_y = rect_change_y*0
if rect_y == 500:
rect_change_y = 0
rect_change_x = 0
screen.blit(text,
(320 - text.get_width() // 2, 240 - text.get_height() // 2))
score=str(score)
print(score)
score = str(score)
scoref = font.render(score, True, (0, 128, 0))
screen.blit(scoref,
(20 - scoref.get_width() // 10, 20 - scoref.get_height() // 10))
clock.tick(30)
pygame.display.flip()
pygame.quit ()
In pygame the input is handled in a event loop. There is a event queue, the system sends input from the keyboard, and by calling pygame.event.get() you get the first event in the queue. There are many types of events, the most popular being KEYUP and KEYDOWN.
The mistake that most beginner people make, is that they believe that when a button is pressed, a KEYDOWN event is sent the whole time. That is not needed, since if you press a button, it is pressed until you release it. So you need to have certain flags to see if a button is pressed.
The most popular way of doing this is by using a d = v*t equation. Since the speed is constant, we need to introduce a direction. So our equation would look like this:
distance_changed = direction * speed * time_change
In your event loop, you then change the direction:
1 if KEYDOWN-RIGHT
-1 if KEYDOWN-LEFT
0 if KEYUP-LEFTorRIGHT.
Now the question might pop up, why use time_change? Since, we cannot predict on which machines the program will work, the amount of times the loop will repeat will not be known.
If you take an old machine, the game will work much slower. So we measure the time taken from the last movement, so that it will not changed on different machines.
I have see that you use pygame.tick(30), which waits so that the time it took for the loop to finish was constant. The problem arises, when you run this at an older machine. The loop cannot speed up.
As a suggestion, you should divide you game into functions. It's much more readable, and you can use you code in different places. Also, your event loop, has to many ifs. Use elif since there is no point to check if RIGTH key was pressed if LEFT was already pressed.
This is how I handle it in one of my own Pygame projects:
class Inputs:
def __init__(self):
self.bindings = {"up": pygame.K_UP,
"down": pygame.K_DOWN,
"left": pygame.K_LEFT,
"right": pygame.K_RIGHT,
"lp": pygame.K_a,
"mp": pygame.K_s,
"hp": pygame.K_d,
"lk": pygame.K_z,
"mk": pygame.K_x,
"hk": pygame.K_c,
"pause": pygame.K_RETURN}
self.inputState = {"up": False,
"down": False,
"right": False,
"left": False,
"lp": False,
"mp": False,
"hp": False,
"lk": False,
"mk": False,
"hk": False,
"pause": False}
self.buffer = InputBuffer()
def lookupBinding(self, keyEntered):
for binding, keyBound in self.bindings.items():
if keyEntered == keyBound:
return binding
return "not found"
def getInputState(self, events):
for event in events:
if event.type == pygame.KEYDOWN:
binding = self.lookupBinding(event.key)
if binding != "not found":
newInput = Input()
newInput.inputName = binding
newInput.timeSinceInput = 0
self.buffer.push(newInput)
self.inputState[binding] = True
if event.type == pygame.KEYUP:
binding = self.lookupBinding(event.key)
if binding != "not found":
self.inputState[binding] = False
return self.inputState
I keep two dictionaries, one of in-game "commands", such as directions, to the pygame key, then another of those commands to a boolean representing the command's on/off state. By watching for KEYDOWN and KEYUP events, I can determine which mapped inputs are on and which are off.
EDIT: A benefit of this way method that I should mention is that it makes it very easy to change the key mapping later on, or even allow custom key-mappings. Your game logic only needs to rely on the basic inputs, such as a jump or move input, and won't need to change if the key-mappings change.
I would use pygame.key.get_pressed(), but you are also forgetting pygame.key.set_repeat(). The first argument is the # of milliseconds it takes to start repeating, and the second is the interval at which the key repeats.
This is an example which uses both:
x = 400
y = 300
import pygame, sys
bkg = (255, 211, 0)
clr = (0, 0, 0)
squ = (8, 11, 134)
pygame.init()
size = (800, 600)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Bloxy")
pygame.key.set_repeat(1, 1)
font = pygame.font.SysFont("Stencil", 20)
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
keys_pressed = pygame.key.get_pressed()
if keys_pressed[pygame.K_LEFT]:
x -= 5
if keys_pressed[pygame.K_RIGHT]:
x += 5
if keys_pressed[pygame.K_UP]:
y -= 5
if keys_pressed[pygame.K_DOWN]:
y += 5
if x > 800:
x = 0
if x < 0:
x = 800
if y > 600:
y = 0
if y < 0:
y = 600
screen.fill(bkg)
text = font.render('(' + str(x) + ',' + str(y) + ')', True, clr)
screen.blit(text, [10, 10])
pygame.draw.rect(screen, squ, [x - 10, y - 10, 20, 20])
pygame.display.flip()
clock.tick(60)