Use pygame to make a hamster hit game

Keywords: Python

1. Preview of running results

Start Interface

First level

Second level

Third level

Level 4

Level 5

Game over

2. Introduction of Game Functions

2.1 Development Environment:

python version: python 3.7

2.2 Related modules:

pygame modules, as well as some modules that come with Python.

2.3 Introduction to the game:

The game is timed in 120 seconds.

The first 40 seconds are the first level, and the mouse appears very slowly.

40-60 seconds for the second level, the mouse appeared slowly;

60-80 seconds for the third level, the mouse appears at a moderate speed;

80-100 seconds for the fourth level, the mouse appears faster;

After 100 seconds, the fifth level, the mice appeared very quickly.

When the countdown ends, the game ends and scores are compared.

3. Development ideas

py file defined in 3.1

3.1.1 mouse.py (main function entry)

Link the entire hamster function through the mouse.py file.

3.1.2cfg.py file (basic configuration such as fonts)

The cfg file defines the basic configuration, font, color, size, and so on

3.1.3mole.py file (hamster)

mole defines the hamster, including picture loading, display, reset, etc.

3.1.4 hammer.py file (hammer)

Hammer defines a hammer, including its picture loading, display, effect on hitting, reset, etc.

3.1.5 endinterface.py file (end interface)

endinterface defines the end-time page, including the score display and the maximum score display

3.1.6 startinterface.py file (start interface)

startinterface defines the starting page.

3.2 Defined Functions

3.2.1 Game Initialization

