How can I limit the screen in pygame? [duplicate] - python

This question already has answers here:
Setting up an invisible boundary for my sprite
(1 answer)
Use vector2 in pygame. Collide with the window frame and restrict the ball to the rectangular area
(1 answer)
How to make ball bounce off wall with PyGame?
(1 answer)
Not letting the character move out of the window
(2 answers)
Closed 10 months ago.
I just started trying out pygame, so I watched a tutorial. When the guy showed, how to create edges left and right from the screen, it just didn't work when I did it, even though I've written it 100% equal as the tutorial guy. The tutorial is already two years old, so maybe pygame just has changed. Can somebody help me?
That's my code:
import pygame
import sys
pygame.init()
background = pygame.image.load("C:\Programmieren\Python\Grafiken\pygame test1 - background.png")
screen = pygame.display.set_mode([1200,595])
clock = pygame.time.Clock()
pygame.display.set_caption("pygame test1")
def draw():
screen.blit(background, (0, 0))
pygame.draw.rect(screen, (0, 0, 255), (x, y, width, height))
pygame.display.update()
x = 300
y = 300
speed = 3
width = 40
height = 80
left_wall = pygame.draw.rect(screen, (0,0,0), (-2,0,2,600), 0)
right_wall = pygame.draw.rect(screen, (0,0,0), (1201,0,2,600), 0)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
character = pygame.Rect(x,y,width, height)
pressed = pygame.key.get_pressed()
if presses[pygame.K_UP] or pressed[pygame.K_w] or pressed[pygame.K_SPACE]:
y -= speed
if pressed[pygame.K_RIGHT] or pressed[pygame.K_d] and not character.colliderect(right_wall):
x += speed
if pressed[pygame.K_DOWN] or pressed[pygame.K_s]:
y += speed
if pressed[pygame.K_LEFT] or pressed[pygame.K_a] and not character.colliderect(left_wall):
x -= speed
draw()
clock.tick(60)

The following code works for me after replacing the background.png path with a picture that exists on my computer. I changed left_wall and right_wall to call pygame.Rect instead of pygame.draw.rect and copied the draw.rect calls that were previously assigned to left_wall and right_wall to draw() function, and added some needed parentheses in two of the if statements. Also fixed a typo where pressed was spelled presses.
Without the parentheses, the character would always move right when right key is pressed even past the right edge of the window. When "d" is pressed, it would check against colliderect. Same for left arrow and "a" keys. or short-circuits, so if K_RIGHT or K_LEFT is pressed, it doesn't check the right hand side of the or in the if statements. With the parentheses added, the "move right" if statement always checks colliderect when K_RIGHT or K_d is pressed, instead of only when K_d is pressed.
import pygame
import sys
pygame.init()
background = pygame.image.load("C:\Programmieren\Python\Grafiken\pygame test1 - background.png")
screen = pygame.display.set_mode([1200,595])
clock = pygame.time.Clock()
pygame.display.set_caption("pygame test1")
def draw():
screen.blit(background, (0, 0))
pygame.draw.rect(screen, (0, 0, 255), (x, y, width, height))
pygame.draw.rect(screen, (0,0,0), left_wall, 0)
pygame.draw.rect(screen, (0,0,0), right_wall, 0)
pygame.display.update()
x = 300
y = 300
speed = 3
width = 40
height = 80
left_wall = pygame.Rect(-2,0,2,600)
right_wall = pygame.Rect(1201,0,2,600)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
character = pygame.Rect(x,y,width, height)
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP] or pressed[pygame.K_w] or pressed[pygame.K_SPACE]:
y -= speed
if (pressed[pygame.K_RIGHT] or pressed[pygame.K_d]) and not character.colliderect(right_wall):
x += speed
if pressed[pygame.K_DOWN] or pressed[pygame.K_s]:
y += speed
if (pressed[pygame.K_LEFT] or pressed[pygame.K_a]) and not character.colliderect(left_wall):
x -= speed
draw()
clock.tick(60)

