Pygame low frame rate on simple gamewxPython or pygame for a simple card game?Is there a simple way to delete a list element by value?Putting a simple if-then-else statement on one lineDebugging a simple pygame gameerror with first simple game with PygameSimple Tic-Tac_Toe Game PygameDownloading pygame games without pygame?pygame simple game laggingPyGame frame rate with keyboard inputCollision detection simple game - Pygame

Do VLANs within a subnet need to have their own subnet for router on a stick?

Prove that NP is closed under karp reduction?

What is the word for reserving something for yourself before others do?

How does one intimidate enemies without having the capacity for violence?

"You are your self first supporter", a more proper way to say it

Problem of parity - Can we draw a closed path made up of 20 line segments...

Why dont electromagnetic waves interact with each other?

I’m planning on buying a laser printer but concerned about the life cycle of toner in the machine

Smoothness of finite-dimensional functional calculus

Example of a continuous function that don't have a continuous extension

Today is the Center

What are the differences between the usage of 'it' and 'they'?

Is it legal for company to use my work email to pretend I still work there?

Arthur Somervell: 1000 Exercises - Meaning of this notation

Can I make popcorn with any corn?

What's the output of a record cartridge playing an out-of-speed record

Is it unprofessional to ask if a job posting on GlassDoor is real?

How to format long polynomial?

Is it possible to do 50 km distance without any previous training?

Animated Series: Alien black spider robot crashes on Earth

Why does Kotter return in Welcome Back Kotter?

Why did the Germans forbid the possession of pet pigeons in Rostov-on-Don in 1941?

Can I ask the recruiters in my resume to put the reason why I am rejected?

Writing rule which states that two causes for the same superpower is bad writing



Pygame low frame rate on simple game


wxPython or pygame for a simple card game?Is there a simple way to delete a list element by value?Putting a simple if-then-else statement on one lineDebugging a simple pygame gameerror with first simple game with PygameSimple Tic-Tac_Toe Game PygameDownloading pygame games without pygame?pygame simple game laggingPyGame frame rate with keyboard inputCollision detection simple game - Pygame






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








3















I'm making a sandbox game/simulation which looks like powdergame from danball.com except way simpler.



My game lags when there is a certain amount of squares that are spawned



don't pay attention to the comments



import pygame
import time
import random

pygame.init()

clock = pygame.time.Clock()

fps = 120

wnx = 800
wny = 600

black = (0,0,0)
grey = (80,80,80)
white = (255,255,255)
black_transparent = (255,255,255,128)
red = (255,0,0)
BACKGROUNDCOLOR = (40,40,40)

#__ Elements __

sand = (255,160,50)
rock = (125,125,125)
bsand = (255,180,150)
brock = (180,180,180)
dirt = (110, 45, 0)
bdirt = (200, 90, 0)
water = (0, 150, 255)
bwater = (25, 200, 255)
wall = (100,100,100)
bwall = (140,140,140)

erase = False

Onbutton = False
color = sand
cubec = sand

wn = pygame.display.set_mode((wnx, wny))
wn.fill(white)

def cursor(cux,cuy,cuw):
boxc = pygame.draw.rect(wn, black, [cux, cuy, cuw, cuw], 1)


def message(Font,Size,colort,xt,yt,text):
font = pygame.font.SysFont('freepixelregular', Size, True)
text = font.render(text, True, colort)
wn.blit(text, (xt, yt))



def cube(cx,cy,cw,ch,cubec):
pygame.draw.rect(wn, cubec, [cx, cy, cw, ch])


def floor(fx,fy,fw,fh):
pygame.draw.rect(wn, grey, [fx, fy, fw, fh])
pygame.draw.line(wn, black, (150,504), (800, 504), 10)

def sidebar(sx,sy,sw,sh):
pygame.draw.rect(wn, grey, [0, 0, 150, 600])
pygame.draw.line(wn, black, (154,0), (154, 500), 10)


def button(bx, by, bw, bh, text, abcol, bcol, colorchange):

global color

mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()


if bx+bw > mouse[0] > bx and by+bh > mouse[1] > by:
Onbutton = True
pygame.draw.rect(wn, abcol, [bx, by, bw, bh])
if click[0] == 1 and colorchange != None:
color = colorchange

else:
pygame.draw.rect(wn, bcol, [bx, by, bw, bh])
Onbutton = False





font = pygame.font.SysFont('freepixelregular', 25,True)
text = font.render(text, True, black)
wn.blit(text, (bx + (bw/14), by + (bh/4)))


def main():


number = 0

toggle_fast = False
erase = False


cubex = [0] * number
cubey = [0] * number
cubec = [0] * number
cubew = 10 #cube size
cubeh = cubew


floory = 500

gravity = (cubew*-1)


clickt = False

exit = False



while not exit:



#________________ QUIT ________________________________________

for event in pygame.event.get():

if event.type == pygame.QUIT:
exit = True

if event.type == pygame.KEYDOWN:

if event.key == pygame.K_SPACE:
toggle_fast = not toggle_fast
if event.key == pygame.K_v:
erase = not erase


#_____________________ Click / spawn cube / erase cube _____________________________

mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()

if toggle_fast == False:

if event.type == pygame.MOUSEBUTTONDOWN:
if mouse[1] < floory and mouse[0] >= 154:



cubex.append(round((mouse[0]/cubew),0)*cubew)
cubey.append(round((mouse[1]/cubew),0)*cubew)
cubec.append(color)





if click[0] == 1 and toggle_fast == True:
print(erase)
if mouse[1] < floory and mouse[0] >= 154:



cubex.append(round((mouse[0]/cubew),0)*cubew)
cubey.append(round((mouse[1]/cubew),0)*cubew)
cubec.append(color)




#_____________________ GRAVITY _____________________________

