317 lines
11 KiB
Python
317 lines
11 KiB
Python
########################################################################################################################
|
|
# programmed by Zachary Hunter
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
########################################################################################################################
|
|
|
|
import pygame, random, sys, time
|
|
from pygame.locals import *
|
|
|
|
#set up some variables
|
|
WINDOWWIDTH = 1024
|
|
WINDOWHEIGHT = 600
|
|
FPS = 6000
|
|
|
|
ZOMBIESIZE =40
|
|
CRAWLERSIZE = 55
|
|
ADDNEWZOMBIERATE = 30
|
|
ADDNEWCRAWLERRATE = ADDNEWZOMBIERATE
|
|
|
|
NORMALZOMBIESPEED = 10
|
|
CRAWLERZOMBIESPEED = NORMALZOMBIESPEED / 2
|
|
|
|
PLAYERMOVERATE = 20
|
|
BULLETSPEED = 50
|
|
ADDNEWBULLETRATE = 10
|
|
|
|
highScore = 0
|
|
|
|
TEXTCOLOR = (255, 255, 255)
|
|
RED = (255, 0, 0)
|
|
|
|
def terminate():
|
|
pygame.quit()
|
|
sys.exit()
|
|
|
|
def waitForPlayerToPressKey():
|
|
while True:
|
|
for event in pygame.event.get():
|
|
if event.type == QUIT:
|
|
terminate()
|
|
if event.type == KEYDOWN:
|
|
if event.key == K_ESCAPE: # pressing escape quits
|
|
terminate()
|
|
if event.key == K_RETURN:
|
|
return
|
|
if event.key == ord('q'):
|
|
return
|
|
|
|
def playerHasHitZombie(playerRect, zombies):
|
|
for z in zombies:
|
|
if playerRect.colliderect(z['rect']):
|
|
return True
|
|
return False
|
|
|
|
def bulletHasHitZombie(bullets, zombies):
|
|
for b in bullets:
|
|
if b['bulletRect'].colliderect(z['rect']):
|
|
return True
|
|
return False
|
|
|
|
def bulletHasHitCrawler(bullets, crawlers):
|
|
for b in bullets:
|
|
if b['bulletRect'].colliderect(c['rect']):
|
|
return True
|
|
return False
|
|
|
|
def drawText(text, font, surface, x, y):
|
|
textobj = font.render(text, 1, TEXTCOLOR)
|
|
textrect = textobj.get_rect()
|
|
textrect.topleft = (x, y)
|
|
surface.blit(textobj, textrect)
|
|
|
|
def showScore():
|
|
drawText('creepers gotten past: %s' % (zombiesGottenPast), font, windowSurface, 10, 0)
|
|
drawText('score: %s' % (score), font, windowSurface, 10, 30)
|
|
|
|
def closeHighScoreTextFile():
|
|
#highScoreText.flush
|
|
highScoreText.close
|
|
|
|
|
|
# set up pygame, the window, and the mouse cursor
|
|
pygame.init()
|
|
mainClock = pygame.time.Clock()
|
|
windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), pygame.FULLSCREEN)
|
|
pygame.display.set_caption('Creeper Defence')
|
|
pygame.mouse.set_visible(False)
|
|
|
|
# set up fonts
|
|
font = pygame.font.SysFont(None, 48)
|
|
|
|
# set up sounds
|
|
gameOverSound = pygame.mixer.Sound('gameover.mp3')
|
|
pygame.mixer.music.load('aether2.ogg')
|
|
|
|
# set up images
|
|
playerImage = pygame.image.load('player.png')
|
|
playerRect = playerImage.get_rect()
|
|
|
|
bulletImage = pygame.image.load('bullet.png')
|
|
bulletRect = bulletImage.get_rect()
|
|
|
|
zombieImage = pygame.image.load('Creeper.png')
|
|
crawlerImage = pygame.image.load('crawler.png')
|
|
|
|
backgroundImage = pygame.image.load('background.png')
|
|
rescaledBackground = pygame.transform.scale(backgroundImage, (WINDOWWIDTH, WINDOWHEIGHT))
|
|
|
|
# show the "Start" screen
|
|
windowSurface.blit(rescaledBackground, (0, 0))
|
|
pygame.draw.line(windowSurface, RED, (WINDOWWIDTH / 2 + 20, WINDOWHEIGHT - 50), (WINDOWWIDTH / 2 + 20, 0), 1)
|
|
windowSurface.blit(playerImage, (WINDOWWIDTH / 2, WINDOWHEIGHT - 50))
|
|
drawText('Creeper Defence', font, windowSurface, (WINDOWWIDTH / 2) - 105, (WINDOWHEIGHT / 3))
|
|
drawText('Press Enter to start', font, windowSurface, (WINDOWWIDTH / 2) - 135, (WINDOWHEIGHT / 3) + 50)
|
|
pygame.display.update()
|
|
waitForPlayerToPressKey()
|
|
while True:
|
|
# set up the start of the game
|
|
|
|
zombies = []
|
|
crawlers = []
|
|
bullets = []
|
|
|
|
zombiesGottenPast = 0
|
|
score = 0
|
|
|
|
|
|
|
|
|
|
playerRect.topleft = (WINDOWWIDTH / 2, WINDOWHEIGHT - 50)
|
|
moveLeft = moveRight = False
|
|
shoot = False
|
|
|
|
zombieAddCounter = 0
|
|
crawlerAddCounter = 0
|
|
bulletAddCounter = 40
|
|
pygame.mixer.music.play(-1, 0.0)
|
|
|
|
while True: # the game loop runs while the game part is playing
|
|
for event in pygame.event.get():
|
|
if event.type == QUIT:
|
|
terminate()
|
|
|
|
if event.type == KEYDOWN:
|
|
if event.key == K_LEFT or event.key == ord('a'):
|
|
moveRight = False
|
|
moveLeft = True
|
|
if event.key == K_RIGHT or event.key == ord('d'):
|
|
moveLeft = False
|
|
moveRight = True
|
|
|
|
if event.key == K_SPACE:
|
|
shoot = True
|
|
|
|
|
|
if event.type == KEYUP:
|
|
if event.key == K_ESCAPE:
|
|
terminate()
|
|
|
|
if event.key == K_LEFT or event.key == ord('a'):
|
|
moveLeft = False
|
|
if event.key == K_RIGHT or event.key == ord('d'):
|
|
moveRight = False
|
|
|
|
if event.key == K_SPACE:
|
|
shoot = False
|
|
|
|
# Add new zombies at the top of the screen, if needed.
|
|
zombieAddCounter += 1
|
|
if zombieAddCounter == ADDNEWCRAWLERRATE:
|
|
zombieAddCounter = 0
|
|
zombieSize = ZOMBIESIZE
|
|
newZombie = {'rect': pygame.Rect(random.randint(0, WINDOWWIDTH-zombieSize), 0 - zombieSize, zombieSize, zombieSize),
|
|
'surface':pygame.transform.scale(zombieImage, (zombieSize, zombieSize)),
|
|
}
|
|
|
|
zombies.append(newZombie)
|
|
|
|
# Add new crawlers at the top of the screen, if needed.
|
|
crawlerAddCounter += 1
|
|
if crawlerAddCounter == ADDNEWZOMBIERATE:
|
|
crawlerAddCounter = 0
|
|
crawlerSize = CRAWLERSIZE
|
|
newCrawler = {'rect': pygame.Rect(random.randint(0, WINDOWWIDTH-crawlerSize), 0 - crawlerSize, crawlerSize, crawlerSize),
|
|
'surface':pygame.transform.scale(crawlerImage, (crawlerSize, crawlerSize * 2)),
|
|
}
|
|
|
|
crawlers.append(newCrawler)
|
|
|
|
# add new bullet
|
|
bulletAddCounter += 1
|
|
if bulletAddCounter >= ADDNEWBULLETRATE and shoot == True:
|
|
bulletAddCounter = 100000
|
|
bulletSize = (15, 5)
|
|
newBullet = {'bulletRect': windowSurface.blit(bulletImage, (playerRect.centerx - 2,playerRect.centery))}
|
|
bullets.append(newBullet)
|
|
|
|
# Move the player around.
|
|
if moveLeft and playerRect.left > 0:
|
|
playerRect.move_ip(-1 * PLAYERMOVERATE, 0)
|
|
if moveRight and playerRect.right < WINDOWWIDTH:
|
|
playerRect.move_ip(PLAYERMOVERATE, 0)
|
|
|
|
# Move the zombies down.
|
|
for z in zombies:
|
|
z['rect'].move_ip(0, NORMALZOMBIESPEED)
|
|
|
|
# Move the crawlers down.
|
|
for c in crawlers:
|
|
c['rect'].move_ip(0, CRAWLERZOMBIESPEED)
|
|
|
|
# move the bullet
|
|
for b in bullets:
|
|
b['bulletRect'].move_ip(0, -1 * BULLETSPEED)
|
|
|
|
# Delete zombies that have fallen past the bottom.
|
|
for z in zombies[:]:
|
|
if z['rect'].top > WINDOWHEIGHT:
|
|
zombies.remove(z)
|
|
zombiesGottenPast += 1
|
|
|
|
# Delete crawlers that have fallen past the bottom.
|
|
for c in crawlers[:]:
|
|
if c['rect'].top > WINDOWHEIGHT:
|
|
crawlers.remove(c)
|
|
zombiesGottenPast += 1
|
|
|
|
# check if the bullet has hit the zombie
|
|
for z in zombies:
|
|
if bulletHasHitZombie(bullets, zombies):
|
|
score += 1
|
|
zombies.remove(z)
|
|
bullets.remove(b)
|
|
for c in crawlers:
|
|
if bulletHasHitCrawler(bullets, crawlers):
|
|
score += 1
|
|
crawlers.remove(c)
|
|
bullets.remove(b)
|
|
|
|
|
|
# delete bullets going past the top
|
|
for b in bullets[:]:
|
|
if b['bulletRect'].top < 0:
|
|
bullets.remove(b)
|
|
|
|
# Draw the game world on the window.
|
|
windowSurface.blit(rescaledBackground, (0, 0))
|
|
|
|
# Draw the player's rectangle, rails
|
|
pygame.draw.line(windowSurface, RED, (playerRect.centerx - 1, playerRect.centery - 20), (playerRect.centerx - 1, 0), 1)
|
|
windowSurface.blit(playerImage, playerRect)
|
|
|
|
# Draw each baddie
|
|
for z in zombies:
|
|
windowSurface.blit(z['surface'], z['rect'])
|
|
|
|
for c in crawlers:
|
|
windowSurface.blit(c['surface'], c['rect'])
|
|
|
|
# draw each bullet
|
|
for b in bullets:
|
|
windowSurface.blit(bulletImage, b['bulletRect'])
|
|
|
|
# Draw the score and how many zombies got past
|
|
showScore()
|
|
|
|
# update the display
|
|
pygame.display.update()
|
|
|
|
# Check if any of the zombies has hit the player.
|
|
if playerHasHitZombie(playerRect, zombies):
|
|
break
|
|
if playerHasHitZombie(playerRect, crawlers):
|
|
break
|
|
|
|
# check if score is over 5 which means game over
|
|
if zombiesGottenPast >= 5:
|
|
break
|
|
|
|
mainClock.tick(FPS)
|
|
|
|
# Stop the game and show the "Game Over" screen.
|
|
pygame.mixer.music.stop()
|
|
gameOverSound.play()
|
|
time.sleep(0.1)
|
|
if zombiesGottenPast >= 5:
|
|
windowSurface.blit(rescaledBackground, (0, 0))
|
|
pygame.draw.line(windowSurface, RED, (WINDOWWIDTH / 2 + 20, WINDOWHEIGHT - 50), (WINDOWWIDTH / 2 + 20, 0), 1)
|
|
windowSurface.blit(playerImage, (WINDOWWIDTH / 2, WINDOWHEIGHT - 50))
|
|
showScore()
|
|
drawText('GAME OVER', font, windowSurface, (WINDOWWIDTH / 2) - 85, (WINDOWHEIGHT / 3))
|
|
drawText('you let to many zombies get past', font, windowSurface, (WINDOWWIDTH / 2)- 115, (WINDOWHEIGHT / 3) + 100)
|
|
drawText('Press enter to play again or escape to exit', font, windowSurface, (WINDOWWIDTH / 3) - 215, (WINDOWHEIGHT / 3) + 150)
|
|
pygame.display.update()
|
|
waitForPlayerToPressKey()
|
|
if playerHasHitZombie(playerRect, zombies):
|
|
windowSurface.blit(rescaledBackground, (0, 0))
|
|
pygame.draw.line(windowSurface, RED, (WINDOWWIDTH / 2 + 20, WINDOWHEIGHT - 50), (WINDOWWIDTH / 2 + 20, 0), 1)
|
|
windowSurface.blit(playerImage, (WINDOWWIDTH / 2, WINDOWHEIGHT - 50))
|
|
showScore()
|
|
drawText('GAME OVER!', font, windowSurface, (WINDOWWIDTH / 2) - 85, (WINDOWHEIGHT / 3))
|
|
drawText('a zombie has hit you!', font, windowSurface, (WINDOWWIDTH / 2.1) - 115, (WINDOWHEIGHT / 3) +100)
|
|
drawText('Press enter to play again or escape to exit.', font, windowSurface, (WINDOWWIDTH / 2.5) - 215, (WINDOWHEIGHT / 3) + 150)
|
|
pygame.display.update()
|
|
waitForPlayerToPressKey()
|
|
gameOverSound.stop()
|