Python - Batalla de defensa del castillo

Realiza la función:

1: ¡El avance continuo del enemigo, sosteniendo una variedad de armas (tenedores, hachas, espadas), balanceando armas para atacar nuestro castillo, causando daños a nuestro castillo!

2: Si nuestro castillo encuentra al enemigo, podemos hacer clic manualmente con el botón izquierdo del mouse para lanzar un ataque de bala, causando daños fatales a los japoneses y ¡causándoles la muerte!

3: Visualización de datos completa, atacando al enemigo para obtener monedas de oro, puntos acumulados, el nivel actual de la tarjeta de gestión, la visualización del valor de salud de nuestro castillo, etc., las monedas de oro obtenidas al matar al enemigo se pueden cambiar por atributos adicionales para equipar y restaurar y fortalecer nuestra fortaleza!

4: La interfaz de diseño del proyecto es hermosa y limpia, combinada con el fondo del juego de música pura agregado y los efectos de sonido de ataque y la visualización de animación en tiempo real (por ejemplo, la apariencia de nuestro castillo cambiará a medida que disminuya el valor de salud de nuestro castillo , es decir, se descompondrá, etc.) para que el proyecto sea más jugable.

5: ¡Llevar este proyecto a la práctica o como un simple diseño de curso de Python también es una opción posible!

6: el código total del proyecto es de aproximadamente 700 líneas

Conocimientos de programación utilizados:

Conceptos básicos de Python, lectura y escritura de archivos OS, módulo pygame y pensamiento orientado a objetos.

el código se muestra a continuación:

archivo de la clase enemigo.py (alrededor de 100 líneas 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 = True 
      self.speed = speed 
      self. salud = salud 
      self.last_attack = pygame.time.get_ticks() 
      self.attack_cooldown = 1000 
      self.animation_list = animation_list 
      self.frame_index = 0 
      self.action = 0#0: caminar, 1: atacar, 2: morir 
      self.update_time = pygame.time.get_ticks() 

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


   actualización def(self, superficie, objetivo, grupo_balas): 
      if self.alive: 
         #comprobar colisión con balas 
         if pygame.sprite.spritecollide(self, grupo_bullet, True): 
            #reducir la salud del enemigo 
            self.health -= 25 

         #check if el enemigo ha llegado al castillo 
         si self.rect.right > target.rect.left: 
            self.update_action(1) 

         #mover enemigo 
         if self.action == 0: 
            #actualizar la posición del rectángulo 
            self.rect.x += self.speed 

         # ataque 
         si self.action == 1:
            #verificar si ha pasado suficiente tiempo desde el ú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() 


         #verificar si la salud ha bajado a cero 
         si self.health <= 0: 
            target.money += 100 
            target.score += 100 
            self.update_action(2)#death 
            self.alive = False 

      self.update_animation() 

      #dibujar imagen en la 
      superficie de la pantalla.blit (self.image, (self.rect.x - 10, self.rect.y - 15)) 


   def update_animation(self): 
      #define el enfriamiento de la animación
      ANIMATION_COOLDOWN = 50 
      #actualizar la imagen según la acción actual 
      self.image = self.animation_list[self.action][self.frame_index] 
      #verificar si ha pasado suficiente tiempo desde la última actualización 
      if pygame.time.get_ticks() - self.update_time > ANIMACIÓN_ENFRIAMIENTO: 
         self.update_time = pygame.time.get_ticks() 
         self.frame_index += 1 
      #si la animación se agotó, reinicie de nuevo al inicio 
      if self.frame_index >= len(self.animation_list[self.action]) : 
         if self.action == 2: 
            self.frame_index = len(self.animation_list[self.action]) - 1 
   def update_action(self, new_action): 
         else:
            self.frame_index = 0 


      #verificar si la nueva acción es diferente a la anterior 
      if new_action != self.action: 
         self.action = new_action 
         #actualizar la configuración de animación 
         self.frame_index = 0 
         self.update_date = pygame.time.get_ticks( )

archivo de clase castle.py (alrededor de 500 líneas de código)

# Importar biblioteca 
import pygame 
import math 
import os 
import sys import 
botón de 
importación aleatoria 
desde pygame import mixer 
# Inicializar pygame 
pygame.init() 
# Definir la altura y el ancho de la ventana del juego 
SCREEN_WIDTH = 800 
SCREEN_HEIGHT = 600 
# Cargar música de fondo 
pygame.mixer.music. load("sonido/bjmusic.WAV") 
pygame.mixer.music.set_volume(0.3) 
jump_fx = pygame.mixer.Sound("sonido/bullet.wav") 
jump_fx.set_volume(0.5) 
# crear 
pantalla de ventana de juego = pygame. display.set_mode((PANTALLA_ANCHO, PANTALLA_ALTO)) 
pygame.display.set_caption("Castle Defense") 
clock = pygame.time.Clock() 
FPS = 60 
# Define la variable del juego 
high_score = 0



 
nivel de la variable del juego = 1 
nivel_difficulty = 0 
Target_DiffiCulty = 1000 Difmity_Multiplier 
= 1.1 Game_over = 
false 
next_level = false 
enemy_timer = 1000 last_enemy 
= 
pygame.time.get_ticks () 
enemies_alive 
= 0 
max_towers = 4 
tower_cost = 5000 
# 炮塔 位置 位置 位置 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的 的- 250, SCREEN_HEIGHT - 200], 
[SCREEN_WIDTH - 200, SCREEN_HEIGHT - 150], 
[SCREEN_WIDTH - 150, SCREEN_HEIGHT - 150], 
[SCREEN_WIDTH - 100, SCREEN_HEIGHT - 150] 
] 
# 加载最高分
si os'path.exists socre.txt'): 
    con open('socre.txt', 'r') como archivo: 
        high_score = int(file.read())


