Problem with simple python game using a pygame libray - python

I'm new at Python and Pygame and I started making a simple game, something like a tennis game, but every time ball is under the rectangle jumping +-5 pixels and blocking. I think the problem is with pXY and bXY.
import sys, pygame
from pygame.locals import *
pygame.init()
pygame.display.set_mode((500,500)) # ustawiwanie wielkosci
pygame.display.set_caption(("little shit")) #ustawianie nazwy
okienko = pygame.display.get_surface() # pobieranie płaszczyzny
# obiekt
prostokat = pygame.Surface((80,20)) # tworzenie prostokąta / tulpa, szerokość / wysokość
prostokat.fill((128, 15, 220)) # zmiana koloru prostokąta / r:g:b
pXY = prostokat.get_rect() # pobranie wymiarów prostokąta
pXY.x = 225 # wartość x
pXY.y = 460 # wartość y
kolko = pygame.image.load("./ball.png")
bXY = kolko.get_rect()
bXY.x = 120 # POŁOŻENIE OBIEKTU
bXY.y = 200 # POŁOŻENIE OBIEKTU
bx,by = 5,5 # o ile sie przesuwamy
px = 3
bAB = kolko.get_rect()
bA = 25
bB = 25
kolko = pygame.transform.scale(kolko,(bA,bB))
pygame.display.flip() # wyświetlenie/odrysowanie całego okna
fps = pygame.time.Clock() # ile czasu minęło od wykonywania instrukcji
while True:
okienko.fill((128, 128, 128)) # zmiana koloru płaszczyzny na szary
pXY.x += px
if pXY.x > 420 or pXY.x < 0:
px *= -1
okienko.blit(prostokat, pXY)
bXY.x +=bx
if bXY.x > 475 or bXY.x < 0:
bx*= -1
bXY.y +=by
if bXY.y > 475 or bXY.y < 0:
by*= -1
if pXY.colliderect(bXY): # KOLIDACJA OBIEKTOW
by=5
okienko.blit(kolko, bXY)
pygame.display.update() # update okienka
fps.tick(30) # odswiezanie obrazu, 30 fps
for zdarzenie in pygame.event.get():
if zdarzenie.type == pygame.QUIT:
pygame.quit()
exit()
if zdarzenie.type == KEYDOWN:
if zdarzenie.key == K_LEFT:
px=-7
if zdarzenie.key == K_RIGHT:
px=7
while True: # pętla do zamykania okienka
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
When the ball is under the rectangle, jumping +- 5 pixels and blocking, the ball can't leave this area when is on the left

Your collision detection logic will not give physically accurate results. For example, no matter where the ball collides with the paddle it will always start moving downward at 5 pixels/frame. This means that the ball will pass through the paddle when it collides hits from above but it will 'bounce' if it hits from below. That is what causes the ball to behave the way it does. This line is where the velocity is set if the paddle and ball are colliding:
if pXY.colliderect(bXY): # KOLIDACJA OBIEKTOW
by=5
A slightly better approach would be to reverse the direction of the ball if it collides with the paddle. But this still makes the ball only reverse direction in the y-axis no matter where on the paddle the ball collides (top, bottom, left, right). The code above can be changed to this code to get this effect:
if pXY.colliderect(bXY): # KOLIDACJA OBIEKTOW
by*=-1
This final chunk of code is cleaned up a bit and translated to English. It uses the second block of code from above to bounce the ball off the paddle:
import sys
import pygame
pygame.init()
window = pygame.display.set_mode((500, 500))
pygame.display.set_caption('new caption')
paddle = pygame.Surface((80, 20))
paddle.fill((128, 15, 220))
paddle_rect = paddle.get_rect()
paddle_rect.x = 225
paddle_rect.y = 460
ball = pygame.Surface((25, 25))
ball.fill((255, 0, 0))
ball_rect = ball.get_rect()
ball_rect.x = 120
ball_rect.y = 200
ball_velocity_x = 5
ball_velocity_y = 5
paddle_velocity_x = 3
clock = pygame.time.Clock()
while True:
# event processing code
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
paddle_velocity_x = -7
elif event.key == pygame.K_RIGHT:
paddle_velocity_x = 7
# update code
# update the position of the paddle and bounce it off the edges of the window
paddle_rect.x += paddle_velocity_x
if paddle_rect.x > 420 or paddle_rect.x < 0:
paddle_velocity_x *= -1
# update the position of the ball and bounce it off th eedges of the window
ball_rect.x += ball_velocity_x
ball_rect.y += ball_velocity_y
if ball_rect.x > 475 or ball_rect.x < 0:
ball_velocity_x *= -1
if ball_rect.y > 475 or ball_rect.y < 0:
ball_velocity_y *= -1
if paddle_rect.colliderect(ball_rect):
ball_velocity_y *= -1
# drawing code
window.fill((128, 128, 128))
window.blit(paddle, paddle_rect)
window.blit(ball, ball_rect)
pygame.display.update()
clock.tick(30)

