i am trying to make a flappy bird game in pygame for school but i am struggling with adding the obstacles. I can add one obstacle but i want to add infinite obstacles and i already have an infinite loop to run my game so when i add an extra infinite, loop my game just crashes. I am using a time.sleep() function when add the obstacle in my infinite loop which makes the game crash.
This is my code so far:
import time
import pygame
pygame.init()
xSpeler = 450
ySpeler = 100
widthSpeler = 40
heightSpeler = 40
vel = 10
vel1 = 10
#obstacle 1
xo1 = 900
yo1 = 0
ho1 = 200
wo1 = 50
xo2 = 900
yo2 = 350
ho2 = 200
wo2 = 50
#obstacle 2
xo3 = 900
yo3 = 0
ho3 = 250
wo3 = 50
xo4 = 900
yo4 = 350
ho4 = 150
wo4 = 50
win = pygame.display.set_mode((1000, 500))
bi = pygame.image.load('bada.png')
pygame.display.flip()
run = True
while run:
win.blit(bi, (0, 0))
pygame.time.delay(1)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
ySpeler += vel
if ySpeler >= 500 - heightSpeler:
ySpeler = 500 - heightSpeler
xo1 -= vel1
xo2 -= vel1
if keys[pygame.K_SPACE] and xSpeler> vel and ySpeler > 0:
ySpeler -= jump
pygame.draw.rect(win, (255, 0, 0), (xSpeler, ySpeler, widthSpeler, heightSpeler))
for x in range(100):
pygame.draw.rect(win, (0, 255, 0), (xo1, yo1, wo1, ho1)) or pygame.draw.rect(win, (0, 255, 0),(xo1, yo1, wo1, ho1))
pygame.draw.rect(win, (0, 255, 0), (xo2, yo2, wo2, ho2)) or pygame.draw.rect(win, (0, 255, 0),(xo2, yo2, wo2, ho2))
time.sleep(7)
pygame.display.update()
im came from netherland so my inglish is not so good and my variables are in dutch so sorry for it
i realy hope someone can help me.
Your screen stays black because of time.sleep(7). It is in a for loop that iterate 100 times so that's your program sleeping 700 seconds every frame. To make an obstacle, make a function that generates and returns 2 obstacles, one for top and the other one for bottom.
def genObstacle():
# generate and return
#1. pygame surface for top and bottom rects
#2. initial position for top rect and bottom rect
topHeight = random.randint(10, 200) # height for bottom obstacle
botHeight = random.randint(10, 200) # height for top obstacle
top = pygame.Surface((10, topHeight)).convert()
bot = pygame.Surface((10, botHeight)).convert()
# return: top rect, bottom rect, top rect's position, bottom rect's position
return [top, bot, [800, 0], [800, 500-botHeight]]
Return the initial positions for both of the obstacles as well, so it is easier to work with. I would really recommend using a class for obstacle, so working with attributes of obstacles like position is easier.
Now that we have a function to generate obstacle, we can make a list to hold those obstacles obstacles = []. Now, we can generate the obstacles every 3 seconds like this:
#other code
start = time.time()
while True:
#other code
now = time.time()
if now - start > 3:
obstacles.append(genObstacle())
start = now
Now that we have obstacles, we can change draw them and change their values like this:
for i in range(len(obstacles)):
# remember, third item in list is position for top and
# fourth item is the position for bottom
# draw the obstacles
win.blit(obstacles[i][0], (obstacles[i][2][0], obstacles[i][3][1]))
win.blit(obstacles[i][1], (obstacles[i][2][0], obstacles[i][3][1]))
# change the x values for it to move to the right
obstacles[i][2][0] -= 1
obstacles[i][2][0] -= 1
Related
import pgzrun
import pygame
WIDTH = 850
HEIGHT = 425
#sprites
title = Actor('title.png') #calling sprites and saying their pos
title.pos = 400, 212
cont = Actor('cont.png')
cont.pos = 470, 300
player = Actor('ship.png')
player.pos = 100, 56
foe = Actor('foe.png')
foe.pos = 200, 112
vel = 5
music.play("temp.mp3")
#controls
def draw():
screen.clear()
screen.fill((0, 0, 0))
title.draw()
cont.draw()
foe.draw()
player.draw()
def update():
keys = pygame.key.get_pressed()
x, y = player.pos
x += (keys[pygame.K_d] - keys[pygame.K_a]) * vel
y += (keys[pygame.K_s] - keys[pygame.K_w]) * vel
player.pos = x, y
if player.left > WIDTH: #if player hits right side of screen it takes the player to the other side of the screen
player.right = 0
def otherimage(): #animation of ship
player.image = 'ship.png'
imagey()
def imagey():
player.image = 'ship1.png'
clock.schedule_unique(otherimage, 1.0)
imagey()
pgzrun.go()
the animation section is the bit commented with "animation of ship". The wrapping bit is the bit labled "if player hits right side of screen it takes the player to the other side of the screen" as you can see i have go it working when the player hits the screen on the right side but every time i have tried getting it to work on the other sides it doesn't work. Please help! Thanks! Im new to coding and i am trying to understand this language. thanks again.
I want to restart where my player is when the player touches a wall, but before I do that, I want to give them a warning then reset position. I can't do either, though. I recently asked a similar question, and although I got a very good and helpful answer, it wouldn't work. Thank you anyway, Rabbid76. This is my code:
def touch_walls(player_pos):
if x-20 < 0:
#give warning not to touch sides
#reset player position
elif x+20 > 800:
#give warning not to touch sides
#reset player position
If anyone finds a solution, please tell me.
You can call a function to draw a "Don't touch walls" text.
`
def touch_walls(player_pos):
global playerPos, blit_font_time
x = player_pos[0]
if x-20 < 0 or x+20 > 800:
#make a text varible
#reset player position
playerPos = (50, 0)
blit_font_time = 60 # set this to as long as you wish
def blit_font():
text = pygame.font.SysFont('Arial', 50)
warning_label = text.render('Don\'t Touch Walls', True, (255, 255, 255)) #You can modify the text or the color anyway you want
center = (screen.get_width()/2 - warning_label.get_width()/2, screen.get_height()/2 - warning_label.get_height()/2)
screen.blit(warning_label, center) #Blit the text at the center of the screen
`
The whole thing will look like this:
`
import pygame
pygame.init()
playerPos = (-60, 50) # Assume playerPos is a varible that contains the player's position
screen = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
blit_font_time = 0
def touch_walls(player_pos):
global playerPos, blit_font_time
x = player_pos[0]
if x-20 < 0 or x+20 > 800:
#make a text varible
#reset player position
playerPos = (50, 0)
blit_font_time = 60 # set this to as long as you wish
def blit_font():
text = pygame.font.SysFont('Arial', 50)
warning_label = text.render('Don\'t Touch Walls', True, (255, 255, 255)) #You can modify the text or the color anyway you want
center = (screen.get_width()/2 - warning_label.get_width()/2, screen.get_height()/2 - warning_label.get_height()/2)
screen.blit(warning_label, center) #Blit the text at the center of the screen
run = True
while run:
clock.tick(60)
for e in pygame.event.get():
if e.type == pygame.QUIT:
run = False
screen.fill((20, 20, 20))
touch_walls(playerPos)
if blit_font_time > 0:
blit_font_time -= 1
blit_font()
pygame.display.update()
pygame.quit()
`
I have a program with a player (who is an image) and a rectangle and I want that when the player has a collision with the rectangle, the size of the image increase.
For now, I have this code :
import pygame
from random import randint
WIDTH, HEIGHT = 800, 800
FPS = 60
pygame.init()
win = pygame.display.set_mode((WIDTH, HEIGHT))
fenetre_rect = pygame.Rect(0, 0, WIDTH, HEIGHT)
pygame.display.set_caption("Hagar.io")
clock = pygame.time.Clock()
bg = pygame.image.load("bg.png").convert()
bg_surface = bg.get_rect(center=(WIDTH / 2, HEIGHT / 2))
bg_x = bg_surface.x
bg_y = bg_surface.y
x_max = WIDTH / 2
y_max = HEIGHT / 2
# player
player = pygame.transform.scale(pygame.image.load("player.png").convert_alpha(), (i, i))
player_rect = player.get_rect(center=(x_max, y_max))
# cell
rect_surface = pygame.Rect(300, 500, 20, 20)
# Game loop
running = True
while running:
dt = clock.tick(FPS) / 1000
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if player_rect.colliderect(rect_surface):
print("collide")
bg_surface.x = bg_x
bg_surface.y = bg_y
# draw on screen
win.blit(bg, bg_surface)
pygame.draw.rect(win, (255, 0, 0), rect_surface)
win.blit(player, player_rect)
pygame.display.flip()
pygame.quit()
I have try to add in the "colliderect" condition but it does not work :
player_rect.width += 1
player_rect.height += 1
Thanks for your help !
This line
player = pygame.transform.scale(pygame.image.load("player.png").convert_alpha(), (i, i))
is using the variable i but it is not defined in your code. I'm not sure where it is defined, but it is key to what you want. I will try to answer without this information anyway:
Thing is, enlarging the rect won't do anything, because a rect is just coordinates. You have to scale the actual image, and pygame.transform.scale does exactly that.
You can keep the image in a separate variable player_img:
player_img = pygame.image.load("player.png").convert_alpha()
player = pygame.transform.scale(player_img, (i, i))
Then when you want to scale it differently, just call .scale() again:
double_size_player = pygame.transform.scale(player_img, (i*2, i*2))
That still leaves us to the mistery of your undefined i variable, but I think you get the gist of it. Remeber that you have to extract a new rect from the scaled image because it will be bigger.
I'm writing an arcade game with traditional resolution 240 x 320 (vertical screen)
I need to render that to a modern display in real time.
This means that I need it to double (1 pixel = 4 on output) or even triple (1 pixel = 9)
I can't simply double scale the sprites because the game movement won't scale with them. (movement won't "snap" to visual scale)
Currently I have a game window that is 480 x 640 pixels.
I'm blitting all game sprites to a 240 x 320 surface, double scaling it and outputting that surface to the window with pygame. The game has slowed down far too much now.
How can all these emulators do nice double scale and triple scales with big clean pixels and pygame not? I thought SDL would be better at 2D rasterization.
Here is the code I currently have:
import pygame
import sys
import random
from Bullet import Bullet
bullets = []
pygame.init()
fps_clock = pygame.time.Clock()
# Our final window layer
window = pygame.display.set_mode((480, 640))
# This is the layer that gets scaled
render_layer = pygame.Surface((240, 320))
red = (255, 0, 0)
white = (255, 255, 255)
dkred =(127, 0, 0)
counter = 0;
# Sprite resources
bullet_sprite = pygame.image.load("shot1.png")
bullet_sprite2 = pygame.image.load("shot2.png")
while True:
render_layer.fill(dkred)
for i in bullets:
i.tick()
if i.sprite == "bullet_sprite1":
render_layer.blit(bullet_sprite, (i.x - 12, i.y -12))
else:
render_layer.blit(bullet_sprite2, (i.x - 12, i.y -12))
pygame.transform.scale2x(render_layer, window)
if i.x < 0 or i.y < 0 or i.x > 240 or i.y > 320:
i.dead = True
bullets = [x for x in bullets if x.dead == False]
counter += 3.33
for i in range(10):
if i % 2 == 0:
bullets.append(Bullet(120,120,360.0/10*i - counter, 3, -1,
sprite = "bullet_sprite1"))
else:
bullets.append(Bullet(120,120,360.0/10*i - counter, 3, -1,
sprite = "bullet_sprite2"))
for e in pygame.event.get():
if e.type == pygame.QUIT:
pygame.quit()
sys.exit()
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_ESCAPE:
pygame.event.post(pygame.event.Event(pygame.QUIT))
pygame.display.update()
fps_clock.tick(60)
I found that pygame.transform.scale2x() is in a for loop. Try just using it before pygame.display.update(). If there is more than one bullet, then I see how it could get laggy quickly.
I am just starting out learning pygame and livewires, and I'm trying to make a single-player pong game, where you just hit the ball, and it bounces around until it passes your paddle (located on the left side of the screen and controlled by the mouse), which makes you lose. I have the basic code, but the ball doesn't stay on the screen, it just flickers and doesn't remain constant. Also, the paddle does not move with the mouse. I'm sure I'm missing something simple, but I just can't figure it out. Help please! Here's what I have:
from livewires import games
import random
games.init(screen_width=640, screen_height=480, fps=50)
class Paddle(games.Sprite):
image=games.load_image("paddle.bmp")
def __init__(self, x=10):
super(Paddle, self).__init__(image=Paddle.image,
y=games.mouse.y,
left=10)
self.score=games.Text(value=0, size=25, top=5, right=games.screen.width - 10)
games.screen.add(self.score)
def update(self):
self.y=games.mouse.y
if self.top<0:
self.top=0
if self.bottom>games.screen.height:
self.bottom=games.screen.height
self.check_collide()
def check_collide(self):
for ball in self.overlapping_sprites:
self.score.value+=1
ball.handle_collide()
class Ball(games.Sprite):
image=games.load_image("ball.bmp")
speed=5
def __init__(self, x=90, y=90):
super(Ball, self).__init__(image=Ball.image,
x=x, y=y,
dx=Ball.speed, dy=Ball.speed)
def update(self):
if self.right>games.screen.width:
self.dx=-self.dx
if self.bottom>games.screen.height or self.top<0:
self.dy=-self.dy
if self.left<0:
self.end_game()
self.destroy()
def handle_collide(self):
self.dx=-self.dx
def end_game(self):
end_message=games.Message(value="Game Over",
size=90,
x=games.screen.width/2,
y=games.screen.height/2,
lifetime=250,
after_death=games.screen.quit)
games.screen.add(end_message)
def main():
background_image=games.load_image("background.bmp", transparent=False)
games.screen.background=background_image
paddle_image=games.load_image("paddle.bmp")
the_paddle=games.Sprite(image=paddle_image,
x=10,
y=games.mouse.y)
games.screen.add(the_paddle)
ball_image=games.load_image("ball.bmp")
the_ball=games.Sprite(image=ball_image,
x=630,
y=200,
dx=2,
dy=2)
games.screen.add(the_ball)
games.mouse.is_visible=False
games.screen.event_grab=True
games.screen.mainloop()
main()
I can't help you because you did not post the complete code here. At least, I do not see where you're updating the positions of the sprites (self.x += self.dx somewhere?) and updating the draw to screen. You're also not utilising your classes in the main() function.
That said, I'm seeing
def __init__(self, x=10):
and inside the constructor you never used the x variable. That worries me, too.
Consider using the Paddle and Ball class as a Sprite, like the following:
if __name__ == '__main__':
background_image = games.load_image("background.bmp", transparent=False)
games.screen.background = background_image
the_paddle = Puddle()
games.screen.add(the_paddle)
the_ball = Ball()
games.screen.add(the_ball)
games.mouse.is_visible = False
games.screen.event_grab = True
games.screen.mainloop()
Note I've taken the liberty to make your code read more Pythonic. I have never used livewires, however, so my code may not function. But it should point you to the right direction. Good luck!
Why are you using livewires? You can use only pygame for a pong game.
import pygame
pygame.init()
screen = pygame.display.set_mode((640, 480)) # window size
pygame.display.set_caption("Simple pong") # window title
# this is a rect that contains the ball
# at the beginning it is set in the center of the screen
ball_rect = pygame.Rect((312, 232), (16, 16))
# speed of the ball (x, y)
ball_speed = [4, 4]
# this contains your paddle
# vertically centered on the left side
paddle_rect = pygame.Rect((8, 200), (8, 80))
# 1 point if you hit the ball
# -5 point if you miss the ball
score = 0
# load the font for displaying the score
font = pygame.font.Font(None, 30)
# mainloop
while True:
# event handler
for event in pygame.event.get():
# quit event => close the game
if event.type == pygame.QUIT:
exit(0)
# control the paddle with the mouse
elif event.type == pygame.MOUSEMOTION:
paddle_rect.centery = event.pos[1]
# correct paddle position if it's going out of window
if paddle_rect.top < 0:
paddle_rect.top = 0
elif paddle_rect.bottom >= 480:
paddle_rect.bottom = 480
# this test if up or down keys are pressed
# if yes move the paddle
if pygame.key.get_pressed()[pygame.K_UP] and paddle_rect.top > 0:
paddle_rect.top -= 5
elif pygame.key.get_pressed()[pygame.K_DOWN] and paddle_rect.bottom < 480:
paddle_rect.top += 5
# update ball position
# this move the ball
ball_rect.left += ball_speed[0]
ball_rect.top += ball_speed[1]
# these two if block control if the ball is going out on the screen
# if it's going it reverse speed to simulate a bounce
if ball_rect.top <= 0 or ball_rect.bottom >= 480:
ball_speed[1] = -ball_speed[1]
if ball_rect.right >= 640:
ball_speed[0] = -ball_speed[0]
# this control if the ball touched the left side
elif ball_rect.left <= 0:
score -= 5
# reset the ball to the center
ball_rect = pygame.Rect((312, 232), (16, 16))
# test if the ball is hit by the paddle
# if yes reverse speed and add a point
if paddle_rect.colliderect(ball_rect):
ball_speed[0] = -ball_speed[0]
score += 1
# clear screen
screen.fill((255, 255, 255))
# draw the ball, the paddle and the score
pygame.draw.rect(screen, (0, 0, 0), paddle_rect) # paddle
pygame.draw.circle(screen, (0, 0, 0), ball_rect.center, ball_rect.width/2) # ball
score_text = font.render(str(score), True, (0, 0, 0))
screen.blit(score_text, (320-font.size(str(score))[0]/2, 5)) # score
# update screen and wait 20 milliseconds
pygame.display.flip()
pygame.time.delay(20)