How to get camera following a top down car in pygame - python

new to pygame and game programming in general, just wondered how I could get a camera to follow a car (nothing fancy) in a top down car game - think Micro Machines! I'm using Python 3.6, and have got a bike rotating, and moving around. I've kept the code here shorter but I do have a static image for reference if the camera worked!
Here's what I have:
import pygame, math, sys, random
from pygame.locals import *
display_width = 1280
display_height = 800
# Sets size of screen
screen = pygame.display.set_mode((display_width, display_height))
# Initialises clock
clock = pygame.time.Clock()
# Colours
white = (255,255,255)
black = (0,0,0)
class Entity(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
class VehicleSprite(Entity):
# Creates a vehicle class
MAX_FORWARD_SPEED = 10
MAX_REVERSE_SPEED = 2
ACCELERATION = 0.05
TURN_SPEED = 0.000000000001
def __init__(self, image, position):
Entity.__init__(self)
# Creates object instance off
pygame.sprite.Sprite.__init__(self)
self.src_image = pygame.image.load(image)
self.position = position
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)
if self.speed > self.MAX_FORWARD_SPEED:
self.speed = self.MAX_FORWARD_SPEED
if self.speed < -self.MAX_REVERSE_SPEED:
self.speed = -self.MAX_REVERSE_SPEED
# Degrees sprite is facing (direction)
self.direction += (self.k_right + self.k_left)
x, y = self.position
rad = self.direction * math.pi / 180
x += -self.speed*math.sin(rad)
y += -self.speed*math.cos(rad)
self.position = (x, y)
self.image = pygame.transform.rotate(self.src_image, self.direction)
self.rect = self.image.get_rect()
self.rect.center = self.position
class Background(pygame.sprite.Sprite):
def __init__(self, image_file, location):
pygame.sprite.Sprite.__init__(self) #call Sprite initializer
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
rect = screen.get_rect()
# Background
BackGround = Background('/home/pi/gametuts/images/backgrounds/bkg_img.png', [0, 0])
# Bike image load
bike = VehicleSprite('/home/pi/gametuts/images/BikePixelBig.png', rect.center)
bike_group = pygame.sprite.RenderPlain(bike)
# Ball image load
ball = VehicleSprite('/home/pi/gametuts/images/ironball.png', rect.center)
ball_group = pygame.sprite.RenderPlain(ball)
# Main game loop
def game_loop():
while 1:
#USER INPUT
# Sets frame rate
time = clock.tick(60)
for event in pygame.event.get():
if not hasattr(event, 'key'): continue
down = event.type == KEYDOWN
# Bike Input (Player 1)
if event.key == K_d: bike.k_right = down * -5
elif event.key == K_a: bike.k_left = down * 5
elif event.key == K_w: bike.k_up = down * 2
elif event.key == K_s: bike.k_down = down * -2
# Quit
elif event.key == K_ESCAPE: sys.exit(0)
#RENDERING
# Game background
screen.fill(white)
screen.blit(BackGround.image, BackGround.rect)
# Bike render
bike_group.update(time)
bike_group.draw(screen)
ball_group.update(time)
ball_group.draw(screen)
pygame.display.flip()
game_loop()
pygame.quit()
quit()
Thanks in advance!

The simplest way to implement a camera is to use a pygame.math.Vector2 as the camera, subtract the player velocity from it each frame and add it to the position of all game elements during the blitting.
import pygame as pg
from pygame.math import Vector2
class Player(pg.sprite.Sprite):
def __init__(self, pos, walls, *groups):
super().__init__(*groups)
self.image = pg.Surface((30, 50))
self.image.fill(pg.Color('dodgerblue'))
self.rect = self.image.get_rect(center=pos)
self.vel = Vector2(0, 0)
self.pos = Vector2(pos)
self.walls = walls
self.camera = Vector2(0, 0)
def update(self):
self.camera -= self.vel # Change the camera pos if we're moving.
# Horizontal movement.
self.pos.x += self.vel.x
self.rect.centerx = self.pos.x
# Change the rect and self.pos coords if we touched a wall.
for wall in pg.sprite.spritecollide(self, self.walls, False):
if self.vel.x > 0:
self.rect.right = wall.rect.left
elif self.vel.x < 0:
self.rect.left = wall.rect.right
self.pos.x = self.rect.centerx
self.camera.x += self.vel.x # Also move the camera back.
# Vertical movement.
self.pos.y += self.vel.y
self.rect.centery = self.pos.y
for wall in pg.sprite.spritecollide(self, self.walls, False):
if self.vel.y > 0:
self.rect.bottom = wall.rect.top
elif self.vel.y < 0:
self.rect.top = wall.rect.bottom
self.pos.y = self.rect.centery
self.camera.y += self.vel.y
class Wall(pg.sprite.Sprite):
def __init__(self, x, y, w, h, *groups):
super().__init__(*groups)
self.image = pg.Surface((w, h))
self.image.fill(pg.Color('sienna2'))
self.rect = self.image.get_rect(topleft=(x, y))
def main():
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
all_sprites = pg.sprite.Group()
walls = pg.sprite.Group()
for rect in ((100, 170, 90, 20), (200, 100, 20, 140),
(400, 60, 150, 100), (300, 470, 150, 100)):
walls.add(Wall(*rect))
all_sprites.add(walls)
player = Player((320, 240), walls, all_sprites)
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.KEYDOWN:
if event.key == pg.K_d:
player.vel.x = 5
elif event.key == pg.K_a:
player.vel.x = -5
elif event.key == pg.K_w:
player.vel.y = -5
elif event.key == pg.K_s:
player.vel.y = 5
elif event.type == pg.KEYUP:
if event.key == pg.K_d and player.vel.x > 0:
player.vel.x = 0
elif event.key == pg.K_a and player.vel.x < 0:
player.vel.x = 0
elif event.key == pg.K_w and player.vel.y < 0:
player.vel.y = 0
elif event.key == pg.K_s and player.vel.y > 0:
player.vel.y = 0
all_sprites.update()
screen.fill((30, 30, 30))
for sprite in all_sprites:
# Add the player's camera offset to the coords of all sprites.
screen.blit(sprite.image, sprite.rect.topleft+player.camera)
pg.display.flip()
clock.tick(30)
if __name__ == '__main__':
pg.init()
main()
pg.quit()
Edit: Here's your code example with a camera. I've also tried to improve a few more things, for example the max(min(...)) trick to clamp the speed value. I'm not sure if the movement works as you want, but you can of course adjust it yourself. (I'd probably make even more modifications to the update method.)
import math
import random
import pygame
pygame.init()
screen = pygame.display.set_mode((1280, 800))
rect = screen.get_rect()
clock = pygame.time.Clock()
WHITE = pygame.Color('white')
# Load images globally and reuse them in your program.
# Also use the `.convert()` or `.convert_alpha()` methods after
# loading the images to improve the performance.
VEHICLE1 = pygame.Surface((40, 70), pygame.SRCALPHA)
VEHICLE1.fill((130, 180, 20))
VEHICLE2 = pygame.Surface((40, 70), pygame.SRCALPHA)
VEHICLE2.fill((200, 120, 20))
BACKGROUND = pygame.Surface((1280, 800))
BACKGROUND.fill((30, 30, 30))
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():
background = Background(BACKGROUND, [0, 0])
bike = VehicleSprite(VEHICLE1, rect.center)
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)
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(sprite.image, sprite.rect.topleft+camera)
pygame.display.flip()
game_loop()
pygame.quit()

