Pygame, trouble with collisions - python

I have been trying to create a game form scratch in Python using Pygame. I followed a tutorial for the most part and have hit a wall. The game is a simple platformer and I'm having trouble adding in collisions. I have looked at many other examples but cant seem to find where abouts to add in the pygame.sprite.collide_rect command and how to get it to stop the players y velocity so that he stops ontop of a platform. Any help would be greatly appreciated! Thanks.
The code
import random
import pygame as pg
pg.init()
icon = pg.image.load("soldier.png")
pg.display.set_icon(icon)
backgroundimage = pg.image.load("background.png")
FPS = 50
Width = 512
Height = 384
Red = (255, 0, 0)
#vec = pg.math.Vector2
class platform(pg.sprite.Sprite):
def __init__(self, x, y):
pg.sprite.Sprite.__init__(self)
self.image = pg.image.load("plat.png")
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
class Player(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.image.load("Spaceman.png")
self.rect = self.image.get_rect()
self.rect.center = (Width / 2, Height / 2)
self.vx = 0
self.vy = 0
#self.pos = vec(Width / 2, Height / 2)
self.acc = 0.2
def update(self):
self.vy = self.vy + self.acc
self.vx = 0
#self.acc = vec(0, 0.5)
keys = pg.key.get_pressed()
if keys[pg.K_SPACE]:
while self.vy > 0:
self.vy = -5 + self.acc
if keys[pg.K_LEFT]:
self.vx = -5
self.image = pg.image.load("Spaceman2.png")
if keys[pg.K_RIGHT]:
self.vx = 5
self.image = pg.image.load("Spaceman.png")
self.rect.x += self.vx
self.rect.y += self.vy
if self.rect.left > Width:
self.rect.right = 0
if self.rect.right < 0:
self.rect.left = Width
class Game:
def __init__(self):
pg.init()
pg.mixer.init()
self.screen = pg.display.set_mode((Width,Height))
pg.display.set_caption("OH NOOOO")
self.clock = pg.time.Clock()
self.running = True
def new(self):
self.all_sprites = pg.sprite.Group()
self.platforms = pg.sprite.Group()
self.soldier = pg.sprite.Group()
self.player = Player()
self.all_sprites.add(self.player)
self.soldier.add(self.player)
p1 = platform(200, 200)
self.all_sprites.add(p1)
self.platforms.add(p1)
self.run()
def run(self):
self.playing = True
while self.playing:
self.clock.tick(FPS)
self.events()
self.update()
self.draw()
def update(self):
self.screen.blit(backgroundimage,[0,0])
self.all_sprites.update()
def events(self):
for event in pg.event.get():
if event.type == pg.QUIT:
if self.playing:
self.playing = False
self.running = False
def draw(self):
self.all_sprites.draw(self.screen)
pg.display.flip()
def show_start_screen(self):
pass
def show_go_screen(self):
pass
g = Game()
g.show_start_screen()
while g.running:
g.new()
g.show_go_screen()
pg.quit()
This is all of the code so far and I've made three groups within this code; all_sprites, soldier and platforms but cant figure out how to make soldier and platforms groups collide. Any help is greatly appreciated thanks!

Use pygame.sprite.groupcollide() to detect the collision of pygame.sprite.Sprite objects in 2 separate pygame.sprite.Groups:
if pygame.sprite.groupcollide(self.soldier, self.platforms, False, Fasle):
print("hit")

Related

Moving forward after angle change. Pygame

I've been working on this project about tanks (based on game Tank Trouble) and I'm wondering how I can move forward after I change angle of the sprite. Also if you know how I can make my bullets ricochet from the walls. I will really appreciate any help given. Thank you!
Here is my tank and bullet:
Here is code of the game:
import sys
import pygame
class Game:
def __init__(self):
self.run = True
self.screen_width = 1060
self.screen_height = 798
self.image = pygame.image.load("sprites/background/background1.png")
self.image = pygame.transform.scale(self.image, (self.screen_width, self.screen_height))
self.screen = pygame.display.set_mode((self.screen_width, self.screen_height))
# all_sprites is used to update and draw all sprites together.
self.all_sprites = pygame.sprite.Group()
# for collision detection with enemies.
self.bullet_group = pygame.sprite.Group()
self.tank = Tank()
self.all_sprites.add(self.tank)
bullet = Bullet(self.tank)
self.bullet_group.add(bullet)
self.all_sprites.add(bullet)
def handle_events(self):
keys = pygame.key.get_pressed()
self.tank.handle_events()
if keys[pygame.K_UP]:
self.tank.rect.centery -= 5
if keys[pygame.K_DOWN]:
self.tank.rect.centery += 5
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.run = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
self.run = False
if event.key == pygame.K_SPACE:
bullet = Bullet(self.tank)
self.bullet_group.add(bullet)
self.all_sprites.add(bullet)
def update(self):
# Calls `update` methods of all contained sprites.
self.all_sprites.update()
def draw(self):
self.screen.blit(self.image, (0, 0))
self.all_sprites.draw(self.screen) # Draw the contained sprites.
pygame.display.update()
class Tank(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("sprites/player/player_tank.png")
self.org_image = self.image.copy()
# A nicer way to set the start pos with `get_rect`.
self.rect = self.image.get_rect(center=(70, 600))
self.angle = 0
self.direction = pygame.Vector2(1, 0)
self.pos = pygame.Vector2(self.rect.center)
def handle_events(self):
pressed = pygame.key.get_pressed()
if pressed[pygame.K_LEFT]:
self.angle += 3
if pressed[pygame.K_RIGHT]:
self.angle -= 3
self.direction = pygame.Vector2(1, 0).rotate(-self.angle)
self.image = pygame.transform.rotate(self.org_image, self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
class Bullet(pygame.sprite.Sprite):
def __init__(self, tank):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("sprites/bullet/bullet.png")
self.image = pygame.transform.scale(self.image, (16, 16))
self.rect = self.image.get_rect()
self.rect.centerx = tank.rect.centerx + 3 # How much pixels from tank turret on x axis
self.rect.centery = tank.rect.centery - 25 # How much pixels from tank turret on y axis
def update(self):
self.rect.y -= 10 # Move up 10 pixels per frame.
def main():
pygame.init()
pygame.display.set_caption('Tank Game')
clock = pygame.time.Clock()
game = Game()
while game.run:
game.handle_events()
game.update()
game.draw()
clock.tick(60)
if __name__ == '__main__':
main()
pygame.quit()
sys.exit()
To move the tank in the direction which is faced, wirte a method, that computes a direction vector, dependent on an velocity argument and the self.angle attribute. The nagle and the velocity define a vector by Polar coordinats.
Add the vector to it's current position (self.pos). Finally update the self.rect attribute by the position:
class Tank(pygame.sprite.Sprite):
# [...]
def move(self, velocity):
direction = pygame.Vector2(0, velocity).rotate(-self.angle)
self.pos += direction
self.rect.center = round(self.pos[0]), round(self.pos[1])
Invoke the method when up or down is pressed:
class Game:
# [...]
def handle_events(self):
# [...]
if keys[pygame.K_UP]:
self.tank.move(-5)
if keys[pygame.K_DOWN]:
self.tank.move(5)
The movement direction of the bullets can be computed similar:
class Bullet(pygame.sprite.Sprite):
def __init__(self, tank):
#[...]
self.rect = self.image.get_rect()
self.angle = tank.angle
self.pos = pygame.Vector2(tank.pos)
self.rect.center = round(self.pos.x), round(self.pos.y)
self.direction = pygame.Vector2(0, -10).rotate(-self.angle)
def update(self):
self.pos += self.direction
self.rect.center = round(self.pos[0]), round(self.pos[1])
To make the bullet bounce, you have to reflect the direction when the bullet hits a border:
class Bullet(pygame.sprite.Sprite):
# [...]
def update(self):
self.pos += self.direction
self.rect.center = round(self.pos.x), round(self.pos.y)
if self.rect.left < 0:
self.direction.x *= -1
self.rect.left = 0
self.pos.x = self.rect.centerx
if self.rect.right > 1060:
self.direction.x *= -1
self.rect.right = 1060
self.pos.x = self.rect.centerx
if self.rect.top < 0:
self.direction.y *= -1
self.rect.top = 0
self.pos.y = self.rect.centery
if self.rect.bottom > 798:
self.direction.y *= -1
self.rect.right = 798
self.pos.y = self.rect.centery

How to shoot bullets from a character facing in direction of cursor in pygame?

In my game the problem is that bullets are coming only from one place i.e, from the center. As my player rotates in direction of cursor, I want the bullets to be shot from top of the player even if the player is rotated and travel in a straight line in the direction player is facing towards, As the player rotates in the direction of cursor.
As you can view here the the bullets are always in same direction and always come out of same place.
I tried to use getpos() method to get cursor position and tried to subtract from the player coordinates but failed to get the result.
I think the problem is within the def shoot(self) method of Rotator class, I need to get the coordinates spaceship's tip even when it is rotating all time.
import math
import random
import os
import pygame as pg
import sys
pg.init()
height=650
width=1200
os_x = 100
os_y = 45
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (os_x,os_y)
screen = pg.display.set_mode((width,height),pg.NOFRAME)
screen_rect = screen.get_rect()
background=pg.image.load('background.png').convert()
background = pg.transform.smoothscale(pg.image.load('background.png'), (width,height))
clock = pg.time.Clock()
running = True
class Mob(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.image.load('enemy.png').convert_alpha()
self.image = pg.transform.smoothscale(pg.image.load('enemy.png'), (33,33))
self.rect = self.image.get_rect()
self.rect.x = random.randrange(width - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 8)
self.speedx = random.randrange(-3, 3)
def update(self):
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.top > height + 10 or self.rect.left < -25 or self.rect.right > width + 20:
self.rect.x = random.randrange(width - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 8)
class Rotator(pg.sprite.Sprite):
def __init__(self, screen_rect):
pg.sprite.Sprite.__init__(self)
self.screen_rect = screen_rect
self.master_image = pg.image.load('spaceship.png').convert_alpha()
self.master_image = pg.transform.smoothscale(pg.image.load('spaceship.png'), (33,33))
self.image = self.master_image.copy()
self.rect = self.image.get_rect(center=[width/2,height/2])
self.delay = 10
self.timer = 0.0
self.angle = 0
self.distance = 0
self.angle_offset = 0
def get_angle(self):
mouse = pg.mouse.get_pos()
offset = (self.rect.centerx - mouse[0], self.rect.centery - mouse[1])
self.angle = math.degrees(math.atan2(*offset)) - self.angle_offset
old_center = self.rect.center
self.image = pg.transform.rotozoom(self.master_image, self.angle,1)
self.rect = self.image.get_rect(center=old_center)
self.distance = math.sqrt((offset[0] * offset[0]) + (offset[1] * offset[1]))
def update(self):
self.get_angle()
self.display = 'angle:{:.2f} distance:{:.2f}'.format(self.angle, self.distance)
self.dx = 1
self.dy = 1
self.rect.clamp_ip(self.screen_rect)
def draw(self, surf):
surf.blit(self.image, self.rect)
def shoot(self):
bullet = Bullet(self.rect.centerx, self.rect.centery)
all_sprites.add(bullet)
bullets.add(bullet)
class Bullet(pg.sprite.Sprite):
def __init__(self, x, y):
pg.sprite.Sprite.__init__(self)
self.image = pg.image.load('bullet.png').convert_alpha()
self.image = pg.transform.smoothscale(pg.image.load('bullet.png'), (10,10))
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
self.speedy = -8
def update(self):
self.rect.y += self.speedy
# kill if it moves off the top of the screen
if self.rect.bottom < 0:
self.kill()
all_sprites = pg.sprite.Group()
bullets = pg.sprite.Group()
mobs = pg.sprite.Group()
rotator = Rotator(screen_rect)
all_sprites.add(rotator)
for i in range(5):
m = Mob()
all_sprites.add(m)
mobs.add(m)
while running:
keys = pg.key.get_pressed()
for event in pg.event.get():
if event.type == pg.QUIT:
sys.exit()
pygame.quit()
if event.type == pg.MOUSEBUTTONDOWN:
rotator.shoot()
screen.blit(background, [0, 0])
all_sprites.update()
hits = pg.sprite.groupcollide(mobs, bullets, True, True)
for hit in hits:
m = Mob()
all_sprites.add(m)
mobs.add(m)
hits = pg.sprite.spritecollide(rotator, mobs, False)
if hits:
running = False
all_sprites.draw(screen)
clock.tick(60)
pg.display.update()
See Shooting a bullet in pygame in the direction of mouse and calculating direction of the player to shoot pygame.
Pass the mouse position to rotator.shoot(), when the mouse button is pressed:
if event.type == pg.MOUSEBUTTONDOWN:
rotator.shoot(event.pos)
Calculate the direction of from the rotator to the mouse position and pass it the constructor of the new bullet object:
def shoot(self, mousepos):
dx = mousepos[0] - self.rect.centerx
dy = mousepos[1] - self.rect.centery
if abs(dx) > 0 or abs(dy) > 0:
bullet = Bullet(self.rect.centerx, self.rect.centery, dx, dy)
all_sprites.add(bullet)
bullets.add(bullet)
Use pygame.math.Vector2 to store the current positon of the bullet and the normalized direction of the bullet (Unit vector):
class Bullet(pg.sprite.Sprite):
def __init__(self, x, y, dx, dy):
pg.sprite.Sprite.__init__(self)
self.image = pg.transform.smoothscale(pg.image.load('bullet.png').convert_alpha(), (10,10))
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.speed = 8
self.pos = pg.math.Vector2(x, y)
self.dir = pg.math.Vector2(dx, dy).normalize()
Calcualate the new position of the bullet in update() (self.pos += self.dir * self.speed) and update the .rect attribute by the new position.
.kill() the bullet when it leaves the screen. This can be checked by self.rect.colliderect():
class Bullet(pg.sprite.Sprite):
# [...]
def update(self):
self.pos += self.dir * self.speed
self.rect.center = (round(self.pos.x), round(self.pos.y))
if not self.rect.colliderect(0, 0, width, height):
self.kill()

Add() argument after * must be an iterable, not int Pygame

Hello I am new to pygame and I am trying to write a shmup game.
However I am always having this error:
TypeError: add() argument after * must be an iterable, not int
self.add(*group)
This is the traceback of the error:
File "C:/Users/Pygame/game.py", line 195, in
player.shoot()
File "C:/Users/Pygame/game.py", line 78, in shoot
bullet = Bullets(self.rect.center,self.angle)
File "C:/Users/Pygame/game.py", line 124, in init
super(Bullets,self).init(pos,angle)
This is the code I have written so far, it works well however when the user wants to shoot the error is being raised.
import os
import pygame
import random
import math
WIDTH = 480
HEIGHT = 600
FPS = 60
#colors:
WHITE = (255,255,255)
BLACK = (0,0,0)
GREEN = (0,250,0)
RED = (255,0,0)
BLUE = (0,0,255)
YELLOW = (255,255,0)
#setup assets
game_folder = os.path.dirname("C:/Users/PygameP/")
img_folder = os.path.join(game_folder,"img")
#intialise pygame
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH,HEIGHT))
clock = pygame.time.Clock()
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((50,40))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH/2
self.rect.bottom = HEIGHT-10
#controls the speed
self.angle = 0
self.orig_image = self.image
#self.rect = self.image.get_rect(center=pos)
def update(self):
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.angle -= 5
self.rotate()
if keystate[pygame.K_RIGHT]:
self.angle += 5
self.rotate()
def rotate(self):
self.image = pygame.transform.rotozoom(self.orig_image, self.angle, 1)
self.rect = self.image.get_rect(center=self.rect.center)
def shoot(self):
bullet = Bullets(self.rect.center,self.angle)
all_sprites.add(bullet)
bullets.add(bullet)
class Mob(pygame.sprite.Sprite):
def __init__(self):
super(Mob,self).__init__()
self.image = pygame.Surface((30,40))
self.image = meteor_img
self.image = pygame.transform.scale(meteor_img,(50,38))
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.radius = int(self.rect.width/2)
self.rect.x = random.randrange(0,WIDTH - self.rect.width)
self.rect.y = random.randrange(-100,-40)
self.speedy = random.randrange(1,8)
#updating the position of the sprite
def update(self):
self.rect.y += self.speedy
if self.rect.top > HEIGHT + 10:
self.rect.x = random.randrange(0,WIDTH - self.rect.width)
self.rect.y = random.randrange(-100,-40)
self.speedy = random.randrange(1,8)
class Bullets(pygame.sprite.Sprite):
def __init__(self,pos,angle):
super(Bullets,self).__init__(pos,angle)
# Rotate the image.
self.image = pygame.Surface((10,20))
self.image = bullet_img
self.image = pygame.transform.scale(bullet_img,(50,38))
self.image = pygame.transform.rotate(bullet_img, angle)
self.rect = self.image.get_rect()
speed = 5
self.velocity_x = math.cos(math.radians(-angle))*speed
self.velocity_y = math.sin(math.radians(-angle))*speed
#store the actual position
self.pos = list(pos)
def update(self):
self.pos[0] += self.velocity_x
self.pos[1] += self.velocity_y
self.rect.center = self.pos
if self.rect.bottom <0:
self.kill()
#load all game graphics
background = pygame.image.load(os.path.join(img_folder,"background.png")).convert()
background_rect = background.get_rect()
player_img = pygame.image.load(os.path.join(img_folder,"arrow.png")).convert()
bullet_img = pygame.image.load(os.path.join(img_folder,"bullet.png")).convert()
meteor_img = pygame.image.load(os.path.join(img_folder,"m.png")).convert()
#creating a group to store sprites to make it easier to deal with them
#every sprite we make goes to this group
all_sprites = pygame.sprite.Group()
mobs = pygame.sprite.Group()
bullets = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
for i in range(8):
m = Mob()
all_sprites.add(m)
mobs.add(m)
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.shoot()
#Update
all_sprites.update()
#checking if a bullet hits a mob
hits = pygame.sprite.groupcollide(mobs,bullets,True,True)
for hit in hits:
m = Mob()
all_sprites.add(m)
mobs.add(m)
hits = pygame.sprite.spritecollide(player,mobs, False,pygame.sprite.collide_circle)
#drawing the new sprites here
screen.fill(BLACK)
#show the background image
screen.blit(background,background_rect)
all_sprites.draw(screen)
pygame.display.flip()
pygame.quit()
Any comments?
You're passing the pos and the angle to the __init__ method of pygame.sprite.Sprite here,
super(Bullets,self).__init__(pos,angle)
but you can only pass sprite groups to which this sprite instance will be added. So just remove those arguments:
super(Bullets,self).__init__()

How to make a sprite move back and forth on a platform in pygame?

After about of hour of disaster and modification on my code, I can't seem to get my enemy sprite to move back and forth on a platform. So any help would be greatly appreciated :D
Test File, Crafted Super Fast....
import pygame, sys, os
GAME_TITLE = "GAME"
WINDOW_WIDTH, WINDOW_HEIGHT = 1280, 720
BLACK = (0, 0, 0)
BLUE = (0, 255, 0)
RED = (255, 0, 0)
FPS = 60
ENEMY_ACC = 0.3
ENEMY_FRICTION = -0.12
ENEMY_GRAVITY = 0.5
vec = pygame.math.Vector2
class Platform(pygame.sprite.Sprite):
def __init__(self, game, x, y, w, h):
pygame.sprite.Sprite.__init__(self)
self.game = game
self.group = self.game.platform_list
self.image = pygame.Surface((1280, 100))
self.rect = self.image.get_rect()
pygame.draw.rect(self.image, RED, (x, y, w, h))
class Enemy(pygame.sprite.Sprite):
def __init__(self, game, pos):
pygame.sprite.Sprite.__init__(self)
self.game = game
self.group = self.game.enemy_list
self.image = pygame.Surface((100, 100))
pygame.draw.rect(self.image, BLUE, (200, 200, 100, 100))
self.rect = self.image.get_rect()
self.pos = vec(pos)
self.rect.center = self.pos
self.vel = vec(0, 0)
self.acc = vec(0, 0)
self.direction = "R"
self.engage = False
def update(self):
hits = pygame.sprite.spritecollide(self, self.game.platform_list, False)
if hits:
plat_right = hits[0].rect.right
plat_left = hits[0].rect.left
self.pos.y = hits[0].rect.top
self.vel.y = 0
if self.direction == "R" and not self.engage:
if self.rect.right >= plat_right:
self.direction = "L"
self.acc.x = -ENEMY_ACC
if self.direction == "L" and not self.engage:
if self.rect.left <= plat_left:
self.direction = "R"
self.acc.x = -ENEMY_ACC
self.acc.x += self.vel.x * ENEMY_FRICTION
self.vel += self.acc
self.pos += self.vel + 0.5 * self.acc
self.rect.midbottom = self.pos
self.acc = vec(0, ENEMY_GRAVITY)
class Game:
def __init__(self):
pygame.init()
pygame.mixer.init()
pygame.font.init()
os.environ['SDL_VIDEO_CENTERED'] = '1'
pygame.display.set_caption(GAME_TITLE)
self.window = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
self.clock = pygame.time.Clock()
self.platform_list = pygame.sprite.Group()
self.enemy_list = pygame.sprite.Group()
def run(self):
enemy = Enemy(self, (200, 500))
self.enemy_list.add(enemy)
platform = Platform(self, 0, 620, 1280, 100)
self.platform_list.add(platform)
while True:
self.events()
self.update()
self.draw()
def events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
def update(self):
self.enemy_list.update()
def draw(self):
self.window.fill(BLACK)
self.platform_list.draw(self.window)
self.enemy_list.draw(self.window)
pygame.display.flip()
def main():
g = Game()
g.run()
if __name__ == "__main__":
main()
Here's an example without the acc attribute. Just accelerate the self.vel by adding the ENEMY_GRAVITY, update the self.pos and self.rect, then if it collides with the platform see if the right or left edge is reached and then just invert the velocity.
I've set the ENEMY_GRAVITY to 3 and call clock.tick(30) to limit the frame rate. The direction attribute doesn't seem to be necessary anymore.
class Enemy(pygame.sprite.Sprite):
def __init__(self, game, pos):
pygame.sprite.Sprite.__init__(self)
self.game = game
self.group = self.game.enemy_list
self.image = pygame.Surface((60, 60))
self.image.fill((30, 90, 200))
self.rect = self.image.get_rect(midbottom=pos)
self.pos = vec(pos)
self.vel = vec(3, 0)
self.engage = False
def update(self):
self.vel.y += ENEMY_GRAVITY
self.pos += self.vel
self.rect.midbottom = self.pos
hits = pygame.sprite.spritecollide(self, self.game.platform_list, False)
for plat in hits:
self.pos.y = plat.rect.top
self.rect.bottom = plat.rect.top
self.vel.y = 0
if self.vel.x > 0 and not self.engage:
if self.rect.right >= plat.rect.right:
self.vel = vec(-3, 0) # Reverse the horizontal velocity.
elif self.vel.x < 0 and not self.engage:
if self.rect.left <= plat.rect.left:
self.vel = vec(3, 0) # Reverse the horizontal velocity.

How would I make a group of sprites and randomly choose one?

this is my first post. I need to make a working game for my final project. Basically the idea is to have the character collide with an Item sprite and Have a random item display on the screen telling the player what the item is and where to take it.
#Initialize
import pygame
import random
pygame.init()
#Display
screen = pygame.display.set_mode((1180, 900))
class PaperBoy(pygame.sprite.Sprite):
def __init__(self,startY):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("paperboy.gif")
self.rect = self.image.get_rect()
self.image = self.image.convert()
self.rect.centery = startY
self.dx= 300
self.dy= 300
def update(self):
#adjust x/y to dx/dy
self.rect.centerx = self.rect.centerx+self.dx
self.rect.centery = self.rect.centery+self.dy
#check Boundaries
#Check right
if self.rect.centerx >= 670:
self.rect.centerx =670
#Check left
elif self.rect.centerx <= 220:
self.rect.centerx = 220
#Check Bottom
if self.rect.centery >= 700:
self.rect.centery = 700
#Check Top
elif self.rect.centery <= 200:
self.rect.centery = 200
def moveUp(self):
self.dx=0
self.dy=-5
def moveDown(self):
self.dx =0
self.dy =5
def moveLeft(self):
self.dx =-5
self.dy = 0
def moveRight(self):
self.dx =5
self.dy =0
"""
mousex, mousey = pygame.mouse.get_pos()
self.rect.centery = mousey
#Check X boundary.
if mousex >= 670:
self.rect.right = 670
elif mousex <= 210:
self.rect.left = 210
else:
self.rect.centerx = mousex
#Check Y boundary.
if mousey >= 670:
self.rect.top = 670
elif mousey >= 250:
self.rect.top = 250
if mousex >= 250 and mousey >= 220:
self.rect.left = 250
self.rect.top = 670
else:
self.rect.centery = mousey
"""
class Parcel(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("parcel.png")
self.rect = self.image.get_rect()
self.image = self.image.convert()
def update(self):
self.rect.center = (200,600)
"""(random.randint(300,800)),(random.randint(300,800))"""
"""
================================HUD======================================
"""
#Green Y
class ItemHUD(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("itemhud.png")
self.rect = self.image.get_rect()
self.image = self.image.convert()
def update(self):
self.rect.center = (950,200)
#Red A
class WhereHUD(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("where.png")
self.rect = self.image.get_rect()
self.image = self.image.convert()
def update(self):
self.rect.center = (950, 350)
#Small Green
class TimeHUD(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("timehud.png")
self.rect = self.image.get_rect()
self.image = self.image.convert()
def update(self):
self.rect.center = (915, 850)
#Yellow
class GoldHUD(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("gold.png")
self.rect = self.image.get_rect()
self.image = self.image.convert()
def update(self):
self.rect.center = (915, 700)
"""
=================================HUD OBJECTS==============================
"""
"""
------------------------------------MAIN-----------------------------------
"""
def main():
pygame.display.set_caption("A Link to the Parcel")
background = pygame.image.load('village.png').convert()
allSprites=pygame.sprite.Group()
parcel = Parcel()
#Heads up Display
itemHud = ItemHUD()
timeHud = TimeHUD()
goldHud = GoldHUD()
whereHud = WhereHUD()
#Player
paperboy = PaperBoy(200)
#Sprites added to AllSprites Group
allSprites.add(paperboy)
allSprites.add(parcel)
allSprites.add(itemHud)
allSprites.add(timeHud)
allSprites.add(goldHud)
allSprites.add(whereHud)
font = pygame.font.Font(None, 25)
goldSack = 0
clock = pygame.time.Clock()
keepGoing = True
while keepGoing:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
keepGoing = False
elif event.type == pygame.KEYUP:
if event.key==pygame.K_UP:
paperboy.moveUp()
elif event.key==pygame.K_DOWN:
paperboy.moveDown()
elif event.key==pygame.K_LEFT:
paperboy.moveLeft()
elif event.key==pygame.K_RIGHT:
paperboy.moveRight()
fontTitle = font.render("A Link to the Parcel", True, (255,255,255,))
screen.blit(background, (0, 0))
screen.blit(fontTitle, [925,100])
allSprites.clear(screen, background,)
allSprites.update()
allSprites.draw(screen)
pygame.display.flip()
pygame.quit()
if __name__ == "__main__":
main()
If I understand what you mean, you have a bunch of Sprite types, and you want to choose one at random. To do that, just put them all in a list, use random.choice to pick one, and then instantiate it. Like this:
class OneKindOfParcel(Parcel): # etc.
class AnotherKindOfParcel(Parcel): # etc.
class AThirdKindOfParcel(Parcel): # etc.
parcels = [OneKindOfParcel, AnotherKindOfParcel, AThirdKindOfParcel]
# … later …
parceltype = random.choice(parcels)
parcel = parceltype()
allSprites.add(parcel)
You probably want to give it a location, and display something about its name and location, and so on, but I think you know how to do all that.
Quick and dirty is a list of items and then use random.choice from the random module.

Categories