Author | Li Qiujian
Produced | AI Technology Base Camp (rgznai100)
"Tank Battle" is a multi-faceted plane shooting game launched by Namco Game Company of Japan on the Nintendo FC platform in 1985. The game is based on the theme of tank battles and defending the base, which is a strategic online category. At the same time, it is also one of the few games with a built-in level editor on the FC platform. Players can create their own unique levels and enhance the tank and base by obtaining some props. Today we will use python to restore the production of the following tank battle.
Preparation before experiment
First of all, the Python version we use is 3.6.5. The modules used are as follows:
Genie program
Among them, the wizard class is used as the basic program framework to call the main function, including bullet programs, food, home, brick walls, trees and other obstacles, and tanks. The specific program layout is as follows:
Among the bullet programs, you first need to establish the bullet.py program, which includes basic information such as bullet position, direction, image loading, bullet speed, etc. The specific code is as follows:
''' bullet'''classBullet(pygame.sprite.Sprite):
def __init__(self, bullet_image_paths, screensize, direction, position, border_len, is_stronger=False, speed=8,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.bullet_image_paths = bullet_image_paths
self.width, self.height = screensize
self.direction = direction
self.position = position
self.image = pygame.image.load(self.bullet_image_paths.get(direction))
self.rect = self.image.get_rect()
self.rect.center = position
# Map edge width
self.border_len = border_len
# Is it an enhanced bullet(Enhanced version of broken iron wall)
self.is_stronger = is_stronger
# Bullet speed
self.speed = speed
''' Move bullet,If the bullet goes out of bounds,Then returns True,Otherwise False'''
def move(self):if self.direction =='up':
self.rect = self.rect.move(0,-self.speed)
elif self.direction =='down':
self.rect = self.rect.move(0, self.speed)
elif self.direction =='left':
self.rect = self.rect.move(-self.speed,0)
elif self.direction =='right':
self.rect = self.rect.move(self.speed,0)if(self.rect.top < self.border_len)or(self.rect.bottom > self.height)or(self.rect.left < self.border_len)or(self.rect.right > self.width):return True
return False
Food reward category, establish food.py as basic rewards such as increasing life when the tank eats food:
''' Food.Used to get rewards'''classFoods(pygame.sprite.Sprite):
def __init__(self, food_image_paths, screensize,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.name = random.choice(list(food_image_paths.keys()))
self.image = pygame.image.load(food_image_paths.get(self.name))
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = random.randint(100, screensize[0]-100), random.randint(100, screensize[1]-100)
self.exist_time =1000
def update(self):
self.exist_time -=1return True if self.exist_time <0else False
Tank family, establish home.py to store basic information (including whether it is alive, image loading, location size, etc.).
''' Base Camp'''classHome(pygame.sprite.Sprite):
def __init__(self, position, imagepaths,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.imagepaths = imagepaths
self.image = pygame.image.load(self.imagepaths[0])
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
self.alive = True
''' was destroyed'''
def setDead(self):
self.image = pygame.image.load(self.imagepaths[1])
self.alive = False
''' Draw on the screen'''
def draw(self, screen):
screen.blit(self.image, self.rect)
For obstacles such as brick walls, create scenes.py which is also the layout of the main position size:
''' Brick wall'''classBrick(pygame.sprite.Sprite):
def __init__(self, position, imagepath,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(imagepath)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
''' Iron wall'''classIron(pygame.sprite.Sprite):
def __init__(self, position, imagepath,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(imagepath)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
''' ice'''classIce(pygame.sprite.Sprite):
def __init__(self, position, imagepath,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((24,24))for i inrange(2):for j inrange(2):
self.image.blit(pygame.image.load(imagepath),(12*i,12*j))
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
''' river'''classRiver(pygame.sprite.Sprite):
def __init__(self, position, imagepath,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((24,24))for i inrange(2):for j inrange(2):
self.image.blit(pygame.image.load(imagepath),(12*i,12*j))
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
''' tree'''classTree(pygame.sprite.Sprite):
def __init__(self, position, imagepath,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((24,24))for i inrange(2):for j inrange(2):
self.image.blit(pygame.image.load(imagepath),(12*i,12*j))
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
For tanks, create tanks.py to include information such as the number of tanks, the initial position, etc.:
''' Player tank'''classPlayerTank(pygame.sprite.Sprite):
def __init__(self, name, player_tank_image_paths, position, border_len, screensize, direction='up', bullet_image_paths=None, protected_mask_path=None, boom_image_path=None,**kwargs):
pygame.sprite.Sprite.__init__(self)
# Player 1/Player 2
self.name = name
# Tank picture path
self.player_tank_image_paths = player_tank_image_paths.get(name)
# Map edge width
self.border_len = border_len
# Screen size
self.screensize = screensize
# Initial tank orientation
self.init_direction = direction
# initial position
self.init_position = position
# Bullet pictures
self.bullet_image_paths = bullet_image_paths
# Protective cover picture path
self.protected_mask = pygame.image.load(protected_mask_path)
self.protected_mask_flash_time =25
self.protected_mask_flash_count =0
self.protected_mask_pointer = False
# Tank explosion view
self.boom_image = pygame.image.load(boom_image_path)
self.boom_last_time =5
self.booming_flag = False
self.boom_count =0
# Number of tank lives
self.num_lifes =3
# Reset
self.reset()'''mobile'''
def move(self, direction, scene_elems, player_tanks_group, enemy_tanks_group, home):
# Cannot move when exploding
if self.booming_flag:return
# Change the direction first if the direction is inconsistent
if self.direction != direction:
self.setDirection(direction)
self.switch_count = self.switch_time
self.move_cache_count = self.move_cache_time
# mobile(Use buffer)
self.move_cache_count +=1if self.move_cache_count < self.move_cache_time:return
self.move_cache_count =0if self.direction =='up':
speed =(0,-self.speed)
elif self.direction =='down':
speed =(0, self.speed)
elif self.direction =='left':
speed =(-self.speed,0)
elif self.direction =='right':
speed =(self.speed,0)
rect_ori = self.rect
self.rect = self.rect.move(speed)
# - - Encounter scene elements
for key, value in scene_elems.items():if key in['brick_group','iron_group','river_group']:if pygame.sprite.spritecollide(self, value, False, None):
self.rect = rect_ori
elif key in['ice_group']:if pygame.sprite.spritecollide(self, value, False, None):
self.rect = self.rect.move(speed)
# - - Encountered other players' tanks
if pygame.sprite.spritecollide(self, player_tanks_group, False, None):
self.rect = rect_ori
# - - Encounter an enemy tank
if pygame.sprite.spritecollide(self, enemy_tanks_group, False, None):
self.rect = rect_ori
# - - Meet the player base camp
if pygame.sprite.collide_rect(self, home):
self.rect = rect_ori
# - - Hit the boundary
if self.rect.left < self.border_len:
self.rect.left = self.border_len
elif self.rect.right > self.screensize[0]-self.border_len:
self.rect.right = self.screensize[0]- self.border_len
elif self.rect.top < self.border_len:
self.rect.top = self.border_len
elif self.rect.bottom > self.screensize[1]-self.border_len:
self.rect.bottom = self.screensize[1]- self.border_len
# Switch pictures for tank wheel motion effects
self.switch_count +=1if self.switch_count > self.switch_time:
self.switch_count =0
self.switch_pointer = not self.switch_pointer
self.image = self.tank_direction_image.subsurface((48*int(self.switch_pointer),0),(48,48))
Game interface settings
Game interface settings include: start interface settings, end interface settings, and level switching interface settings:
The game start interface includes the selection of the number of players and the loading of pictures and music:
''' Game start interface'''
def gameStartInterface(screen, cfg):
background_img = pygame.image.load(cfg.OTHER_IMAGE_PATHS.get('background'))
color_white =(255,255,255)
color_red =(255,0,0)
font = pygame.font.Font(cfg.FONTPATH, cfg.WIDTH//12)
logo_img = pygame.image.load(cfg.OTHER_IMAGE_PATHS.get('logo'))
logo_img = pygame.transform.scale(logo_img,(446,70))
logo_rect = logo_img.get_rect()
logo_rect.centerx, logo_rect.centery = cfg.WIDTH/2, cfg.HEIGHT//4
tank_cursor = pygame.image.load(cfg.PLAYER_TANK_IMAGE_PATHS.get('player1')[0]).convert_alpha().subsurface((0,144),(48,48))
tank_rect = tank_cursor.get_rect()
# Number of players selection
player_render_white = font.render('1 PLAYER', True, color_white)
player_render_red = font.render('1 PLAYER', True, color_red)
player_rect = player_render_white.get_rect()
player_rect.left, player_rect.top = cfg.WIDTH/2.8, cfg.HEIGHT/2.5
players_render_white = font.render('2 PLAYERS', True, color_white)
players_render_red = font.render('2 PLAYERS', True, color_red)
players_rect = players_render_white.get_rect()
players_rect.left, players_rect.top = cfg.WIDTH/2.8, cfg.HEIGHT/2
# Game tips
game_tip = font.render('press <Enter> to start', True, color_white)
game_tip_rect = game_tip.get_rect()
game_tip_rect.centerx, game_tip_rect.top = cfg.WIDTH/2, cfg.HEIGHT/1.4
game_tip_flash_time =25
game_tip_flash_count =0
game_tip_show_flag = True
# Main loop
clock = pygame.time.Clock()
is_dual_mode = False
while True:for event in pygame.event.get():if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:if event.key == pygame.K_RETURN:return is_dual_mode
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN or event.key == pygame.K_w or event.key == pygame.K_s:
is_dual_mode = not is_dual_mode
screen.blit(background_img,(0,0))
screen.blit(logo_img, logo_rect)
game_tip_flash_count +=1if game_tip_flash_count > game_tip_flash_time:
game_tip_show_flag = not game_tip_show_flag
game_tip_flash_count =0if game_tip_show_flag:
screen.blit(game_tip, game_tip_rect)if not is_dual_mode:
tank_rect.right, tank_rect.top = player_rect.left-10, player_rect.top
screen.blit(tank_cursor, tank_rect)
screen.blit(player_render_red, player_rect)
screen.blit(players_render_white, players_rect)else:
tank_rect.right, tank_rect.top = players_rect.left-10, players_rect.top
screen.blit(tank_cursor, tank_rect)
screen.blit(player_render_white, player_rect)
screen.blit(players_render_red, players_rect)
pygame.display.update()
clock.tick(60)
The end of the game interface includes the judgment of game victory and failure, and whether to exit the game or restart the setting:
''' Game over interface'''
def gameEndIterface(screen, cfg, is_win=True):
background_img = pygame.image.load(cfg.OTHER_IMAGE_PATHS.get('background'))
color_white =(255,255,255)
color_red =(255,0,0)
font = pygame.font.Font(cfg.FONTPATH, cfg.WIDTH//12)
# Game failure graph
gameover_img = pygame.image.load(cfg.OTHER_IMAGE_PATHS.get('gameover'))
gameover_img = pygame.transform.scale(gameover_img,(150,75))
gameover_img_rect = gameover_img.get_rect()
gameover_img_rect.midtop = cfg.WIDTH/2, cfg.HEIGHT/8
gameover_flash_time =25
gameover_flash_count =0
gameover_show_flag = True
# Tips for winning the game
if is_win:
font_render = font.render('Congratulations, You win!', True, color_white)else:
font_render = font.render('Sorry, You fail!', True, color_white)
font_rect = font_render.get_rect()
font_rect.centerx, font_rect.centery = cfg.WIDTH/2, cfg.HEIGHT/3
# Used to opt out or restart
tank_cursor = pygame.image.load(cfg.PLAYER_TANK_IMAGE_PATHS.get('player1')[0]).convert_alpha().subsurface((0,144),(48,48))
tank_rect = tank_cursor.get_rect()
restart_render_white = font.render('RESTART', True, color_white)
restart_render_red = font.render('RESTART', True, color_red)
restart_rect = restart_render_white.get_rect()
restart_rect.left, restart_rect.top = cfg.WIDTH/2.4, cfg.HEIGHT/2
quit_render_white = font.render('QUIT', True, color_white)
quit_render_red = font.render('QUIT', True, color_red)
quit_rect = quit_render_white.get_rect()
quit_rect.left, quit_rect.top = cfg.WIDTH/2.4, cfg.HEIGHT/1.6
is_quit_game = False
# Main loop
clock = pygame.time.Clock()while True:for event in pygame.event.get():if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:if event.key == pygame.K_RETURN:return is_quit_game
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN or event.key == pygame.K_w or event.key == pygame.K_s:
is_quit_game = not is_quit_game
screen.blit(background_img,(0,0))
gameover_flash_count +=1if gameover_flash_count > gameover_flash_time:
gameover_show_flag = not gameover_show_flag
gameover_flash_count =0if gameover_show_flag:
screen.blit(gameover_img, gameover_img_rect)
screen.blit(font_render, font_rect)if not is_quit_game:
tank_rect.right, tank_rect.top = restart_rect.left-10, restart_rect.top
screen.blit(tank_cursor, tank_rect)
screen.blit(restart_render_red, restart_rect)
screen.blit(quit_render_white, quit_rect)else:
tank_rect.right, tank_rect.top = quit_rect.left-10, quit_rect.top
screen.blit(tank_cursor, tank_rect)
screen.blit(restart_render_white, restart_rect)
screen.blit(quit_render_red, quit_rect)
pygame.display.update()
clock.tick(60)
The game interface switch is mainly loaded by the progress bar:
''' Level switching interface'''
def switchLevelIterface(screen, cfg, level_next=1):
background_img = pygame.image.load(cfg.OTHER_IMAGE_PATHS.get('background'))
color_white =(255,255,255)
color_gray =(192,192,192)
font = pygame.font.Font(cfg.FONTPATH, cfg.WIDTH//20)
logo_img = pygame.image.load(cfg.OTHER_IMAGE_PATHS.get('logo'))
logo_img = pygame.transform.scale(logo_img,(446,70))
logo_rect = logo_img.get_rect()
logo_rect.centerx, logo_rect.centery = cfg.WIDTH/2, cfg.HEIGHT//4
# Game loading tips
font_render = font.render('Loading game data, You will enter Level-%s'% level_next, True, color_white)
font_rect = font_render.get_rect()
font_rect.centerx, font_rect.centery = cfg.WIDTH/2, cfg.HEIGHT/2
# Game loading progress bar
gamebar = pygame.image.load(cfg.OTHER_IMAGE_PATHS.get('gamebar')).convert_alpha()
gamebar_rect = gamebar.get_rect()
gamebar_rect.centerx, gamebar_rect.centery = cfg.WIDTH/2, cfg.HEIGHT/1.4
tank_cursor = pygame.image.load(cfg.PLAYER_TANK_IMAGE_PATHS.get('player1')[0]).convert_alpha().subsurface((0,144),(48,48))
tank_rect = tank_cursor.get_rect()
tank_rect.left = gamebar_rect.left
tank_rect.centery = gamebar_rect.centery
# Loading time
load_time_left = gamebar_rect.right - tank_rect.right +8
# Main loop
clock = pygame.time.Clock()while True:for event in pygame.event.get():if event.type == pygame.QUIT:
pygame.quit()
sys.exit()if load_time_left <=0:return
screen.blit(background_img,(0,0))
screen.blit(logo_img, logo_rect)
screen.blit(font_render, font_rect)
screen.blit(gamebar, gamebar_rect)
screen.blit(tank_cursor, tank_rect)
pygame.draw.rect(screen, color_gray,(gamebar_rect.left+8, gamebar_rect.top+8, tank_rect.left-gamebar_rect.left-8, tank_rect.bottom-gamebar_rect.top-16))
tank_rect.left +=1
load_time_left -=1
pygame.display.update()
clock.tick(60)
Complete code:
Extraction code: 09bl
***Author: Qiu key ***
***CSDN blog expert, CSDN master class author. He is currently studying at China University of Mining and Technology, and has won tappap competitions. ***
Recommended Posts