Related

How do I implement sliding window algorithm on an image?

I'm making the Super Mario Bros. game on python using the pygame library. I wanted to fit only a portion of the map of mario bros level and I have no idea how am I supposed to do that. One of my seniors told me that I could use the sliding window algorithm. However, the problem is I don't know how to implement this algorithm on the image. If I can get any help that would be really appreciated.mario level world 1-1
I have also been able to print out the map to a suitable scaling:
map on code
edit: I am sorry I did not post my code. here it is:
import pygame
import pygame.transform
i = pygame.init()
X = 640
Y = 480
Window = pygame.display.set_mode ((X, Y))
pygame.display.set_caption ("Game")
Mario_Standing_Left = pygame.image.load("F:\\Mario in Python\\Mario_Standing_Left.png")
Mario_Standing_Right = pygame.image.load("F:\\Mario in Python\\Mario_Standing_Right.png")
x = 50
y = 430
width = 40
height = 60
speed = 5
isjump = False
jumpcount = 10
left = False
right = False
WalkCount = 0
ScreenWidth = X - width - speed
ScreenHeight = Y - height - speed
isjump = False
jumpcount = 10
run = True
while run:
pygame.time.delay (50) #time in pygame measured in milliseconds
for event in pygame.event.get ():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and x > speed:
x -= speed
if keys[pygame.K_RIGHT] and x <= ScreenWidth:
x += speed
if not (isjump):
if keys[pygame.K_SPACE]:
isjump = True
else:
if jumpcount >= -10:
neg = 1
if jumpcount < 0:
neg = -1
y -= (jumpcount ** 2) * 0.5 * neg
jumpcount -= 1
else:
isjump = False
jumpcount = 10
Window.fill ((0,0,0))
#(surface, (the window defined above, (colour), (the object being drawn)))
pygame.display.update()
world = pygame.image.load('World 1-1.png').convert()
world = pygame.transform.smoothscale(world,(8750,1400))
while True:
Window.blit(world,(0,0))
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.display.quit()
pygame.quit()
You should use area in blit(..., area=...) to display only some part of world
I use area = pygame.Rect(0, 300, SCREEN_WIDTH, SCREEN_HEIGHT) to keep information what area to display. And I change area.x to scroll it right and left.
import pygame
# --- constants --- # PEP8: all constants directly after imports
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
FPS = 60
# --- main --- # PEP8: `lower_case_names` for variables
pygame.init()
window = pygame.display.set_mode ((SCREEN_WIDTH, SCREEN_HEIGHT))
world_image = pygame.image.load('World 1-1.png').convert()
world_image = pygame.transform.smoothscale(world_image, (8750,1400))
world_rect = world_image.get_rect()
area = pygame.Rect(0, 300, SCREEN_WIDTH, SCREEN_HEIGHT)
direction = 'right'
# - mainloop -
clock = pygame.time.Clock()
run = True
while run:
for event in pygame.event.get ():
if event.type == pygame.QUIT:
run = False
if direction == 'right':
# move right
area.x += 2
# change direction
if area.right > world_rect.right:
area.right = world_rect.right
direction = 'left'
else:
# move left
area.x -= 2
# change direction
if area.left < world_rect.left:
area.left = world_rect.left
direction = 'right'
#window.fill((0, 0, 0))
window.blit(world_image, (0,0), area=area)
pygame.display.flip()
clock.tick(FPS) # keep speed 60 FPS (Frames Per Second)
# - end -
pygame.quit()
PEP 8 -- Style Guide for Python Code
EDIT:
If you will have other elements then you may need to create Surface with size of world to blit world and other elements before on this surface and later display it in window using area.
import pygame
# --- constants ---
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
FPS = 60
# --- main --- # PEP8: `lower_case_names` for variables
pygame.init()
window = pygame.display.set_mode ((SCREEN_WIDTH, SCREEN_HEIGHT))
window_rect = window.get_rect()
world_image = pygame.image.load('World 1-1.png').convert()
world_image = pygame.transform.smoothscale(world_image, (8750,1400))
world_rect = world_image.get_rect()
player_image = pygame.Surface((40, 40))
player_image.fill((255, 0, 0)) # red
player_rect = player_image.get_rect(centerx=window_rect.centerx, centery=window_rect.centery+300 )
area = pygame.Rect(0, 300, SCREEN_WIDTH, SCREEN_HEIGHT)
direction = 'right'
buffer = pygame.Surface(world_rect.size)
# - mainloop -
clock = pygame.time.Clock()
run = True
while run:
for event in pygame.event.get ():
if event.type == pygame.QUIT:
run = False
if direction == 'right':
# move right
area.x += 5
player_rect.x += 5
# change direction
if area.right > world_rect.right:
area.x -= 5
player_rect.x -= 5
#area.right = world_rect.right
direction = 'left'
else:
# move left
area.x -= 5
player_rect.x -= 5
# change direction
if area.left < world_rect.left:
area.x += 5
player_rect.x += 5
#area.left = world_rect.left
direction = 'right'
#player_rect.center = area.center
buffer.blit(world_image, (0,0))
buffer.blit(player_image, player_rect)
# ---
#window.fill((0, 0, 0))
window.blit(buffer, (0,0), area=area)
pygame.display.flip()
clock.tick(FPS) # keep speed 60 FPS (Frames Per Second)
# - end -
pygame.quit()

