• Python实现【贪吃蛇大作战】+源码


    前言:

    今天的GitHub小游戏分享,我们将聚焦于一个经典而又极富趣味性的游戏——贪吃蛇大作战。这款游戏不仅考验玩家的反应速度和策略规划,而且在不断的更新和迭代中,增加了更多的现代元素和创新玩法,使得它能够吸引各年龄层的玩家。现在我带大家手把手用Python复刻出童年回忆!

    在这里插入图片描述

    一、游戏概述

    贪吃蛇大作战》是由武汉微派网络科技有限公司研发的一款极具人气的休闲竞技类手机游戏。自推出以来,它以其独特的游戏机制和易于上手的操作方式,迅速在全球范围内获得了巨大的成功和影响力。这款游戏不仅仅是一场简单的手速比拼,更是一场对玩家策略布局和应变能力的全面考验。

    1.游戏玩法

    在《贪吃蛇大作战》的世界里,玩家一开始操控的是一条细小的蛇。通过巧妙地移动和策略性地捕食,玩家可以使自己的蛇快速成长,变得更加强大。游戏中,蛇需要在地图上躲避其他玩家的蛇,同时吃掉随机出现的食物来增长身体长度。随着蛇的不断增长,玩家需要更加小心地操控,避免撞到自己的尾巴或是其他玩家的蛇,因为每一次碰撞都可能导致游戏的结束。
    在这里插入图片描述

    2.游戏特色

    • 多人在线竞技:玩家可以与来自世界各地的对手同场竞技,体验紧张刺激的对战乐趣。
    • 实时排行榜:游戏内设有实时更新的排行榜,玩家可以随时查看自己的全球排名,并与好友一较高下。
    • 丰富的皮肤系统:玩家可以通过游戏内的货币解锁各种独特的蛇皮肤,打造个性化的游戏角色。
    • 多样化的游戏模式:除了经典的生存模式,游戏还提供了多种不同的游戏模式,满足不同玩家的需求。
    • 社交互动:玩家可以添加好友,组建队伍,一起参与游戏,增强了游戏的社交属性。

    二、游戏规则

    • 初始状态:游戏开始时,每位玩家控制一条位于地图中心的小蛇。

    • 移动控制:玩家通过屏幕上的虚拟摇杆或者触摸屏幕的滑动来控制蛇的移动方向。

    • 成长与进食:地图上会随机出现食物点,玩家需要引导自己的蛇去吃掉这些食物。每吃掉一个食物点,蛇的长度就会增加一小段。

    • 避免碰撞:在游戏中,玩家需要避免自己的蛇头撞到自己的蛇身或者游戏边界,否则游戏结束。同时,也要尽量避免与其他玩家的蛇发生碰撞,因为碰撞可能会导致蛇失去部分身体长度或者直接被淘汰。

    • 竞争与合作:虽然玩家需要避免与其他蛇的直接接触,但游戏中也存在一定的竞争和合作元素。玩家可以选择围堵其他玩家,迫使他们撞到自己的身体或边界,从而获得优势。同时,玩家也可以通过合作来共同对抗更强大的对手。

    • 生存与排名:游戏的目标是尽可能长时间地生存下去,并在游戏结束时拥有最长的蛇身。游戏会根据玩家的表现给予相应的排名和奖励。

    在这里插入图片描述

    三、工具选择

    要使用Python实现《贪吃蛇大作战》游戏,以下是具体所需的工具:

    1. Python 3.8.0 或更高版本:用于编写游戏代码。
    2. Pygame:用于创建游戏界面和处理游戏逻辑。
    3. PyCharmVisual Studio Code:用于编写和调试代码。
    4. Git:用于代码管理和协作。

    四、主要技术

    pygame 库

    pygame 是一个开源的Python模块,专门用于编写视频游戏。它包含了图形、声音、事件处理等功能,非常适合用来开发2D游戏。使用 pygame,我们可以轻松创建游戏窗口、处理用户输入、绘制图形和动画,以及添加音效等。

    安装:可以通过 pip 命令安装 pygame:

    pip install pygame
    
    • 1

    主要功能:

    • 创建游戏窗口和表面对象。
    • 处理键盘和鼠标事件。
    • 绘制图形和文本。
    • 添加音效和背景音乐。
    • 控制游戏循环和帧率。

    numpy 库

    numpy 是Python中用于科学计算的基础库,提供了强大的多维数组对象和各种用于操作这些数组的工具。在游戏中,我们可以使用 numpy 来处理蛇的身体结构和食物的随机生成位置。

    安装:可以通过 pip 命令安装 numpy:

    pip install numpy
    
    • 1

    主要功能:

    • 创建和操作多维数组。
    • 进行高效的数学运算。
    • 生成随机数,用于食物的随机位置生成。

    cocos2d

    使用了 cocos2d-python 作为游戏引擎。如果要运行代码,需要安装 cocos2d 库。

    pip install cocos2d
    
    • 1

    五、源码分享

    地图:

    import cocos
    from cocos.director import director
    
    import define
    from snake import Snake
    from dot import Dot
    
    class Arena(cocos.layer.ColorLayer):
        is_event_handler = True
    
        def __init__(self):
            super(Arena, self).__init__(250, 255, 255, 255, define.WIDTH, define.HEIGHT)
            self.center = (director.get_window_size()[0] / 2, director.get_window_size()[1] / 2)
            self.batch = cocos.batch.BatchNode()
            self.add(self.batch)
    
            self.snake = Snake()
            self.add(self.snake, 10000)
            self.snake.init_body()
    
            self.enemies = []
            for i in range(7):
                self.add_enemy()
    
            self.keys_pressed = set()
    
            for i in range(50):
                self.batch.add(Dot())
    
            self.schedule(self.update)
    
        def add_enemy(self):
            enemy = Snake(True)
            self.add(enemy, 10000)
            enemy.init_body()
            self.enemies.append(enemy)
    
        def update(self, dt):
            self.x = self.center[0] - self.snake.x
            self.y = self.center[1] - self.snake.y
    
        def on_key_press(self, key, modifiers):
            self.keys_pressed.add(key)
            self.snake.update_angle(self.keys_pressed)
    
        def on_key_release (self, key, modifiers):
            self.keys_pressed.remove(key)
            self.snake.update_angle(self.keys_pressed)
    
    • 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

    游戏脚本:负责创建和管理游戏场景、处理用户输入和游戏逻辑。通过Cocos引擎提供的类和方法,这个脚本实现了一个简单的游戏循环,包括游戏的开始、运行、结束和重新开始。

    import cocos
    
    import define
    from arena import Arena
    from gameover import Gameover
    
    class HelloWorld(cocos.layer.Layer):
        is_event_handler = True
    
        def __init__(self):
            super(HelloWorld, self).__init__()
            self.arena = Arena()
            self.add(self.arena)
            self.score = cocos.text.Label('30',
                                          font_name='Times New Roman',
                                          font_size=24,
                                          color=define.GOLD)
            self.score.position = 20, 440
            self.add(self.score, 99999)
    
            self.gameover = Gameover()
            self.add(self.gameover, 100000)
    
        def update_score(self):
            self.score.element.text = str(self.arena.snake.score)
    
        def end_game(self):
            self.gameover.visible = True
            self.gameover.score.element.text = str(self.arena.snake.score)
    
        def on_mouse_press(self, x, y, buttons, modifiers):
            if self.gameover.visible:
                self.gameover.visible = False
                self.arena.unschedule(self.arena.update)
                self.remove(self.arena)
                self.arena = Arena()
                self.add(self.arena)
                self.update_score()
    
    
    cocos.director.director.init(caption="Gluttonous Python")
    cocos.director.director.run(cocos.scene.Scene(HelloWorld()))
    
    • 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

    snake.py贪吃蛇

    # -*- coding: utf-8 -*-
    import math
    import random
    import cocos
    from cocos.sprite import Sprite
    
    import define
    from dot import Dot
    
    
    class Snake(cocos.cocosnode.CocosNode):
        no = 0
    
        def __init__(self, is_enemy=False):
            super(Snake, self).__init__()
            self.is_dead = False
            self.angle = random.randrange(360)  # 目前角度
            self.angle_dest = self.angle  # 目标角度
            self.color = random.choice(define.ALL_COLOR)
            self.no = Snake.no
            Snake.no += 1
            if is_enemy:
                self.position = random.randrange(300, 1300), random.randrange(200, 600)
                if 600 < self.x < 1000:
                    self.x += 400
            else:
                self.position = random.randrange(700, 900), random.randrange(350, 450)
            self.is_enemy = is_enemy
            self.head = Sprite('circle.png', color=self.color)
            self.scale = 1.5
            eye = Sprite('circle.png')
            eye.y = 5
            eye.scale = 0.5
            eyeball = Sprite('circle.png', color=define.BLACK)
            eyeball.scale = 0.5
            eye.add(eyeball)
            self.head.add(eye)
            eye = Sprite('circle.png')
            eye.y = -5
            eye.scale = 0.5
            eyeball = Sprite('circle.png', color=define.BLACK)
            eyeball.scale = 0.5
            eye.add(eyeball)
            self.head.add(eye)
    
            self.add(self.head)
    
            self.speed = 150
            if not is_enemy:
                self.speed = 180
            self.path = [self.position] * 100
    
            self.schedule(self.update)
            if self.is_enemy:
                self.schedule_interval(self.ai, random.random() * 0.1 + 0.05)
    
        def add_body(self):
            b = Sprite('circle.png', color=self.color)
            b.scale = 1.5
            self.body.append(b)
            if self.x == 0:
                print(self.position)
            b.position = self.position
            try:
                self.parent.batch.add(b, 999 + 100*self.no - len(self.body))
            except:
                print(999 + 100*self.no - len(self.body))
    
        def init_body(self):
            self.score = 30
            self.length = 4
            self.body = []
            for i in range(self.length):
                self.add_body()
    
        def update(self, dt):
            self.angle = (self.angle + 360) % 360
    
            arena = self.parent
            if self.is_enemy:
                self.check_crash(arena.snake)
            for s in arena.enemies:
                if s != self and not s.is_dead:
                    self.check_crash(s)
            if self.is_dead:
                return
    
            if abs(self.angle - self.angle_dest) < 2:
                self.angle = self.angle_dest
            else:
                if (0 < self.angle - self.angle_dest < 180) or (
                    self.angle - self.angle_dest < -180):
                    self.angle -= 500 * dt
                else:
                    self.angle += 500 * dt
            self.head.rotation = -self.angle
    
            self.x += math.cos(self.angle * math.pi / 180) * dt * self.speed
            self.y += math.sin(self.angle * math.pi / 180) * dt * self.speed
            self.path.append(self.position)
    
            lag = int(round(1100.0 / self.speed))
            for i in range(len(self.body)):
                idx = (i + 1) * lag + 1
                self.body[i].position = self.path[-min(idx,len(self.path))]
                if self.body[i].x == 0:
                    print(self.body[i].position)
            m_l = max(self.length * lag * 2, 60)
            if len(self.path) > m_l:
                self.path = self.path[int(-m_l * 2):]
    
        def update_angle(self, keys):
            x, y = 0, 0
            if 65361 in keys:  # 左
                x -= 1
            if 65362 in keys:  # 上
                y += 1
            if 65363 in keys:  # 右
                x += 1
            if 65364 in keys:  # 下
                y -= 1
            directs = ((225, 180, 135), (270, None, 90), (315, 0, 45))
            direct = directs[x + 1][y + 1]
            if direct is None:
                self.angle_dest = self.angle
            else:
                self.angle_dest = direct
    
        def add_score(self, s=1):
            if self.is_dead:
                return
            self.score += s
            l = (self.score - 6) / 6
            if l > self.length:
                self.length = l
                self.add_body()
    
        def ai(self, dt):
            self.angle_dest = (self.angle_dest + 360) % 360
            if (self.x < 100 and 90 < self.angle_dest < 270) or (
                self.x > define.WIDTH - 100 and (
                    self.angle_dest < 90 or self.angle_dest > 270)
            ):
                self.angle_dest = 180 - self.angle_dest
            elif (self.y < 100 and self.angle_dest > 180) or (
                self.y > define.HEIGHT - 100 and self.angle_dest < 180
            ):
                self.angle_dest = -self.angle_dest
            else:
                arena = self.parent
                self.collision_detect(arena.snake)
                for s in arena.enemies:
                    if s != self:
                        self.collision_detect(s)
    
        def collision_detect(self, other):
            if self.is_dead or other.is_dead:
                return
            for b in other.body:
                d_y = b.y - self.y
                d_x = b.x - self.x
                if abs(d_x) > 200 or abs(d_y) > 200:
                    return
                if d_x == 0:
                    if d_y > 0:
                        angle = 90
                    else:
                        angle = -90
                else:
                    angle = math.atan(d_y / d_x) * 180 / math.pi
                    if d_x < 0:
                        angle += 180
                angle = (angle + 360) % 360
                if abs(angle - self.angle_dest) < 5:
                    self.angle_dest += random.randrange(90, 270)
    
        def check_crash(self, other):
            if self.is_dead or other.is_dead:
                return
            if (self.x < 0 or self.x > define.WIDTH) or (
                self.y < 0 or self.y > define.HEIGHT
            ):
                self.crash()
                return
            for b in other.body:
                dis = math.sqrt((b.x - self.x) ** 2 + (b.y - self.y) ** 2)
                if dis < 24:
                    self.crash()
                    return
    
        def crash(self):
            if not self.is_dead:
                self.is_dead = True
                self.unschedule(self.update)
                self.unschedule(self.ai)
                arena = self.parent
                for b in self.body:
                    arena.batch.add(Dot(b.position, b.color))
                    arena.batch.add(Dot(b.position, b.color))
                    arena.batch.remove(b)
    
                arena.remove(self)
                arena.add_enemy()
                del self.path
                if self.is_enemy:
                    arena.enemies.remove(self)
                    del self.body
                    del self
                else:
                    arena.parent.end_game()
    
    • 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
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210

    游戏结束:

    # -*- coding: utf-8 -*-
    import cocos
    from cocos.director import director
    import define
    
    class Gameover(cocos.layer.ColorLayer):
        def __init__(self):
            super(Gameover, self).__init__(200, 235, 235, 200, 400, 300)
            self.position = (director.get_window_size()[0] / 2 - 200,
                             director.get_window_size()[1] / 2 - 150)
            self.visible = False
            self.score = cocos.text.Label('',
                                          font_name='SimHei',
                                          font_size=36,
                                          color=define.MAROON)
            self.score.position = 250, 200
            self.add(self.score)
    
            text = cocos.text.Label('SCORE: ',
                                    font_name='SimHei',
                                    font_size=24,
                                    color=define.MAROON)
            text.position = 50, 200
            self.add(text)
            text = cocos.text.Label('CLICK TO REPLAY...',
                                    font_name='SimHei',
                                    font_size=24,
                                    color=define.MAROON)
            text.position = 50, 100
            self.add(text)
    
    • 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

    六、项目地址

    https://github.com/Luoyukeji/python-

    在这里插入图片描述

    原作:crossin

  • 相关阅读:
    Android OpenGL ES 3.0 3D模型介绍以及加载和渲染
    Navicat 携手华为云 GaussDB,联合打造便捷高效的数据库开发和建模工具方案
    USACO 2021 December Contest, Silver
    InheritableThreadLocal 在线程池中进行父子线程间消息传递出现消息丢失的解析
    springboot集成canal实现同步双写
    Iterable、Collection、List等接口
    JavaCV人脸识别三部曲之一:视频中的人脸保存为图片
    Python库学习(八):Numpy[续篇二]:数组操作
    微服务(基础篇-007-RabbitMQ部署指南)
    【iOS-界面传值方式的比较】
  • 原文地址:https://blog.csdn.net/m0_68089732/article/details/137343560