I am trying to make a simple moving game with Pygame since I am currently learning it. Whenever i try to run the code I keep on getting a problem saying: "pygame.error: display Surface quit"
I've tried adding "break" at the end but the window closes immediately! I've tried searching for the solution but I can't find one that helps my code.
import pygame
import random
pygame.init()
# Window setup
size = [400, 400]
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
# player position
x = size[0] // 2
y = size[1] // 2
# ball position
ballX = random.randrange(0, size[0])
ballY = random.randrange(0, size[1])
# colours
red = pygame.color.Color('#FF8080')
blue = pygame.color.Color('#8080FF')
white = pygame.color.Color('#FFFFFF')
black = pygame.color.Color('#000000')
def CheckOffScreenX(x):
if x > size[0]:
x = 0
elif x < 0:
x = size[0]
return x
def CheckOffScreenY(y):
if y > size[1]:
y = 0
elif y < 0:
y = size[1]
return y
# Game loop
done = False
while not done:
screen.fill(black)
keys = pygame.key.get_pressed()
#player movement
if keys[pygame.K_w]:
y -=1
if keys[pygame.K_s]:
y +=1
if keys[pygame.K_a]:
x -=1
if keys[pygame.K_d]:
x +=1
# Check offscreen
x = CheckOffScreenX(x)
y = CheckOffScreenY(y)
# draw player
pygame.draw.circle(screen, red, [x, y], 6)
pygame.display.flip()
# draw ball
pygame.draw.circle(screen, blue, [ballX, ballY], 6)
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
clock.tick(32)
pygame.quit()
Any help would be appreciated!
The issue is the pygame.quit() insider the main loop. pygame.quit() uninitialize all pygame modules. After the modules are uninitialized all further calls to pygyme instructions (in the next frame) will cause a crash.
Do pygame.quit() after the main loop, when the application has end.
done = False
while not done:
screen.fill(black)
# [...]
# pygame.quit() <----- delete
pygame.quit() # <---- add
Note, probably you've added an Indentation when you copied the code.
Related
So I used the collidepoint function to test out whether or not my mouse is interacting or can interact with the images on the surface Surface but the variable mouse_pos does give out a position yet the mouse cannot ever collide with the object (see A is always false rather than true when the mouse hit the object). How do I solve this
Code:
import pygame
from sys import exit
pygame.init()
widthscreen = 1440 #middle 720
heightscreen = 790 #middle 395
w_surface = 800
h_surface = 500
midalignX_lg = (widthscreen-w_surface)/2
midalignY_lg = (heightscreen-h_surface)/2
#blue = player
#yellow = barrier
screen = pygame.display.set_mode((widthscreen,heightscreen))
pygame.display.set_caption("Collision Game")
clock = pygame.time.Clock()
test_font = pygame.font.Font('font/Pixeltype.ttf', 45)
surface = pygame.Surface((w_surface,h_surface))
surface.fill('Light Yellow')
blue_b = pygame.image.load('images/blue.png').convert_alpha()
blue_b = pygame.transform.scale(blue_b,(35,35))
yellow_b = pygame.image.load('images/yellow.png').convert_alpha()
yellow_b = pygame.transform.scale(yellow_b,(35,35))
text_surface = test_font.render('Ball Option:', True, 'White')
barrier_1_x = 0
barrier_1_surf = pygame.image.load('images/yellow.png').convert_alpha()
barrier_1_surf = pygame.transform.scale(barrier_1_surf,(35,35))
barrier_1_rect = barrier_1_surf.get_rect(center = (100, 350))
player_surf = pygame.image.load('images/blue.png').convert_alpha()
player_surf = pygame.transform.scale(player_surf,(35,35))
player_rect = player_surf.get_rect(center = (0,350))
while True:
#elements & update
#event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
screen.blit(surface, (midalignX_lg,midalignY_lg))
screen.blit(blue_b,(150,250))
screen.blit(yellow_b, (150,300))
screen.blit(text_surface,(150, 200))
#barrier_1_x += 3
#if barrier_1_x > 800: barrier_1_x = 0
#barrier_1_rect.x += 3
#if barrier_1_rect.x > 800: barrier_1_rect.x = 0
barrier_1_rect.x += 2
if barrier_1_rect.right >= 820: barrier_1_rect.left = -10
player_rect.x += 3
if player_rect.right >= 820: player_rect.left = -10
surface = pygame.Surface((w_surface,h_surface))
surface.fill('Light Yellow')
surface.blit(barrier_1_surf, barrier_1_rect)
surface.blit(player_surf, player_rect)
'''if player_rect.colliderect(barrier_1_rect):
print('collision')'''
A = False;
mouse_pos = pygame.mouse.get_pos()
if player_rect.collidepoint(mouse_pos):
A = True
print(A)
pygame.display.update()
clock.tick(60)
I am not sure what else to do. i think it may be something wrong with the layering of the surface?
You are not drawing the objects on the screen, but on the surface. Therefore the coordinates of player_rect are relative to the surface and you also have to calculate the mouse position relative to the surface. The top left coordinate of the surface is (midalignX_lg, midalignY_lg):
while True:
# [...]
mouse_pos = pygame.mouse.get_pos()
rel_x = mouse_pos[0] - midalignX_lg
rel_y = mouse_pos[1] - midalignY_lg
if player_rect.collidepoint(rel_x, rel_y):
print("hit")
pygame.draw.circle(screen, btms3, (250, 187.5), 125, 2)
pygame.display.update()
x=10
y=10
running = 1
while running:
if x <=10:
hmove = 1
elif x >= 350:
hmove = -1
if hmove == 1:
x += 1
elif hmove == -1:
x += -1
How do i make it do as the title says?
i do have the pygame flip and display update nd things like that but i could not show as i didnt want to have a super long code.
You have to move the object in the application loop and you have to redraw the scene in every frame.Change the center coordinates of the circle in the loop and draw the circle at its new location in each frame:
import pygame
pygame.init()
screen = pygame.display.set_mode((360, 360))
clock = pygame.time.Clock()
x, y, hmove = 10, 10, 1
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
x += hmove
if x >= 350 or x <= 10:
hmove *= -1
screen.fill((0, 0, 0))
pygame.draw.circle(screen, "red", (x, y), 10, 2)
pygame.display.update()
clock.tick(100)
pygame.quit()
exit()
The typical PyGame application loop has to:
limit the frames per second to limit CPU usage with pygame.time.Clock.tick
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()
I have a game display on which I used the blit-function to display a flight path as well as a drone. The flight path starts from the right side and goes beyond the left side of the display.
The game display is filled white and what I want is to move my drone via pressed keys from right to left along the flight path (which is just a set of contiguous lines connecting random points).
I want the 'coordinate system' of my display to move/scroll so that you can see where the flight path ends. At the same time I want my drone to maintain a static position during that scrolling, e.g. stay in the middle of the screen while it follows the flight path.
Does anybody know a function that allows me to achieve that? All I found in forums and on YouTube seemed rather complex and required one to have set a background image first. I just want the white-filled screen to scroll while I move my drone to the left to follow the red flight path. Below is what I coded so far.
Thank you a lot in advance for any advice!
import pygame
import pygame.gfxdraw
import random
import sys
white = (255,255,255)
display_width = 1200
display_height = 700
game_screen = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('gameScreen')
the_drone = pygame.image.load('drone.png')
X=1000
Y=350
p1=[X, Y]
p2=[X, Y]
p3=[X, Y]
p4=[X, Y]
p5=[X, Y]
pointlist = [p1, p2, p3, p4, p5]
limit1=1000
limit2=850
for i in pointlist:
i[0] = random.randrange(limit2, limit1)
limit1-=300
limit2-=300
for i in pointlist:
if i == 0:
i[1] = random.randrange(200, 600)
else:
range = i[1]-1
i[1] = random.randrange(range-100, range+100)
def flightpath(pointlist):
pygame.draw.lines(game_screen, (255, 0, 0), False, pointlist, 3)
def drone(x,y):
game_screen.blit(the_drone,(X,Y))
def game_loop():
global X, Y
gameExit = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
keys = pygame.key.get_pressed() #checking pressed keys
if keys[pygame.K_LEFT]:
X -= 0.5
if keys[pygame.K_DOWN]:
Y -= 0.5
if keys[pygame.K_UP]:
Y +=0.5
game_screen.fill(white)
flightpath(pointlist)
drone(X,Y)
pygame.display.update()
game_loop()
pygame.quit()
sys.exit()
Hi to be hones I don't really understand your Code but I got it working like that:
import pygame
import sys
import random
# init window
def init():
pygame.init()
pygame.display.set_caption("Drone Game")
screen = pygame.display.set_mode((500, 500))
return screen
# make closing the window possible
def escape():
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# draws all objects on screen
def draw(screen, f, y_pos):
screen.fill((50, 50, 50))
for y in range(20):
for x in range(5):
pygame.draw.rect(screen, f[y][x], (x * 100, (y * 100) - y_pos, 100, 100))
pygame.draw.rect(screen, (250, 0, 0), (240, 240, 20, 20)) # drone
pygame.display.update()
# creates background
def field():
f = []
for y in range(20):
f.append([])
for x in range(5):
f[y].append((random.randint(200, 255), random.randint(200, 255), random.randint(200, 255)))
return f
# combines all functions
def main(screen):
f = field()
y_pos = 500
while True:
pygame.time.Clock().tick(30)
escape()
y_pos -= 1
draw(screen, f, y_pos)
# starts program
if __name__ == '__main__':
main(init())
I hope it works for you. :)
I'm experimenting, and I'm trying to get a circle to move along a line but stop once it reaches the edge of the screen. once this happens I can no longer go back the other way. There's probably a simple fix I'm not seeing, and it would be helpful to have someone point me in the right direction. Please keep in mind I am still a beginner.
from pygame import *
import random
import math
import os #Displays the pygame window at the top left of the screen
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d, %d" %(0,25)
init() #Starts pygame
font.init()
LENGTH = 1000 #Creates Screen that is 1000 X 700
WIDTH = 700
SIZE = (LENGTH, WIDTH)
Screen = display.set_mode(SIZE)
#Defines colours
BLACK = (0,0,0)
WHITE = (255,255,255)
RED = (255,0,0)
running = True
CaptainY = 350
Key = 0
while running:
for evnt in event.get(): # checks all events that happen
if evnt.type == QUIT: # if event type is quit the program stops running
running = False
if evnt.type == KEYDOWN:
Key = evnt.key
if evnt.type == KEYUP:
Key = 0
if 20 < CaptainY < 680:
if Key == K_UP:
CaptainY -= 5
if Key == K_DOWN:
CaptainY += 5
draw.rect(Screen, BLACK, (0,0, LENGTH, WIDTH))
draw.circle(Screen, WHITE, (950, CaptainY), 15)
if Key == K_ESCAPE:
print(CaptainY)
display.flip()
quit()
The program is doing what you told it: Move only if the y-position is between 20 and 680. If it's less than 20, this condition won't be True and the circle won't be able move anymore.
# You only move if this is True.
if 20 < CaptainY < 680:
Instead of stopping the movement, you should just move the position back, so that the circle ends up on the screen. Here's a complete example with a few more changes:
import pygame # Avoid * imports, since they make code harder to read and cause bugs.
pygame.init()
screen = pygame.display.set_mode((1000, 700))
HEIGHT = screen.get_height()
BLACK = (0,0,0)
WHITE = (255,255,255)
clock = pygame.time.Clock() # Use a clock to limit the frame rate.
running = True
captain_y = 350
captain_radius = 15
while running:
# Handle events.
for evnt in pygame.event.get():
if evnt.type == pygame.QUIT:
running = False
elif evnt.type == pygame.KEYDOWN:
if evnt.key == pygame.K_ESCAPE:
running = False
# To see if a key is being held down, use `pygame.key.get_pressed()`.
pressed_keys = pygame.key.get_pressed()
# Move if up or down keys are pressed.
if pressed_keys[pygame.K_UP]:
captain_y -= 5
elif pressed_keys[pygame.K_DOWN]:
captain_y += 5
# Update the game.
# Reset the position if the circle is off screen.
if captain_y - captain_radius <= 0:
captain_y = 0 + captain_radius
elif captain_y + captain_radius >= HEIGHT:
captain_y = HEIGHT - captain_radius
# Draw everything.
screen.fill(BLACK)
pygame.draw.circle(screen, WHITE, (950, captain_y), captain_radius)
pygame.display.flip()
clock.tick(60) # Cap the frame rate at 60 fps.
pygame.quit()
I have created a small program in pygame where the player controls a blue square moving around the screen, but I want to stop the player from moving past the edge of the screen. Here is the code I have so far, how can I do this?
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
done = False
x = 30
y = 30
clock = pygame.time.Clock()
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
is_blue = not is_blue
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP]: y -= 5
if pressed[pygame.K_DOWN]: y += 5
if pressed[pygame.K_LEFT]: x -= 5
if pressed[pygame.K_RIGHT]: x += 5
screen.fill((0, 0, 0))
color = (0, 128, 255)
pygame.draw.rect(screen, color, pygame.Rect(x, y, 60, 60))
pygame.display.flip()
clock.tick(60)
pygame.Rects have a clamp (and clamp_ip) method which you can use to limit the movement area. So create a rect with the size of the screen (called screen_rect here) and a rect for the player (player_rect) and call the clamp_ip method after each movement to keep it inside of the screen area.
import pygame as pg
pg.init()
screen = pg.display.set_mode((640, 480))
BG_COLOR = pg.Color(30, 30, 50)
def main():
clock = pg.time.Clock()
image = pg.Surface((50, 30))
image.fill(pg.Color('dodgerblue'))
pg.draw.rect(image, pg.Color(40, 220, 190), (0, 0, 49, 29), 2)
player_rect = image.get_rect(topleft=(200, 200))
# This pygame.Rect has the dimensions of the screen and
# is used to clamp the player_rect to this area.
screen_rect = screen.get_rect()
speed = 5
while True:
for event in pg.event.get():
if event.type == pg.QUIT:
return
pressed = pg.key.get_pressed()
if pressed[pg.K_UP]:
player_rect.y -= speed
if pressed[pg.K_DOWN]:
player_rect.y += speed
if pressed[pg.K_LEFT]:
player_rect.x -= speed
if pressed[pg.K_RIGHT]:
player_rect.x += speed
# Clamp the rect to the dimensions of the screen_rect.
player_rect.clamp_ip(screen_rect)
screen.fill(BG_COLOR)
screen.blit(image, player_rect)
pg.display.flip()
clock.tick(60)
if __name__ == '__main__':
main()
pg.quit()
This should work
if pressed[pygame.K_UP] and y > 0: y -= 5
if pressed[pygame.K_DOWN] and y < 600 - 60: y += 5
if pressed[pygame.K_LEFT] and x > 0: x -= 5
if pressed[pygame.K_RIGHT] and x < 800 - 60: x += 5
Where 600 and 800 is the screen size and 60 the size of your rectangle
Something like:
if pressed[pygame.K_UP]:
if not (y > maxwidth or y < 0):
y += 5
And so on for the others. the maxwidth looks like 600 in your code but I'd put it at the top of your code so you dont keep having to change it in different places.
What you are trying to do is called edge detection, as in detect if you are at an edge, in this case you want the edges to be the screen's edges. what you should do, is check if your x or y are at an edge, if so don't go any further.
if pressed[pygame.K_UP]:
if 0 < y-5 < 600: #0 and 600 being the edges of your screen, you can use a variable to change it dynamically later one
y -= 5
Note this will only detect if the top left's square is going out of bounds, since x and y is the top and left coords for the rectangle, meaning the bottom right of the square will be able to still go out of bounds,
If you want to check the whole square, you will have to make adjustment calculations in the if statement, or base your x and y on the center (which you will still have to modify the if statement to something like below. (note I'm altering based on your current code for x and y being top left.
if pressed[pygame.K_UP]:
if (0 < y-5 < 600) or (0< y+60-5 <600) #0 and 600 being the edges of your screen, you can use a variable to change it dynamically later one
y -= 5
This checks the other side of the square. Note for x you will check for the horizontal limits which in this case is 800. Also we are checking including the -5 because we want to see where we are going, not where we are at.