This question already has an answer here:
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
Closed 2 years ago.
I’m new to programming and know the basics of Python and wanted to ask how I can perform an action if two images overlap a little bit and then a specific button is pressed in pygame.
The game looks like following:
import pygame
import random
pygame.init()
window = pygame.display.set_mode((1000, 600))
caption = pygame.display.set_caption(
'Test your reaction speed. Shoot the target game!') # sets a caption for the window
game_running = True # this is the gameloop so the window stays open
PlayerImg = pygame.image.load('F:\PythonPortable\oscn.png')
PlayerX = 370
PlayerY = 420
PlayerX_change = 0
PlayerY_change = 0
def player():
window.blit(PlayerImg, (PlayerX, PlayerY))
aim_sight = pygame.image.load('F:\PythonPortable\ktarget.png')
aim_sightX = 460
aim_sightY = 300
aim_sight_changeX = 0
aim_sight_changeY = 0
def aim_sight_function(x, y):
window.blit(aim_sight, (x, y))
targetedImg = pygame.image.load('F:\PythonPortable\ktargetedperson.png')
targetedX = random.randint(0, 872)
targetedY = random.randint(0, 200)
def random_target():
window.blit(targetedImg, (targetedX, targetedY))
while game_running:
window.fill((255, 255, 255))
random_target()
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
aim_sight_changeX = -2
PlayerX_change = -2
elif event.key == pygame.K_RIGHT:
aim_sight_changeX = 2
PlayerX_change = 2
elif event.key == pygame.K_UP:
aim_sight_changeY = -2
PlayerY_change = -2
elif event.key == pygame.K_DOWN:
aim_sight_changeY = 2
PlayerY_change = 2
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
aim_sight_changeX = 0
PlayerX_change = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
aim_sight_changeY = 0
PlayerY_change = 0
aim_sightX += aim_sight_changeX
if aim_sightX <= 46.5:
aim_sight_changeX = 0
elif aim_sightX >= 936:
aim_sight_changeX = 0
aim_sightY += aim_sight_changeY
if aim_sightY <= 0:
aim_sight_changeY = 0
elif aim_sightY >= 400:
aim_sight_changeY = 0
PlayerX += PlayerX_change
if PlayerX <= -50:
PlayerX_change = 0
elif PlayerX >= 850:
PlayerX_change = 0
player()
aim_sight_function(aim_sightX, aim_sightY)
pygame.display.update()
I would like to know how a do what I want. I thought maybe:
if event.type == pygame.K_SPACE and targetedX == targetedX in range(aim_sightX - 100, aim_sightY + 100) or targetedY == targetedY in range (aim_sightY - 100, aim_sightY + 100):
...
It seems as though none of the tutorials I watched cover this topic and would like to recieve recommendations for tutorials that cover this problem or a direct answer.
I recommend to use a pygame.Rect objects and colliderect() to find a collision between two Surface objects. pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, that always starts at (0, 0) since a Surface object has no position. The position of the rectangle can be specified by a keyword argument:
PlayerImg_rect = PlayerImg.get_rect(topleft = (PlayerX, PlayerY))
targetedImg_rect = targetedImg .get_rect(topleft = (targetedX, targetedX))
if PlayerImg_rect.colliderect(targetedImg_rect):
print("hit")
Related
This question already has an answer here:
How do I get the snake to grow and chain the movement of the snake's body?
(1 answer)
Closed 1 year ago.
Hi guys I started learning pygames, i started playing snake and came to an obstacle. I don't know how to make a function for my snake to grow when it eats an apple, I've looked at a lot of snake codes and I'm still not sure how to do it. I dont have idea how to do that, I realy hope you can give mi some advice to improve my game.
your help would do me good, thanks
import pygame
import random
import math
# Init
pygame.init()
# Screen
screen = pygame.display.set_mode((800, 600))
# Caption and Icon
pygame.display.set_caption("Snake Game")
icon = pygame.image.load('icon.png')
pygame.display.set_icon(icon)
# Background
background = pygame.image.load('background.jpg')
# Snake
snakeImg = pygame.image.load('snake.png')
snakeX = 300
snakeY = 300
snakeX_change = 0
snakeY_change = 0
# Apple
appleImg = pygame.image.load('apple.png')
appleX = random.randint(32, 768)
appleY = random.randint(32, 568)
def snake(x, y):
screen.blit(snakeImg, (x, y))
def apple(x, y):
screen.blit(appleImg, (x, y))
# Collision
def isCollision(appleX, appleY, snaketX, snakeY):
distance = distance = math.sqrt(math.pow(appleX - snakeX, 2) + (math.pow(appleY - snakeY, 2)))
if distance < 27:
return True
else:
return False
# Game Loop
score = 0
running = True
while running:
# Background Image
screen.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Snake Movment
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
snakeX_change = -0.1
snakeY_change = 0
if event.key == pygame.K_UP:
snakeY_change = -0.1
snakeX_change = 0
if event.key == pygame.K_RIGHT:
snakeX_change = 0.1
snakeY_change = 0
if event.key == pygame.K_DOWN:
snakeY_change = 0.1
snakeX_change = 0
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
snakeX_change = -0.1
if event.key == pygame.K_RIGHT:
snakeX_change = 0.1
if event.key == pygame.K_DOWN:
snakeY_change = 0.1
if event.key == pygame.K_UP:
snakeY_change = -0.1
snakeX += snakeX_change
snakeY += snakeY_change
if snakeX <= 0:
snakeX = 0
elif snakeX >= 770:
snakeX = 770
if snakeY <= 0:
snakeY = 0
elif snakeY >= 570:
snakeY = 570
# Collision
collision = isCollision(appleX, appleY, snakeX, snakeY)
if collision:
score += 1
print(score)
appleX = random.randint(32, 768)
appleY = random.randint(32, 568)
snake(snakeX, snakeY)
apple(appleX, appleY)
pygame.display.flip()
When snake's head collide with the apple, add 1 element inside snake's body, you can interprete snake's body as a list of elements, containing tuples perhaps.
I've been trying to create a game screen but I can't seem to add a boundary around the houses on the screen so that the player doesn't walk over them. Below is my code
import pygame
import sys
from pygame import mixer
pygame.init()
playerImg = pygame.image.load('player.png')
WalkFront = [pygame.image.load('B1.png'), pygame.image.load('B2.png'),pygame.image.load('B3.png'),
pygame.image.load('B4.png')]
WalkBack = [pygame.image.load('F1.png'), pygame.image.load('F2.png'), pygame.image.load('F3.png'),
pygame.image.load('F4.png')]
WalkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'),
pygame.image.load('R4.png')]
WalkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('L3.png'),
pygame.image.load('L4.png')]
walkcount = 0
clock = pygame.time.Clock()
scr = pygame.display.set_mode((800, 600))
pygame.display.set_caption('Pokemon: Red')
logo = pygame.image.load('logo.png')
pygame.display.set_icon(logo)
background = pygame.image.load('BG.png')
pallet = pygame.image.load('pallet town.png')
mixer.music.load('Start menu.mp3')
mixer.music.play(100, 0, 0)
playerX = 200
playerY = 200
up = False
down = False
left = False
right = False
def redrawgamewindow():
global walkcount
scr.fill((0, 0, 0))
scr.blit(pallet, (60, 0))
if walkcount + 1 >= 29:
walkcount = 0
if up:
scr.blit(WalkFront[walkcount // 7], (playerX, playerY))
walkcount += 1
elif down:
scr.blit(WalkBack[walkcount // 7], (playerX, playerY))
walkcount += 1
elif left:
scr.blit(WalkLeft[walkcount // 7], (playerX, playerY))
walkcount += 1
elif right:
scr.blit(WalkRight[walkcount // 7], (playerX, playerY))
walkcount += 1
else:
player(playerX, playerY)
pygame.display.update()
def player(x, y):
scr.blit(playerImg, (x, y))
def start_menu():
while True:
scr.fill((255, 255, 255))
scr.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
game()
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
pygame.display.update()
def game():
global playerX
global playerY
clock.tick(12)
mixer.music.pause()
mixer.music.load('pallet_music.mp3')
mixer.music.play(100)
playerX_change = 0
playerY_change = 0
running = True
while running:
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_UP:
global up
global down
global left
global right
up = True
down = False
playerY_change = -0.8
elif event.key == pygame.K_DOWN:
up = False
down = True
playerY_change = 0.8
else:
up = False
down = False
walkcount = 0
if event.key == pygame.K_LEFT:
playerX_change = -1
left = True
right = False
elif event.key == pygame.K_RIGHT:
playerX_change = 1
right = True
left = False
else:
left = False
right = False
walkcount = 0
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
playerY_change = 0
up = False
down = False
left = False
right = False
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
up = False
down = False
left = False
right = False
playerX += playerX_change
playerY += playerY_change
if playerX <= 90:
playerX = 90
elif playerX >= 670:
playerX = 670
if playerY <= 40:
playerY = 40
elif playerY >= 540:
playerY = 540
redrawgamewindow()
start_menu()
the background image has an area on it with a house in the top left. See the background image below so you can get a better idea. what I want is for the player to not be able to walk on the house so he gets blocked at the edge.
I recommend to define a rectangular area for the house. Use pygame.Rect. You have to find the values for hx, hy, hw and hh:
house_rect = pygame.Rect(hx, hy, hw, hh)
Create a rectangle for the player after the position of the player is changed. The size of the rectangle can be get from the pygame.Surface object which represents the player by get_rect(). The position has to be set by an keyword argument (topleft = (playerX, playerY)).
Use pygame.Rect.colliderect to evaluate if the player collides with the house and restrict the position of the player to the area outside the house:
playerX += playerX_change
player_rect = playerImg.get_rect(topleft = (playerX, playerY))
if player_rect.colliderect(house_rect):
if playerX_change > 0:
player_rect.right = house_rect.left
elif playerX_change < 0:
player_rect.left = house_rect.right
playerX = player_rect.x
playerY += playerY_change
player_rect = playerImg.get_rect(topleft = (playerX, playerY))
if player_rect.colliderect(house_rect):
if playerY_change < 0:
player_rect.top = house_rect.bottom
elif playerY_change > 0:
player_rect.bottom = house_rect.top
playerY = player_rect.y
I guess you have to patiently make the boundaries with x and y like this:
if x > boundaryX and y > boundaryY:
xOfThePlayer -= moving
It is an example you have to change this according to your needs.
#enable pygame mode
import pygame
pygame.init()
#create screen
screen = pygame.display.set_mode((1000,600))
#Title + Logo
pygame.display.set_caption("Space Invader")
icon = pygame.image.load("chicken.png")
pygame.display.set_icon(icon)
#Player icon
player_icon = pygame.image.load("spaceship.png")
playerX = 400
playerY = 500
player_changeX = 0
player_changeY = 0
def player(x, y):
screen.blit(player_icon, (x, y))
surface.blit(image,((1920/2)-(image.get_width()/2),(1080/2)-
(image.get_height()/2)))
#game loop
running = True
while running:
# backround colour RGB
screen.fill((0, 0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#If key pressed check wether its right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player_changeX = -1
if event.key == pygame.K_RIGHT:
player_changeX = 1
if event.key == pygame.K_UP:
player_changeY = -1
if event.key == pygame.K_DOWN:
player_changeY = 1
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key ==pygame.K_RIGHT:
player_changeX = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
player_changeY = 0
# If player reaches boarder
if playerX >= 936:
player_changeX = -1
if playerX <= 0:
player_changeX = 1
if playerY <= 0:
player_changeY = 1
if playerY >= 550:
player_changeY = -1
#Player change in coordinates
playerX += player_changeX
playerY += player_changeY
player(playerX, playerY)
pygame.display.update()
I am creating a simple game as i just got into programing and I was wondering if you could make the game screen appear in the centre of your own screen as when I run it it keeps appearing on the bottom of my screen and I then have to manually move it into the centre. If you can please tell me how. Hope my question was formated good enough. Thank you for any help.
It depends; if it's a image you can do:
surface.blit(image,((screenwidth/2)-(image.get_width()/2),(screenheight/2)-(image.get_height()/2)))
Please tell me it it's different
import pygame
import random
pygame.init()
black = (0,0,0)
red = (255,0,0)
display_width = 800
display_height = 600
FPS = 20
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("The Space Jumpers")
img = pygame.image.load('starship2.png')
spritesize = 50
boundlimit = 200
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 25)
def gameLoop():
gameExit = False
gameOver = False
lead_x = display_width / 2
lead_y = display_height / 2
xchange = 0
ychange = 0
randBlockX = random.randrange(0,boundlimit+1)
randBlockY = random.randrange(0,575)
while not gameExit:
gameDisplay.blit(img, [lead_x,lead_y])
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
xchange = -spritesize / 2
ychange = 0
if event.key == pygame.K_RIGHT:
xchange = spritesize / 2
ychange = 0
if event.key == pygame.K_UP:
ychange = -spritesize / 2
xchange = 0
if event.key == pygame.K_DOWN:
ychange = spritesize / 2
xchange = 0
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
xchange = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
ychange = 0
lead_x += xchange
lead_y += ychange
gameDisplay.fill(black)
pygame.draw.rect(gameDisplay,red, [randBlockX, randBlockY, 600, 25])
if (lead_x+spritesize < randBlockX and randBlockY<lead_y<randBlockY+25) :
randBlockX = random.randrange(0,boundlimit+1)
randBlockY = random.randrange(0,575)
elif (lead_x+spritesize < randBlockX and randBlockY<lead_y<randBlockY+25 ):
randBlockX = random.randrange(0,boundlimit+1)
randBlockY = random.randrange(0,575)
elif (lead_x > randBlockX+600 and randBlockY<lead_y<randBlockY+25):
randBlockX = random.randrange(0,boundlimit+1)
randBlockY = random.randrange(0,575)
elif (lead_x > randBlockX+600 and randBlockY<lead_y<randBlockY+25):
randBlockX = random.randrange(0,boundlimit+1)
randBlockY = random.randrange(0,575)
clock.tick(FPS)
pygame.quit()
quit()
gameLoop()
This is my current code and in this code when the object(sprite) hits the boundary, it keeps on moving but what I want to do is, I want to stop the movement of the object when it hits the boundary, for example when the object hits the left boundary it shouldnt move left anymore. You kind of get the idea, its a simple game
Instead of using two variables (lead_x, lead_y) to store the position of the object, use a Rect. It's as simple as
gameDisplay = pygame.display.set_mode((display_width,display_height))
gameDisplay_rect = gameDisplay.get_rect()
img = pygame.image.load('starship2.png')
img_rect = img.get_rect(center=gameDisplay_rect.center)
To draw you object, simply do:
gameDisplay.blit(img, img_rect)
Now, to move your object, instead of
lead_x += xchange
lead_y += ychange
you can do
img_rect.move_ip(lead_x, lead_y)
img_rect.clamp_ip(gameDisplay_rect)
clamp_ip will then prevent your object from leaving the screen.
I think this will work:
try changing your if statement(if pygame.key == pygame.K_LEFT:) to(if pygame.key == pygame.K_LEFT and x > 0:)
i have been struggling with the same thing for a school project and have gotten it so that it stops the sprite if you touch the border, but if you spam that button you can get through. I currently have an if statement saying(If x < 0: x_change = 0), but i have not tried the one i suggested. i hope it works.
sloth's method is for sure better in many ways, but if you still want to keep your old lead_x, lead_y structure you could just add a separate statements outside of the event loop:
if lead_x <= 0:
lead_x += 10 # just use any small distance to push you back to place every frame
elif lead_x >= display_width:
lead_x -= 10
and so on for every direction.
I'm developing a very basic engine, basing myself on tutorials from Pygame, and I'm having a little problem with "smoothness". How do I make my player walk "smoother"?
My event handler is pretty basic, pretty standard, nothing new, and I even figured out how to make a "boost" (run) for test. But the thing is, at the pygame.KEYUP, those lots of zeros destroy the "smoothness" of my little player, and I don't want that, but I don't want it to walk ad infinitum.
import pygame
import gfx
# Main Class
class Setup:
background = gfx.Images.background
player = gfx.Images.player
pygame.init()
# Configuration Variables:
black = (0,0,0)
white = (255,255,255)
green = (0,255,0)
red = (255,0,0)
title = "Ericson's Game"
# Setup:
size = [700,700]
screen = pygame.display.set_mode(size)
pygame.display.set_caption(title)
done = False
clock = pygame.time.Clock()
# Logic Variables
x_speed = 0
y_speed = 0
x_speed_boost = 0
y_speed_boost = 0
x_coord = 350
y_coord = 350
screen.fill(white)
# Main Loop:
while done == False:
screen.blit(background,[0,0])
screen.blit(player,[x_coord,y_coord])
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
done = True
if event.key == pygame.K_a:
x_speed = -6
x_speed_boost = 1
if event.key == pygame.K_d:
x_speed = 6
x_speed_boost = 2
if event.key == pygame.K_w:
y_speed = -6
y_speed_boost = 1
if event.key == pygame.K_s:
y_speed = 6
y_speed_boost = 2
if event.key == pygame.K_LSHIFT:
if x_speed_boost == 1:
x_speed = -10
if x_speed_boost == 2:
x_speed = 10
if y_speed_boost == 1:
y_speed = -10
if y_speed_boost == 2:
y_speed = 10
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
x_speed = 0
x_speed_boost = 0
if event.key == pygame.K_d:
x_speed = 0
x_speed_boost = 0
if event.key == pygame.K_w:
y_speed = 0
y_speed_boost = 0
if event.key == pygame.K_s:
y_speed = 0
y_speed_boost = 0
x_coord = x_coord + x_speed
y_coord = y_coord + y_speed
pygame.display.flip()
pygame.display.update()
clock.tick(20)
pygame.quit()
Code will be simpler/clearer using keystate polling for your use. If other parts of the game use 'on press' logic, you can use event handling. So your movement would be:
If you are calling pygame.display.flip() then you don't use pygame.display.update(). Infact it will probably slow it down to use both.
I used your x_coord variable. But it would simplify things to use a tuple or vector for player location. You can use a float, for smoother precision for movement. Then it blits as an int to screen.
while not done:
for event in pygame.event.get():
# any other key event input
if event.type == QUIT:
done = True
elif event.type == KEYDOWN:
if event.key == K_ESC:
done = True
vel_x = 0
vel_y = 0
speed = 1
if pygame.key.get_mods() & KMOD_SHIFT
speed = 2
# get key current state
keys = pygame.key.get_pressed()
if keys[K_A]:
vel_x = -1
if keys[K_D]:
vel_x = 1
if keys[K_W]:
vel_y = -1
if keys[K_S]:
vel_y = 1
x_coord += vel_x * speed
y_coord += vel_y * speed
You are ticking the clock at a rate of 20 frames per second. This is probably causing the choppiness. Change it to something bigger like 70:
clock.tick(70)