Pygame actual combat: the work of God worship inherited for 40 years - bomber college game! [source code attached]

Keywords: Python pygame

Introduction

In this impetuous age: Xiaobian's glory of the king every time he lands, and stimulating battlefield Z every time he lands!

Look at the chat interface inside, all kinds of generation calls and all kinds of search cp. Xiaobian feels that we have lost our original intention to play games.

Next, xiaotai will lead you back to your childhood and appreciate the simplicity and innocence of our original 4399 game!

I still remember when I was a child, every time after school, I would take my little cousin who was only half my age to play computer at my relatives' house

Every time I open the computer, the first thing I do is to open the browser and enter the four numbers of 4399. At that time, I thought hao123 was really a magical home page!

Can let me open 4399 to play all kinds of games qwq, especially the Q version bubble hall won my heart!

Then today I'll take you to recall your childhood and make a classic Bomber game!

text

The rules of the game are still clear. I won't introduce more. Those who don't know how to play can Baidu!

First, prepare the corresponding materials: [part is as follows]

Bomber main program:

import sys
import cfg
import random
import pygame
from modules import *


'''Game main program'''
def main(cfg):
    # initialization
    pygame.init()
    pygame.mixer.init()
    pygame.mixer.music.load(cfg.BGMPATH)
    pygame.mixer.music.play(-1, 0.0)
    screen = pygame.display.set_mode(cfg.SCREENSIZE)
    pygame.display.set_caption('Bomber - source code base:#959755565#')
    # Start interface
    Interface(screen, cfg, mode='game_start')
    # Game main loop
    font = pygame.font.SysFont('Consolas', 15)
    for gamemap_path in cfg.GAMEMAPPATHS:
        # -Maps
        map_parser = mapParser(gamemap_path, bg_paths=cfg.BACKGROUNDPATHS, wall_paths=cfg.WALLPATHS, blocksize=cfg.BLOCKSIZE)
        # -Fruit
        fruit_sprite_group = pygame.sprite.Group()
        used_spaces = []
        for i in range(5):
            coordinate = map_parser.randomGetSpace(used_spaces)
            used_spaces.append(coordinate)
            fruit_sprite_group.add(Fruit(random.choice(cfg.FRUITPATHS), coordinate=coordinate, blocksize=cfg.BLOCKSIZE))
        # -Our Hero
        coordinate = map_parser.randomGetSpace(used_spaces)
        used_spaces.append(coordinate)
        ourhero = Hero(imagepaths=cfg.HEROZELDAPATHS, coordinate=coordinate, blocksize=cfg.BLOCKSIZE, map_parser=map_parser, hero_name='ZELDA')
        # -Computer Hero
        aihero_sprite_group = pygame.sprite.Group()
        coordinate = map_parser.randomGetSpace(used_spaces)
        aihero_sprite_group.add(Hero(imagepaths=cfg.HEROBATMANPATHS, coordinate=coordinate, blocksize=cfg.BLOCKSIZE, map_parser=map_parser, hero_name='BATMAN'))
        used_spaces.append(coordinate)
        coordinate = map_parser.randomGetSpace(used_spaces)
        aihero_sprite_group.add(Hero(imagepaths=cfg.HERODKPATHS, coordinate=coordinate, blocksize=cfg.BLOCKSIZE, map_parser=map_parser, hero_name='DK'))
        used_spaces.append(coordinate)
        # -bomb
        bomb_sprite_group = pygame.sprite.Group()
        # -flag used to judge the victory or failure of the game
        is_win_flag = False
        # -Main cycle
        screen = pygame.display.set_mode(map_parser.screen_size)
        clock = pygame.time.Clock()
        while True:
            dt = clock.tick(cfg.FPS)
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit(-1)
                # --↑↓←→ key to control up, down, left and right, space bar to drop bomb
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_UP:
                        ourhero.move('up')
                    elif event.key == pygame.K_DOWN:
                        ourhero.move('down')
                    elif event.key == pygame.K_LEFT:
                        ourhero.move('left')
                    elif event.key == pygame.K_RIGHT:
                        ourhero.move('right')
                    elif event.key == pygame.K_SPACE:
                        if ourhero.bomb_cooling_count <= 0:
                            bomb_sprite_group.add(ourhero.generateBomb(imagepath=cfg.BOMBPATH, digitalcolor=cfg.YELLOW, explode_imagepath=cfg.FIREPATH))
            screen.fill(cfg.WHITE)
            # --Computer Hero random action
            for hero in aihero_sprite_group:
                action, flag = hero.randomAction(dt)
                if flag and action == 'dropbomb':
                    bomb_sprite_group.add(hero.generateBomb(imagepath=cfg.BOMBPATH, digitalcolor=cfg.YELLOW, explode_imagepath=cfg.FIREPATH))
            # --Eat fruit and add HP (as long as Hero can add)
            ourhero.eatFruit(fruit_sprite_group)
            for hero in aihero_sprite_group:
                hero.eatFruit(fruit_sprite_group)
            # --Game elements are bound to the screen
            map_parser.draw(screen)
            for bomb in bomb_sprite_group:
                if not bomb.is_being:
                    bomb_sprite_group.remove(bomb)
                explode_area = bomb.draw(screen, dt, map_parser)
                if explode_area:
                    # --Hero's health within the explosion flame range will continue to decrease
                    if ourhero.coordinate in explode_area:
                        ourhero.health_value -= bomb.harm_value
                    for hero in aihero_sprite_group:
                        if hero.coordinate in explode_area:
                            hero.health_value -= bomb.harm_value
            fruit_sprite_group.draw(screen)
            for hero in aihero_sprite_group:
                hero.draw(screen, dt)
            ourhero.draw(screen, dt)
            # --The upper left corner displays health
            pos_x = showText(screen, font, text=ourhero.hero_name+'(our):'+str(ourhero.health_value), color=cfg.YELLOW, position=[5, 5])
            for hero in aihero_sprite_group:
                pos_x, pos_y = pos_x+15, 5
                pos_x = showText(screen, font, text=hero.hero_name+'(ai):'+str(hero.health_value), color=cfg.YELLOW, position=[pos_x, pos_y])
            # --If our player's HP is less than or equal to 0 / the computer player's HP is less than or equal to 0, the game is judged to be over
            if ourhero.health_value <= 0:
                is_win_flag = False
                break
            for hero in aihero_sprite_group:
                if hero.health_value <= 0:
                    aihero_sprite_group.remove(hero)
            if len(aihero_sprite_group) == 0:
                is_win_flag = True
                break
            pygame.display.update()
            clock.tick(cfg.FPS)
        if is_win_flag:
            Interface(screen, cfg, mode='game_switch')
        else:
            break
    Interface(screen, cfg, mode='game_end')


