Python Fatal error while creating a Sudoku game - python

I'm trying to create a Sudoku game in python with a solver included. First of all, for some reason, it doesn't show me the procedure of resolving, the window opens only when the board is solved and secondly when i close the window it returns me that python fatal error :Fatal Python error: pygame_parachute: (pygame parachute) Segmentation Fault
Python runtime state: initialized
That is my code :
import time
import pygame
from random import *
import numpy as np
pygame.init()
pygame.font.init()
LARGEUR, HAUTEUR = 550, 550
WIN = pygame.display.set_mode((LARGEUR, HAUTEUR))
pygame.display.set_caption('Sudoku Game')
Font1 = pygame.font.SysFont(None, 35)
clock = pygame.time.Clock()
BLANC = (255, 255, 255)
NOIR = (0, 0, 0)
BLEU = (0,0,255)
def gen_grille():
grille = [
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0]
]
val_debut = 17
for n in range(val_debut):
lgn = randint(1, 8)
cl = randint(1, 8)
num = randint(1, 9)
while(not is_possible(grille,lgn,cl,num) or grille[lgn][cl] != 0):
lgn = randint(1, 8)
cl = randint(1, 8)
num = randint(1, 9)
grille[lgn][cl]= num;
return list(grille)
def is_possible(grille,lgn,cl,num):
statut = True
for a in range(9):
if (grille[a][cl] == num):
statut = False
for b in range(9):
if (grille[lgn][b] == num):
statut = False
zone_lgn = lgn // 3
zone_cl = cl // 3
for a in range(3):
for b in range(3):
if(grille[zone_lgn*3 + a][zone_cl*3 + b] == num):
statut = False
return statut
gen_grille()
grille = gen_grille()
grid_original = [[grille[x][y] for y in range(len(grille[0]))] for x in range(len(grille))]
def draw_new_vals(WIN, position):
x,y = position[0], position[1]
myfont = pygame.font.SysFont('Comic Sans MS', 35)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYDOWN:
if(grid_original[x-1][y-1] != 0):
return
if(event.key == 48):
grille[x-1][y-1] = event.key - 48
pygame.draw.rect(WIN, BLANC, (position[0]*50 + 5, position[0]*50+ 5, 40, 40))
pygame.display.update()
return
if(0 < event.key - 48 <10):
pygame.draw.rect(WIN, BLANC, (position[0]*50 + 5, position[1]*50+ 5, 40, 40))
value = myfont.render(str(event.key-48), True, (0,0,0))
WIN.blit(value, (position[0]*50 +15, position[1]*50))
grille[x-1][y-1] = event.key - 48
pygame.display.update()
return
return
def draw_strt_vals():
for x in range(9):
for y in range(9):
if(0 < grille[x][y] < 10):
num = Font1.render(str(grille[x][y]), True, BLEU)
WIN.blit(num, ((x+1)*50 + 15, (y+1)*50 + 15))
def draw_all():
WIN.fill(BLANC)
draw_grille()
draw_strt_vals()
pygame.display.update()
def draw_grille():
for x in range(10):
pygame.draw.line(WIN, (NOIR), (50 + 50*x, 50), (50 + 50*x, 500), 2)
pygame.draw.line(WIN, (NOIR), (50, 50 + 50*x), (500, 50 + 50*x), 2)
for x in range(10):
if x % 3 == 0:
pygame.draw.line(WIN, (NOIR), (50 + 50*x, 50), (50 + 50*x, 500), 4)
pygame.draw.line(WIN, (NOIR), (50, 50 + 50*x), (500, 50 + 50*x), 4)
solved = 0
def solver(grille):
Font1 = pygame.font.SysFont(None, 35)
for lgn in range(9):
for cl in range(9):
if grille[lgn][cl] == 0:
for num in range(1,10):
if is_possible(grille, lgn, cl, num):
grille[lgn][cl] = num
pygame.draw.rect(WIN, BLANC, ((cl+1)*50 + 5, (lgn+1)*50+ 5,40 ,40))
value = Font1.render(str(num), True, (0,0,0))
WIN.blit(value, ((cl+1)*50 +15,(lgn+1)*50))
pygame.display.update()
solver(grille)
global solved
if(solved == 1):
return
grille[lgn][cl] = 0
pygame.draw.rect(WIN, BLANC, ((lgn+1)*50 + 5, (cl+1)*50+ 5,40 ,40))
pygame.display.update()
return
solved = 1
def main():
pygame.init()
clock.tick(60)
marche = True
for i in range(0, len(grille[0])):
for j in range(0, len(grille[0])):
if(0<grille[i][j]<10):
value = Font1.render(str(grille[i][j]), True, BLEU)
WIN.blit(value, ((j+1)*50 + 15, (i+1)*50 ))
pygame.display.update()
solver(grille)
while marche:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONUP and event.button == 1:
m_pos = pygame.mouse.get_pos()
draw_new_vals(WIN, (m_pos[0]//50, m_pos[1]//50))
if event.type == pygame.QUIT:
pygame.quit()
return
draw_all()
main()
if __name__ == "__main__":
main()
main()

Related

PyGame: Why isn't my object moving automatically

I want 'rock' to be able to automatically move to the left when running the program but nothing happens, from my understanding I have made it so that the rocks x position moves by 3 every iteration
import pygame
p = pygame.display.set_mode((900, 600))
pygame.display.set_caption("First game")
FPS = 60
WHITE = 255, 255, 255
RED = 255, 0, 0
GREEN = 0, 255, 0
BLUE = 0, 0, 255
DBLUE = 57, 64, 90
board1 = pygame.image.load("board.png")
board2 = pygame.image.load("board.png")
rock = pygame.image.load("rock.png")
def draw_window(board1_move, board2_move, rock_scaled):
p.fill(DBLUE)
board1_scaled = pygame.transform.rotate(pygame.transform.scale(board1, (55, 40)), 40)
board2_scaled = pygame.transform.rotate(pygame.transform.scale(board2, (55, 40)), 40)
rock_scaled = pygame.transform.rotate(pygame.transform.scale(rock, (55, 40)), 0)
p.blit(board1_scaled, (board1_move.x, board1_move.y))
p.blit(board2_scaled, (board2_move.x, board2_move.y))
p.blit(rock_scaled, (400, 250))
pygame.display.update()
keypress = pygame.key.get_pressed()
def board1_move_func(keypress, board1_move):
if keypress[pygame.K_w] and board1_move.y > 0:
board1_move.y -= 3
if keypress[pygame.K_s] and board1_move.y < 530:
board1_move.y += 3
def board2_move_func(keypress, board2_move):
if keypress[pygame.K_UP] and board2_move.y > 0:
board2_move.y -= 3
if keypress[pygame.K_DOWN] and board2_move.y < 530:
board2_move.y += 3
def main():
rock_x = 450
rock_y = 250
board1_move = pygame.Rect(20, 250, 55, 40)
board2_move = pygame.Rect(805, 250, 55, 40)
rock_move = pygame.Rect(rock_x, rock_y, 55, 40)
clock = pygame.time.Clock()
run = True
while run == True:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keypress = pygame.key.get_pressed()
rock_x += 3
board1_move_func(keypress, board1_move)
board2_move_func(keypress, board2_move)
draw_window(board1_move, board2_move, rock_move)
pygame.quit()
if __name__ == "__main__":
main()
You change rock_x, but draw the object at the position stored in rock_move. rock_move is not magically tied with rock_x. You can update rock_move after changing rock_x:
rock_x += 3
rock_move.x = rock_x
However, I recommend changing rock_move instead of rock_x:
rock_move.x += 3

TypeError: 'Board' object cannot be interpreted as an integer

The problem is in check_win(self, player): function in class Board: in line for row in range(self, board_rows):
my code is here:
import pygame
from pygame.locals import *
from pathlib import *
import numpy as np
'''
---------
CONSTANTS
---------
'''
base_directory = Path(__file__).parent.absolute()
icon_path = 'tic_tac_toe_resources/images/tic_tac_toe.ico'
full_icon_path = base_directory / icon_path
width = height = 600
line_width = 14
board_rows = 3
board_columns = 3
box_size = width // board_columns
circle_radius = box_size // 3
cross_box_space = box_size // 4
circle_width = cross_width = 24
screen_color = (28, 170, 156)
line_color = (23, 145, 135)
circle_color = (1, 111, 124)
cross_color = (65, 65, 65)
class Board:
def __init__(self):
self.screen = pygame.display.set_mode((width, height))
self.icon = pygame.image.load(full_icon_path)
pygame.display.set_icon(self.icon)
pygame.display.set_caption('Tic Tac Toe by ZamaaN')
self.screen.fill(screen_color)
self.console_board = np.zeros((board_rows, board_columns))
def draw_board(self):
#? first horizontal line
pygame.draw.line(self.screen, line_color, (11, box_size), (width - 11, box_size), line_width)
#? second horizontal line
pygame.draw.line(self.screen, line_color, (11, 2 * box_size), (width - 11, 2 * box_size), line_width)
#? first vertical line
pygame.draw.line(self.screen, line_color, (box_size, 11), (box_size, height - 11), line_width)
#? second vertical line
pygame.draw.line(self.screen, line_color, (2 * box_size, 11),
(2 * box_size, height - 11), line_width)
def draw_figures(self):
for row in range(board_rows):
for column in range(board_columns):
if self.console_board[row][column] == 1:
pygame.draw.circle(self.screen, circle_color, (int(column * box_size + box_size // 2), int(row * box_size + box_size // 2)), circle_radius, circle_width)
elif self.console_board[row][column] == 2:
pygame.draw.line(self.screen, cross_color, (column * box_size + cross_box_space, row * box_size + box_size - cross_box_space), (column *box_size + box_size - cross_box_space, row * box_size + cross_box_space), cross_width)
pygame.draw.line(self.screen, cross_color, (column * box_size + cross_box_space, row * box_size + cross_box_space), (column *box_size + box_size - cross_box_space, row * box_size + box_size - cross_box_space), cross_width)
def mark_box(self, row, column, player):
self.console_board[row][column] = player
def is_box_available(self, row, column):
return self.console_board[row][column] == 0
def is_board_full(self):
for row in range(board_rows):
for column in range(board_columns):
if self.console_board[row][column] == 0:
return False
return True
def draw_vertical_winning_line(self, column, player):
position_x = column * box_size + box_size // 2
if player == 1:
vertical_winning_line_color = circle_color
elif player == 2:
vertical_winning_line_color = cross_color
pygame.draw.line(self.screen, vertical_winning_line_color, (position_x, 14), (position_x, height - 14), 14)
def draw_horizontal_winning_line(self, row, player):
position_y = row * box_size + box_size // 2
if player == 1:
horizontal_winning_line_color = circle_color
elif player == 2:
horizontal_winning_line_color = cross_color
pygame.draw.line(self.screen, horizontal_winning_line_color, (14, position_y), (width - 14, position_y), 14)
def draw_ascending_diagonal_winning_line(self, player):
if player == 1:
ascending_diagonal_winning_line_color = circle_color
elif player == 2:
ascending_diagonal_winning_line_color = cross_color
pygame.draw.line(self.screen, ascending_diagonal_winning_line_color, (14, height - 14), (width - 14, 14), 14)
def draw_descending_diagonal_winning_line(self, player):
if player == 1:
descending_diagonal_winning_line_color = circle_color
elif player == 2:
descending_diagonal_winning_line_color = cross_color
pygame.draw.line(self.screen, descending_diagonal_winning_line_color, (14, 14), (width - 14, height - 14), 14)
def check_win(self, player):
#? vertical win check
for column in range(board_columns):
if self.console_board[0][column] == player and self.console_board[1][column] == player and self.console_board[2][column] == player:
self.draw_vertical_winning_line(column, player)
return True
#? horizontal win check
for row in range(self, board_rows):
if self.console_board[row][0] == player and self.console_board[row][1] == player and self.console_board[row][2] == player:
self.draw_horizontal_winning_line(row, player)
return True
#? ascending diagonal win check
if self.console_board[2][0] == player and self.console_board[1][1] == player and self.console_board[0][2] == player:
self.draw_ascending_diagonal_winning_line(player)
return True
#? descending diagonal win check
if self.console_board[0][0] == player and self.console_board[1][1] == player and self.console_board[2][2] == player:
self.draw_descending_diagonal_winning_line(player)
return True
return False
class Game_TicTacToe:
def __init__(self):
pygame.init()
self.board = Board()
self.board.draw_board()
self.player = 1
def restart(self):
self.board.screen.fill(screen_color)
self.board.draw_board()
self.player = 1
for row in range(board_rows):
for column in range(board_columns):
self.board.console_board[row][column] = 0
def run(self):
running = True
game_over = False
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.key == K_RETURN:
self.restart()
game_over = False
elif event.type == pygame.MOUSEBUTTONDOWN and not game_over:
mouse_x = event.pos[0]
mouse_y = event.pos[1]
clicked_row = int(mouse_y // box_size)
clicked_column = int(mouse_x // box_size)
if self.board.is_box_available(clicked_row, clicked_column):
self.board.mark_box(clicked_row, clicked_column, self.player)
if self.board.check_win(self.player):
game_over = True
self.player = self.player % 2 + 1
self.board.draw_figures()
elif event.type == pygame.QUIT:
running = False
pygame.display.update()
if __name__ == '__main__':
game = Game_TicTacToe()
game.run()
I'm getting these errors:
Traceback (most recent call last):
File "e:\archive_root\CSE\Python\portfolio_py\projects_py\games_py\tic_tac_toe_py\tic_tac_toe.py", line 192, in <module>
game.run()
File "e:\archive_root\CSE\Python\portfolio_py\projects_py\games_py\tic_tac_toe_py\tic_tac_toe.py", line 179, in run
if self.board.check_win(self.player):
File "e:\archive_root\CSE\Python\portfolio_py\projects_py\games_py\tic_tac_toe_py\tic_tac_toe.py", line 124, in check_win
for row in range(self, board_rows):
TypeError: 'Board' object cannot be interpreted as an integer
The self there is redundant (read: wrong). You only need the number of rows in order to iterate over them:
for row in range(board_rows):

Changing Selected Variables Chosen From Input()

I want to change different variables in my code while it's running, for example changing the variable speed = 1 to speed = 2 using the CMD. The variable I want to change is decided on the person running the code through an input(). They type in speed, and the variable speed changes to another number, also chosen by the person running the code through another input().
To change the values, you should need to-
.
Press Enter, to pause the game
Select the CMD window
Type 'setvar', then Enter
Type 'speed', then Enter
Type '5', then Enter
.
I want this to change speed = 1 to speed = 5, but I also want to be able to do this with every variable, being able to change the score variable, or anything else. So far, I have made it so you input the variable you want to change, and what you want to change it to. The code is slightly messy, but readable.
So far I have tried
exec("%s = %s" % (var,setTo))
and
exec(f"{var} = '{setTo}'")
But it hasn't worked, although speed = 5 does.
The code I want help with is near the bottom. The whole code is...
def RUN():
import pygame
import time
import random
import msvcrt as m
pygame.init()
dis_width = 800
dis_height = 600
score = 0
x = 375
y = 275
foodx = -100
foody = -100
speed = 1
stanima = 0
gotox = 200
gotoy = 200
gotoSet = []
goto = []
gotoSet.append(gotox)
gotoSet.append(gotoy)
goto.append(gotoSet)
people = []
numOfPeople = 1 # Number of people
foodEaten = True
foodRun = True
speedRunPlus = True
speedRunMinus = True
runningRun = True
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 18)
dis = pygame.display.set_mode((dis_width, dis_height)) #screen stuff
pygame.display.set_caption('Game')
game_over = False
running = True
lightBlue = (50, 153, 213) #colors
red = (255, 100, 0)
yellow = (255, 255, 102)
blue = (70, 70, 255)
green1 = (0, 255, 0)
green2 = (0, 255, 25)
green3 = (0, 255, 50)
green4 = (0, 255, 75)
green5 = (0, 255, 100)
green6 = (0, 255, 125)
green7 = (0, 255, 150)
green8 = (0, 255, 175)
green9 = (0, 255, 200)
green10 = (0, 255, 225)
dis.fill(blue) #Backround
pygame.draw.rect(dis, lightBlue, [50, 50, 700, 500]) #Inner rectangle
def update_fps():
fps = str(int(clock.get_fps()))
fps = str("FPS: "+fps)
fps_text = font.render(fps, 1, pygame.Color("coral"))
return fps_text
def speedRender():
speed_str = str(speed)
speed_sentance = str("Average Speed: "+speed_str)
speed_text = font.render(speed_sentance, 1, pygame.Color("coral"))
return speed_text
def player(x, y, color, stamina): #Rectangle player
player = pygame.draw.rect(dis, color, [x, y, 25, 25])
if stanima == 1:
pygame.draw.rect(dis, red, [x+11, y+11, 3, 3])
elif stanima == 2:
pygame.draw.rect(dis, red, [x+10, y+10, 5, 5])
elif stanima == 3:
pygame.draw.rect(dis, red, [x+9, y+9, 7, 7])
elif stanima == 4:
pygame.draw.rect(dis, red, [x+8, y+8, 9, 9])
elif stanima == 5:
pygame.draw.rect(dis, red, [x+7, y+7, 11, 11])
elif stanima == 6:
pygame.draw.rect(dis, red, [x+6, y+6, 13, 13])
elif stanima == 7:
pygame.draw.rect(dis, red, [x+5, y+5, 15, 15])
elif stanima == 8:
pygame.draw.rect(dis, red, [x+4, y+4, 17, 17])
elif stanima == 9:
pygame.draw.rect(dis, red, [x+3, y+3, 19, 19])
def food(foodx, foody): #Rectangle food
food = pygame.draw.rect(dis, yellow, [foodx, foody, 10, 10])
for num1 in range(numOfPeople):
x = random.randint(300,400)
y = random.randint(300,400)
person = []
person.append(x)
person.append(y)
person.append(1)
person.append(goto)
person.append(score)
people.append(person)
while not game_over:
while running:
dis.fill(blue)
pygame.draw.rect(dis, lightBlue, [50, 50, 700, 500])
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
game_over = True
for num2 in range(numOfPeople):
x = people[0][0]
y = people[0][1]
#speed = people[0][2]
goto = people[0][3]
score = people[0][4]
del people[0]
if x+12 > foodx+5: # "AI"
x -= speed
elif x+12 < foodx+5:
x += speed
if y+12 > foody+5: # "AI"
y -= speed
elif y+12 < foody+5:
y += speed
if x > 725: #Creates Borders
x = 725
game_over = True
elif x < 50:
x = 50
game_over = True
if y > 525:
y = 525
game_over = True
elif y < 50:
y = 50
game_over = True
if x >= foodx-24 and x <= foodx+10:
if y >= foody-24 and y <= foody+10:
score += 1
foodEaten = True
#print("Score:", score)
person = []
person.append(x)
person.append(y)
person.append(1)
person.append(goto)
person.append(score)
people.append(person)
playerColor = green1
player(x, y, playerColor, stanima) #Creating Player
if foodEaten == True:
foodx = random.randint(90, 700)
foody = random.randint(90, 500)
stanima += 1
foodEaten = False
food(foodx, foody) #Creating Food
pressed = pygame.key.get_pressed() #Key Movement
if pressed[pygame.K_RCTRL]:
dis.blit(update_fps(), (10,0))
dis.blit(speedRender(), (100,0))
if pressed[pygame.K_SPACE]:
RUN()
if pressed[pygame.K_ESCAPE]:
running = False
game_over = True
if pressed[pygame.K_RSHIFT]:
if foodRun == True:
foodx = random.randint(90, 700)
foody = random.randint(90, 500)
stanima += 1
foodEaten = False
foodRun = False
else:
foodRun = True
if pressed[pygame.K_RETURN]:
if runningRun == True:
running = False
runningRun = False
print(" ")
else:
runningRun = True
if pressed[pygame.K_MINUS]:
if speedRunMinus == True:
speed -= 0.1
speedRunMinus = False
else:
speedRunMinus = True
if pressed[pygame.K_EQUALS]:
if speedRunPlus == True:
speed += 0.1
speedRunPlus = False
else:
speedRunPlus = True
pygame.display.flip() #updating screen
clock.tick()
if not game_over:
command = input(" :")
commandSplit = command.split(".")
#try:
if commandSplit[0] == "return":
var = input(" :")
if var in dir():
print(" :", eval(var), sep='')
else:
print(" :Variable Not Found")
elif commandSplit[0] == "run":
if commandSplit[1] == "exit":
running = False
game_over = True
elif commandSplit[0] == "setvar":
var = input(" :")
print("Var value now:", eval(var), sep='')
if var in locals():
setTo = input("Change variable to:") #Code I need help with -----------------------
print("Var value after:", eval(var), sep='')
else:
print(" :Invalid Syntax Error")
'''
except Exception:
print(" :Invalid Syntax Error")
pass
'''#to implement later
RUN()

Pygame low frame rate on simple game

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!
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()

Python, Pygame, my while loop breaks before it ends and i dont kno how to fix it [duplicate]

This question already has answers here:
Why is my PyGame application not running at all?
(2 answers)
Why is nothing drawn in PyGame at all?
(2 answers)
Closed 1 year ago.
Im working on a school project on a motion projectile but my while loop breaks before it ends.
import pygame, sys
from pygame.locals import *
from math import *
def rot_center(image, center_angle):
orig_rect = image.get_rect()
rot_image = pygame.transform.rotate(image, center_angle)
rot_rect = orig_rect.copy()
rot_rect.center = rot_image.get_rect().center
rot_image = rot_image.subsurface(rot_rect).copy()
return rot_image
pygame.init()
FPS = 144
fpsClock = pygame.time.Clock()
SCENE = pygame.display.set_mode((1280, 720), 0, 32)
pygame.display.set_caption('Domača naloga')
backgroundImg = pygame.image.load('images/background.png')
cannonBaseImg = pygame.image.load('images/base.png')
cannonImg = pygame.image.load('images/cannon.png')
ballImg = pygame.image.load('images/cannonBall.png')
enemy = pygame.image.load('images/enemy.png')
cannonBasePos = (9,490)
cannonPos = (-5, 480)
ballPos = (22,510)
enemyPos = (40, 400)
cannonImg = pygame.transform.rotate(cannonImg, -15)
ang = 45
cannonMovImg = rot_center(cannonImg, ang)
# bug: backgoround image dissapears and it bugges green
SCENE.blit(backgroundImg, (0,0))
SCENE.blit(cannonMovImg, cannonPos )
SCENE.blit(ballImg, ballPos)
SCENE.blit(cannonBaseImg, cannonBasePos)
SCENE.blit(enemy, enemyPos)
t = 0
s = ballPos
v = (0, 0)
vm = 100
launched = False
while True: #<-- while starts here
dt = fpsClock.tick(FPS)
if launched:
t = t + dt/250.0 # cajt is clocka
a = (0.0, 10.0) # acceleration
v = (v0[0] + a[0]*t, v0[1] + a[1]*t) # spazz out nad 1000 !!!
vm = sqrt(v[0]*v[0] + v[1]*v[1])
s0 = ballPos # poz
s = (s0[0] + v0[0]*t + a[0]*t*t/2, s0[1] + v0[1]*t + a[1]*t*t/2)
if s[1] >= 510: # tla
launched = False
font = pygame.font.Font(None, 30)
text_ang = font.render("Kot = %d" % ang, 1, (10, 10, 10))
text_ang_pos = (1050, 50)
text_vm = font.render("Hitrost = %.1f m/s" % vm, 1, (10, 10, 10))
text_vm_pos = (1050, 80)
text_stat = font.render("Statistika:", 1, (10, 10, 10))
text_stat_pos = (1050, 20)
text_x = font.render("Dolžina = %.1f m" % s[0], 1, (10, 10, 10))
text_x_pos = (1050, 110)
text_t = font.render("Čas = %.1f s" % t, 1, (10, 10, 10))
text_t_pos = (1050, 140)
SCENE.blit(backgroundImg, (0,0))
SCENE.blit(cannonMovImg, cannonPos)
SCENE.blit(ballImg, s)
SCENE.blit(cannonBaseImg, cannonBasePos)
SCENE.blit(enemy, enemyPos) #<--- while loop breaks here
SCENE.blit(text_t, text_t_pos)
SCENE.blit(text_stat, text_stat_pos)
SCENE.blit(text_vm, text_vm_pos)
SCENE.blit(text_x, text_x_pos)
SCENE.blit(text_ang, text_ang_pos)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_SPACE:
ballPos = (0,478)
s = ballPos
t = 0
launched = True
v0 = (vm*cos(radians(ang)), -vm*sin(radians(ang)))
keystate = pygame.key.get_pressed()
if keystate[K_LEFT]:
ang+=2
if ang > 90:
ang = 90
cannonMovImg = rot_center(cannonImg, ang)
if keystate[K_RIGHT]:
ang-=2
if ang < 0:
ang = 0
cannonMovImg = rot_center(cannonImg, ang)
if keystate[K_UP]:
vm+=2
if keystate[K_DOWN]:
vm-=2
pygame.display.flip() #<-- while should end here
I've tried everything but even my teacher doesnt know the anwser. He said it's a bug in Python 3.6.3. Any ideas. I've researched for the past week and im frustrated. If anyone has any ideas please let me know. Thanks for your anwsers in advance

Categories

Resources