曾经迷恋的坦克大战,自己动手试试吧!

python

小时候玩的“坦克大战”,你还记得吗?

环境依赖

python3.7

pygame1.9.6

urllib

内置库,如random、sys、time、os等

pygame介绍

Pygame被设计用来写游戏的python模块集合,基于SDL库开发。使用python可以导入pygame来开发具有全部特性的游戏和多媒体软件,Pygame是极度轻便的并且可以运行在几乎所有的平台和操作系统上。

1. 导入依赖 & 通用配置

import random

import sys

import time

from urllib.request import urlretrieve

import os

import pygame

 

SCREEN_WIDTH, SCREEN_HEIGHT = 1200, 700  # 画面大小

MY_BIRTH_LEFT, MY_BIRTH_TOP = SCREEN_WIDTH / 2, SCREEN_HEIGHT - 60

DIRECTION = [U, D, L, R] = [ U ,  D ,  L ,  R ]  # 控制键

Tank_IMAGE_POSITION = r D:/tank_img

URL =  https://gitee.com/tyoui/logo/raw/master/img/

 2. 通用加载函数

# 加载图片

def load_img(name_img):

    save = Tank_IMAGE_POSITION + os.sep + name_img +  .gif

    if not os.path.exists(save):

        urlretrieve(URL + name_img +  .gif , save)

    return pygame.image.load(save)

 

# 加载背景音乐

def load_music(name_music):

    save = Tank_IMAGE_POSITION + os.sep + name_music +  .wav

    if not os.path.exists(save):

        urlretrieve(URL + name_music +  .wav , save)

    pygame.mixer.music.load(save)

    pygame.mixer.music.play()

3. 通用基础类

* pygame.sprite模块,官方文档上说这个模块是轻量级的,在游戏开发中也未必要使用。

* sprite翻译为精灵,在游戏动画一般是指一个独立运动的画面元素,在pygame中,

就可以是一个带有图像(Surface)和大小位置(Rect)的对象。

* pygame.sprite.Sprite是pygame精灵的基类,一般来说,需要写一个自己的精灵类继承一下它然后加入自己的代码。

   

class BaseItem(pygame.sprite.Sprite):

    def __init__(self):

        super().__init__()

4. 定义bullet类

class Bullet(BaseItem):

    # 参数初始化

    def __init__(self, tank, window):

        super().__init__()

        self.direction = tank.direction

        self.speed = tank.speed * 3

        self.img = load_img( bullet )

        self.rect = self.img.get_rect()

        self.window = window

        self.live = True

        if self.direction == U:

            self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2

            self.rect.top = tank.rect.top - self.rect.height

        elif self.direction == D:

            self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2

            self.rect.top = tank.rect.top + tank.rect.height

        elif self.direction == L:

            self.rect.left = tank.rect.left - self.rect.width / 2 - self.rect.width / 2

            self.rect.top = tank.rect.top + tank.rect.height / 2 - self.rect.height / 2

        else:

            self.rect.left = tank.rect.left + tank.rect.width

            self.rect.top = tank.rect.top + tank.rect.height / 2 - self.rect.height / 2

 

    # 子弹显示

    def display_bullet(self):

        self.window.blit(self.img, self.rect)

 

    # 通过按键控制子弹移动

    def bullet_move(self):

        if self.direction == U:

            if self.rect.top > 0:

                self.rect.top -= self.speed

                return

        elif self.direction == D:

            if self.rect.top < SCREEN_HEIGHT:

                self.rect.top += self.speed

                return

        elif self.direction == L:

            if self.rect.left > 0:

                self.rect.left -= self.speed

                return

        else:

            if self.rect.left < SCREEN_WIDTH:

                self.rect.left += self.speed

                return

        self.live = False

 

    # 我方坦克子弹击中对方坦克

    def hit_enemy_tank(self):

        for enemy in TankGame.enemy_tank_list:

            hit = pygame.sprite.collide_rect(self, enemy)

            if hit:

                self.live = False

                if enemy.click_count == 1:

                    enemy.live = False

                    return None

                enemy.click_count -= 1

                if enemy.click_count == 2:

                    enemy.load_image = enemy.img32

                if enemy.click_count == 1:

                    enemy.load_image = enemy.img31

                load_music( hit )

 

    # 对方坦克子弹击中我方坦克

    def hit_my_tank(self, tank):

        hit = pygame.sprite.collide_rect(self, tank)

        if hit:

            self.live = False

            tank.live = False

 

    # 子弹击中围墙

    def bullet_collide_wall(self):

        for wall in TankGame.wall_list:

            result = pygame.sprite.collide_rect(self, wall)

            if result:

                self.live = False

                if wall.count == 1:

                    wall.live = False

                else:

                    load_music( hit )

 

    # 子弹击中子弹

    def bullet_collide_bullet(self):

        for bullet in TankGame.enemy_bullet_list:

            if pygame.sprite.collide_rect(bullet, self):

                bullet.live = False

                self.live = False

