I have two files, one to generate a world, and another to run the main code. However, the main screen keeps crashing for no reason. I think the world gen may also be broken, but it does at least pass on valid data to the main code.
# Main loop.
while RUNNING:
# Fill the screen.
screen.fill((0,0,0))
# Event handling.
for eventa in event.get():
if eventa.type == QUIT:
RUNNING = f
screen.fill(SCREENCOLOR)
# Draw the world.
for tile in WORLD:
if tile.surface == None:
pass
else:
screen.blit(tile.surface,tile.location)
# Draw the character
screen.blit(PLAYER["image"],PLAYER["loc"])
# Pygame commands clear up.
clock.tick(FPS)
screen.flip()
This code doesn't even fill the screen with white. This may just be too much data to handle, sorry if it is.
World generator
Main code
Previous question
I'm fairly sure that you aren't inserting too many things onto the screen. I believe that the problem is far more simple. You have said screen.flip() However, a surface object has no attribute called flip. You must be confused with the function pygame.display.flip() If you use this instead, the game shall display its visual output.
Related
Trying to design and call open a basic customized pygame window that pops up right after the program starts. The window I'm producing gets minimized by default instead of just opening. It's also not updating the color, and it immediately crashes when I open the tab that it's in.
# I'm running Windows 10 with Spyder (Python 3.9), if that matters
# This is the entire code:
import pygame
WIDTH, HEIGHT = 900, 500
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Space Shooter Friends (Version 1.0)")
# Color presets
WHITE = (255,255,255)
BLACK = (0,0,0)
# Event loop
def main():
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
WIN.fill(WHITE)
pygame.display.update()
pygame.quit()
# Ensure the game only executes in the file named: space_shooter.py
if __name__ == "__space_shooter__":
main()
For context, I'm a beginner level student just trying to generate a basic white display for now, with dimensions: 9ooW x 500H, and centered ideally so that the pygame window's center is superimposed onto the center of my computer screen. I want this window to pop up as soon as the program starts running, and it should stay open for an indefinite amount of time, or until exited from with the X icon.
It seems to be producing the window right away as intended, but it places it into a minimized tab instead of an opened window display for some reason. The window pops open if I click on the tab, but it's filled in with black regardless of what values I insert into WIN.fill(R,B,G) as arguments. Also, the program immediately becomes non-responsive with the message: (Not responding) next to the game's title (at the top of the pygame window, not in the Spyder terminal).
Seems like it's not able to update for some reason, possibly causing it to crash, but I'm not really sure. I'm not getting any runtime or syntax errors from Python, but I do get a "Python is not responding" message from Windows in the pygame window as well as whenever I try to close the window using the X icon. Any help is much appreciated!
The problem is in the following line:
if __name__ == "__space_shooter__":
The __name__ variable will not contain the file name of the current script. If the script is ran directly, it will contain "__main__". If the script is imported by another script, it will contain the file name of that other script.
In order to check the script's file name, which you according to the comment wanted to do, you have to use the __file__ variable. The only problem is that the __file__ variable does not only containt the file name, but also the file path and the file extension. That's why I would use the str.endswith function, which checks whether a certain string ends with a given string. There are also some more complicate and reliable ways, but I will leave it to this:
if __file__.endswith("space_shooter.py"):
However, it is more common to check whether the current file is being ran directly instead of being imported from another file. This allows other files to import and use the functions and classes present in the file, without that everything in the file is ran too.
For this, you have to use the __name__ variable:
if __name__ == "__main__":
As said above, the __name__ variable will contain "__main__" when the file is ran directly. Thus we can compare __name__ with it to know whether the file is ran directly or not.
For more information on the __name__ variable, there is more explanation and a useful example.
I'm trying to create a pygame program with a 2d drawable grid and methods that run for a long time. I want the main game loop to be able to process while the methods are running so I opted for the threading module and it worked fine but I found out that the multiprocessing module is better suited for CPU-heavy programs so I wanted to switch. The code below is an example or representative of my actual code
# importing the necessary libraries
class Board:
# class representing the actual 2d grid or board on screen
class Graph:
# class for drawing methods that take a long time to run
# Graph's methods call q.get() to get the Board object then
# make appropriate changes to it then call q.put() to put it back in the Queue
def draw_board(surface, rects):
# surface: pygame.display
# rects: list of pygame rectangle objects
# draw every rectangle in rects to the display surface.
def main():
# main game loop
board = Board(*args)
q = multiprocessing.Queue()
q.put(board)
graph = Graph(q)
while True:
draw_board(*args)
for event in pygame.event.get():
# checking some conditions and keypresses here
elif event.type == KEYDOWN:
if event.key == pygame.K_r:
t = multiprocessing.Process(target=graph.draw_sth)
t.start()
pygame.display.update()
# fps clock ticks for 60 FPS here
if __name__ == "__main__":
main()
I use multiprocessing.Queue to transfer resources from the main process to the processes spawned inside main() and back. When I run this and click the key "r", nothing happens and the terminal prints the introduction line when main is first called, namely
pygame 2.0.1 (SDL 2.0.14, Python 3.9.5)
Hello from the pygame community. https://www.pygame.org/contribute.html
This doesn't happen when I use threading so I assume that this is due to my usage of Queue or I might have misunderstood and misused multiprocessing instead. Any help is appreciated on the matter. For simplicity, some lines of code have been omitted.
Try calling this function before your event loop. ( I don't know if this will apply to multiprocessing )
def continue_pygame_loop():
pygame.mainloop(0.1)
yield
This post can do a better job of explaining the mechanics behind it : pyGame in a thread
This is the programme I wrote but I'm not sure what's wrong:-
import turtle
import random
bob = turtle.Turtle()
screen = turtle.Screen()
def coord(x,y):
print(x,y)
turtle.onscreenclick(None)
turtle.onscreenclick(coord)
turtle.listen()
print('hello')
turtle.done()
The programme works fine except that the print('hello') part happens first, followed by the on screen event. How do I make the onscreen event occur first before the rest of my programme?
You can simply make the rest of your code part of the coord function:
def coord():
print(x,y)
turtle.onscreenclick(None)
print("Hello")
# The rest of your program goes here.
However, a few things to note:
This isn't an amazing elegant solution, especially if you intend to set up other events further into your code. It can become quite hard to keep track of.
It's imperative that you remove the event binding (in this case the binding of coord to onscreenclick) as soon as it's been used, otherwise you could end up with multiple instances of the same code running at once if someone double-clicked the screen, for example. In your case you've already done this (with turtle.onscreenclick(None)), but it is something to keep in mind.
If you choose to go this route, don't forget to rename the coord function something more representative of what that section of your code will do.
im making a basic pygame and I was wondering if anyone can help me out
so after a certain amount of time a power-up scrolls down the screen but I cant get it to work
here is the method im using:
def random_event(self):
self.force_img_r = self.force_img.get_bounding_rect()
self.rnd_x = random.randint(5,315)
self.force_img_r.x = self.rnd_x
self.force_img_r.y += 3
screen.blit(self.force_img,(self.rnd_x, self.force_img_r.y))
all its doing is the image is blinking for a split second then nothing
can anyone tell me why its not working!?
In pygame you usually have a main loop that cleans the screen on every iteration, that's probably why you only see a blink, you draw and in the next loop you clean again.
To work arround this, in pygame events should only update game state, and draw the screen on every loop according to the current state.
Some pseudocode:
# Main Loop
while True:
# Process events
# -> Update game state
# Clean screen
# Draw current state to the screen
# Update or flip display
# Keep framerate (clock.Tick())
You can call external classes/methods/functions, but you should always keep this structure at the main loop.
This question already has answers here:
Pygame how to fix 'trailing pixels'?
(4 answers)
Closed 5 years ago.
I'm trying to develop a simple game in python using pygame and IDLE. I have, since yesterday, looked through a variety of sources in order to learn about the language (and programming in general), even so I have encountered some problems and misunderstandings of how it all works. So, if anyone could please advise me on how to proceed (or point me in the direction of some good learning material) then I would appreciate it greatly.
So far, I've got a small bit of code that forms the basis of my game idea, so I will post it here and list some of my problems.
import pygame
def main():
pygame.init()
logo = pygame.image.load("coolblack.jpg")
pygame.display.set_icon(logo)
pygame.display.set_caption("Battleship")
screenWidth = 800
screenHeight = 600
screen = pygame.display.set_mode((screenWidth, screenHeight))
bgd_image = pygame.image.load("grid.png")
#--------------------------------------------------------------------
#the image named 'image' should be above 'bgd_image' but below 'cv9'
#in fact, everything should be above bgd_image, especially 'cv9'
#--------------------------------------------------------------------
image = pygame.image.load("coolblack.jpg")
cv9 = pygame.image.load("ussessexcv9.gif").convert_alpha()
xposCv9 = 400
yposCv9 = 510
step_xCv9 = 1
step_yCv9 = 1
screen.blit(bgd_image, (0,0))
screen.blit(image, (400,300))
screen.blit(cv9, (xposCv9, yposCv9))
pygame.display.flip()
clock = pygame.time.Clock()
running = True
#---------------------------------------------
#I've got a pretty good idea (sort of) about
#what is happening in the section
#below this point, however it seems that
#the image 'cv9' creates a trail of itself
#every time it moves, so how could I make it
#so that it doesn't do so?
#---------------------------------------------
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
running = False
if xposCv9>screenWidth-64 or xposCv9<0:
step_xCv9 = -step_xCv9
if yposCv9>screenHeight-64 or yposCv9<0:
step_yCv9 = -step_yCv9
xposCv9 += step_xCv9
yposCv9 += step_yCv9
screen.blit(cv9, (xposCv9, yposCv9))
pygame.display.flip()
clock.tick(60)
if __name__=="__main__":
main()
The way that pygame works is that it has internally a representation of the screen which you are updating. So, it starts entirely black, then you do your first "blit". This will update the internal representation. Then when you call "pygame.display.flip" it shows that representation on the screen. However, this will not automatically "clear" the representation for you back to all black for your next frame. So, on the next frame, you blit again (slightly to the left, say), and the first blit remains, creating your "trail".
Therefore, for what you're doing, the best thing would be to in your loop, clear the internal representation of the screen before you start drawing the next frame. You can "clear" the screen by filling it with a single color, like so...
BLACK = (0,0,0)
....
screen.blit(cv9, (xposCv9, yposCv9))
pygame.display.flip()
clock.tick(60)
screen.fill(BLACK) # Add this to "clear" the screen.
Note that if you chose to go this route, this means you will need to redraw ALL of the elements every single frame (not just the ones that changed since the last frame).
BTW, in case you are wondering, there is a good reason for why the frame is not automatically cleared at the end. In some cases, it might be faster to only update the parts of the screen that update. This can cause performance speedups in some applications. However, it's probably best to start with clearing the screen as the example shows above.