Related

Pygame ball movement flickering

I have been trying to make a basic Pygame code where the ball bounces around the screen and off your paddle. The paddle movement is smooth, but the ball flickers and is pretty choppy. Here is my complete code:
import pygame, sys
from pygame.locals import *
import random, time
pygame.init()
window = (800, 600)
background = (0, 0, 0)
back = pygame.Surface(window)
entity_color = (255, 255, 255)
x = 362.5
y = 550
ball_x = 387.5
ball_y = 50
width = 75
height = 25
clockobject = pygame.time.Clock()
screen = pygame.display.set_mode((window))
pygame.display.set_caption("Test Game")
class Ball(pygame.sprite.Sprite):
def __init__(self):
super(Ball, self).__init__()
self.surf = pygame.Surface((25, 25))
self.surf.fill((255, 255, 255))
self.rect = self.surf.get_rect()
self.dir_x = 1
self.dir_y = 1
self.speed = 2
def update(self):
global ball_x
global ball_y
if ball_x > 775:
ball_x = 775
ball.dir_x = -1
elif ball_x < 0:
ball_x = 0
ball.dir_x = 1
if ball_y < 0:
ball_y = 0
ball.dir_y = 1
elif ball_y > 600:
ball_y = 50
ball_x = 387.5
if ball_x <= x + 75 and ball_x >= x and ball_y <= y and ball_y >= y - 25:
ball.dir_y = -1
ball_x = ball_x + ball.speed * ball.dir_x
ball_y = ball_y + ball.speed * ball.dir_y
class Player(pygame.sprite.Sprite):
def __init__(self):
super(Player, self).__init__()
self.image_s = pygame.image.load("paddle.png")
self.image_b = self.image_s.get_rect()
self.surf = pygame.Surface((75, 25))
self.surf.fill((255, 255, 255))
self.rect = self.surf.get_rect()
def update(self):
global x
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
x = x - 5
elif keys[pygame.K_RIGHT]:
x = x + 5
def checkboundaries(self):
global x
if x > 725:
x = 725
if x < 0:
x = 0
ball = Ball()
player = Player()
waiting = True
while waiting:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
elif event.key == pygame.K_SPACE:
running = True
waiting = False
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
player.update()
ball.update()
player.checkboundaries()
screen.blit(back, (0,0))
screen.blit(player.surf, (x, y))
screen.blit(ball.surf, (ball_x, ball_y))
pygame.display.flip()
clockobject.tick(360)
pygame.quit()
sys.exit()
Is this because of something wrong in my code that is running slowly, or am I missing something?
If you are using pygame.sprite.Sprite, you should also use pygame.sprite.Group.
pygame.sprite.Group.draw() and pygame.sprite.Group.update() are methods which are provided by pygame.sprite.Group.
The latter delegates to the update method of the contained pygame.sprite.Sprites — you have to implement the method. See pygame.sprite.Group.update():
Calls the update() method on all Sprites in the Group. [...]
The former uses the image and rect attributes of the contained pygame.sprite.Sprites to draw the objects — you have to ensure that the pygame.sprite.Sprites have the required attributes. See pygame.sprite.Group.draw():
Draws the contained Sprites to the Surface argument. This uses the Sprite.image attribute for the source surface, and Sprite.rect. [...]
e.g.:
import pygame, sys
from pygame.locals import *
pygame.init()
clockobject = pygame.time.Clock()
screen = pygame.display.set_mode((800, 600))
back = pygame.Surface(screen.get_size())
pygame.display.set_caption("Test Game")
class Ball(pygame.sprite.Sprite):
def __init__(self):
super(Ball, self).__init__()
self.image = pygame.Surface((25, 25))
self.image.fill((255, 255, 255))
self.rect = self.image.get_rect(topleft = (387, 50))
self.dir_x = 1
self.dir_y = 1
self.speed = 2
def update(self):
if self.rect.x > 775:
self.rect.x = 775
self.dir_x = -1
elif self.rect.x < 0:
self.rect.x = 0
self.dir_x = 1
if self.rect.y < 0:
self.rect.y = 0
self.dir_y = 1
elif self.rect.y > 600:
self.rect.topleft = (387, 50)
if self.rect.colliderect(player.rect):
ball.dir_y = -1
self.rect.x += ball.speed * ball.dir_x
self.rect.y += ball.speed * ball.dir_y
class Player(pygame.sprite.Sprite):
def __init__(self):
super(Player, self).__init__()
self.image = pygame.Surface((75, 25))
self.image.fill((255, 255, 255))
self.rect = self.image.get_rect(topleft = (363, 550))
def update(self):
keys = pygame.key.get_pressed()
self.rect.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 5
self.rect.clamp_ip(screen.get_rect())
ball = Ball()
player = Player()
all_sprites = pygame.sprite.Group([ball, player])
started = False
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
elif event.key == pygame.K_SPACE:
started = True
screen.blit(back, (0,0))
if started:
all_sprites.update()
all_sprites.draw(screen)
pygame.display.flip()
clockobject.tick(100)
pygame.quit()
sys.exit()

