Python Game Development-Super Pirate! ! !

Development environment configuration

After installing the python environment, download the pygame module and use the following command

pip install pygame

Note: This project uses some new features and uses version 3.10 or above

Game project introduction

The game is divided into two modules, namely the editing module and the level module. Under the editing module, players can drag different map elements in the map menu to layout the map on the game interface. In level mode, players can control the character to Break through the map levels you designed yourself

This game is a level-breaking game similar to Mario. The difference is that players can design game levels by themselves.

Game project demo

Get the project source code at the end of the article below 

Introduction to some game functions

Game mode switch

main.py is the entry file of the program, editor.py is the function implementation of the editing mode, and level.py is the function implementation of the level mode. The relationship between the three is as follows

picture

An identifier (self.editor_active) is defined in main.py for switching between the two modes of the game. The default value is True, that is, to run the program, first enter the editing mode. After the editing is completed, press the Enter key to call toggle() function, change the value to False, and enter the level mode during the execution of the loop body of the main program

  #main.py中的Main类
  def run(self):
    while True:
      dt = self.clock.tick() / 1000

      # 通过检查self.editor_active的值,决定是运行编辑器还是关卡
      if self.editor_active:
        self.editor.run(dt)
      else:
        self.level.run(dt)
      self.transition.display(dt)
      pygame.display.update
 #main.py中的Main类
  def toggle(self):
    print('进入toggle,切换游戏的模式状态')
    self.editor_active = not self.editor_active
    # 通过检查self.editor_active的值,判断是否需要启动编辑器音乐
    if self.editor_active:
      self.editor.editor_music.play()

The calling process of the toggle function is more complicated. After the program runs, it first calls editor.run(dt) to enter the editing mode, and then calls the event_loop() function in the Editor class. This function will respond to the player's event operations (mouse) in a timely manner. and keyboard), when the player enters the Enter key on the keyboard, the switch function is called to change the game mode state.

picture

The Translation class is an attribute of the main class. When the display() method is executed, if the value of the attribute transition.ative is True (the default is False), it enters the if branch, calls the toggle() function in main, and changes The value of the editor_active attribute

 #Translation类
 #用于在游戏窗口中绘制过渡效果
  def display(self, dt):
    if self.active:
      self.border_width += 1000 * dt * self.direction
      if self.border_width >= self.threshold:
        self.direction = -1
        self.toggle()

      if self.border_width < 0:
        self.active = False
        self.border_width = 0
        self.direction = 1
      pygame.draw.circle(self.display_surface, 'black',self.center, self.radius, int(self.border_width))

Game score display

In order to improve the game experience, the function of displaying game scores is added. After the player completes the level design, he will challenge the level. As long as the character controlled by the player touches the coin, the game score in the upper right corner will increase. For gold coins, it will increase by two points. For silver coins, it will increase by two points. Add one point to the calculation

Add the attribute score in the __init__() method of the Level class in level.py to record game scores.

# 游戏分数
self.score = 0

The Player (player character Sprite) class is created as a class attribute in the level object when creating the Level class. At the same time, other (Sprite) classes on the map are also created. These sprite classes all inherit the general character class Generic. Generic inherits Sprite

"""
通用的角色类,包含了角色的基本属性和方法
"""
class Generic(pygam,ere.sprite.Sprite):
  def __init__(self, pos, surf, group, z = LEVEL_LAYERS['main']):
    super().__init__(group)
    self.image = surf
    self.rect = self.image.get_rect(topleft = pos)
    self.z = z

These sprite classes are managed by pygame.sprite.Group, which is a container that can accommodate multiple sprite objects. As an attribute of the Level class, it facilitates object acquisition.

self.coin_sprites = pygame.sprite.Group()   # 硬币
self.shell_sprites = pygame.sprite.Group()  # 敌人