def initGame():
	pygame.init()
	pygame.mixer.init()
	screen = pygame.display.set_mode(cfg.SCREENSIZE)
	pygame.display.set_caption('Yuan Xin Zhang Chen-en's Hamster Game')
	return screen

3.2.2 Main Entrance to Games

def main():

3.2.3 Mouse in Game

class Mole(pygame.sprite.Sprite):

3.2.4 Hammers in Games

class Hammer(pygame.sprite.Sprite):

3.2.5 Game Start Interface

def startInterface(screen, begin_image_paths):

3.2.6 End of Game Interface

def endInterface(screen, end_image_path, again_image_paths, score_info, font_path, font_colors, screensize):

4. Related Codes

4.1mouse.py (main function entry)

def main():
	# Initialization
	screen = initGame()

4.1.1 Load background music and other sound effects

	pygame.mixer.music.load(cfg.BGM_PATH)
	pygame.mixer.music.play(-1)
	audios = {
				'count_down': pygame.mixer.Sound(cfg.COUNT_DOWN_SOUND_PATH),
				'hammering': pygame.mixer.Sound(cfg.HAMMERING_SOUND_PATH)
			}

4.1.2 Loading Fonts

	font = pygame.font.Font(cfg.FONT_PATH, 40)

4.1.3 Load background pictures

	bg_img = pygame.image.load(cfg.GAME_BG_IMAGEPATH)

4.1.4 Beginning Interface

	startInterface(screen, cfg.GAME_BEGIN_IMAGEPATHS)

4.1.5 Timing of Hamster Position Change

	hole_pos = random.choice(cfg.HOLE_POSITIONS)
	change_hole_event = pygame.USEREVENT
	pygame.time.set_timer(change_hole_event, 800)

4.1.6 Hamster

	mole = Mole(cfg.MOLE_IMAGEPATHS, hole_pos)

4.1.7 Hammer

	hammer = Hammer(cfg.HAMMER_IMAGEPATHS, (500, 250))

4.1.8 Clock

	clock = pygame.time.Clock()

4.1.9 Score

	your_score = 0

Level 4.1.10

	number = 1
	flag = False

4.1.11 Main Game Cycle

	while True:
		# --120s game time
		time_remain = round((121000 - pygame.time.get_ticks()) / 1000.)

4.1.12 Game time decreased and hamsters moved faster

		# First level
		if time_remain == 100 and not flag:
			hole_pos = random.choice(cfg.HOLE_POSITIONS)
			mole.reset()
			mole.setPosition(hole_pos)
			pygame.time.set_timer(change_hole_event, 650)
			flag = True

		# Second level
		elif time_remain == 80 and not flag:
			hole_pos = random.choice(cfg.HOLE_POSITIONS)
			mole.reset()
			mole.setPosition(hole_pos)
			pygame.time.set_timer(change_hole_event, 600)
			flag = True
		# Third level
		elif time_remain == 60 and not flag:
			hole_pos = random.choice(cfg.HOLE_POSITIONS)
			mole.reset()
			mole.setPosition(hole_pos)
			pygame.time.set_timer(change_hole_event, 550)
			flag = True

		# Level 4
		elif time_remain == 40 and not flag:
			hole_pos = random.choice(cfg.HOLE_POSITIONS)
			mole.reset()
			mole.setPosition(hole_pos)
			pygame.time.set_timer(change_hole_event, 500)
			flag = True

		# Level 5
		elif time_remain == 20 and flag:
			hole_pos = random.choice(cfg.HOLE_POSITIONS)
			mole.reset()
			mole.setPosition(hole_pos)
			pygame.time.set_timer(change_hole_event, 450)
			flag = False
		# Level display
		if time_remain == 100:
			number = 1
		elif time_remain == 80:
			number = 2
		elif time_remain == 60:
			number = 3
		elif time_remain == 40:
			number = 4
		elif time_remain == 20:
			number = 5

4.1.13 Countdown Sound

		if time_remain == 10:
			audios['count_down'].play()

4.1.14 Game over

		if time_remain < 0:
			break
		count_down_text = font.render('Time: '+str(time_remain), True, cfg.WHITE)

4.1.15 Key Detection

		for event in pygame.event.get():
			if event.type == pygame.QUIT:
				pygame.quit()
				sys.exit()
			elif event.type == pygame.MOUSEMOTION:
				hammer.setPosition(pygame.mouse.get_pos())
			elif event.type == pygame.MOUSEBUTTONDOWN:
				if event.button == 1:
					hammer.setHammering()
			elif event.type == change_hole_event:
				hole_pos = random.choice(cfg.HOLE_POSITIONS)
				mole.reset()
				mole.setPosition(hole_pos)

4.1.16 - Collision detection

		if hammer.is_hammering and not mole.is_hammer:
			is_hammer = pygame.sprite.collide_mask(hammer, mole)
			if is_hammer:
				audios['hammering'].play()
				mole.setBeHammered()
				your_score += 10

4.1.17 Score

		your_score_text = font.render('Score: '+str(your_score), True, cfg.BROWN)
		your_number_text2 = font.render('No. '+str(number)+'shut', True, cfg.WHITE)

4.1.18 Bind the necessary game elements to the screen (note the order)

		screen.blit(bg_img, (0, 0))
		screen.blit(count_down_text, (800, 8))
		screen.blit(your_score_text, (750, 430))
		screen.blit(your_number_text2, (600, 430))
		mole.draw(screen)
		hammer.draw(screen)

4.1.19 Read Best Score

	try:
		best_score = int(open(cfg.RECORD_PATH).read())
	except:
		best_score = 0

4.1.20 Update the best score if the current score is greater than the best score

	if your_score > best_score:
		f = open(cfg.RECORD_PATH, 'w')
		f.write(str(your_score))
		f.close()

4.1.21 End Interface

	score_info = {'your_score': your_score, 'best_score': best_score}
	is_restart = endInterface(screen, cfg.GAME_END_IMAGEPATH, cfg.GAME_AGAIN_IMAGEPATHS, score_info, cfg.FONT_PATH, [cfg.WHITE, cfg.RED], cfg.SCREENSIZE)
	return is_restart

4.2cfg.py file (basic configuration such as fonts)

import os
CURPATH = os.getcwd()
SCREENSIZE = (993, 477)
HAMMER_IMAGEPATHS = [os.path.join(CURPATH, 'resources/images/hammer0.png'), os.path.join(CURPATH, 'resources/images/hammer1.png')]
GAME_BEGIN_IMAGEPATHS = [os.path.join(CURPATH, 'resources/images/begin.png'), os.path.join(CURPATH, 'resources/images/begin1.png')]
GAME_AGAIN_IMAGEPATHS = [os.path.join(CURPATH, 'resources/images/again1.png'), os.path.join(CURPATH, 'resources/images/again2.png')]
GAME_BG_IMAGEPATH = os.path.join(CURPATH, 'resources/images/background.png')
GAME_END_IMAGEPATH = os.path.join(CURPATH, 'resources/images/end.png')
MOLE_IMAGEPATHS = [os.path.join(CURPATH, 'resources/images/mole_1.png'), os.path.join(CURPATH, 'resources/images/mole_laugh1.png'),
                   os.path.join(CURPATH, 'resources/images/mole_laugh2.png'), os.path.join(CURPATH, 'resources/images/mole_laugh3.png')]
HOLE_POSITIONS = [(90, -20), (405, -20), (720, -20), (90, 140), (405, 140), (720, 140), (90, 290), (405, 290), (720, 290)]
BGM_PATH = 'resources/audios/bgm.mp3'
COUNT_DOWN_SOUND_PATH = 'resources/audios/count_down.wav'
HAMMERING_SOUND_PATH = 'resources/audios/hammering.wav'
FONT_PATH = 'resources/font/Font stewardship fat baby body.ttf'
BROWN = (150, 75, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
RECORD_PATH = 'score.rec'

4.3mole.py file (hamster)

import pygame
class Mole(pygame.sprite.Sprite):
    def __init__(self, image_paths, position, **kwargs):
        pygame.sprite.Sprite.__init__(self)
        self.images = [pygame.transform.scale(pygame.image.load(image_paths[0]), (101, 103)), 
                       pygame.transform.scale(pygame.image.load(image_paths[-1]), (101, 103))]
        self.image = self.images[0]
        self.rect = self.image.get_rect()
        self.mask = pygame.mask.from_surface(self.image)
        self.setPosition(position)
        self.is_hammer = False

4.3.1 Set Location

    def setPosition(self, pos):
        self.rect.left, self.rect.top = pos

4.3.2 setting hit

    def setBeHammered(self):
        self.is_hammer = True

4.3.3 Display on screen

    def draw(self, screen):
        if self.is_hammer: self.image = self.images[1]
        screen.blit(self.image, self.rect)

4.3.4 Reset

    def reset(self):
        self.image = self.images[0]
        self.is_hammer = False

4.4hammer.py file (hammer)

import pygame
class Hammer(pygame.sprite.Sprite):
    def __init__(self, image_paths, position, **kwargs):
        pygame.sprite.Sprite.__init__(self)
        self.images = [pygame.image.load(image_paths[0]), pygame.image.load(image_paths[1])]
        self.image = self.images[0]
        self.rect = self.image.get_rect()
        self.mask = pygame.mask.from_surface(self.images[1])
        self.rect.left, self.rect.top = position

4.4.1 Used to show special effects when hammering

        self.hammer_count = 0
        self.hammer_last_time = 4
        self.is_hammering = False

4.4.2 Set Location

    def setPosition(self, pos):
        self.rect.centerx, self.rect.centery = pos

4.4.3 Setting up hammering

    def setHammering(self):
        self.is_hammering = True

4.4.4 Display on screen

    def draw(self, screen):
        if self.is_hammering:
            self.image = self.images[1]
            self.hammer_count += 1
            if self.hammer_count > self.hammer_last_time:
                self.is_hammering = False
                self.hammer_count = 0
        else:
            self.image = self.images[0]
        screen.blit(self.image, self.rect)

4.5endinterface.py file (end interface)

import sys
import pygame
def endInterface(screen, end_image_path, again_image_paths, score_info, font_path, font_colors, screensize):
    end_image = pygame.image.load(end_image_path)
    again_images = [pygame.image.load(again_image_paths[0]), pygame.image.load(again_image_paths[1])]
    again_image = again_images[0]
    font = pygame.font.Font(font_path, 50)
    your_score_text = font.render('Your Score: %s' % score_info['your_score'], True, font_colors[0])
    your_score_rect = your_score_text.get_rect()
    your_score_rect.left, your_score_rect.top = (screensize[0] - your_score_rect.width) / 2, 215
    best_score_text = font.render('Best Score: %s' % score_info['best_score'], True, font_colors[1])
    best_score_rect = best_score_text.get_rect()
    best_score_rect.left, best_score_rect.top = (screensize[0] - best_score_rect.width) / 2, 275
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEMOTION:
                mouse_pos = pygame.mouse.get_pos()
                if mouse_pos[0] in list(range(419, 574)) and mouse_pos[1] in list(range(374, 416)):
                    again_image = again_images[1]
                else:
                    again_image = again_images[0]
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1 and mouse_pos[0] in list(range(419, 574)) and mouse_pos[1] in list(range(374, 416)):
                    return True
        screen.blit(end_image, (0, 0))
        screen.blit(again_image, (416, 370))
        screen.blit(your_score_text, your_score_rect)
        screen.blit(best_score_text, best_score_rect)
        pygame.display.update()
        

4.6startinterface.py file (start interface)

import sys
import pygame
def startInterface(screen, begin_image_paths):
    begin_images = [pygame.image.load(begin_image_paths[0]), pygame.image.load(begin_image_paths[1])]
    begin_image = begin_images[0]
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEMOTION:
                mouse_pos = pygame.mouse.get_pos()
                if mouse_pos[0] in list(range(419, 574)) and mouse_pos[1] in list(range(374, 416)):
                    begin_image = begin_images[1]
                else:
                    begin_image = begin_images[0]
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1 and mouse_pos[0] in list(range(419, 574)) and mouse_pos[1] in list(range(374, 416)):
                    return True
        screen.blit(begin_image, (0, 0))
        pygame.display.update()

Posted by rigbyae on Mon, 06 Apr 2020 10:55:49 -0700