Does anybody see the problem in this code? Trying to make the ball/bullet come out of the left paddle and disappear once it hits the right paddle but when I try running the code I don't see the ball in general. I think its hidden behind the left paddle but its not moving either when I'm space. I am trying to make a game where the left player would should bullets and the right player would try to dodge them. Now I'm stuck at the bullet. Please help. Thanks!
import pygame
pygame.init()
screen_width = 1280
screen_height = 720
window = pygame.display.set_mode((screen_width, screen_height),0,0)
pygame.display.set_caption("PongGame")
clock = pygame.time.Clock()
#background
background = pygame.image.load("C:/Users/teamb/Desktop/PythonWorkspace/myGame/background.png")
#paddle image
paddle = pygame.image.load("C:/Users/teamb/Desktop/PythonWorkspace/myGame/paddle.png")
paddle_size = paddle.get_rect().size
#left paddle
left_paddle_width = paddle_size[0]
left_paddle_height = paddle_size[1]
left_paddle_xpos = 10
left_paddle_ypos = (screen_height/2 - left_paddle_height/2)
to_x = 0
to_y = 0
character_speed = 10
#right paddle
right_paddle_width = paddle_size[0]
right_paddle_height = paddle_size[1]
right_paddle_xpos = screen_width - right_paddle_width - 10
right_paddle_ypos = (screen_height/2 - left_paddle_height/2)
to_y_2 = 0
# ball
bullet = pygame.image.load("C:/Users/teamb/Desktop/PythonWorkspace/myGame/ball.png")
bullet_size = bullet.get_rect().size
bullet_width = bullet_size[0]
#make the bullet be able to shoot multiple at the same time
bullets = []
#bulllet speed
bullet_speed = 15
running = True
while running:
dt = clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#left paddle
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
to_y -= character_speed
elif event.key == pygame.K_s:
to_y += character_speed
elif event.key == pygame.K_SPACE:
bullet_ypos = left_paddle_ypos
bullet_xpos = left_paddle_xpos
bullets.append([bullet_xpos, bullet_ypos])
if event.type == pygame.KEYUP:
if event.key == pygame.K_w or event.key == pygame.K_s:
to_y = 0
#right paddle
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
to_y_2 -= character_speed
elif event.key == pygame.K_DOWN:
to_y_2 += character_speed
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
to_y_2 = 0
left_paddle_ypos += to_y
right_paddle_ypos += to_y_2
bullets = [ [w[0] - bullet_speed, w[1]] for w in bullets] #shoot the bullet
bullets = [ [w[0], w[1]] for w in bullets if w[0] == right_paddle_xpos and w[1] == right_paddle_ypos]
#barrier for the paddles to not go outside the screen.
if left_paddle_ypos < 0:
left_paddle_ypos = 0
if left_paddle_ypos > screen_height - left_paddle_height:
left_paddle_ypos = screen_height - left_paddle_height
window.blit(background,(0,0))
window.blit(paddle, (left_paddle_xpos,left_paddle_ypos))
window.blit(paddle, (right_paddle_xpos, right_paddle_ypos))
for bullet_xpos, bullet_ypos in bullets:
window.blit(bullet, (bullet_xpos, bullet_ypos))
pygame.display.update()
pygame.quit()
Two changes required:
Remove this line. It clears the bullet list before the bullets are shown.
#bullets = [ [w[0], w[1]] for w in bullets if w[0] == right_paddle_xpos and w[1] == right_paddle_ypos]
Change this line (- to +). It sends the bullets in the wrong direction.
bullets = [ [w[0] + bullet_speed, w[1]] for w in bullets] #shoot the bullet
Trying to make the ball/bullet... disappear once it hits the right paddle
So, I assume this is the line intended to have that effect:
bullets = [ [w[0], w[1]] for w in bullets if w[0] == right_paddle_xpos and w[1] == right_paddle_ypos]
Read it more carefully: for each of the bullet positions, we will check if it is positioned exactly where the right paddle is (i.e., top-left corners coincide!), and if so, keep that one unmodified; everything else is discarded.
You need to use proper collision logic, and you need to keep bullets that have not collided with the absorber.
Incidentally:
elif event.key == pygame.K_SPACE:
bullet_ypos = left_paddle_ypos
bullet_xpos = left_paddle_xpos
bullets.append([bullet_xpos, bullet_ypos])
How exactly did you want new bullets to be positioned, relative to the left paddle? How does this code say they will be positioned?
bullets = [ [w[0] - bullet_speed, w[1]] for w in bullets] #shoot the bullet
Which way do you want the bullet to move, if its speed is positive? Which way will it actually move, according to this logic?
Related
The left paddle works fine it moves up and down no problem. But the right is okay when I don't move but when I do it moves to the directions I coded to but doesn't erase the previously drawn location which in the end just draws a straight line. Trying to make my first ever game with no tutorial and I'm kind of stuck
Here's the code
import pygame
pygame.init()
screen_width = 1280
screen_height = 720
window = pygame.display.set_mode((screen_width, screen_height),0,0)
pygame.display.set_caption("PongGame")
clock = pygame.time.Clock()
#background
background = pygame.image.load("C:/Users/teamb/Desktop/PythonWorkspace/myGame/background.png")
#paddle image
paddle = pygame.image.load("C:/Users/teamb/Desktop/PythonWorkspace/myGame/paddle.png")
paddle_size = paddle.get_rect().size
#left paddle
left_paddle_width = paddle_size[0]
left_paddle_height = paddle_size[1]
left_paddle_xpos = 10
left_paddle_ypos = (screen_height/2 - left_paddle_height/2)
to_x = 0
to_y = 0
character_speed = 10
#right paddle
right_paddle_width = paddle_size[0]
right_paddle_height = paddle_size[1]
right_paddle_xpos = screen_width - right_paddle_width - 10
right_paddle_ypos = (screen_height/2 - left_paddle_height/2)
to_y_2 = 0
# ball
ball = pygame.image.load("C:/Users/teamb/Desktop/PythonWorkspace/myGame/ball.png")
running = True
while running:
dt = clock.tick(60)
print("fps : " + str(clock.get_fps()))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#left paddle
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
to_y -= character_speed
elif event.key == pygame.K_s:
to_y += character_speed
if event.type == pygame.KEYUP:
if event.key == pygame.K_w or event.key == pygame.K_s:
to_y = 0
#right paddle
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
to_y_2 -= character_speed
elif event.key == pygame.K_DOWN:
to_y_2 += character_speed
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
to_y_2 = 0
left_paddle_ypos += to_y
right_paddle_ypos += to_y_2
if left_paddle_ypos < 0:
left_paddle_ypos = 0
if left_paddle_ypos > screen_height - left_paddle_height:
left_paddle_ypos = screen_height - left_paddle_height
window.blit(background,(0,0))
window.blit(paddle, (left_paddle_xpos,left_paddle_ypos))
window.blit(paddle, (right_paddle_xpos, right_paddle_ypos))
window.blit(ball, (640, 360))
pygame.display.update()
pygame.quit()
Moste likely the background Surface (background) has a smaller width than the display Surface (window).
Clear the display before drawing the scene:
while running:
# [...]
window.fill(0) # <--- clear display
window.blit(background,(0,0))
window.blit(paddle, (left_paddle_xpos,left_paddle_ypos))
window.blit(paddle, (right_paddle_xpos, right_paddle_ypos))
window.blit(ball, (640, 360))
pygame.display.update()
Or scale the background image by pygame.transform.smoothscale:
background = pygame.image.load("C:/Users/teamb/Desktop/PythonWorkspace/myGame/background.png")
background = pygame.transform.smoothscale(background, window.get_size())
This line is redrawing your background on every movement:
window.blit(background,(0,0))
However, I suppose your background image is actually smaller than your play field, so you are not redrawing the background on that side. You can either make your background image larger, or draw it again using an offset, or even draw it stretched. The idea is cover the entire play field when you are drawing the background.
It is worth pointing out this is not necessarily the most optimized way to do that. Ideally, you would redraw only the parts that had changed, but this is way more complex. Drawing the entire background is an easy fix.
For a school project I am building a recreation of Among Us in python with Pygame. I have already set up all the server and client side code and that's all working fine. I'm now in the process of making the camera follow the player. Only I can't get it to work.
My idea was: when a player moves, everything in his surroundings has to move in the opposite direction. But when you have a multiplayer game this doesn't work. Because then the other player moves as well which breaks the system.
If anyone has any idea how to make such a code, please let me know.
Thank you in advance
You don't have to move the background and object rects around the player, you can just move the player around and have a scroll offset value that keeps track of how much the blitted objects have to be offset. You don't apply the scroll value to the rect position because the rect position isn't relative to the window like the blit objects are. Here is an example of how you could achieve this.
import pygame, sys
clock = pygame.time.Clock()
from pygame.locals import *
pygame.init()
pygame.display.set_caption("Scrolling example")
WINDOW_SIZE = (600, 400)
screen = pygame.display.set_mode(WINDOW_SIZE, 0, 32)
scroll = [0, 0]
player = pygame.Rect(100, 100, 10, 10)
up = False
down = False
left = False
right = False
blocks = [pygame.Rect(250,250,50,50)]
while True:
screen.fill((0, 0, 0))
scroll[0] += (player.x - scroll[0] - (WINDOW_SIZE[0]/2)) // 20
scroll[1] += (player.y - scroll[1] - (WINDOW_SIZE[1]/2)) // 20
player_movement = [0, 0]
if right == True:
player_movement[0] += 2
if left == True:
player_movement[0] -= 2
if up == True:
player_movement[1] -= 2
if down == True:
player_movement[1] += 2
player.x += player_movement[0]
player.y += player_movement[1]
player_scroll_rect = player.copy()
player_scroll_rect.x -= scroll[0]
player_scroll_rect.y -= scroll[1]
pygame.draw.rect(screen, (255,255,255), player_scroll_rect)
for block in blocks:
scroll_block = block.copy()
scroll_block.x = scroll_block.x - scroll[0]
scroll_block.y = scroll_block.y - scroll[1]
pygame.draw.rect(screen, (0,0,255), scroll_block)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_RIGHT:
right = True
if event.key == K_LEFT:
left = True
if event.key == K_UP:
up = True
if event.key == K_DOWN:
down = True
if event.type == KEYUP:
if event.key == K_RIGHT:
right = False
if event.key == K_LEFT:
left = False
if event.key == K_UP:
up = False
if event.key == K_DOWN:
down = False
pygame.display.update()
clock.tick(60)
If you want a solution for using images, ask me.
Also, you can find more about scrolling here: https://www.youtube.com/watch?v=5q7tmIlXROg
This question already has answers here:
Not letting the character move out of the window
(2 answers)
Closed 2 years ago.
I need a rectangular border around an image so my character stops walking through it. It would be nice if my character stopped at certain coordinates instead of walking over the image.
I've tried to create a border with my 'x' and 'y' coordinates, but the border seems to stretch across the screen.
import pygame
from pygame.locals import *
pygame.init()
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 700
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT,))
pygame.display.set_caption("Zombie Hunters")
background = pygame.image.load("background.jpg").convert()
background = pygame.transform.scale(background, (SCREEN_WIDTH,SCREEN_HEIGHT))
player = pygame.image.load("character no gun.png").convert_alpha()
player = pygame.transform.scale(player, (270, 270))
# these are the coordinates to move the player
x, y = 0, 0
MOVE_RIGHT = 1
MOVE_LEFT = 2
MOVE_UP = 3
MOVE_DOWN = 4
direction = 0
speed = 1
#House barrier
barrier_xlocation = 345
barrier_ylocation = 80
barrier_width = 190
barrier_height = 260
while True:
for event in pygame.event.get():
if event.type == QUIT:
exit()
if event.type == KEYDOWN:
if event.key == ord('q'):
pygame.quit()
exit()
if event.key == K_LEFT:
direction = MOVE_LEFT
if event.key == K_RIGHT:
direction = MOVE_RIGHT
if event.key == K_UP:
direction = MOVE_UP
if event.key == K_DOWN:
direction = MOVE_DOWN
elif event.type == KEYUP:
if event.key == K_LEFT:
direction = 0
if event.key == K_RIGHT:
direction = 0
if event.key == K_UP:
direction = 0
if event.key == K_DOWN:
direction = 0
if(direction == MOVE_LEFT):
x-= speed
if(direction == MOVE_RIGHT):
x+= speed
if(direction == MOVE_UP):
y-= speed
if(direction == MOVE_DOWN):
y += speed
#Background
screen.blit(background, (0, 0))
#House border
pygame.draw.rect(screen, (255,0,0), (barrier_xlocation,barrier_ylocation,barrier_width,barrier_height), 2)
#Player hitbox
pygame.draw.rect(screen, (255,0,0), (x + 117,y + 105, 50,50),2)
screen.blit(player, (x,y))
pygame.display.update()
I don't get any error messages, but I need to create a border around the house.
Use pygame.Rect objects and .colliderect() to check for the collision of two rectangles.
Store the current position of the player. After the player position has change, check for a collision with the barrier. When the player and the barrier are colliding, then reset the position of the player.
The size of as [pygame.Surface] object can be get by .get_size():
# store current position
px, py = x, y
# change position
if(direction == MOVE_LEFT):
x-= speed
if(direction == MOVE_RIGHT):
x+= speed
if(direction == MOVE_UP):
y-= speed
if(direction == MOVE_DOWN):
y += speed
# set player and barrier rectangle
playerRect = pygame.Rect(x, y, *player.get_size())
barrierRect = pygame.Rect(
barrier_xlocation, barrier_ylocation, barrier_width, barrier_height)
# check for collision
if playerRect.colliderect(barrierRect):
# reset position
x, y = px, py
Before this I used the code to say 'every button press it moves' but now I have changed it to 'when you press the button it moves in one direction until further instructions', but now the colliderect doesn't work. It worked before, and I'm still new to pygame. I have found a few similar issues but I think I've done what the people asking the questions have done. Any help at all is accepted.
import pygame, sys, random
from pygame.locals import *
from time import sleep
pygame.init()
def render():
windowSurface.fill(black)
player = pygame.Rect(225 + xmod,450 - ymod,30,30)
pygame.draw.rect(windowSurface,white,player)
pygame.draw.rect(windowSurface,white,wall_1)
pygame.draw.rect(windowSurface,white,wall_2)
pygame.display.update()
black = (0,0,0)
white = (255,255,255)
windowSurface = pygame.display.set_mode((500, 500),0,32)
windowSurface.fill(black)
xmod = 0
ymod = 0
direction = 'none'
player = pygame.Rect(225 + xmod,450 - ymod,30,30)
wall_1 = pygame.Rect(0,225,250,50)
wall_2 = pygame.Rect(300,250,200,50)
render()
while True:
render()
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_LEFT:
direction = 'left'
if event.key == K_RIGHT:
direction = 'right'
if event.key == K_UP:
direction = 'up'
if event.key == K_DOWN:
direction = 'down'
if event.type == QUIT:
pygame.quit()
sys.exit()
if player.colliderect(wall_1) or player.colliderect(wall_2):
xmod = 0
ymod = 0
player = pygame.Rect(225 + xmod,450 - ymod,30,30)
render()
print('again')
if direction == 'left':
xmod -= 1
sleep(0.004)
if direction == 'right':
xmod += 1
sleep(0.004)
if direction == 'up':
ymod += 1
sleep(0.004)
if direction == 'down':
ymod -= 1
sleep(0.004)
You never update the global player variable, so it stays at its original coordinates. In the render function you create a new rect and assign it to a local player variable, but it is not the same as the global player which you use for the collision detection.
I suggest adding variables for the velocity speed_x, speed_y and adding them to the player.x and .y attributes every frame to move the rect directly.
The local player rect in the render function can be removed.
import sys
import pygame
from pygame.locals import *
pygame.init()
def render():
windowSurface.fill(black)
pygame.draw.rect(windowSurface, white, wall_1)
pygame.draw.rect(windowSurface, white, wall_2)
pygame.draw.rect(windowSurface, white, player)
pygame.display.update()
black = (0,0,0)
white = (255,255,255)
windowSurface = pygame.display.set_mode((500, 500),0,32)
clock = pygame.time.Clock() # A clock to limit the frame rate.
player = pygame.Rect(225, 450, 30, 30)
wall_1 = pygame.Rect(0,225,250,50)
wall_2 = pygame.Rect(300,250,200,50)
speed_x = 0
speed_y = 0
while True:
# Handle events.
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_LEFT:
speed_x = -5
speed_y = 0
elif event.key == K_RIGHT:
speed_x = 5
speed_y = 0
elif event.key == K_UP:
speed_y = -5
speed_x = 0
elif event.key == K_DOWN:
speed_y = 5
speed_x = 0
# Add the speed to the x and y attributes to move the rect.
player.x += speed_x
player.y += speed_y
# Game logic.
if player.colliderect(wall_1) or player.colliderect(wall_2):
player = pygame.Rect(225, 450, 30, 30)
print('again')
# Render everything.
render()
clock.tick(60) # Limit the frame rate to 60 FPS.
I would like to know how to create a border in Pygame to stop the user controlled object from exiting the screen. Right now, I only have it so python prints some text when the user controlled object has come near one of the 4 sides.
Here is my code so far.
import pygame
from pygame.locals import *
pygame.init()
#Display Stuff
screenx = 1000
screeny = 900
screen = pygame.display.set_mode((screenx,screeny))
pygame.display.set_caption('Block Runner')
clock = pygame.time.Clock()
image = pygame.image.load('square.png')
#Color Stuff
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
white = (255,255,255)
black = (0,0,0)
#Variables
x_blocky = 50
y_blocky = 750
blocky_y_move = 0
blocky_x_move = 0
#Animations
def Blocky(x_blocky, y_blocky, image):
screen.blit(image,(x_blocky,y_blocky))
#Game Loop
game_over = False
while not game_over:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
blocky_y_move = -3
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
blocky_y_move = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN:
blocky_y_move = 3
if event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN:
blocky_y_move = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
blocky_x_move = 3
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
blocky_x_move = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
blocky_x_move = -3
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
blocky_x_move = 0
if x_blocky > 870 or x_blocky < 0:
print(' X Border')
if y_blocky > 750 or y_blocky < 2:
print(' Y Border')
y_blocky += blocky_y_move
x_blocky += blocky_x_move
screen.fill(white)
Blocky(x_blocky, y_blocky, image)
pygame.display.update()
clock.tick(60)
Don't use integers to store your position. Use a Rect.
So instead of
x_blocky = 50
y_blocky = 750
use
blocky_pos = pygame.rect.Rect(50, 750)
Now you can simply use
blocky_pos.move_ip(blocky_x_move, blocky_y_move)
to move your object.
After moving, you can simply call clamp/clamp_ip to ensure the blocky_pos Rect is always inside the screen.
blocky_pos.clamp_ip(screen.get_rect())
Also, you don't need to define basic colors yourself, you could simply use pygame.color.Color('Red') for example.
I also suggest you use pygame.key.get_pressed() to get all pressed keys to see how to move your object instead of creating 1000 lines of event handling code.
Well, simply don't increase your move variable any further, if you detect that the user object is near or at the border. Or reverse the move direction, depending on your general intent.
if x_blocky > 870 or x_blocky < 0:
print(' X Border')
blocky_x_move = 0
if y_blocky > 750 or y_blocky < 2:
print(' Y Border')
blocky_y_move = 0
Also, you have some redundant code with your keyboard movement. Instead of writing
if event.type == KEYDOWN:
over and over again, group the KEYUP if statements and KEYDOWN if statements.
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
blocky_y_move = -3
elif event.key == pygame.K_DOWN:
blocky_y_move = +3
etc, and:
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
blocky_y_move = 0
elif event.type == pygame.K_DOWN:
blocky_y_move = 0
etc
You can set the boundaries using the min and max functions.
Here is the concept:
We have a pygame object that moves in all four directions; lets say the user holds down the LEFT arrow key, so that the object reaches the top of the screen. The y-coordinate of the top of the screen will always be 0, so we want the object to come to a stop at y-coordinate 0.
This may seem as simple as:
if char.rect.y > 0:
char.rect.y -= char.speed
But this will result in a bug ig char.speed is greater than 1. Like when the object is at y-coordinate 5,
and its speed is 10; the condition still allows for one more step for the object, resulting in the object
coming 5 pixels out of the pygame window. What we want to do is more like:
if char.rect.y > 0:
char.rect.y -= char.speed
if char.rect.y < 0:
char.rect.y = 0
to push the object back into the boundaries. The above block of code can be simplified with the max function:
self.rect.y = max([self.rect.y - self.speed, 0])
For the object moving down:
if char.rect.y < HEIGHT - char.height:
char.rect.y += char.speed
if char.rect.y > HEIGHT - char.height:
char.rect.y = HEIGHT - char.height
or, the more efficient and clean method:
self.rect.y = min([self.rect.y + self.speed, HEIGHT - self.height])
For going left and right, simply replace the ys and height (and HEIGHT) from two lines above with xs and widths (and WIDTH).
All together:
import pygame
pygame.init()
WIDTH = 600
HEIGHT = 600
wn = pygame.display.set_mode((WIDTH, HEIGHT))
class Player:
def __init__(self):
self.speed = 1
self.width = 20
self.height = 20
self.color = (255, 255, 0)
self.rect = pygame.Rect((WIDTH - self.width) / 2, (HEIGHT - self.height) / 2, 20, 20)
def up(self):
self.rect.y = max([self.rect.y - self.speed, 0])
def down(self):
self.rect.y = min([self.rect.y + self.speed, HEIGHT - self.height])
def left(self):
self.rect.x = max([self.rect.x - self.speed, 0])
def right(self):
self.rect.x = min([self.rect.x + self.speed, WIDTH - self.width])
def draw(self):
pygame.draw.rect(wn, self.color, self.rect)
char = Player()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
char.up()
if keys[pygame.K_DOWN]:
char.down()
if keys[pygame.K_LEFT]:
char.left()
if keys[pygame.K_RIGHT]:
char.right()
wn.fill((0, 0, 0))
char.draw()
pygame.display.update()
Good luck!