Related

i cant figure out my python game keep crashing

please help when i press space, e, or f my game crashes but i cant find out why also can you help me make this dam block move upwards. please help me i will go insane if i cant figure this out.
`
# import the pygame module
import pygame
import keyboard
import time
xb = 30
yb = 670
x = 30
y = 670
o = 0
# Define the background colour
# using RGB color coding.
background_colour = (10,10,10)
# Define the dimensions of
# screen object(width,height)
screen = pygame.display.set_mode((800, 750),pygame.RESIZABLE)
# Set the caption of the screen
pygame.display.set_caption('shoter')
# Fill the background colour to the screen
screen.fill(background_colour)
def player():
color = (40,40,45)
pygame.draw.rect(screen, color, pygame.Rect(x, y, 60, 60))
pygame.draw.polygon(screen, color, ((x+60,y), (x+30,y-80), (x,y)))
pygame.draw.polygon(screen, color, ((x-20,y+52.5), (x+30,y+70), (x+80,y+52.5)))
color = (60,60,65)
pygame.draw.rect(screen, color, pygame.Rect((x-70), (y+20), 200, 30))
color = (40,40,45)
pygame.draw.rect(screen, color, pygame.Rect(x-70, y-20, 20, 40))
pygame.draw.rect(screen, color, pygame.Rect(x+110, y-20, 20, 40))
# Update the display using flip
pygame.display.flip()
# Variable to keep our game loop running
running = True
while running:
for event in pygame.event.get():
# Check for QUIT event
if event.type == pygame.QUIT:
running = False
if keyboard.is_pressed("a") or keyboard.is_pressed("w") or keyboard.is_pressed("left arrow"):
print("left")
screen.fill(background_colour)
x = (x + -3.75)
player()
time.sleep(0.005)
pygame.display.flip()
if keyboard.is_pressed("d") or keyboard.is_pressed("s") or keyboard.is_pressed("right arrow"):
print("right")
screen.fill(background_colour)
x = (x + 3.75)
player()
time.sleep(0.005)
pygame.display.flip()
if keyboard.is_pressed("space") or keyboard.is_pressed("f") or keyboard.is_pressed("e"):
color = (255,0,0)
pygame.draw.rect(screen, color, pygame.Rect(xb, yb, 60, 60))
while (yb > -40):
yb = yb + 5
time.sleep(0.5)
print("shot")
pygame.display.flip()
time.sleep(0.01)
`
please help me ive tried to almost everything to make it work but everytime i press space it crashes
i think this is because of the while loop?
In PyGame, the 0,0 co-ordinate is in the upper-left corner of the window. In your game the player is positioned at the bottom, so the projectile moves up the display, going from a large y-coordinate to a smaller one, and eventually negative once off-screen.
As #Chris Doyle points out in a comment, your code has a tight loop where yb is increased, but then is tested for being < -40. Since yb is already positive, this can never happen. So your program is locking up at this point, as the loop exiting condition can never be satisfied.
Looking at your code, there's a few tweaks necessary for the projectile logic.
First it's best to try to paint everything on the screen from one place, then you're not re-painting (or accidentally erasing) items on every loop.
I also moved the logic of the bullet movement out into the main loop. So pressing space only starts the bullet. The movement happens when the main loop "sees" a bullet on the screen (when firing is True).
Other tweaks: I don't have the keyboard module, so I ported this to standard PyGame keys. And I took the liberty of renaming the x,y and xb,yb to player_x, player_y and projectile_x, projectile_y. I hope that's OK.
# import the pygame module
import pygame
#import keyboard
import time
projectile_x = 30
projectile_y = 670
player_x = 30
player_y = 670
o = 0
# Define the background colour
# using RGB color coding.
background_colour = (10,10,10)
# Define the dimensions of
# screen object(width,height)
screen = pygame.display.set_mode((800, 750),pygame.RESIZABLE)
# Set the caption of the screen
pygame.display.set_caption('shoter')
# Fill the background colour to the screen
screen.fill(background_colour)
def player():
color = (40,40,45)
pygame.draw.rect(screen, color, pygame.Rect(player_x, player_y, 60, 60))
pygame.draw.polygon(screen, color, ((player_x+60,player_y), (player_x+30,player_y-80), (player_x,player_y)))
pygame.draw.polygon(screen, color, ((player_x-20,player_y+52.5), (player_x+30,player_y+70), (player_x+80,player_y+52.5)))
color = (60,60,65)
pygame.draw.rect(screen, color, pygame.Rect((player_x-70), (player_y+20), 200, 30))
color = (40,40,45)
pygame.draw.rect(screen, color, pygame.Rect(player_x-70, player_y-20, 20, 40))
pygame.draw.rect(screen, color, pygame.Rect(player_x+110, player_y-20, 20, 40))
# Update the display using flip
pygame.display.flip()
# Is a projectile on screen?
firing = False
# Variable to keep our game loop running
running = True
clock = pygame.time.Clock()
while running:
for event in pygame.event.get():
# Check for QUIT event
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
a_w_left = keys[pygame.K_LEFT] or keys[pygame.K_a] or keys[pygame.K_w]
d_s_right = keys[pygame.K_RIGHT] or keys[pygame.K_d] or keys[pygame.K_s]
e_f_space = keys[pygame.K_SPACE] or keys[pygame.K_e] or keys[pygame.K_f]
if a_w_left:
print("left")
player_x = (player_x + -3.75)
if d_s_right:
print("right")
player_x = (player_x + 3.75)
if e_f_space:
if ( not firing ):
firing = True
projectile_x = player_x
projectile_y = player_y - 10
print("shot")
# repaint the screen
screen.fill(background_colour)
player()
if ( firing ):
color = (255,0,0)
pygame.draw.rect(screen, color, pygame.Rect(projectile_x, projectile_y, 60, 60))
projectile_y = projectile_y - 5
if ( projectile_y < -60 ):
firing = False # bullet off screen
pygame.display.flip()
clock.tick( 60 ) # limit FPS
Also, it's not good practice to use time.sleep() to control movement (etc.) in a PyGame program, because it blocks everything up. It's better to use the real-time millisecond clock provided by pygame.time.get_ticks().

