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

文章目录

    • 前言:
    • 一、游戏概述
      • 1.游戏玩法
      • 2.游戏特色
    • 二、游戏规则
    • 三、工具选择
    • 四、主要技术
      • pygame 库
      • numpy 库
      • cocos2d
    • 五、源码分享
    • 六、项目地址

前言:

今天的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

主要功能:

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

numpy 库

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

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

pip install numpy

主要功能:

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

cocos2d

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

pip install cocos2d

五、源码分享

地图:

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)

游戏脚本:负责创建和管理游戏场景、处理用户输入和游戏逻辑。通过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()))

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()

游戏结束:

# -*- 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)

六、项目地址

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

在这里插入图片描述

原作:crossin

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/512750.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++】二分查找算法(模板)

重点 只需要记住两点&#xff1a; 1.left right 时&#xff0c;一定就是最终结果&#xff08;包括找不到目标值&#xff09;&#xff0c;无需再次判断&#xff0c;如果判断就会死循环 2.求中点如果是求左端点 mid left (right - left)/2 如果是求右端点 mid left (right -…

【Python项目】AI动物识别工具

目录 背景 技术简介 系统简介 界面预览 背景 成像技术在全球科技发展中扮演了关键角色。在科学研究领域&#xff0c;拍摄所得的图像成为了一种不可或缺的研究工具。特别是在生态学与动物学研究中&#xff0c;鉴于地球的广阔地域和多样的气候条件&#xff0c;利用图像技术捕…

关于我20系列显示安装cuda11.8版本一直还报找不到nvcc.exe的这档子事

这几天研究3d gaussian&#xff08;3d高斯&#xff09; 由于本人电脑还是五年前的20系列显卡&#xff0c;本身还是支持cuda的&#xff0c;就没想那么多&#xff0c;结果处处踩坑处处踩雷&#xff0c;在研究2天国内资料翻遍了的情况下&#xff0c;终于去外面看老外发了一个chec…

arm的状态寄存器

目录 一、arm 的 PSRs二、CPSR2.1 CPSR_cxsf 三、SPSR四、APSR 一、arm 的 PSRs arm 中有很多程序状态寄存器&#xff08;Program Status Registers&#xff0c;PSRs&#xff09;用于存储处理器的状态信息&#xff0c;包括 CPSR\SPSR\FPSR\APSR 等&#xff1a; CPSR&#xff…

九州金榜家庭教育孩子沉迷手机网络怎么办?

孩子沉迷于手机网络的问题&#xff0c;在当今社会已变得日益严重。手机网络的普及使得孩子们过早地接触到了虚拟世界&#xff0c;而长时间沉浸其中不仅影响他们的学业&#xff0c;还可能对他们的身心健康造成危害。那么&#xff0c;面对这一问题&#xff0c;家长应该如何应对呢…

数字人视频合成平台推荐

数字人讲解视频和全景作品的结合是一种全新的数字交互方式&#xff0c;可为用户提供更加直观和具有沉浸感的内容展示和交互体验&#xff0c;从而适用于诸如旅游、展览、博物馆、教育培训、泛房地产、以及娱乐和文化等应用场景。 当前数字人合成视频技术已经发展至日益成熟的阶…

Oracle基础-PL/SQL编程 备份

1、PL/SQL简介 PL/SQL块结构 约定&#xff1a;为了方便&#xff0c;本文后面把PL/SQL简称PL。 PL程序都是以块&#xff08;BLOCK&#xff09;为基本单位&#xff0c;整个PL块分三部分&#xff1a;声明部分&#xff08;使用DECLARE开头&#xff09;、执行部分(以BEGIN开头)和异…

武汉星起航:跨境电商优势尽显,引领全球贸易与文化交流新浪潮

在全球化日益加深的今天&#xff0c;跨境电商行业以其独特的优势和好处&#xff0c;逐渐超越了国内电商行业&#xff0c;成为了电商领域的新宠。跨境电商不仅拓展了企业的市场范围&#xff0c;还为消费者带来了更多选择和便利。武汉星起航认为与国内电商相比&#xff0c;跨境电…

5032温补晶振的一些常用型号和实例应用

