how do you create multiple rectangles and make them move independently - python

I am trying to create a flappy bird game with python but i cant get multiple walls to appear on the page and move across.
I was wondering if there was a way to make multiple walls (rectangles) and move them without defining them individually. Im using Pygame.
import pygame
pygame.init()
white = (255,255,255)
yellow = (255,200,0)
green = (0,255,0)
displayHeight = 600
displayWidth = 500
gameDisplay = pygame.display.set_mode((displayWidth, displayHeight))
clock = pygame.time.Clock()
crash = False
def bird(b_X, b_Y, b_R, b_Colour):
pygame.draw.circle(gameDisplay, b_Colour, (b_X, b_Y), b_R)
def game_loop():
bX = 50
bY = 300
bR = 20
bColour = yellow
velocity = 0
gravity = 0.6
lift = -15
while crash == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.QUIT
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
velocity += lift
gameDisplay.fill(white)
bird(bX, bY, bR, bColour)
velocity = velocity + gravity
bY += velocity
bY = round(bY)
if bY > displayHeight:
bY = displayHeight
velocity = 0
if bY < 0:
bY = 0
velocity = 0
pygame.display.update()
clock.tick(60)
game_loop()
pygame.quit()
quit()
Is there a way to make a big population of blocks and move them individually without defining them one by one.

I do not know how the code exactly works out, but you can store multiple wall 'objects' in a list, and looping over that list every time you update the screen. In pseudocode, it works like this
wall-list = []
for wanted_wall_amount in range():
wall = create_a_wall
wall-list.append(wall)
game loop:
for wall in wall-list:
wall.x_coordinate += movespeed
because of the for loop within the game loop, every wall object you stored will update it's position, or whatever you want to move simultanously. I hope you understand the weird pseudocode

Related

Player sprite ignoring my colliderect() with the ground surface and clipping right through and going down very fast

import pygame, time
from sys import exit
pygame.init()
pygame.font.init()
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 18)
def update_fps():
fps = str(int(clock.get_fps()))
fps_text = font.render(fps, 1, pygame.Color("coral"))
return fps_text
# Game Variables / Functions
screen_width = 1068
screen_height = 628
screen = pygame.display.set_mode((screen_width, screen_height))
original_player_pos = (50, 500)
original_player_size = (40, 60)
FPS = 69
gravity = 0
jump_force = 15
player_speed_right = 10
player_speed_left = 10
ground_grip = True
can_jump = True
# Player
class player():
player_surf = pygame.image.load("Graphics\player_idle.png").convert_alpha()
player = player_surf.get_rect(topleft=(original_player_pos))
class background():
sky_surf = pygame.image.load("Graphics\Sky.png")
sky_surf = pygame.transform.scale(sky_surf, (screen_width * 2, screen_height * 2))
sky = sky_surf.get_rect(topleft=(0, -screen_height))
class surfaces():
main_platform_surf = pygame.image.load("Graphics\main_ground.png")
main_platform = main_platform_surf.get_rect(topleft=(0, screen_height - main_platform_surf.get_height() + (main_platform_surf.get_height()) / 2))
# Game Engine Functions
def y_movement():
global gravity, ground_grip,can_jump
gravity += 1
player().player.y += gravity
if ground_grip == True:
if player().player.colliderect(surfaces().main_platform):
player().player.y = surfaces().main_platform.y - original_player_size[1]
if not player().player.colliderect(surfaces().main_platform) and player().player.y < surfaces().main_platform.y - original_player_size[1]:
can_jump = False
else:
can_jump = True
def x_movement():
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
player().player.x += player_speed_right
return "Right"
if keys[pygame.K_LEFT] or keys[pygame.K_a]:
player().player.x -= player_speed_left
return "Left"
def draw(surface, rect):
screen.blit(surface, rect)
def jump():
global gravity
gravity = -jump_force
# Game Engine
while True:
update_fps()
screen.fill("black")
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and can_jump == True:
ground_grip = False
if ground_grip == False:
jump()
ground_grip = True
x_movement()
y_movement()
draw(background().sky_surf, background().sky)
draw(surfaces().main_platform_surf, surfaces().main_platform)
draw(player().player_surf, player().player)
draw(update_fps(), (10,0))
clock.tick(FPS)
pygame.display.update()
Please try the code above out yourself, if you don't mind add some graphics to replace the pygame.image.load() or just replace it with a blank surface. When you run the program you see the main character and stuff, you can move around using WASD or arrow keys. Feel free to move around some stuff. Till now there is not a problem right? Now what I want you to do is stand still for 10 seconds (might happen sooner or later than that, should be around 10 seconds tho). When you stand still you will see the player sprite that you were moving around earlier literally just disappear. Now exit the program and add
print(player().player.y)
you will see the current player y location. Wait till the player dissapeares, and once it does, look at the y location that's gonna be printed out in your terminal. It will rapidly increase.
I tried 2 things. I added a variable that tries to grip the player into the ground if the player.y is over 0. It did not help and the player goes down anyways. I tried adding a variable that decides when the player can jump (because the y movement is linked directly to gravity and jumping) to decide when the player can jump. I was expecting the player sprite to just stay where it is.
When the player hits the platform, they must set the bottom of the player to the top of the platform.
player().player.bottom = surfaces().main_platform.top
Also set gravity = 0. If you do not reset gravity, gravity will increase until the player falls through the platform.
def y_movement():
global gravity, ground_grip,can_jump
gravity += 1
player().player.y += gravity
if ground_grip == True:
if player().player.colliderect(surfaces().main_platform):
player().player.bottom = surfaces().main_platform.top
gravity = 0
can_jump = True

