No, Xiaobian made a skiing adventure game in Python

Posted by DrDankWD on Thu, 20 Jan 2022 05:28:32 +0100

Related documents

Source code sharing, problem solving!!
Pay attention to Xiaobian and receive private letter Xiaobian!
Of course, don't forget a triple~~

Yes, we can pay attention to the official account of Xiaobian yo ~ ~
There are many resources to get!!

You can also go to station b to watch some of my teaching videos!!
More Python video teaching: Python video teaching (station b)

Python log

development environment

Python version: 3.6.4
Related modules:
pygame module;
And some Python built-in modules.

Environment construction

Install Python and add it to the environment variable. pip can install the relevant modules required.

Principle introduction

Rules of the game:
Players use the "AD" key or "←→" to control the skiers moving forward, try to avoid the trees on the road and try to pick up the small flag on the road.
If you touch a tree, the score will be reduced by 50. If you pick up a small flag, the score will be increased by 10.

Progressive realization

Step 1: define sprite class

Since the game involves collision detection (collision between skiers and trees and flags), we define two elf classes to represent skiers and obstacles (i.e. trees and flags):

```handlebars
'''Skiers'''
class SkierClass(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        # Orientation of skiers (- 2 to 2)
        self.direction = 0
        self.imagepaths = cfg.SKIER_IMAGE_PATHS[:-1]
        self.image = pygame.image.load(self.imagepaths[self.direction])
        self.rect = self.image.get_rect()
        self.rect.center = [320, 100]
        self.speed = [self.direction, 6-abs(self.direction)*2]
    '''Change the orientation of the skier. Negative numbers are left, positive numbers are right, and 0 is forward'''
    def turn(self, num):
        self.direction += num
        self.direction = max(-2, self.direction)
        self.direction = min(2, self.direction)
        center = self.rect.center
        self.image = pygame.image.load(self.imagepaths[self.direction])
        self.rect = self.image.get_rect()
        self.rect.center = center
        self.speed = [self.direction, 6-abs(self.direction)*2]
        return self.speed
    '''Mobile skier'''
    def move(self):
        self.rect.centerx += self.speed[0]
        self.rect.centerx = max(20, self.rect.centerx)
        self.rect.centerx = min(620, self.rect.centerx)
    '''Set to fall state'''
    def setFall(self):
        self.image = pygame.image.load(cfg.SKIER_IMAGE_PATHS[-1])
    '''Set to standing'''
    def setForward(self):
        self.direction = 0
        self.image = pygame.image.load(self.imagepaths[self.direction])


'''
Function:
    Obstacles
Input:
    img_path: Obstacle picture path
    location: Obstacle location
    attribute: Obstacle Category Properties
'''
class ObstacleClass(pygame.sprite.Sprite):
    def __init__(self, img_path, location, attribute):
        pygame.sprite.Sprite.__init__(self)
        self.img_path = img_path
        self.image = pygame.image.load(self.img_path)
        self.location = location
        self.rect = self.image.get_rect()
        self.rect.center = self.location
        self.attribute = attribute
        self.passed = False
    '''move'''
    def move(self, num):
        self.rect.centery = self.location[1] - num

Among them, the skier should have the ability to shift left and right in the process of moving forward, and it is more reasonable for the skier to slow down when shifting, so as to be operated by the player. At the same time, skiers should have different postures to express their sliding state:

Straight line:

A little to the left:

A lot to the left:

A little to the right:

A lot to the right:

In addition, although the left and right movement of the skier is realized by moving the skier itself, the forward movement of the skier is realized by moving an obstacle.

Step 2: create obstacles randomly
Now we need to define a function that randomly creates obstacles to invoke in the main game loop:

'''Create obstacles'''
def createObstacles(s, e, num=10):
    obstacles = pygame.sprite.Group()
    locations = []
    for i in range(num):
        row = random.randint(s, e)
        col = random.randint(0, 9)
        location  = [col*64+20, row*64+20]
        if location not in locations:
            locations.append(location)
            attribute = random.choice(list(cfg.OBSTACLE_PATHS.keys()))
            img_path = cfg.OBSTACLE_PATHS[attribute]
            obstacle = ObstacleClass(img_path, location, attribute)
            obstacles.add(obstacle)
    return obstacles

Step 3: game main loop
First, we initialize some parameters:

 pygame.init()
    pygame.mixer.init()
    pygame.mixer.music.load(cfg.BGMPATH)
    pygame.mixer.music.set_volume(0.4)
    pygame.mixer.music.play(-1)
    # Setup screen
    screen = pygame.display.set_mode(cfg.SCREENSIZE)
    pygame.display.set_caption('Skiing game—— Charles Picchu')
    # Game start interface
    ShowStartInterface(screen, cfg.SCREENSIZE)
    # Instantiate game sprites
    # --Skier
    skier = SkierClass()
    # --Create obstacles
    obstacles0 = createObstacles(20, 29)
    obstacles1 = createObstacles(10, 19)
    obstaclesflag = 0
    obstacles = AddObstacles(obstacles0, obstacles1)
    # Game clock
    clock = pygame.time.Clock()
    # Record the distance of skiing
    distance = 0
    # Record the current score
    score = 0
    # Record the current speed
    speed = [0, 6]
    # Game main loop

The purpose of creating obstacles twice is to facilitate picture connection.

Then we can define the main loop:

while True:
    # --Event capture
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT or event.key == pygame.K_a:
                speed = skier.turn(-1)
            elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                speed = skier.turn(1)
    # --Update the data of the current game frame
    skier.move()
    distance += speed[1]
    if distance >= 640 and obstaclesflag == 0:
        obstaclesflag = 1
        obstacles0 = createObstacles(20, 29)
        obstacles = AddObstacles(obstacles0, obstacles1)
    if distance >= 1280 and obstaclesflag == 1:
        obstaclesflag = 0
        distance -= 1280
        for obstacle in obstacles0:
            obstacle.location[1] = obstacle.location[1] - 1280
        obstacles1 = createObstacles(10, 19)
        obstacles = AddObstacles(obstacles0, obstacles1)
    for obstacle in obstacles:
        obstacle.move(distance)
    # --Collision detection
    hitted_obstacles = pygame.sprite.spritecollide(skier, obstacles, False)
    if hitted_obstacles:
        if hitted_obstacles[0].attribute == "tree" and not hitted_obstacles[0].passed:
            score -= 50
            skier.setFall()
            updateFrame(screen, obstacles, skier, score)
            pygame.time.delay(1000)
            skier.setForward()
            speed = [0, 6]
            hitted_obstacles[0].passed = True
        elif hitted_obstacles[0].attribute == "flag" and not hitted_obstacles[0].passed:
            score += 10
            obstacles.remove(hitted_obstacles[0])
    # --Update screen
    updateFrame(screen, obstacles, skier, score)
    clock.tick(cfg.FPS)

The main cycle includes:
Event monitoring, obstacle update, collision detection and score display are easy to implement.

Step4: others
The start and end interfaces are up to you. I wrote a simple start interface:

'''Show score'''
def showScore(screen, score, pos=(10, 10)):
    font = pygame.font.Font(cfg.FONTPATH, 30)
    score_text = font.render("Score: %s" % score, True, (0, 0, 0))
    screen.blit(score_text, pos)


'''Update the game screen of the current frame'''
def updateFrame(screen, obstacles, skier, score):
    screen.fill((255, 255, 255))
    obstacles.draw(screen)
    screen.blit(skier.image, skier.rect)
    showScore(screen, score)
    pygame.display.update()

Effect display

Well, that's all for today's sharing. Small partners who need source code can view relevant files!
You can also focus on the official account of Xiaobian to get source code and resources!
Official account: Python log

More Python video teaching: Python video teaching (station b)

Topics: Python pygame