'''run'''
if __name__ == '__main__':
    while True:
        main(cfg)

The starting interface is as follows:

Define map classes:

class mapParser():
	def __init__(self, mapfilepath, bg_paths, wall_paths, blocksize, **kwargs):
		self.instances_list = self.__parse(mapfilepath)
		self.bg_paths = bg_paths
		self.wall_paths = wall_paths
		self.blocksize = blocksize
		self.height = len(self.instances_list)
		self.width = len(self.instances_list[0])
		self.screen_size = (blocksize * self.width, blocksize * self.height)
	'''Draw the map on the screen'''
	def draw(self, screen):
		for j in range(self.height):
			for i in range(self.width):
				instance = self.instances_list[j][i]
				if instance == 'w':
					elem = Wall(self.wall_paths[0], [i, j], self.blocksize)
				elif instance == 'x':
					elem = Wall(self.wall_paths[1], [i, j], self.blocksize)
				elif instance == 'z':
					elem = Wall(self.wall_paths[2], [i, j], self.blocksize)
				elif instance == '0':
					elem = Background(self.bg_paths[0], [i, j], self.blocksize)
				elif instance == '1':
					elem = Background(self.bg_paths[1], [i, j], self.blocksize)
				elif instance == '2':
					elem = Background(self.bg_paths[2], [i, j], self.blocksize)
				else:
					raise ValueError('instance parse error in mapParser.draw...')
				elem.draw(screen)
	'''Random acquisition of an open space'''
	def randomGetSpace(self, used_spaces=None):
		while True:
			i = random.randint(0, self.width-1)
			j = random.randint(0, self.height-1)
			coordinate = [i, j]
			if used_spaces and coordinate in used_spaces:
				continue
			instance = self.instances_list[j][i]
			if instance in ['0', '1', '2']:
				break
		return coordinate
	'''Get element type from coordinates'''
	def getElemByCoordinate(self, coordinate):
		return self.instances_list[coordinate[1]][coordinate[0]]
	'''analysis.map file'''
	def __parse(self, mapfilepath):
		instances_list = []
		with open(mapfilepath) as f:
			for line in f.readlines():
				instances_line_list = []
				for c in line:
					if c in ['w', 'x', 'z', '0', '1', '2']:
						instances_line_list.append(c)
				instances_list.append(instances_line_list)
		return instances_list

Define some necessary elf classes: characters, fruits, etc.

'''Wall class'''
class Wall(pygame.sprite.Sprite):
	def __init__(self, imagepath, coordinate, blocksize, **kwargs):
		pygame.sprite.Sprite.__init__(self)
		self.image = pygame.image.load(imagepath)
		self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
		self.rect = self.image.get_rect()
		self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
		self.coordinate = coordinate
		self.blocksize = blocksize
	'''Draw to screen'''
	def draw(self, screen):
		screen.blit(self.image, self.rect)
		return True


