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;
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
add a comment |
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
Its because you iterate through every pair of cubes, which isO(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
add a comment |
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
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
python python-3.x pygame game-physics
asked Mar 9 at 3:03
matiasvlevimatiasvlevi
283
283
Its because you iterate through every pair of cubes, which isO(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
add a comment |
Its because you iterate through every pair of cubes, which isO(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
add a comment |
1 Answer
1
active
oldest
votes
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()
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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()
add a comment |
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()
add a comment |
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()
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()
answered Mar 9 at 10:10
Rabbid76Rabbid76
43.4k123354
43.4k123354
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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