5032晶振是常用的一种尺寸的晶振&#xff0c;而5032温补晶振因为其高精度高稳定性而被广泛应用。小尺寸封装5.0mm*3.2mm*1.45mm&#xff0c;非常节省空间&#xff0c;便于设计与使用。其实爱普生推出了一系列的5032温补晶振:以TG5032CAN、TG5032SAN、TG5032CDN、TG5032SDN&…

IDEA一行代码出现下划实线,怎么处理?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

【Qt】使用Qt实现Web服务器(九):EventSource+JSON实现工业界面数据刷新

1、效果 效果如下,实时刷新温度、湿度 2、源码 2.1 index.html <html><body> <!-- 页面布局,本人对HTML标签不熟悉,凑合看吧 --> <div><label for

整顿编剧市场:程序员提交测试流程的最佳实践

讲动人的故事,写懂人的代码 最近,一部去年推出的国产电视剧在IT圈子里引起了轰动。 引起关注的原因,并非剧中程序员的外形出众,而是她提交代码测试的方式——将写有代码的纸张放入文件夹,然后递给了对面的测试人员。如图1所示。 图1 程序员将写有代码的纸张放入文件夹,并…

2024年全新靠谱的FTP替代升级解决方案

随着企业规模的扩大和业务的多元化&#xff0c;传统的TCP协议在数据传输效率上逐渐显现出局限性。TCP协议虽然以其稳定性和可靠性被广泛应用&#xff0c;但在面对大规模数据传输时&#xff0c;其性能瓶颈逐渐成为企业发展的阻碍。同时&#xff0c;基于TCP的应用协议如Telnet、F…

JS两道题:判断这个月有几天;计算薪资缴税。

计算的时候直接在字符串模版中没问题的&#xff1a; swicth语句分支结构&#xff1a;&#xff08;很多不一样的固定值&#xff09; break结束当前穿透现象 他它的表达式的结果和值必须是全等的关系 当所有的值都不匹配的时候就执行这个部分代码 其实就是在考察条件问题。比如&…

网络钓鱼升级 Darcula如何窃取用户信息

近日&#xff0c;网络安全领域一种名为 “Darcula” 的网络钓鱼欺诈&#xff08;PhaaS&#xff09;悄然兴起。这种新型钓鱼方式不同于传统的手段&#xff0c;它巧妙地利用了谷歌信息和 iMessage 的富通信服务&#xff08;RCS&#xff09;&#xff0c;成为了网络犯罪分子的新手段…

AI绘画软件有什么用?

人工智能(AI)的应用已经渗透到我们生活的各个角落&#xff0c;其中就包括图像生成。AI绘画软件&#xff0c;是一种基于深度学习技术的创新工具&#xff0c;它能够根据指定的风格、主题或者素材自动创作出新的图片。那么&#xff0c;AI绘画软件具体有什么用呢? 首先&#xff0c…

开源大模型AI代理操作系统:像Windows一样,操控AI代理

去年&#xff0c;AutoGPT的出现让我们见识到了AI代理强大的自动化能力&#xff0c;并开创了一个全新的AI代理赛道。但在子任务调度、资源分配以及AI之间协作还有不少的难题。 因此&#xff0c;罗格斯大学的研究人员开源了AIOS&#xff0c;这是一种以大模型为核心的AI代理操作系…

资源优化题

资源平滑类资源优化题 不改变关键路径的情况下&#xff0c;如何避免资源扎堆使用。 破解思路: 1、能串行尽量串行。 2、一定要并行&#xff0c;尽量躲开跟人数多的活动并行。 3、如何躲开&#xff0c;就靠时差来实现。 例题1&#xff1a;某工程包括A、B、C、D、E、F、G七项工作…

Vue ElementPlus Input 输入框

Input 输入框 通过鼠标或键盘输入字符 input 为受控组件&#xff0c;它总会显示 Vue 绑定值。 通常情况下&#xff0c;应当处理 input 事件&#xff0c;并更新组件的绑定值&#xff08;或使用v-model&#xff09;。否则&#xff0c;输入框内显示的值将不会改变&#xff0c;不支…

生鲜网上交易信息系统的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)海鲜,餐饮电商,超市,农产品,购物车,订单管理,广告信息管理,生鲜信息管理

本项目包含可运行源码数据库LW&#xff0c;文末可获取本项目的所有资料。 推荐阅读300套最新项目持续更新中..... 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含ja…