Reputation: 87
UPDATED CODE:
import pygame
pygame.init()
width = 700
height = 700
running = True
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Dijkstra's Path-Finding Algorithm Solver")
icon = pygame.image.load('icon.jpg')
pygame.display.set_icon(icon)
def title_main():
title_font = pygame.font.Font('TrajanPro-Regular.otf', 40)
text_font = pygame.font.SysFont("comicsans", 30, bold=True)
Dijkstra_img = pygame.image.load('Dijkstra.jpg')
text1_display = title_font.render("Dijkstra's Path-Finding", True, (255, 255, 255))
text2_display = title_font.render('Algorithm', True, (255, 255, 255))
text3_display = text_font.render('Press any key to continue...', True, (255, 255, 255))
screen.blit(Dijkstra_img, (225, 40))
screen.blit(text1_display, (75, 400))
screen.blit(text2_display, (225, 460))
screen.blit(text3_display, (190, 550))
def title_game():
title_font = pygame.font.Font('TrajanPro-Regular.otf', 35)
title_display = title_font.render('Dijkstra Path-Finding Algorithm', True, (255, 255, 255))
screen.blit(title_display, (12, 15))
def title_underline():
rect = pygame.Rect(0, 60, 800, 3)
rect_display = pygame.draw.rect(screen, [255, 255, 255], rect)
title_font = pygame.font.Font('TrajanPro-Regular.otf', 100)
title_display = title_font.render('', True, (255, 255, 255))
screen.blit(title_display, (270, 198))
def grid():
grid_x = 0
grid_y = 63
blockSize = 20
for x in range(width):
for y in range(height):
rect = pygame.Rect(x*blockSize + grid_x, y*blockSize + grid_y, blockSize, blockSize)
pygame.draw.rect(screen, (200,200,200), rect, 1)
def game_loop():
game_is_active = True
while game_is_active:
for game_event in pygame.event.get():
if game_event.type == pygame.QUIT:
game_is_active = False
if game_event.type == pygame.MOUSEBUTTONDOWN:
start = print(pygame.mouse.get_pos())
print(start)
screen.fill((0, 0, 0))
title_game()
title_underline()
grid()
pygame.display.update()
while running:
for event in pygame.event.get():
screen.fill((0, 0, 0))
title_main()
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
running = game_loop()
pygame.display.update()
I have created a title page for my project under a function that I run when I start the GUI, but what I want to do is that when the user presses any key, I want to NOT display the title_main() function anymore and just display my main application instead. I used KEYDOWN to try to do this but for some reason, its very slow and non-responsive and also the title_main() function still is displayed.
Upvotes: 2
Views: 537
Reputation: 14906
@Cribber explains why your existing loop is not working.
I would like to provide an answer where only a single event-loop is used because I believe having a simple main-loop is the best architecture for an event-driven program (i.e.: all PyGame programs).
Your program is divided into two states, showing the "title page" and "main application". I would keep this state in a variable, and determine which path to take in the main loop based on it. At each step of the draw → input → update cycle, examine the state (iff necessary) and act based on the value.
# Function definitions as per question
# States the app can be in
TITLE_PAGE = 10 # TODO: maybe use an Enumerated Type
MAIN_APP = 20
app_state = TITLE_PAGE # start with the titles
while running:
# Handle user input
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if ( app_state == TITLE_PAGE ):
# user dismissed title page, switch to app-mode
app_state = MAIN_APP
# Update the screen
screen.fill((0, 0, 0))
if ( app_state == TITLE_PAGE ): # In Title-page mode?
title_main()
elif ( app_state == MAIN_APP ): # In Main-Application mode?
title_game()
title_underline()
grid()
pygame.display.update()
Sure, when it's very simple like this, it's not a big deal which way it's implemented. But as the program becomes more and more complex, it helps to lay-out the logic flow in simple steps. There's no duplicated event-loop code blocks, or screen-painting, so (for example) if there's a user-input bug, it can only be in one place.
EDIT: Handling first and second mouse clicks
It's pretty easy to handle two mouse clicks. It's just necessary to remember both the click-count, and where the "previous" click was.
This can be accomplished by storing a single initialised variable first_click
, but starting with a value of None
. The None is important, because it indicates there has not been a click yet. So it tracks the first/second click, and where the position of the first click.
So...
first_click == None
→ User has not clicked yetfirst_click != None
→ First click OK, waiting on second.In your code, first_click
is called start
. It just needs to be initialised to None.
start = None # no clicks yet
def game_loop():
game_is_active = True
while game_is_active:
for game_event in pygame.event.get():
if game_event.type == pygame.QUIT:
game_is_active = False
if game_event.type == pygame.MOUSEBUTTONDOWN:
# Mouse has been clicked
if ( start == None ): # Is this a first click?
# Save the First click
start = pygame.mouse.get_pos()
else:
# This is a second click, process both
handleTwoClicks( start, pygame.mouse.get_pos() )
# reset back to no-clicks-made
start = None
Upvotes: 2
Reputation: 2913
The lines in the block beneath if event.type == pygame.KEYDOWN:
only get executed if a button is pressed - and only once per KEYDOWN!
Since you have no separate loop after the initial pygame.KEYDOWN, your while running:
continues after the functions title_game()
, title_underline()
and grid()
are executed once. Then the loop starts anew and the function title_main()
also gets executed again (which is why it is still displayed).
I think you might want to implement another loop after the KEYDOWN was registered.
You will also have to capture the input in this loop separately as you don't "come back" to the for event in pygame.event.get():
in your while running:
loop.
I included a bit more cleaned-up version of the code and implemented a game loop after showing your title_main()
as I understood your problem.
while running: # your loop - display the title and wait for a button to be pressed
for event in pygame.event.get():
screen.fill((0, 0, 0))
title_main()
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
# start the actual game upon pressing a button for the first time
running = game_loop() # stop the loop if the game returns with False
pygame.display.update()
def game_loop():
game_is_active = True
while game_is_active :
for game_event in pygame.event.get():
if game_event.type == pygame.QUIT:
return False # return to your outer loop
# game logic - display the title, the underline and the grid:
screen.fill((0, 0, 0))
title_game()
title_underline()
grid()
pygame.display.update() # update screen
Upvotes: 2