Related
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 am making the game Space Invaders with Pygame and I am trying to make the enemy shoot, firstly by pressing the TAB button. When I get this working I will let the enemy shoot randomly. At this moment I cannot see the BulletEnemy and when I press TAB it does not shoot anything. What am I doing wrong?
Thanks.
import pygame, sys
from pygame.locals import *
import random
screenWidth = 800
screenHeight = 600
FPS = 60
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((screenWidth,screenHeight))
pygame.display.set_caption("Space Invaders")
clock = pygame.time.Clock()
shipWidth = 78
#colors
black=(0,0,0)
blue=(0,0, 255)
green=(0,128,0)
red=(255,0,0)
white=(255,255,255)
yellow=(255,255,0)
def app_quit():
pygame.quit()
sys.exit("System exit.")
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("spaceship7.png").convert()
self.image.set_colorkey(white)#make white transparant
self.rect = self.image.get_rect()
self.rect.centerx = screenWidth / 2
self.rect.bottom = screenHeight - 10
self.speedx = 0
def update(self):
self.speedx = 0
if event.type == KEYDOWN and event.key == K_LEFT:
self.speedx = -2
elif event.type == KEYDOWN and event.key == K_RIGHT:
self.speedx = 2
self.rect.x += self.speedx
if self.rect.right > screenWidth:
self.rect.right = screenWidth
if self.rect.left < 0:
self.rect.left = 0
def shootPlayer(self):
bulletPlayer = BulletPlayer(self.rect.centerx, self.rect.top)
allSprites.add(bulletPlayer)
bulletsPlayer.add(bulletPlayer)
class Enemy(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("enemy.png").convert()
self.image.set_colorkey(white)
self.rect = self.image.get_rect()
self.rect.x = 0
self.rect.y = random.randrange(0, 200)
self.speedx = random.randrange(1,2)
def update(self):
self.rect.x += self.speedx
if self.rect.right > screenWidth:
self.rect.x = 50
self.rect.y = random.randrange(0, 250)
self.speedx = random.randrange(1,3)
if self.rect.x > screenWidth:
self.kill()
def shootEnemy(self):
bulletEnemy = BulletEnemy(self.rect.centerx, self.rect.bottom)
allSprites.add(bulletEnemy)
bulletsEnemy.add(bulletEnemy)
class BulletPlayer(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("bullet.png").convert()
self.image.set_colorkey(white)
self.rect = self.image.get_rect()
self.rect.bottom = y
self.rect.centerx = x
self.speedy = -3
def update(self):
self.rect.y += self.speedy
if self.rect.bottom < 0:
self.kill()
class BulletEnemy(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("bulletenemy.png").convert()
self.image.set_colorkey(white)
self.rect = self.image.get_rect()
self.rect.bottom = y
self.rect.centerx = x
self.speedy = 3
def update(self):
self.rect.y += self.speedy
if self.rect.bottom > screenHeight:
self.kill()
class Wall(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("wall.png").convert()
self.rect = self.image.get_rect()
self.rect.center = 100, 300
allSprites = pygame.sprite.Group()
player = Player()
enemy = pygame.sprite.Group()
bulletsPlayer = pygame.sprite.Group()
bulletsEnemy = pygame.sprite.Group()
wall = Wall()
allSprites.add(player, enemy, bulletsPlayer, bulletsEnemy, wall)
for i in range(1):
e = Enemy()
allSprites.add(e)
enemy.add(e)
running = True
while True:
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
running = False
app_quit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.shootPlayer()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_TAB:
enemy.shootEnemy()
allSprites.update()
screen.fill(black)
allSprites.draw(screen)
pygame.display.flip()
pygame.quit()
Spaceship
Enemy
Wall
BulletPlayer
BulletEnemy
The problem is here:
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.shootPlayer()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_TAB:
enemy.shootEnemy()
Once event.type == KEYDOWN one time, the second evaluation is ignored.
Try this
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.shootPlayer()
elif event.key == pygame.K_TAB:
enemy.shootEnemy()
This checks for a KEYDOWN event, then for the specific key that's pressed.
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()
It is asking for 3 arguments and i have given it one. How do i give it 2 more and could you explain how to do that as well? Thanks
import pygame, random, collisionObjects
pygame.init()
screen = pygame.display.set_mode((640,480))
class Pirate(pygame.sprite.Sprite):
EAST = 0
def __init__(self, screen, dx):
self.screen = screen
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("king_pirate/running e0000.bmp")
self.image = self.image.convert()
tranColor = self.image.get_at((1, 1))
self.image.set_colorkey(tranColor)
self.rect = self.image.get_rect()
self.rect.inflate_ip(-50, -30)
self.rect.center = (0, random.randrange(30,450))
self.img = []
self.loadPics()
self.frame = 0
self.delay = 4
self.pause = self.delay
self.dx = dx
def update(self):
#set delay
self.pause -= 1
if self.pause <= 0:
self.pause = self.delay
self.frame += 1
if self.frame > 7:
self.frame = 0
self.image = self.img[self.frame]
self.rect.centerx += self.dx
if self.rect.centerx > self.screen.get_width():
self.rect.centerx = 0
self.rect.centery = random.randrange(30,450)
#load pictures
def loadPics(self):
for i in range(8):
imgName = "king_pirate/running e000%d.bmp" % i
tmpImg = pygame.image.load(imgName)
tmpImg.convert()
tranColor = tmpImg.get_at((0, 0))
tmpImg.set_colorkey(tranColor)
self.img.append(tmpImg)
class Pirate2(pygame.sprite.Sprite):
WEST = 0
def __init__(self, screen, dx):
self.screen = screen
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("pirate/running w0000.bmp")
self.image = self.image.convert()
tranColor = self.image.get_at((1, 1))
self.image.set_colorkey(tranColor)
self.rect = self.image.get_rect()
self.rect.inflate_ip(-50, -30)
self.rect.center = (640, random.randrange(20,460))
self.img = []
self.loadPics()
self.frame = 0
self.delay = 4
self.pause = self.delay
self.dx = dx
def update(self):
#set delay
self.pause -= 1
if self.pause <= 0:
self.pause = self.delay
self.frame += 1
if self.frame > 7:
self.frame = 0
self.image = self.img[self.frame]
self.rect.centerx -= self.dx
if self.rect.centerx < 0:
self.rect.centerx = self.screen.get_width()
self.rect.centery = random.randrange(20,460)
#load pictures
def loadPics(self):
for i in range(8):
imgName = "pirate/running w000%d.bmp" % i
tmpImg = pygame.image.load(imgName)
tmpImg.convert()
tranColor = tmpImg.get_at((0, 0))
tmpImg.set_colorkey(tranColor)
self.img.append(tmpImg)
#set up class for gold object,
class Gold(pygame.sprite.Sprite):
def __init__(self, screen, imageFile):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(imageFile)
self.image = self.image.convert()
self.rect = self.image.get_rect()
self.rect.centerx = random.randrange(0, screen.get_width())
self.rect.centery = random.randrange(0, screen.get_height())
#main character class
class Thief(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("thief2.gif")
self.image = self.image.convert()
tranColor = self.image.get_at((1, 1))
self.image.set_colorkey(tranColor)
self.rect = self.image.get_rect()
self.rect.inflate_ip(-15, -10)
self.rect.center = (30, (screen.get_height()-40))
self.dx = 30
self.dy = 30
if not pygame.mixer:
print("problem with sound")
else:
pygame.mixer.init()
self.collectcoin = pygame.mixer.Sound("collectcoin.wav")
self.hit = pygame.mixer.Sound("hit.ogg")
def update(self):
if self.rect.bottom > screen.get_height():
self.rect.centery = (screen.get_height()-40)
elif self.rect.top < 0:
self.rect.centery = 40
elif self.rect.right > screen.get_width():
self.rect.centerx = (screen.get_width()-30)
elif self.rect.left < 0:
self.rect.centerx = 30
#define movements
def moveUp(self):
self.rect.centery -= self.dy
def moveDown(self):
self.rect.centery += self.dy
def moveLeft(self):
self.rect.centerx -= self.dx
def moveRight(self):
self.rect.centerx += self.dx
def reset(self):
self.rect.center = (30, (screen.get_height()-40))
#set up a scoreboard
class Scoreboard(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.lives = 0
self.score = 0
self.font = pygame.font.SysFont("None", 40)
self.number = 0
#with a self updating label
def update(self):
self.text = "Damage: %d %% Gold Taken: %d" % (self.lives, self.score)
self.image = self.font.render(self.text, 1, (199,237,241))
self.rect = self.image.get_rect()
#define the game function
def game():
#set up background
background = pygame.Surface(screen.get_size())
background = pygame.image.load("sand.jpg")
background = pygame.transform.scale(background, screen.get_size())
screen.blit(background, (0, 0))
#initialize pirates & scoreboard sprites
pirate = Pirate()
scoreboard = Scoreboard()
#create two arrays for multiple gold object occurances
#two arrays are used for better distribution on screen
gold1 = []
numberofGold = 16
for i in range(numberofgolds):
oneGold = golds(screen,"gold1.png")
golds1.append(onegold)
for gold in golds1:
gold.rect.centerx = random.randrange(20,620)
gold.rect.centery = random.randrange(20,240)
gold.rect.inflate_ip(-5, -5)
gold2 = []
for i in range(numberofgolds):
onegold = golds(screen,"gold1.png")
golds2.append(onegold)
for gold in golds2:
gold.rect.centerx = random.randrange(20,620)
gold.rect.centery = random.randrange(250,460)
gold.rect.inflate_ip(-5, -5)
totalgolds = ((len(golds1)-1)+(len(golds2)-1))
#initialize gold sprites
goldSprites = pygame.sprite.Group(golds1,
#initialize pirate sprites & instances
pirate1 = pirate1(screen,13)
pirate2 = pirate2(screen,13)
pirate3 = pirate1(screen,11)
pirate4 = pirate2(screen,11)
pirate5 = pirate1(screen,13)
pirateSprites = pygame.sprite.Group(pirate1, pirate2, pirate3, pirate4, pirate5)
#use ordered updates to keep clean appearance
allSprites = pygame.sprite.OrderedUpdates(goldSprites, thief, pirateSprites, scoreboard)
#set up clock & loop
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.KEYDOWN:
if event.key == pygame.K_UP:
thief.moveUp()
elif event.key == pygame.K_DOWN:
thief.moveDown()
elif event.key == pygame.K_LEFT:
thief.moveLeft()
elif event.key == pygame.K_RIGHT:
thief.moveRight()
elif event.key == pygame.K_ESCAPE:
keepGoing = False
#check collisions here
hitpirates = pygame.sprite.spritecollide(thief, pirateSprites, False)
hitgold = pygame.sprite.spritecollide(thief, goldSprites, True)
if hitpirates:
thief.hit.play()
scoreboard.lives += 1
if scoreboard.lives >= 100:
keepGoing = False
number = 0
if hitgolds:
thief.collectcoin.play()
scoreboard.score += 1
totalgolds -= 1
if totalgolds <= 0:
keepGoing = False
number = 1
#draw sprites
allSprites.clear(screen, background)
allSprites.update()
allSprites.draw(screen)
pygame.display.flip()
return scoreboard.score
return scoreboard.number
def instructions(score, number):
pygame.display.set_caption("Hunt for Gold!")
background = pygame.Surface(screen.get_size())
background = pygame.image.load("sand.jpg")
background = pygame.transform.scale(background, screen.get_size())
screen.blit(background, (0, 0))
if number == 0:
message = "Sorry try again..."
elif number == 1:
message = "The theif escapes!"
else:
message = "Onto the hunt for gold!"
insFont = pygame.font.SysFont("Calibri", 25)
insLabels = []
instructions = (
"Last score: %d" % score ,
"%s" % message,
"",
"GOLD!",
"Get all the gold before you are "
"obliterated!",
"Use arrow keys to move the thief.",
"Space to start, Esc to quit."
)
for line in instructions:
tempLabel = insFont.render(line, 1 , (0,0,0))
insLabels.append(tempLabel)
#set up homescreen loop
keepGoing = True
clock = pygame.time.Clock()
while keepGoing:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
keepGoing = False
donePlaying = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
keepGoing = False
donePlaying = False
if event.key == pygame.K_ESCAPE:
keepGoing = False
donePlaying = True
for i in range(len(insLabels)):
screen.blit(insLabels[i], (50, 30*i))
pygame.display.flip()
return donePlaying
#define main function
def main():
donePlaying = False
score = 0
message = ""
while not donePlaying:
donePlaying = instructions(score, message)
if not donePlaying:
score = game()
else:
pygame.quit()
if __name__ == "__main__":
main()
Glancing at your code, this line:
pirate = Pirate()
Your Pirate class expects self, screen, dx. You only implicitly provide self.
I can only guess at what you want, especially since I don't know off the bat what dx is supposed to mean in respect to your game, but this will probably at least avoid the error:
pirate = Pirate(pygame.display.get_surface(), 60)
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?