5. 定义tank类

class Tank(BaseItem):

    # 参数初始化

    def __init__(self, left, top, window, image, direction, speed):

        super().__init__()

        self.window = window

        self.load_image = image

        self.direction = direction

        self.img = self.load_image[self.direction]

        self.rect = self.img.get_rect()

        self.rect.left = left

        self.rect.top = top

        self.speed = speed

        self.tank_width = self.rect.width

        self.tank_height = self.rect.height

        self.wall_switch = False

        self.move_stop = True

        self.live = True

        self.old_left = 0

        self.old_top = 0

 

    # 开火

    def fire(self):

        return Bullet(self, self.window)

 

    # 显示

    def display(self):

        self.img = self.load_image[self.direction]

        self.window.blit(self.img, self.rect)

 

    def wall_not(self, direction):

        if direction == U:

            return self.rect.top > 0

        elif direction == D:

            return self.rect.top <= SCREEN_HEIGHT - self.tank_height

        elif direction == L:

            return self.rect.left > 0

        else:

            return self.rect.left <= SCREEN_WIDTH - self.tank_width

 

    def wall_yes(self, direction):

        if direction == U:

            if self.rect.top < 0:

                self.rect.top = SCREEN_HEIGHT

        elif direction == D:

            self.rect.top %= SCREEN_HEIGHT

        elif direction == L:

            if self.rect.left < 0:

                self.rect.left = SCREEN_WIDTH

        else:

            self.rect.left %= SCREEN_WIDTH

 

    def move(self, direction):

        self.old_left = self.rect.left

        self.old_top = self.rect.top

        if self.wall_switch:

            self.wall_yes(direction)

        elif not self.wall_not(direction):

            return None

        if direction == U:

            self.rect.top -= self.speed

        elif direction == D:

            self.rect.top += self.speed

        elif direction == L:

            self.rect.left -= self.speed

        else:

            self.rect.left += self.speed

 

    def stay(self):

        self.rect.left = self.old_left

        self.rect.top = self.old_top

 

    def tank_collide_wall(self):

        for wall in TankGame.wall_list:

            if pygame.sprite.collide_rect(self, wall):

                self.stay()

 

    def tank_collide_tank(self):

        for tank in TankGame.enemy_tank_list:

            if pygame.sprite.collide_rect(self, tank):

                self.stay()

6. 定义我方 & 对方tank类

class MyTank(Tank):

    def __init__(self, left, top, window):

        self.img = dict(U=load_img( p2tankU ), D=load_img( p2tankD ), L=load_img( p2tankL ), R=load_img( p2tankR ))

        self.my_tank_speed = 4

        super().__init__(left, top, window, self.img, U, self.my_tank_speed)

 

 

