So my code as been acting up and I don't know what the problem is. When I try to test the file "Battle" it works like it supposed to and everything is fine. It pulls up a tkinter window like I want to, shows the buttons, My sprites, etc. But when I use my main file to run the Battle file it doesn't show the buttons, listbox, or sprites. I looked all over my code and I cant find out whats wrong. If anyone could help me then that would be great! It's a lot of code and I am kinda a rookie so it may not be the cleanest but I do leave a lot of notes.
This is the Battle code:
import tkinter as tk
import random
import time
inBattle = False
gameOver = True
i = 0
enemy_type = 0
MAX_HP = 60
MAX_MP = 40
HPval = 20
MPval = 30
POTIONSval = 3
#test
def add_text(recap):
global i
recap.insert(0, 'Damage: ' + str(i))
i += 1
#switch to turn the whole thing on or off
def GameOver():
global gameOver
if gameOver == True:
gameOver = False
else:
gameOver = True
#spells
def Cast_Fireball(spells, MP, recap):
global MPval
if MPval - 10 > 0 or MPval - 10 == 0:
MPval -= 10
MP.config(text='MP: ' + str(MPval))
hit = random.randint(0, 100)
damage = random.randint(1,10) # 1d10
if hit > 9: # 90%
recap.insert(0, 'Hit for ' + str(damage))
spells.destroy()
else:
recap.insert(0, 'Missed!')
spells.destroy()
else:
recap.insert(0, 'Not enough mana.')
spells.destroy()
def Cast_Iceball(spells, MP, recap):
global MPval
if MPval - 12 > 0 or MPval - 12 == 0:
MPval -= 12
MP.config(text='MP: ' + str(MPval))
hit = random.randint(0, 100)
damage = random.randint(1,6) * 2 # 2d6
if hit > 4: # 95%
recap.insert(0, 'Hit for ' + str(damage))
spells.destroy()
else:
recap.insert(0, 'Missed!')
spells.destroy()
else:
recap.insert(0, 'Not enough mana.')
spells.destroy()
def Cast_Heal(spells, HP, MP, recap):
global MPval
global HPval
if MPval - 15 > 0 or MPval - 15 == 0:
if HPval < MAX_HP:
MPval -= 15
MP.config(text='MP: ' + str(MPval))
damage = random.randint(7,25) # 2d10 + 5
if HPval + damage > MAX_HP:
damage = MAX_HP - HPval
recap.insert(0, 'Healed for ' + str(damage))
HPval += damage
HP.config(text='HP: ' + str(HPval))
spells.destroy()
else:
recap.insert(0, 'Not enough mana.')
spells.destroy()
def Cast_Drain(spells, MP, recap):
global MPval
hit = random.randint(0, 100)
damage = random.randint(1,6) # 1d6
if hit > 19: # 80%
recap.insert(0, 'Hit for ' + str(damage))
recap.insert(0, 'Recovered some mana!')
MPval += damage
MP.config(text='MP: ' + str(MPval))
spells.destroy()
else:
recap.insert(0, 'Missed!')
spells.destroy()
#activates window for spell list
def Spell_list(HP, MP, recap):
spells = tk.Tk()
spells.title("Spell List")
spells.minsize(150,168)
Fireball = tk.Button(spells, text='Fireball', bg='black', font=("arial", 15, "bold"), fg="white", width=12, command= lambda: Cast_Fireball(spells, MP, recap))
Fireball.pack()
Iceball = tk.Button(spells, text='Iceball', bg='black', font=("arial", 15, "bold"), fg="white", width=12, command= lambda: Cast_Iceball(spells, MP, recap))
Iceball.pack()
Mana_Drain = tk.Button(spells, text='Mana Drain', bg='black', font=("arial", 15, "bold"), fg="white", width=12, command= lambda: Cast_Drain(spells, MP, recap))
Mana_Drain.pack()
Crude_Heal = tk.Button(spells, text='Crude Heal', bg='black', font=("arial", 15, "bold"), fg="white", width=12, command= lambda: Cast_Heal(spells, HP, MP, recap))
Crude_Heal.pack()
spells.mainloop()
#drinks a max hp potion and checks if your full already and doesn't use it
def Drink_Potion(HP,POTIONS,recap):
global HPval
global POTIONSval
if POTIONSval > 0 and HPval < MAX_HP:
temp = MAX_HP - HPval
HPval = MAX_HP
POTIONSval -= 1
recap.insert(0, 'Healed for ' + str(temp))
HP.config(text="HP: " + str(HPval))
POTIONS.config(text="Potions: " + str(POTIONSval))
#main fucntion
def Battle():
#trigger so the player on the other screen is stopped and cant move
global inBattle
global HPval
global MPval
global POTIONSval
global enemy_type
inBattle = True
#screen settings
screen = tk.Tk()
screen.title("Encounter")
screen.minsize(1000,500)
screen.configure(bg='black')
#background settings and rectangle for the bottom half of screen
canvas = tk.Canvas(screen, width=1000, height=500)
canvas.configure(bg='black')
canvas.pack()
canvas.create_rectangle(3,300,1000,500,fill='white')
sprites = tk.Canvas(screen, width=200, height=200, bg='black')
sprites.place(x=285, y=50)
#choses which enemy to fight
#enemy_type = random.randint(0,6)
#spawning of the enemy
if enemy_type == 0:
img = tk.PhotoImage(file='sprites/slime.png')
sprites.create_image(20,20, image=img, anchor="nw")
#box on right to list the past actions
recap = tk.Listbox(screen, font=("arial", 14), bg="white", width=22, height=12)
recap.place(x=754, y=10)
#trackers for health, mana, and potions
HP = tk.Label(screen, text="HP: " + str(HPval), font=("arial",30), bg="white")
HP.place(x=775, y=310)
MP = tk.Label(screen, text="MP: " + str(MPval), font=("arial",30), bg="white")
MP.place(x=775, y=360)
Potions = tk.Label(screen, text="Potions: " + str(POTIONSval), font=("arial",30), bg="white")
Potions.place(x=775, y=410)
#buttons for commands
Attack = tk.Button(screen,text="Attack",width=9, height=4, bg="black", fg="white", font=("arial", 24, "bold"), command= lambda: add_text(recap))
Attack.place(x=10, y= 313)
Defend = tk.Button(screen,text="Defend",width=9, height=4, bg="black", fg="white", font=("arial", 24, "bold"))
Defend.place(x=200, y= 313)
Item = tk.Button(screen,text="Item",width=9, height=4, bg="black", fg="white", font=("arial", 24, "bold"), command= lambda: Drink_Potion(HP, Potions, recap))
Item.place(x=390, y= 313)
Magic = tk.Button(screen,text="Magic",width=9, height=4, bg="black", fg="white", font=("arial", 24, "bold"), command= lambda: Spell_list(HP, MP, recap))
Magic.place(x=580, y= 313)
screen.mainloop()
#testing purposes / comment out on release
#Battle()
This is the Main code:
import random
import turtle
import tkinter as tk
import time
import Battle
callOnce = False
GWIDTH = 800
GHEIGHT = 800
SWIDTH = 50
SHEIGHT = 50
START_Y = 0
END_Y = 0
PLAYER_X = 0
PLAYER_Y = 0
BUFFER = 80
DungeonCord = []
DungeonStorage = []
Treasure = []
pathingPlaces = []
pathingAmount = 0
start = tk.Tk()
start.title("Dungeon Generator")
start.minsize(500,500)
#generate function making it save the set x and y and passing it to the turtle functions
def Generate():
global GHEIGHT
global GWIDTH
Battle.GameOver()
GWIDTH = xInsert.get()
GHEIGHT = yInsert.get()
start.destroy()
DunGenText = tk.Label(text="Dungeon Generator", relief="solid", width = 20, font=("arial", 24, "bold"))
DunGenText.place(x=60, y=35)
xLabel = tk.Label(text="X Grid Count:", width = 10, font=("arial", 14))
xLabel.place(x=145,y=145)
xInsert = tk.Entry(start, width=5)
xInsert.place(x=280,y=150)
yLabel = tk.Label(text="Y Grid Count:", width = 10, font=("arial", 14))
yLabel.place(x=145,y=245)
yInsert = tk.Entry(start, width=5)
yInsert.place(x=280,y=250)
button = tk.Button(start,text="Generate",width=30, bg="black", fg="white", command=Generate)
button.place(x=135, y=450)
start.mainloop()
#main loop for the turtle side of things
while not Battle.gameOver:
#window settings
wn = turtle.Screen()
wn.title("Dungeon Crawler")
wn.setup(width=(int(GWIDTH) * int(SWIDTH))+BUFFER, height=(int(GHEIGHT) * int(SHEIGHT))+BUFFER)
wn.bgcolor("black")
wn.tracer(0)
#where the grid would start to draw itself
Gridx = (int(GWIDTH) * int(SWIDTH) * -1) / 2
Gridy = (int(GHEIGHT) * int(SHEIGHT)) /2
#this will determine the lowest number between the x axis and the y axis
if int(GWIDTH) > int(GHEIGHT):
LOWEST = int(GHEIGHT)
else:
LOWEST = int(GWIDTH)
#this is the formula for the dungeon count in the grid // ((x * y) - 2y) / l
DCOUNT = ((int(GHEIGHT) * int(GWIDTH)) - (2 * int(GHEIGHT))) / int(LOWEST)
#the function to draw the grid
def draw_grid(t, x, y, sx, sy,):
for i in range(int(y)):
for j in range(int(x)):
t.penup()
t.goto(x= Gridx + (sx * int(j)), y= Gridy - (sy * int(i)))
t.pendown()
t.forward(sx)
t.right(90)
t.forward(sx)
t.right(90)
t.forward(sx)
t.right(90)
t.forward(sx)
t.right(90)
#function to draw a square at a location
def draw_square(t, s):
for i in range(4):
t.forward(int(s) * 20)
t.right(90)
#drawing the circle on the left side that would be the start
def draw_start(t, t2):
global START_Y
global PLAYER_Y
START_Y = random.randint(0, int(GHEIGHT) - 1)
PLAYER_Y = START_Y
t.penup()
t.goto(x= Gridx + (SWIDTH / 2), y= (Gridy - (SHEIGHT / 2)) - (SHEIGHT * START_Y) - 10)
t.pendown()
t.circle(10)
t2.penup()
t2.goto(x= Gridx + (SWIDTH / 2), y= (Gridy - (SHEIGHT / 2)) - (SHEIGHT * START_Y))
t2.pendown()
draw_player(t2)
#drawing a circle on the right side that would be the end
def draw_end(t):
global END_Y
END_Y = random.randint(0, int(GHEIGHT) - 1)
t.penup()
t.goto(x= (Gridx + (SWIDTH / 2)) * -1, y= (Gridy - (SHEIGHT / 2)) - (SHEIGHT * END_Y) - 10)
t.pendown()
t.circle(10)
#draws the player at its location
def draw_player(t):
t.penup()
t.goto(x= (Gridx + (SWIDTH / 2)) + (SWIDTH * PLAYER_X) - 10, y= (Gridy - (SHEIGHT / 2)) - (SHEIGHT * PLAYER_Y)+3)
t.pendown()
for i in range(50):
t.forward(20)
t.right(144)
#drawing the dungeon at random locations that can be anyware between the entrance and the exit.
def draw_dungeons(t, d):
global DungeonCord
global Treasure
for i in range(int(d)):
closestX = random.randint(1, int(GWIDTH) - 2)
closestY = random.randint(0, int(GHEIGHT) - 1)
DungeonCord.append((closestX,closestY))
DungeonStorage.append((closestX,closestY))
for j in range(i):
if DungeonCord[j] == DungeonCord[i]:
closestX = random.randint(1, int(GWIDTH) - 2)
closestY = random.randint(0, int(GHEIGHT) - 1)
DungeonCord[i] = (closestX,closestY)
DungeonStorage[i] = (closestX,closestY)
if DungeonCord[j] == DungeonCord[i]:
closestX = random.randint(1, int(GWIDTH) - 2)
closestY = random.randint(0, int(GHEIGHT) - 1)
DungeonCord[i] = (closestX,closestY)
DungeonStorage[i] = (closestX,closestY)
#treasure room chance
TR = random.randint(1,5)
if TR == 5:
t.color("yellow")
Treasure.append(DungeonCord[i])
t.penup()
t.goto(x= (Gridx + (SWIDTH / 2)) + (SWIDTH * closestX) - 10, y= (Gridy - (SHEIGHT / 2)) - (SHEIGHT * closestY) + 10)
t.pendown()
draw_square(t, 1)
t.color("white")
#the pathmaking function that would go to each dungeon and from the start to the end
def draw_path(t):
global DungeonCord
global START_Y
global END_Y
global DCOUNT
global pathingAmount
global pathingPlaces
t.penup()
t.goto(x= Gridx + (SWIDTH / 2), y= (Gridy - (SHEIGHT / 2)) - (SHEIGHT * START_Y))
t.pendown()
myCordsx = 0
myCordsy = START_Y
dungeon = 0
for j in range(int(DCOUNT)):
traveling = True
closestX = 500
closestY = 500
#finds the closest dungeon
for i in range(int(DCOUNT)):
x, y = DungeonCord[i]
if abs(x - myCordsx) + abs(y - myCordsy) < abs(closestX - myCordsx) + abs(closestY - myCordsy):
closestX, closestY = x, y
dungeon = i
elif abs(x - myCordsx) + abs(y - myCordsy) == abs(closestX - myCordsx) + abs(closestY - myCordsy):
if x < closestX:
closestX, closestY = x, y
dungeon = i
#path to the current closest dungeon
while traveling:
if closestX > myCordsx: #path right
t.forward(int(SWIDTH))
myCordsx += 1
pathingPlaces.append((myCordsx, myCordsy))
pathingAmount +=1
elif closestY > myCordsy: #path down
t.right(90)
t.forward(int(SWIDTH))
t.left(90)
myCordsy += 1
pathingPlaces.append((myCordsx, myCordsy))
pathingAmount +=1
elif closestX < myCordsx: #path left
t.right(180)
t.forward(int(SWIDTH))
t.left(180)
myCordsx -= 1
pathingPlaces.append((myCordsx, myCordsy))
pathingAmount +=1
elif closestY < myCordsy: #path up
t.left(90)
t.forward(int(SWIDTH))
t.right(90)
myCordsy -= 1
pathingPlaces.append((myCordsx, myCordsy))
pathingAmount +=1
else:
traveling = False
i = 0 #reset on counter
DungeonCord[dungeon] = (99, 99) #null entry / dungeon is checked off
#pathing to the end
traveling = True
while traveling:
if int(GWIDTH) - 1 > myCordsx: #going right
t.forward(int(SWIDTH))
myCordsx += 1
pathingPlaces.append((myCordsx, myCordsy))
pathingAmount +=1
elif END_Y > myCordsy: #going down
t.right(90)
t.forward(int(SWIDTH))
t.left(90)
myCordsy += 1
pathingPlaces.append((myCordsx, myCordsy))
pathingAmount +=1
elif int(GWIDTH) - 1 != myCordsx and END_Y == myCordsy: #going left
t.right(180)
t.forward(int(SWIDTH))
t.left(180)
myCordsx -= 1
pathingPlaces.append((myCordsx, myCordsy))
pathingAmount +=1
elif int(GWIDTH) - 1 == myCordsx and END_Y != myCordsy: #going up
t.left(90)
t.forward(int(SWIDTH))
t.right(90)
myCordsy -= 1
pathingPlaces.append((myCordsx, myCordsy))
pathingAmount +=1
else:
traveling = False
#all the turtle units involved in drawing
grid = turtle.Turtle()
grid.hideturtle()
grid.pencolor("white")
entrance = turtle.Turtle()
entrance.hideturtle()
entrance.pencolor("green")
end = turtle.Turtle()
end.hideturtle()
end.pencolor("red")
dun = turtle.Turtle()
dun.hideturtle()
dun.pencolor("white")
dun.shape("square")
path = turtle.Turtle()
path.hideturtle()
path.pencolor("green")
player = turtle.Turtle()
player.hideturtle()
player.pencolor("pink")
#player movement
def moveUP():
global PLAYER_X
global PLAYER_Y
for i in range(pathingAmount):
if (PLAYER_X, PLAYER_Y - 1) == pathingPlaces[i] and not Battle.inBattle:
PLAYER_Y -= 1
player.clear()
draw_player(player)
for i in range(int(DCOUNT)):
if (PLAYER_X, PLAYER_Y) == DungeonStorage[i]:
Battle.Battle()
break
def moveDOWN():
global PLAYER_X
global PLAYER_Y
for i in range(pathingAmount):
if (PLAYER_X, PLAYER_Y + 1) == pathingPlaces[i] and not Battle.inBattle:
PLAYER_Y += 1
player.clear()
draw_player(player)
for i in range(int(DCOUNT)):
if (PLAYER_X, PLAYER_Y) == DungeonStorage[i]:
Battle.Battle()
break
def moveLEFT():
global PLAYER_X
global PLAYER_Y
for i in range(pathingAmount):
if (PLAYER_X - 1, PLAYER_Y) == pathingPlaces[i] and not Battle.inBattle:
PLAYER_X -= 1
player.clear()
draw_player(player)
for i in range(int(DCOUNT)):
if (PLAYER_X, PLAYER_Y) == DungeonStorage[i]:
Battle.Battle()
break
def moveRIGHT():
global PLAYER_X
global PLAYER_Y
for i in range(pathingAmount):
if (PLAYER_X + 1, PLAYER_Y) == pathingPlaces[i] and not Battle.inBattle:
PLAYER_X += 1
player.clear()
draw_player(player)
for i in range(int(DCOUNT)):
if (PLAYER_X, PLAYER_Y) == DungeonStorage[i]:
Battle.Battle()
break
#a call once function so the dungeons, start, and end doesn't keep drawing.
if callOnce == False:
draw_grid(grid, GWIDTH, GHEIGHT, SWIDTH, SHEIGHT)
draw_start(entrance, player)
draw_end(end)
draw_dungeons(dun, DCOUNT)
draw_path(path)
callOnce = True
wn.listen()
wn.onkey(moveRIGHT, "d")
wn.onkey(moveUP, "w")
wn.onkey(moveLEFT, "a")
wn.onkey(moveDOWN, "s")
while True:
wn.update()
Never Mind, the problem was tkinter itself. Just needed to change the tk.Tk() in my battle code to tk.Toplevel() since you cant have two tk.Tk() code. Well..... Damn
Related
Im new to the world of algorithms. I created my first NEAT AI using python. This was originally for a school project, but the school doesn't let us install any software on the computers. Therefore, I wanted to make a .exe file from a .py file. I've done this several times, this time it didn't work though. I'm guessing it's because it has NEAT involved. In case anybody is interested, here's the code I use(flappy bird with AI):
import pygame
import neat
import time
import os
import random
pygame.font.init()
WIN_WIDTH = 500
WIN_HEIGHT = 800
GEN = 0
BIRD_IMGS = [pygame.transform.scale2x(pygame.image.load("bird1.png")),
pygame.transform.scale2x(pygame.image.load("bird2.png")),
pygame.transform.scale2x(pygame.image.load("bird3.png"))]
PIPE_IMG = pygame.transform.scale2x(pygame.image.load("pipe.png"))
BASE_IMG = pygame.transform.scale2x(pygame.image.load("base.png"))
BG_IMG = pygame.transform.scale2x(pygame.image.load("bg.png"))
STAT_FONT = pygame.font.SysFont("comicsans", 50)
class Bird:
IMGS = BIRD_IMGS
MAX_ROTATION = 25
ROT_VEL = 25
ANIMATION_TIME = 5
def __init__(self, x, y):
self.x = x
self.y = y
self.tilt = 0
self.tick_count = 0
self.vel = 0
self.height = self.y
self.img_count = 0
self.img = self.IMGS[0]
def jump(self):
self.vel = -10.5
self.tick_count = 0
self.height = self.y
def move(self):
self.tick_count += 1
d = self.vel*self.tick_count + 1.5*self.tick_count**2
if d >= 16:
d = 16
if d < 0:
d -= 2
self.y = self.y + d
if d < 0 or self.y < self.height + 50:
if self.tilt < self.MAX_ROTATION:
self.tilt = self.MAX_ROTATION
else:
if self.tilt > -90:
self.tilt -= self.ROT_VEL
def draw(self, win):
self.img_count += 1
if self.img_count < self.ANIMATION_TIME:
self.img = self.IMGS[0]
elif self.img_count < self.ANIMATION_TIME*2:
self.img = self.IMGS[1]
elif self.img_count < self.ANIMATION_TIME*3:
self.img = self.IMGS[2]
elif self.img_count < self.ANIMATION_TIME*4:
self.img = self.IMGS[1]
elif self.img_count == self.ANIMATION_TIME*4 + 1:
self.img = self.IMGS[0]
self.img_count = 0
if self.tilt <= -80:
self.img = self.IMGS[1]
self.img_count = self.ANIMATION_TIME*2
rotated_image = pygame.transform.rotate(self.img, self.tilt)
new_rect = rotated_image.get_rect(center=self.img.get_rect(topleft= (self.x, self.y)).center)
win.blit(rotated_image, new_rect.topleft)
def get_mask(self):
return pygame.mask.from_surface(self.img)
class Pipe:
GAP = 200
VEL = 5
def __init__(self, x):
self.x = x
self.height = 0
self.top = 0
self.bottom = 0
self.PIPE_TOP = pygame.transform.flip(PIPE_IMG, False, True)
self.PIPE_BOTTOM = PIPE_IMG
self.passed = False
self.get_height()
def get_height(self):
self.height = random.randrange(50, 450)
self.top = self.height - self.PIPE_TOP.get_height()
self.bottom = self.height + self.GAP
def move(self):
self.x -= self.VEL
def draw(self, win):
win.blit(self.PIPE_TOP, (self.x, self.top))
win.blit(self.PIPE_BOTTOM, (self.x, self.bottom))
def collide(self, bird):
bird_mask = bird.get_mask()
top_mask = pygame.mask.from_surface(self.PIPE_TOP)
bottom_mask = pygame.mask.from_surface(self.PIPE_BOTTOM)
top_offset = (self.x - bird.x, self.top - round(bird.y))
bottom_offset = (self.x - bird.x, self.bottom - round(bird.y))
b_point = bird_mask.overlap(bottom_mask, bottom_offset)
t_point = bird_mask.overlap(top_mask, top_offset)
if t_point or b_point:
return True
return False
class Base:
VEL = 5
WIDTH = BASE_IMG.get_width()
IMG = BASE_IMG
def __init__(self, y):
self.y = y
self.x1 = 0
self.x2 = self.WIDTH
def move(self):
self.x1 -= self.VEL
self.x2 -= self.VEL
if self.x1 + self.WIDTH < 0:
self.x1 = self.x2 + self.WIDTH
if self.x2 + self.WIDTH < 0:
self.x2 = self.x1 + self.WIDTH
def draw(self, win):
win.blit(self.IMG, (self.x1, self.y))
win.blit(self.IMG, (self.x2, self.y))
def draw_window(win, birds, pipes, base, score, gen):
win.blit(BG_IMG, (0,0))
for pipe in pipes:
pipe.draw(win)
text = STAT_FONT.render("Pontok: " + str(score), 1, (255,255,255))
win.blit(text, (WIN_WIDTH - 10 - text.get_width(), 10))
text = STAT_FONT.render("Generáció: " + str(gen), 1, (255,255,255))
win.blit(text, (10, 10))
base.draw(win)
for bird in birds:
bird.draw(win)
pygame.display.update()
def main(genomes, config):
global GEN
GEN += 1
nets = []
ge = []
birds = []
for _, g in genomes:
net = neat.nn.FeedForwardNetwork.create(g, config)
nets.append(net)
birds.append(Bird(230, 350))
g.fitness = 0
ge.append(g)
score = 0
base = Base(730)
pipes = [Pipe(600)]
win = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT))
clock = pygame.time.Clock()
run = True
while run:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
quit()
pipe_ind = 0
if len(birds) > 0:
if len(pipes) > 1 and birds[0].x > pipes[0].x + pipes[0].PIPE_TOP.get_width():
pipe_ind = 1
else:
run = False
break
for x, bird in enumerate(birds):
bird.move()
ge[x].fitness += 0.1
output = nets[x].activate((bird.y, abs(bird.y - pipes[pipe_ind].height), abs(bird.y - pipes[pipe_ind].bottom)))
if output[0] > 0.5:
bird.jump()
add_pipe = False
rem = []
base.move()
for pipe in pipes:
for x, bird in enumerate(birds):
if pipe.collide(bird):
ge[x].fitness -= 1
birds.pop(x)
nets.pop(x)
ge.pop(x)
if not pipe.passed and pipe.x < bird.x:
pipe.passed = True
add_pipe = True
if pipe.x + pipe.PIPE_TOP.get_width() < 0:
rem.append(pipe)
pipe.move()
if add_pipe:
score += 1
for g in ge:
g.fitness += 5
pipes.append(Pipe(600))
for r in rem:
pipes.remove(r)
for x, bird in enumerate(birds):
if bird.y + bird.img.get_height() >= 730 or bird.y < 0:
birds.pop(x)
nets.pop(x)
ge.pop(x)
draw_window(win, birds, pipes, base, score, GEN)
def run(config_path):
config = neat.config.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet,
neat.DefaultStagnation, config_path)
p = neat.Population(config)
p.add_reporter(neat.StdOutReporter(True))
stats = neat.StatisticsReporter()
p.add_reporter(stats)
winner = p.run(main,20)
if __name__ == "__main__":
local_dir = os.path.dirname(__file__)
config_path = os.path.join(local_dir, "config_feedforward.txt")
run(config_path)
When I run the .exe file, the console appears, and shows:
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
And then stops.
when I run the .py file, it starts the AIs normally and says something like:
******* Running Generation 1 *******
The pyinstaller command I use:
pyinstaller --onefile game.py
I didnt find any solutions to this yet, and I've been browsing for 2 days.
I get no errors when running it from cmd. I also get some "hidden import not found" warnings in pyinstaller while building but I don't think that should be a problem.
I've tried by referencing the /imgs library and config-feedforward.txt but it didn't work that way either. Any help is appreciated. Sorry for any typos or bad english.
Have a nice day!
So, I have been trying to implement water physics in pygame based on this tutorial
https://gamedevelopment.tutsplus.com/tutorials/make-a-splash-with-dynamic-2d-water-effects--gamedev-236
The issue is, when I implemented this code in pygame, the water decides that instead of having a nice ripple effect, its going to go crazy and wiggle all over the screen until it eventually crashes.
I looked around on some discord server and found someone else had tried to implement the same thing, and had got the same problem. Their code is basically the same as mine just more neatly organized so I will post it instead of mine.
import pygame, random
import math as m
from pygame import *
pygame.init()
WINDOW_SIZE = (854, 480)
screen = pygame.display.set_mode(WINDOW_SIZE,0,32) # initiate the window
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 18)
class surface_water_particle():
def __init__(self, x,y):
self.x_pos = x
self.y_pos = y
self.target_y = y
self.velocity = 0
self.k = 0.02
self.d = 0.02
self.time = 1
def update(self):
x = -(self.target_y - self.y_pos)
a = -(self.k * x - self.d * self.velocity)
self.y_pos += self.velocity
self.velocity += a
class water():
def __init__(self, x_start, x_end, y_start, y_end, segment_length):
self.springs = []
self.x_start = x_start
self.y_start = y_start
self.x_end = x_end
self.y_end = y_end - 10
for i in range(abs(x_end - x_start) // segment_length):
self.springs.append(surface_water_particle(i * segment_length + x_start, y_end))
def update(self, spread):
for i in range(len(self.springs)):
self.springs[i].update()
leftDeltas = [0] * len(self.springs)
rightDeltas = [0] * len(self.springs)
for i in range(0, len(self.springs) ):
if i > 0:
leftDeltas[i] = spread * (self.springs[i].y_pos - self.springs[i - 1].y_pos)
self.springs[i - 1].velocity += leftDeltas[i]
if i < len(self.springs) - 1:
rightDeltas[i] = spread * (self.springs[i].y_pos - self.springs[i + 1].y_pos)
self.springs[i + 1].velocity += rightDeltas[i]
for i in range(0, len(self.springs) ):
if i > 0:
self.springs[i - 1].velocity += leftDeltas[i]
if i < len(self.springs) - 1:
self.springs[i + 1].velocity += rightDeltas[i]
def splash(self, index, speed):
if index > 0 and index < len(self.springs) :
self.springs[index].velocity = speed
def draw(self):
water_surface = pygame.Surface((abs(self.x_start - self.x_end), abs(self.y_start - self.y_end))).convert_alpha()
water_surface.fill((0,0,0,0))
water_surface.set_colorkey((0,0,0,0))
polygon_points = []
polygon_points.append((self.x_start, self.y_start))
for spring in range(len(self.springs)):
polygon_points.append((water_test.springs[spring].x_pos, water_test.springs[spring].y_pos))
polygon_points.append((water_test.springs[len(self.springs) - 1].x_pos, self.y_start))
#pygame.draw.polygon(water_surface, (0,0,255), polygon_points)
for spring in range(0,len(self.springs) - 1):
pygame.draw.line(screen, (0,0,255), (water_test.springs[spring].x_pos, water_test.springs[spring].y_pos), (water_test.springs[spring + 1].x_pos, water_test.springs[spring + 1].y_pos), 2)
#water_surface.set_alpha(100)
return water_surface
def update_fps():
fps_text = font.render(str(int(clock.get_fps())), 1, pygame.Color("coral"))
screen.blit(fps_text, (0,0))
water_test = water(0,800,200,80, 20)
while True:
screen.fill((255,255,255))
water_test.update(0.5)
screen.blit(water_test.draw(), (0,0))
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
if event.type == MOUSEBUTTONDOWN:
water_test.splash(10,0.1)
pygame.display.update()
clock.tick(60)
I tried looking for any issues with our implementations of the tutorial but I could not find anything that seemed out of place. I then tried adding a resistance function that would divide the water velocity each time it updates. This however did not fix the issue.
Does anyone know what was done wrong and how to fix this?
Many of the same observations as the other post. I commented a few things up, changed your velocity statement a bit. And in the "spreading" I added the passes.
Tinkered with the numbers a bit, and got some real nice splashes. (better than the accepted solution! :( lol.
If you need to troubleshoot this some more, I would suggest you comment out the spreading piece (or give it a value of zero) and you can check the springiness of the water by itself. This made it much easier to T/S.
import pygame, random
import math as m
from pygame import *
pygame.init()
WINDOW_SIZE = (854, 480)
screen = pygame.display.set_mode(WINDOW_SIZE,0,32) # initiate the window
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 18)
class surface_water_particle():
k = 0.04 # spring constant
d = 0.08 # damping constant
def __init__(self, x,y):
self.x_pos = x
self.y_pos = y
self.target_y = y
self.velocity = 0
def update(self):
x = self.y_pos - self.target_y # displacement of "spring"
a = -self.k * x - self.d * self.velocity # unit of acceleration
self.y_pos += self.velocity
self.velocity += a
class water():
def __init__(self, x_start, x_end, y_start, y_end, segment_length):
self.springs = []
self.x_start = x_start
self.y_start = y_start
self.x_end = x_end
self.y_end = y_end - 10
for i in range(abs(x_end - x_start) // segment_length):
self.springs.append(surface_water_particle(i * segment_length + x_start, y_end))
def update(self, spread):
passes = 4 # more passes = more splash spreading
for i in range(len(self.springs)):
self.springs[i].update()
leftDeltas = [0] * len(self.springs)
rightDeltas = [0] * len(self.springs)
for p in range(passes):
for i in range(0, len(self.springs) -1 ):
if i > 0:
leftDeltas[i] = spread * (self.springs[i].y_pos - self.springs[i - 1].y_pos)
self.springs[i - 1].velocity += leftDeltas[i]
if i < len(self.springs) - 1:
rightDeltas[i] = spread * (self.springs[i].y_pos - self.springs[i + 1].y_pos)
self.springs[i + 1].velocity += rightDeltas[i]
for i in range(0, len(self.springs) -1):
if i > 0:
self.springs[i - 1].y_pos += leftDeltas[i] # you were updating velocity here!
if i < len(self.springs) - 1:
self.springs[i + 1].y_pos += rightDeltas[i]
def splash(self, index, speed):
if index > 0 and index < len(self.springs) :
self.springs[index].velocity = speed
def draw(self):
water_surface = pygame.Surface((abs(self.x_start - self.x_end), abs(self.y_start - self.y_end))).convert_alpha()
water_surface.fill((0,0,0,0))
water_surface.set_colorkey((0,0,0,0))
polygon_points = []
polygon_points.append((self.x_start, self.y_start))
for spring in range(len(self.springs)):
polygon_points.append((water_test.springs[spring].x_pos, water_test.springs[spring].y_pos))
polygon_points.append((water_test.springs[len(self.springs) - 1].x_pos, self.y_start))
#pygame.draw.polygon(water_surface, (0,0,255), polygon_points)
for spring in range(0,len(self.springs) - 1):
pygame.draw.line(screen, (0,0,255), (water_test.springs[spring].x_pos, water_test.springs[spring].y_pos), (water_test.springs[spring + 1].x_pos, water_test.springs[spring + 1].y_pos), 2)
#water_surface.set_alpha(100)
return water_surface
def update_fps():
fps_text = font.render(str(int(clock.get_fps())), 1, pygame.Color("coral"))
screen.blit(fps_text, (0,0))
water_test = water(0,800,200,200, 3)
while True:
screen.fill((255,255,255))
water_test.update(0.025)
screen.blit(water_test.draw(), (0,0))
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
if event.type == MOUSEBUTTONDOWN:
water_test.splash(50,100)
pygame.display.update()
clock.tick(60)
I modified the code to match the example exactly and at least it doesn't explode instantly any more.
The main problem seemed to be the loops with the deltas. Adjusting the code for the spring update and commenting those out lead to a nice oscillation which didn't stop, but also did not explode.
The outer loop seems to be important to ease everything out a bit.
I would think it is because of the added height, as changing the height changes the force of the spring.
import pygame, random
import math as m
from pygame import *
pygame.init()
WINDOW_SIZE = (854, 480)
screen = pygame.display.set_mode(WINDOW_SIZE,0,32) # initiate the window
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 18)
class surface_water_particle():
def __init__(self, x,y):
self.x_pos = x
self.y_pos = y
self.target_y = y
self.velocity = 0
self.k = 0.02
self.d = 0.02
self.time = 1
def update(self):
x = self.y_pos - self.target_y #this was overly complicated for some reason
a = -self.k * x - self.d * self.velocity #here was a wrong sign for the dampening
self.y_pos += self.velocity
self.velocity += a
class water():
def __init__(self, x_start, x_end, y_start, y_end, segment_length):
self.springs = []
self.x_start = x_start
self.y_start = y_start
self.x_end = x_end
self.y_end = y_end - 10
for i in range(abs(x_end - x_start) // segment_length):
self.springs.append(surface_water_particle(i * segment_length + x_start, y_end))
def update(self, spread):
for i in range(len(self.springs)):
self.springs[i].update()
leftDeltas = [0] * len(self.springs)
rightDeltas = [0] * len(self.springs)
# adding this outer loop gave the real success
for j in range(0,8):
for i in range(0, len(self.springs) ):
if i > 0:
leftDeltas[i] = spread * (self.springs[i].y_pos - self.springs[i - 1].y_pos)
self.springs[i - 1].velocity += leftDeltas[i]
if i < len(self.springs) - 1:
rightDeltas[i] = spread * (self.springs[i].y_pos - self.springs[i + 1].y_pos)
self.springs[i + 1].velocity += rightDeltas[i]
# here you used velocity instead of height before
for i in range(0, len(self.springs) ):
if i > 0:
self.springs[i - 1].y_pos += leftDeltas[i]
if i < len(self.springs) - 1:
self.springs[i + 1].y_pos += rightDeltas[i]
def splash(self, index, speed):
if index > 0 and index < len(self.springs) :
self.springs[index].velocity = speed
def draw(self):
water_surface = pygame.Surface((abs(self.x_start - self.x_end), abs(self.y_start - self.y_end))).convert_alpha()
water_surface.fill((0,0,0,0))
water_surface.set_colorkey((0,0,0,0))
polygon_points = []
polygon_points.append((self.x_start, self.y_start))
for spring in range(len(self.springs)):
polygon_points.append((water_test.springs[spring].x_pos, water_test.springs[spring].y_pos))
polygon_points.append((water_test.springs[len(self.springs) - 1].x_pos, self.y_start))
#pygame.draw.polygon(water_surface, (0,0,255), polygon_points)
for spring in range(0,len(self.springs) - 1):
pygame.draw.line(screen, (0,0,255), (water_test.springs[spring].x_pos, water_test.springs[spring].y_pos), (water_test.springs[spring + 1].x_pos, water_test.springs[spring + 1].y_pos), 2)
#water_surface.set_alpha(100)
return water_surface
def update_fps():
fps_text = font.render(str(int(clock.get_fps())), 1, pygame.Color("coral"))
screen.blit(fps_text, (0,0))
water_test = water(0,800,200,80, 20)
while True:
screen.fill((255,255,255))
water_test.update(0.5)
screen.blit(water_test.draw(), (0,0))
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
if event.type == MOUSEBUTTONDOWN:
water_test.splash(10,0.1)
pygame.display.update()
clock.tick(60)
Generally, what you want is that the acceleration goes in the opposite direction of the height difference (it wants to restore the original position). The velocity should decreases and eventually get back to 0.
With the original code you had, even without the loops that perform the spread, the velocity increased instead of decreased.
The velocity will probably never reach 0, so you should probably also add a threshold where you will just set it to 0 so avoid flickering.
For debugging, always print your values and have a look if they make sense. In this case you would have noticed the velocity goes up even for the single spring update step.
Edit:
This answer fixes the issue but does not tweak parameters to make it look good. See Jeff H.'s answer for a good choice of parameters.
I'm currently finishing a Flappy Bird game in Python 3.8 that will be played by an AI that will learn by itself how to play the game and improve itself from its previous mistakes until a point where it will be "unbeatable". I'm really close to finish this but there's this error in my code:
NameError: name 'base' is not defined
This error wasn't appearing during the previous tests that I made. I looked into all the code that mentioned the base in the game but still, I couldn't find anything wrong. The game code is this:
import pygame
import neat
import time
import os
import random
pygame.font.init()
WIN_WIDTH = 500
WIN_HEIGHT = 800
BIRD_IMGS = [pygame.transform.scale2x(pygame.image.load(os.path.join('imgs', 'bird1.png'))), pygame.transform.scale2x(pygame.image.load(os.path.join('imgs', 'bird2.png'))), pygame.transform.scale2x(pygame.image.load(os.path.join('imgs', 'bird3.png')))]
PIPE_IMG = pygame.transform.scale2x(pygame.image.load(os.path.join('imgs', 'pipe.png')))
BASE_IMG = pygame.transform.scale2x(pygame.image.load(os.path.join('imgs', 'base.png')))
BG_IMG = pygame.transform.scale2x(pygame.image.load(os.path.join('imgs', 'bg.png')))
STAT_FONT = pygame.font.SysFont('comicsans', 50)
class Bird:
IMGS = BIRD_IMGS
MAX_ROTATION = 25
ROT_VEL = 20
ANIMATION_TIME = 5
def __init__(self, x, y):
self.x = x
self.y = y
self.tilt = 0
self.tick_count = 0
self.vel = 0
self.height = self.y
self.img_count = 0
self.img = self.IMGS[0]
def jump(self):
self.vel = -10.5
self.tick_count = 0
self.height = self.y
def move(self):
self.tick_count += 1
d = self.vel * self.tick_count + 1.5 * self.tick_count ** 2
if d >= 16:
d = 16
if d < 0:
d -= 2
self.y = self.y + d
if d < 0 or self.y < self.height + 50:
if self.tilt < self.MAX_ROTATION:
self.tilt = self.MAX_ROTATION
else:
if self.tilt > -90:
self.tilt -= self.ROT_VEL
def draw(self, win):
self.img_count += 1
if self.img_count < self.ANIMATION_TIME:
self.img = self.IMGS[0]
elif self.img_count < self.ANIMATION_TIME*2:
self.img = self.IMGS[1]
elif self.img_count < self.ANIMATION_TIME*3:
self.img = self.IMGS[2]
elif self.img_count < self.ANIMATION_TIME*4:
self.img = self.IMGS[1]
elif self.img_count == self.ANIMATION_TIME*4 + 1:
self.img = self.IMGS[0]
self.img_count = 0
if self.tilt <= -80:
self.img = self.IMGS[1]
self.img_count = self.ANIMATION_TIME*2
rotated_image = pygame.transform.rotate(self.img, self.tilt)
new_rect = rotated_image.get_rect(center=self.img.get_rect(topleft = (self.x, self.y)).center)
win.blit(rotated_image, new_rect.topleft)
def get_mask(self):
return pygame.mask.from_surface(self.img)
class Pipe:
GAP = 200
VEL = 5
def __init__(self, x):
self.x = x
self.height = 0
self.top = 0
self.bottom = 0
self.PIPE_TOP = pygame.transform.flip(PIPE_IMG, False, True)
self.PIPE_BOTTOM = PIPE_IMG
self.passed = False
self.set_height()
def set_height(self):
self.height = random.randrange(50, 450)
self.top = self.height - self.PIPE_TOP.get_height()
self.bottom = self.height + self.GAP
def move(self):
self.x -= self.VEL
def draw(self, win):
win.blit(self.PIPE_TOP, (self.x, self.top))
win.blit(self.PIPE_BOTTOM, (self.x, self.bottom))
def collide(self, bird):
bird_mask = bird.get_mask()
top_mask = pygame.mask.from_surface(self.PIPE_TOP)
bottom_mask = pygame.mask.from_surface(self.PIPE_BOTTOM)
top_offset = (self.x - bird.x, self.top - round(bird.y))
bottom_offset = (self.x - bird.x, self.bottom - round(bird.y))
b_point = bird_mask.overlap(bottom_mask, bottom_offset)
t_point = bird_mask.overlap(top_mask, top_offset)
if t_point or b_point:
return True
return False
class Base:
VEL = 5
WIDTH = BASE_IMG.get_width()
IMG = BASE_IMG
def __init__(self, y):
self.y = y
self.x1 = 0
self.x2 = self.WIDTH
def move(self):
self.x1 -= self.VEL
self.x2 -= self.VEL
if self.x1 + self.WIDTH < 0:
self.x1 = self.x2 + self.WIDTH
if self.x2 + self.WIDTH < 0:
self.x2 = self.x1 + self.WIDTH
def draw(self, win):
win.blit(self.IMG, (self.x1, self.y))
win.blit(self.IMG, (self.x2, self.y))
def draw_window(win, bird, pipes, base, score):
win.blit(BG_IMG, (0, 0))
for pipe in pipes:
pipe.draw(win)
text = STAT_FONT.render('Score: ' + str(score), 1, (255, 255, 255))
win.blit(text, (WIN_WIDTH - 10 - text.get_width(), 10))
base.draw(win)
for bird in birds:
bird.draw(win)
pygame.display.update()
def main(genomes, config):
nets = []
ge = []
birds = []
for _, g in genomes:
net = neat.nn.FeedForwardNetwork.create(g, config)
nets.append(net)
birds.append(Bird(230, 350))
g.fitness = 0
ge.append(g)
pipes = [Pipe(600)]
win = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT))
clock = pygame.time.Clock()
score = 0
run = True
while run:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
quit()
pipe_ind = 0
if len(birds) > 0:
if len(pipes) > 1 and birds[0].x > pipes[0].x + pipes[0].PIPE_TOP.get_width():
pipe_ind = 1
else:
run = False
break
for x, bird in enumerate(birds):
bird.move()
ge[x].fitness += 0.1
output = nets[x].activate((bird.y, abs(bird.y - pipes[pipe_ind].height), abs(bird.y - pipes[pipe_ind].bottom)))
if output[0] > 0.5:
bird.jump()
#bird.move()
add_pipe = False
rem = []
for pipe in pipes:
for x, bird in enumerate(birds):
if pipe.collide(bird):
ge[x].fitness -= 1
birds.pop(x)
nets.pop(x)
ge.pop(x)
if not pipe.passed and pipe.x < bird.x:
pipe.passed = True
add_pipe = True
if pipe.x + pipe.PIPE_TOP.get_width() < 0:
rem.append(pipe)
pipe.move()
if add_pipe:
score += 1
for g in ge:
g.fitness += 5
pipes.append(Pipe(600))
for r in rem:
pipes.remove(r)
for x, bird in enumerate(birds):
if bird.y + bird.img.get_height() >= 730 or bird.y < 0:
birds.pop(x)
nets.pop(x)
ge.pop(x)
base.move()
draw_window(win, birds, pipes, base, score)
def run(config_path):
config = neat.config.Config(neat.DefaultGenome, neat.DefaultReproduction,
neat.DefaultSpeciesSet, neat.DefaultStagnation,
config_path)
p = neat.Population(config)
p.add_reporter(neat.StdOutReporter(True))
stats = neat.StatisticsReporter()
p.add_reporter(stats)
winner = p.run(main, 50)
if __name__ == '__main__':
local_dir = os.path.dirname(__file__)
config_path = os.path.join(local_dir, 'config-feedforward.txt')
run(config_path)
And sorry for the such long code, you might want to press Ctrl+F to find all the locations of the base element in the code, and I thank you for the help in advance.
PS: The Base is the floor of the game.
You missed to create an instance of Base in main(). e.g:
def main(genomes, config):
# [...]
base = Base(0)
This question already has answers here:
How do I detect collision in pygame?
(5 answers)
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
Closed 2 years ago.
I'm making a game environment for NEAT. The first two obstacles seem to collide with the players just fine, but none of the other obstacles do anything. The visuals won't work, but based on the size of the player list, yeah no it's not working. The collide class also wouldn't work before I started implementing NEAT, so there's that.
Anyway here's some (probably) irrelevant code:
import pygame
from pygame.locals import *
import random
import os
import neat
debugfun = 0
W = 300
H = 300
win = pygame.display.set_mode((W, H))
pygame.display.set_caption("bruv moment")
coords = [0, 60, 120, 180, 240]
class Player(object):
def __init__(self, x):
self.x = x
self.y = 600 - 60
self.width = 60
self.height = 60
self.pos = 0
self.left = False
self.right = False
def move(self):
if self.left:
self.pos -= 1
if self.right:
self.pos += 1
if self.pos < 0:
self.pos = 4
if self.pos > 4:
self.pos = 0
self.x = coords[self.pos]
class Block(object):
def __init__(self, pos, vel):
self.pos = pos
self.x = coords[self.pos]
self.y = -60
self.width = 60
self.height = 60
self.vel = vel
def move(self):
self.y += self.vel
def redraw_window():
pygame.draw.rect(win, (0, 0, 0), (0, 0, W, H))
for ob in obs:
pygame.draw.rect(win, (0, 255, 0), (ob.x, ob.y, ob.width, ob.height))
for ind in homies:
pygame.draw.rect(win, (255, 0, 0), (ind.x, ind.y, ind.width, ind.height))
pygame.display.update()
obs = []
homies = []
player_collision = False
ge = []
nets = []
And here's some relevant code:
def collide():
for ob in obs:
for x, ind in enumerate(homies):
if ind.y < ob.y + ob.height and ind.y + ind.height > ob.y and ind.x + ind.width > ob.x and ind.x < ob.x + ob.width:
ge[x].fitness -= 1
homies.pop(x)
nets.pop(x)
ge.pop(x)
def main(genomes, config):
speed = 30
pygame.time.set_timer(USEREVENT + 1, 550)
pygame.time.set_timer(USEREVENT + 2, 1000)
for _, g in genomes:
net = neat.nn.FeedForwardNetwork.create(g, config)
nets.append(net)
homies.append(Player(0))
g.fitness = 0
ge.append(g)
clock = pygame.time.Clock()
ran = True
while ran and len(homies) > 0:
clock.tick(27)
collide()
for x, ind in enumerate(homies):
ind.move()
ge[x].fitness += 0.1
try:
output = nets[x].activate((ind.x, abs(obs[0].x - ind.x)))
except IndexError:
output = 50
try:
if output in range(5, 25):
ind.left = True
else:
ind.left = False
if output > 25:
ind.right = True
else:
ind.right = False
except TypeError:
if output[0] in range(5, 25):
ind.left = True
else:
ind.left = False
if output[1] > 25:
ind.right = True
else:
ind.right = False
for ob in obs:
ob.move()
if ob.x > H:
obs.pop(obs.index(ob))
for event in pygame.event.get():
if event.type == pygame.QUIT:
ran = False
pygame.quit()
if event.type == USEREVENT+1:
if speed <= 200:
speed += 3
if event.type == USEREVENT+2:
for g in ge:
g.fitness += 0.5
if len(obs) == 0:
obs.append(Block(round(random.randint(0, 4)), speed))
print(len(homies))
print(len(obs))
redraw_window()
def run(config_file):
config = neat.config.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet,
neat.DefaultStagnation, config_path)
p = neat.Population(config)
p.add_reporter(neat.StdOutReporter(True))
stats = neat.StatisticsReporter()
p.add_reporter(stats)
winner = p.run(main, 50)
if __name__ == "__main__":
local_dir = os.path.dirname(__file__)
config_path = os.path.join(local_dir, "avoidpedofiles.txt")
run(config_path)
I'm having trouble aligning my buttons and labels in a python PONG game gui I created with tkinter. I've searched for answers on how to do this but found nothing that resolved my issue.
What I'm trying to do is make the buttons not all stack on top of each other. I want the score for the left player aligned to the left of the screen, and the score for the right player aligned to the right of the screen, and to be able to understand how to move the other buttons where I want them.
Things I've tried:
anchor = "..."
justify = "..."
grid(row="...", column = "...")
Any help would be appreciated. I'm not sure how to fix this.
I'm wondering if it has to do with my use of canvas and buttons together?
Here is my code for the full program:
#PONG Game
from tkinter import *
import random
#http://www.tutorialspoint.com/python/tk_anchors.htm
#Globals
ball_x1 = 480
ball_x2 = 520
ball_y1 = 280
ball_y2 = 320
left_paddle_x1 = 0
left_paddle_x2 = 20
left_paddle_y1 = 240
left_paddle_y2 = 360
right_paddle_x1 = 980
right_paddle_x2 = 1000
right_paddle_y1 = 240
right_paddle_y2 = 360
left_player_score = 0
right_player_score = 0
paused = False
ball_x_motion = 10#random.randrange(-20, 20) #actually need to make a set number but random direction
ball_y_motion = 10#random.randrange(-20, 20)
def start():
global paused
if(field.coords(ball)[0] == 480):
paused = False
ball_movement()
else:
new_game(False)
def pause():
global paused
if(paused):
paused = False
else:
paused = True
ball_movement()
def new_game(reset):
global ball_x1, ball_x2, ball_y1, ball_y2, left_paddle_x1, left_paddle_x2, left_paddle_y1, left_paddle_yw
global right_paddle_x1, right_paddle_x2, right_paddle_y1, right_paddle_y2
global paused, left_player_score, right_player_score
print("here1")
if(reset):
left_player_score = 0
right_player_score = 0
print("here")
left_player_score_label.config(text=left_player_score)
right_player_score_label.config(text=right_player_score)
left_paddle_x1 = 0
left_paddle_x2 = 20
left_paddle_y1 = 240
left_paddle_y2 = 360
right_paddle_x1 = 980
right_paddle_x2 = 1000
right_paddle_y1 = 240
right_paddle_y2 = 360
field.coords(left_paddle, left_paddle_x1, left_paddle_y1, left_paddle_x2, left_paddle_y2)
field.coords(right_paddle, right_paddle_x1, right_paddle_y1, right_paddle_x2, right_paddle_y2)
paused = True
print("here2")
#starting positions
ball_x1 = 480
ball_x2 = 520
ball_y1 = 280
ball_y2 = 320
field.coords(ball, ball_x1, ball_y1, ball_x2, ball_y2)
#Event Handlers
def ball_movement():
#while(variable = true) move ball
# move the object
global ball_x_motion, ball_y_motion, ball_x1, ball_x2, ball_y1, ball_y2, paused
global left_player_score, right_player_score
#keep ball on playing field horizontally if ball hits paddles
print(((((left_paddle_y1 + left_paddle_y2)/2) - ((ball_y1 + ball_y2)/2))))
if(((ball_x1 <= 20) and (-60 <= ((((left_paddle_y1 + left_paddle_y2)/2) - ((ball_y1 + ball_y2)/2))) <= 60)) or ((ball_x2 >= 980) and (-60 <= ((((right_paddle_y1 + right_paddle_y2)/2) - ((ball_y1 + ball_y2)/2))) <= 60))):
ball_x_motion = -ball_x_motion
#increase speed
elif(ball_x1 <=0):
right_player_score += 1
new_game(False)
#paused = True
right_player_score_label.config(text=right_player_score)
elif(ball_x2 >= 1000):
left_player_score += 1
new_game(False)
#paused = True
left_player_score_label.config(text=left_player_score)
if(field.coords(ball)[1] <= 0 or field.coords(ball)[3] >= 600): #keep ball in playing field vertically
ball_y_motion = -ball_y_motion
#increase speed
if(not paused):
field.coords(ball, ball_x1 + ball_x_motion, ball_y1 + ball_y_motion, ball_x2 + ball_x_motion, ball_y2 + ball_y_motion)
ball_x1 = field.coords(ball)[0]
ball_x2 = field.coords(ball)[2]
ball_y1 = field.coords(ball)[1]
ball_y2 = field.coords(ball)[3]
#ball moves every 10 milliseconds
field.after(10, ball_movement)
def move_left_paddle_up(event):
global left_paddle_y1, left_paddle_y2
#print(event.keysym)
if(field.coords(left_paddle)[1] > 0):
field.move("left_paddle", 0, -40)
left_paddle_y1 = field.coords(left_paddle)[1]
left_paddle_y2 = field.coords(left_paddle)[3]
def move_left_paddle_down(event):
global left_paddle_y1, left_paddle_y2
if(field.coords(left_paddle)[3] < 600):
field.move("left_paddle", 0, 40)
left_paddle_y1 = field.coords(left_paddle)[1]
left_paddle_y2 = field.coords(left_paddle)[3]
def move_right_paddle_up(event):
global right_paddle_y1, right_paddle_y2
if(field.coords(right_paddle)[1] > 0):
field.move("right_paddle", 0, -40)
right_paddle_y1 = field.coords(right_paddle)[1]
right_paddle_y2 = field.coords(right_paddle)[3]
#print(event.keysym)
def move_right_paddle_down(event):
global right_paddle_y1, right_paddle_y2
if(field.coords(right_paddle)[3] < 600):
field.move("right_paddle", 0, 40)
right_paddle_y1 = field.coords(right_paddle)[1]
right_paddle_y2 = field.coords(right_paddle)[3]
#print(event.keysym)
#Canvas
master = Tk() #master
field = Canvas(master, width=1000, height=600, bg="black") #playing field
master.bind('<w>', move_left_paddle_up) #left paddle up
master.bind('<s>', move_left_paddle_down) #left paddle down
master.bind('<Up>', move_right_paddle_up) #right paddle up
master.bind('<Down>', move_right_paddle_down) #right paddle down
#create field border lines with a rectangle
border = field.create_rectangle(0, 0, 1000, 600, fill="gray")
#create midline
midline = field.create_line(500, 0, 500, 600, fill="white", dash=(4, 4))
#create ball
ball = field.create_oval(ball_x1, ball_y1, ball_x2, ball_y2, fill="white", tags=("ball"))
#create left paddle
left_paddle = field.create_rectangle(left_paddle_x1, left_paddle_y1, left_paddle_x2, left_paddle_y2, fill="red", tags=("left_paddle"))
#create right paddle
right_paddle = field.create_rectangle(right_paddle_x1, right_paddle_y1, right_paddle_x2, right_paddle_y2, fill="blue", tags=("right_paddle"))
#create Pause Button
pause_button = Button(master, text="Pause/Unpause", command=pause)
#pause_button.grid(row=1, column=1)
pause_button.pack()
#create Start Button
start_button = Button(master, text="Start", command=start)
#start_button.grid(row=1, column=3)
start_button.pack()
#left player scorekeeper
left_player_score_label = Label(master, text=left_player_score)
left_player_score_label.pack()
#right player scorekeeper
right_player_score_label = Label(master, text=right_player_score)
right_player_score_label.pack()
#create New Game Button
new_game_button = Button(master, text="New Game", command=lambda: new_game(True))
#new_game_button.grid(row=1, column=2)
new_game_button.pack()
#pack it all together on the screen
field.pack()
#execute loop to run screen processing
mainloop()
Edit
This is the final result after changing from pack() to grid(). I realized that you don't use both, but rather one or the other.
#PONG Game
from tkinter import *
import random
#http://www.tutorialspoint.com/python/tk_anchors.htm
#Globals
ball_x1 = 480
ball_x2 = 520
ball_y1 = 280
ball_y2 = 320
left_paddle_x1 = 0
left_paddle_x2 = 20
left_paddle_y1 = 240
left_paddle_y2 = 360
right_paddle_x1 = 980
right_paddle_x2 = 1000
right_paddle_y1 = 240
right_paddle_y2 = 360
left_player_score = 0
right_player_score = 0
paused = False
direction_factor = random.randrange(0,1)
ball_x_motion = 5
ball_y_motion = random.randrange(-5, 5)
if direction_factor == 0:
ball_x_motion *= -1
def start():
global paused
if(field.coords(ball)[0] == 480):
paused = False
ball_movement()
else:
new_game(False)
def pause():
global paused
if(paused):
paused = False
else:
paused = True
ball_movement()
def new_game(reset):
global ball_x1, ball_x2, ball_y1, ball_y2, left_paddle_x1, left_paddle_x2, left_paddle_y1, left_paddle_yw
global right_paddle_x1, right_paddle_x2, right_paddle_y1, right_paddle_y2
global paused, left_player_score, right_player_score, ball_x_motion, ball_y_motion, direction_factor
direction_factor = random.randrange(0,1)
ball_x_motion = 10
ball_y_motion = random.randrange(-10, 10)
if direction_factor == 0:
ball_x_motion *= -1
if(reset):
left_player_score = 0
right_player_score = 0
left_player_score_label.config(text=left_player_score)
right_player_score_label.config(text=right_player_score)
left_paddle_x1 = 0
left_paddle_x2 = 20
left_paddle_y1 = 240
left_paddle_y2 = 360
right_paddle_x1 = 980
right_paddle_x2 = 1000
right_paddle_y1 = 240
right_paddle_y2 = 360
field.coords(left_paddle, left_paddle_x1, left_paddle_y1, left_paddle_x2, left_paddle_y2)
field.coords(right_paddle, right_paddle_x1, right_paddle_y1, right_paddle_x2, right_paddle_y2)
paused = True
#starting positions
ball_x1 = 480
ball_x2 = 520
ball_y1 = 280
ball_y2 = 320
field.coords(ball, ball_x1, ball_y1, ball_x2, ball_y2)
#Event Handlers
def ball_movement():
#while(variable = true) move ball
# move the object
global ball_x_motion, ball_y_motion, ball_x1, ball_x2, ball_y1, ball_y2, paused
global left_player_score, right_player_score
#keep ball on playing field horizontally if ball hits paddles
#print(((((left_paddle_y1 + left_paddle_y2)/2) - ((ball_y1 + ball_y2)/2))))
if(((ball_x1 <= 20) and (-60 <= ((((left_paddle_y1 + left_paddle_y2)/2) - ((ball_y1 + ball_y2)/2))) <= 60)) or ((ball_x2 >= 980) and (-60 <= ((((right_paddle_y1 + right_paddle_y2)/2) - ((ball_y1 + ball_y2)/2))) <= 60))):
ball_x_motion *= -1.1
#ball_y_motion = ball_y_motion + 5
elif(ball_x1 <=0):
right_player_score += 1
new_game(False)
#paused = True
right_player_score_label.config(text=right_player_score)
elif(ball_x2 >= 1000):
left_player_score += 1
new_game(False)
#paused = True
left_player_score_label.config(text=left_player_score)
if(field.coords(ball)[1] <= 0 or field.coords(ball)[3] >= 600): #keep ball in playing field vertically
ball_y_motion = -ball_y_motion
if(not paused):
field.coords(ball, ball_x1 + ball_x_motion, ball_y1 + ball_y_motion, ball_x2 + ball_x_motion, ball_y2 + ball_y_motion)
ball_x1 = field.coords(ball)[0]
ball_x2 = field.coords(ball)[2]
ball_y1 = field.coords(ball)[1]
ball_y2 = field.coords(ball)[3]
#ball moves every 10 milliseconds
field.after(10, ball_movement)
def move_left_paddle_up(event):
global left_paddle_y1, left_paddle_y2
#print(event.keysym)
if(field.coords(left_paddle)[1] > 0):
field.move("left_paddle", 0, -40)
left_paddle_y1 = field.coords(left_paddle)[1]
left_paddle_y2 = field.coords(left_paddle)[3]
def move_left_paddle_down(event):
global left_paddle_y1, left_paddle_y2
if(field.coords(left_paddle)[3] < 600):
field.move("left_paddle", 0, 40)
left_paddle_y1 = field.coords(left_paddle)[1]
left_paddle_y2 = field.coords(left_paddle)[3]
def move_right_paddle_up(event):
global right_paddle_y1, right_paddle_y2
if(field.coords(right_paddle)[1] > 0):
field.move("right_paddle", 0, -40)
right_paddle_y1 = field.coords(right_paddle)[1]
right_paddle_y2 = field.coords(right_paddle)[3]
#print(event.keysym)
def move_right_paddle_down(event):
global right_paddle_y1, right_paddle_y2
if(field.coords(right_paddle)[3] < 600):
field.move("right_paddle", 0, 40)
right_paddle_y1 = field.coords(right_paddle)[1]
right_paddle_y2 = field.coords(right_paddle)[3]
#print(event.keysym)
#Canvas
master = Tk() #master
field = Canvas(master, width=1000, height=600, bg="black") #playing field
field.grid(row=4, columnspan=10)
#field.pack()
master.bind('<w>', move_left_paddle_up) #left paddle up
master.bind('<s>', move_left_paddle_down) #left paddle down
master.bind('<Up>', move_right_paddle_up) #right paddle up
master.bind('<Down>', move_right_paddle_down) #right paddle down
#create field border lines with a rectangle
border = field.create_rectangle(0, 0, 1000, 600, fill="gray")
#create midline
midline = field.create_line(500, 0, 500, 600, fill="white", dash=(4, 4))
#create ball
ball = field.create_oval(ball_x1, ball_y1, ball_x2, ball_y2, fill="white", tags=("ball"))
#create left paddle
left_paddle = field.create_rectangle(left_paddle_x1, left_paddle_y1, left_paddle_x2, left_paddle_y2, fill="red", tags=("left_paddle"))
#create right paddle
right_paddle = field.create_rectangle(right_paddle_x1, right_paddle_y1, right_paddle_x2, right_paddle_y2, fill="blue", tags=("right_paddle"))
#create Pause Button
pause_button = Button(master, text="Pause/Unpause", command=pause)
pause_button.grid(row=1, column=6)
#pause_button.pack()
#create Start Button
start_button = Button(master, text="Start", command=start)
start_button.grid(row=1, column=4)
#start_button.pack()
#left player scorekeeper
left_player_score_label = Label(master, text=left_player_score)
left_player_score_label.grid(row=1, column=0)
#left_player_score_label.pack()
#right player scorekeeper
right_player_score_label = Label(master, text=right_player_score)
right_player_score_label.grid(row=1, column=9)
#right_player_score_label.pack()
#create New Game Button
new_game_button = Button(master, text="New Game", command=lambda: new_game(True))
new_game_button.grid(row=1, column=5)
#new_game_button.pack()
#pack it all together on the screen
#field.pack()
#execute loop to run screen processing
mainloop()
I realized that you don't use both the grid manager and the pack manager, it's one or the other. So I deleted the pack()'s that I had and used all grid()'s and posted the final result.