how to randomly generate spikes in pygame which are constantly moving down

im building a game in pygame in which a hot air balloon is constantly going up and spikes are coming down and hot air balloon has to dodge them. However i dont know how to randomly generate nicely spaced spikes which constantly moving downwards im having issue with randomly generating downward moving spikes.
here is the code:
import pygame
import random
import math
pygame.init()
clock = pygame.time.Clock()
screenwid = 400
screenhigh = 500
screen = pygame.display.set_mode((screenwid, screenhigh))
grey = (240,240,240)
black = (0,0,0)
initvel = 3
player_x = 100
player_y = 250
spikex= -100
spikey = -100
xchange = 0
ychange = 0
baloon = pygame.image.load('C:/Users/aliab/Downloads/hotair balloom.png')
baloon = pygame.transform.scale(baloon,(300, 300))
spike = pygame.image.load('C:/Users/aliab/Downloads/spikes.png')
spike = pygame.transform.scale(spike,(300, 300))
bg = pygame.image.load('E:/bgparacute.jpg')
def balloon(x,y):
screen.blit(baloon,(x,y ))
def spikee(x,y):
screen.blit(spike,(x,y ))
y = 0
run = True
while run:
rel_y = y % bg.get_rect().height
screen.blit(bg,(0,rel_y - bg.get_rect().height))
if rel_y < screenhigh:
screen.blit(bg, (0, rel_y))
y +=1
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
xchange = -initvel
ychange = 0
if event.key == pygame.K_RIGHT:
xchange = initvel
ychange = 0
if event.key == pygame.K_UP:
ychange = -initvel
xchange = 0
if event.key == pygame.K_DOWN:
ychange = initvel
xchange = 0
if spikey == 100:
print('hihiohug')
spikex = random.randint(0, 400)
spikey = random.randint(-20, 10)
spikey += 2
player_x += xchange
player_y += ychange
balloon(player_x,player_y)
spikee(spikex, spikey)
clock.tick(60)
pygame.display.update()
pygame.quit()
I tried out your program. If you are looking to only have a few spikes on your screen, theoretically, you could just individually define the spikes and then randomly generate their starting position as in your code with some simple tweaks.
import pygame
import random
import math
pygame.init()
clock = pygame.time.Clock()
screenwid = 400
screenhigh = 500
screen = pygame.display.set_mode((screenwid, screenhigh))
grey = (240,240,240)
black = (0,0,0)
initvel = 2
player_x = 100
player_y = 250
spikex1 = -100
spikey1 = -100
spikex2 = -40
spikey2 = -100
xchange = 0
ychange = 0
baloon = pygame.image.load('Balloon.png')
baloon = pygame.transform.scale(baloon,(240, 240))
spike1 = pygame.image.load('Mine.png') # Multiple spike definitions (very simplistic)
spike1 = pygame.transform.scale(spike1,(30, 30))
spike2 = pygame.image.load('Mine.png')
spike2 = pygame.transform.scale(spike2,(30, 30))
bg = pygame.image.load('background-day.png')
def balloon(x,y):
screen.blit(baloon,(x,y ))
def spikee(x,y):
screen.blit(spike1,(x,y ))
screen.blit(spike2,(x,y ))
y = 0
run = True
while run:
rel_y = y % bg.get_rect().height
screen.blit(bg,(0,rel_y - bg.get_rect().height))
if rel_y < screenhigh:
screen.blit(bg, (0, rel_y))
y +=1
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
xchange = -initvel
ychange = 0
if event.key == pygame.K_RIGHT:
xchange = initvel
ychange = 0
if event.key == pygame.K_UP:
ychange = -initvel
xchange = 0
if event.key == pygame.K_DOWN:
ychange = initvel
xchange = 0
if event.type == pygame.KEYUP: # Allow for a little more control of the balloon
xchange = 0
ychange = 0
if spikey1 == 280:
print('hihiohug')
spikex1 = random.randint(0, 300)
spikey1 = random.randint(-100, 10) # Adjust the random start above the screen for the spike
if spikey2 == 280:
print('hihiohug')
spikex2 = random.randint(0, 300)
spikey2 = random.randint(-100, 10) # Adjust the random start above the screen for the spike
spikey1 += 1
spikey2 += 1
player_x += xchange
player_y += ychange
balloon(player_x,player_y)
spikee(spikex1, spikey1)
spikee(spikex2, spikey2)
clock.tick(60)
pygame.display.update()
pygame.quit()
This produced randomly generated spikes (mines in my test).
However, you might want to define an array of spikes that are randomly placed just off of the display. As an example of that, I am including a link to GitHub for you to pull down a simple game I call "Submarine".
Submarine Game
It is an arcade like game where the submarine tries to avoid hitting underwater mines. It effectively is running in a horizontal fashion as opposed to your vertical action, but the underlying premises are alike. It has an array set up for storing underwater mine images that then appear on the screen.
Give that a try and see if that moves you forward in your game.

