CODING/Python/CreeperDefense/CreeperDefense.py
2026-01-19 17:54:17 -05:00

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()