Im making an air hokey game using pygame , but i have no idea how to make the ball bounce in the right direction when the player hits it.
i tried making the ball move in the x direction if the player hits it and if the player is under the ball or aboce it i made it move in the y and x direction but that didnt work
import pygame
import math
pygame.init()
screen = pygame.display.set_mode((800, 400))
background = pygame.image.load("ER.png")
player1 = pygame.image.load("eee.png")
px = 20
py = 148
change = 0
cy = 0
player2 = pygame.image.load("a.png")
px2 = 700
py2 = 148
cx2 = 0
cy2 = 0
ball = pygame.image.load("qw.png")
bx = 351
by = 148
chx = 0
chy = 0
def balls(x,y):
screen.blit(ball,(x,y))
def p1(x, y):
screen.blit(player1,(x , y))
def p2(x, y):
screen.blit(player2,(x , y))
def colid(ex,ey, bx, by):
d = math.sqrt((math.pow(ex - bx, 2)) + (math.pow(by - ey,2)))
if d < 40:
return True
else:
return False
run = True
while run:
screen.blit(background,(0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_d:
change += 1
if event.key == pygame.K_a:
change += -1
if event.key == pygame.K_s:
cy += 1
if event.key == pygame.K_w:
cy += -1
if event.key == pygame.K_LEFT:
cx2 -= 1
print(px2)
print(py2)
if event.key == pygame.K_RIGHT:
cx2 += 1
print(px2)
print(py2)
if event.key == pygame.K_DOWN:
cy2 += 1
print(px2)
print(py2)
if event.key == pygame.K_UP:
cy2 += -1
print(px2)
print(py2)
if event.type == pygame.KEYUP:
if event.key == pygame.K_d:
change -= 1
if event.key == pygame.K_a:
change += 1
if event.key == pygame.K_s:
cy -= 1
if event.key == pygame.K_w:
cy += 1
if event.key == pygame.K_LEFT:
cx2 += 1
if event.key == pygame.K_RIGHT:
cx2 -= 1
if event.key == pygame.K_DOWN:
cy2 -= 1
if event.key == pygame.K_UP:
cy2 += 1
colide = colid(bx, by, px, py)
if colide:
print("colided")
bx += ch
py2 += cy2
px2 += cx2
py += cy
px += change
balls(bx,by)
p1(px,py)
p2(px2, py2)
if px <= -8:
px = -8
if px >= 326:
px = 326
if py <= -8:
py = -8
if py >= 312:
py = 312
if px2 >= 712:
px2 = 712
if py2 <= -8:
py2 = -8
if py2 >= 312:
py2 = 312
if px2 <= 378:
px2 = 378
pygame.display.update()
You update the ball position with
bx += ch
but the colide result does not influence ch.
Therefore the ball behavior does not change when Player1 hits it.
Have your if statement do something like this
after printing that the ball collided:
ch = -ch
This assumes values like 1 or -1.
The code you posted does not set ch.
If ch is zero the ball will remain stationary.
You might also make your bounds check code flip the sign,
so the ball bounces off the left and right walls
independent of what Player1 is doing.
Or try one of these special effects within the bounds check:
ch *= -0.95 # friction slows the ball down
ch *= -1.05 # hot walls continually impart more energy to the ball
You have an inconveniently large number of variables.
You could get away with roughly half as many if a class introduced
the concept of a Point located at some (x, y).
You might even create a Ball class that models both position and velocity.
A related difficulty is that you almost adhered to a consistent
naming scheme. Clean that up and you'll find design and debugging much easier.
This question already has answers here:
Not letting the character move out of the window
(2 answers)
I made a border in this pong game, but the paddles can cross it. How do I stop that?
(2 answers)
Closed 2 years ago.
I have tried many sites but still cannot come up with anything. All online tutorials are not helpful. I have just started learning python and every time I try to move it goes out of the border. I have tried basically all online guide and came across an error...........................
pygame.init()
screen_width = 800
screen_height = 600
window = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Test')
bg_color1 = (135,142,142) #MAIN BG COLOR
bg_color2 = (255,0,0) #red
bg_color3 = (255,255,0) #yellow
clock = pygame.time.Clock()
crashed = False
UFO = pygame.image.load('ufo.png')
rect = UFO.get_rect()
obstacle = pygame.Rect(400, 200, 80, 80)
def car(x, y):
window.blit(UFO, (x, y))
x = (screen_width * 0.45)
y = (screen_height * 0.8)
x_change = 0
car_speed = 0
y_change = 0
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
############SIDE TO SIDE################
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
elif event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
###########UP AND DOWN#################
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
y_change = -5
elif event.key == pygame.K_DOWN:
y_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
##
x += x_change
y += y_change
##
window.fill(bg_color1)
car(x, y)
pygame.display.update()
clock.tick(100)
pygame.quit()
quit()
Check that the coordinate is less than 0 or greater than the width or height of the screen. Limit the coordinate if it is out of bounds:
while not crashed:
# [...]
x += x_change
if x < 0:
x = 0
elif x > screen_width - UFO.get_width():
x = screen_width - UFO.get_width()
y += y_change
if y < 0:
y = 0
elif y > screen_height - UFO.get_height():
y = screen_height - UFO.get_height()
You can simplify the code using the min and max functions:
while not crashed:
# [...]
x = max(0, min(screen_width - UFO.get_width(), x + x_change))
y = max(0, min(screen_height - UFO.get_height(), y + y_change))
Another option is to use pygame.Rect objects and clamp_ip. See clamp_ip:
moves the rectangle inside another, in place
while not crashed:
# [...]
x += x_change
y += y_change
border_rect = window.get_rect()
ufo_rect = UFO.get_rect(topleft = (x, y))
ufo_rect.clamp_ip(border_rect)
x, y = ufo_rect.topleft
So I'm just making a simple game that allows a red rectangle to move around the screen, but the boundaries that should make the red rectangle stop before it gets off the screen won't work. Can someone tell me what I'm doing wrong?
while Game:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_1:
gameDisplay = pygame.display.set_mode((display_width,display_height), pygame.FULLSCREEN)
if event.key == pygame.K_2:
gameDisplay = pygame.display.set_mode((display_width,display_height))
if event.key == pygame.K_RIGHT:
x_change = 5
if event.key == pygame.K_LEFT:
x_change = -5
if event.key == pygame.K_UP:
y_change = -5
if event.key == pygame.K_DOWN:
y_change = 5
if x > display_width - 100 or x < 0 and event.key == pygame.K_RIGHT:
if event.key == pygame.K_LEFT:
x_change = -5
else:
x_change = 0 #I did this for all directions
x += x_change
y += y_change
Just so you know, clock.tick is 80 and I have imported pygame and did the pygame.init() thing. Also, movement and every thing else works, just not this.
Try this code:
def clamp(value, minimum=0, maximum=1): return max(minimum, min(value, maximum))
maxX = display_width-rectangle_width
maxY = display_height-rectangle_height
if x not in range(maxX): x_change = 0
if y not in range(maxY): y_change = 0
x = clamp(x, maximum=maxX)
y = clamp(y, maximum=maxY)
However, you are changing the velocity and not the position, when it is out of the screen, the velocity is not moving it back, it keeps there or the speed from the pressed key in the next frame moves it again.
I'm trying to create a bird's-eye-view game (e.g. hotline miami) in pygame. I've gotten stuck at the collision detection. I'm trying to to see if the player hits a block on the left, right, in front or behind . I've gotten only to doing the 'in front' collision but that doesn't work; the player will hit the block 'head first', stop, but is then able to move through the block if he spams the arrow key. I know what the problem is (in the if else statement in the collision detection) but I can't for the life of me find the solution. Everything I tried doesn't seem to work. Help! Any help would be greatly appreciated, thanks in advance! (btw this is my first time on stack overflow, so sorry if I'm not asking the question well) (I removed some of the unnecessary code like the pygame.init() and variables)
def drawBlock(block_width,block_height,x,y):
pygame.draw.rect(gameDisplay, red, [x,y,block_width,block_height])
def gameLoop(x,y):
while not gameExit:
level = ["W","W","W","W","W","W","W","W","W","W","W","W",
"N","N","N","N","N","N","N","N","N","N","N","N","L",
"N","N","N","N","N","N","N","N","N","N","N","N","L",
"N","N","N","N","P","N","N","N","N","N","N","N","L",
"N","N","N","N","N","N","N","N","N","N","N","N","L",
"N","N","N","N","N","N","N","N","N","N","N","N","L",
"N","N","N","N","N","N","N","N","N","N","N","N","L",
"N","N","N","N","N","N","N","N","N","N","N","N","L",
"N","N","N","N","N","N","N","N","N","P","N","N","L",
"N","N","N","N","P","N","N","N","N","N","N","N","L",
"N","N","N","N","N","N","N","N","N","N","N","N","L","S"]
#EVENT HANDLING
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if canMoveUp:
if event.key == pygame.K_UP:
y_change = -player_movement
if canMoveDown:
if event.key == pygame.K_DOWN:
y_change = player_movement
if event.key == pygame.K_LEFT:
x_change = -player_movement
if event.key == pygame.K_RIGHT:
x_change = player_movement
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
pX += x_change
pY += y_change
gameDisplay.fill(black)
#CALCULATING THE SIZE OF THE BLOCKS SO THEY FIT W/ A VARIETY OF RESOLUTIONS
if calculateBlockX:
for element in level:
if element == "W":
W_count += 1
if element == "S":
block_width = (display_width/W_count)
calculateBlockX = False
if calculateBlockY:
for element in level:
if element == "L":
L_count += 1
if element == "S":
block_height = (display_height/L_count)
calculateBlockY = False
#COUNTING HOW MANY BLOCKS THERE ARE IN THE LEVEL ARRAY (P)
if P_countFunction:
for element in level:
if element == "P":
P_count += 1
if element == "S":
print(P_count)
P_countFunction = False
#ALL THE X AND Ys OF ALL THE BLOCKS IN THE LEVEL, AND ACTUALLY DRAWING THEM
blockXY = []
for element in level:
if element == "N":
x += block_width
if element == "L":
y += block_height
x = 0
if element == "P":
drawBlock(block_width,block_height,x,y)
blockXY.append(x)
blockXY.append(y)
if appendBlockXY:
if len(collisionArray) > P_count:
del(collisionArray[P_count])
print(collisionArray)
appendBlockXY = False
collisionArray.append(blockXY)
blockXY = []
x += block_width
if element == "S":
y = 0
#COLLISION DETECTION
for XnY in collisionArray:
if pX >= XnY[0] and pX <= XnY[0] + block_width and pY + playerSize <= XnY[1] or pX + playerSize >= XnY[0] and pX <= XnY[0] + block_width:
if pY - block_height == XnY[1]:
canMoveUp = False
y_change = 0
if pY - block_height != XnY[1]:
canMoveUp = True
else:
if pY - block_height >= XnY[1]:
canMoveUp = True
#gameDisplay.blit(img,[pX,pY])
pygame.draw.rect(gameDisplay, green, [pX,pY,playerSize,playerSize])
clock.tick(60)
pygame.display.update()
pygame.quit()
quit()
gameLoop(x,y)
pygame.display.update()
Your collision detection is written in a way that allows the last iteration to override all earlier checks. Instead of that, have canMoveUp set to True before the loop, and the loop should only set it to False or leave it alone.
I have problem with my code, I started to make 2D tank game, the problem is the shooting bullets from the tank position.. Here's my code, check it out, I'm trying to figure it out like 3-4 hours.. I hope someone knows how to do it, thanks!:)
by the way, sorry for the creepy code, I'm new to Pygame :)
import pygame
pygame.init()
#---WINDOW----
display_width = 1000
display_height = 600
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('powpypow')
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
background = pygame.image.load('background.png')
tank1 = pygame.image.load('tank1.png')
tankfire = pygame.image.load('tankfire.png')
shot = pygame.image.load('shot.png')
clock = pygame.time.Clock()
def tank(x,y):
gameDisplay.blit(tank1, (x,y))
x = (display_width * 0.10)
y = (display_height * 0.58)
x_change = 0
tank_width = 73
#---GAME LOOP----
gameExit = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
x_change = -10
elif event.key == pygame.K_d:
x_change = 10
elif event.key == pygame.K_SPACE:
tank1 = pygame.image.load('tankfire.png')
if event.type == pygame.KEYUP:
if event.key == pygame.K_a or event.key == pygame.K_d or event.key == pygame.K_SPACE:
tank1 = pygame.image.load('tank1.png')
x_change = 0
if x >= display_width - tank_width or x <= 0:
x = 0
if x > display_width / 2:
x = 0
x += x_change
gameDisplay.blit(background, (0,0))
tank(x,y)
pygame.display.update()
clock.tick(60)
pygame.quit()
quit()
If you are going to want to render bullets, you are going to need to keep track of them as they move across the screen. This will require some sort of list or group of bullets that you iterate through and draw, one at a time.
I recommend you have a look at a tutorial to help you switch to using Sprites in a group, rather than blitting each image onto the screen individually. You will find that it is much easier to track each object and adjust its position.
The Chimp tutorial from the Pygame website is pretty good: https://www.pygame.org/docs/tut/chimp/ChimpLineByLine.html