I believe I'm not updating the masks location correctly, according to the images position in the screen. I can't understand why, because, after updating the images x and y coordinate, I redraw the mask to match their location. I believe it doesn't colide, even after drawing the mask, because the mask isn't being updated to match the image's coordinates. Is that what's happening here?
The minimal code is posted below:
import pygame
import random
pygame.init()
black = (0, 0, 0)
height = 600
width = 800
screen = pygame.display.set_mode((width, height))
white = (255, 255, 255)
FPS = 60
clock = pygame.time.Clock()
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((40, 50))
self.image.fill(black)
self.rect = self.image.get_rect()
self.rect.x = 0 + self.rect.x
self.rect.y = height - self.rect.height
self.lead_x_change = 0
self.lead_y_change = 0
self.speed = 5
self.health = 100
self.mask = pygame.mask.from_surface(self.image)
def move_x(self):
self.rect.x += self.lead_x_change
self.mask = pygame.mask.from_surface(self.image)
def move_y(self):
self.rect.y += self.lead_y_change
self.mask = pygame.mask.from_surface(self.image)
def move_xd_change(self):
self.lead_x_change += self.speed
def move_xa_change(self):
self.lead_x_change += -self.speed
def move_yu_change(self):
self.lead_y_change += -self.speed
def move_yd_change(self):
self.lead_y_change += self.speed
def stop_x_change(self):
self.lead_x_change = 0
def stop_y_change(self):
self.lead_y_change = 0
class Apple(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((40, 50))
self.image.fill(black)
self.rect = self.image.get_rect()
self.rect.x = random.randint(100, 700)
self.rect.y = random.randint(100, 500)
self.mask = pygame.mask.from_surface(self.image)
apple = Apple()
player = Player()
all_sprites = pygame.sprite.Group()
all_sprites.add(player, apple)
gameExit = False
while not gameExit:
screen.fill(white)
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
player.move_yu_change()
if event.key == pygame.K_s:
player.move_yd_change()
if event.key == pygame.K_d:
player.move_xd_change()
if event.key == pygame.K_a:
player.move_xa_change()
if event.type == pygame.KEYUP:
if event.key == pygame.K_w or event.key == pygame.K_s:
player.stop_y_change()
if event.key == pygame.K_d or event.key == pygame.K_a:
player.stop_x_change()
player.move_x()
player.move_y()
all_sprites.draw(screen)
hit = pygame.sprite.collide_mask(player, apple)
if hit:
apple.rect.x = random.randint((100, 700))
apple.rect.y = random.randint((100, 500))
apple.mask = pygame.mask.from_surface(apple.image)
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
quit()
pygame.mask.from_surface works only if the surface has an alpha channel. Either pass pygame.SRCALPHA as the flags (the second) argument to pygame.Surface
self.image = pygame.Surface((40, 50), pygame.SRCALPHA)
or call convert_alpha
self.image = pygame.Surface((40, 50)).convert_alpha()
or call set_colorkey
self.image.set_colorkey((0, 0, 0))
By the way, there's no reason to create new masks in the move_x and move_y methods. You only have to do this if you modify the self.image surface. It would be better for the performance to create the masks beforehand and just switch them when you need another one.
Related
The following code attempts; unsuccessfully, to move a small graphic together with its mask. The graphic (car.png) moves as intended when the keyboard input indicates forward and backward. However, when the keyboard input indicates a rotation, the car graphic disappears and the place-holder triangle appears. The place-holder triangle subsequently behaves as the car graphic (with its mask) is supposed to behave.
import math
import pygame as pg
from pygame.math import Vector2
class Player(pg.sprite.Sprite):
def __init__(self, pos=(420, 420)):
super(Player, self).__init__()
self.image = pg.Surface((70, 50), pg.SRCALPHA)
pg.draw.polygon(self.image, (50, 120, 180), ((0, 0), (0, 50), (70, 25)))
self.original_image = self.image
self.rect = self.image.get_rect(center=pos)
# Instead we could load a picture of a car
self.image = pg.image.load("car.png").convert_alpha()
self.mask = pg.mask.from_surface(self.image)
self.position = Vector2(pos)
self.direction = Vector2(1, 0) # A unit vector pointing rightward.
self.speed = 2
self.angle_speed = 0
self.angle = 0
def update(self):
if self.angle_speed != 0:
# Rotate the direction vector and then the image.
self.direction.rotate_ip(self.angle_speed)
self.angle += self.angle_speed
self.image = pg.transform.rotate(self.original_image, -self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
# Update the position vector and the rect.
self.position += self.direction * self.speed
self.rect.center = self.position
def main():
pg.init()
screen = pg.display.set_mode((1280, 720))
player = Player((420, 420))
playersprite = pg.sprite.RenderPlain((player))
clock = pg.time.Clock()
done = False
while not done:
clock.tick(60)
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.KEYDOWN:
if event.key == pg.K_UP:
player.speed += 1
elif event.key == pg.K_DOWN:
player.speed -= 1
elif event.key == pg.K_LEFT:
player.angle_speed = -4
elif event.key == pg.K_RIGHT:
player.angle_speed = 4
elif event.type == pg.KEYUP:
if event.key == pg.K_LEFT:
player.angle_speed = 0
elif event.key == pg.K_RIGHT:
player.angle_speed = 0
playersprite.update()
screen.fill((30, 30, 30))
playersprite.draw(screen)
pg.display.flip()
if __name__ == '__main__':
main()
pg.quit()
See How do I rotate an image around its center using PyGame?. You don't need the triangle at all. original_image needs to be the car:
class Player(pg.sprite.Sprite):
def __init__(self, pos=(420, 420)):
super(Player, self).__init__()
self.original_image = pg.image.load("car.png").convert_alpha()
self.image = self.original_image
self.rect = self.image.get_rect(center=pos)
self.mask = pg.mask.from_surface(self.image)
self.position = Vector2(pos)
self.direction = Vector2(1, 0) # A unit vector pointing rightward.
self.speed = 2
self.angle_speed = 0
self.angle = 0
I am stuck on how to write my collision function in my player class. Also should I put my collision check function in my player class or should it be in my bullet class? I honestly don't know. I mean common sense says my bullet should have the collision check function in it, just because I want the top of my bullet checking if it hits a falling cement block sprite, but I don't know.... I would appreciate an answer on how to code my collision function. This would really help me out. My collision function is right below my shoot function in my player class.
My code:
import pygame
pygame.init()
#screen settings
WIDTH = 1000
HEIGHT = 400
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("AutoPilot")
screen.fill((255, 255, 255))
#fps
FPS = 120
clock = pygame.time.Clock()
#load images
bg = pygame.image.load('background/street.png').convert_alpha() # background
bullets = pygame.image.load('car/bullet.png').convert_alpha()
debris_img = pygame.image.load('debris/cement.png')
#define game variables
shoot = False
#player class
class Player(pygame.sprite.Sprite):
def __init__(self, scale, speed):
pygame.sprite.Sprite.__init__(self)
self.bullet = pygame.image.load('car/bullet.png').convert_alpha()
self.bullet_list = []
self.speed = speed
#self.x = x
#self.y = y
self.moving = True
self.frame = 0
self.flip = False
self.direction = 0
#load car
self.images = []
img = pygame.image.load('car/car.png').convert_alpha()
img = pygame.transform.scale(img, (int(img.get_width()) * scale, (int(img.get_height()) * scale)))
self.images.append(img)
self.image = self.images[0]
self.rect = self.image.get_rect()
self.update_time = pygame.time.get_ticks()
self.movingLeft = False
self.movingRight = False
self.rect.x = 465
self.rect.y = 325
#draw car to screen
def draw(self):
screen.blit(self.image, (self.rect.centerx, self.rect.centery))
#move car
def move(self):
#reset the movement variables
dx = 0
dy = 0
#moving variables
if self.movingLeft and self.rect.x > 33:
dx -= self.speed
self.flip = True
self.direction = -1
if self.movingRight and self.rect.x < 900:
dx += self.speed
self.flip = False
self.direction = 1
#update rectangle position
self.rect.x += dx
self.rect.y += dy
#shoot
def shoot(self):
bullet = Bullet(self.rect.centerx + 18, self.rect.y + 30, self.direction)
bullet_group.add(bullet)
#def collision(self):
#write code here
#bullet class
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y, direction):
pygame.sprite.Sprite.__init__(self)
self.speed = 5
self.image = bullets
self.rect = self.image.get_rect()
self.rect.center = (x,y)
self.direction = direction
def update(self):
self.rect.centery -= self.speed
#check if bullet has gone off screen
if self.rect.top < 1:
self.kill()
#debris class
class Debris(pygame.sprite.Sprite):
def __init__(self, x, y, scale, speed):
pygame.sprite.Sprite.__init__(self)
self.scale = scale
self.x = x
self.y = y
self.speed = speed
self.vy = 0
self.on_ground = True
self.move = True
self.health = 4
self.max_health = self.health
self.alive = True
#load debris
self.image = debris_img
self.rect = self.image.get_rect()
self.rect.center = (x,y)
######################CAR/DEBRIS##########################
player = Player(1,5)
debris = Debris(300,15,1,5)
##########################################################
#groups
bullet_group = pygame.sprite.Group()
debris_group = pygame.sprite.Group()
debris_group.add(debris)
#game runs here
run = True
while run:
#draw street
screen.blit(bg, [0, 0])
#update groups
bullet_group.update()
bullet_group.draw(screen)
debris_group.update()
debris_group.draw(screen)
#draw car
player.draw()
player.move()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#check if key is down
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
run = False
if event.key == pygame.K_a:
player.movingLeft = True
if event.key == pygame.K_d:
player.movingRight = True
if event.key == pygame.K_SPACE:
player.shoot()
shoot = True
#check if key is up
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
player.movingLeft = False
if event.key == pygame.K_d:
player.movingRight = False
#update the display
pygame.display.update()
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
I suggest reading How do I detect collision in pygame?. Use pygame.sprite.spritecollide() for the collision detection. Set the dokill argument True. So the bullets gat automatically destroyed.
The following code is base on one of your previous questions: Check collision of bullet sprite hitting cement block sprite
class Car(pygame.sprite.Sprite):
# [...]
def collision(self, debris_group):
for debris in debris_group:
if pygame.sprite.spritecollide(debris, bullet_group, True):
debris.health -= 1
if debris.health <= 0:
debris.kill()
I was confused about how to make the user's car be visible on top of the background. At the moment, when you move the car the track and car move as they should, but the car is under the racetrack. I have tried different blitting orders and i attempted the LayeredUpdates function but it didn't help. I may have been doing it wrong as i am very new to python/pygame. So i would like to know how to get the car to be driving on the track.
Thank you
import math
import random
import pygame
pygame.mixer.pre_init(44100,16,2,4096)
pygame.init()
screen = pygame.display.set_mode((1280, 800))
rect = screen.get_rect()
clock = pygame.time.Clock()
#music
pygame.mixer.music.load("Wice.mp3")
pygame.mixer.music.set_volume(0.5)
pygame.mixer.music.play(-1)
WHITE = pygame.Color('white')
VEHICLE1 = pygame.Surface((40, 70), pygame.SRCALPHA)
VEHICLE1.fill((130, 180, 20))
#blitting car onto 'rectangle car'
VEHICLE1 = pygame.image.load("YellowLambo.png")
screen.blit(VEHICLE1,(0,0))
pygame.display.update()
VEHICLE2 = pygame.Surface((40, 70), pygame.SRCALPHA)
VEHICLE2.fill((200, 120, 20))
#blitting computer's car
VEHICLE2 = pygame.image.load("RedLambo.png")
screen.blit(VEHICLE2,(0,0))
BACKGROUND = pygame.Surface((1280, 800))
BACKGROUND.fill((127, 69, 2))
BACKGROUND = pygame.image.load("track1.png").convert()
screen.blit(BACKGROUND,(0,0))
pygame.display.update()
class Entity(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
class VehicleSprite(Entity):
MAX_FORWARD_SPEED = 10
MAX_REVERSE_SPEED = 2
ACCELERATION = 0.05
TURN_SPEED = 0.000000000001
def __init__(self, image, position):
Entity.__init__(self)
self.src_image = image
self.image = image
self.rect = self.image.get_rect(center=position)
self.position = pygame.math.Vector2(position)
self.velocity = pygame.math.Vector2(0, 0)
self.speed = self.direction = 0
self.k_left = self.k_right = self.k_down = self.k_up = 0
def update(self, time):
# SIMULATION
self.speed += self.k_up + self.k_down
# To clamp the speed.
self.speed = max(-self.MAX_REVERSE_SPEED,
min(self.speed, self.MAX_FORWARD_SPEED))
# Degrees sprite is facing (direction)
self.direction += (self.k_right + self.k_left)
rad = math.radians(self.direction)
self.velocity.x = -self.speed*math.sin(rad)
self.velocity.y = -self.speed*math.cos(rad)
self.position += self.velocity
self.image = pygame.transform.rotate(self.src_image, self.direction)
self.rect = self.image.get_rect(center=self.position)
class Background(pygame.sprite.Sprite):
def __init__(self, image, location):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect = self.image.get_rect(topleft=location)
def game_loop():
bike = VehicleSprite(VEHICLE1, rect.center)
pygame.sprite.LayeredUpdates.move_to_front
ball = VehicleSprite(VEHICLE2, rect.center)
bike_group = pygame.sprite.Group(bike)
ball_group = pygame.sprite.Group(ball)
all_sprites = pygame.sprite.Group(bike_group, ball_group)
background = Background(BACKGROUND, [0, 0])
camera = pygame.math.Vector2(0, 0)
done = False
while not done:
time = clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
# Bike Input (Player 1)
if event.key == pygame.K_d:
bike.k_right = -5
elif event.key == pygame.K_a:
bike.k_left = 5
elif event.key == pygame.K_w:
bike.k_up = 2
elif event.key == pygame.K_s:
bike.k_down = -2
elif event.key == pygame.K_ESCAPE:
done = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d:
bike.k_right = 0
elif event.key == pygame.K_a:
bike.k_left = 0
elif event.key == pygame.K_w:
bike.k_up = 0
elif event.key == pygame.K_s:
bike.k_down = 0
camera -= bike.velocity
all_sprites.update(time)
screen.fill(WHITE)
screen.blit(background.image, background.rect)
for sprite in all_sprites:
screen.blit(background.image, background.rect.topleft+camera)
screen.blit(sprite.image, sprite.rect.topleft+camera)
pygame.display.flip()
game_loop()
pygame.quit()
Look at these lines:
screen.blit(background.image, background.rect)
for sprite in all_sprites:
screen.blit(background.image, background.rect.topleft+camera)
screen.blit(sprite.image, sprite.rect.topleft+camera)
For each sprite you blit to the screen, you blit the background image again.
I guess you want something like:
screen.blit(background.image, background.rect.topleft+camera)
for sprite in all_sprites:
screen.blit(sprite.image, sprite.rect.topleft+camera)
drawing the background only once.
Not sure if it makes a difference but have you tried to replace:
for sprite in all_sprites:
screen.blit(background.image, background.rect.topleft+camera)
screen.blit(sprite.image, sprite.rect.topleft+camera)
with
all_sprites.draw(screen)
So, I'm a beginner to Python and Pygame and would like some help. I'm trying to make a game similar to Asteroids and I've made most of this program by looking around at other examples on the internet. However, I'm stuck on this problem: how do I get an enemy sprite to follow the player sprite? I've googled how to do so and tried implementing the same thing on my code but the sprite just stays in one place and doesn't follow the player. I've used the vector stuff to create the player sprite and I still barely understand how that works. I'm sort of on a tight schedule so I don't have time to thoroughly understand this stuff but I intend to later. Sorry if I haven't explained my code properly but I'm still trying to understand how Pygame works and most of this code is basically just copied.
import random, math, pygame, time, sys
from pygame.locals import *
from pygame.math import Vector2
######Setting up Variables
class settings:
fps = 30
windowwidth = 590
windowheight = 332
class ship:
HEALTH = 3
SPEED = 4
SIZE = 25
class colours:
black = (0, 0, 0)
white = (255, 255, 255)
###########################
######################################################################################
class Player(pygame.sprite.Sprite):
def __init__(self,image_file , pos=(0,0)):
super(Player, self).__init__()
self.image = pygame.image.load(image_file)
self.image = pygame.transform.scale(self.image, (25,25))
self.original_image = self.image
self.rect = self.image.get_rect(center=pos)
self.position = Vector2(pos)
self.direction = Vector2(1, 0)
self.speed = 0
self.angle_speed = 0
self.angle = 0
def update(self):
if self.angle_speed != 0:
self.direction.rotate_ip(self.angle_speed)
self.angle += self.angle_speed
self.image = pygame.transform.rotate(self.original_image, -self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
self.position += self.direction * self.speed
self.rect.center = self.position
class Enemy(pygame.sprite.Sprite):
def __init__(self, image_file, pos=(0,0)):
super(Enemy, self).__init__()
self.image = pygame.image.load(image_file)
self.image = pygame.transform.scale(self.image, (25, 25))
self.original_image = self.image
self.rect = self.image.get_rect(center=pos)
self.speed = 1
def move_towards_player(self, Player):
dx, dy = self.rect.x - Player.rect.x, self.rect.y - Player.rect.y
dist = math.hypot(dx, dy)
dx, dy = dx/dist, dy/dist
self.rect.x += dx * self.speed
self.rect.y += dy * self.speed
class Background(pygame.sprite.Sprite):
def __init__(self, image_file, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
def main():
pygame.init()
screen = pygame.display.set_mode((settings.windowwidth, settings.windowheight))
pygame.display.set_caption('Final Game')
background = Background('space.jpg',[0,0])
global player, enemy
player = Player('SpaceShip.png',[200,100])
playersprite = pygame.sprite.RenderPlain((player))
enemy = Enemy('Enemy Hexagon.png',[300,150])
enemysprite = pygame.sprite.RenderPlain((enemy))
fpsClock = pygame.time.Clock()
intro = True
while intro == True:
myFont = pygame.font.SysFont('freesansbold.ttf', 75)
otherFont = pygame.font.SysFont('freesansbold.ttf', 30)
SurfaceFont = myFont.render("Space Destroyer", True, (colours.white))
SurfaceFont2 = otherFont.render("Press Space to Start", True, (colours.white))
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_SPACE:
intro= False
screen.blit(SurfaceFont,(50,50))
screen.blit(SurfaceFont2,(125,125))
pygame.display.flip()
screen.blit(background.image, background.rect)
while intro == False:
fpsClock.tick(settings.fps)
for event in pygame.event.get():
enemy.rect.x
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_UP:
player.speed += 4
if event.key == K_LEFT:
player.angle_speed = -4
if event.key == K_RIGHT:
player.angle_speed = 4
if player.position.y < 0:
player.position = (player.position.x ,332)
elif player.position.y > settings.windowheight:
player.position = (player.position.x, 0)
elif player.position.x < 0:
player.position = (590, player.position.y)
elif player.position.x > settings.windowwidth:
player.position = (0, player.position.y)
elif event.type == KEYUP:
if event.key == K_LEFT:
player.angle_speed = 0
if event.key == K_RIGHT:
player.angle_speed = 0
if event.key == K_UP:
player.speed = 0
screen.fill(colours.white)
screen.blit(background.image, background.rect)
enemysprite.draw(screen)
enemysprite.update()
playersprite.draw(screen)
playersprite.update()
pygame.display.update()
playersprite.update()
pygame.display.flip()
if __name__ == '__main__': main()
You never called move_towards_player. Try adding this:
...
enemysprite.draw(screen)
enemysprite.update()
playersprite.draw(screen)
playersprite.update()
enemy.move_towards_player(player)
...
I'm quite new to pygame and came across a bug that i just can't fix on my own. I'm trying to program a Flappy Bird game. The Problem is that the collision detection works, but it also messes with my sprites. If i manage to get past the first obstacle while playing, then the gap resets itself randomly. But the gap should always be the same, just on another position. If i remove the collision detection, it works perfectly fine. Any ideas?
import pygame
import random
randomy = random.randint(-150, 150)
class Bird(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((25,25))
self.image.fill((255,255,255))
self.rect = self.image.get_rect()
self.rect.center = (100, 200)
self.velocity = 0.05
self.acceleration =0.4
def update(self):
self.rect.y += self.velocity
self.velocity += self.acceleration
if self.rect.bottom > 590:
self.velocity = 0
self.acceleration = 0
class Pipe1(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((85, 500))
self.image.fill((255, 255, 255))
self.rect = self.image.get_rect()
self.rect.center = (500, randomy)
self.randomyupdate = random.randint(-150, 150)
def update(self):
self.rect.x -= 2
if self.rect.x < -90:
self.randomyupdate = random.randint(-150, 150)
self.rect.center = (450, self.randomyupdate)
class Pipe2(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((85, 500))
self.image.fill((255, 255, 255))
self.rect = self.image.get_rect()
self.rect.center = (500, (randomy +640))
def update(self):
self.rect.x -= 2
self.randomyupdate = Pipe1.randomyupdate
if self.rect.x < -90:
self.rect.center = (450, (self.randomyupdate + 640))
pygame.init()
pygame.mouse.set_visible(1)
pygame.key.set_repeat(1, 30)
pygame.display.set_caption('Crappy Bird')
clock = pygame.time.Clock()
Bird_sprite = pygame.sprite.Group()
Pipe_sprite = pygame.sprite.Group()
Bird = Bird()
Pipe1 = Pipe1()
Pipe2 = Pipe2 ()
Bird_sprite.add(Bird)
Pipe_sprite.add(Pipe1)
Pipe_sprite.add(Pipe2)
def main():
running = True
while running:
clock.tick(60)
screen = pygame.display.set_mode((400,600))
screen.fill((0,0,0))
Bird_sprite.update()
Pipe_sprite.update()
Bird_sprite.draw(screen)
Pipe_sprite.draw(screen)
The line im talking about:
collide = pygame.sprite.spritecollideany(Bird, Pipe_sprite)
if collide:
running = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.event.post(pygame.event.Event(pygame.QUIT))
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
Bird.rect.y -= 85
Bird.velocity = 0.05
Bird.acceleration = 0.4
Bird.rect.y += Bird.velocity
Bird.velocity += Bird.acceleration
pygame.display.flip()
if __name__ == '__main__':
main()
This has nothing to do with the collision detection, it has to do with the order of the sprites in the sprite group which can vary because sprite groups use dictionaries internally which are unordered (in Python versions < 3.6). So if the Pipe1 sprite comes first in the group, the game will work correctly, but if the Pipe2 sprite comes first, then its update method is also called first and the previous randomyupdate of Pipe1 is used to set the new centery coordinate of the sprite.
To fix this you could either turn the sprite group into an ordered group, e.g.
Pipe_sprite = pygame.sprite.OrderedUpdates()
or update the rect of Pipe2 each frame,
def update(self):
self.rect.x -= 2
self.rect.centery = Pipe1.randomyupdate + 640
if self.rect.x < -90:
self.rect.center = (450, Pipe1.randomyupdate + 640)
Also, remove the global randomy variable and always use the randomyupdate attribute of Pipe1.