current position:Home>Python game development, pyGame module, python takes you to realize a magic tower game from scratch (2)
Python game development, pyGame module, python takes you to realize a magic tower game from scratch (2)
2022-01-30 09:51:04 【Dai mubai】
Little knowledge , Great challenge ! This article is participating in “ A programmer must have a little knowledge ” Creative activities
Preface
In this issue, we will take you to further reproduce our magic tower game , The main content includes the definition of hero class and the realization of its basic actions , Trigger the switching of different layers in the process of action .
I don't say much nonsense , Let's start happily ~
development tool
Python edition : 3.7.4
Related modules :
pygame modular ;
As well as some python Built in modules .
Environment building
install Python And add to environment variable ,pip Install the relevant modules required .
Introduction of the principle
Last issue , We realized the basic picture definition of the game , Like this :
Careful friends must have found , Why don't we have our warriors in the map ? How can we save the princess without him ~ Don't worry. , This issue brings you to realize this part .
First , Let's define our hero warrior class :
''' Define our hero Warrior '''
class Hero(pygame.sprite.Sprite):
def __init__(self, imagepaths, blocksize, position, fontpath=None):
pygame.sprite.Sprite.__init__(self)
# Set basic properties
self.font = pygame.font.Font(fontpath, 40)
# Load the corresponding picture
self.images = {}
for key, value in imagepaths.items():
self.images[key] = pygame.transform.scale(pygame.image.load(value), (blocksize, blocksize))
self.image = self.images['down']
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
# Set level and other information
self.level = 1
self.life_value = 1000
self.attack_power = 10
self.defense_power = 10
self.num_coins = 0
self.experience = 0
self.num_yellow_keys = 0
self.num_purple_keys = 0
self.num_red_keys = 0
''' Bind the warrior to the screen '''
def draw(self, screen):
screen.blit(self.image, self.rect)
Copy code
After binding it to the main interface of the game, the effect is as follows :
Does it look like something's wrong ? you 're right , There was text on the left to show the current status of the warrior ! It's all gone now ! But that's okay , No big problem , Let's write a few lines of code to display the hero's information on the left panel :
font_renders = [
self.font.render(str(self.level), True, (255, 255, 255)),
self.font.render(str(self.life_value), True, (255, 255, 255)),
self.font.render(str(self.attack_power), True, (255, 255, 255)),
self.font.render(str(self.defense_power), True, (255, 255, 255)),
self.font.render(str(self.num_coins), True, (255, 255, 255)),
self.font.render(str(self.experience), True, (255, 255, 255)),
self.font.render(str(self.num_yellow_keys), True, (255, 255, 255)),
self.font.render(str(self.num_purple_keys), True, (255, 255, 255)),
self.font.render(str(self.num_red_keys), True, (255, 255, 255)),
]
rects = [fr.get_rect() for fr in font_renders]
rects[0].topleft = (160, 80)
for idx in range(1, 6):
rects[idx].topleft = 160, 127 + 42 * (idx - 1)
for idx in range(6, 9):
rects[idx].topleft = 160, 364 + 55 * (idx - 6)
for fr, rect in zip(font_renders, rects):
screen.blit(fr, rect)
Copy code
The effect is like this :
Completed the most basic definition of warrior class , Then we should let him move , To be specific , We first implement a class function of warrior action :
''' action '''
def move(self, direction):
assert direction in self.images
self.image = self.images[direction]
move_vector = {
'left': (-self.blocksize, 0),
'right': (self.blocksize, 0),
'up': (0, -self.blocksize),
'down': (0, self.blocksize),
}[direction]
self.rect.left += move_vector[0]
self.rect.top += move_vector[1]
Copy code
Then write a key to detect , And determine the action direction of the warrior according to the key value pressed by the player :
key_pressed = pygame.key.get_pressed()
if key_pressed[pygame.K_w] or key_pressed[pygame.K_UP]:
self.hero.move('up')
elif key_pressed[pygame.K_s] or key_pressed[pygame.K_DOWN]:
self.hero.move('down')
elif key_pressed[pygame.K_a] or key_pressed[pygame.K_LEFT]:
self.hero.move('left')
elif key_pressed[pygame.K_d] or key_pressed[pygame.K_RIGHT]:
self.hero.move('right')
Copy code
If you think my code above is OK , It's done , There are two problems with this writing .
First , This writing will cause the player to press the up key once , Warriors move many squares , It makes it difficult for players to control the position of warriors , At this point, we can add an action cooling variable :
# Action cooling
self.move_cooling_count = 0
self.move_cooling_time = 5
self.freeze_move_flag = False
Copy code
Count while cooling :
if self.freeze_move_flag:
self.move_cooling_count += 1
if self.move_cooling_count > self.move_cooling_time:
self.move_cooling_count = 0
self.freeze_move_flag = False
Copy code
After counting, the hero can restore his action ability . therefore move Can be rewritten as :
''' action '''
def move(self, direction):
if self.freeze_move_flag: return
assert direction in self.images
self.image = self.images[direction]
move_vector = {
'left': (-self.blocksize, 0),
'right': (self.blocksize, 0),
'up': (0, -self.blocksize),
'down': (0, self.blocksize),
}[direction]
self.rect.left += move_vector[0]
self.rect.top += move_vector[1]
self.freeze_move_flag = True
Copy code
Interested partners can remove this code by themselves and actually feel whether there will be a difference when the keyboard operates our warriors .
Another question , And the most serious problem , That is, action will be illegal , For example, warriors will appear in such a position :
therefore , We need to add additional judgment on whether the movement is legal :
''' action '''
def move(self, direction, map_parser):
if self.freeze_move_flag: return
assert direction in self.images
self.image = self.images[direction]
move_vector = {'left': (-1, 0), 'right': (1, 0), 'up': (0, -1), 'down': (0, 1)}[direction]
block_position = self.block_position[0] + move_vector[0], self.block_position[1] + move_vector[1]
if block_position[0] >= 0 and block_position[0] < map_parser.map_size[1] and \
block_position[1] >= 0 and block_position[1] < map_parser.map_size[0]:
if map_parser.map_matrix[block_position[1]][block_position[0]] in ['0']:
self.block_position = block_position
elif map_parser.map_matrix[block_position[1]][block_position[0]] in ['24']:
self.dealcollideevent(
elem=map_parser.map_matrix[block_position[1]][block_position[0]],
block_position=block_position,
map_parser=map_parser,
)
self.rect.left, self.rect.top = self.block_position[0] * self.blocksize + self.offset[0], self.block_position[1] * self.blocksize + self.offset[1]
self.freeze_move_flag = True
Copy code
here , For the convenience of judgment , We changed the original pixel coordinates into the element block coordinates in the game map ( In the game map designed in the last issue , The location index of each number in the map matrix ). in addition , Here we also need to think about the process of further reproducing the game in the future , We need to respond when warriors collide with some elements in the map , For example, warriors duel with monsters , Pick up the key and so on , So we are also in the above move Function is embedded in dealcollideevent To deal with such a situation , A simple effect is shown below :
Of course , In theory, according to the original game, there should be a dialog box with a background story , This part will be realized in the next issue , In this issue, we mainly realize some basic functions , For example, the triggering of some simple events , Including meeting the door , Pick up the key, etc :
''' Deal with impact events '''
def dealcollideevent(self, elem, block_position, map_parser):
# Encounter doors of different colors , If you have a key, open , Otherwise you can't move forward
if elem in ['2', '3', '4']:
flag = False
if elem == '2' and self.num_yellow_keys > 0:
self.num_yellow_keys -= 1
flag = True
elif elem == '3' and self.num_purple_keys > 0:
self.num_purple_keys -= 1
flag = True
elif elem == '4' and self.num_red_keys > 0:
self.num_red_keys -= 1
flag = True
if flag: map_parser.map_matrix[block_position[1]][block_position[0]] = '0'
return flag
# Picked up keys of different colors
elif elem in ['6', '7', '8']:
if elem == '6': self.num_yellow_keys += 1
elif elem == '7': self.num_purple_keys += 1
elif elem == '8': self.num_red_keys += 1
map_parser.map_matrix[block_position[1]][block_position[0]] = '0'
return True
# I found a gem
elif elem in ['9', '10']:
if elem == '9': self.defense_power += 3
elif elem == '10': self.attack_power += 3
map_parser.map_matrix[block_position[1]][block_position[0]] = '0'
return True
# Meet a fairy , A dialogue , And move one space left
elif elem in ['24']:
map_parser.map_matrix[block_position[1]][block_position[0] - 1] = elem
map_parser.map_matrix[block_position[1]][block_position[0]] = '0'
return False
Copy code
Last , Let's realize the effect of switching the current game map when the warrior goes up and down the stairs , This sounds a little difficult at first , But it's not , Just return the command of the event of going up and down stairs to the main game loop :
# Up and down stairs
elif elem in ['13', '14']:
if elem == '13': events = ['upstairs']
elif elem == '14': events = ['downstairs']
return True, events
''' action '''
def move(self, direction, map_parser):
# Determine whether freezing action
if self.freeze_move_flag: return
assert direction in self.images
self.image = self.images[direction]
# Mobile warrior
move_vector = {'left': (-1, 0), 'right': (1, 0), 'up': (0, -1), 'down': (0, 1)}[direction]
block_position = self.block_position[0] + move_vector[0], self.block_position[1] + move_vector[1]
# Judge whether the movement is legal , And trigger the corresponding event
events = []
if block_position[0] >= 0 and block_position[0] < map_parser.map_size[1] and \
block_position[1] >= 0 and block_position[1] < map_parser.map_size[0]:
# -- Legal movement
if map_parser.map_matrix[block_position[1]][block_position[0]] in ['0']:
self.block_position = block_position
# -- Triggering event
elif map_parser.map_matrix[block_position[1]][block_position[0]] in ['2', '3', '4', '6', '7', '8', '9', '10', '13', '14', '24']:
flag, events = self.dealcollideevent(
elem=map_parser.map_matrix[block_position[1]][block_position[0]],
block_position=block_position,
map_parser=map_parser,
)
if flag: self.block_position = block_position
# Reset warrior position
self.rect.left, self.rect.top = self.block_position[0] * self.blocksize + self.offset[0], self.block_position[1] * self.blocksize + self.offset[1]
# Freezing operation
self.freeze_move_flag = True
# Returns the event that needs to be triggered in the main loop
return events
Copy code
Then respond in the main loop :
# -- Trigger game events
for event in move_events:
if event == 'upstairs':
self.map_level_pointer += 1
self.loadmap()
elif event == 'downstairs':
self.map_level_pointer -= 1
self.loadmap()
Copy code
The effect is as follows :
I wonder if you have found a problem , It's that the warrior is in the wrong position when he goes upstairs , In theory, it should be near the lower staircase of the current map , Not where the warrior last went upstairs in the last game map , So how should this part be implemented ? It's very simple , A simple solution is to define the game map , Define a... At the upper and lower stairs 00 Variable :
Draw the game map according to 0 Elements to draw :
if elem in self.element_images:
image = self.element_images[elem][self.image_pointer]
image = pygame.transform.scale(image, (self.blocksize, self.blocksize))
screen.blit(image, position)
elif elem in ['00', 'hero']:
image = self.element_images['0'][self.image_pointer]
image = pygame.transform.scale(image, (self.blocksize, self.blocksize))
screen.blit(image, position)
Copy code
But when switching game maps up and down stairs , We can use this identifier to reset the location of the role :
# -- Trigger game events
for event in move_events:
if event == 'upstairs':
self.map_level_pointer += 1
self.loadmap()
self.hero.placenexttostairs(self.map_parser, 'down')
elif event == 'downstairs':
self.map_level_pointer -= 1
self.loadmap()
self.hero.placenexttostairs(self.map_parser, 'up')
Copy code
The function to reset the position is implemented as follows :
''' Place on / Next to the stairs '''
def placenexttostairs(self, map_parser, stairs_type='up'):
assert stairs_type in ['up', 'down']
for row_idx, row in enumerate(map_parser.map_matrix):
for col_idx, elem in enumerate(row):
if (stairs_type == 'up' and elem == '13') or (stairs_type == 'down' and elem == '14'):
if row_idx > 0 and map_parser.map_matrix[row_idx - 1][col_idx] == '00':
self.block_position = col_idx, row_idx - 1
elif row_idx < map_parser.map_size[0] - 1 and map_parser.map_matrix[row_idx + 1][col_idx] == '00':
self.block_position = col_idx, row_idx + 1
elif col_idx > 0 and map_parser.map_matrix[row_idx][col_idx - 1] == '00':
self.block_position = col_idx - 1, row_idx
elif col_idx < map_parser.map_size[1] - 1 and map_parser.map_matrix[row_idx][col_idx + 1] == '00':
self.block_position = col_idx + 1, row_idx
self.rect.left, self.rect.top = self.block_position[0] * self.blocksize + self.offset[0], self.block_position[1] * self.blocksize + self.offset[1]
Copy code
Retest and see :
To sum up , The main thing is to realize our warrior role , And some simple event responses after he meets some elements in the map .
copyright notice
author[Dai mubai],Please bring the original link to reprint, thank you.
https://en.pythonmana.com/2022/01/202201300951032977.html
The sidebar is recommended
- Similarities and differences of five pandas combinatorial functions
- Python beginner's eighth day ()
- Necessary knowledge of Python: take you to learn regular expressions from zero
- Get your girlfriend's chat records with Python and solve the paranoia with one move
- My new book "Python 3 web crawler development practice (Second Edition)" has been recommended by the father of Python!
- From zero to familiarity, it will take you to master the use of Python len() function
- Python type hint type annotation guide
- leetcode 108. Convert Sorted Array to Binary Search Tree(python)
- For the geometric transformation of Python OpenCV image, let's first talk about the extraordinary resize function
- leetcode 701. Insert into a Binary Search Tree (python)
guess what you like
-
For another 3 days, I sorted out 80 Python datetime examples, which must be collected!
-
Python crawler actual combat | using multithreading to crawl lol HD Wallpaper
-
Complete a python game in 28 minutes, "customer service play over the president card"
-
The universal Python praise machine (commonly known as the brushing machine) in the whole network. Do you want to know the principle? After reading this article, you can write one yourself
-
How does Python compare file differences between two paths
-
Common OS operations for Python
-
[Python data structure series] linear table - explanation of knowledge points + code implementation
-
How Python parses web pages using BS4
-
How do Python Network requests pass parameters
-
Python core programming - decorator
Random recommended
- Python Network Programming -- create a simple UPD socket to realize mutual communication between two processes
- leetcode 110. Balanced Binary Tree(python)
- Django uses Django celery beat to dynamically add scheduled tasks
- The bear child said "you haven't seen Altman" and hurriedly studied it in Python. Unexpectedly
- Optimization iteration of nearest neighbor interpolation and bilinear interpolation algorithm for Python OpenCV image
- Bilinear interpolation algorithm for Python OpenCV image, the most detailed algorithm description in the whole network
- Use of Python partial()
- Python game development, pyGame module, python implementation of angry birds
- leetcode 1104. Path In Zigzag Labelled Binary Tree(python)
- Save time and effort. 10 lines of Python code automatically clean up duplicate files in the computer
- Learn python, know more meat, and be a "meat expert" in the technical circle. One article is enough
- [Python data structure series] "stack (sequential stack and chain stack)" -- Explanation of knowledge points + code implementation
- Datetime module of Python time series
- Python encrypts and decrypts des to solve the problem of inconsistency with Java results
- Chapter 1: introduction to Python programming-4 Hello World
- Summary of Python technical points
- 11.5K Star! An open source Python static type checking Library
- Chapter 2: Fundamentals of python-1 grammar
- [Python daily homework] day4: write a function to count the number of occurrences of each number in the incoming list and return the corresponding dictionary.
- Python uses turtle to express white
- Some people say Python does not support function overloading?
- "Python instance" was shocked and realized the dirty words and advertisement detection of the chat system with Python
- Introduction to Python - CONDA common commands
- Python actual combat | just "4 steps" to get started with web crawler (with benefits)
- Don't know what to eat every day? Python to tell you! Generate recipes and don't worry about what to eat every day!
- Are people who like drinking tea successful? I use Python to make a tea guide! Do you like it?
- I took 100g pictures offline overnight with Python just to prevent the website from disappearing
- Binary operation of Python OpenCV image re learning and image smoothing (convolution processing)
- Analysis of Python event mechanism
- Iterator of Python basic language
- Base64 encryption and decryption in Python
- Chapter 2: Fundamentals of python-2 variable
- Python garbage collection summary
- Python game development, pyGame module, python takes you to realize a magic tower game from scratch (1)
- Python draws a spinning windmill with turtle
- Deep understanding of Python features
- A website full of temptations for Python crawler writers, "lovely picture network", look at the name of this website
- Python opencv Canny edge detection knowledge supplement
- Complex learning of Python opencv Sobel operator, ScHARR operator and Laplacian operator
- Python: faker extension package