'''Background class'''
class Background(pygame.sprite.Sprite):
	def __init__(self, imagepath, coordinate, blocksize, **kwargs):
		pygame.sprite.Sprite.__init__(self)
		self.image = pygame.image.load(imagepath)
		self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
		self.rect = self.image.get_rect()
		self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
		self.coordinate = coordinate
		self.blocksize = blocksize
	'''Draw to screen'''
	def draw(self, screen):
		screen.blit(self.image, self.rect)
		return True


'''Fruits'''
class Fruit(pygame.sprite.Sprite):
	def __init__(self, imagepath, coordinate, blocksize, **kwargs):
		pygame.sprite.Sprite.__init__(self)
		self.kind = imagepath.split('/')[-1].split('.')[0]
		if self.kind == 'banana':
			self.value = 5
		elif self.kind == 'cherry':
			self.value = 10
		else:
			raise ValueError('Unknow fruit %s...' % self.kind)
		self.image = pygame.image.load(imagepath)
		self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
		self.rect = self.image.get_rect()
		self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
		self.coordinate = coordinate
		self.blocksize = blocksize
	'''Draw to screen'''
	def draw(self, screen):
		screen.blit(self.image, self.rect)
		return True


'''Bomb class'''
class Bomb(pygame.sprite.Sprite):
	def __init__(self, imagepath, coordinate, blocksize, digitalcolor, explode_imagepath, **kwargs):
		pygame.sprite.Sprite.__init__(self)
		self.image = pygame.image.load(imagepath)
		self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
		self.explode_imagepath = explode_imagepath
		self.rect = self.image.get_rect()
		# Pixel position
		self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
		# Coordinates (unit length of element block)
		self.coordinate = coordinate
		self.blocksize = blocksize
		# Explosion countdown
		self.explode_millisecond = 6000 * 1 - 1
		self.explode_second = int(self.explode_millisecond / 1000)
		self.start_explode = False
		# Explosion duration
		self.exploding_count = 1000 * 1
		# Bomb damage ability
		self.harm_value = 1
		# Does the bomb still exist
		self.is_being = True
		self.font = pygame.font.SysFont('Consolas', 20)
		self.digitalcolor = digitalcolor
	'''Draw to screen'''
	def draw(self, screen, dt, map_parser):
		if not self.start_explode:
			# Explosion countdown
			self.explode_millisecond -= dt
			self.explode_second = int(self.explode_millisecond / 1000)
			if self.explode_millisecond < 0:
				self.start_explode = True
			screen.blit(self.image, self.rect)
			text = self.font.render(str(self.explode_second), True, self.digitalcolor)
			rect = text.get_rect(center=(self.rect.centerx-5, self.rect.centery+5))
			screen.blit(text, rect)
			return False
		else:
			# Continuous countdown to explosion
			self.exploding_count -= dt
			if self.exploding_count > 0:
				return self.__explode(screen, map_parser)
			else:
				self.is_being = False
				return False
	'''Explosion effect'''
	def __explode(self, screen, map_parser):
		explode_area = self.__calcExplodeArea(map_parser.instances_list)
		for each in explode_area:
			image = pygame.image.load(self.explode_imagepath)
			image = pygame.transform.scale(image, (self.blocksize, self.blocksize))
			rect = image.get_rect()
			rect.left, rect.top = each[0] * self.blocksize, each[1] * self.blocksize
			screen.blit(image, rect)
		return explode_area
	'''Calculate explosion area'''
	def __calcExplodeArea(self, instances_list):
		explode_area = []
		# The area calculation rule is that the wall can prevent the explosion from spreading, and the explosion range is only within the range of the game map
		for ymin in range(self.coordinate[1], self.coordinate[1]-5, -1):
			if ymin < 0 or instances_list[ymin][self.coordinate[0]] in ['w', 'x', 'z']:
				break
			explode_area.append([self.coordinate[0], ymin])
		for ymax in range(self.coordinate[1]+1, self.coordinate[1]+5):
			if ymax >= len(instances_list) or instances_list[ymax][self.coordinate[0]] in ['w', 'x', 'z']:
				break
			explode_area.append([self.coordinate[0], ymax])
		for xmin in range(self.coordinate[0], self.coordinate[0]-5, -1):
			if xmin < 0 or instances_list[self.coordinate[1]][xmin] in ['w', 'x', 'z']:
				break
			explode_area.append([xmin, self.coordinate[1]])
		for xmax in range(self.coordinate[0]+1, self.coordinate[0]+5):
			if xmax >= len(instances_list[0]) or instances_list[self.coordinate[1]][xmax] in ['w', 'x', 'z']:
				break
			explode_area.append([xmax, self.coordinate[1]])
		return explode_area