class EnemyTank(Tank):

    def __init__(self, left, top, window):

        self.img1 = dict(U=load_img( enemy1U ), D=load_img( enemy1D ), L=load_img( enemy1L ), R=load_img( enemy1R ))

        self.img2 = dict(U=load_img( enemy2U ), D=load_img( enemy2D ), L=load_img( enemy2L ), R=load_img( enemy2R ))

        self.img3 = dict(U=load_img( enemy3U ), D=load_img( enemy3D ), L=load_img( enemy3L ), R=load_img( enemy3R ))

        self.img31 = dict(U=load_img( enemy3U_1 ), D=load_img( enemy3D_1 ), L=load_img( enemy3L_1 ),

                          R=load_img( enemy3R_1 ))

        self.img32 = dict(U=load_img( enemy3U_2 ), D=load_img( enemy3D_2 ), L=load_img( enemy3L_2 ),

                          R=load_img( enemy3R_2 ))

        # 不同的坦克击中的次数不一样

        image, self.click_count, speed = random.choice([(self.img1, 1, 4), (self.img3, 3, 3), (self.img2, 1, 5)])

        super().__init__(left, top, window, image, self.random_direction(), speed)

        self.step = 100

 

    @staticmethod

    def random_direction():

        n = random.randint(0, 3)

        return DIRECTION[n]

 

    def random_move(self):

        if self.step == 0:

            self.direction = self.random_direction()

            self.step = random.randint(10, 100)

        else:

            self.move(self.direction)

            self.step -= 1

 

    def random_fire(self):

        if random.randint(0, 50) == 1 and len(TankGame.enemy_bullet_list) < 30:

            enemy_bullet = self.fire()

            TankGame.enemy_bullet_list.append(enemy_bullet)

7. 爆炸动作类

class Explode(BaseItem):

    def __init__(self, tank, window):

        super().__init__()

        self.img = [load_img( blast0 ), load_img( blast1 ), load_img( blast2 ), load_img( blast3 ), load_img( blast4 ),

                    load_img( blast5 ), load_img( blast6 )]

        self.rect = tank.rect

        self.stop = 0

        self.window = window

        self.rect.left = tank.rect.left - tank.rect.width / 2

    def display_explode(self):

        load_music( blast )

        while self.stop < len(self.img):

            self.window.blit(self.img[self.stop], self.rect)

            self.stop += 1

8. 定义wall类

class Wall(BaseItem):

    def __init__(self, left, top, window):

        super().__init__()

        self.count = random.randint(0, 1)

        self.img = [load_img( steels ), load_img( walls )][self.count]

        self.rect = self.img.get_rect()

        self.rect.left = left

        self.rect.top = top

        self.window = window

        self.live = True

 

    def display_wall(self):

        self.window.blit(self.img, self.rect)

9. 定义坦克大战类