# Definir el color 
tower_img_50 = pygame.image.load('img/tower/tower_50.png').convert_alpha()
BLANCO = (255, 255, 255) 
GRIS = (100, 100, 100) 

# Definir la fuente 
fuente = pygame.font.SysFont('Nubes coloridas chinas', 30) 
font_60 = pygame.font.SysFont('Xingkai chino' , 60 ) 

# cargar imagen 
bg = pygame.image.load('img/bg.png').convert_alpha() 
# castillo 
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() 

# torreta 
torre_img_100 = pygame. image.load('img/tower/tower_100.png').convert_alpha() 
tower_img_25 = pygame.image.load('img/tower/tower_25.png').convert_alpha() 

# imagen de viñeta
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 ) 

_ 
_ 
    _ 
        _ 
        _ = True 
        self.speed = velocidad 
        self.health = salud 
        self.last_attack = pygame.time.get_ticks() 
        self.attack_cooldown = 1000  
        self.animation_list = animation_list
        self.frame_index = 0 
        self.action = 0 
        self.update_time = pygame.time.get_ticks() 
        #选择动画开始的图片
        self.imagen = self.animation_list[self.action][self.frame_index] 
        self.rect = pygame.Rect(0, 0, 25, 40) 
        self.rect.center = (x, y) 

    def update(self, superficie , target, bullet_group): 
        if self.alive: 
            # Comprobar si el enemigo ha chocado con la bala 
            if pygame.sprite.spritecollide(self, bullet_group, True): 
                # Reducir la salud 
                self.health -= 25 
            # Comprobar si el enemigo ha alcanzado el castillo 
            si self .rect.right > target.rect.left: 
                self.update_action(1) 
            # mover al enemigo 
            if self.action == 0:  
                self.rect.x += 1
            # atacar el castillo 
            if self.action == 1: 
                # detectar enfriamiento
                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() 
            # Comprobar la sangre del enemigo Si la barra es 0 
            si self.health <= 0: 
                target.money += 100 
                target.score += 100 
                self.update_action(2) 
                self.alive = False 
        # llamar a actualizar la animación 
        self.update_animation() 
        # dibujar la  
        # pygame. dibujar. rect(superficie, (255, 255, 255), self. rect, 1)
        superficie enemiga. blit (self. image, (self. rect. x - 10, self. rect. y - 15)) 

    def update_animation(self):
        # Definir el tiempo de enfriamiento de la animación 
        ANIMATION_COOLDOWN = 50 
        # Actualizar el marco de acuerdo con la calabaza de cera seleccionada 
        self.image = self.animation_list[self.action][self.frame_index] 
        # Determinar con qué frecuencia actualizar el marco 
        si pygame.time.get_ticks () - self.update_time > ANIMATION_COOLDOWN: 
            self.update_time = pygame.time.get_ticks() 
            self.frame_index += 1 
        # Compruebe que el número de fotogramas no puede exceder el número máximo de fotogramas 
        si self.frame_index >= len(self. animation_list[self.action]): 
            if self.action == 2: 
                self.frame_index = len(self.animation_list[self.action]) - 1 
            else: 
        # Comprobar si la nueva acción es igual que el anterior 
                self.frame_index = 0
    def update_action(self, new_action): 
        if new_action != self.action: 
            self.action = new_action 
            # actualizar animación reset 
            self.frame_index = 0 
            self.update_time = pygame.time.get_ticks() 