Pygame rect will not update

I am building a game in pygame where there is a red target that moves up and down on the right side of the screen and a ship on the left side of the screen the moves up and down that fires bullets (which is just a blue rectangle) at the target.
My ship, and my target start in the center of each side of the screen and are properly moving. The problem that I have is when I 'fire' a bullet the bullet is getting drawn at the ship's original position, not where the ship has moved to on the screen.
I have the bullet's rect set to the ship image's rect outside of my while loop, but I would think that it would get updated as my ship moves up and down on the screen.
import pygame
import pygame.sprite
import sys
screen_width = 1200
screen_height = 800
screen = pygame.display.set_mode((screen_width, screen_height))
screen_rect = screen.get_rect()
image = pygame.image.load('ship.bmp')
image_rect = image.get_rect()
image_rect.midleft = screen_rect.midleft
target_rect = pygame.Rect(400, 0, 100, 100)
target_color = (255, 0, 0)
target_rect.midright = screen_rect.midright
target_direction = 1
bullet_rect = pygame.Rect(0, 0, 15, 3)
bullet_rect.midright = image_rect.midright
bullet_color = (0, 0, 255)
fire_bullet = False
while True:
screen.fill((0, 255, 0))
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
sys.exit()
# Move the ship up and down
elif event.key == pygame.K_UP:
image_rect.y -= 45
elif event.key == pygame.K_DOWN:
image_rect.y += 45
# Active bullet fired
elif event.key == pygame.K_SPACE:
fire_bullet = True
elif event.type == pygame.QUIT:
sys.exit()
# Move the bullet across the screen if fired
if fire_bullet:
screen.fill(bullet_color, bullet_rect)
bullet_rect.x += 1
# Move the Target up and down
target_rect.y += target_direction
if target_rect.bottom >= screen_height:
target_direction *= -1
elif target_rect.top <= 0:
target_direction *= -1
screen.fill(target_color, target_rect)
screen.blit(image, image_rect)
pygame.display.flip()
I have the bullet's rect set to the ship image's rect outside of my while loop, but I would think that it would get updated as my ship moves up and down on the screen.
That's not it. You just set the position of the rect, there is not automatic update. You have to write the code to keep them in sync.
But even simpler, in your case you could create the bullet rect when you shot. Move the bullet creation in the loop like this:
elif event.key == pygame.K_SPACE:
bullet_rect = pygame.Rect(0, 0, 15, 3)
bullet_rect.midright = image_rect.midright
bullet_color = (0, 0, 255)
fire_bullet = True