pygame rectangle moving back to its original position after every move

I'm making a game for a school assignment and every time the character moves, it moves back to its original position. I'm not particularly well versed in pygame but I've looked over time and time again and I can't really figure out what the problem is.
Any tips?
import math
import sys
import pygame
def game():
pygame.init()
clock = pygame.time.Clock()
white = (255,255,255)
black = (0,0,0)
purple = (127, 84, 253)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
break
running = False
player_x = 12
player_y = 12
velocity = 10
surface = pygame.display.set_mode((400,400))
player = pygame.Rect(player_x,player_y,20,20)
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:player.y-=50
if keys[pygame.K_a]:player.x-=50
if keys[pygame.K_s]:player.y+=50
if keys[pygame.K_d]:player.x+=50
if keys[pygame.K_ESCAPE]:pygame.quit()
pygame.display.flip()
pygame.display.update()
surface.fill((255, 255, 255))
clock.tick(40)
pygame.quit()
game()```
player_x = 12
player_y = 12
velocity = 10
Should be out of the while loop you are resetting them each frame which cause the problem

Why is my platform game in PyGame suddenly so slow?

So I have a platform game I made in PyGame that all works, so I am now trying to make it a bit more colourful. So the code that I changed used to be:
def draw(self, screen):
""" Draw everything on this level. """
# Draw the background
screen.fill(BLUE)
and I changed it to:
def draw(self, screen):
""" Draw everything on this level. """
# Image from http://freepik
background_image = pygame.image.load("pink background.jpg").convert()
# Draw the background
screen.blit(background_image, [0, 0])
to get the pink background to be the background :) Now this is the only thing I changed in the code but everything now moves much slower e.g. the player that is being controlled by the user and the moving platform. There are two levels and I didn't change the code for the second levels background and the player still moves fine there :)
I did think I might of changed the line:
# Limit to 60 frames per second
clock.tick(60)
by accident, but it is still exactly the same.
I hope someone can help :) and thank you in advance :)
The error occurs somewhere in this code:
`
def main():
pygame.init()
# Set the height and width of the screen
size = [SCREEN_WIDTH, SCREEN_HEIGHT]
screen = pygame.display.set_mode(size)
pygame.display.set_caption('Platformer with moving platforms')
# Create the player
player = Player()
# Create all the levels
level_list = []
level_list.append(Level_01(player))
# Set the current level
current_level_no = 0
current_level = level_list[current_level_no]
active_sprite_list = pygame.sprite.Group()
player.level = current_level
player.rect.x = 200
player.rect.y = SCREEN_HEIGHT - player.rect.height - 30
active_sprite_list.add(player)
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
# -------- Main Program Loop --------
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.go_left()
if event.key == pygame.K_RIGHT:
player.go_right()
if event.key == pygame.K_UP:
player.jump()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and player.change_x < 0:
player.stop()
if event.key == pygame.K_RIGHT and player.change_x > 0:
player.stop()
# Update the player.
active_sprite_list.update()
# Update items in the level
current_level.update()
# If the player gets near the right side, shift the world left (-x)
if player.rect.right >= 500:
diff = player.rect.right - 500
player.rect.right = 500
current_level.shift_world(-diff)
# If the player gets near the left side, shift the world right (+x)
if player.rect.left <= 120:
diff = 120 - player.rect.left
player.rect.left = 120
current_level.shift_world(diff)
# If the player touches the floor they die.
if player.rect.y == SCREEN_HEIGHT - player.rect.height:
done = True
# If the player gets to the end of the level, go to the next level
current_position = player.rect.x + current_level.world_shift
if current_position < current_level.level_limit:
all_lines = []
list_of_files = os.listdir()
if username1 in list_of_files:
file1 = open(username1, "r")
for line in file1:
all_lines.append(line)
all_lines[2] = str(1)
with open(username1, 'w') as filehandle:
for listitem in all_lines:
filehandle.write(str(listitem))
done = True
# ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT
current_level.draw(screen)
active_sprite_list.draw(screen)
# Select the font to use, size, bold, italics
# ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT
# Limit to 60 frames per second
clock.tick(60)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Be IDLE friendly. If you forget this line, the program will 'hang'
# on exit.
pygame.quit()
if __name__ == "__main__":
main()
`
Do not load the image in your main loop. Define (load) it outside of the loop and then use it via variable. This is your problem, because it loads the image (in this case FPS = 60) times per second from your disk.

Creating multiple instances of bouncing ball pygame

So I am new to pygame and I made a program that will make a ball bounce according to gravity, and it works perfectly but now I want to be able to make infinite of them by creating one wherever I click. I know how to get the coordinates of the click, but I don't know how to create multiple circles. Would I somehow use a function or a class? Here's my code, sorry if it's a little messy.
import pygame,random,time
pygame.init()
infoObject = pygame.display.Info()
side = pygame.display.Info().current_h
side = side - ((1.0/12)*(pygame.display.Info().current_h))
side = int(side)
screen = pygame.display.set_mode([side, side])
pygame.display.set_caption("")
clock = pygame.time.Clock()
done = False
BLACK = (0,0,0)
WHITE = (255,255,255)
RED = (250,30,25)
GREEN = (25, 240, 25)
YELLOW = (250,240,25)
FPS = 60
x=100
y=100
t=0
r=10
direction=0
count = 0
def faller(x,y,color,size):
pygame.draw.circle(screen,color,(x,y),size,0)
def reverse():
global t,direction
if direction == 0:
direction = 1
t=t*4/5
elif direction == 1:
direction = 0
t=1
while not done:
clock.tick(FPS)
events = pygame.event.get()
screen.fill(BLACK)
for event in events:
if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
done = True
if direction==0:
t+=1
y+=int((9.8/FPS)*t)
elif direction==1:
t-=1
y-=int((9.8/FPS)*t)
if t==0:
reverse()
if y+r>side:
y=side-r
faller(x,y,RED,r)
reverse()
else:
faller(x,y,RED,r)
if y==side-r:
count+=1
else:
count=0
if count>=3:
done = True
pygame.display.flip()
pygame.quit()
I would encourage you to experiment with classes and methods. Once you have a class Ball, you can make a list of the Ball objects and process them all at once. You could then use the .append() list method to add a new Ball on mouse click.
I would suggest you use variables such as:
pos_x,
pos_y,
vel_x,
vel_y,
This will make things much easier to understand if you wanted to implement collisions. Dont forget to comment your code :)

Pygame sprite assistance

I've basically just started developing with PyGame and I am having trouble with the whole Sprite concept. I have been looking every where for guides on how to use it, I just can't seem to find any. I would like to know the basic concept of how it all works. This is the code I have been working on:
#!/usr/bin/python
import pygame, sys
from pygame.locals import *
size = width, height = 320, 320
clock = pygame.time.Clock()
xDirection = 0
yDirection = 0
xPosition = 32
yPosition = 256
blockAmount = width/32
pygame.init()
screen = pygame.display.set_mode(size)
screen.fill([0, 155, 255])
pygame.display.set_caption("Mario Test")
background = pygame.Surface(screen.get_size())
mainCharacter = pygame.sprite.Sprite()
mainCharacter.image = pygame.image.load("data/character.png").convert()
mainCharacter.rect = mainCharacter.image.get_rect()
mainCharacter.rect.topleft = [xPosition, yPosition]
screen.blit(mainCharacter.image, mainCharacter.rect)
grass = pygame.sprite.Sprite()
grass.image = pygame.image.load("data/grass.png").convert()
grass.rect = grass.image.get_rect()
for i in range(blockAmount):
blockX = i * 32
blockY = 288
grass.rect.topleft = [blockX, blockY]
screen.blit(grass.image, grass.rect)
grass.rect.topleft = [64, 256]
screen.blit(grass.image, grass.rect.topleft )
running = False
jumping = False
falling = False
standing = True
jumpvel = 22
gravity = -1
while True:
for event in pygame.event.get():
if event.type == KEYDOWN and event.key == K_ESCAPE:
pygame.quit()
sys.exit()
elif event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_LEFT:
running = True
xRun = -5
elif event.key == K_RIGHT:
running = True
xRun = 5
elif event.key == K_UP or event.key == K_SPACE:
jumping = True
elif event.type == KEYUP:
if event.key == K_LEFT or event.key == K_RIGHT:
running = False
if running == True:
xPosition += xRun
if mainCharacter.rect.right >= width:
xPosition = xPosition - 10
print "hit"
running = False
elif mainCharacter.rect.left <= 0:
xPosition = xPosition + 10
print "hit"
running = False
screen.fill([0, 155, 255])
for i in range(blockAmount):
blockX = i * 32
blockY = 288
grass.rect.topleft = [blockX, blockY]
screen.blit(grass.image, grass.rect)
grass.rect.topleft = [64, 64]
screen.blit(grass.image, grass.rect.topleft )
if jumping:
yPosition -= jumpvel
print jumpvel
jumpvel += gravity
if jumpvel < -22:
jumping = False
if mainCharacter.rect.bottom == grass.rect.top:
jumping = False
if not jumping:
jumpvel = 22
mainCharacter.rect.topleft = [xPosition, yPosition]
screen.blit(mainCharacter.image,mainCharacter.rect)
clock.tick(60)
pygame.display.update()
basically I just want to know how to make these grass blocks into sprites in a group, so that when I add my player (also a sprite) I can determine whether or not he is in the air or not through the collision system. Can someone please explain to me how I would do this. All I am looking for is basically a kick starter because some of the documentation is quite bad in my opinion as it doesn't completely tell you how to use it. Any help is greatly appreciated :)
In Pygame, sprites are very minimal. They consist of two main parts: an image and a rect. The image is what is displayed on the screen and the rect is used for positioning and collision detection. Here's an example of how your grass image could be made into a Sprite:
grass = pygame.image.load("grass.png")
grass = grass.convert_alpha()
grassSprite = new pygame.sprite.Sprite()
grassSprite.image = grass
#This automatically sets the rect to be the same size as your image.
grassSprite.rect = grass.get_rect()
Sprites are pretty pointless on their own, since you can always keep track of images and positions yourself. The advantage is in using groups. Here's an example of how a group might be used:
myGroup = pygame.sprite.Group()
myGroup.add([sprite1,sprite2,sprite3])
myGroup.update()
myGroup.draw()
if myGroup.has(sprite2):
myGroup.remove(sprite2)
This code creates a group, adds three sprites to the group, updates the sprites, draws them, checks to see if sprite2 is in the group, then removes the sprite. It is mostly straight forward, but there are some things to note:
1) Group.add() can take either a single sprite or any iterable collection of sprites, such as a list or a tuple.
2) Group.update() calls the update methods of all the Sprites it contains. Pygame's Sprite doesn't do anything when its update method is called; however, if you make a subclass of Sprite, you can override the update method to make it do something.
3) Group.draw() blits the images of all the Group's Sprites to the screen at the x and y positions of their rects. If you want to move a sprite, you change its rect's x and y positions like so: mySprite.rect.x = 4 or mySprite.rect.y -= 7
One way to use Groups is to create a different group for each level. Then call the update and draw method of whichever group represents the current level. Since nothing will happen or be displayed unless those methods are called, all other levels will remain "paused" until you switch back to them. Here's an example:
levels = [pygame.sprite.Group(),pygame.sprite.Group(),pygame.sprite.Group()]
levels[0].add(listOfLevel0Sprites)
levels[1].add(listOfLevel1Sprites)
levels[2].add(listOfLevel2Sprites)
currentLevel = 0
while(True):
levels[currentLevel].update()
levels[currentLevel].draw()
I know this question is somewhat old, but I hope you still find it helpful!

Categories

Resources