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()
Related
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.
import pygame
pygame.init()
display_width = (640)
display_height = (480)
title = pygame.display.set_caption("test")
IMG = pygame.image.load("image.png")
screen = pygame.display.set_mode((display_width,display_height))
screen.blit(IMG,(1,1))
pygame.display.update()
Whenever I use pygame, even simple displays like this are skewed for me. it shows 0,0 at around the middle of my display screen and i dont know why. Basically, it is showing - x values on the x axis help!
I am using python 2.7 and this seems to not be a coding issue, but rather something else. please help! ty
I've not been able to replicate your problem with the above code in Python 2.7.12, the image is a red, fifty-pixel square:
Here's an extended demo that will draw the image around the cursor position based on the mouse button clicked. Perhaps that'll help you get towards the behaviour you're after.
import pygame
if __name__ == "__main__":
pygame.init()
screen_width, screen_height = 640, 480
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Blit Demo')
clock = pygame.time.Clock() #for limiting FPS
FPS = 10
exit_demo = False
# start with a white background
screen.fill(pygame.Color("white"))
img = pygame.image.load("image.png")
width, height = img.get_size()
pos = (1,1) # initial position to draw the image
# main loop
while not exit_demo:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit_demo = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
# fill the screen with white, erasing everything
screen.fill(pygame.Color("white"))
elif event.type == pygame.MOUSEBUTTONUP:
if event.button == 1: # left
pos = (event.pos[0] - width, event.pos[1] - height)
elif event.button == 2: # middle
pos = (event.pos[0] - width // 2, event.pos[1] - height // 2)
elif event.button == 3: # right
pos = event.pos
# draw the image here
screen.blit(img, pos)
# update screen
pygame.display.update()
clock.tick(FPS)
pygame.quit()
quit()
This question already has answers here:
Pygame doesn't let me use float for rect.move, but I need it
(2 answers)
Problem with Pygame movement acceleration, platformer game
(1 answer)
Closed 2 years ago.
Im trying to set player controlled character in the game constantly face the mouse. I managed to get the angle working well except that towards the edges of the screen, as in the surface the object is blited onto, it seems to get progressively less and less accurate. it rotates allot less and seems to want to face the center of the screen. In the middle of the screen the object rotates almost perfectly.
Edit: It doesnt actually seem to want to face the center, it wants to face the original point that it blited into, rather then the place it is currently in.
# Imports
import pygame
import os
import math
import pyganim
# -- Initialize the Surface --
# Startup
pygame.init()
# Screen
size = (500, 500)
screen = pygame.display.set_mode(size)
pygame.mouse.set_visible(True)
clock = pygame.time.Clock()
# -- Assign Global Variables --
#Sets the color of pure white to a variable to be called
WHITE = (255, 255, 255)
#Sets the color of pure black to a variable to be called
BLACK = (0, 0, 0)
#Sets the background to an image
menu_Background = pygame.image.load("image-menu_background.png")
#Sets the possible players to images
player_bright_blue = pygame.image.load("player-bright_blue.png")
player_dark_blue = pygame.image.load("player-dark_blue.png")
player_bright_green = pygame.image.load("player-bright_green.png")
player_dark_green = pygame.image.load("player-dark_green.png")
player_bright_purple = pygame.image.load("player-bright_purple.png")
player_dark_purple = pygame.image.load("player-dark_purple.png")
player_bright_red = pygame.image.load("player-bright_red.png")
player_dark_red = pygame.image.load("player-dark_red.png")
#Sets the weapons for the player to images\
player_bright_green_shortsword = pygame.image.load("player-bright_green_shortsword.png")
#Sets the pointer to an image
pointer = pygame.image.load("pointer-cross_green.png")
#Sets the dark and bright menu go button to an image
menu_go_dark = pygame.image.load("button-go_dark.png")
menu_go_bright = pygame.image.load("button-go_bright.png")
#Sets the dark and bright menu exit button to an image
menu_exit_dark = pygame.image.load("button-exit_dark.png")
menu_exit_bright = pygame.image.load("button-exit_bright.png")
#sets the dark and bright menu options button to an image
menu_options_dark = pygame.image.load("button-options_dark.png")
menu_options_bright = pygame.image.load("button-options_bright.png")
#sets the arcflash text to an image and animation
anim_arcflash = pyganim.PygAnimation([("anim-arcflash_001.png", 100),
("anim-arcflash_002.png", 100),
("anim-arcflash_003.png", 100),
("anim-arcflash_004.png", 100),
("anim-arcflash_005.png", 100),
("anim-arcflash_006.png", 100)])
anim_arcflash.play
arcflash = pygame.image.load("image-arcflash.png")
#Sets a variable to know whether the script has run once or not
firstRun = 0
#sets up the Main loop of the game
# -- Main Loop --
def Main_Loop():
#Sets the bool for the loop to run on
loop = True
#Game variables --
#Sets the player center position
player_pos_x = 255
player_pos_y = 255
#Sets the players X and y speed
move_a_speed = 0
move_d_speed = 0
move_w_speed = 0
move_s_speed = 0
move_x_speed = 0
move_y_speed = 0
#Makes the mouse invisible
pygame.mouse.set_visible(False)
#Starts the loop
while loop == True:
# -- Event Loop --
for event in pygame.event.get():
if event.type == pygame.QUIT:
Game_Quit()
if event.type == pygame.KEYDOWN:
if event.type == pygame.QUIT:
done = True
elif event.key == pygame.K_a:
move_a_speed = -2
elif event.key == pygame.K_d:
move_d_speed = 2
elif event.key == pygame.K_w:
move_w_speed = -2
elif event.key == pygame.K_s:
move_s_speed = 2
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
move_a_speed = 0
elif event.key == pygame.K_d:
move_d_speed = 0
elif event.key == pygame.K_w:
move_w_speed = 0
elif event.key == pygame.K_s:
move_s_speed = 0
# -- Screen Clearing --
screen.fill(WHITE)
# -- Drawing Logic --
move_x_speed = move_a_speed + move_d_speed
move_y_speed = move_w_speed + move_s_speed
#Increments vertical and horizontal player position by horizontal
#and vertical speed
player_pos_x += move_x_speed
player_pos_y += move_y_speed
#Set the mouse X and Y to a variable
mouse_pos = pygame.mouse.get_pos()
#Set the angle needed to rotate
angle = 270-math.atan2(mouse_pos[1] - player_pos_x, mouse_pos[0] - player_pos_y) * 180 / math.pi
# should rotate the character to the mouse, but doesnt work properly towards the edge/while moving
#Transforms the image to the angle
player_rotate = pygame.transform.rotate(player_bright_green, angle)
rect = player_rotate.get_rect(center=(player_pos_x + 15, player_pos_y + 15))
# -- Drawing --
#blits the rotated player
screen.blit(player_rotate, rect)
#blits the weapon the player is currently using
Sword(player_bright_green_shortsword, player_pos_x, player_pos_y, 14, 25)
#blits the pointer at mouse - KEEP ABOVE ALL OTHER BLITS
screen.blit(pointer, [mouse_pos[0] - 50, mouse_pos[1] - 50])
#Screen Refresh
pygame.display.flip()
# -- Refresh Rate --
clock.tick(80)
fps = str(clock.get_fps())
pygame.display.set_caption(fps)
# -- Runs the game --
(i left out the whole menu script it seemed unnecessary.)
Ive tried adjusting the values in the angle calculation and this game isnt really going to be viable without a moving character.
My end goal is to have the character perfectly synced to the mouse, or atleast as perfect as possible.
A section of jetfighterx leaves the screen when the mouse hovers over the edge of the window, this causes tarantula to explode from time to time as soon as it respawns to the top of the window, how can I stop this from happening (without the use of classes)?
Code:
import pygame, sys, pygame.mixer
from pygame.locals import *
import random
pygame.init()
bif = "space.jpg"
jf = "spacefightersprite.png"
enemy = "TarantulaSpaceFighter.png"
laser = pygame.mixer.Sound("LaserBlast.wav")
explosionsound = pygame.mixer.Sound("Explosion.wav")
screen = pygame.display.set_mode((1000,900),0,32)
caption = pygame.display.set_caption("Jet Fighter X")
background = pygame.image.load(bif).convert()
jetfighterx = pygame.image.load(jf)
jetfighterx = pygame.transform.scale(jetfighterx, (400,400))
tarantula = pygame.image.load(enemy)
tarantula = pygame.transform.scale(tarantula, (100,100))
laserblast = pygame.image.load("C:\Python27\laser.png")
explosion=pygame.image.load("C:\Python27\explosion.png")
explosion=pygame.transform.scale(explosion, (150,150))
ex,ey = 450,0
movex,movey = 0,0
clock = pygame.time.Clock()
speed = 300
shoot_y = 0
laser_fired = False
collision = False
alive = True
explo_timer = 25
while True:
pygame.mouse.set_visible(False)
mx,my = pygame.mouse.get_pos()
jetfighterx_rect = jetfighterx.get_rect(center=(mx, my))
jetfighterx_rect = jetfighterx_rect.inflate(-200,-200)
tarantula_rect = tarantula.get_rect(center=(ex, ey))
tarantula_rect = tarantula_rect.inflate(-180,-200)
# Check for player inputs
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE or event.key == K_q:
sys.exit()
if event.type == MOUSEBUTTONDOWN:
laser_fired = True
laser.play()
shoot_y = my-200
shoot_x = mx-16
# Update Game
milli = clock.tick()
seconds = milli/1000.
dmy = seconds * speed
ey += dmy
if ey > 900:
explo_timer = 25
collision = False
alive = True
ey = 0
ex = random.randint(50,900)
if laser_fired:
shoot_y -= 10
if shoot_y < 0:
laser_fired = False
else:
laserblast_rect = laserblast.get_rect(center=(shoot_x, shoot_y))
if laserblast_rect.colliderect(tarantula_rect):
explosionsound.play()
collision = True
alive = False
if jetfighterx_rect.colliderect(tarantula_rect) and alive:
explosionsound.play()
collision = True
alive = False
# Draw on screen
screen.blit(background, (0,0))
screen.blit(jetfighterx,(mx-200,my-200))
if not collision:
screen.blit(tarantula, (ex, ey))
elif collision:
explo_timer-=2
if explo_timer > 0 and alive == False:
screen.blit(explosion, (ex, ey-50))
if laser_fired:
screen.blit(laserblast, (shoot_x, shoot_y))
pygame.display.update()
Just add a limit that does not allow the fighter to move within x pixels of the border.
Assuming that the x,y coordinates of the centre of your fighter are jetfighter_x, jetfighter_y (You will need to change the variable names to whatever your code has) then write something like this:
LBuffer = 16
RBuffer = 1000 - 16
TBuffer = 900 - 16
BBuffer = 16
if jetfighter_x > RBuffer:
jetfighter_x = RBuffer
if jetfighter_x < LBuffer:
jetfighter_x = LBuffer
if jetfighter_y > TBuffer:
jetfighter_y = TBuffer
if jetfighter_y < BBuffer:
jetfighter_y = BBuffer
This should prevent the center of the ship from getting closer than 16 pixels from the edge. Obviously you will need to tweak this to accommodate the size of your ship. (The buffer for the sides would be the width of the image/2 .Respectively the buffer for the top and bottom would be the height of the image/2).
I've been racking my brain and trying to find how to:
Start a program displaying image 1 on a Pygame drawing surface
Flash image 2 for a short amount of time, like 2 seconds
Reset the program to the initial state (step 1)
For some reason, I'm getting an error message:
AttributeError: 'module' object has no attribute 'sleep'
I found a post (https://ubuntuforums.org/showthread.php?t=1129861) where the person having this error message had a file called time.py. That doesn't seem to be the problem here.
It seems that sleep should work inside Pygame (animation in pygame).
What I'm trying to achieve here is not necessarily to stop the whole program, but just to display a different image while the program is running.
Here is my code. I am fully aware that it is far from elegant and I'm working on that also:
===
# This is my first game demonstration in python
import pygame, sys, random, time
from pygame import *
pygame.init()
# variables globales
global width, height
width, height = 500, 400
pygame.display.set_caption("Test Program")
global player, px, py
player = pygame.image.load("image 1.png") # load the player image
player = pygame.transform.scale(player, (125,125))
px,py = (width - 125)/2, (height - 125)/2 # pour centrer l'image
global DISPLAYSURF
DISPLAYSURF = pygame.display.set_mode((500, 400), 0, 32)
def game():
global player, px, py
# set up the colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
# draw on the surface object
DISPLAYSURF.fill(BLACK)
# speed of game and other variables initiated
clock = pygame.time.Clock()
gamespeed = 100
movex = movey = 0
score = 0
# this is the score text loading
gamefont = pygame.font.Font(None, 30)
scoretext = gamefont.render("Player Score: " + str(score), 2, [255,0,0])
boxsize = scoretext.get_rect()
scoreXpos = (width - boxsize[2])/2
# running of the game loop
while True:
# image display updates
seconds = clock.tick()/1000.0
playerImage()
scoretext = gamefont.render("Player Score: " + str(score), 2, [255,0,0])
DISPLAYSURF.blit(scoretext, [scoreXpos, 20])
pygame.display.update()
# keyboard and/or mouse movements
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == KEYDOWN:
if event.key == K_RIGHT:
movex = 2
if event.key == K_LEFT:
movex = -2
if event.key == K_UP:
movey = -2
if event.key == K_DOWN:
movey = 2
elif event.type == KEYUP:
if event.key == K_RIGHT:
movex = 0
if event.key == K_LEFT:
movex = 0
if event.key == K_UP:
movey = 0
if event.key == K_DOWN:
movey = 0
px = px + movex
py = py + movey
def playerImage():
global player
global px
global py
player = pygame.image.load("image 2.png") # load the player image
DISPLAYSURF.blit(player, (px, py))
player = pygame.transform.scale(player, (125,125))
px,py = (width - 125)/2, (height - 125)/2 # pour centrer l'image
time.sleep(2)
# python's way of running the main routine
if __name__ == "__main__":
game()
You're calling implicit
pygame.time.sleep
that doesn't have the sleep method instead of
time.sleep
Import the time module to access its functionality. But watch out to not overwrite the names in your script.
It's generally a bad idea to use from xxx import *, just use import pygame or import pygame as xxx.
Since "time" is extremely important in any decent game (Events happening after some time in milliseconds, seconds, minutes, etc), I've created a way to deal with it natively in my engine. (The wiki is far from complete, but you should check out my "EwApp" class, as it provides methods to do exactly that.).
Anyway, the point here is: You should solve this issue without using python's time. Instead, you should work only with pygame.time (Since using Python's time will PAUSE your entire game for that given amount of time, and that's atrocious). I've developed a simple example adapting my method using "dt", that draws a red rectangle, then draws a green one and waits for 1 second, and then returns to the initial state.
import pygame
if __name__ == "__main__":
pygame.init()
done = False
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
SURFACE_SIZE = 300
screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
clock = pygame.time.Clock()
FPS = 1
time_elapsed = 0
def check_if_time_has_elapsed_in_seconds(seconds):
global time_elapsed
if time_elapsed > seconds*1000:
time_elapsed = 0
return True
else:
return False
def get_center(*args):
if len(args) == 2:
return ((args[0]/2)-(args[1]/2))
surf1 = pygame.Surface((SURFACE_SIZE, SURFACE_SIZE))
pygame.draw.rect(surf1, (0, 255, 0), (0, 0, SURFACE_SIZE, SURFACE_SIZE), 0)
surf2 = pygame.Surface((SURFACE_SIZE, SURFACE_SIZE))
pygame.draw.rect(surf2, (255, 0, 0), (0, 0, SURFACE_SIZE, SURFACE_SIZE), 0)
while not done:
dt = clock.tick(FPS)
time_elapsed += dt
pygame.display.flip()
screen.fill((0, 0, 0))
screen.blit(surf1, (get_center(SCREEN_WIDTH, SURFACE_SIZE), get_center(SCREEN_HEIGHT, SURFACE_SIZE)))
if check_if_time_has_elapsed_in_seconds(1):
screen.blit(surf2, (get_center(SCREEN_WIDTH, SURFACE_SIZE), get_center(SCREEN_HEIGHT, SURFACE_SIZE)))
for e in pygame.event.get():
if e.type == pygame.QUIT:
done = True
pygame.quit()
With my engine this can be achieved really easily, though. My engine is open-source and is on github, but that's the main spirit: Incrementing a "time_elapsed" variable by dt (ticks) within the main loop in order to check wether some amount of time has passed or not. Creating external functions, like I did, make it much easier/handy. This technique is also known as "cooldown". Useful for one hundred thousand things (Like, for example, moving characteres by great amount of pixels, but slowly (After some milliseconds of cooldown)).