Fullscreen toggle seems to instantly go back again - python

I'm new to python and i was trying to let the 1-button on the keyboard toggle fullscreen in an application using pygame. Somehow the else: statement causes it to instantly go back to windowed mode again. At least that is my understanding. Can anyone enlighten me why that happens and care to give an alternative method?
This is the code:
# screen = pygame.display.set_mode((1024, 768))
# fullscreen = False
if event.key == K_1:
if fullscreen == False:
pygame.display.set_mode((1024, 768), FULLSCREEN)
fullscreen = True
else:
pygame.display.set_mode((1024, 768))
fullscreen = False

It looks like you're checking each frame to see if your event key (K_1) is being held. Instead, you probably want to check for a KEY_UP or KEY_DOWN event. I'm not familiar with pygame - but I assume you could probably get that sort of information out of your event variable.
Alternatively, keep a variable that detects when you're still holding the key - which may look something like this:
# outside of the loop code
holding_fullscreen = false
# inside the loop code
if event.key == K_1:
if not holding_fullscreen:
holding_fullscreen = true
if not fullscreen: # more pythonic version of fullscreen == False
# set fullscreen
else:
# set windowed
else:
holding_fullscreen = False

I assume this is inside your loop. If so, every time the game refreshes, it will check for an input, and when it sees that K_1 is not pressed, fullscreen will be disabled again. You'd have to constantly hold done K_1. You need to just remove the else.

Related

Is there a way to completely prevent the user form exiting the pygame window?

