Python - Batalha de Defesa do Castelo

Perceba a função:

1: O avanço contínuo do inimigo, segurando uma variedade de armas (garfos, machados, espadas), balançando as armas para atacar nosso castelo, causando danos ao nosso castelo!

2: Se nosso castelo encontrar o inimigo, podemos clicar manualmente com o botão esquerdo do mouse para lançar um ataque de bala, causando danos fatais aos japoneses e fazendo-os morrer!

3: Exibição de dados completa, atacando o inimigo para obter moedas de ouro, pontos acumulados, nível atual do cartão de gerenciamento, exibição do valor de saúde do nosso castelo, etc., as moedas de ouro obtidas ao matar o inimigo podem ser trocadas por atributos adicionais para equipar e restaurar e fortalecer nossa fortaleza!

4: A interface de layout do projeto é bonita e limpa, combinada com o fundo do jogo de música pura adicionado e efeitos sonoros de ataque e exibição de animação em tempo real (por exemplo, a aparência do nosso castelo mudará à medida que o valor de saúde do nosso castelo diminuir , ou seja, ficará quebrado, etc.) para tornar o projeto mais jogável!

5: Levar este projeto para a prática ou como um simples design de curso de python também é uma escolha possível!

6: O código total do projeto é de cerca de 700 linhas

Conhecimento de programação utilizado:

Noções básicas de Python, leitura e escrita de arquivos, módulo pygame e pensamento orientado a objetos!

código mostra como abaixo:

arquivo de classe inimigo.py (cerca de 100 linhas de código)

import pygame 

class Enemy(pygame.sprite.Sprite): 
   def __init__(self, health, animation_list, x, y, speed): 
      pygame.sprite.Sprite.__init__(self) 
      self.alive = Verdadeiro 
      self.speed = velocidade 
      self. health = saúde 
      self.last_attack = pygame.time.get_ticks() 
      self.attack_cooldown = 1000 
      self.animation_list = animation_list 
      self.frame_index = 0 
      self.action = 0#0: caminhada, 1: ataque, 2: morte 
      self.update_time = pygame.time.get_ticks() 

      #selecione a imagem inicial 
      self.image = self.animation_list[self.action][self.frame_index] 
      self.rect = pygame.Rect(0, 0, 25, 40)
      self.rect.center = (x, y) 


   def update(self, surface, target, bullet_group): 
      if self.alive: #verifica 
         colisões com marcadores 
         if pygame.sprite.spritecollide(self, bullet_group, True): 
            #lower saúde do inimigo 
            self.health -= 25 

         #verifica se o inimigo alcançou o castelo 
         if self.rect.right > target.rect.left: 
            self.update_action(1) 

         #move o inimigo 
         if self.action == 0: 
            #atualiza a posição do retângulo 
            self.rect.x += self.speed 

         #attack 
         if self.action == 1: 
            #verifica se já passou tempo suficiente desde o último ataque
            if pygame.time.get_ticks() - self.last_attack > self.attack_cooldown: 
               target.health -= 25 
               if target.health < 0: 
                  target.health = 0 
               self.last_attack = pygame.time.get_ticks() 


         #verifica se a saúde caiu para zero 
         se self.health <= 0: 
            target.money += 100 
            target.score += 100 
            self.update_action(2)#death 
            self.alive = False 

      self.update_animation() 

      #desenhar imagem na 
      superfície da tela.blit (self.image, (self.rect.x - 10, self.rect.y - 15)) 


   def update_animation(self): 
      #define o tempo de espera da animação 
      ANIMATION_COOLDOWN = 50 
      #atualiza a imagem dependendo da ação atual 
      self.image = self.animation_list[self.action][self.frame_index] #verifica 
      se já passou tempo suficiente desde a última atualização 
      if pygame.time.get_ticks () - self.update_time > ANIMATION_COOLDOWN: 
         self.update_time = pygame.time.get_ticks() 
         self.frame_index += 1 #se 
      a animação acabou, redefina de volta ao início 
      if self.frame_index >= len(self.animation_list [self.action]): 
         se self.action == 2: 
            self.frame_index = len(self.animation_list[self.action]) - 1 
         else:
            self.frame_index = 0 

 
   def update_action(self, new_action):
      #verifica se a nova ação é diferente da anterior 
      if new_action != self.action: 
         self.action = new_action 
         #atualiza as configurações de animação 
         self.frame_index = 0 
         self.update_date = pygame.time.get_ticks( )