I cant move my sprite unless I shoot first?

I'm developing a basic game, where you can move around and shoot projectiles to kill randomly spawned enemies, but if I boot the game and I try to move before I do anything else, the game crashes. If I shoot a projectile first, however, the game runs perfectly and I can move around without any problems, but I can't seem to figure out why this is.
import pygame
import random
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
#Classes
class Player(pygame.sprite.Sprite):
def __init__(self, filename, x, y):
super().__init__()
self.image = pygame.image.load(filename).convert()
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
self.change_x = 0
self.change_y = 0
self.walls = None
def changespeed(self, x, y):
self.change_x += x
self.change_y += y
def update(self):
self.rect.x += self.change_x
block_hit_list = pygame.sprite.spritecollide(self, self.walls, False)
for block in block_hit_list:
if self.change_x > 0:
self.rect.right = block.rect.left
else:
self.rect.left = block.rect.right
self.rect.y += self.change_y
block_hit_list = pygame.sprite.spritecollide(self, self.walls, False)
for block in block_hit_list:
if self.change_y > 0:
self.rect.bottom = block.rect.top
else:
self.rect.top = block.rect.bottom
class Wall(pygame.sprite.Sprite):
def __init__(self, x, y, width, height):
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(BLACK)
self.rect = self.image.get_rect()
self.rect.y = y
self.rect.x = x
class Enemy(pygame.sprite.Sprite):
def __init__(self, filename):
super().__init__()
self.image = pygame.image.load(filename).convert()
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
class ProjectileUp(pygame.sprite.Sprite):
def __init__(self, filename):
super().__init__()
self.image = pygame.image.load(filename).convert()
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
def update(self):
self.rect.y -= 5
class ProjectileDown(pygame.sprite.Sprite):
def __init__(self, filename):
super().__init__()
self.image = pygame.image.load(filename).convert()
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
def update(self):
self.rect.y += 5
class ProjectileLeft(pygame.sprite.Sprite):
def __init__(self, filename):
super().__init__()
self.image = pygame.image.load(filename).convert()
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
def update(self):
self.rect.x -= 5
class ProjectileRight(pygame.sprite.Sprite):
def __init__(self, filename):
super().__init__()
self.image = pygame.image.load(filename).convert()
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
def update(self):
self.rect.x += 5
# --- Create the window
#Initialise pygame
pygame.init()
#Window dimensions
screen_width = 1080
screen_height = 607
screen = pygame.display.set_mode([screen_width, screen_height])
#Window display name
pygame.display.set_caption('Labyrinth')
#Sprite Lists
all_sprite_list = pygame.sprite.Group()
block_list = pygame.sprite.Group()
wall_list = pygame.sprite.Group()
projectile_list = pygame.sprite.Group()
#Define game borders
wall = Wall(-32, 0, 10, 607)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(0 , -64, 1080, 10)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(1100, 0, 10, 607)
wall_list.add(wall)
all_sprite_list.add(wall)
wall = Wall(0 , 600, 1080, 10)
wall_list.add(wall)
all_sprite_list.add(wall)
#Create player sprite
player = Player("Isaac.png", 420, 150)
all_sprite_list = pygame.sprite.Group()
all_sprite_list.add(player)
player.walls = wall_list
#Create enemies
for i in range(7):
block = Enemy("Judas.png")
block.rect.x = random.randrange(50, 950)
block.rect.y = random.randrange(50, 450)
block_list.add(block)
all_sprite_list.add(block)
#Manage screen updates
clock = pygame.time.Clock()
#Load background image
background_position = [0, 0]
background_image = pygame.image.load("Floor.png").convert()
#Loop until game_exit
done = False
#---------- MAIN PROGRAM LOOP ----------#
while not done:
# --- Event processing
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
#Projectile spawn
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
projectile = ProjectileUp("LightningUp.png")
projectile.rect.x = player.rect.x+65
projectile.rect.y = player.rect.y
elif event.key == pygame.K_DOWN:
projectile = ProjectileDown("LightningDown.png")
projectile.rect.x = player.rect.x+65
projectile.rect.y = player.rect.y+100
elif event.key == pygame.K_LEFT:
projectile = ProjectileLeft("LightningLeft.png")
projectile.rect.x = player.rect.x+35
projectile.rect.y = player.rect.y+100
elif event.key == pygame.K_RIGHT:
projectile = ProjectileRight("LightningRight.png")
projectile.rect.x = player.rect.x+115
projectile.rect.y = player.rect.y+100
all_sprite_list.add(projectile)
projectile_list.add(projectile)
#Movement controls
if event.type == pygame.KEYDOWN:
if event.key == ord('a'):
player.changespeed(-7, 0)
elif event.key == ord('d'):
player.changespeed(7, 0)
elif event.key == ord('w'):
player.changespeed(0, -7)
elif event.key == ord('s'):
player.changespeed(0, 7)
elif event.type == pygame.KEYUP:
if event.key == ord('a'):
player.changespeed(7, 0)
elif event.key == ord('d'):
player.changespeed(-7, 0)
elif event.key == ord('w'):
player.changespeed(0, 7)
elif event.key == ord('s'):
player.changespeed(0, -7)
# --- Game logic
#Update sprites
all_sprite_list.update()
#Projectile mechanics
for projectile in projectile_list:
block_hit_list = pygame.sprite.spritecollide(projectile, block_list, True)
for block in block_hit_list:
projectile_list.remove(projectile)
#Determine if player hits enemy
blocks_hit_list = pygame.sprite.spritecollide(player, block_list, True)
#Call on background image
screen.blit(background_image, background_position)
# --- Draw the window
all_sprite_list.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
It's because your if/elif/else logic is messed up a bit. You have two paths for the KEYDOWN event. If the first event happens to be a movement command, your code runs through the projectile code first (without finding a valid projectile command) and then tries to reference a projectile object that doesn't exist. Try this instead:
#---------- MAIN PROGRAM LOOP ----------#
while not done:
# --- Event processing
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
projectile = None # initialize
if event.key == pygame.K_UP:
projectile = ProjectileUp("LightningUp.png")
projectile.rect.x = player.rect.x+65
projectile.rect.y = player.rect.y
elif event.key == pygame.K_DOWN:
projectile = ProjectileDown("LightningDown.png")
projectile.rect.x = player.rect.x+65
projectile.rect.y = player.rect.y+100
elif event.key == pygame.K_LEFT:
projectile = ProjectileLeft("LightningLeft.png")
projectile.rect.x = player.rect.x+35
projectile.rect.y = player.rect.y+100
elif event.key == pygame.K_RIGHT:
projectile = ProjectileRight("LightningRight.png")
projectile.rect.x = player.rect.x+115
projectile.rect.y = player.rect.y+100
elif event.key == ord('a'):
player.changespeed(-7, 0)
elif event.key == ord('d'):
player.changespeed(7, 0)
elif event.key == ord('w'):
player.changespeed(0, -7)
elif event.key == ord('s'):
player.changespeed(0, 7)
if projectile: # did we create a valid projectile?
all_sprite_list.add(projectile)
projectile_list.add(projectile)
elif event.type == pygame.KEYUP:
if event.key == ord('a'):
player.changespeed(7, 0)
elif event.key == ord('d'):
player.changespeed(-7, 0)
elif event.key == ord('w'):
player.changespeed(0, 7)
elif event.key == ord('s'):
player.changespeed(0, -7)