I want to completely prevent the user from closing the Pygame window except for the key x. Currently, I'm able to prevent the user from closing it, but I am unable to prevent the user from opening another window that overlaps it (press windows key -> open chrome, which overlaps the Pygame window).
import sys
import pygame
from pygame.locals import *
pygame.init()
infoObject = pygame.display.Info()
screen = pygame.display.set_mode((infoObject.current_w, infoObject.current_h), flags=pygame.NOFRAME)
while True:
screen.fill((0, 0, 0))
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_x:
pygame.quit()
sys.exit()
if event.type == QUIT:
pass
pygame.display.flip()
We don't have complete solutions for this task.
You can make the title var vanish away by setting display mode to NOFRAME (You have already used this): pygame.display.set_mode(flags = pygame.NOFRAME), but this is overkill for just stopping close buttons
Although any user with minimum Computer Knowledge will fire up a Task manager and kill python.exe :-(
There are ways of disabling task manager through Registry in Windows, Image File Execution Options blah blah, but your game script will barely run with Administrator priviliges (With nagging of UAC)
In order to do this, you can add this piece of code to your pygame.display.set_mode():
pygame.display.set_mode(..., flags=pygame.NOFRAME). Now, the bar with the "x" button will disapear.
Notice that if you decide to make this change, you won't be able to move your game window anymore. (Unless you change it back).

Pygame seems to skip an if statement on whether or not I click again

In making my chess game function for moving pieces, I've created a system that should:
Look for a click
See if a piece was clicked on
Determine what piece was clicked on
Click on a square to move to
Move said piece to said square
I've written the follow code for this:
if event.type == pygame.MOUSEBUTTONDOWN and moving == False:
mousepos = pygame.mouse.get_pos()
roundedmouse1 = rounddown80(mousepos[0]) #function to found out what square was clicked
roundedmouse2 = rounddown80(mousepos[1]) #function to found out what square was clicked
mousecoords = [roundedmouse1,roundedmouse2]
for key,value in piecepositionsdict.items():
if int(value[0]) == int(mousecoords[0]) and int(value[1]) == int(mousecoords[1]):
x = coordstosquaredict[str(mousecoords)]
print("You have clicked",whatpiece(x),"on square",x)
print("Click a square to move the piece to:")
moving = True
time.sleep(0.5)
#this should be where the program stops until it gets another click
if event.type == pygame.MOUSEBUTTONDOWN and moving == True:
mousepos2 = pygame.mouse.get_pos()
roundedmouse21 = rounddown80(mousepos2[0])
roundedmouse22 = rounddown80(mousepos2[1])
mousecoords2 = [roundedmouse21, roundedmouse22]
print(mousecoords2)
print(piecepositionsdict[whatpiece(x)+"pos"])
piecepositionsdict[whatpiece(x)+"pos"] = mousecoords2
print(piecepositionsdict[whatpiece(x) + "pos"])
However, the program goes right past the second click check, as shown by how it prints out mousecoords 2 etc. when I have only clicked once.
What have I done wrong to cause this error?
Games are event driven applications. In event driven application you have a main loop checking for all events, and code executed when an event is detected. The starting point of your logic is always the event.
In your case the event is the clicking of the button. You have to check for the click only once in your code (in the main loop) and then determine the action the code has to do. If different actions may be triggered by the same event, you need some additional logic or flags to determine which action should be executed.
In your case you have an event (mouse click) and two possible actions, check what pieces has been clicked, or move the piece.
So the code should be designed like this:
def check_and_grab(position):
# code here
def move_piece(position):
# code here
piece_grabbed = None
while True:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTODOWN:
if piece_grabbed is None:
check_and_grab(event.pos)
else:
move_piece(event.pos)
piece_grabbed is a variable storing the piece grabbed: if is None, no piece has been grabbed.
check_and_grab(position) should check if there is a piece at the clicked position and, if so, set piece_grabbed to that piece. It implements your points 2 and 3.
move_piece(position) should move the grabbed piece at the new position and after that, set again grabbed_piece = None. It implements your point 5.
Your code will run in a single frame and the code will only register one click during that frame. You need to have a function thats gets called everytime you click on the screen.
See my sort of example bellow:
#Holder for the piece you have selected
currentPiece = piece
##Mouse click event/function##
if currentPiece == None:
getPiece()
else:
movePiece()
##Get piece function##
def getPiece():
#Your function here which sets
#currentPiece to what you selected.
##Move function##
def movePiece():
#Moves the currentPieece to the selected spot

Pygame : The game stops temporarily when I am moving the window

I'm a new in PyGame and I was making a game. Until I discovered that when you were moving the window to another place of your desktop for example, the game temporarily stops. But ticks of the game still running when I used pygame.time.get_ticks().
So I made a completely new program with only the necessary code and it does the same thing.
Can someone explain me why it does it and if we can resolve this problem?
import pygame
screen = pygame.display.set_mode((800,600))
pygame.display.set_caption('The Test Program')
running = True
update_counter = 1
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.flip()
print(str(update_counter) + " updates")
update_counter += 1
pygame.quit()
quit()
# So try to move the window across your screen and you will see that, prints will stop and they will resume when you will release the click
So someone tell me that was normal, so I think it's only on Windows but there are no solutions. I put a script that show a pause symbol on screen when the cursor leave the window to make it normal.

Tab out of Pygame fullscreen window without crashing it

So I'm using Pygame to create a fancy display for a program I am writing. I chose Pygame because it's easy to get started and does a great job with animations. I want the display to be as big as I can make it so as much information can be shown as possible. Here is the kicker however, I still want to be able to get to the console of the program.
Pygame forces a fullscreen window to the front, so you cant tab out, and moving the windows to another windows desktop crashes the display. I would do a key trick to switch the pygame mode, but I cannot use pygame.event.get() because of how the program the threaded.
Is there a way to make it a full-screen window so that I can tab out and leave it up in the background? I dont really want it to just be a normal window because it is not as big that way.
The display crashes after I tab out and back in, here is what that looks like:
I also get a non-zero exit code: -805306369 (0xCFFFFFFF)
Here is a broken down version of the code that still gives me this error, you'll notice there are some things in here you wouldn't have if this was your full program, but I wanted to retain as much architecture as I could.
import pygame
import os
BACKGROUND = (9, 17, 27)
os.environ['SDL_VIDEO_WINDOW_POS'] = "0,0"
pygame.init()
pygame.font.init()
infoObject = pygame.display.Info()
SIZE = (infoObject.current_w, infoObject.current_h)
X_CENTER = SIZE[0]/2
Y_CENTER = SIZE[1]/2
# create a borderless window that's as big as the entire screen
SCREEN = pygame.display.set_mode((SIZE[0], SIZE[1]), pygame.NOFRAME)
clock = pygame.time.Clock()
TextFont = pygame.font.SysFont('Courant', 30)
class DisplayState:
state = type(bool)
def __init__(self):
self.state = True
def get_state(self):
return self.state
def change_state(self, new_state):
self.state = new_state
def main(display_state_object):
running = True
while running:
if display_state_object.get_state():
SCREEN.fill(BACKGROUND)
pygame.display.flip()
else:
return 1
return
if __name__ == "__main__":
main(DisplayState())
EDIT
I think it is a multi-threading problem! See this code:
Produces Error
def start_display():
display(params)
def display(params):
pygame loop
if __name__ == "__main__":
display_thread = threading.Thread(target=start_display)
display_thread.start()
Does not produce error
def display(params):
pygame loop
if __name__ == "__main__":
display_thread = threading.Thread(target=display(params))
display_thread.start
# marker
One problem with the version that does work, the program does not seem to be continuing forwards outside the thread (ie the marker is never reached). Is this how the threading library works? It may explain why I had the middle man function present. Maybe this is a different problem and deserves its own question?
EDIT
Setting up the thread like this allows the main thread to continue, but brings back the pygame error:
threading.Thread(target=display, args=(DisplayState(),))
There's no easy way to do this on windows/sdl using the real fullscreen mode, and the usual way to solve this is to use a borderless window.
Here's how to create such a "fake" fullscreen window in pygame:
import pygame
import os
# you can control the starting position of the window with the SDL_VIDEO_WINDOW_POS variable
os.environ['SDL_VIDEO_WINDOW_POS'] = "0,0"
pygame.init()
# now let's see how big our screen is
info = pygame.display.Info()
# and create a borderless window that's as big as the entire screen
screen = pygame.display.set_mode((info.current_w, info.current_h), pygame.NOFRAME)
You have to call one of the pygame event functions (e.g. pygame.event.pump() or pygame.event.get()) each frame or the window will become unresponsive and the program will appear to have crashed. If you call one of those functions, you should be able to press Alt+Tab (in Windows) to get back to the desktop without crashing the program (if you select the desktop, the window will be minimized and if you select another window, it will just be brought to the front).
def main(display_state_object):
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
# Press Esc to quit.
if event.key == pygame.K_ESCAPE:
running = False
if display_state_object.get_state():
SCREEN.fill(BACKGROUND)
pygame.display.flip()
else:
return 1
return

Let an image appear with key stroke and stay [pygame]

I'm currently working on a school project and I'm stuck with this problem.
The problem is in this line of code:
if pressed[pygame.K_SPACE]:
a = 1
while a == 1:
gameDisplay.blit(bulletIMG, (x,y))
I know what that problem is, the loop will go on forever.
Is there a way to break out of this loop? or should I try a different approach.
If I understand you correctly, you want to have the user press a button and an image displays permanently:
display_image = False
while game_running:
if pressed[pygame.K_SPACE]:
display_image = True
if display_image:
gameDisplay.blit(bulletIMG, (x,y))
now the image will always be displayed because the flag will always be true once the user hits the space bar (the key is bringing the flag outside the game loop).

Categories

Resources