Inspiration
I wrote a few ideas based on Halloween down and decided this one was possible to complete in the time provided while having some complexity.
What it does
The program will give the players rounds of approximately 30 seconds to click on as many minsters on the screen as they can to earn points to move onto the next round with the aim of achieving a high score. Monsters have different movement styles and have slight variation between one another whether that be starting position or number of clicks it takes to defeat. After a round is finished, a user will then be asked if they wish to continue if they meet a certain number of points and if so they play another round with a higher score multiplier allowing them to get higher scores. If they wish to stop or don't meet the required number of points then their score is compared to see if it is a high score and if so they provide their username and their score is saved to the high scores files. If not then they just get an output of the top 10 scores and the usernames of those who got them.
How I built it
I started off just practicing with a single image moving it around on the background and seeing if I could get some interaction out of it by clicking on the image. After that, I made the image part of an object which would move and be destroyed if clicked on providing the user points and created the other monster classed with their unique movement styles and special features. I then worked on the loops which would spawn new monsters and move them around the screen and how to handle clicking now that there were multiple monsters on the screen rather than just the one. Once all of this was done, I added in the time and score to the GUI and what would happen when the time runs out. My final task was then reading the high scores from a file and inserting the new score if necessary and then outputting the high scores at the end of the game.
Challenges I ran into
I attempted to install a mySQL database onto my computer to allow myself to store scores in a large database but I was having issues with the install so I had to change to a file based-system instead. I don't believe that all of pygame was installed properly so the command meant to close the window without issue isn't present so my game doesn't end but instead it crashes once finished with.
Accomplishments that I'm proud of
I managed to learn pygame and produce a functioning program in the span of time provided.
What I learned
Basics in using pygame including moving images around a screen, and how to work with a user input by handling an event based system. This will help me in the future with producing other GUIs not related to games since I now have an idea on how event-based systems work.
What's next for Haunted Halloween Blast
Move from storing high scores on a file to a database such as SQL. Tidying up the images so that they have transparent backgrounds. Providing users with a menu. Having new levels rather than just the same one with a higher score required to progress each time. Move all user input into the GUI rather than having some command line input and output when it comes to high scores. Music. Tidying up the code into more than just a main() method and a method for high scores. Providing more information, such as how many hits a Frankenstein has left or what the points threshold for the next level is. More variety in monsters and patterns.
from pygame import *
import random
font.init()
class monster():
def __init__(self):
self.points
self.monsterImage
self.position
def getPoints(self):
return self.points
def getPosition(self):
return self.position
def getImage(self):
return self.monsterImage
class frankenstein(monster):
def __init__(self):
self.monsterImage = image.load("frankenstein.png").convert()
self.position = self.monsterImage.get_rect()
self.position[0] = 1120
self.position[1] = 400
self.health = random.randint(20, 30)
self.points = 50 * self.health
def move(self):
self.position = self.position.move(-15,0)
if self.position[0] < 0:
return False
else:
return True
def damaged(self):
self.health -= 1
if self.health == 0:
return self.points
else:
return 0
class bat(monster):
def __init__(self):
self.points = 25
self.monsterImage = image.load("bat.png").convert()
self.position = self.monsterImage.get_rect()
self.variation = random.randint(0, 60)
self.position[1] += self.variation
def move(self):
self.position = self.position.move(20,0)
if self.position[0] > 1123:
return False
else:
return True
def damaged(self):
return self.points
class reverseBat(monster):
def __init__(self):
self.points = 25
self.monsterImage = image.load("bat.png").convert()
self.position = self.monsterImage.get_rect()
self.position[0] = 1123
self.variation = random.randint(0, 60)
self.position[1] += self.variation
def move(self):
self.position = self.position.move(-20,0)
if self.position[0] < 0:
return False
else:
return True
def damaged(self):
return self.points
class spider(monster):
def __init__(self):
self.points = 50
self.monsterImage = image.load("spider.jpg").convert()
self.position = self.monsterImage.get_rect()
self.verticalMove = 10
self.variation = random.randint(0, 1000)
self.position[0] += self.variation
def move(self):
self.position = self.position.move(0, self.verticalMove)
if self.position[1] >= 250:
self.verticalMove *= -1
return True
elif self.position[1] <= 0:
return False
else:
return True
def damaged(self):
return self.points
class pumpkin(monster):
def __init__(self):
self.points = 250
self.monsterImage = image.load("pumpkin.png").convert()
self.position = self.monsterImage.get_rect()
self.position[0] = random.randint(0, 800)
self.position[1] = random.randint(0, 500)
self.existFrames = 10
def move(self):
self.existFrames -= 1
if self.existFrames == 0:
return False
else:
return True
def damaged(self):
return self.points
def scoreWriting(score):
scoreFile = open('highscores.txt', 'r')
scores = []
intScores = []
for line in scoreFile:
scores.append(line.rstrip())
count = 0
for data in line.split(","):
if count == 1:
intScores.append(int(data[1:]))
count += 1
scoreFile.close()
if len(scores) < 10:
userName = input("You got a high score! Enter your name.")
if len(scores) == 0:
scores.append(userName + ", " + str(score))
else:
posFind = False
i = 0
while posFind == False and i < len(intScores):
if score > intScores[i]:
scores.insert(i, userName + ", " + str(score))
posFind = True
else:
i += 1
if posFind == False:
scores.append(userName + ", " + str(score))
scoreFile = open('highscores.txt', 'w')
for i in range(0, len(scores)):
scoreFile.write(scores[i] + "\n")
scoreFile.close()
else:
if score > intScores[9]:
userName = input("You got a high score! Enter your name.")
posFind = False
i = 0
while posFind == False and i < len(intScores):
if score > intScores[i]:
scores.insert(i, userName + ", " + str(score))
posFind = True
scores.pop(10)
else:
i += 1
scoreFile = open('highscores.txt', 'w')
for i in range(0, len(scores)):
scoreFile.write(scores[i] + "\n")
scoreFile.close()
else:
print("Sorry but you didn't get a high score. Thanks for Playing.")
for i in range(0, len(scores)):
print(str(i + 1) + ": " + scores[i])
def main():
screen = display.set_mode((1123, 750))
resetSquare = image.load("resetSquare.jpg").convert()
background = image.load("HauntedHouse.jpg").convert()
screen.blit(background, (0,0))
event.set_blocked(None)
event.set_allowed([MOUSEBUTTONUP, MOUSEBUTTONDOWN, QUIT, KEYDOWN])
spawnDelay = 0
monsters = []
score = 0
roundTime = 30
timeGap = 10
multiplier = 1
levelLimit = 3000
nextLevelAddition = 2000
while 1:
if roundTime > 0:
for currentEvent in event.get():
if currentEvent.type in (QUIT, QUIT):
sys.exit()
elif currentEvent.type in (MOUSEBUTTONDOWN, MOUSEBUTTONDOWN):
mousePos = mouse.get_pos()
mouseX = mousePos[0]
mouseY = mousePos[1]
clickHits = 0
clickScore = 0
for i in range(0, len(monsters)):
monsterMiss = False
while i < len(monsters) and monsterMiss == False:
currentMonster = monsters[i]
currentMonsterxLimit = currentMonster.getPosition()[0] + currentMonster.getPosition()[2]
currentMonsteryLimit = currentMonster.getPosition()[1] + currentMonster.getPosition()[3]
if mouseX >= currentMonster.getPosition()[0] and mouseX <= currentMonsterxLimit and mouseY >= currentMonster.getPosition()[1] and mouseY <= currentMonsteryLimit:
monsterPoints = currentMonster.damaged()
clickHits += 1
if monsterPoints > 0:
clickScore += monsterPoints
screen.blit(background, currentMonster.getPosition(), currentMonster.getPosition())
monsters.pop(i)
else:
monsterMiss = True
else:
monsterMiss = True
score += clickHits * clickScore * multiplier
timeGap -= 1
if timeGap == 0:
roundTime -= 1
timeGap = 10
currentFont = font.SysFont(None, 25)
scoreText = currentFont.render("Score: " + str(score), True, (255, 255, 255))
screen.blit(resetSquare, (10, 730))
screen.blit(scoreText, (10, 730))
timeText = currentFont.render("Time: " + str(roundTime), True, (255, 255, 255))
screen.blit(resetSquare, (200, 730))
screen.blit(timeText, (200, 730))
if spawnDelay == 0 and len(monsters) < 20:
spawnDelay = random.randint(5, 10)
monsterSpawn = random.randint(0, 4)
if monsterSpawn == 0:
monsters.append(bat())
elif monsterSpawn == 1:
monsters.append(reverseBat())
elif monsterSpawn == 2:
monsters.append(frankenstein())
elif monsterSpawn == 3:
monsters.append(pumpkin())
else:
monsters.append(spider())
for i in range(0, len(monsters)):
screen.blit(background, monsters[i].getPosition(), monsters[i].getPosition())
for i in range(0, len(monsters)):
currentMove = False
while currentMove == False and i < len(monsters):
if monsters[i].move() == True:
screen.blit(monsters[i].getImage(), monsters[i].getPosition())
currentMove = True
else:
monsters.pop(i)
time.delay(100)
spawnDelay -= 1
display.update()
else:
if score >= levelLimit:
multiplier += 1
valid = False
while valid == False:
continueChoice = input("Would you like to continue to the next level? (Y/N)").upper()
if continueChoice == "Y" or continueChoice == "N":
valid = True
else:
print("Invalid input, please try again.")
if continueChoice == "Y":
roundTime = 30
timeGap = 10
monsters = []
screen.blit(background, (0, 0))
levelLimit += nextLevelAddition
nextLevelAddition *= 2
else:
scoreWriting(score)
sys.quit()
else:
print("Your score isn't high enough to progress to the next level.")
scoreWriting(score)
sys.quit()
main()
Log in or sign up for Devpost to join the conversation.