for i in range(len(cubex)):
cubeR = pygame.Rect(cubex[i], cubey[i] + cubew, cubew, cubeh)
cisect = [j for j in range(len(cubey)) if j != i and cubeR.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
watercheck = [j for j in range(len(cubey)) if j != i and cubec[i] != (0, 150, 255) and cubec[j] == (0, 150, 255) and cubeR.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]

if not any(cisect) and not (cubey[i] + cubew) >= floory:
if not cubec[i] == (100,100,100):
cubey[i] -= gravity



#for j in range(len(cubex):
# if any(watercheck):
# if not (cubey[i] + cubew) >= floory or any(cisect):
# oldposy = CUBEINFO[i][1]
# oldposx = CUBEINFO[i][0]

# CUBEINFO.append(oldposx, oldposy, (0, 150, 255))

#cubex.append(oldposx)
#cubey.append(oldposy)
#cubec.append((0, 150, 255))



#________water physics___________

cubeRxr = pygame.Rect(cubex[i] - cubew, cubey[i], cubew, cubeh)
cubeRxl = pygame.Rect(cubex[i] + cubew, cubey[i], cubew, cubeh)
cubeRdiagr = pygame.Rect(cubex[i] + 10, cubey[i] + 10, cubew, cubeh)
cubeRdiagl = pygame.Rect(cubex[i] - 10, cubey[i] + 10, cubew, cubeh)
cisectx = [j for j in range(len(cubex)) if j != i and cubeRxr.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
cisectxl = [j for j in range(len(cubex)) if j != i and cubeRxl.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
cisectdr = [j for j in range(len(cubex)) if j != i and cubeRdiagr.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
cisectdl = [j for j in range(len(cubex)) if j != i and cubeRdiagl.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]



if cubec[i] == (0, 150, 255):

if (cubey[i] + cubew) >= floory or any(cisect): # on ground


if not (cubex[i] + cubew) >= 800 and not cubex[i] <= 164:


if any(cisectx) and not any(cisectxl): #going right because of right wall
cubex[i] += 10
elif any(cisectxl) and not any(cisectx): #going left because of left wall
cubex[i] -= 10

elif any(cisectx) and any(cisectxl):
cubex[i] += 0

elif any(cisect) or (cubey[i] + cubew) >= floory:

negative = [-10, 10]
cubex[i] += random.choice(negative)

elif any(cisect) and not any(cisectdl) and not any(cisectdr):
negative = [-10, 10]
cubex[i] += random.choice(negative)




#____________________ Element _____________________________

#_____________________ DRAW _____________________________

wn.fill(BACKGROUNDCOLOR)

floor(0,floory,800,100)
sidebar(0, 0, 150, 600)

for i in range(len(cubex)):
cube(cubex[i], cubey[i], cubew, cubeh, cubec[i])

cursor(round((mouse[0]/cubew),0)*cubew, round((mouse[1]/cubew),0)*cubew, cubew,)

button(20, 40, 50, 40, 'RCK', brock, rock, (125,125,125))
button(20, 85, 50, 40, 'SND', bsand, sand, (255,160,50))
button(20, 130, 50, 40, 'DRT', bdirt, dirt, (110, 45, 2))
button(20, 175, 50, 40, 'WTR', bwater, water, (0, 150, 255))
button(20, 220, 50, 40, 'WLL', bwall, wall, (100,100,100))

#(Font,Size,colort,xt,yt,message):
message(None, 20, black, 10,400,('ERASE:'+str(erase)))

pygame.display.update()
clock.tick(fps)

main()

pygame.quit()
quit()


Maybe it is because of the fact that the squares positions (refered as cubex,cubey) are in separate lists or something?



im just starting out with python so it can be a silly error



thanks for the help!










share|improve this question






















  • Its because you iterate through every pair of cubes, which is O(n^2) time complexity. The question is, are all these necessary?

    – Dillon Davis
    Mar 9 at 3:15











  • yes they are, it so I can find all the cubes that are colliding

    – matiasvlevi
    Mar 9 at 3:20











  • I haven't used pygame, so I don't know what comes built in, but there most certainly are better ways to do collision detection. An easy option would be by binning your cubes by some reasonable interval. A more advanced option would be to use a kd-tree or octree.

    – Dillon Davis
    Mar 9 at 3:22

















3















I'm making a sandbox game/simulation which looks like powdergame from danball.com except way simpler.



My game lags when there is a certain amount of squares that are spawned



don't pay attention to the comments



import pygame
import time
import random

pygame.init()

clock = pygame.time.Clock()

fps = 120

wnx = 800
wny = 600

black = (0,0,0)
grey = (80,80,80)
white = (255,255,255)
black_transparent = (255,255,255,128)
red = (255,0,0)
BACKGROUNDCOLOR = (40,40,40)

#__ Elements __

sand = (255,160,50)
rock = (125,125,125)
bsand = (255,180,150)
brock = (180,180,180)
dirt = (110, 45, 0)
bdirt = (200, 90, 0)
water = (0, 150, 255)
bwater = (25, 200, 255)
wall = (100,100,100)
bwall = (140,140,140)

erase = False

Onbutton = False
color = sand
cubec = sand

wn = pygame.display.set_mode((wnx, wny))
wn.fill(white)

def cursor(cux,cuy,cuw):
boxc = pygame.draw.rect(wn, black, [cux, cuy, cuw, cuw], 1)


def message(Font,Size,colort,xt,yt,text):
font = pygame.font.SysFont('freepixelregular', Size, True)
text = font.render(text, True, colort)
wn.blit(text, (xt, yt))



def cube(cx,cy,cw,ch,cubec):
pygame.draw.rect(wn, cubec, [cx, cy, cw, ch])


def floor(fx,fy,fw,fh):
pygame.draw.rect(wn, grey, [fx, fy, fw, fh])
pygame.draw.line(wn, black, (150,504), (800, 504), 10)

def sidebar(sx,sy,sw,sh):
pygame.draw.rect(wn, grey, [0, 0, 150, 600])
pygame.draw.line(wn, black, (154,0), (154, 500), 10)


def button(bx, by, bw, bh, text, abcol, bcol, colorchange):

global color

mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()


if bx+bw > mouse[0] > bx and by+bh > mouse[1] > by:
Onbutton = True
pygame.draw.rect(wn, abcol, [bx, by, bw, bh])
if click[0] == 1 and colorchange != None:
color = colorchange

else:
pygame.draw.rect(wn, bcol, [bx, by, bw, bh])
Onbutton = False





font = pygame.font.SysFont('freepixelregular', 25,True)
text = font.render(text, True, black)
wn.blit(text, (bx + (bw/14), by + (bh/4)))


def main():


number = 0

toggle_fast = False
erase = False


cubex = [0] * number
cubey = [0] * number
cubec = [0] * number
cubew = 10 #cube size
cubeh = cubew


floory = 500

gravity = (cubew*-1)


clickt = False

exit = False



while not exit:



#________________ QUIT ________________________________________

for event in pygame.event.get():

if event.type == pygame.QUIT:
exit = True

if event.type == pygame.KEYDOWN:

if event.key == pygame.K_SPACE:
toggle_fast = not toggle_fast
if event.key == pygame.K_v:
erase = not erase


#_____________________ Click / spawn cube / erase cube _____________________________

mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()

if toggle_fast == False:

if event.type == pygame.MOUSEBUTTONDOWN:
if mouse[1] < floory and mouse[0] >= 154:



cubex.append(round((mouse[0]/cubew),0)*cubew)
cubey.append(round((mouse[1]/cubew),0)*cubew)
cubec.append(color)





if click[0] == 1 and toggle_fast == True:
print(erase)
if mouse[1] < floory and mouse[0] >= 154:



cubex.append(round((mouse[0]/cubew),0)*cubew)
cubey.append(round((mouse[1]/cubew),0)*cubew)
cubec.append(color)




#_____________________ GRAVITY _____________________________

for i in range(len(cubex)):
cubeR = pygame.Rect(cubex[i], cubey[i] + cubew, cubew, cubeh)
cisect = [j for j in range(len(cubey)) if j != i and cubeR.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
watercheck = [j for j in range(len(cubey)) if j != i and cubec[i] != (0, 150, 255) and cubec[j] == (0, 150, 255) and cubeR.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]

if not any(cisect) and not (cubey[i] + cubew) >= floory:
if not cubec[i] == (100,100,100):
cubey[i] -= gravity



#for j in range(len(cubex):
# if any(watercheck):
# if not (cubey[i] + cubew) >= floory or any(cisect):
# oldposy = CUBEINFO[i][1]
# oldposx = CUBEINFO[i][0]

# CUBEINFO.append(oldposx, oldposy, (0, 150, 255))

#cubex.append(oldposx)
#cubey.append(oldposy)
#cubec.append((0, 150, 255))



#________water physics___________

cubeRxr = pygame.Rect(cubex[i] - cubew, cubey[i], cubew, cubeh)
cubeRxl = pygame.Rect(cubex[i] + cubew, cubey[i], cubew, cubeh)
cubeRdiagr = pygame.Rect(cubex[i] + 10, cubey[i] + 10, cubew, cubeh)
cubeRdiagl = pygame.Rect(cubex[i] - 10, cubey[i] + 10, cubew, cubeh)
cisectx = [j for j in range(len(cubex)) if j != i and cubeRxr.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
cisectxl = [j for j in range(len(cubex)) if j != i and cubeRxl.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
cisectdr = [j for j in range(len(cubex)) if j != i and cubeRdiagr.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
cisectdl = [j for j in range(len(cubex)) if j != i and cubeRdiagl.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]



if cubec[i] == (0, 150, 255):

if (cubey[i] + cubew) >= floory or any(cisect): # on ground


if not (cubex[i] + cubew) >= 800 and not cubex[i] <= 164:


if any(cisectx) and not any(cisectxl): #going right because of right wall
cubex[i] += 10
elif any(cisectxl) and not any(cisectx): #going left because of left wall
cubex[i] -= 10

elif any(cisectx) and any(cisectxl):
cubex[i] += 0

elif any(cisect) or (cubey[i] + cubew) >= floory:

negative = [-10, 10]
cubex[i] += random.choice(negative)

elif any(cisect) and not any(cisectdl) and not any(cisectdr):
negative = [-10, 10]
cubex[i] += random.choice(negative)




#____________________ Element _____________________________

#_____________________ DRAW _____________________________

wn.fill(BACKGROUNDCOLOR)

floor(0,floory,800,100)
sidebar(0, 0, 150, 600)

for i in range(len(cubex)):
cube(cubex[i], cubey[i], cubew, cubeh, cubec[i])

cursor(round((mouse[0]/cubew),0)*cubew, round((mouse[1]/cubew),0)*cubew, cubew,)

button(20, 40, 50, 40, 'RCK', brock, rock, (125,125,125))
button(20, 85, 50, 40, 'SND', bsand, sand, (255,160,50))
button(20, 130, 50, 40, 'DRT', bdirt, dirt, (110, 45, 2))
button(20, 175, 50, 40, 'WTR', bwater, water, (0, 150, 255))
button(20, 220, 50, 40, 'WLL', bwall, wall, (100,100,100))

#(Font,Size,colort,xt,yt,message):
message(None, 20, black, 10,400,('ERASE:'+str(erase)))

pygame.display.update()
clock.tick(fps)

main()

pygame.quit()
quit()


Maybe it is because of the fact that the squares positions (refered as cubex,cubey) are in separate lists or something?



im just starting out with python so it can be a silly error



thanks for the help!










share|improve this question






















  • Its because you iterate through every pair of cubes, which is O(n^2) time complexity. The question is, are all these necessary?

    – Dillon Davis
    Mar 9 at 3:15











  • yes they are, it so I can find all the cubes that are colliding

    – matiasvlevi
    Mar 9 at 3:20











  • I haven't used pygame, so I don't know what comes built in, but there most certainly are better ways to do collision detection. An easy option would be by binning your cubes by some reasonable interval. A more advanced option would be to use a kd-tree or octree.

    – Dillon Davis
    Mar 9 at 3:22













3












3








3


0






I'm making a sandbox game/simulation which looks like powdergame from danball.com except way simpler.



My game lags when there is a certain amount of squares that are spawned



don't pay attention to the comments



import pygame
import time
import random

pygame.init()

clock = pygame.time.Clock()

fps = 120

wnx = 800
wny = 600

black = (0,0,0)
grey = (80,80,80)
white = (255,255,255)
black_transparent = (255,255,255,128)
red = (255,0,0)
BACKGROUNDCOLOR = (40,40,40)

#__ Elements __

sand = (255,160,50)
rock = (125,125,125)
bsand = (255,180,150)
brock = (180,180,180)
dirt = (110, 45, 0)
bdirt = (200, 90, 0)
water = (0, 150, 255)
bwater = (25, 200, 255)
wall = (100,100,100)
bwall = (140,140,140)

erase = False

Onbutton = False
color = sand
cubec = sand

wn = pygame.display.set_mode((wnx, wny))
wn.fill(white)

def cursor(cux,cuy,cuw):
boxc = pygame.draw.rect(wn, black, [cux, cuy, cuw, cuw], 1)


def message(Font,Size,colort,xt,yt,text):
font = pygame.font.SysFont('freepixelregular', Size, True)
text = font.render(text, True, colort)
wn.blit(text, (xt, yt))



def cube(cx,cy,cw,ch,cubec):
pygame.draw.rect(wn, cubec, [cx, cy, cw, ch])


def floor(fx,fy,fw,fh):
pygame.draw.rect(wn, grey, [fx, fy, fw, fh])
pygame.draw.line(wn, black, (150,504), (800, 504), 10)

def sidebar(sx,sy,sw,sh):
pygame.draw.rect(wn, grey, [0, 0, 150, 600])
pygame.draw.line(wn, black, (154,0), (154, 500), 10)


def button(bx, by, bw, bh, text, abcol, bcol, colorchange):

global color

mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()


if bx+bw > mouse[0] > bx and by+bh > mouse[1] > by:
Onbutton = True
pygame.draw.rect(wn, abcol, [bx, by, bw, bh])
if click[0] == 1 and colorchange != None:
color = colorchange

else:
pygame.draw.rect(wn, bcol, [bx, by, bw, bh])
Onbutton = False





font = pygame.font.SysFont('freepixelregular', 25,True)
text = font.render(text, True, black)
wn.blit(text, (bx + (bw/14), by + (bh/4)))


def main():


number = 0

toggle_fast = False
erase = False


cubex = [0] * number
cubey = [0] * number
cubec = [0] * number
cubew = 10 #cube size
cubeh = cubew


floory = 500

gravity = (cubew*-1)


clickt = False

exit = False



while not exit:



#________________ QUIT ________________________________________

for event in pygame.event.get():

if event.type == pygame.QUIT:
exit = True

if event.type == pygame.KEYDOWN:

if event.key == pygame.K_SPACE:
toggle_fast = not toggle_fast
if event.key == pygame.K_v:
erase = not erase


#_____________________ Click / spawn cube / erase cube _____________________________

mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()

if toggle_fast == False:

if event.type == pygame.MOUSEBUTTONDOWN:
if mouse[1] < floory and mouse[0] >= 154:



cubex.append(round((mouse[0]/cubew),0)*cubew)
cubey.append(round((mouse[1]/cubew),0)*cubew)
cubec.append(color)





if click[0] == 1 and toggle_fast == True:
print(erase)
if mouse[1] < floory and mouse[0] >= 154:



cubex.append(round((mouse[0]/cubew),0)*cubew)
cubey.append(round((mouse[1]/cubew),0)*cubew)
cubec.append(color)




#_____________________ GRAVITY _____________________________

for i in range(len(cubex)):
cubeR = pygame.Rect(cubex[i], cubey[i] + cubew, cubew, cubeh)
cisect = [j for j in range(len(cubey)) if j != i and cubeR.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
watercheck = [j for j in range(len(cubey)) if j != i and cubec[i] != (0, 150, 255) and cubec[j] == (0, 150, 255) and cubeR.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]

if not any(cisect) and not (cubey[i] + cubew) >= floory:
if not cubec[i] == (100,100,100):
cubey[i] -= gravity



#for j in range(len(cubex):
# if any(watercheck):
# if not (cubey[i] + cubew) >= floory or any(cisect):
# oldposy = CUBEINFO[i][1]
# oldposx = CUBEINFO[i][0]

# CUBEINFO.append(oldposx, oldposy, (0, 150, 255))

#cubex.append(oldposx)
#cubey.append(oldposy)
#cubec.append((0, 150, 255))



#________water physics___________

cubeRxr = pygame.Rect(cubex[i] - cubew, cubey[i], cubew, cubeh)
cubeRxl = pygame.Rect(cubex[i] + cubew, cubey[i], cubew, cubeh)
cubeRdiagr = pygame.Rect(cubex[i] + 10, cubey[i] + 10, cubew, cubeh)
cubeRdiagl = pygame.Rect(cubex[i] - 10, cubey[i] + 10, cubew, cubeh)
cisectx = [j for j in range(len(cubex)) if j != i and cubeRxr.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
cisectxl = [j for j in range(len(cubex)) if j != i and cubeRxl.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
cisectdr = [j for j in range(len(cubex)) if j != i and cubeRdiagr.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
cisectdl = [j for j in range(len(cubex)) if j != i and cubeRdiagl.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]



if cubec[i] == (0, 150, 255):

if (cubey[i] + cubew) >= floory or any(cisect): # on ground


if not (cubex[i] + cubew) >= 800 and not cubex[i] <= 164:


if any(cisectx) and not any(cisectxl): #going right because of right wall
cubex[i] += 10
elif any(cisectxl) and not any(cisectx): #going left because of left wall
cubex[i] -= 10

elif any(cisectx) and any(cisectxl):
cubex[i] += 0

elif any(cisect) or (cubey[i] + cubew) >= floory:

negative = [-10, 10]
cubex[i] += random.choice(negative)

elif any(cisect) and not any(cisectdl) and not any(cisectdr):
negative = [-10, 10]
cubex[i] += random.choice(negative)




#____________________ Element _____________________________

#_____________________ DRAW _____________________________

wn.fill(BACKGROUNDCOLOR)

floor(0,floory,800,100)
sidebar(0, 0, 150, 600)

for i in range(len(cubex)):
cube(cubex[i], cubey[i], cubew, cubeh, cubec[i])

cursor(round((mouse[0]/cubew),0)*cubew, round((mouse[1]/cubew),0)*cubew, cubew,)

button(20, 40, 50, 40, 'RCK', brock, rock, (125,125,125))
button(20, 85, 50, 40, 'SND', bsand, sand, (255,160,50))
button(20, 130, 50, 40, 'DRT', bdirt, dirt, (110, 45, 2))
button(20, 175, 50, 40, 'WTR', bwater, water, (0, 150, 255))
button(20, 220, 50, 40, 'WLL', bwall, wall, (100,100,100))

#(Font,Size,colort,xt,yt,message):
message(None, 20, black, 10,400,('ERASE:'+str(erase)))

pygame.display.update()
clock.tick(fps)

main()

pygame.quit()
quit()


Maybe it is because of the fact that the squares positions (refered as cubex,cubey) are in separate lists or something?



im just starting out with python so it can be a silly error



thanks for the help!










share|improve this question














I'm making a sandbox game/simulation which looks like powdergame from danball.com except way simpler.



My game lags when there is a certain amount of squares that are spawned



don't pay attention to the comments



import pygame
import time
import random

pygame.init()

clock = pygame.time.Clock()

fps = 120

wnx = 800
wny = 600

black = (0,0,0)
grey = (80,80,80)
white = (255,255,255)
black_transparent = (255,255,255,128)
red = (255,0,0)
BACKGROUNDCOLOR = (40,40,40)

#__ Elements __

sand = (255,160,50)
rock = (125,125,125)
bsand = (255,180,150)
brock = (180,180,180)
dirt = (110, 45, 0)
bdirt = (200, 90, 0)
water = (0, 150, 255)
bwater = (25, 200, 255)
wall = (100,100,100)
bwall = (140,140,140)

erase = False

Onbutton = False
color = sand
cubec = sand

wn = pygame.display.set_mode((wnx, wny))
wn.fill(white)

def cursor(cux,cuy,cuw):
boxc = pygame.draw.rect(wn, black, [cux, cuy, cuw, cuw], 1)


def message(Font,Size,colort,xt,yt,text):
font = pygame.font.SysFont('freepixelregular', Size, True)
text = font.render(text, True, colort)
wn.blit(text, (xt, yt))



def cube(cx,cy,cw,ch,cubec):
pygame.draw.rect(wn, cubec, [cx, cy, cw, ch])


def floor(fx,fy,fw,fh):
pygame.draw.rect(wn, grey, [fx, fy, fw, fh])
pygame.draw.line(wn, black, (150,504), (800, 504), 10)

def sidebar(sx,sy,sw,sh):
pygame.draw.rect(wn, grey, [0, 0, 150, 600])
pygame.draw.line(wn, black, (154,0), (154, 500), 10)


def button(bx, by, bw, bh, text, abcol, bcol, colorchange):

global color

mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()


if bx+bw > mouse[0] > bx and by+bh > mouse[1] > by:
Onbutton = True
pygame.draw.rect(wn, abcol, [bx, by, bw, bh])
if click[0] == 1 and colorchange != None:
color = colorchange

else:
pygame.draw.rect(wn, bcol, [bx, by, bw, bh])
Onbutton = False





font = pygame.font.SysFont('freepixelregular', 25,True)
text = font.render(text, True, black)
wn.blit(text, (bx + (bw/14), by + (bh/4)))


def main():


number = 0

toggle_fast = False
erase = False


cubex = [0] * number
cubey = [0] * number
cubec = [0] * number
cubew = 10 #cube size
cubeh = cubew


floory = 500

gravity = (cubew*-1)


clickt = False

exit = False



while not exit:



#________________ QUIT ________________________________________

for event in pygame.event.get():

if event.type == pygame.QUIT:
exit = True

if event.type == pygame.KEYDOWN:

if event.key == pygame.K_SPACE:
toggle_fast = not toggle_fast
if event.key == pygame.K_v:
erase = not erase


#_____________________ Click / spawn cube / erase cube _____________________________

mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()

if toggle_fast == False:

if event.type == pygame.MOUSEBUTTONDOWN:
if mouse[1] < floory and mouse[0] >= 154:



cubex.append(round((mouse[0]/cubew),0)*cubew)
cubey.append(round((mouse[1]/cubew),0)*cubew)
cubec.append(color)





if click[0] == 1 and toggle_fast == True:
print(erase)
if mouse[1] < floory and mouse[0] >= 154:



cubex.append(round((mouse[0]/cubew),0)*cubew)
cubey.append(round((mouse[1]/cubew),0)*cubew)
cubec.append(color)




#_____________________ GRAVITY _____________________________

for i in range(len(cubex)):
cubeR = pygame.Rect(cubex[i], cubey[i] + cubew, cubew, cubeh)
cisect = [j for j in range(len(cubey)) if j != i and cubeR.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
watercheck = [j for j in range(len(cubey)) if j != i and cubec[i] != (0, 150, 255) and cubec[j] == (0, 150, 255) and cubeR.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]

if not any(cisect) and not (cubey[i] + cubew) >= floory:
if not cubec[i] == (100,100,100):
cubey[i] -= gravity



#for j in range(len(cubex):
# if any(watercheck):
# if not (cubey[i] + cubew) >= floory or any(cisect):
# oldposy = CUBEINFO[i][1]
# oldposx = CUBEINFO[i][0]

# CUBEINFO.append(oldposx, oldposy, (0, 150, 255))

#cubex.append(oldposx)
#cubey.append(oldposy)
#cubec.append((0, 150, 255))



#________water physics___________

cubeRxr = pygame.Rect(cubex[i] - cubew, cubey[i], cubew, cubeh)
cubeRxl = pygame.Rect(cubex[i] + cubew, cubey[i], cubew, cubeh)
cubeRdiagr = pygame.Rect(cubex[i] + 10, cubey[i] + 10, cubew, cubeh)
cubeRdiagl = pygame.Rect(cubex[i] - 10, cubey[i] + 10, cubew, cubeh)
cisectx = [j for j in range(len(cubex)) if j != i and cubeRxr.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
cisectxl = [j for j in range(len(cubex)) if j != i and cubeRxl.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
cisectdr = [j for j in range(len(cubex)) if j != i and cubeRdiagr.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]
cisectdl = [j for j in range(len(cubex)) if j != i and cubeRdiagl.colliderect(pygame.Rect(cubex[j], cubey[j], cubew, cubeh))]



if cubec[i] == (0, 150, 255):

if (cubey[i] + cubew) >= floory or any(cisect): # on ground


if not (cubex[i] + cubew) >= 800 and not cubex[i] <= 164:


if any(cisectx) and not any(cisectxl): #going right because of right wall
cubex[i] += 10
elif any(cisectxl) and not any(cisectx): #going left because of left wall
cubex[i] -= 10

elif any(cisectx) and any(cisectxl):
cubex[i] += 0

elif any(cisect) or (cubey[i] + cubew) >= floory:

negative = [-10, 10]
cubex[i] += random.choice(negative)

elif any(cisect) and not any(cisectdl) and not any(cisectdr):
negative = [-10, 10]
cubex[i] += random.choice(negative)




#____________________ Element _____________________________

#_____________________ DRAW _____________________________

wn.fill(BACKGROUNDCOLOR)

floor(0,floory,800,100)
sidebar(0, 0, 150, 600)

for i in range(len(cubex)):
cube(cubex[i], cubey[i], cubew, cubeh, cubec[i])

cursor(round((mouse[0]/cubew),0)*cubew, round((mouse[1]/cubew),0)*cubew, cubew,)

button(20, 40, 50, 40, 'RCK', brock, rock, (125,125,125))
button(20, 85, 50, 40, 'SND', bsand, sand, (255,160,50))
button(20, 130, 50, 40, 'DRT', bdirt, dirt, (110, 45, 2))
button(20, 175, 50, 40, 'WTR', bwater, water, (0, 150, 255))
button(20, 220, 50, 40, 'WLL', bwall, wall, (100,100,100))

#(Font,Size,colort,xt,yt,message):
message(None, 20, black, 10,400,('ERASE:'+str(erase)))

pygame.display.update()
clock.tick(fps)

main()

pygame.quit()
quit()


Maybe it is because of the fact that the squares positions (refered as cubex,cubey) are in separate lists or something?



im just starting out with python so it can be a silly error



thanks for the help!







python python-3.x pygame game-physics






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Mar 9 at 3:03









matiasvlevimatiasvlevi

283




283












  • Its because you iterate through every pair of cubes, which is O(n^2) time complexity. The question is, are all these necessary?

    – Dillon Davis
    Mar 9 at 3:15











  • yes they are, it so I can find all the cubes that are colliding

    – matiasvlevi
    Mar 9 at 3:20











  • I haven't used pygame, so I don't know what comes built in, but there most certainly are better ways to do collision detection. An easy option would be by binning your cubes by some reasonable interval. A more advanced option would be to use a kd-tree or octree.

    – Dillon Davis
    Mar 9 at 3:22

















  • Its because you iterate through every pair of cubes, which is O(n^2) time complexity. The question is, are all these necessary?

    – Dillon Davis
    Mar 9 at 3:15











  • yes they are, it so I can find all the cubes that are colliding

    – matiasvlevi
    Mar 9 at 3:20











  • I haven't used pygame, so I don't know what comes built in, but there most certainly are better ways to do collision detection. An easy option would be by binning your cubes by some reasonable interval. A more advanced option would be to use a kd-tree or octree.

    – Dillon Davis
    Mar 9 at 3:22
















Its because you iterate through every pair of cubes, which is O(n^2) time complexity. The question is, are all these necessary?

– Dillon Davis
Mar 9 at 3:15





Its because you iterate through every pair of cubes, which is O(n^2) time complexity. The question is, are all these necessary?

– Dillon Davis
Mar 9 at 3:15













yes they are, it so I can find all the cubes that are colliding

– matiasvlevi
Mar 9 at 3:20





yes they are, it so I can find all the cubes that are colliding

– matiasvlevi
Mar 9 at 3:20













I haven't used pygame, so I don't know what comes built in, but there most certainly are better ways to do collision detection. An easy option would be by binning your cubes by some reasonable interval. A more advanced option would be to use a kd-tree or octree.

– Dillon Davis
Mar 9 at 3:22





I haven't used pygame, so I don't know what comes built in, but there most certainly are better ways to do collision detection. An easy option would be by binning your cubes by some reasonable interval. A more advanced option would be to use a kd-tree or octree.

– Dillon Davis
Mar 9 at 3:22












1 Answer
1






active

oldest

votes


















1














The only way to speed up your game is to avoid the continuously searching in the array of cubes.



To achieve this you have to change the representation of your data. You have to think the problem from the other direction. Don't search a cube at a position, but "ask" a position if a cube is on it. Instead of storing the cubes in lists, create a 2 dimensional playground grid and associate a cube to a field in the grid.



Create and object for a cube (the attribute '.dir' is for the water and explained later):



class Cube:
def __init__(self, color):
self.color = color
self.dir = 1


Create the empty playground (each filed is initialized by None):



cubew = 10 #cube size
cubeh = cubew

pg_rect = pygame.Rect(160, 0, 650, 500)
pg_size = (pg_rect.width // cubew, pg_rect.height // cubeh)
pg_grid = [[None for i in range(pg_size[1])] for j in range(pg_size[0])]


On mouse click a cube can be added to the playground with ease:



if event.type == pygame.MOUSEBUTTONDOWN:
if mouse[1] < floory and mouse[0] >= 154:

i, j = ((mouse[0]-pg_rect.left) // cubew, (mouse[1]-pg_rect.top) // cubeh)
if not pg_grid[i][j]:
pg_grid[i][j] = Cube(color)


To draw the cubes the entire field has to be traversed:



for i in range(pg_size[0]):
for j in range(pg_size[1]):
if pg_grid[i][j]:
pos = (pg_rect.left + i * cubew, pg_rect.top + j * cubeh)
cube(*pos, cubew, cubeh, pg_grid[i][j].color)


For the update of positions of the cubes (gravity, water), all the cubes have to be listed and the location of the cube in the filed has to be changed.



cubes = [(i, j) for i in range(pg_size[0]) for j in range(pg_size[1]-1, 0, -1) if pg_grid[i][j]]
for i, j in cubes:

# [...]


For gravity it has to be checked if the filed below the cube is "free" (None):



fall_down = pg_grid[i][j].color != wall
if fall_down and j < pg_size[1]-1 and pg_grid[i][j+1] == None:

pg_grid[i][j+1] = pg_grid[i][j]
pg_grid[i][j] = None


And for the water effect it has to be checked if the filed beside the cube, which is identified by self.dir is "free", If it is "free", then the cube steps forward. Else its direction has to be changed:



is_water = pg_grid[i][j].color == water
if is_water:

if pg_grid[i][j].dir < 0:
if i <= 0 or pg_grid[i-1][j]:
pg_grid[i][j].dir = 1
else:
pg_grid[i-1][j] = pg_grid[i][j]
pg_grid[i][j] = None

else:
if i >= pg_size[0]-1 or pg_grid[i+1][j]:
pg_grid[i][j].dir = -1
else:
pg_grid[i+1][j] = pg_grid[i][j]
pg_grid[i][j] = None


See the example, where I applied the changes to your original code:





import pygame
import time
import random

pygame.init()

clock = pygame.time.Clock()

fps = 120

wnx = 800
wny = 600

black = (0,0,0)
grey = (80,80,80)
white = (255,255,255)
black_transparent = (255,255,255,128)
red = (255,0,0)
BACKGROUNDCOLOR = (40,40,40)

#__ Elements __

sand = (255,160,50)
rock = (125,125,125)
bsand = (255,180,150)
brock = (180,180,180)
dirt = (110, 45, 0)
bdirt = (200, 90, 0)
water = (0, 150, 255)
bwater = (25, 200, 255)
wall = (100,100,100)
bwall = (140,140,140)

erase = False

Onbutton = False
color = sand
cubec = sand

wn = pygame.display.set_mode((wnx, wny))
wn.fill(white)

class Cube:
def __init__(self, color):
self.color = color
self.dir = 1

def cursor(cux,cuy,cuw):
boxc = pygame.draw.rect(wn, black, [cux, cuy, cuw, cuw], 1)

def message(Font,Size,colort,xt,yt,text):
font = pygame.font.SysFont('freepixelregular', Size, True)
text = font.render(text, True, colort)
wn.blit(text, (xt, yt))

def cube(cx,cy,cw,ch,cubec):
pygame.draw.rect(wn, cubec, [cx, cy, cw, ch])

def floor(fx,fy,fw,fh):
pygame.draw.rect(wn, grey, [fx, fy, fw, fh])
pygame.draw.line(wn, black, (150,504), (800, 504), 10)

def sidebar(sx,sy,sw,sh):
pygame.draw.rect(wn, grey, [0, 0, 150, 600])
pygame.draw.line(wn, black, (154,0), (154, 500), 10)

def button(bx, by, bw, bh, text, abcol, bcol, colorchange):

global color

mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()

if bx+bw > mouse[0] > bx and by+bh > mouse[1] > by:
Onbutton = True
pygame.draw.rect(wn, abcol, [bx, by, bw, bh])
if click[0] == 1 and colorchange != None:
color = colorchange
else:
pygame.draw.rect(wn, bcol, [bx, by, bw, bh])
Onbutton = False

font = pygame.font.SysFont('freepixelregular', 25,True)
text = font.render(text, True, black)
wn.blit(text, (bx + (bw/14), by + (bh/4)))


def main():

number = 0

toggle_fast = False
erase = False

cubew = 10 #cube size
cubeh = cubew

pg_rect = pygame.Rect(160, 0, 650, 500)
pg_size = (pg_rect.width // cubew, pg_rect.height // cubeh)
pg_grid = [[None for i in range(pg_size[1])] for j in range(pg_size[0])]

floory = 500
gravity = (cubew*-1)
clickt = False
exit = False

while not exit:
#________________ QUIT ________________________________________
for event in pygame.event.get():

if event.type == pygame.QUIT:
exit = True

if event.type == pygame.KEYDOWN:

if event.key == pygame.K_SPACE:
toggle_fast = not toggle_fast
if event.key == pygame.K_v:
erase = not erase
#_____________________ Click / spawn cube / erase cube _____________________________

mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()

if toggle_fast == False:

if event.type == pygame.MOUSEBUTTONDOWN:
if mouse[1] < floory and mouse[0] >= 154:

i, j = ((mouse[0]-pg_rect.left) // cubew, (mouse[1]-pg_rect.top) // cubeh)
if not pg_grid[i][j]:
pg_grid[i][j] = Cube(color)

if click[0] == 1 and toggle_fast == True:
print(erase)
if mouse[1] < floory and mouse[0] >= 154:

i, j = ((mouse[0]-pg_rect.left) // cubew, (mouse[1]-pg_rect.top) // cubeh)
if not pg_grid[i][j]:
pg_grid[i][j] = Cube(color)

# update cubes
cubes = [(i, j) for i in range(pg_size[0]) for j in range(pg_size[1]-1, 0, -1) if pg_grid[i][j]]
for i, j in cubes:

fall_down = pg_grid[i][j].color != wall
is_water = pg_grid[i][j].color == water

if fall_down and j < pg_size[1]-1 and pg_grid[i][j+1] == None:
#_____________________ GRAVITY _____________________________
pg_grid[i][j+1] = pg_grid[i][j]
pg_grid[i][j] = None

elif is_water:
#________water physics___________
if pg_grid[i][j].dir < 0:
if i <= 0 or pg_grid[i-1][j]:
pg_grid[i][j].dir = 1
else:
pg_grid[i-1][j] = pg_grid[i][j]
pg_grid[i][j] = None

else:
if i >= pg_size[0]-1 or pg_grid[i+1][j]:
pg_grid[i][j].dir = -1
else:
pg_grid[i+1][j] = pg_grid[i][j]
pg_grid[i][j] = None

wn.fill(BACKGROUNDCOLOR)

floor(0,floory,800,100)
sidebar(0, 0, 150, 600)

# draw cubes
for i in range(pg_size[0]):
for j in range(pg_size[1]):
if pg_grid[i][j]:
pos = (pg_rect.left + i * cubew, pg_rect.top + j * cubeh)
cube(*pos, cubew, cubeh, pg_grid[i][j].color)

cursor(round((mouse[0]/cubew),0)*cubew, round((mouse[1]/cubew),0)*cubew, cubew,)

button(20, 40, 50, 40, 'RCK', brock, rock, (125,125,125))
button(20, 85, 50, 40, 'SND', bsand, sand, (255,160,50))
button(20, 130, 50, 40, 'DRT', bdirt, dirt, (110, 45, 2))
button(20, 175, 50, 40, 'WTR', bwater, water, (0, 150, 255))
button(20, 220, 50, 40, 'WLL', bwall, wall, (100,100,100))

#(Font,Size,colort,xt,yt,message):
message(None, 20, black, 10,400,('ERASE:'+str(erase)))

pygame.display.update()
clock.tick(fps)

main()

pygame.quit()
quit()





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55073598%2fpygame-low-frame-rate-on-simple-game%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    The only way to speed up your game is to avoid the continuously searching in the array of cubes.



    To achieve this you have to change the representation of your data. You have to think the problem from the other direction. Don't search a cube at a position, but "ask" a position if a cube is on it. Instead of storing the cubes in lists, create a 2 dimensional playground grid and associate a cube to a field in the grid.



    Create and object for a cube (the attribute '.dir' is for the water and explained later):



    class Cube:
    def __init__(self, color):
    self.color = color
    self.dir = 1


    Create the empty playground (each filed is initialized by None):



    cubew = 10 #cube size
    cubeh = cubew

    pg_rect = pygame.Rect(160, 0, 650, 500)
    pg_size = (pg_rect.width // cubew, pg_rect.height // cubeh)
    pg_grid = [[None for i in range(pg_size[1])] for j in range(pg_size[0])]


    On mouse click a cube can be added to the playground with ease:



    if event.type == pygame.MOUSEBUTTONDOWN:
    if mouse[1] < floory and mouse[0] >= 154:

    i, j = ((mouse[0]-pg_rect.left) // cubew, (mouse[1]-pg_rect.top) // cubeh)
    if not pg_grid[i][j]:
    pg_grid[i][j] = Cube(color)


    To draw the cubes the entire field has to be traversed:



    for i in range(pg_size[0]):
    for j in range(pg_size[1]):
    if pg_grid[i][j]:
    pos = (pg_rect.left + i * cubew, pg_rect.top + j * cubeh)
    cube(*pos, cubew, cubeh, pg_grid[i][j].color)


    For the update of positions of the cubes (gravity, water), all the cubes have to be listed and the location of the cube in the filed has to be changed.



    cubes = [(i, j) for i in range(pg_size[0]) for j in range(pg_size[1]-1, 0, -1) if pg_grid[i][j]]
    for i, j in cubes:

    # [...]


    For gravity it has to be checked if the filed below the cube is "free" (None):



    fall_down = pg_grid[i][j].color != wall
    if fall_down and j < pg_size[1]-1 and pg_grid[i][j+1] == None:

    pg_grid[i][j+1] = pg_grid[i][j]
    pg_grid[i][j] = None


    And for the water effect it has to be checked if the filed beside the cube, which is identified by self.dir is "free", If it is "free", then the cube steps forward. Else its direction has to be changed:



    is_water = pg_grid[i][j].color == water
    if is_water:

    if pg_grid[i][j].dir < 0:
    if i <= 0 or pg_grid[i-1][j]:
    pg_grid[i][j].dir = 1
    else:
    pg_grid[i-1][j] = pg_grid[i][j]
    pg_grid[i][j] = None

    else:
    if i >= pg_size[0]-1 or pg_grid[i+1][j]:
    pg_grid[i][j].dir = -1
    else:
    pg_grid[i+1][j] = pg_grid[i][j]
    pg_grid[i][j] = None


    See the example, where I applied the changes to your original code:





    import pygame
    import time
    import random

    pygame.init()

    clock = pygame.time.Clock()

    fps = 120

    wnx = 800
    wny = 600

    black = (0,0,0)
    grey = (80,80,80)
    white = (255,255,255)
    black_transparent = (255,255,255,128)
    red = (255,0,0)
    BACKGROUNDCOLOR = (40,40,40)

    #__ Elements __

    sand = (255,160,50)
    rock = (125,125,125)
    bsand = (255,180,150)
    brock = (180,180,180)
    dirt = (110, 45, 0)
    bdirt = (200, 90, 0)
    water = (0, 150, 255)
    bwater = (25, 200, 255)
    wall = (100,100,100)
    bwall = (140,140,140)

    erase = False

    Onbutton = False
    color = sand
    cubec = sand

    wn = pygame.display.set_mode((wnx, wny))
    wn.fill(white)

    class Cube:
    def __init__(self, color):
    self.color = color
    self.dir = 1

    def cursor(cux,cuy,cuw):
    boxc = pygame.draw.rect(wn, black, [cux, cuy, cuw, cuw], 1)

    def message(Font,Size,colort,xt,yt,text):
    font = pygame.font.SysFont('freepixelregular', Size, True)
    text = font.render(text, True, colort)
    wn.blit(text, (xt, yt))

    def cube(cx,cy,cw,ch,cubec):
    pygame.draw.rect(wn, cubec, [cx, cy, cw, ch])

    def floor(fx,fy,fw,fh):
    pygame.draw.rect(wn, grey, [fx, fy, fw, fh])
    pygame.draw.line(wn, black, (150,504), (800, 504), 10)

    def sidebar(sx,sy,sw,sh):
    pygame.draw.rect(wn, grey, [0, 0, 150, 600])
    pygame.draw.line(wn, black, (154,0), (154, 500), 10)

    def button(bx, by, bw, bh, text, abcol, bcol, colorchange):

    global color

    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()

    if bx+bw > mouse[0] > bx and by+bh > mouse[1] > by:
    Onbutton = True
    pygame.draw.rect(wn, abcol, [bx, by, bw, bh])
    if click[0] == 1 and colorchange != None:
    color = colorchange
    else:
    pygame.draw.rect(wn, bcol, [bx, by, bw, bh])
    Onbutton = False

    font = pygame.font.SysFont('freepixelregular', 25,True)
    text = font.render(text, True, black)
    wn.blit(text, (bx + (bw/14), by + (bh/4)))


    def main():

    number = 0

    toggle_fast = False
    erase = False

    cubew = 10 #cube size
    cubeh = cubew

    pg_rect = pygame.Rect(160, 0, 650, 500)
    pg_size = (pg_rect.width // cubew, pg_rect.height // cubeh)
    pg_grid = [[None for i in range(pg_size[1])] for j in range(pg_size[0])]

    floory = 500
    gravity = (cubew*-1)
    clickt = False
    exit = False

    while not exit:
    #________________ QUIT ________________________________________
    for event in pygame.event.get():

    if event.type == pygame.QUIT:
    exit = True

    if event.type == pygame.KEYDOWN:

    if event.key == pygame.K_SPACE:
    toggle_fast = not toggle_fast
    if event.key == pygame.K_v:
    erase = not erase
    #_____________________ Click / spawn cube / erase cube _____________________________

    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()

    if toggle_fast == False:

    if event.type == pygame.MOUSEBUTTONDOWN:
    if mouse[1] < floory and mouse[0] >= 154:

    i, j = ((mouse[0]-pg_rect.left) // cubew, (mouse[1]-pg_rect.top) // cubeh)
    if not pg_grid[i][j]:
    pg_grid[i][j] = Cube(color)

    if click[0] == 1 and toggle_fast == True:
    print(erase)
    if mouse[1] < floory and mouse[0] >= 154:

    i, j = ((mouse[0]-pg_rect.left) // cubew, (mouse[1]-pg_rect.top) // cubeh)
    if not pg_grid[i][j]:
    pg_grid[i][j] = Cube(color)

    # update cubes
    cubes = [(i, j) for i in range(pg_size[0]) for j in range(pg_size[1]-1, 0, -1) if pg_grid[i][j]]
    for i, j in cubes:

    fall_down = pg_grid[i][j].color != wall
    is_water = pg_grid[i][j].color == water

    if fall_down and j < pg_size[1]-1 and pg_grid[i][j+1] == None:
    #_____________________ GRAVITY _____________________________
    pg_grid[i][j+1] = pg_grid[i][j]
    pg_grid[i][j] = None

    elif is_water:
    #________water physics___________
    if pg_grid[i][j].dir < 0:
    if i <= 0 or pg_grid[i-1][j]:
    pg_grid[i][j].dir = 1
    else:
    pg_grid[i-1][j] = pg_grid[i][j]
    pg_grid[i][j] = None

    else:
    if i >= pg_size[0]-1 or pg_grid[i+1][j]:
    pg_grid[i][j].dir = -1
    else:
    pg_grid[i+1][j] = pg_grid[i][j]
    pg_grid[i][j] = None

    wn.fill(BACKGROUNDCOLOR)

    floor(0,floory,800,100)
    sidebar(0, 0, 150, 600)

    # draw cubes
    for i in range(pg_size[0]):
    for j in range(pg_size[1]):
    if pg_grid[i][j]:
    pos = (pg_rect.left + i * cubew, pg_rect.top + j * cubeh)
    cube(*pos, cubew, cubeh, pg_grid[i][j].color)

    cursor(round((mouse[0]/cubew),0)*cubew, round((mouse[1]/cubew),0)*cubew, cubew,)

    button(20, 40, 50, 40, 'RCK', brock, rock, (125,125,125))
    button(20, 85, 50, 40, 'SND', bsand, sand, (255,160,50))
    button(20, 130, 50, 40, 'DRT', bdirt, dirt, (110, 45, 2))
    button(20, 175, 50, 40, 'WTR', bwater, water, (0, 150, 255))
    button(20, 220, 50, 40, 'WLL', bwall, wall, (100,100,100))

    #(Font,Size,colort,xt,yt,message):
    message(None, 20, black, 10,400,('ERASE:'+str(erase)))

    pygame.display.update()
    clock.tick(fps)

    main()

    pygame.quit()
    quit()





    share|improve this answer



























      1














      The only way to speed up your game is to avoid the continuously searching in the array of cubes.



      To achieve this you have to change the representation of your data. You have to think the problem from the other direction. Don't search a cube at a position, but "ask" a position if a cube is on it. Instead of storing the cubes in lists, create a 2 dimensional playground grid and associate a cube to a field in the grid.



      Create and object for a cube (the attribute '.dir' is for the water and explained later):



      class Cube:
      def __init__(self, color):
      self.color = color
      self.dir = 1


      Create the empty playground (each filed is initialized by None):



      cubew = 10 #cube size
      cubeh = cubew

      pg_rect = pygame.Rect(160, 0, 650, 500)
      pg_size = (pg_rect.width // cubew, pg_rect.height // cubeh)
      pg_grid = [[None for i in range(pg_size[1])] for j in range(pg_size[0])]


      On mouse click a cube can be added to the playground with ease:



      if event.type == pygame.MOUSEBUTTONDOWN:
      if mouse[1] < floory and mouse[0] >= 154:

      i, j = ((mouse[0]-pg_rect.left) // cubew, (mouse[1]-pg_rect.top) // cubeh)
      if not pg_grid[i][j]:
      pg_grid[i][j] = Cube(color)


      To draw the cubes the entire field has to be traversed:



      for i in range(pg_size[0]):
      for j in range(pg_size[1]):
      if pg_grid[i][j]:
      pos = (pg_rect.left + i * cubew, pg_rect.top + j * cubeh)
      cube(*pos, cubew, cubeh, pg_grid[i][j].color)


      For the update of positions of the cubes (gravity, water), all the cubes have to be listed and the location of the cube in the filed has to be changed.



      cubes = [(i, j) for i in range(pg_size[0]) for j in range(pg_size[1]-1, 0, -1) if pg_grid[i][j]]
      for i, j in cubes:

      # [...]


      For gravity it has to be checked if the filed below the cube is "free" (None):



      fall_down = pg_grid[i][j].color != wall
      if fall_down and j < pg_size[1]-1 and pg_grid[i][j+1] == None:

      pg_grid[i][j+1] = pg_grid[i][j]
      pg_grid[i][j] = None


      And for the water effect it has to be checked if the filed beside the cube, which is identified by self.dir is "free", If it is "free", then the cube steps forward. Else its direction has to be changed:



      is_water = pg_grid[i][j].color == water
      if is_water:

      if pg_grid[i][j].dir < 0:
      if i <= 0 or pg_grid[i-1][j]:
      pg_grid[i][j].dir = 1
      else:
      pg_grid[i-1][j] = pg_grid[i][j]
      pg_grid[i][j] = None

      else:
      if i >= pg_size[0]-1 or pg_grid[i+1][j]:
      pg_grid[i][j].dir = -1
      else:
      pg_grid[i+1][j] = pg_grid[i][j]
      pg_grid[i][j] = None


      See the example, where I applied the changes to your original code:





      import pygame
      import time
      import random

      pygame.init()

      clock = pygame.time.Clock()

      fps = 120

      wnx = 800
      wny = 600

      black = (0,0,0)
      grey = (80,80,80)
      white = (255,255,255)
      black_transparent = (255,255,255,128)
      red = (255,0,0)
      BACKGROUNDCOLOR = (40,40,40)

      #__ Elements __

      sand = (255,160,50)
      rock = (125,125,125)
      bsand = (255,180,150)
      brock = (180,180,180)
      dirt = (110, 45, 0)
      bdirt = (200, 90, 0)
      water = (0, 150, 255)
      bwater = (25, 200, 255)
      wall = (100,100,100)
      bwall = (140,140,140)

      erase = False

      Onbutton = False
      color = sand
      cubec = sand

      wn = pygame.display.set_mode((wnx, wny))
      wn.fill(white)

      class Cube:
      def __init__(self, color):
      self.color = color
      self.dir = 1

      def cursor(cux,cuy,cuw):
      boxc = pygame.draw.rect(wn, black, [cux, cuy, cuw, cuw], 1)

      def message(Font,Size,colort,xt,yt,text):
      font = pygame.font.SysFont('freepixelregular', Size, True)
      text = font.render(text, True, colort)
      wn.blit(text, (xt, yt))

      def cube(cx,cy,cw,ch,cubec):
      pygame.draw.rect(wn, cubec, [cx, cy, cw, ch])

      def floor(fx,fy,fw,fh):
      pygame.draw.rect(wn, grey, [fx, fy, fw, fh])
      pygame.draw.line(wn, black, (150,504), (800, 504), 10)

      def sidebar(sx,sy,sw,sh):
      pygame.draw.rect(wn, grey, [0, 0, 150, 600])
      pygame.draw.line(wn, black, (154,0), (154, 500), 10)

      def button(bx, by, bw, bh, text, abcol, bcol, colorchange):

      global color

      mouse = pygame.mouse.get_pos()
      click = pygame.mouse.get_pressed()

      if bx+bw > mouse[0] > bx and by+bh > mouse[1] > by:
      Onbutton = True
      pygame.draw.rect(wn, abcol, [bx, by, bw, bh])
      if click[0] == 1 and colorchange != None:
      color = colorchange
      else:
      pygame.draw.rect(wn, bcol, [bx, by, bw, bh])
      Onbutton = False

      font = pygame.font.SysFont('freepixelregular', 25,True)
      text = font.render(text, True, black)
      wn.blit(text, (bx + (bw/14), by + (bh/4)))


      def main():

      number = 0

      toggle_fast = False
      erase = False

      cubew = 10 #cube size
      cubeh = cubew

      pg_rect = pygame.Rect(160, 0, 650, 500)
      pg_size = (pg_rect.width // cubew, pg_rect.height // cubeh)
      pg_grid = [[None for i in range(pg_size[1])] for j in range(pg_size[0])]

      floory = 500
      gravity = (cubew*-1)
      clickt = False
      exit = False

      while not exit:
      #________________ QUIT ________________________________________
      for event in pygame.event.get():

      if event.type == pygame.QUIT:
      exit = True

      if event.type == pygame.KEYDOWN:

      if event.key == pygame.K_SPACE:
      toggle_fast = not toggle_fast
      if event.key == pygame.K_v:
      erase = not erase
      #_____________________ Click / spawn cube / erase cube _____________________________

      mouse = pygame.mouse.get_pos()
      click = pygame.mouse.get_pressed()

      if toggle_fast == False:

      if event.type == pygame.MOUSEBUTTONDOWN:
      if mouse[1] < floory and mouse[0] >= 154:

      i, j = ((mouse[0]-pg_rect.left) // cubew, (mouse[1]-pg_rect.top) // cubeh)
      if not pg_grid[i][j]:
      pg_grid[i][j] = Cube(color)

      if click[0] == 1 and toggle_fast == True:
      print(erase)
      if mouse[1] < floory and mouse[0] >= 154:

      i, j = ((mouse[0]-pg_rect.left) // cubew, (mouse[1]-pg_rect.top) // cubeh)
      if not pg_grid[i][j]:
      pg_grid[i][j] = Cube(color)

      # update cubes
      cubes = [(i, j) for i in range(pg_size[0]) for j in range(pg_size[1]-1, 0, -1) if pg_grid[i][j]]
      for i, j in cubes:

      fall_down = pg_grid[i][j].color != wall
      is_water = pg_grid[i][j].color == water

      if fall_down and j < pg_size[1]-1 and pg_grid[i][j+1] == None:
      #_____________________ GRAVITY _____________________________
      pg_grid[i][j+1] = pg_grid[i][j]
      pg_grid[i][j] = None

      elif is_water:
      #________water physics___________
      if pg_grid[i][j].dir < 0:
      if i <= 0 or pg_grid[i-1][j]:
      pg_grid[i][j].dir = 1
      else:
      pg_grid[i-1][j] = pg_grid[i][j]
      pg_grid[i][j] = None

      else:
      if i >= pg_size[0]-1 or pg_grid[i+1][j]:
      pg_grid[i][j].dir = -1
      else:
      pg_grid[i+1][j] = pg_grid[i][j]
      pg_grid[i][j] = None

      wn.fill(BACKGROUNDCOLOR)

      floor(0,floory,800,100)
      sidebar(0, 0, 150, 600)

      # draw cubes
      for i in range(pg_size[0]):
      for j in range(pg_size[1]):
      if pg_grid[i][j]:
      pos = (pg_rect.left + i * cubew, pg_rect.top + j * cubeh)
      cube(*pos, cubew, cubeh, pg_grid[i][j].color)

      cursor(round((mouse[0]/cubew),0)*cubew, round((mouse[1]/cubew),0)*cubew, cubew,)

      button(20, 40, 50, 40, 'RCK', brock, rock, (125,125,125))
      button(20, 85, 50, 40, 'SND', bsand, sand, (255,160,50))
      button(20, 130, 50, 40, 'DRT', bdirt, dirt, (110, 45, 2))
      button(20, 175, 50, 40, 'WTR', bwater, water, (0, 150, 255))
      button(20, 220, 50, 40, 'WLL', bwall, wall, (100,100,100))

      #(Font,Size,colort,xt,yt,message):
      message(None, 20, black, 10,400,('ERASE:'+str(erase)))

      pygame.display.update()
      clock.tick(fps)

      main()

      pygame.quit()
      quit()





      share|improve this answer

























        1












        1








        1







        The only way to speed up your game is to avoid the continuously searching in the array of cubes.



        To achieve this you have to change the representation of your data. You have to think the problem from the other direction. Don't search a cube at a position, but "ask" a position if a cube is on it. Instead of storing the cubes in lists, create a 2 dimensional playground grid and associate a cube to a field in the grid.



        Create and object for a cube (the attribute '.dir' is for the water and explained later):



        class Cube:
        def __init__(self, color):
        self.color = color
        self.dir = 1


        Create the empty playground (each filed is initialized by None):



        cubew = 10 #cube size
        cubeh = cubew

        pg_rect = pygame.Rect(160, 0, 650, 500)
        pg_size = (pg_rect.width // cubew, pg_rect.height // cubeh)
        pg_grid = [[None for i in range(pg_size[1])] for j in range(pg_size[0])]


        On mouse click a cube can be added to the playground with ease:



        if event.type == pygame.MOUSEBUTTONDOWN:
        if mouse[1] < floory and mouse[0] >= 154:

        i, j = ((mouse[0]-pg_rect.left) // cubew, (mouse[1]-pg_rect.top) // cubeh)
        if not pg_grid[i][j]:
        pg_grid[i][j] = Cube(color)


        To draw the cubes the entire field has to be traversed:



        for i in range(pg_size[0]):
        for j in range(pg_size[1]):
        if pg_grid[i][j]:
        pos = (pg_rect.left + i * cubew, pg_rect.top + j * cubeh)
        cube(*pos, cubew, cubeh, pg_grid[i][j].color)


        For the update of positions of the cubes (gravity, water), all the cubes have to be listed and the location of the cube in the filed has to be changed.



        cubes = [(i, j) for i in range(pg_size[0]) for j in range(pg_size[1]-1, 0, -1) if pg_grid[i][j]]
        for i, j in cubes:

        # [...]


        For gravity it has to be checked if the filed below the cube is "free" (None):



        fall_down = pg_grid[i][j].color != wall
        if fall_down and j < pg_size[1]-1 and pg_grid[i][j+1] == None:

        pg_grid[i][j+1] = pg_grid[i][j]
        pg_grid[i][j] = None


        And for the water effect it has to be checked if the filed beside the cube, which is identified by self.dir is "free", If it is "free", then the cube steps forward. Else its direction has to be changed:



        is_water = pg_grid[i][j].color == water
        if is_water:

        if pg_grid[i][j].dir < 0:
        if i <= 0 or pg_grid[i-1][j]:
        pg_grid[i][j].dir = 1
        else:
        pg_grid[i-1][j] = pg_grid[i][j]
        pg_grid[i][j] = None

        else:
        if i >= pg_size[0]-1 or pg_grid[i+1][j]:
        pg_grid[i][j].dir = -1
        else:
        pg_grid[i+1][j] = pg_grid[i][j]
        pg_grid[i][j] = None


        See the example, where I applied the changes to your original code:





        import pygame
        import time
        import random

        pygame.init()

        clock = pygame.time.Clock()

        fps = 120

        wnx = 800
        wny = 600

        black = (0,0,0)
        grey = (80,80,80)
        white = (255,255,255)
        black_transparent = (255,255,255,128)
        red = (255,0,0)
        BACKGROUNDCOLOR = (40,40,40)

        #__ Elements __

        sand = (255,160,50)
        rock = (125,125,125)
        bsand = (255,180,150)
        brock = (180,180,180)
        dirt = (110, 45, 0)
        bdirt = (200, 90, 0)
        water = (0, 150, 255)
        bwater = (25, 200, 255)
        wall = (100,100,100)
        bwall = (140,140,140)

        erase = False

        Onbutton = False
        color = sand
        cubec = sand

        wn = pygame.display.set_mode((wnx, wny))
        wn.fill(white)

        class Cube:
        def __init__(self, color):
        self.color = color
        self.dir = 1

        def cursor(cux,cuy,cuw):
        boxc = pygame.draw.rect(wn, black, [cux, cuy, cuw, cuw], 1)

        def message(Font,Size,colort,xt,yt,text):
        font = pygame.font.SysFont('freepixelregular', Size, True)
        text = font.render(text, True, colort)
        wn.blit(text, (xt, yt))

        def cube(cx,cy,cw,ch,cubec):
        pygame.draw.rect(wn, cubec, [cx, cy, cw, ch])

        def floor(fx,fy,fw,fh):
        pygame.draw.rect(wn, grey, [fx, fy, fw, fh])
        pygame.draw.line(wn, black, (150,504), (800, 504), 10)

        def sidebar(sx,sy,sw,sh):
        pygame.draw.rect(wn, grey, [0, 0, 150, 600])
        pygame.draw.line(wn, black, (154,0), (154, 500), 10)

        def button(bx, by, bw, bh, text, abcol, bcol, colorchange):

        global color

        mouse = pygame.mouse.get_pos()
        click = pygame.mouse.get_pressed()

        if bx+bw > mouse[0] > bx and by+bh > mouse[1] > by:
        Onbutton = True
        pygame.draw.rect(wn, abcol, [bx, by, bw, bh])
        if click[0] == 1 and colorchange != None:
        color = colorchange
        else:
        pygame.draw.rect(wn, bcol, [bx, by, bw, bh])
        Onbutton = False

        font = pygame.font.SysFont('freepixelregular', 25,True)
        text = font.render(text, True, black)
        wn.blit(text, (bx + (bw/14), by + (bh/4)))


        def main():

        number = 0

        toggle_fast = False
        erase = False

        cubew = 10 #cube size
        cubeh = cubew

        pg_rect = pygame.Rect(160, 0, 650, 500)
        pg_size = (pg_rect.width // cubew, pg_rect.height // cubeh)
        pg_grid = [[None for i in range(pg_size[1])] for j in range(pg_size[0])]

        floory = 500
        gravity = (cubew*-1)
        clickt = False
        exit = False

        while not exit:
        #________________ QUIT ________________________________________
        for event in pygame.event.get():

        if event.type == pygame.QUIT:
        exit = True

        if event.type == pygame.KEYDOWN:

        if event.key == pygame.K_SPACE:
        toggle_fast = not toggle_fast
        if event.key == pygame.K_v:
        erase = not erase
        #_____________________ Click / spawn cube / erase cube _____________________________

        mouse = pygame.mouse.get_pos()
        click = pygame.mouse.get_pressed()

        if toggle_fast == False:

        if event.type == pygame.MOUSEBUTTONDOWN:
        if mouse[1] < floory and mouse[0] >= 154:

        i, j = ((mouse[0]-pg_rect.left) // cubew, (mouse[1]-pg_rect.top) // cubeh)
        if not pg_grid[i][j]:
        pg_grid[i][j] = Cube(color)

        if click[0] == 1 and toggle_fast == True:
        print(erase)
        if mouse[1] < floory and mouse[0] >= 154:

        i, j = ((mouse[0]-pg_rect.left) // cubew, (mouse[1]-pg_rect.top) // cubeh)
        if not pg_grid[i][j]:
        pg_grid[i][j] = Cube(color)

        # update cubes
        cubes = [(i, j) for i in range(pg_size[0]) for j in range(pg_size[1]-1, 0, -1) if pg_grid[i][j]]
        for i, j in cubes:

        fall_down = pg_grid[i][j].color != wall
        is_water = pg_grid[i][j].color == water

        if fall_down and j < pg_size[1]-1 and pg_grid[i][j+1] == None:
        #_____________________ GRAVITY _____________________________
        pg_grid[i][j+1] = pg_grid[i][j]
        pg_grid[i][j] = None

        elif is_water:
        #________water physics___________
        if pg_grid[i][j].dir < 0:
        if i <= 0 or pg_grid[i-1][j]:
        pg_grid[i][j].dir = 1
        else:
        pg_grid[i-1][j] = pg_grid[i][j]
        pg_grid[i][j] = None

        else:
        if i >= pg_size[0]-1 or pg_grid[i+1][j]:
        pg_grid[i][j].dir = -1
        else:
        pg_grid[i+1][j] = pg_grid[i][j]
        pg_grid[i][j] = None

        wn.fill(BACKGROUNDCOLOR)

        floor(0,floory,800,100)
        sidebar(0, 0, 150, 600)

        # draw cubes
        for i in range(pg_size[0]):
        for j in range(pg_size[1]):
        if pg_grid[i][j]:
        pos = (pg_rect.left + i * cubew, pg_rect.top + j * cubeh)
        cube(*pos, cubew, cubeh, pg_grid[i][j].color)

        cursor(round((mouse[0]/cubew),0)*cubew, round((mouse[1]/cubew),0)*cubew, cubew,)

        button(20, 40, 50, 40, 'RCK', brock, rock, (125,125,125))
        button(20, 85, 50, 40, 'SND', bsand, sand, (255,160,50))
        button(20, 130, 50, 40, 'DRT', bdirt, dirt, (110, 45, 2))
        button(20, 175, 50, 40, 'WTR', bwater, water, (0, 150, 255))
        button(20, 220, 50, 40, 'WLL', bwall, wall, (100,100,100))

        #(Font,Size,colort,xt,yt,message):
        message(None, 20, black, 10,400,('ERASE:'+str(erase)))

        pygame.display.update()
        clock.tick(fps)

        main()

        pygame.quit()
        quit()





        share|improve this answer













        The only way to speed up your game is to avoid the continuously searching in the array of cubes.



        To achieve this you have to change the representation of your data. You have to think the problem from the other direction. Don't search a cube at a position, but "ask" a position if a cube is on it. Instead of storing the cubes in lists, create a 2 dimensional playground grid and associate a cube to a field in the grid.



        Create and object for a cube (the attribute '.dir' is for the water and explained later):



        class Cube:
        def __init__(self, color):
        self.color = color
        self.dir = 1


        Create the empty playground (each filed is initialized by None):



        cubew = 10 #cube size
        cubeh = cubew

        pg_rect = pygame.Rect(160, 0, 650, 500)
        pg_size = (pg_rect.width // cubew, pg_rect.height // cubeh)
        pg_grid = [[None for i in range(pg_size[1])] for j in range(pg_size[0])]


        On mouse click a cube can be added to the playground with ease:



        if event.type == pygame.MOUSEBUTTONDOWN:
        if mouse[1] < floory and mouse[0] >= 154:

        i, j = ((mouse[0]-pg_rect.left) // cubew, (mouse[1]-pg_rect.top) // cubeh)
        if not pg_grid[i][j]:
        pg_grid[i][j] = Cube(color)


        To draw the cubes the entire field has to be traversed:



        for i in range(pg_size[0]):
        for j in range(pg_size[1]):
        if pg_grid[i][j]:
        pos = (pg_rect.left + i * cubew, pg_rect.top + j * cubeh)
        cube(*pos, cubew, cubeh, pg_grid[i][j].color)


        For the update of positions of the cubes (gravity, water), all the cubes have to be listed and the location of the cube in the filed has to be changed.



        cubes = [(i, j) for i in range(pg_size[0]) for j in range(pg_size[1]-1, 0, -1) if pg_grid[i][j]]
        for i, j in cubes:

        # [...]


        For gravity it has to be checked if the filed below the cube is "free" (None):



        fall_down = pg_grid[i][j].color != wall
        if fall_down and j < pg_size[1]-1 and pg_grid[i][j+1] == None:

        pg_grid[i][j+1] = pg_grid[i][j]
        pg_grid[i][j] = None


        And for the water effect it has to be checked if the filed beside the cube, which is identified by self.dir is "free", If it is "free", then the cube steps forward. Else its direction has to be changed:



        is_water = pg_grid[i][j].color == water
        if is_water:

        if pg_grid[i][j].dir < 0:
        if i <= 0 or pg_grid[i-1][j]:
        pg_grid[i][j].dir = 1
        else:
        pg_grid[i-1][j] = pg_grid[i][j]
        pg_grid[i][j] = None

        else:
        if i >= pg_size[0]-1 or pg_grid[i+1][j]:
        pg_grid[i][j].dir = -1
        else:
        pg_grid[i+1][j] = pg_grid[i][j]
        pg_grid[i][j] = None


        See the example, where I applied the changes to your original code:





        import pygame
        import time
        import random

        pygame.init()

        clock = pygame.time.Clock()

        fps = 120

        wnx = 800
        wny = 600

        black = (0,0,0)
        grey = (80,80,80)
        white = (255,255,255)
        black_transparent = (255,255,255,128)
        red = (255,0,0)
        BACKGROUNDCOLOR = (40,40,40)

        #__ Elements __

        sand = (255,160,50)
        rock = (125,125,125)
        bsand = (255,180,150)
        brock = (180,180,180)
        dirt = (110, 45, 0)
        bdirt = (200, 90, 0)
        water = (0, 150, 255)
        bwater = (25, 200, 255)
        wall = (100,100,100)
        bwall = (140,140,140)

        erase = False

        Onbutton = False
        color = sand
        cubec = sand

        wn = pygame.display.set_mode((wnx, wny))
        wn.fill(white)

        class Cube:
        def __init__(self, color):
        self.color = color
        self.dir = 1

        def cursor(cux,cuy,cuw):
        boxc = pygame.draw.rect(wn, black, [cux, cuy, cuw, cuw], 1)

        def message(Font,Size,colort,xt,yt,text):
        font = pygame.font.SysFont('freepixelregular', Size, True)
        text = font.render(text, True, colort)
        wn.blit(text, (xt, yt))

        def cube(cx,cy,cw,ch,cubec):
        pygame.draw.rect(wn, cubec, [cx, cy, cw, ch])

        def floor(fx,fy,fw,fh):
        pygame.draw.rect(wn, grey, [fx, fy, fw, fh])
        pygame.draw.line(wn, black, (150,504), (800, 504), 10)

        def sidebar(sx,sy,sw,sh):
        pygame.draw.rect(wn, grey, [0, 0, 150, 600])
        pygame.draw.line(wn, black, (154,0), (154, 500), 10)

        def button(bx, by, bw, bh, text, abcol, bcol, colorchange):

        global color

        mouse = pygame.mouse.get_pos()
        click = pygame.mouse.get_pressed()

        if bx+bw > mouse[0] > bx and by+bh > mouse[1] > by:
        Onbutton = True
        pygame.draw.rect(wn, abcol, [bx, by, bw, bh])
        if click[0] == 1 and colorchange != None:
        color = colorchange
        else:
        pygame.draw.rect(wn, bcol, [bx, by, bw, bh])
        Onbutton = False

        font = pygame.font.SysFont('freepixelregular', 25,True)
        text = font.render(text, True, black)
        wn.blit(text, (bx + (bw/14), by + (bh/4)))


        def main():

        number = 0

        toggle_fast = False
        erase = False

        cubew = 10 #cube size
        cubeh = cubew

        pg_rect = pygame.Rect(160, 0, 650, 500)
        pg_size = (pg_rect.width // cubew, pg_rect.height // cubeh)
        pg_grid = [[None for i in range(pg_size[1])] for j in range(pg_size[0])]

        floory = 500
        gravity = (cubew*-1)
        clickt = False
        exit = False

        while not exit:
        #________________ QUIT ________________________________________
        for event in pygame.event.get():

        if event.type == pygame.QUIT:
        exit = True

        if event.type == pygame.KEYDOWN:

        if event.key == pygame.K_SPACE:
        toggle_fast = not toggle_fast
        if event.key == pygame.K_v:
        erase = not erase
        #_____________________ Click / spawn cube / erase cube _____________________________

        mouse = pygame.mouse.get_pos()
        click = pygame.mouse.get_pressed()

        if toggle_fast == False:

        if event.type == pygame.MOUSEBUTTONDOWN:
        if mouse[1] < floory and mouse[0] >= 154:

        i, j = ((mouse[0]-pg_rect.left) // cubew, (mouse[1]-pg_rect.top) // cubeh)
        if not pg_grid[i][j]:
        pg_grid[i][j] = Cube(color)

        if click[0] == 1 and toggle_fast == True:
        print(erase)
        if mouse[1] < floory and mouse[0] >= 154:

        i, j = ((mouse[0]-pg_rect.left) // cubew, (mouse[1]-pg_rect.top) // cubeh)
        if not pg_grid[i][j]:
        pg_grid[i][j] = Cube(color)

        # update cubes
        cubes = [(i, j) for i in range(pg_size[0]) for j in range(pg_size[1]-1, 0, -1) if pg_grid[i][j]]
        for i, j in cubes:

        fall_down = pg_grid[i][j].color != wall
        is_water = pg_grid[i][j].color == water

        if fall_down and j < pg_size[1]-1 and pg_grid[i][j+1] == None:
        #_____________________ GRAVITY _____________________________
        pg_grid[i][j+1] = pg_grid[i][j]
        pg_grid[i][j] = None

        elif is_water:
        #________water physics___________
        if pg_grid[i][j].dir < 0:
        if i <= 0 or pg_grid[i-1][j]:
        pg_grid[i][j].dir = 1
        else:
        pg_grid[i-1][j] = pg_grid[i][j]
        pg_grid[i][j] = None

        else:
        if i >= pg_size[0]-1 or pg_grid[i+1][j]:
        pg_grid[i][j].dir = -1
        else:
        pg_grid[i+1][j] = pg_grid[i][j]
        pg_grid[i][j] = None

        wn.fill(BACKGROUNDCOLOR)

        floor(0,floory,800,100)
        sidebar(0, 0, 150, 600)

        # draw cubes
        for i in range(pg_size[0]):
        for j in range(pg_size[1]):
        if pg_grid[i][j]:
        pos = (pg_rect.left + i * cubew, pg_rect.top + j * cubeh)
        cube(*pos, cubew, cubeh, pg_grid[i][j].color)

        cursor(round((mouse[0]/cubew),0)*cubew, round((mouse[1]/cubew),0)*cubew, cubew,)

        button(20, 40, 50, 40, 'RCK', brock, rock, (125,125,125))
        button(20, 85, 50, 40, 'SND', bsand, sand, (255,160,50))
        button(20, 130, 50, 40, 'DRT', bdirt, dirt, (110, 45, 2))
        button(20, 175, 50, 40, 'WTR', bwater, water, (0, 150, 255))
        button(20, 220, 50, 40, 'WLL', bwall, wall, (100,100,100))

        #(Font,Size,colort,xt,yt,message):
        message(None, 20, black, 10,400,('ERASE:'+str(erase)))

        pygame.display.update()
        clock.tick(fps)

        main()

        pygame.quit()
        quit()






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Mar 9 at 10:10









        Rabbid76Rabbid76

        43.4k123354




        43.4k123354





























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55073598%2fpygame-low-frame-rate-on-simple-game%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Can't initialize raids on a new ASUS Prime B360M-A motherboard2019 Community Moderator ElectionSimilar to RAID config yet more like mirroring solution?Can't get motherboard serial numberWhy does the BIOS entry point start with a WBINVD instruction?UEFI performance Asus Maximus V Extreme

            Identity Server 4 is not redirecting to Angular app after login2019 Community Moderator ElectionIdentity Server 4 and dockerIdentityserver implicit flow unauthorized_clientIdentityServer Hybrid Flow - Access Token is null after user successful loginIdentity Server to MVC client : Page Redirect After loginLogin with Steam OpenId(oidc-client-js)Identity Server 4+.NET Core 2.0 + IdentityIdentityServer4 post-login redirect not working in Edge browserCall to IdentityServer4 generates System.NullReferenceException: Object reference not set to an instance of an objectIdentityServer4 without HTTPS not workingHow to get Authorization code from identity server without login form

            2005 Ahvaz unrest Contents Background Causes Casualties Aftermath See also References Navigation menue"At Least 10 Are Killed by Bombs in Iran""Iran"Archived"Arab-Iranians in Iran to make April 15 'Day of Fury'"State of Mind, State of Order: Reactions to Ethnic Unrest in the Islamic Republic of Iran.10.1111/j.1754-9469.2008.00028.x"Iran hangs Arab separatists"Iran Overview from ArchivedConstitution of the Islamic Republic of Iran"Tehran puzzled by forged 'riots' letter""Iran and its minorities: Down in the second class""Iran: Handling Of Ahvaz Unrest Could End With Televised Confessions""Bombings Rock Iran Ahead of Election""Five die in Iran ethnic clashes""Iran: Need for restraint as anniversary of unrest in Khuzestan approaches"Archived"Iranian Sunni protesters killed in clashes with security forces"Archived