Pygame: bullets sticks to the screen

My problem is very simple. The bullets I fire sticks to the screen if I shoot fast. If I shoot slowly, they don't stick. Anyone have an idea how this phenomenon occurs?
screenshot of the bullets sticking to the screen
Below I have entered the code. I follow this default game flowchart:
I am curious about the origin of the problem. Is it the code or hardware?
import sys
import pygame
from pygame.sprite import Sprite
from pygame.sprite import Group
# pygame initializing
pygame.init()
#create the screen surface
screen = pygame.display.set_mode((800, 700))
class Color():
def __init__(self):
self.black = (0, 0, 0)
self.white = (255, 255, 255)
self.red = (255, 0, 0)
self.green = (0, 255, 0)
self.green_lambda = (10, 255, 150)
self.blue = (0, 0, 255)
# set up the colors
color = Color() # make an instance of this class - this makes some colors available
class Spaceship(Sprite):
"""
This class represents the Spaceship.
It derives from the "Sprite" class in Pygame.
"""
def __init__(self):
""" Constructor"""
# Call the parent class (Sprite) constructor
super().__init__()
width = 22
height = 32
self.screen = screen
self.image = pygame.Surface((width, height))
self.image.fill(color.black)
self.image.set_colorkey(color.black)
pygame.draw.polygon(self.image, color.green_lambda, [[10,0],[15,22],[20,30],[10,27],[0,30],[5,22]],2)
self.rect = self.image.get_rect()
self.screen_rect = self.screen.get_rect()
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
# As the rect method only take integers we store a
# This value is only used at the beginning, i.e. before the game loop starts
self.center_x = self.rect.centerx
self.center_y = self.rect.centery
class Bullet(Sprite):
"""
This class represents the bullets.
It derives from the "Sprite" class in Pygame.
"""
def __init__(self):
# Call the parent class (Sprite) constructor
super().__init__()
self.image = pygame.Surface((8,10))
self.image.fill(color.red)
self.image.set_colorkey((color.red))
pygame.draw.ellipse(self.image, color.green, [1, 0, 5, 8], 2)
self.rect = self.image.get_rect()
self.rect.centerx = defender.rect.centerx
self.rect.bottom = defender.rect.top
# def function to move the bullets
def update_pos(self):
self.rect.y -= bullet_speed
# create spaceship instance
defender = Spaceship()
# create group to store sprites in
all_sprites_list = Group()
all_sprites_list.add(defender)
ship_speed = 0.5
bullet_speed = 3
def run_game():
m_right = False
m_left = False
m_up = False
m_down = False
new_bullet = False
while True:
"""This is the user interaction section"""
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
sys.exit()
elif event.key == pygame.K_RIGHT:
m_right = True
elif event.key == pygame.K_LEFT:
m_left = True
elif event.key == pygame.K_UP:
m_up = True
elif event.key == pygame.K_DOWN:
m_down = True
elif event.key == pygame.K_SPACE:
new_bullet = Bullet()
#print(dir(new_bullet))
all_sprites_list.add(new_bullet)
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
m_right = False
elif event.key == pygame.K_LEFT:
m_left = False
elif event.key == pygame.K_UP:
m_up = False
elif event.key == pygame.K_DOWN:
m_down = False
"""Below is the game logic, which gets input from the user interaction
section and more"""
# Movement of spaceship depending on the flag boolean value and on screen width and height
if m_right and defender.rect.right < defender.screen_rect.right:
defender.center_x += ship_speed
if m_left and defender.rect.left > defender.screen_rect.left:
defender.center_x -= ship_speed
if m_up and defender.rect.top > defender.screen_rect.top:
defender.center_y -= ship_speed
if m_down and defender.rect.bottom < defender.screen_rect.bottom:
defender.center_y += ship_speed
# The cumulative value (which is a float number) for the spaceships movement
# is given to the spaceship rect variable (which can only be integer) now.
# This enables fine adjusting of the speed
defender.rect.centerx = defender.center_x
defender.rect.centery = defender.center_y
all_sprites_list.update()
screen.fill(color.black)
if new_bullet:
new_bullet.update_pos()
# Below the bullets which leaves the screen display are deleted
if new_bullet.rect.bottom < defender.screen_rect.top:
all_sprites_list.remove(new_bullet)
all_sprites_list.draw(screen)
print(all_sprites_list)
pygame.display.flip()
run_game()
instead of just updating the position of new_bullet
# if new_bullet:
# new_bullet.update_pos()
# # Below the bullets which leaves the screen display are deleted
# if new_bullet.rect.bottom < defender.screen_rect.top:
# all_sprites_list.remove(new_bullet)
update the position of all bullets
for bullet in all_sprites_list:
if isinstance(bullet,Bullet):
bullet.update_pos()
if bullet.rect.bottom < defender.screen_rect.top:
all_sprites_list.remove(bullet)
del bullet
Joran Beasley's answer is correct. I'd just like to point out that you can also put the behavior of the sprites into their update methods which get called automatically when you call all_sprites_list.update(). You can actually move most of the code in the while loop to the update methods.
I've got an example with these changes and some more tips in the comments (a quick code review):
import pygame
from pygame.sprite import Sprite
from pygame.sprite import Group
# I'd just define some global constants for the colors.
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
GREEN_LAMBDA = (10, 255, 150)
class Spaceship(Sprite):
"""This class represents the Spaceship."""
def __init__(self, screen):
"""Constructor"""
super().__init__()
self.screen = screen
# pygame.SRCALPHA makes the surface transparent.
self.image = pygame.Surface((22, 32), pygame.SRCALPHA)
pygame.draw.polygon(
self.image, GREEN_LAMBDA,
[[10,0],[15,22],[20,30],[10,27],[0,30],[5,22]], 2
)
self.screen_rect = self.screen.get_rect()
# You can pass the position as the midbottom argument to `get_rect`.
self.rect = self.image.get_rect(midbottom=self.screen_rect.midbottom)
self.center_x = self.rect.centerx
self.center_y = self.rect.centery
# I've removed the `m_right`, etc. variables and just set the speed
# of the sprite in the event loop.
self.max_speed = 3.5
self.speed_x = 0
self.speed_y = 0
def update(self):
# Move the sprite.
self.center_x += self.speed_x
self.center_y += self.speed_y
self.rect.centerx = self.center_x
self.rect.centery = self.center_y
# Keep the sprite on the screen.
if not self.screen_rect.contains(self.rect):
self.rect.clamp_ip(self.screen_rect)
self.center_x, self.center_y = self.rect.center
class Bullet(Sprite):
"""This class represents the bullets."""
def __init__(self, pos):
super().__init__()
self.image = pygame.Surface((8, 10), pygame.SRCALPHA)
pygame.draw.ellipse(self.image, GREEN, [1, 0, 5, 8], 2)
self.rect = self.image.get_rect(midbottom=pos)
self.speed = 3 # The speed is now an attribute.
def update(self):
self.rect.y -= self.speed
if self.rect.top < 0:
self.kill() # Remove the sprite from all groups.
def run_game():
pygame.init()
screen = pygame.display.set_mode((800, 700))
clock = pygame.time.Clock() # Use a clock to limit the frame rate.
defender = Spaceship(screen)
all_sprites = Group() # Changed the name because groups are not lists.
all_sprites.add(defender)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
return
elif event.key == pygame.K_RIGHT:
defender.speed_x = defender.max_speed
elif event.key == pygame.K_LEFT:
defender.speed_x = -defender.max_speed
elif event.key == pygame.K_UP:
defender.speed_y = -defender.max_speed
elif event.key == pygame.K_DOWN:
defender.speed_y = defender.max_speed
elif event.key == pygame.K_SPACE:
new_bullet = Bullet(defender.rect.midtop) # Pass the pos.
all_sprites.add(new_bullet)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT and defender.speed_x > 0:
defender.speed_x = 0
elif event.key == pygame.K_LEFT and defender.speed_x < 0:
defender.speed_x = 0
elif event.key == pygame.K_UP and defender.speed_y < 0:
defender.speed_y = 0
elif event.key == pygame.K_DOWN and defender.speed_y > 0:
defender.speed_y = 0
all_sprites.update() # Calls the update methods of all sprites.
screen.fill(BLACK)
all_sprites.draw(screen)
pygame.display.flip()
clock.tick(60) # Limit the frame rate to 60 FPS.
run_game()