# cargar lista de enemigos 
enemigos_animaciones = [] 
enemigos_tpyes = ['knight', 'goblin', 'purple_goblin', 'red_goblin'] 
enemiga_salud = [75, 100, 125, 150] 

animation_types = ['caminar', 'atacar', 'muerte'] 
para el enemigo en enemigos_tpyes: 
    # Cargue la lista de 
    animaciones animation_list = [] 
    para animaciones en animation_types: 
        # Crear una lista temporal 
        temp_list = [] 
        # Definir el número de fotogramas 
        num_of_frames = 20 
        para i en el rango (num_of_frames):
            img = pygame.image.load(f'img/enemigos/{enemigo}/{animación}/{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) 
    enemiga_animaciones.append(animation_list) 

# cargar imagen de botón 
repair_img = pygame.image .load('img/repair.png').convert_alpha() 
armour_img = pygame.image.load('img/armour.png').convert_alpha() 

# Mostrar información de texto en la pantalla 
def draw_text(text, font, text_color , x, y): 
# Definir una función para mostrar el estado 
def show_info(): 
    img = fuente.render(texto, True, color_texto)
    screen.blit(img, (x, y)) 

    draw_text('钱数:' + str(castle.money), font, GREY, 10, 10) 
    draw_text('分数:' + str(castle.score), font , GREY, 180, 10) 
    draw_text('最分数:' + str(high_score), fuente, GREY, 180, 50) 
    draw_text('级别:' + str(level), font, GREY, SCREEN_WIDTH // 2, 10 ) 
    draw_text('健康:' + str(castillo.salud) + "/" + str(castillo.max_salud), fuente, GRIS, ANCHO_PANTALLA - 230, ALTURA_PANTALLA - 50) 
    draw_text('1000', fuente, GRIS, ANCHO_PANTALLA - 250, 70) 
    draw_text(str(TOWER_COST), font, GREY, SCREEN_WIDTH - 150, 70) 
    draw_text('500', font, GREY, SCREEN_WIDTH - 70, 70) 

# 城堡类
class Castle(): 
    def __init__(self, imagen100, imagen50, imagen25,x, y, escala): 
        self.health = 1000 
        self.max_health = self.salud 
        self.fired = Falso
        self.money = 0 
        self.score = 0 
        ancho = imagen100.get_width() 
        altura = imagen100.get_altura() 

        self.imagen100 = pygame.transform.scale(imagen100, (int(ancho * escala), int(altura * escala) )) 
        self.image50 = pygame.transform.scale(image50, (int(ancho * escala), int(altura * escala))) 
        self.image25 = pygame.transform.scale(imagen25, (int(ancho * 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])
        self.angle = math.degrees(math.atan2(y_dist, x_dist)) 
        # Haga clic con el mouse en esta posición 
        si pygame.mouse.get_pressed()[0] y 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() 
        # restablecer clic del mouse 
        si pygame .mouse.get_pressed()[0] == False: 
            self.fired = False 

    def draw(self): 
        # Determina qué imagen cargar según el volumen de sangre 
        si self.health <= 250: 
            self.image = self.image25  
        elif self.health <= 500:
            self .imagen = self.imagen50 
        más:
            self.image = self.image100 
        screen.blit(self.image, self.rect) 

    def repair(self): 
        if self.money >= 1000 and self.health < self.max_health: 
            self.health += 500 
            self.money -= 1000 
            if castillo.salud > castillo.max_salud: 
                castillo.salud = castillo.max_salud 
    def armadura(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):  
        super().__init__()
        self.got_target = False 
        self.angle = 0
        self.last_shot = pygame.time.get_ticks() 
        ancho = imagen100.get_width() 
        altura = imagen100.get_height() 

        self.image100 = pygame.transform.scale(image100, (int(ancho * escala), int(altura * escala ))) 
        self.image50 = pygame.transform.scale(image50, (int(ancho * escala), int(altura * escala))) 
        self.image25 = pygame.transform.scale(imagen25, (int(ancho * escala) , int(altura * escala))) 
        self.imagen = self.imagen100 
        self.rect = self.imagen100.get_rect() 
        self.rect.x = x 
        self.rect.y = y 
    def update(self, grupo_enemigo): 
        self .got_target = Falso  
        para e en grupo_enemigo:
            si e.alive:
                target_x, target_y = e.rect.midbottom 
                self.got_target = Corte verdadero 
        si self.got_target: 
                x_dist 
            = target_x - self.rect.midleft[0] 
            y_dist = -(target_y - self.rect.midleft[1]) 
            self.angle = matemáticas.grados(matemáticas.atan2(y_dist, x_dist)) 
            # pygame.draw.line(pantalla, BLANCO, (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: 
                bullet = Bullet(bullet_img, self.rect.midleft[0], self.rect.midleft[1], self.angle) 
                self.last_shot = pygame.time.get_ticks()
                bullet_group.add(bullet) 
        # Carga esa imagen según el volumen de sangre del castillo 
        if castle.health <= 250: 
            self.image = self.image25 
        elif castle.health <= 500: 
            self.image = self.image50 
        else: 
            self. image = self.image100 

# Crear clase de viñeta 
class Bullet(pygame.sprite.Sprite): 
    def __init__(self, image, x, y, angle): 
        super().__init__() 
        self.image = image 
        self.rect = self .image.get_rect() 
        self.rect.x = x  
        self.rect.y = y
        self.angle = math.radianes(ángulo) # Convertir ángulos a radianes 
        self.speed = 10 
        # Calcular velocidades horizontales y verticales basadas en ángulos
        self.dx = math.cos(self.angle) * self.speed 
        self.dy = -(math.sin(self.angle) * self.speed) 

    def update(self): 
        # Comprobar si la bala ha superado la ventana 
        if self .rect.right < 0 o self.rect.left > SCREEN_WIDTH o self.rect.bottom < 0 o self.rect.top > SCREEN_HEIGHT: 
            self.kill() 
        # mover la viñeta 
        self.rect.x += self .dx 
        self .rect.y += self.dy 

# Crear una 
clase de punto de mira Crosshair(): 
    def __init__(self, scale): 
        image = pygame.image.load("img/crosshair.png").convert_alpha() 
        ancho = imagen .get_width() 
        altura = imagen.get_height()
        self.imagen = pygame.transform.scale(imagen, (int(ancho * escala), int(altura * escala))) 
        self.rect = self.image.get_rect() 
        # ocultar el puntero del mouse 
        pygame.mouse.set_visible(False ) 

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

# crear castillo 
castillo = Castillo(castillo_img_100, castle_img_50, castle_img_25, SCREEN_WIDTH - 250, SCREEN_HEIGHT - 300, 0.2) # Crear una 

instancia de 
crosshair crosshair = Crosshair(0.025) 

# Create button 
repair_button = button.Button(SCREEN_WIDTH - 240, 10, repair_button.button.5) 
tower_ (SCREEN_WIDTH - 130, 10, torre_img_100, 0.1) 
botón_armadura = botón.Botón(ANCHO_PANTALLA - 75, 10, armadura_img, 1.5) 

# crear grupo 
bullet_group = pygame.sprite.Group() 
grupo_enemigoprite = pygame.sprite. .Grupo() 
tower_group = pygame.sprite.Group() 

# Usar una torre temporal 
# tower = Tower(tower_img_100, tower_img_50, tower_img_25, SCREEN_WIDTH - 350, 200 , 0.2) 
# tower_group.add(tower) 

# Ventana de visualización del ciclo del juego 
pygame.mixer.music.unpause() 
pygame.mixer.music.play(-1) 
run = True 
while run: 

    clock.tick(FPS) 

    if game_over = = Falso: 

        pantalla.blit(bg, (0, 0)) 
        # mostrar castillo castillo.dibujar 
        () 
        castillo.disparar() 

        # mostrar torreta 
        grupo_torre.dibujar(pantalla) 
        grupo_torre.update(grupo_enemigo) 

        # mostrar punto de mira
        crosshair.draw() 
 
        # Dibujar balas en la pantalla 
        bullet_group.update()
        bullet_group.draw(screen) 

        # dibujar enemigo 
        enemigo_group.update(screen, castle, bullet_group) 

        # mostrar información detallada 
        show_info() 

        # mostrar botón de reparación y botón de armadura 
        if repair_button.draw(screen): 
            castle.repair( ) 
        if tower_button.draw(screen): 
            # Comprobar si hay suficiente dinero para construir la torre 
            if castle.money >= TOWER_COST and len(tower_group) < max_towers: 
                tower = Tower(tower_img_100, 
                              tower_img_50, 
                              tower_img_25, 
                              tower_positions[len(tower_group) ) ][0],
                              posiciones_de_torre[len(grupo_de_torre)][1], 
                último_enemigo = pygame.time.get_ticks() 
                              0.2)
                grupo_torre.add(torre) 
                # Resta el dinero gastado 
                castillo.dinero -= COSTE_TORRE 

        si botón_armadura.dibujar(pantalla): 
            castillo.armadura() 

        # Crear diferentes enemigos 
        si nivel_dificultad < dificultad_objetivo: 
            si pygame.time.get_ticks() - último_enemigo > ENEMY_TIMER: 
                # crear una instancia de enemigo 
                e = random.randint(0, len(enemy_tpyes) - 1) 
                enemigo = Enemigo(enemy_health[e], enemigos_animaciones[e], -100, SCREEN_HEIGHT - 100, 1) 
                enemigo_grupo.add (enemigo ) 
                nivel_dificultad += salud_enemiga[e] 
        # La detección es que todos los enemigos 
        aparecen si nivel_dificultad >= dificultad_objetivo:
            # 
            Comprueba 
            cuántos 
                enemigos 
                    siguen 
            vivos 
            . False: 
                next_level = True 
                level_reset_time = pygame.time.get_ticks() 
        # Determinar si ingresar al siguiente nivel 
        si next_level == True: 
            draw_text('El nivel ha sido completado', font_60, WHITE, 200, 300) 
            # Actualizar el más alto Sub 
            si castle.score > high_score: 
                with open('socre.txt', 'w') as file: 
                    file.write(str(high_score)) 
                high_score = castle.score
            if pygame.time.get_ticks() - level_reset_time > 1500: 
                next_level = False 
                level += 1 
                last_enemy = pygame.time.get_ticks() 
                target_difficulty *= DIFICULTAD_MULTIPLIER 
                level_difficulty = 0 
                grupo_enemigo.empty() 
        # comprobar si el juego ha terminado 
        if < pygame 
            _ 

    _ 
        _ 
        _ 
        _ .mouse.set_visible(True)  
        key = pygame.key.obtener_presionado()
        if key[pygame.K_a]: 
            # restablecer el juego 
            game_over = False
            nivel = 1 
            target_difficulty = 1000 
            level_difficulty = 0 
            last_enemy = pygame.time.get_ticks() 
            grupo_enemigo.vacío() 
            grupo_torre.vacío() 
            castillo.puntuación = 0 
            castillo.salud = 1000 
            castillo.max_salud = castillo.salud 
            castillo.dinero = 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()

archivo de clase button.py (alrededor de 50 líneas de código)

import pygame 

# Clase 
de botón clase Botón(): 
   def __init__(self, x, y, image, scale): 
      ancho = image.get_width() 
      height = image.get_height() 
      self.image = pygame.transform.scale(image, (int(ancho * escala), int(altura * escala))) 
      self.rect = self.image.get_rect() 
      self.rect.topleft = (x, y) 
      self.clicked = False 

   def dibujar(self, superficie) : 
      action = False 
      # Obtener la posición del mouse 
      pos = pygame.mouse.get_pos() 

      # Detectar la colisión del puntero del mouse 
      if self.rect.collidepoint(pos): 
         if pygame.mouse.get_pressed()[0] = = 1 y self.clicked == False: 
            self.clicked = True
            action = True 

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

      # dibujar el botón en la superficie de la pantalla.blit 
      (self.image, (self.rect.x, self.rect.y ) ) 

      acción de retorno

Captura de pantalla de ejecución parcial:

 

 

Supongo que te gusta

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