I can't get my 'player' to move to move both ways in pygame, how do i do it?

I am making a game and was wondering how to make my 'player' or green piece to move both ways. Whenever I click any of the arrows he moves right because that's all I can figure out. The animation code is on lines 27 and 28. I need the green circle to be able to move right and left 5 pixels every time either of the arrows are clicked.
EDIT: I also need the collision to be when it hits anywhere on the red bullets because in my current code the bullets have to hit the exact coordinates of the player.
import pygame
import random
BLACK = (0,0,0)
WHITE = (255,255,255)
GREEN = (0,255,0)
RED = (255,0,0)
BLUE = (0,0,255)
pygame.init()
size = (700,700)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Dodger")
done = False
clock = pygame.time.Clock()
def resetpositions():
global bulletrect1, bulletrect2, bulletrect3, bulletrect4, bulletrect5, circlerect
bulletrect1 = pygame.rect.Rect((350, 0, 20, 20))
bulletrect2 = pygame.rect.Rect((175, 0, 20, 20))
bulletrect3 = pygame.rect.Rect((525, 0, 20, 20))
bulletrect4 = pygame.rect.Rect((525, 0, 20, 20))
bulletrect5 = pygame.rect.Rect((525, 0, 20, 20))
circlerect = pygame.rect.Rect((350, 600, 20, 20))
resetpositions()
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
circlerect.x += 5
bulletrect1.y += 1
bulletrect2.y += 2
bulletrect3.y += 3
bulletrect4.y += 4
bulletrect5.y += 5
screen.fill(BLACK)
pygame.draw.circle(screen, GREEN, (circlerect.center), 15)
pygame.draw.circle(screen, RED, (bulletrect1.center), 20)
pygame.draw.circle(screen, RED, (bulletrect2.center), 20)
pygame.draw.circle(screen, RED, (bulletrect3.center), 20)
pygame.draw.circle(screen, RED, (bulletrect4.center), 20)
pygame.draw.circle(screen, RED, (bulletrect5.center), 20)
if bulletrect1.y == 800:
bulletrect1.y = 0
bulletrect1.x = random.randint(20,680)
if bulletrect2.y == 800:
bulletrect2.y = 0
bulletrect2.x = random.randint(20,680)
if bulletrect3.y == 800:
bulletrect3.y = 0
bulletrect3.x = random.randint(20,680)
if bulletrect4.y == 800:
bulletrect4.y = 0
bulletrect4.x = random.randint(20,680)
if bulletrect5.y == 800:
bulletrect5.y = 0
bulletrect5.x = random.randint(20,680)
if circlerect.x == 685:
circlerect.x = 15
if circlerect.collidelist((bulletrect1, bulletrect2, bulletrect3, bulletrect4, bulletrect5)) == 0:
screen.fill(BLACK)
font = pygame.font.SysFont('Calibri',40,True,False)
text = font.render("GAME OVER",True,RED)
screen.blit(text,[250,350])
pygame.display.update()
pygame.time.delay(3000)
resetpositions()
pygame.display.flip()
clock.tick(300)
pygame.quit()
Lines 30 and 31 are:
if event.type == pygame.KEYDOWN:
circlerect.x += 5
This code detects when ANY key is pressed down and will subsequently move the circlerect object 5 units to the right (always to the right because it is always +=).
If you want to move both ways you will have to detect more than just KEYDOWN. You have to detect when the key press is left (and subtract 5) and when it is right (and add 5).
As Isaac mentioned, you have to check which key was pressed by the user and move left -= 5 or right += 5 accordingly.
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
circlerect.x -= 5
elif event.key == pygame.K_RIGHT:
circlerect.x += 5
The problem is that this only moves the player once per key press and you'd have to add variables like moving_left to get continuous movement. In your case it would be easier to use pygame.key.get_pressed instead of handling the events in the event loop, because you can use it to check if a key is held down.
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# A list of the pressed keys.
keys = pygame.key.get_pressed()
# If the key at index `K_LEFT` is held.
if keys[pygame.K_LEFT]:
circlerect.x -= 5
elif keys[pygame.K_RIGHT]:
circlerect.x += 5
Side note: clock.tick(300) is too high. Better limit your game to 30 or 60 fps and increase the speed of the circles.