Two enemy movement glitches

So this is my game I've bean working on and so have things are going very well, the player can move around and shoot down the boxes which are ment to be moving but theres these small glitches, but before I go on heres the code:
import pygame, math, random, sys
from pygame import *
import random, math, cmath
pygame.init()
#variables end----------------------------------------------------------------
#imagers
grass = "grass_shit.png" #grass image
player_img = "shithead.png" #player name
ali_img = "shit_head2.png" #alien image
dead_screen = "dead_shit.png"
cross_hair = "crosshair.png"
playButton = "playbutton.png"
#screen
screen = pygame.display.set_mode((850, 640),0,32) #set screen
background = pygame.image.load(grass).convert() #load image to screen
health = 100
#mouse things
crosshair = pygame.image.load(cross_hair).convert_alpha()
#variables end----------------------------------------------------------------
pygame.mouse.set_visible(False)
black = ( 0, 0, 0)
white = ( 255, 255, 255)
red = ( 255, 0, 0)
blue = ( 0, 0, 255)
player_x, player_y = 0, 0
move_player_x, move_player_y = 0, 0
move_ali_x, move_ali_y = 0, 0
class Block(pygame.sprite.Sprite):
def __init__(self, color):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20, 15])
self.image.fill(color)
self.rect = self.image.get_rect()
def update(self):
global move_ali_x
global move_ali_y
if block.rect.x < player_x:
move_ali_x =+ 0.05
elif block.rect.x > player_x:
move_ali_x =- 0.05
if block.rect.y < player_y:
move_ali_y =+ 0.05
elif block.rect.y > player_y:
move_ali_y =- 0.05
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20,20])
self.image.fill(red)
self.rect = self.image.get_rect()
def update(self):
pos = pygame.mouse.get_pos()
self.rect.x = player_x
self.rect.y = player_y
class Bullet(pygame.sprite.Sprite):
def __init__(self, mouse, player):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([4, 10])
self.image.fill(black)
self.mouse_x, self.mouse_y = mouse[0], mouse[1]
self.player = player
self.rect = self.image.get_rect()
def update(self):
speed = 10
range = 50000
distance = [self.mouse_x - self.player[0], self.mouse_y - self.player[1]]
norm = math.sqrt(distance[0] ** 2 + distance[1] ** 2)
direction = [distance[0] / norm, distance[1] / norm]
bullet_vector = [direction[0] * speed, direction[1] * speed]
self.rect.x += bullet_vector[0]
self.rect.y += bullet_vector[1]
pygame.init()
screen_width = 850
screen_height = 640
screen = pygame.display.set_mode([screen_width,screen_height])
all_sprites_list = pygame.sprite.Group()
block_list = pygame.sprite.Group()
bullet_list = pygame.sprite.Group()
for i in range(5):
block = Block(blue)
block.rect.x = random.randrange(screen_width)
block.rect.y = random.randrange(350)
block_list.add(block)
all_sprites_list.add(block)
player = Player()
all_sprites_list.add(player)
done = False
clock = pygame.time.Clock()
score = 0
player.rect.y = 370
# -------- Main Program Loop -----------
while not done:
# --- Event Processing
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
bullet = Bullet(event.pos, [player.rect.x, player.rect.y])
bullet.rect.x = player.rect.x
bullet.rect.y = player.rect.y
all_sprites_list.add(bullet)
bullet_list.add(bullet)
if event.type== pygame.KEYDOWN:
if event.key==K_a:
move_player_x=-4
elif event.key==K_d:
move_player_x=+4
elif event.key==K_w:
move_player_y=-4
elif event.key==K_s:
move_player_y=+4
if event.type== pygame.KEYUP:
if event.key==K_a:
move_player_x=0
elif event.key==K_d:
move_player_x=0
elif event.key==K_w:
move_player_y=0
elif event.key==K_s:
move_player_y=0
# --- Game logic
all_sprites_list.update()
player_x += move_player_x
player_y += move_player_y
block.rect.y += move_ali_y
block.rect.x += move_ali_x
for bullet in bullet_list:
block_hit_list = pygame.sprite.spritecollide(bullet, block_list, True)
for block in block_hit_list:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
score += 1
print( score )
if bullet.rect.y < -10:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
if player.rect.colliderect(block.rect):
health =- 35
mouse_x, mouse_y = pygame.mouse.get_pos()
mouse_x -= crosshair.get_width() / 2
mouse_y -= crosshair.get_height() / 2
screen.blit(background,(0,0))
all_sprites_list.draw(screen)
screen.blit(crosshair,(mouse_x, mouse_y))
pygame.display.flip()
pygame.display.update()
clock.tick(20)
pygame.quit()
So glitch number one:
only one of the boxers moves, I cant figure out why it only one of them is moving towards the player, all the boxers are meant to move towards the player as this is hoping to become a zombie shooter.
Glitch two:
At a random point the box that does move does stops moving in all directions but one, so lets say this happens when the box in in the center of the screen, if the player goes to the left of the box, nothing, but when the player moves to thr right of the player it moves right, but only right not up or down, and this seams to happen at soem point everytime.
Well thats it, hope you can help thanks heaps stackoverflow
Your code should looks like this:
import pygame
from pygame import *
import sys
import math
import random
import cmath
#----------------------------------------------------------------------
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
#imagers
IMAGE_GRASS = "grass_shit.png" #grass image
IMAGE_PLAYER = "shithead.png" #player name
IMAGE_ALI = "shit_head2.png" #alien image
IMAGE_DEAD_SCREEN = "dead_shit.png"
IMAGE_CROSSHAIR = "crosshair.png"
IMAGE_PLAYBUTTON = "playbutton.png"
#~ IMAGE_GRASS = "ball3.png" #grass image
#~ IMAGE_PLAYER = "ball2.png" #player name
#~ IMAGE_ALI = "ball3.png" #alien image
#~ IMAGE_DEAD_SCREEN = "ball3.png"
#~ IMAGE_CROSSHAIR = "ball1.png"
#~ IMAGE_PLAYBUTTON = "ball3.png"
#----------------------------------------------------------------------
class Block(pygame.sprite.Sprite):
def __init__(self, color, x, y, player = None):
pygame.sprite.Sprite.__init__(self)
self.player = player
self.image = pygame.Surface([20, 15])
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.move_x = self.move_y = 0
def update(self):
if self.player:
player_x, player_y = self.player.rect.center
if self.rect.x < player_x:
self.rect.x += 1
elif self.rect.x > player_x:
self.rect.x -= 1
if self.rect.y < player_y:
self.rect.y += 1
elif self.rect.y > player_y:
self.rect.y -= 1
#----------------------------------------------------------------------
class Player(pygame.sprite.Sprite):
def __init__(self, screen_rect, x=0, y=0):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20,20])
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.min_x = screen_rect.left
self.min_y = screen_rect.top
self.max_x = screen_rect.right
self.max_y = screen_rect.bottom
self.move_x = self.move_y = 0
self.health = 100
def update(self):
pos = pygame.mouse.get_pos()
self.rect.x += self.move_x
self.rect.y += self.move_y
if self.rect.top < self.min_x:
self.rect.top = self.min_x
elif self.rect.bottom > self.max_y:
self.rect.bottom = self.max_y
if self.rect.left < self.min_x:
self.rect.left = self.min_x
elif self.rect.right > self.max_x:
self.rect.right = self.max_x
def event_handler(self, event):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
self.move_x = -4
elif event.key == pygame.K_d:
self.move_x = +4
elif event.key == pygame.K_w:
self.move_y = -4
elif event.key == pygame.K_s:
self.move_y = +4
if event.type == pygame.KEYUP:
if event.key in (pygame.K_a, pygame.K_d):
self.move_x = 0
elif event.key in (pygame.K_w, pygame.K_s):
self.move_y = 0
#----------------------------------------------------------------------
class Bullet(pygame.sprite.Sprite):
def __init__(self, start_pos, mouse_pos):
pygame.sprite.Sprite.__init__(self)
self.start_rect = start_pos.rect.copy()
self.mouse_x, self.mouse_y = mouse_pos # mouse[0], mouse[1]
self.image = pygame.Surface([5, 5])
self.image.fill(BLACK)
self.rect = self.image.get_rect()
self.rect.centerx = self.start_rect.centerx
self.rect.centery = self.start_rect.centery
self.speed = 10
self.max_range = 50
self.current_range = 0
distance_x = self.mouse_x - self.start_rect.centerx
distance_y = self.mouse_y - self.start_rect.centery
norm = math.sqrt(distance_x ** 2 + distance_y ** 2)
direction_x = distance_x / norm
direction_y = distance_y / norm
self.bullet_vector_x = direction_x * self.speed
self.bullet_vector_y = direction_y * self.speed
def update(self):
self.current_range += 1
if self.current_range < self.max_range:
print self.start_rect.centerx + (self.bullet_vector_x*self.current_range),
print self.rect.centerx + self.bullet_vector_x,
#self.rect.centerx += self.bullet_vector_x
self.rect.centerx = self.start_rect.centerx + (self.bullet_vector_x*self.current_range)
print self.rect.centerx
#self.rect.centery += self.bullet_vector_y
self.rect.centery = self.start_rect.centery + (self.bullet_vector_y*self.current_range)
else:
self.kill()
#----------------------------------------------------------------------
class Crosshair(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(IMAGE_CROSSHAIR).convert_alpha()
self.rect = self.image.get_rect()
def update(self):
mouse_x, mouse_y = pygame.mouse.get_pos()
self.rect.centerx = mouse_x
self.rect.centery = mouse_y
def draw(self, screen):
screen.blit(self.image,self.rect.topleft)
#----------------------------------------------------------------------
class Background(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(IMAGE_GRASS).convert_alpha()
self.rect = self.image.get_rect()
def draw(self, screen):
screen.fill((128,128,128))
screen.blit(self.image,(0,0))
#----------------------------------------------------------------------
class Game():
def __init__(self):
pygame.init()
screen_width = 850
screen_height = 640
self.screen = pygame.display.set_mode( (screen_width,screen_height) )
pygame.mouse.set_visible(False)
#-----
self.all_sprites_list = pygame.sprite.Group()
self.block_list = pygame.sprite.Group()
self.bullet_list = pygame.sprite.Group()
# --- create sprites ---
self.background = Background()
self.player = Player(self.screen.get_rect(), 0, 370)
self.all_sprites_list.add(self.player)
for i in range(5):
block = Block(BLUE, random.randrange(100, screen_width), random.randrange(10, screen_height-10), self.player)
self.block_list.add(block)
self.all_sprites_list.add(block)
self.crosshair = Crosshair()
#-----
font = pygame.font.SysFont("", 72)
self.text_pause = font.render("PAUSE", -1, RED)
self.text_pause_rect = self.text_pause.get_rect(center=self.screen.get_rect().center) # center text
#-----
self.score = 0
def bullet_create(self, start_pos, mouse_pos):
bullet = Bullet(start_pos, mouse_pos)
self.all_sprites_list.add(bullet)
self.bullet_list.add(bullet)
def bullets_update(self):
for bullet in self.bullet_list:
block_hit_list = pygame.sprite.spritecollide(bullet, self.block_list, True)
for block in block_hit_list:
self.bullet_list.remove(bullet)
self.all_sprites_list.remove(bullet)
self.score += 1
print self.score
if bullet.rect.y < -10:
self.bullet_list.remove(bullet)
self.all_sprites_list.remove(bullet)
if pygame.sprite.collide_rect(self.player, block):
self.player.health =- 35
# -------- Main Program Loop -----------
def run(self):
clock = pygame.time.Clock()
RUNNING = True
PAUSED = False
while RUNNING:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
RUNNING = false
elif event.key == pygame.K_SPACE:
PAUSED = not PAUSED
elif event.type == pygame.MOUSEBUTTONDOWN:
self.bullet_create(self.player, event.pos)
# send event to player
self.player.event_handler(event)
# send event to crosshair for mousebuttondown
#if not PAUSED:
# self.crosshair.event_handler(event)
# --- updates ---
if not PAUSED:
self.all_sprites_list.update()
self.bullets_update()
self.crosshair.update()
# --- draws ---
self.background.draw(self.screen)
self.all_sprites_list.draw(self.screen)
self.crosshair.draw(self.screen)
if PAUSED:
self.screen.blit(self.text_pause, self.text_pause_rect.topleft)
pygame.display.update() # use flip() OR update()
# --- FPS ---
clock.tick(20)
# --- quit ---
pygame.quit()
#----------------------------------------------------------------------
Game().run()
Changes:
player can move but can leave screen
press space to pause game - but you can still move cursor and fire :)
bullet has max range - than it is removed
i change bullet vetor calculations because value was rounded to integer every frame and bullet trajectory was incorrect
bullet never change trajectory when player is moving
all code is in classes except some constant values. I add class Crosshair and Background
you can see how class (Player) handle events in event_handle
I use pygame.Rect() (screen.get_rect(), image.get_rect()) to get rect.top, rect.left, rect.center, rect.centerx, rect.topleft, etc.
There is still many things to do.
ps. if someone needs images 'ball1.png', 'ball2.png', 'ball3.png' to run this example you can find it in answer to
Space invaders project
Pygame- window and sprite class - python

My sprites checker doesn't work

I have created code to see whether my aliens are dead however it doesn't work, can anyone see the problem.
CODE:
enemies = pygame.sprite.Group(aliens)
if len(enemies) <= 0:
print("game over")
gameover()
Complete code:
#MathsVaders
import pygame, random, time
from pygame.locals import *
import Databaseconnector
import tkMessageBox
pygame.init()
# set up the graphics window
size = [800, 595]
screen = pygame.display.set_mode(size, 0)
screenrect = screen.get_rect()
pygame.display.set_caption("Mathsvaders")
# set some variables
done = False
life = 3
aliens = pygame.sprite.Group()
allsprites = pygame.sprite.Group()
bombs = pygame.sprite.Group()
green = [0, 255, 0]
white = [255, 255, 255]
# create a timer to control how often the screen updates
clock = pygame.time.Clock()
fps = 100
# loads images to use in the game which link in with my classes(further down)
cannon = pygame.image.load("spaceship.png").convert()
cannon.set_colorkey(white)
blast = pygame.image.load("blast.png").convert_alpha()
boom = pygame.image.load("expl.png").convert_alpha()
bomb = pygame.image.load("missile_player.png").convert_alpha()
back = pygame.image.load("rsz_space.png").convert()
enemy = pygame.image.load("sii.png").convert_alpha()
lives2 = pygame.image.load("alien2.png").convert()
lives2.set_colorkey(white)
lives3 = pygame.image.load("alien3.png").convert()
lives3.set_colorkey(white)
lives1 = pygame.image.load("alien1.png").convert()
lives1.set_colorkey(white)
# (Classes)
# the explosion class
class Explosion(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = boom
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
self.count = 6
def update(self):
self.count -= 1
if self.count < 1:
self.kill()
class scoreClass:
def __init__(self):
self.value = 0
# set a font, default font size 28
self.font = pygame.font.Font(None, 28)
def update(self):
text = self.font.render("Score: %s" % self.value, True, (green))
textRect = text.get_rect()
textRect.centerx = screenrect.centerx
screen.blit(text, textRect)
class Msg:
def __init__(self, words):
# set a font, default font size 28
self.font = pygame.font.Font(None, 28)
self.text = self.font.render(words, True, (green))
self.textRect = self.text.get_rect()
def update(self):
self.textRect.centerx = screenrect.centerx
self.textRect.centery = screenrect.centery
screen.blit(self.text, self.textRect)
# the invader class
class Pi(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
aliens.add(self)
self.image = enemy
self.rect = self.image.get_rect()
self.rect.left = x
self.rect.top = y
self.speed = 1
def update(self):
self.rect.right += self.speed
if self.rect.right >= (screenrect.right -5):
self.speed = -1
self.rect.top += self.rect.height
if self.rect.left <= (screenrect.left +5):
self.speed = 1
self.rect.top += self.rect.height
if self.rect.top > screenrect.bottom:
self.kill()
i = random.randrange(1000)
j = self.rect.centerx
if i == 1:
laser_bomb = Bomb(j, self.rect.bottom)
allsprites.add(laser_bomb)
aliens.add(laser_bomb)
class Gun(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = cannon
self.rect = self.image.get_rect()
self.rect.bottom = screenrect.bottom
self.rect.centerx = screenrect.centerx
self.speed=0
def update(self):
self.rect.centerx += self.speed
if self.rect.right >= screenrect.right:
self.rect.centerx = 0
if self.rect.right <= 0:
self.rect.right = screenrect.right
# bomb class
class Bomb(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = bomb
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
bombs.add(self)
def update(self):
self.rect.centery +=1
# the laser blast class
class Blast(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = blast
self.image.set_colorkey(white)
self.rect = self.image.get_rect()
self.rect.top = (player.rect.top + 5)
self.rect.centerx = player.rect.centerx
self.speed = 0
def update(self):
if self.speed == 0:
self.rect.centerx = player.rect.centerx
self.rect.top -= self.speed
# function to make a sheet of invaders
def invade():
for j in range(10, 200, 120):
for i in range(10):
aliens.add(Pi((i*70)+10, j))
def gameover():
message = Msg("Game Over")
message.update()
player.kill()
shot.kill()
SQL = 'INSERT INTO TblScore(Score, StudentID) VALUES (' + str(score.value) + ', ' + str(8) + ')'
Databaseconnector.INSERT(SQL)
#pygame.quit()
##def gameover():
## message = Msg("Game Over")
## message.update()
## player.kill()
## shot.kill()
## SQL = 'INSERT INTO TblScore(Score, StudentID) VALUES (' + str(score.value) + ', ' + str(8) + ')'
## Databaseconnector.INSERT(SQL)
##
## #pygame.quit()
def gamewon():
# sprites(aliens) == 0
#sprites.aliens == 0
message = Msg("YOU WON, YOUR SCORE WAS " + score + " WELL DONE")
message.update
aliens.kill()
shot.kill()
pygame.quit()
# pre-game window
invade()
message = Msg("Press a key to play.")
allsprites.add(aliens)
key = True
while key:
screen.blit(back, (0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYDOWN:
for item in (aliens):
item.kill()
key = False
allsprites.update()
allsprites.draw(screen)
message.update()
# set the loop to 40 cycles per second
clock.tick(fps)
# update the display
pygame.display.flip()
# Main Game Starts Here
score = scoreClass()
player = Gun()
shot = Blast()
invade()
allsprites.add(player, aliens, shot)
while done==False:
screen.blit(back, (0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
done=True
if life <= 0:
gamewon()
## elif allsprites == 0:
## gamewon()
else:
# shoots laser missile
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
if shot.speed == 0:
shot.speed = 7
#laser.play()
if event.key == pygame.K_LEFT:
player.speed = -3
if event.key == pygame.K_RIGHT:
player.speed = 3
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.speed = 0
if event.key == pygame.K_RIGHT:
player.speed = 0
hit = pygame.sprite.spritecollide(shot, aliens, 1)
if len(hit) > 0:
explosion1 = Explosion(shot.rect.centerx, shot.rect.top)
score.value += 1500
shot.kill()
#explode.play()
shot = Blast()
allsprites.add(shot, explosion1)
hit2 = pygame.sprite.spritecollide(player, aliens, 1)
if len(hit2) > 0:
life -= 1
#explode.play()
explosion2 = Explosion(player.rect.centerx, player.rect.centery)
allsprites.add(explosion2)
player.kill()
shot.kill()
if life > 0:
ready = Msg("Push Harder !!.")
ready.update()
allsprites.update()
allsprites.draw(screen)
score.update()
pygame.display.flip()
for item in bombs:
item.kill()
while 1:
event = pygame.event.wait()
if event.type == pygame.KEYDOWN:
break
player = Gun()
shot = Blast()
allsprites.add(player, shot)
if shot.rect.top <= screenrect.top:
shot.kill()
shot = Blast()
allsprites.add(shot)
if life == 2:
men = lives2
if life == 1:
men = lives1
if life == 3:
men = lives3
if life > 0:
screen.blit(men, (0,0))
allsprites.update()
allsprites.draw(screen)
score.update()
# set the loop to "fps" cycles per second
clock.tick(fps)
# update the display
pygame.display.flip()
# close pygame
pygame.quit()
This is the "pythonic" way since an empty list is False:
if not enemies:
print("game over")
gameover()
Where is the part of code that kills your aliens?

Categories