arquivo de classe Castle.py (cerca de 500 linhas de código)

# Import library 
import pygame 
import math 
import os 
import sys 
import random 
import button 
from pygame import mixer 
# Initialize pygame 
pygame.init() 

# Define altura e largura da janela do jogo 
SCREEN_WIDTH = 800 
SCREEN_HEIGHT = 600 
# Carrega música de fundo 
pygame.mixer.music. load("sound/bjmusic.WAV") 
pygame.mixer.music.set_volume(0.3) 
jump_fx = pygame.mixer.Sound("sound/bullet.wav") 
jump_fx.set_volume(0.5) 

# cria 
tela da janela do jogo = pygame. display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) 
pygame.display.set_caption("Castle Defense") 

clock = pygame.time.Clock() 
FPS = 60 

# Defina a variável do jogo  
= 1
high_score = 0
Level_difficulty = 0 Target_difficulty 
= 1000 
dificuldades_multiplier = 1.1 
game_over = false 
next_level = false 
inimy_timer = 1000 
last_enemy = pygame.Time.TET_TICKS () 
inimies_alive = 0 
max_towers = 4 
Tower_Cost = 5000 
# # 定义 定义 定义 定义 定义 定义 定义 定义 定义 定义 定义 定义 # # # # # # # # # # # # # # # 
#ests = 
. SCREEN_HEIGHT - 200], 
[SCREEN_WIDTH - 200, SCREEN_HEIGHT - 150], 
[SCREEN_WIDTH - 150, SCREEN_HEIGHT - 150], 
[SCREEN_WIDTH - 100, SCREEN_HEIGHT - 150] 
] 

# 加载最高分
if os.path.exists('socre.txt '): 
    with open('socre.txt', 'r') as file: 
        high_score = int(file.read())

# Defina a cor 
BRANCO = (255, 255, 255) 
CINZENTO = (100, 100, 100) 

# Defina a fonte 
font = pygame.font.SysFont('Nuvens coloridas chinesas', 30) 
font_60 = pygame.font.SysFont( 'Chinese Xingkai ', 60) 

# carregar imagem 
bg = pygame.image.load('img/bg.png').convert_alpha() 
# castelo 
castle_img_100 = pygame.image.load('img/castle/castle_100.png') .convert_alpha( ) 
castle_img_50 = pygame.image.load('img/castle/castle_50.png').convert_alpha() 
castle_img_25 = pygame.image.load('img/castle/castle_25.png').convert_alpha() 

# torre 
tower_img_100 = pygame .image.load('img/tower/tower_100.png').convert_alpha() 
tower_img_50 = pygame.image.load('img/tower/tower_50.png').convert_alpha() 
tower_img_25 = pygame.image.load('img/tower/tower_25.png').convert_alpha() 

# bullet image 
bullet_img = pygame.image.load('img/bullet.png').convert_alpha() 
b_w = bullet_img.get_width() 
b_h = bullet_img.get_height() 
bullet_img = pygame.transform.scale(bullet_img, (int(b_w * 0.075), int(b_h * 0.075))) 

