As you might probably be able to guess, I'm quite new to Python! I'm trying to write a (very) simple Space Invaders game. Nothing flashy. No sounds, no explosions, not even any scores tracking (although, at some point, the aliens will move and shoot!). Right now though the problem with my code is that I can shoot (and destroy) any aliens in the bottom row - but I can't destroy aliens in any other row. It's most perplexing - and I'd welcome any advice that anyone can offer. This is my code:
# !/usr/bin/python
import pygame
bulletDelay = 40
class Bullet(object):
def __init__(self, xpos, ypos):
self.image = pygame.image.load("bullet.bmp")
self.rect = self.image.get_rect()
self.x = xpos
self.y = ypos
def current_position(self):
return [self.x, self.y]
def draw(self, surface):
surface.blit(self.image, (self.x, self.y))
class Player(object):
def __init__(self, screen):
self.image = pygame.image.load("spaceship.bmp") # load the spaceship image
self.rect = self.image.get_rect() # get the size of the spaceship
size = screen.get_rect()
self.x = (size.width * 0.5) - (self.rect.width * 0.5) # draw the spaceship in the horizontal middle
self.y = size.height - self.rect.height # draw the spaceship at the bottom
def current_position(self):
return self.x
def draw(self, surface):
surface.blit(self.image, (self.x, self.y)) # blit to the player position
class Alien(object):
def __init__(self, xpos, ypos):
self.image = pygame.image.load("alien.bmp") # load the alien image
self.rect = self.image.get_rect() # get the size of the alien
self.x = xpos
self.y = ypos
def current_position(self):
return [self.x, self.y]
def draw(self, surface):
surface.blit(self.image, (self.x, self.y)) # blit to the player position
def collision(alien,bullet):
if ((alien.current_position()[0] < bullet.current_position()[0] + 10) and
(alien.current_position()[0] > bullet.current_position()[0] - 10) and
(alien.current_position()[1] == bullet.current_position()[1])):
return True
else:
return False
def destroyObject(objectArray,killList):
if len(killList) > 0: # remove any bullets that have hit an alien
for item in killList:
del objectArray[item]
pygame.init()
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
player = Player(screen) # create the player sprite
missiles = [] # create missile array
aliensW = 6
aliensH = 3
# layout the initial field of aliens
aliens = [[Alien((screen.get_rect().width/7)*(x+0.75),(screen.get_rect().height/5)*(y+0.5)) for x in range(aliensW)] for y in range(aliensH)]
running = True
counter = bulletDelay
while running: # the event loop
counter=counter+1
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
key = pygame.key.get_pressed()
dist = 5 # distance moved for each key press
if key[pygame.K_RIGHT]: # right key
player.x += dist
elif key[pygame.K_LEFT]: # left key
player.x -= dist
elif key[pygame.K_SPACE]: # fire key
if counter > bulletDelay:
missiles.append(Bullet(player.current_position(),screen.get_rect().height))
counter=0
screen.fill((255, 255, 255)) # fill the screen with white - without this the old graphics will remain onscreen.
for m in missiles:
if m.y < (screen.get_rect()).height+1 and m.y > 0:
m.draw(screen)
m.y -= 5
else:
missiles.pop(0)
alienGrid = []
for a in aliens:
killList=[]
spentBullets=[]
alienNumber=0
alienRow = a
for b in alienRow:
#need to move aliens as well!
missileNumber=0
for m in missiles:
if (collision(b,m)):
killList.insert(0,alienNumber)
spentBullets.insert(0,missileNumber)
missileNumber+=1
alienNumber += 1
b.draw(screen)
destroyObject(alienRow,killList)
destroyObject(missiles,spentBullets)
alienGrid.insert(0,alienRow)
aliens = alienGrid
player.draw(screen) # draw the spaceship to the screen
pygame.display.update() # update the screen
clock.tick(40)
Of course, I also welcome any other advice that you might be able to offer for improving my code!
self.rect.xandself.rect.yinstead ofself.x,self.yand then you can useblit(self.image, self.rect). Andself.rect.colliderect(alien.rect)to check collision. Besideself.rectis used bypygame.sprite.Group()which is usefull.self.rect.centerx = screen.get_rect().centerx. Andself.rect.bottom = screen.get_rect().bottom