• 技术文章 >头条

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

     Ly Ly2020-06-10 12:09:58转载2441

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

    p1.jpg

    环境依赖

    python3.7

    pygame1.9.6

    urllib

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

    pygame介绍

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

    1. 导入依赖 & 通用配置

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    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. 通用加载函数

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    # 加载图片

    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. 通用基础类

    1

    2

    3

    4

    5

    6

    7

    8

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

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

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

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

        

    class BaseItem(pygame.sprite.Sprite):

        def __init__(self):

            super().__init__()

    4. 定义bullet类

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

    76

    77

    78

    79

    80

    81

    82

    83

    84

    85

    86

    87

    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类

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

    76

    77

    78

    79

    80

    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类

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    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. 爆炸动作类

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    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类

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    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. 定义坦克大战类

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

    76

    77

    78

    79

    80

    81

    82

    83

    84

    85

    86

    87

    88

    89

    90

    91

    92

    93

    94

    95

    96

    97

    98

    99

    100

    101

    102

    103

    104

    105

    106

    107

    108

    109

    110

    111

    112

    113

    114

    115

    116

    117

    118

    119

    120

    121

    122

    123

    124

    125

    126

    127

    128

    129

    130

    131

    132

    133

    134

    135

    136

    137

    138

    139

    140

    141

    142

    143

    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. 入口

    1

    2

    3

    if __name__ ==  __main__ :

        g = TankGame()

        g.start_game()

    执行界面

    p1.jpg

    专题推荐:python
    上一篇:Python教你随时看美剧! 下一篇:超好看的3D绘图方式,Python厉害了!

    相关文章推荐

    • python如何爬取网页数据步骤图解• python里怎么调用函数• python的字符如何保存• python input函数如何不要引号• python如何解决报表显示中文乱码• python的ide PyCharm怎么放大字体

    全部评论我要评论

    © 2021 Python学习网 苏ICP备2021003149号-1

  • 取消发布评论
  • 

    Python学习网