'''Role class'''
class Hero(pygame.sprite.Sprite):
	def __init__(self, imagepaths, coordinate, blocksize, map_parser, **kwargs):
		pygame.sprite.Sprite.__init__(self)
		self.imagepaths = imagepaths
		self.image = pygame.image.load(imagepaths[-1])
		self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
		self.rect = self.image.get_rect()
		self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
		self.coordinate = coordinate
		self.blocksize = blocksize
		self.map_parser = map_parser
		self.hero_name = kwargs.get('hero_name')
		# Life value
		self.health_value = 50
		# Bomb cooldown
		self.bomb_cooling_time = 5000
		self.bomb_cooling_count = 0
		# Random movement cooling time (for AI computers only)
		self.randommove_cooling_time = 100
		self.randommove_cooling_count = 0
	'''Character movement'''
	def move(self, direction):
		self.__updateImage(direction)
		if direction == 'left':
			if self.coordinate[0]-1 < 0 or self.map_parser.getElemByCoordinate([self.coordinate[0]-1, self.coordinate[1]]) in ['w', 'x', 'z']:
				return False
			self.coordinate[0] = self.coordinate[0] - 1
		elif direction == 'right':
			if self.coordinate[0]+1 >= self.map_parser.width or self.map_parser.getElemByCoordinate([self.coordinate[0]+1, self.coordinate[1]]) in ['w', 'x', 'z']:
				return False
			self.coordinate[0] = self.coordinate[0] + 1
		elif direction == 'up':
			if self.coordinate[1]-1 < 0 or self.map_parser.getElemByCoordinate([self.coordinate[0], self.coordinate[1]-1]) in ['w', 'x', 'z']:
				return False
			self.coordinate[1] = self.coordinate[1] - 1
		elif direction == 'down':
			if self.coordinate[1]+1 >= self.map_parser.height or self.map_parser.getElemByCoordinate([self.coordinate[0], self.coordinate[1]+1]) in ['w', 'x', 'z']:
				return False
			self.coordinate[1] = self.coordinate[1] + 1
		else:
			raise ValueError('Unknow direction %s...' % direction)
		self.rect.left, self.rect.top = self.coordinate[0] * self.blocksize, self.coordinate[1] * self.blocksize
		return True
	'''Random action(AI Computer use)'''
	def randomAction(self, dt):
		# Cooling down countdown
		if self.randommove_cooling_count > 0:
			self.randommove_cooling_count -= dt
		action = random.choice(['left', 'left', 'right', 'right', 'up', 'up', 'down', 'down', 'dropbomb'])
		flag = False
		if action in ['left', 'right', 'up', 'down']:
			if self.randommove_cooling_count <= 0:
				flag = True
				self.move(action)
				self.randommove_cooling_count = self.randommove_cooling_time
		elif action in ['dropbomb']:
			if self.bomb_cooling_count <= 0:
				flag = True
				self.bomb_cooling_count = self.bomb_cooling_time
		return action, flag
	'''Generate bomb'''
	def generateBomb(self, imagepath, digitalcolor, explode_imagepath):
		return Bomb(imagepath=imagepath, coordinate=copy.deepcopy(self.coordinate), blocksize=self.blocksize, digitalcolor=digitalcolor, explode_imagepath=explode_imagepath)
	'''Draw to screen'''
	def draw(self, screen, dt):
		# Cooling down countdown
		if self.bomb_cooling_count > 0:
			self.bomb_cooling_count -= dt
		screen.blit(self.image, self.rect)
		return True
	'''eat fruit'''
	def eatFruit(self, fruit_sprite_group):
		eaten_fruit = pygame.sprite.spritecollide(self, fruit_sprite_group, True, None)
		for fruit in eaten_fruit:
			self.health_value += fruit.value
	'''Update character orientation'''
	def __updateImage(self, direction):
		directions = ['left', 'right', 'up', 'down']
		idx = directions.index(direction)
		self.image = pygame.image.load(self.imagepaths[idx])
		self.image = pygame.transform.scale(self.image, (self.blocksize, self.blocksize))

The effects are as follows:

This exquisite picture is OK ~ hahaha, praise me, praise me~

summary

Ann! The article is written here. Your support is my biggest driving force. Remember the third consecutive Oh ~ wood!

Complete source code + material old rules source code base: click the blue font to get it for free!

Warm tips: don't forget to like, pay attention and comment! Look at the bomb in my hand~

Posted by Shuriken1 on Tue, 21 Sep 2021 23:36:44 -0700