Pygame mouse position not precise enough to rotate the 3D scene

I need to rotate a 3D scene or a character using the mouse position: for example, if I move the mouse to the right, I want to turn to the right / the character should turn right.
I've seen lots of games place the mouse in the center of the screen, then get its position relatively to the previous frame, update the game accordingly and move the mouse back in the center.
I tried to replicate this but I ran into the issue that pygame does not rotate reliably: with higher framerates, I tend to get a slower rotation. This is not a problem when rotating a character in a 2D game, but this is concerning when a 3D scene rotates differently if there are more objects to draw.
I used this simple code to make sure the problem actually came from this:
import pygame
from pygame.locals import *
pygame.init()
WIDTH, HEIGHT = (640, 480)
screen = pygame.display.set_mode((WIDTH, HEIGHT))
font = pygame.font.SysFont('consolas', 20)
clock = pygame.time.Clock()
angle = 0
time_passed = 0
pygame.mouse.set_pos((WIDTH//2, HEIGHT//2))
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
exit()
# I did not use the MOUSEMOTION event because it used to glitch a bit
x, y = pygame.mouse.get_pos()
angle += (WIDTH//2 - x) * 360 / WIDTH # 360° every WIDTH pixels
pygame.mouse.set_pos((WIDTH//2, HEIGHT//2))
screen.fill(0)
text = font.render('Angle: %d°' %angle, True, (255, 255, 255))
w, h = text.get_size()
screen.blit(text, (WIDTH//2 - w//2, HEIGHT//2 - h//2))
pygame.display.flip()
time_passed = clock.tick(60)/1000
I think either the mouse or the OS tweak the travelled distance according to the mouse speed, so I did the following tests at similar and relatively constant speed:
Going say 5 centimeters with the framerate limited to 60 FPS did not result in the same final angle as with 120 FPS for example, even when moving the mouse at the same speed, with the same mouse with high DPI.
Do I need to implement a tick system for example, where I only update the position every few frames? I think the problem wouldn't be solved with slower framerates then, and maybe the movement would not be as responsive as I want.
Or perhaps there is an alternative to pygame.mouse.get_pos() / event.pos, getting the raw, more precise position from the mouse?
I would appreciate any help.
You get the position of the mouse with pygame.mouse.get_pos() and you reset the position with pygame.mouse.set_pos(). What if there was an event between pygame.mouse.get_pos() and pygame.mouse.set_pos()? Also pygame.mouse.get_pos() only tells you the current position of the mouse curosr, but it does not tell you how the mouse got there.
I suggest to use the MOUSEMOTION event. The event queue gives you all movements of the mouse. The relative movement of the mouse pointer since the last movement can be queried with the rel attribute:
for event in pygame.event.get():
if event.type == pygame.MOUSEMOTION:
angle += event.rel[0] * 360 / screen.get_width()
Minimal example
import pygame
pygame.init()
screen = pygame.display.set_mode((640, 480))
font = pygame.font.SysFont('consolas', 20)
clock = pygame.time.Clock()
angle = 0
text = font.render(f'Angle: {angle}°', True, (255, 255, 255))
pygame.mouse.set_pos(screen.get_rect().center)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
run = False
if event.type == pygame.MOUSEMOTION:
angle += event.rel[0] * 360 / screen.get_width()
text = font.render(f'Angle: {angle}°', True, (255, 255, 255))
pygame.mouse.set_pos(screen.get_rect().center)
screen.fill(0)
screen.blit(text, text.get_rect(center = screen.get_rect().center))
pygame.display.flip()
pygame.quit()
exit()

pygame movement speed is not constant [duplicate]

This question already has answers here:
Pygame clock and event loops
(1 answer)
Framerate affect the speed of the game
(1 answer)
Closed last year.
I recently started with pygame and im trying to create movement but when I move my rectangle the speed changes at various times. it becomes slower and faster at various times
import pygame
pygame.init() # inisializing pygame
WIN = pygame.display.set_mode((500, 500)) # the width and hieght of the window
pygame.display.set_caption('pygame tutorial') # give the window a title
x = 50
y = 50 # character x and y positions
width = 40
height = 60 # rectangle width and height
vel = 5 # velocity (speed)
run = True # boolean variable
while run: # forever loop
for event in pygame.event.get(): # specifing the event
if event.type == pygame.QUIT: # pygame.QUIT makes the red x work so you can close the window
run = False # run = false so the while loop stops
key = pygame.key.get_pressed()
if key [pygame.K_a]:
x -= vel
if key[pygame.K_d]:
x += vel
if key[pygame.K_w]:
y -= vel
if key[pygame.K_s]:
y += vel
WIN.fill((0,0,0))
pygame.draw.rect(WIN, (255, 0, 0), (x, y, width, height))
'''
create a rectangle with 3 arguements, the window, the rgb colour, and the x,y positions width and height
'''
pygame.display.update()
pygame.quit()
You have wrong indentations so some code is executed inside many times in for-loop but it should be executed only once after for-loop
After changing indentations code work too fast and I needed to add clock.tick(60) to reduce speed to max 60 frames per second. This way it should run with the same speed on computers with older and newer CPU.
WIN = pygame.display.set_mode((500, 500)) # the width and hieght of the window
pygame.display.set_caption('pygame tutorial') # give the window a title
x = 50
y = 50 # character x and y positions
width = 40
height = 60 # rectangle width and height
vel = 5 # velocity (speed)
run = True # boolean variable
clock = pygame.time.Clock()
while run: # forever loop
for event in pygame.event.get(): # specifying the event
if event.type == pygame.QUIT: # pygame.QUIT makes the red x work so you can close the window
run = False # run = false so the while loop stops
# --- after loop --
key = pygame.key.get_pressed()
if key [pygame.K_a]:
x -= vel
if key[pygame.K_d]:
x += vel
if key[pygame.K_w]:
y -= vel
if key[pygame.K_s]:
y += vel
WIN.fill((0,0,0))
pygame.draw.rect(WIN, (255, 0, 0), (x, y, width, height))
'''
create a rectangle with 3 arguments, the window, the rgb colour, and the x,y positions width and height
'''
pygame.display.update()
clock.tick(60) # reduce speed to max 60 frames per seconds
pygame.quit()

How to print out background image using "blit" in pygame? [duplicate]

This question already has answers here:
Why is nothing drawn in PyGame at all?
(2 answers)
Closed 1 year ago.
import pygame
import os
pygame.font.init()
pygame.mixer.init()
WIDTH, HEIGHT = 900, 500
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("HELP ME")
WHITE = (255, 255, 255)
black = (0, 0, 0)
MENU_bg = pygame.transform.scale(pygame.image.load(os.path.join("menu.png")), (WIDTH, HEIGHT))
quiting = 0
def main_menu():
running = True
quiting = 0
clock = pygame.time.Clock()
FPS = 60
WIN.blit(MENU_bg, (0, 0))
while running:
clock.tick(FPS)
if quiting == 1:
exit()
WIN.blit(MENU_bg, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
quiting = 1
if event.type == pygame.MOUSEBUTTONUP:
mouse_pos = pygame.mouse.get_pos()
print(mouse_pos)
if mouse_pos[0] >= 0 and mouse_pos[0] <= 450 and mouse_pos[1] >= 200 and mouse_pos[1] <= 500:
running = False
# Here I will link to another function
I get no error messages when running the code, but the images don´t show up. The image files are available and their right names have been used. I have read several tutorials and don´t see what I´ve done wrong.
You need to update the display.
You are actually drawing on a Surface object. If you draw on the Surface associated to the PyGame display, this is not immediately visible in the display. The changes become visibel, when the display is updated with either pygame.display.update() or pygame.display.flip():
def main_menu():
# [...]
while running:
clock.tick(FPS)
if quiting == 1:
exit()
WIN.blit(MENU_bg, (0, 0))
# [...]
pygame.display.flip()

My pygame window keeps crashing and I'm following a youtube tutorial, on mac [duplicate]

This question already has answers here:
Pygame Drawing a Rectangle
(6 answers)
Closed 2 years ago.
I'm very new to python and I've been following Tech With Tim's pygame tutorial, but my window isn't responding or closing. I'm using a mac and I don't know if that changes anything... and I keep getting the error message
Error:
function missing required argument 'rect' (pos 3).
Code:
import pygame
pygame.init()
win = pygame.display.set_mode((500, 500))
pygame.display.set_caption("First game")
x = 50
y = 50
width = 40
height = 60
vel = 5
run = True
while run:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
x -= vel
if keys[pygame.K_RIGHT]:
x += vel
if keys[pygame.K_UP]:
y -= vel
if keys[pygame.K_DOWN]:
y += vel
pygame.draw.rect(win, (255, 0, 0))
pygame.display.update()
pygame.quit()
rect function takes at least three arguments, only 2 were given:
pygame.draw.rect(win, (255, 0, 0), (x, y, width, height))
It should work on mac too
Check pygame docs for reference : https://www.pygame.org/docs/ref/draw.html#pygame.draw.rect
Actually you have not typed it's height width x position and y position where you drew the rectangle do this
pygame.draw.rect(win, (255, 0, 0), (x, y, height, width))
You have x, y, height, width already defined this should work.

Categories

Resources