# 创建敌人类
class Enemy(pygame.sprite.Sprite): 
    def __init__(self , saúde, lista_animação, x, y, velocidade): 
        super().__init__() 
        self.alive = True 
        self.speed = velocidade 
        self.health = saúde 
        self.last_attack = pygame.time.get_ticks() 
        self.attack_cooldown = 1000 
        self.animation_list = animation_list
        self.frame_index = 0 
        self.action = 0 
                self.rect.x += 1 
        self.update_time = pygame.time.get_ticks() 
        # fotos de fotos
        self.image = self.animation_list[self.action][self.frame_index] 
        self.rect = pygame.Rect(0, 0, 25, 40) 
        self.rect.center = (x, y) 

    def update(self, surface , target, bullet_group): 
        if self.alive: 
            # Verifica se o inimigo colidiu com a bala 
            if pygame.sprite.spritecollide(self, bullet_group, True): 
                # Reduz a saúde 
                self.health -= 25 
            # Verifica se o inimigo colidiu alcançou o castelo 
            se self.rect.right > target.rect.left: 
                self.update_action(1) 
            # move o inimigo 
            se self.action == 0: 
            # ataca o castelo 
            if self.action == 1: 
                # detecta cooldown
                if pygame.time.get_ticks() - self.last_attack > self.attack_cooldown: 
                    target.health -= 25 
                    if target.health < 0: 
                        target.health = 0 
                    self.last_attack = pygame.time.get_ticks() 
            # Verifica o sangue inimigo Se a barra é 0 
            se self.health <= 0: 
                target.money += 100 
                target.score += 100 
                self.update_action(2) 
                self.alive = False 
        # chama a animação de atualização 
        self.update_animation() 
        inimiga 
    def update_animation(self): 
        # pygame. draw. rect(surface, (255, 255, 255), self. rect, 1)
        surface.blit(self.image, (self.rect.x - 10, self.rect.y - 15)) 

        # Define o tempo de resfriamento da animação 
        ANIMATION_COOLDOWN = 50 
        # Atualiza o quadro de acordo com o melão de inverno selecionado 
        self.image = self .animation_list[self .action][self.frame_index] 
        # Determina com que frequência atualizar o quadro 
        if pygame.time.get_ticks() - self.update_time > ANIMATION_COOLDOWN: 
            self.update_time = pygame.time.get_ticks() 
            self.frame_index + = 1 
        # Verifique o número do quadro Não pode exceder o número máximo de quadros 
        if self.frame_index >= len(self.animation_list[self.action]): 
            if self.action == 2: 
                self.frame_index = len(self.animation_list[self .action]) - 1 
            outro: 
                self.frame_index = 0
    def update_action(self, new_action): 
        num_of_frames = 20 
        # Verifique se a nova ação é o mesmo que o anterior
        if new_action != self.action: 
            self.action = new_action 
            # atualiza a animação redefinir 
            self.frame_index = 0 
            self.update_time = pygame.time.get_ticks() 


# carrega a lista de inimigos 
inimigos_animações = [] 
inimigo_tpyes = ['cavaleiro', ' goblin ', 'purple_goblin', 'red_goblin'] 
inimigo_saúde = [75, 100, 125, 150] 

animation_types = ['andar', 'ataque', 'morte'] 
para inimigo em inimigo_tpyes: 
    # carregar lista de 
    animação animation_list = [] 
    para animation in animation_types: 
        # Crie uma lista temporária 
        temp_list = [] 
        # Defina o número de frames 
        para i in range(num_of_frames): 
            img = pygame.image.load(f'img/enemies/{enemy}/{animation}/{i}.png').convert_alpha() 
            e_w = img.get_width() 
            e_h = img.get_height() 
            img = pygame.transform.scale(img, (int(e_w * 0.2), int(e_h * 0.2))) 
            temp_list.append(img) 
        animation_list.append(temp_list) 
    inimigo_animations.append(animation_list) 

# Repair_img 
= pygame.image.load('img/repair.png').convert_alpha() 
armour_img = pygame.image.load('img/armour.png').convert_alpha() 

# 在屏幕上输出文本信息
def draw_text(texto, fonte, cor_texto, x, y): 
    img = fonte.render(texto, True, cor_texto) 
    screen.blit(img, (x, y)) 