class TankGame:

    my_bullet_list = list()

    enemy_bullet_list = list()

    enemy_tank_list = list()

    wall_list = list()

 

    def __init__(self):

        if not os.path.exists(Tank_IMAGE_POSITION):

            os.makedirs(Tank_IMAGE_POSITION)

        pygame.init()

        pygame.font.init()

        self.display = pygame.display

        self.window = self.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT], pygame.RESIZABLE, 32)

        self.display.set_caption( 坦克世界 )

        self.my_tank = MyTank(MY_BIRTH_LEFT, MY_BIRTH_TOP, self.window)

        self.creat_enemy_number = 10

        self.my_tank_lift = 3

        self.creat_enemy(self.creat_enemy_number)

        self.creat_walls()

        self.font = pygame.font.SysFont( kai_ti , 18)

        self.number = 1

 

    def creat_enemy(self, number):

        for _ in range(number):

            left = random.randint(0, SCREEN_WIDTH - self.my_tank.tank_width)

            enemy_tank = EnemyTank(left, 20, self.window)

            TankGame.enemy_tank_list.append(enemy_tank)

 

    def creat_walls(self):

        for i in range(SCREEN_WIDTH // 60 + 1):

            wall_h = random.randint(100, 500)

            w = Wall(60 * i, wall_h, self.window)

            TankGame.wall_list.append(w)

 

    @staticmethod

    def show_walls():

        for w in TankGame.wall_list:

            if w.live:

                w.display_wall()

            else:

                TankGame.wall_list.remove(w)

 

    def start_game(self):

        load_music( start )

        while True:

            self.window.fill([0, 0, 0])

            self.get_event()

            len_enemy = len(TankGame.enemy_tank_list)

            self.window.blit(

                self.draw_text( 敌方坦克*{0},我方生命值*{1},当前{2}关 .format(len_enemy, self.my_tank_lift, self.number)), (10, 10))

            if len_enemy == 0:

                self.creat_enemy_number += 10

                self.number += 1

                self.my_tank_lift += 1

                self.creat_enemy(self.creat_enemy_number)

                self.wall_list.clear()

                self.creat_walls()

            self.show_my_tank()

            self.show_enemy_tank()

            self.show_bullet(TankGame.enemy_bullet_list)

            self.show_bullet(TankGame.my_bullet_list)

            self.show_walls()

            self.display.update()

            time.sleep(0.02)

 

    def show_my_tank(self):

        if self.my_tank.live:

            self.my_tank.display()

            self.my_tank.tank_collide_tank()

            self.my_tank.tank_collide_wall()

        else:

            Explode(self.my_tank, self.window).display_explode()

            del self.my_tank

            if self.my_tank_lift == 0:

                self.end_game()

            self.my_tank_lift -= 1

            load_music( add )

            self.my_tank = MyTank(MY_BIRTH_LEFT, MY_BIRTH_TOP, self.window)

        if not self.my_tank.move_stop:

            self.my_tank.move(self.my_tank.direction)

 

    def show_enemy_tank(self):

        for e in TankGame.enemy_tank_list:

            e.random_move()

            e.tank_collide_wall()

            if e.live:

                e.display()

            else:

                TankGame.enemy_tank_list.remove(e)

                Explode(e, self.window).display_explode()

            e.random_fire()

 

    def show_bullet(self, ls):

        for b in ls:

            b.bullet_move()

            b.bullet_collide_wall()

            if ls is TankGame.my_bullet_list:

                b.hit_enemy_tank()

                b.bullet_collide_bullet()

            else:

                b.hit_my_tank(self.my_tank)

            if b.live:

                b.display_bullet()

            else:

                ls.remove(b)

 

    def get_event(self):

        global SCREEN_WIDTH, SCREEN_HEIGHT

        event_list = pygame.event.get()

        for event in event_list:

            if event.type == pygame.VIDEORESIZE:

                SCREEN_WIDTH, SCREEN_HEIGHT = event.size

                self.window = self.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT], pygame.RESIZABLE, 32)

 

            if event.type == pygame.QUIT:

                self.end_game()

            if event.type == pygame.KEYDOWN:

                if event.key == pygame.K_w:

                    self.my_tank.direction = U

                elif event.key == pygame.K_s:

                    self.my_tank.direction = D

                elif event.key == pygame.K_a:

                    self.my_tank.direction = L

                elif event.key == pygame.K_d:

                    self.my_tank.direction = R

                else:

                    return None

                self.my_tank.move_stop = False

            elif event.type == pygame.MOUSEBUTTONDOWN:

                if len(TankGame.my_bullet_list) < 3:

                    bullet = self.my_tank.fire()

                    load_music( fire )

                    TankGame.my_bullet_list.append(bullet)

            elif event.type == pygame.KEYUP:

                self.my_tank.move_stop = True

 

    def end_game(self):

        self.display.quit()

        sys.exit()

 

    def draw_text(self, content):

        text_sf = self.font.render(content, True, [255, 0, 0])

        return text_sf

10. 入口

if __name__ ==  __main__ :

    g = TankGame()

    g.start_game()

执行界面

以上是 曾经迷恋的坦克大战,自己动手试试吧! 的全部内容, 来源链接: utcz.com/z/528888.html

回到顶部