Declare the get_coin() method in the Level class to detect whether the character touches the coin. pygame.sprite.spritecollide is used to detect whether the two sprite objects collide and return the collision list. The reason why it is called twice is that the first time Used to obtain the colliding coin object information. The second time it is set to True is used to delete the colliding sprite.

  def get_coins(self):

    # pygame.sprite.spritecollide:检测玩家和硬币的碰撞
    # 返回和玩家发生碰撞的硬币精灵的列表,同时将这些硬币精灵从 self.coin_sprites 精灵组中移除(设置碰撞为 True)
    collided_coins1 = pygame.sprite.spritecollide(self.player, self.coin_sprites, False)
    len = collided_coins1.__len__()
    if(len > 0):
      coin_type = collided_coins1[0].coin_type
      print(f'碰撞1:{collided_coins1[0].coin_type}')
      if coin_type == 'silver':
        print(self.score)
        self.score += 1
      elif coin_type == 'gold':
        print(self.score)
        self.score += 2
      else:
        self.player.life += 1
        print(f'生命数:{self.player.life}')

    collided_coins = pygame.sprite.spritecollide(self.player, self.coin_sprites, True)
    for sprite in collided_coins:
      print('碰撞')
      self.coin_sound.play()
      Particle(self.particle_surfs, sprite.rect.center, self.all_sprites)

At this time, the recording of the game score function has been completed, but it still needs to be displayed in the game window. The CameraGroup class is defined in level.py, which is inherited from pygame.sprite.Group and is used to manage sprite objects and display sprite objects in the game window. of drawing

When the game level mode is running, the level.run method will be called. In the run method, the update method in the CameraGroup class is called to update the game window. When calling this method, the game score should be passed to the cameraGroup object.

 #level.run 
  def run(self, dt):

    # update
    self.event_loop()
    life = self.player.life

    self.all_sprites.score = self.score
    self.all_sprites.life = life
    self.all_sprites.update(dt)

    self.get_coins()
    self.get_damage()

Therefore, you can add the display of game scores in draw_horizon() of the CameraGroup class

# 绘制游戏分数
text = pygame.font.Font("../font/LycheeSoda.ttf", 36).render(f'SCORE:{self.score}', True, (255, 255, 255))
self.display_surface.blit(text, (20, 20))

operation result

picture

game life display

The design here is that the red gem is the character's life. When it touches an enemy or is hit by an enemy attack, the number of lives is reduced by 1. When a red gem is touched on the game map, the number of lives is increased by 1.

Determining whether the user has come into contact with rubies has been completed in the get_coin method above. Add the life attribute to the attributes of the Player class, set the blood volume of the game character, and pass the attribute value to the cameraGroup object, the same as the game score above.

#sprite.py中的Player类
# 设置血条
self.life = 2

Declare the damage method in the Player class to reduce the number of characters' lives, and the logic of actual character collision injuries is implemented in level

  """
  Player类
  受到伤害时的操作,使玩家向上移动并启动无敌计时器
  """
  def damage(self):
    if not self.invul_timer.active:
      print('受伤')
      self.invul_timer.activate()
      self.direction.y -= 1.5
      self.life -= 1
  #Level类
  def get_damage(self):
    # 检测角色是否与敌人发生碰撞
    collision_sprites = pygame.sprite.spritecollide(self.player, self.damage_sprites, False, pygame.sprite.collide_mask)
    if collision_sprites:
      self.hit_sound.play()
      self.player.damage()

The running results are shown in the figure above

game over

When the player's life number reaches 0, the game ends and the GAME OVER font prompt is displayed in the game window. Just judge the value of life in the CameraGroup class.

      # 绘制生命(用宝石数量代表生命数量)
      image = pygame.image.load("../graphics/items/diamond/0.png")
      image_rect = image.get_rect()
      image_rect.center = (30,80)
      text2 = pygame.font.Font("../font/LycheeSoda.ttf", 36).render(f':× {self.life}', True, (255, 255, 255))
      self.display_surface.blit(text2, (50, 65))
      self.display_surface.blit(image, image_rect)
      if self.life <= 0:
        text = pygame.font.Font('../font/LycheeSoda.ttf', 120).render('GAME  OVER', True, (215, 55, 74))
        self.display_surface.blit(text, (400, 250))

picture

Get the project source code at the end of the article below

Guess you like

Origin blog.csdn.net/m0_59595915/article/details/132622404