Python collision detect

I've made a game in pygame and I'm starting to add collision detection. For the two sprites (duck and rock), I've given them a rect variable.What do I do know to check if they collide?
This is the code:
import pygame, sys
from pygame.locals import *
pygame.init()
clock = pygame.time.Clock()
#screen constants
screen = pygame.display.set_mode((1050,350),0,32)
x = 0
screenWidth = 1050
speed = 2
#background constants
b1 = "bg1.jpg"
b2 = "bg2.jpg"
back = pygame.image.load(b1).convert()
back2 = pygame.image.load(b2).convert()
#duck constants
duck = pygame.image.load("duck.png")
rect_duck = duck.get_rect()
duckY = 246
duckMoveY=0
flying = False
falling = False
#rock constants
rock = pygame.image.load("rock.png")
rect_rock = rock.get_rect()
rockX = 0
#init game loop
while True:
#check if they want to quit
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
#see if they fly
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
flying = True
#see if they fall
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
falling = True
flying = False
#flying
if flying == True:
duckMoveY = -5
#falling
if falling == True:
duckMoveY = 5
#display the backgrounds
screen.blit(back, (x,0))
screen.blit(back2,(x-screenWidth,0))
#display the duck
screen.blit(duck, (500,duckY))
#display the rock
screen.blit(rock, (rockX, 275))
#move background
x += speed
if x == screenWidth:
x = 0
#move the duck
duckY += duckMoveY
#move the rock
rockX += speed
#stop them falling off the screen
if duckY > 246:
falling = False
duckY = 246
#stop them flying off the top
if duckY < 0:
flying = False
duckY = 0
#update the screen and set fps
pygame.display.update()
pygame.display.flip()
msElapsed = clock.tick(100)
I would advise you to make those variables a circle instead of rectangles. Then, you will have a collision when the distance between the two centers is less than the sum of the radiuses.
if(m.sqrt((duckX-rockX)**2+(duckY-rockY)**2)<=radius+cursorRadius):
print("Collision!")

Categories

Resources