Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”
preface
In the next few episodes, I will take you hand in hand to achieve the magic Tower from scratch this little game (is the old friends often play that picture
The development tools
Python version: 3.7.4
Related modules:
Pygame module;
And some modules that come with Python.
Environment set up
Install Python and add it to the environment variables. PIP installs the required related modules.
Introduction of the principle
First, we went to the start screen of the original game and found something like this:
Specifically, the idea is to define a button class to simulate the function of the three buttons in the original game: “Start game”, “Game description” and “Leave game” :
"Button class"
class Button(pygame.sprite.Sprite) :
def __init__(self, text, fontpath, fontsize, position, color_selected=(255.0.0), color_default=(255.255.255)) :
pygame.sprite.Sprite.__init__(self)
self.text = text
self.color_selected = color_selected
self.color_default = color_default
self.font = pygame.font.Font(fontpath, fontsize)
self.font_render = self.font.render(text, True, color_default)
self.rect = self.font_render.get_rect()
self.rect.center = position
Update function: continuously update to check whether the mouse is on the button.
def update(self) :
mouse_pos = pygame.mouse.get_pos()
if self.rect.collidepoint(mouse_pos):
self.font_render = self.font.render(self.text, True, self.color_selected)
else:
self.font_render = self.font.render(self.text, True, self.color_default)
Bind to screen
def draw(self, screen) :
screen.blit(self.font_render, self.rect)
Copy the code
The main idea is to constantly check if the mouse is in the corresponding button area, and if so, change the color of the button (red in this case), otherwise use the default color (white in this case) to indicate to the player that it is clickable.
Then, we instantiate it three times to add these three buttons to the game’s start screen:
"Game start screen"
class StartGameInterface() :
def __init__(self, cfg) :
self.cfg = cfg
self.play_btn = Button('Start the game', cfg.FONTPATH_CN, 50, (cfg.SCREENSIZE[0] / /2, cfg.SCREENSIZE[1] - 400))
self.intro_btn = Button('Game Notes', cfg.FONTPATH_CN, 50, (cfg.SCREENSIZE[0] / /2, cfg.SCREENSIZE[1] - 300))
self.quit_btn = Button('Leave the game', cfg.FONTPATH_CN, 50, (cfg.SCREENSIZE[0] / /2, cfg.SCREENSIZE[1] - 200))
"External call"
def run(self, screen) :
# found
font = pygame.font.Font(self.cfg.FONTPATH_CN, 80)
font_render_cn = font.render('found'.True, (255.255.255))
rect_cn = font_render_cn.get_rect()
rect_cn.center = self.cfg.SCREENSIZE[0] / /2.200
# Magic Tower
font = pygame.font.Font(self.cfg.FONTPATH_EN, 80)
font_render_en = font.render('Magic Tower'.True, (255.255.255))
rect_en = font_render_en.get_rect()
rect_en.center = self.cfg.SCREENSIZE[0] / /2.350
# (Ver 1.12)
font = pygame.font.Font(self.cfg.FONTPATH_CN, 40)
font_render_version = font.render('(Ver 1.12)'.True, (255.255.255))
rect_ver = font_render_version.get_rect()
rect_ver.center = self.cfg.SCREENSIZE[0] / /2.400
clock = pygame.time.Clock()
while True:
screen.fill((0.0.0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit(0)
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
mouse_pos = pygame.mouse.get_pos()
if self.play_btn.rect.collidepoint(mouse_pos):
return True
elif self.quit_btn.rect.collidepoint(mouse_pos):
pygame.quit()
sys.exit(0)
elif self.intro_btn.rect.collidepoint(mouse_pos):
self.showgameintro(screen)
for btn in [self.intro_btn, self.play_btn, self.quit_btn]:
btn.update()
btn.draw(screen)
for fr, rect in zip([font_render_cn, font_render_en, font_render_version], [rect_cn, rect_en, rect_ver]):
screen.blit(fr, rect)
pygame.display.flip()
clock.tick(self.cfg.FPS)
"Show game introduction"
def showgameintro(self, screen) :
font = pygame.font.Font(self.cfg.FONTPATH_CN, 20)
font_renders = [
font.render('Tower game.'.True, (255.255.255)),
font.render('the game footage from: http://www.4399.com/flash/1749_1.htm..True, (255.255.255)),
font.render('The backstory of the game is that the princess is captured by the demon king, and the warrior needs to go to the demon tower to rescue it.'.True, (255.255.255)),
font.render('Python Project Lion.'.True, (255.255.255)),
font.render('Wechat official account: Python Project Lion.'.True, (255.255.255)),
font.render(All Rights reserved..True, (255.255.255)),
]
rects = [fr.get_rect() for fr in font_renders]
for idx, rect in enumerate(rects):
rect.center = self.cfg.SCREENSIZE[0] / /2.50 * idx + 100
clock = pygame.time.Clock()
while True:
screen.fill((0.0.0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit(0)
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
mouse_pos = pygame.mouse.get_pos()
if self.play_btn.rect.collidepoint(mouse_pos):
return True
elif self.quit_btn.rect.collidepoint(mouse_pos):
pygame.quit()
sys.exit(0)
elif self.intro_btn.rect.collidepoint(mouse_pos):
return
for btn in [self.intro_btn, self.play_btn, self.quit_btn]:
btn.update()
btn.draw(screen)
for fr, rect in zip(font_renders, rects):
screen.blit(fr, rect)
pygame.display.flip()
clock.tick(self.cfg.FPS)
Copy the code
The other extra code is to display the game’s title and other information, which is very simple and will not be discussed in detail
Now, what does the interface look like when the game starts
Specifically, we can define what the game map should look like in a text file, like the one below, where each number represents a game element:
I have also collected the game materials that I found online.
So, we can write a parser class for the game map file, like this:
Game map Parsing class
class MapParser() :
def __init__(self, blocksize, filepath, element_images, offset=(0.0), **kwargs) :
self.count = 0
self.switch_times = 15
self.image_pointer = 0
self.offset = offset
self.blocksize = blocksize
self.element_images = element_images
self.map_matrix = self.parse(filepath)
"' resolution ' ' '
def parse(self, filepath) :
map_matrix = []
with open(filepath, 'r') as fp:
for line in fp.readlines():
line = line.strip()
if not line: continue
map_matrix.append([c.strip() for c in line.split(', ')])
return map_matrix
Draw the game map to the screen.
def draw(self, screen) :
self.count += 1
if self.count == self.switch_times:
self.count = 0
self.image_pointer = int(not self.image_pointer)
for row_idx, row in enumerate(self.map_matrix):
for col_idx, elem in enumerate(row):
position = col_idx * self.blocksize + self.offset[0], row_idx * self.blocksize + self.offset[1]
if elem+'.png' in self.element_images:
image = self.element_images[elem+'.png'][self.image_pointer]
image = pygame.transform.scale(image, (self.blocksize, self.blocksize))
screen.blit(image, position)
Copy the code
The parse function actually reads the text file storing the game map information, and the draw function actually binds the corresponding game element pictures to the map for display according to the read map information. In addition, the three variables image_pointer, switch_times, and count are used to achieve the scene element flashing effect in the original map, like this:
Based on this principle, we can easily draw the original map in all layers of the Tower, and define the game map file as shown below:
The effect is shown below:
Ok, to sum up, this is the main implementation of the magic Tower game in each layer of the initial screen, this period of complete source code see personal home page introduction to obtain
This is the end of the article, thank you for watching Python28 small games, next article to share the magic Tower small games!
To thank you readers, I’d like to share some of my recent programming favorites to give back to each and every one of you in the hope that they can help you.
Tomorrow I will take you to further reproduce the magic Tower this small game, interested partners can pay more attention to ~