# Defina uma função para exibir o status 
def show_info():
    draw_text('钱数:' + str(castle.money), font, GREY, 10, 10) 
    draw_text('分数:' + str(castle.score), font, GREY, 180, 10) 
    draw_text('最分数:' + str(high_score), fonte, GREY, 180, 50) 
    draw_text('级别:' + str(level), fonte, GREY, SCREEN_WIDTH // 2, 10) 
    draw_text('健康:' + str(castle. saúde) + "/" + str(castle.max_health), fonte, GREY, SCREEN_WIDTH - 230, SCREEN_HEIGHT - 50) 
    draw_text('1000', fonte, GREY, SCREEN_WIDTH - 250, 70) 
    draw_text(str(TOWER_COST), fonte , GREY, SCREEN_WIDTH - 150, 70) 
    draw_text('500', font, GREY, SCREEN_WIDTH - 70, 70) 

# 城堡类
class Castle(): 
        self.max_health = self.saúde 
        self.fired = Falso 
    def __init__(self, imagem100, imagem50, imagem25,x, y, escala):
        self.health = 1000 
        self.money = 0 
        self.score = 0 
        width = image100.get_width() 
        height = image100.get_height() 

        self.image100 = pygame.transform.scale(image100, (int(width * scale), int (altura * escala))) 
        self.image50 = pygame.transform.scale(image50, (int(largura * escala), int(altura * escala))) 
        self.image25 = pygame.transform.scale(image25, (int( largura * escala), int(altura * escala))) 
        self.rect = self.image100.get_rect() 
        self.rect.x = x 
        self.rect.y = y 

    def shoot(self): 
        pos = pygame.mouse. get_pos() 
        x_dist = pos[0] - self.rect.midleft[0]
        y_dist = -(pos[1] - self.rect.midleft[1]) 
        elif self.health <= 500:
        self.angle = math.degrees(math.atan2(y_dist, x_dist)) 
        # Clique com o mouse nesta posição 
        if pygame.mouse.get_pressed()[0] e self.fired == False and pos[1] > 70: 
            self .fired = True 
            bullet = Bullet(bullet_img, self.rect.midleft[0], self.rect.midleft[1], self.angle) 
            bullet_group.add(bullet) 
            jump_fx.play() 
        # reinicia o clique do mouse 
        se pygame .mouse.get_pressed()[0] == False: 
            self.fired = False 

    def draw(self): 
        # Determina qual imagem carregar com base no volume de sangue 
        se self.health <= 250: 
            self.image = self.image25 
            self . image = self. image50 
        else:
            self.image = self.image100 
        screen.blit(self.image, self.rect) 

    def repair(self): 
        if self.money >= 1000 e self.health < self.max_health: 
            self.health += 500 
            self.money -= 1000 
            if Castle.health > Castle.max_health: 
                Castle.health = Castle.max_health 
    def armour(self): 
        if self.money >= 500: 
            self.max_health += 250 
            self.money -= 500 

# 炮塔类
class Tower (pygame.sprite.Sprite): 
    def __init__(self, image100, image50, image25, x, y, scale): 
        self.angle = 0 
        super().__init__()
        self.got_target = False 
        self.last_shot = pygame.time.get_ticks() 
        largura = image100.get_width() 
        altura = image100.get_height() 

        self.image100 = pygame.transform.scale(image100, (int(largura * escala), int(altura * escala))) 
        self.image50 = pygame.transform.scale(image50, (int(largura * escala), int(altura * escala))) 
        self.image25 = pygame.transform.scale(image25, (int (largura * escala), int(altura * escala))) 
        self.image = self.image100 
        self.rect = self.image100.get_rect() 
        self.rect.x = x 
        self.rect.y = y 
    def update(self , grupo_inimigo): 
        self.got_target = Falso 
        para e no grupo_inimigo:
            if e.alive: 
                target_x, target_y = e.rect.midbottom 
                self.got_target = True 
                break 
        if self.got_target: 
            x_dist = target_x - self.rect.midleft[0] 
            y_dist = -(target_y - self.rect.midleft[1 ]) 
            self.angle = math.degrees(math.atan2(y_dist, x_dist)) 
            # pygame.draw.line(screen, WHITE, (self.rect.midleft[0], self.rect.midleft[1]), (target_x, target_y)) 
            shot_cooldown = 1000 
            # 开火
            if pygame.time.get_ticks() - self.last_shot > shot_cooldown: 
                self.last_shot = pygame.time.get_ticks()
                bullet = Bullet(bullet_img, self.rect.midleft[0], self.rect.midleft[1], self.angle) 
                bullet_group.add(bullet) 
        # Carregue a imagem de acordo com o volume de sangue do castelo 
        if castle.health <= 250: 
            self.image = self.image25 
        elif castle.health <= 500: 
            self.image = self.image50 
        else: 
            self.image = self.image100 

# Crie uma 
classe de marcadores Bullet(pygame.sprite.Sprite): 
    def __init__( self, imagem, x, y, ângulo): 
        super().__init__() 
        self.image = imagem 
        self.rect = self.image.get_rect() 
        self.rect.x = x 
        self.rect.y = y 
        self.angle = math.radians(angle) # Converte ângulos em radianos 
        self.speed = 10 
        # Calcula as velocidades horizontal e vertical com base nos ângulos
        self.dx = math.cos(self.angle) * self.speed 
        self.dy = -(math.sin(self.angle) * self.speed) 

    def update(self): 
        # Verifique se o marcador excedeu a janela 
        if self .rect.right < 0 ou self.rect.left > SCREEN_WIDTH ou self.rect.bottom < 0 ou self.rect.top > SCREEN_HEIGHT: 
            self.kill() 
        # move o marcador 
        self.rect.x += self .dx 
        self .rect.y += self.dy 

# Cria uma 
classe de mira Crosshair(): 
    def __init__(self, scale): 
        image = pygame.image.load("img/crosshair.png").convert_alpha() 
        width = imagem .get_width()  
        altura = image.get_height()
        self.image = pygame.transform.scale(imagem, (int(largura * escala), int(altura * escala))) 
        self.rect = self.image.get_rect() 
        # esconde o ponteiro do mouse 
        pygame.mouse.set_visible(False ) 

    def draw(self): 
        mx, my = pygame.mouse.get_pos() 
        self.rect.center = (mx, my) 
        screen.blit(self.image, self.rect) 

# cria castelo 
Castle = Castle(castle_img_100, Castle_img_50, Castle_img_25, SCREEN_WIDTH - 250, SCREEN_HEIGHT - 300, 0.2) 

# Instanciar 
crosshair crosshair = Crosshair(0.025) 

# Criar botão 
repair_button = button.Button(SCREEN_WIDTH - 240, 10, repair_button.button.5) 
tower_ (SCREEN_WIDTH - 130, 10, torre_img_100, 0.1)
armour_button = button.Button(SCREEN_WIDTH - 75, 10, armour_img, 1.5) 

# Cria um grupo  
bullet_group = pygame.sprite.Group() 
inimigo_groupprite = pygame.sprite. .Grupo()
tower_group = pygame.sprite.Group() 

# Usa uma torre temporária 
# tower = Tower(tower_img_100, tower_img_50, tower_img_25, SCREEN_WIDTH - 350, 200 , 0.2) 
# tower_group.add(tower) 

# Janela de exibição do ciclo do jogo 
pygame.mixer.music.unpause() 
pygame.mixer.music.play(-1) 
run = True 
while run: 

    clock.tick(FPS) 

    if game_over = = False: 

        screen.blit(bg, (0, 0)) 
        # mostra o castelo 
        castle.draw() 
        castle.shoot() 

        # mostra a torre 
        tower_group.draw(screen) 
        tower_group.update(enemy_group) 

        # mostra a mira
        crosshair.draw() 
 
        # Desenha balas na tela 
        bullet_group.update()
        bullet_group.draw(screen) 

        # desenha inimigo 
        inimigo_group.update(tela, castelo, bullet_group) 

        # mostra informações detalhadas 
        show_info() 

        # mostra botão de reparo e botão de armadura 
        if repair_button.draw(screen): 
            Castle.repair( ) 
        if tower_button.draw(screen): 
            # Verifica se há dinheiro suficiente para construir a torre 
            if castle.money >= TOWER_COST e len(tower_group) < max_towers: 
                tower = Tower(tower_img_100, 
                              tower_img_50, 
                              tower_img_25, 
                              tower_positions[len(tower_group ) ][0],
                              tower_positions[len(tower_group)][1], 
                last_enemy = pygame.time.get_ticks() 
                              0,2)
                tower_group.add(tower) 
                # Subtrai o dinheiro gasto 
                castle.money -= TOWER_COST 

        if armor_button.draw(screen): 
            Castle.armour() 

        # Cria inimigos diferentes 
        if level_difficulty < target_difficulty: 
            if pygame.time.get_ticks() - last_enemy > ENEMY_TIMER: 
                # cria uma instância de inimigo 
                e = random.randint(0, len(enemy_tpyes) - 1) 
                inimigo = Enemy(enemy_health[e], inimigo_animações[e], -100, SCREEN_HEIGHT - 100, 1) 
                inimigo_grupo.add (inimigo ) 
                level_difficulty += inimigo_health[e] 
        # A detecção é que todos os inimigos aparecem 
        se level_difficulty >= target_difficulty:
            # Verifique quantos inimigos ainda estão vivos 
            inimigos_alive = 0 
            para e em inimigo_grupo: 
                if e.alive == Verdadeiro: 
                    inimigos_alive += 1 
            # Verifique se os inimigos vivos foram todos mortos e o nível atual está completo 
            if inimigos_alive == 0 e próximo_nível == False: 
                next_level = True 
                level_reset_time = pygame.time.get_ticks() 
        # Determine se deve entrar no próximo nível 
        if next_level == True: 
            draw_text('The level has been complete', font_60, WHITE, 200, 300) 
            # Atualize o mais alto Sub 
            se Castle.score > high_score: 
                    file.write(str(high_score)) 
                high_score = Castle.score
                com open('socre.txt', 'w') como arquivo: 
        key = pygame.key.get_pressed()
            if pygame.time.get_ticks() - level_reset_time > 1500: 
                next_level = False 
                level += 1 
                last_enemy = pygame.time.get_ticks() 
                target_difficulty *= 
                DIFFICULTY_MULTIPLIER level_difficulty = 0 
                inimigo_group.empty() 
        # verifique se o jogo acabou 
        if < = 0: 
            game_over = True 

    else: 
        draw_text('O jogo acabou!', font, GREY, 300, 300) 
        draw_text('Pressione "A" para entrar novamente no jogo', font, GREY, 250, 350) 
        pygame .mouse. set_visible(True) 
        if key[pygame.K_a]: 
            # reinicie o jogo 
            game_over = False
            level = 1 target_difficulty 
            = 1000 
            level_difficulty = 0 
            last_enemy = pygame.time.get_ticks() 
            inimigo_group.empty() 
            tower_group.empty() 
            Castle.score = 0 
            Castle.health = 1000 
            Castle.max_health = Castle.Health 
            Castle.money = 0 
            pygame.mouse.set_visible(False) 



    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
            run = False 
            pygame.quit() 
            sys.exit() 
    pygame.display.update()

arquivo de classe button.py (cerca de 50 linhas de código)

import pygame 

# Button class 
class Button(): 
   def __init__(self, x, y, image, scale): 
      width = image.get_width() 
      height = image.get_height() 
      self.image = pygame.transform.scale(image, (int(largura * escala), int(altura * escala))) 
      self.rect = self.image.get_rect() 
      self.rect.topleft = (x, y) 
      self.clicked = False 

   def draw(self, surface) : 
      action = False 
      # Obtém a posição do mouse 
      pos = pygame.mouse.get_pos() 

      # Detecta a colisão do ponteiro do mouse 
      if self.rect.collidepoint(pos): 
         if pygame.mouse.get_pressed()[0] = = 1 e self.clicked == False: 
            self.clicked = True
            action = True

      if pygame.mouse.get_pressed()[0] == 0: 
         self.clicked = False 

      # desenha o botão na superfície da 
      tela.blit(self.image, (self.rect.x, self.rect.y)) 

      return ação

Captura de tela parcial da execução:

 

 

Acho que você gosta

Origin blog.csdn.net/Abtxr/article/details/128666412
Recomendado
Clasificación