Unity之街机捕鱼

news2024/12/29 8:15:43

目录

😪炮台系统

🎶炮口方向跟随鼠标

🎶切换炮台

😪战斗系统

🎮概述

🎮单例模式 

🎮开炮

🎮子弹脚本

🎮渔网脚本 

🎮鱼属性信息的脚本

😪奖励和等级的实现 

😪Unity数据持久化

📖保存游戏

📖继续游戏

📖开始新游戏

最近又跟着教程从头到尾完成了一个实例,虽然是好久之前的教程,但是老师讲的很好,我作为Unity初学者也收获很多,复盘后把收获写在这篇博客上,希望看到的你同样会有收获。


来看一下实例效果:切换炮台、捕鱼、加减金币(消耗炮弹的金币)、等级头衔设置、保存、继续游戏;作为一个捕鱼游戏基本功能都很齐全。

Unity中级案例 - 捕鱼达人哔哩哔哩_bilibili 教程分为上、中、下三部分。上主要对游戏UI进行设计和制作;中负责完成游戏主要玩法战斗系统;下对游戏进一步优化包括特效、音效、游戏保存、游戏发布。


UI和特效这里就先不说了,可以跟着教程实操一下。这里想记录核心玩法的实现和编码思路 ,学会思路和实现方式在其他想写的游戏上也能用到。

炮台系统

炮口方向跟随鼠标

所谓炮口方向跟随鼠标就是给炮口一个旋转朝向鼠标的方向。

我们要做的是获取 鼠标到炮台中心的连线 和 炮口所指位置的 夹角,然后将炮台 z轴旋转的数值 设置到和夹角一致就可以实现炮口方向跟随鼠标转动的目的。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//让炮口跟随鼠标
public class GunFollow : MonoBehaviour
{
    public RectTransform UGUICanvas;
    public Camera mainCamera;
    void Update()
    {
        //定义鼠标的当前位置
        Vector3 mousePos;
        //将屏幕坐标转换为世界坐标,结合Input.mousePosition获取鼠标在 当前Canvas(炮台所在的Canvas) 下的位置
        RectTransformUtility.ScreenPointToWorldPointInRectangle(UGUICanvas,
            new Vector2(Input.mousePosition.x, Input.mousePosition.y), mainCamera,out mousePos);

        //定义 z轴 的旋转值
        float z;
        
        //判断鼠标在炮口左边还是右边
        if (mousePos.x > transform.position.x)
        {
            //Vector3.up  表示炮口的正方向
            //mousePos - transform.position  向量相减得到一条线;  与炮口正方向形成夹角
            //Vector3.Angle()  鼠标和炮台的夹角计算方法  返回值为正数  所以要判断鼠标在炮口左边还是右边
            z = -Vector3.Angle(Vector3.up, mousePos - transform.position);
        }
        else
        {
            z = Vector3.Angle(Vector3.up, mousePos - transform.position);
        }
        
        //设置炮口旋转
        transform.localRotation = Quaternion.Euler(0, 0, z);
    }
}

给所有炮台都挂载上跟随脚本:

切换炮台

炮台在游戏中一共有五种,同样也对应着五种子弹类型(每种子弹类型又有不同颜色与等级相对应),(每一炮所需要的金币数量)类型却有20种。也就是说每一种炮台分别有四挡所消耗的金币数。

来看看脚本是怎么实现的:

public class GameController : MonoBehaviour
{
   //所有炮台的预设体,用来更换炮台
    public GameObject[] gunGos;

    //炮弹生成点父物体
    public Transform bulletHolder;
    //五种炮弹预制体,对应五种炮台
    public GameObject[] bullet1Gos;
    public GameObject[] bullet2Gos;
    public GameObject[] bullet3Gos;
    public GameObject[] bullet4Gos;
    public GameObject[] bullet5Gos;

    //每一炮所消耗的金币数档位
    private int[] oneShootCosts =  { 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 };

    //使用的是第几档消耗金币数档位
    private int costIndex = 0;  //五种炮台对应20个消耗金币档位,也就是说每种炮台对应四个消耗金币档位
    
    void Update()
    {
        ChangeBulletCost();
    }

    //通过滚轮改变每发炮弹所消耗的钱
    void ChangeBulletCost()
    {
        if (Input.GetAxis("Mouse ScrollWheel") < 0)
        {
            OnButtonMDown();
        }
        if (Input.GetAxis("Mouse ScrollWheel") > 0)
        {
            OnButtonPDown();
        }
    }
    
    public void OnButtonPDown()
    {
        //costIndex  表示消耗金币档位,炮台和消耗金币档位是1对4的关系,那么 costIndex / 4  代表了我们在用哪个炮台
        //禁用武器          
        gunGos[costIndex / 4].SetActive(false);
        costIndex++;
        //播放音效
        AudioManager.Instance.PlayEffectSound(AudioManager.Instance.changeClip);
        //播放换枪特效
        Instantiate(changeEffect);
        //防止数组越界
        costIndex = (costIndex > oneShootCosts.Length - 1) ? 0 : costIndex;
        //启用武器
        gunGos[costIndex / 4].SetActive(true);
        
        //更新每发炮弹所消耗的钱
        oneShootCostText.text = "$" + oneShootCosts[costIndex];
    }

    public void OnButtonMDown()
    {
        //禁用武器
        gunGos[costIndex / 4].SetActive(false);
        costIndex--;
        AudioManager.Instance.PlayEffectSound(AudioManager.Instance.changeClip);
        //播放换枪特效
        Instantiate(changeEffect);
        //防止数组越界
        costIndex = (costIndex < 0) ? oneShootCosts.Length - 1 : costIndex;
        //启用武器
        gunGos[costIndex / 4].SetActive(true);
        //更新每发炮弹所消耗的钱
        oneShootCostText.text = "$" + oneShootCosts[costIndex];
    }
}

战斗系统

概述


当炮弹射出去之后碰到鱼;炮弹会消失生成渔网;渔网生成后也会在特定的时间消失。

同时渔网在消失前会对鱼进行碰撞检测;撞到渔网的鱼也会对自身生命值进行判断;

鱼死了(┏┛<・)))><<  墓┗┓) ——  播放死亡动画销毁自身并生成金币,对应玩家金币数量增加;鱼没死  ——  接着游,炮台接着开炮。



 单例模式 

我们来看一下实例中单例模式的应用:

public class GameController : MonoBehaviour
{
    //单例模式
    private static GameController _instance;
    public static GameController Instance
    {
        get
        {
            return _instance;
        }
    }
    //在Awake()生命周期函数中给 _instance 赋值
    void Awake()
    {
        _instance = this;
    }

    //定义初始金币和经验值
    public int exp = 0;
    public int gold = 500;
}

//=================================================================
//当鱼死亡后通过单例模式增加 GameController 脚本中的金币和经验值
//=================================================================
            //当鱼死亡加金币和经验值
            GameController.Instance.gold += gold;
            GameController.Instance.exp += exp;

开炮

每个炮台都有一个空对象用来标记子弹发射点;来看看脚本是怎么实现开炮功能的:

  //开炮
    void Fire()
    {
        //当前炮台用的什么子弹,默认是第五种炮使用的炮弹
        GameObject[] useBullets = bullet5Gos;
        int bulletIndex;
        
        //当按下发射键并没有碰到其他UI按键(比如加减钱按钮、设置按钮)时才会发射炮弹
        if (Input.GetMouseButtonDown(0) && EventSystem.current.IsPointerOverGameObject() == false)
        {
            //判断当前金币够不够开炮
            if (gold - oneShootCosts[costIndex] >= 0)
            {
                switch (costIndex / 4)
                {
                    case 0: useBullets = bullet1Gos; break;
                    case 1: useBullets = bullet2Gos; break;
                    case 2: useBullets = bullet3Gos; break;
                    case 3: useBullets = bullet4Gos; break;
                    case 4: useBullets = bullet5Gos; break;
                }
                //根据等级分配哪一套子弹里的哪一种颜色
                bulletIndex = (lv % 10 >= 9) ? 9 : lv % 10;
                //扣钱
                gold -= oneShootCosts[costIndex];
                //播放音效
                AudioManager.Instance.PlayEffectSound(AudioManager.Instance.fireClip);
                //播放开火特效
                Instantiate(fireEffect);
                //实例化子弹
                GameObject bullet = Instantiate(useBullets[bulletIndex]);
                bullet.transform.SetParent(bulletHolder, false);
            
                //让子弹的朝向和旋转都和炮口开炮位置一样
                bullet.transform.position = gunGos[costIndex / 4].transform.Find("FirePos").transform.position;
                bullet.transform.rotation = gunGos[costIndex / 4].transform.Find("FirePos").transform.rotation;
                //设置子弹的伤害值
                bullet.GetComponent<BulletAttr>().damage = oneShootCosts[costIndex];  //把价格的序号传过去
            
                //让子弹移动
                bullet.AddComponent<Ef_AutoMove>().dir = Vector3.up; //改变方向
                bullet.GetComponent<Ef_AutoMove>().speed = bullet.GetComponent<BulletAttr>().speed ;     //给子弹速度    
            }
            else
            {
                //TODO Flash The Text;如果金币不足,通过闪烁金币数值提醒玩家
                StartCoroutine(GoldNotEnough());  //以协程的方式开启
            }
        }
    }

   //金币不足开炮时进行闪烁提示
    IEnumerator GoldNotEnough()
    {
        goldText.color = goldColor;
        goldText.color = Color.red;
        //让程序在这等待0.5秒然后从这接着运行
        yield return new WaitForSeconds(0.5f);
        goldText.color = goldColor;
    }

子弹脚本

public class BulletAttr : MonoBehaviour
{
    //子弹速度
    public int speed;
    //子弹伤害值
    public int damage;
    //子弹碰到鱼后生成网的预制体
    public GameObject webPrefab;

    private void OnTriggerEnter2D(Collider2D collision)
    {
        //如果撞到边界(屏幕之外设定了一个UI边界),直接销毁自身
        if (collision.tag == "Border")
        {
            Destroy(gameObject);
        }
        //如果撞到鱼,销毁自身并生成网
        if (collision.tag == "Fish")
        {
            //生成网
            GameObject web = Instantiate(webPrefab);
            web.transform.SetParent(gameObject.transform.parent, false);
            //网的位置等于当前子弹的位置
            web.transform.position = gameObject.transform.position;
            //将子弹的伤害赋值给网的伤害
            web.GetComponent<WebAttr>().damage = damage;
            Destroy(gameObject);
        }
    }
}

渔网脚本 

public class WebAttr : MonoBehaviour
{
    //网消失的时间
    public float disapperTime;
    //子弹的伤害
    public int damage;

    void Start()
    {
        //隔多长时间销毁网自身
        Destroy(gameObject, disapperTime);
    }
    
    //检测是否碰到鱼
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.tag=="Fish")
        {
            //发送消息 给 FishAttr脚本 的 TakeDamage() 方法
            //通知鱼 我(渔网)打到你了 伤害值为 damage
            collision.SendMessage("TakeDamage", damage);
        }
    }
}

鱼属性信息的脚本

//记录鱼的属性信息
public class FishAttr : MonoBehaviour
{
    //每种鱼的这些属性值都不一样,自己来设定
    public int hp;    //血量
    public int exp;   //经验值
    public int gold;  //金币值
    public int maxNum;    //生成最大数量
    public int maxSpeed;  //最大速度 

    //鱼死亡预设体
    public GameObject diePrefab;
    //金币预设体
    public GameObject goldPrefab;

    private void OnTriggerEnter2D(Collider2D collision)
    {
        //撞到边界(屏幕之外设定了一个UI边界)就销毁鱼
        if (collision.tag == "Border")
        {
            Destroy(gameObject);
        }
    }

    //鱼受伤
    void TakeDamage(int value)  //value是从WebAttr脚本传过来的伤害值
    {
        hp -= value;
        //鱼死亡
        if (hp <= 0)
        {
            //当鱼死亡加金币和经验值 —— 单例模式的应用
            GameController.Instance.gold += gold;
            GameController.Instance.exp += exp;
            
            //播放鱼死亡动画
            GameObject die = Instantiate(diePrefab);
            die.transform.SetParent(gameObject.transform.parent, false);
            die.transform.position = transform.position;
            die.transform.rotation = transform.rotation;
            
            //鱼死亡实例化金币
            GameObject goldGo = Instantiate(goldPrefab);
            goldGo.transform.SetParent(gameObject.transform.parent, false);
            goldGo.transform.position = transform.position;
            goldGo.transform.rotation = transform.rotation;
            //判断鱼身上有没有播放特效的脚本 Ef_PlayEffect
            if (gameObject.GetComponent<Ef_PlayEffect>() != null)
            {
                AudioManager.Instance.PlayEffectSound(AudioManager.Instance.rewardClip);
                gameObject.GetComponent<Ef_PlayEffect>().PlayEffect();
            }
            Destroy(gameObject);
        }
    }
}

奖励和等级的实现 

游戏中为避免玩家金币耗光有两种金币奖励功能:小奖励通过每60s倒计时自动给玩家50金币;大奖励240s倒计时结束后变为按钮,玩家点击按钮会获得500金币然后会重新倒计时。

 游戏设定等级称号为:"新手", "入门", "钢铁", "青铜", "白银", "黄金", "白金", "钻石", "大师", "宗师"。根据等级来对应称号

提示玩家升到多少级的UI文本: 

 脚本实现:

public class GameController : MonoBehaviour
{
    //等级
    public int lv = 0;
    //经验
    public int exp = 0;
    //初始金币值
    public int gold = 500;
    public const int bigCountdown = 240;   //240秒大奖励
    public const int smallCountdown = 60;  //60秒小奖励
    public float bigTimer = bigCountdown;  //计时器
    public float smallTimer = smallCountdown;

    private string[] lvName = { "新手", "入门", "钢铁", "青铜", "白银", "黄金", "白金", "钻石", "大师", "宗师" };

    void Update()
    {
        //更新等级
        UpdateUI();
    }

    void UpdateUI()
    {
        bigTimer -= Time.deltaTime;   //倒计时
        smallTimer -= Time.deltaTime; //倒计时
        //如果小计时器小于0,给玩家发金币
        if (smallTimer <= 0)
        {
            //计时器重新计时
            smallTimer = smallCountdown;
            gold += 50;
        }
        //大计时器小于0 并且 当按钮没有显示出来才会执行
        if (bigTimer <= 0 && bigCountdownButton.gameObject.activeSelf == false)
        {
            //倒计时结束隐藏计时器
            bigCountdownText.gameObject.SetActive(false);
            //显示领取金币按钮
            bigCountdownButton.gameObject.SetActive(true);
        }

        //经验等级换算公式:升级所需经验=1000+200*当前等级
        while (exp >= 1000 + 20*lv)
        {
            exp = exp - (1000 + 200 * lv);
            lv++;
            //提示玩家升到多少级
            lvUpTips.SetActive(true);
            lvUpTips.transform.Find("Text").GetComponent<Text>().text = lv.ToString();
            //启动协程把提示关闭
            StartCoroutine(lvUpTips.GetComponent<Ef_HideSelf>().HideSelf(0.6f));
            //播放音效
            AudioManager.Instance.PlayEffectSound(AudioManager.Instance.lvUpClip);
            //播放升级特效
            Instantiate(lvEffect);
        }
        goldText.text = "$" + gold;
        lvText.text = lv.ToString();
        //如果玩家等级超过99级,就一直是宗师
        if ((lv / 10) <= 9)
        {
            lvNameText.text = lvName[lv / 10];
        }
        else
        {
            lvNameText.text = lvName[9];
        }
        //小计时器                           拿到十位数                       拿到个位
        smallCountdownText.text = "  " + (int)smallTimer / 10 + "  " + (int)smallTimer % 10;
        //大计时器
        bigCountdownText.text = (int)bigTimer + "s";
        //滑动条显示的是比例 —— 滑动条用来显示等级进度
        expSlider.value = ((float)exp) / (1000 + 20 * lv);
    }
    
    //大计时器点击领取金币按钮
    public void OnBigCountdownButtonDown()
    {
        gold += 500;
        AudioManagerFwl.Instance.PlayEffectSound(AudioManagerFwl.Instance.rewardClip);
        //显示加金币特效
        Instantiate(goldEffect);
        //领取完隐藏按钮
        bigCountdownButton.gameObject.SetActive(false);
        //显示倒计时
        bigCountdownText.gameObject.SetActive(true);
        //给倒计时重新赋值
        bigTimer = bigCountdown;
    }
}

Unity数据持久化

Unity的这种数据持久化是通过 键值对 的方式存储在 Windows注册表 

unity PlayerPrefs数据存储位置_playerprefer保存的数据位置-CSDN博客文章浏览阅读1.4k次,点赞4次,收藏8次。1、首先查看自己当前工程的名字:可以在Unity->Edit->Project Settings->Player中设置与查看,如图所示:2、按下键盘Win+R键,输入regedit,打开注册表编辑器,找到相应位置查看如下图:_playerprefer保存的数据位置https://blog.csdn.net/Monkey_Xuan/article/details/115518561unity3d--PlayerPrefs 游戏存档_unity 修改playerprefs.setfloat-CSDN博客文章浏览阅读5.7k次,点赞4次,收藏42次。Unity3D游戏开发之数据持久化PlayerPrefs的使用 转载自 本文作者:秦元培,本文出处:http://blog.csdn.net/qinyuanpei/article/details/24195977 博主今天研究了在Unity3D中的数据持久化问题。数据持久化在任何一个开发领域都是一个值得关注的问题,小到一个_unity 修改playerprefs.setfloathttps://blog.csdn.net/acmer_sly/article/details/52675954

保存游戏

游戏一共两个场景:一个Start游戏开始界面场景和Main主要玩法场景。在Main中有一个 返回 按钮点击会返回到开始界面场景中,当我们按下这个按钮保存当前游戏的功能就发挥了作用。

我们需要保存的数据有金币数量、当前等级、当前倒计时数值、还有背景音乐的开关。


当我们按下返回按钮后 :

    //返回按钮
    public void OnBackButtonDown()
    {
        //TODO 保存当前游戏  PlayerPrefs只支持 int float string 三种数据类型
        //保存金币值
        PlayerPrefs.SetInt("gold", GameController.Instance.gold);
        //保存等级
        PlayerPrefs.SetInt("lv", GameController.Instance.lv); 
        //小计时器
        PlayerPrefs.SetFloat("scd", GameController.Instance.smallTimer);
        //大计时器
        PlayerPrefs.SetFloat("bcd", GameController.Instance.bigTimer);
        //保存经验值
        PlayerPrefs.SetInt("exp", GameController.Instance.exp);
        int temp = (AudioManager.Instance.IsMute == false) ? 0 : 1;
        //保存当前游戏场景的背景音乐是开还是关
        PlayerPrefs.SetInt("mute", temp);
        //跳转到开始界面场景
        UnityEngine.SceneManagement.SceneManager.LoadScene(2);
    }

继续游戏

当我们点击完返回按钮来到游戏开始界面后,点击 继续游戏 按钮会获取保存好的玩家信息。

public class GameController : MonoBehaviour
{
    //等级
    public int lv = 0;
    //经验
    public int exp = 0;
    public int gold = 500;
    public const int bigCountdown = 240;   //240大奖励
    public const int smallCountdown = 60;  //60秒小奖励
    public float bigTimer = bigCountdown;  //计时器
    public float smallTimer = smallCountdown;


    //读取游戏
    void Start()
    {
        //通过键值对的形式获取保存好的数值
        gold = PlayerPrefs.GetInt("gold", gold);
        lv = PlayerPrefs.GetInt("lv", lv);
        exp = PlayerPrefs.GetInt("exp", exp);
        smallTimer = PlayerPrefs.GetFloat("scd", smallCountdown);
        bigTimer = PlayerPrefs.GetFloat("bcd", bigCountdown);
        UpdateUI();
    }
}

 开始新游戏

保存好玩家信息后如果点击 开始游戏 ,通过脚本会删除保存好的玩家信息开始新游戏。

using UnityEngine;
using UnityEngine.SceneManagement;

public class StartSceneUI : MonoBehaviour
{
    //开始游戏按钮清空数据后在加载游戏场景
    public void NewGame()
    {
        //根据键删除保存好的值
        PlayerPrefs.DeleteKey("gold");
        PlayerPrefs.DeleteKey("lv");
        PlayerPrefs.DeleteKey("exp");
        PlayerPrefs.DeleteKey("scd");
        PlayerPrefs.DeleteKey("bcd");
        SceneManager.LoadScene(1);
    }

    //继续游戏直接加载游戏场景,在 GameController 脚本获取保存好的玩家信息
    public void OldGame()
    {
        SceneManager.LoadScene(1);
    }

    public void OnCloseButton()
    {
        //退出游戏
        Application.Quit();
    }
}

想要完整源码就在评论区评论吧,本篇到这里就先结束了,希望我们都能有所收获,拜拜┏(^0^)┛ 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTML5:七天学会基础动画网页9

在进行接下来的了解之前我们先来看一下3d的xyz轴&#xff0c;下面图中中间的平面就相当于电脑屏幕&#xff0c;z轴上是一个近大远小的效果。 3d转换属性 transform 2D或3D转换 transform-origin 改变旋转点位置 transform-style 嵌套元素在3D空间如何显 …

文件二维码怎么加访问权限?加密、限时、限次的二维码制作技巧

扫码查看或者下载文件已经是现在经常被使用的一种方式&#xff0c;当我们通过这种方式来展现文件内容时&#xff0c;是否能够加入一些权限设置来保障文件的安全性&#xff0c;是很多小伙伴非常关心的一个问题。 想要制作文件二维码&#xff0c;大多情况下会通过在线二维码生成…

GPQA数据集分享

来源: AINLPer公众号&#xff08;每日干货分享&#xff01;&#xff01;&#xff09; 编辑: ShuYini 校稿: ShuYini 时间: 2024-2-28 尽管AI系统在许多任务上表现出色&#xff0c;但在需要大量专业知识和推理能力的任务上仍然存在局限性。为此&#xff0c;纽约大学的研究者提出…

Yii2中如何使用scenario场景,使rules按不同运用进行字段验证

Yii2中如何使用scenario场景&#xff0c;使rules按不同运用进行字段验证 当创建news新闻form表单时&#xff1a; 添加新闻的时候执行create动作。 必填字段&#xff1a;title-标题&#xff0c;picture-图片&#xff0c;description-描述。 这时候在model里News.php下rules规则…

智慧城市中的数据力量:大数据与AI的应用

目录 一、引言 二、大数据与AI技术的融合 三、大数据与AI在智慧城市中的应用 1、智慧交通 2、智慧环保 3、智慧公共安全 4、智慧公共服务 四、大数据与AI在智慧城市中的价值 1、提高城市管理的效率和水平 2、优化城市资源的配置和利用 3、提升市民的生活质量和幸福感…

【人工智能课程】计算机科学博士作业三

【人工智能课程】计算机科学博士作业三 来源&#xff1a;李宏毅2022课程第10课的作业 1 图片攻击概念 图片攻击是指故意对数字图像进行修改&#xff0c;以使机器学习模型产生错误的输出或者产生预期之外的结果。这种攻击是通过将微小的、通常对人类难以察觉的扰动应用于输入…

1.5 简述转置卷积的主要思想以及应用场景

1.5 简述转置卷积的主要思想以及应用场景 普通的卷积主要思想&#xff1a; 普通的卷积操作可以形式化为一个矩阵乘法运算&#xff0c;即yAx&#xff08;1-12&#xff09; 其中&#xff0c;x和y分别是卷积的输入和输出(展平成一维向量形式)&#xff0c;维度分别为d⁽i⁾和d⁽…

计算机设计大赛 深度学习花卉识别 - python 机器视觉 opencv

文章目录 0 前言1 项目背景2 花卉识别的基本原理3 算法实现3.1 预处理3.2 特征提取和选择3.3 分类器设计和决策3.4 卷积神经网络基本原理 4 算法实现4.1 花卉图像数据4.2 模块组成 5 项目执行结果6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &a…

[网络安全] PKI

一、PKI 概述 名称; 公钥基础设施 (Public Key Facility) 作用: 通过加密技术和数字签名保证信息安全 组成: 公钥机密技术、数字证书、CA、RA 二、信息安全三要素 机密性&#xff1a;确保仅信息发收双方 能看懂信息 完整性&#xff1a; 确保信息发收完整&#xff0c;不被破坏 …

阿珊带你深入理解 async/await 函数

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【RabbitMQ】WorkQueue

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;MQ ⛺️稳中求进&#xff0c;晒太阳 Work Queues Work queues任务模型&#xff0c;简单来说就是让多个消费者绑定到一个队列&#xff0c;共同消费队列中的消息 当消息处理比较耗时的时候&…

仿牛客网项目---消息队列的实现

本篇文章讲一讲我们的项目中用到的消息队列。 1.阻塞队列 2.kafka 我的项目为什么要用消息队列&#xff1f; 如果采用消息队列&#xff0c;那么评论、点赞、关注三类不同的事&#xff0c;可以定义三类不同的主题&#xff08;评论、点赞、关注&#xff09;&#xff0c;发生相应…

基于cnn卷积神经网络的车辆颜色检测识别-图像去雾-图像去雨(改进yolo目标检测-附代码)

– 引言&#xff1a; 开篇简述图像处理在智能交通监控、自动驾驶等领域的关键作用&#xff0c;并强调随着深度学习尤其是卷积神经网络&#xff08;CNN&#xff09;的发展&#xff0c;在复杂环境下的车辆颜色精确识别、图像恢复&#xff08;如去雾和去雨&#xff09;等难题得以…

基于毕奥-萨伐尔定律的交流电机的4极旋转磁场matlab模拟与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于毕奥-萨伐尔定律的交流电机的4极旋转磁场&#xff0c;对比不同定子半径&#xff0c;对比2级旋转磁场。 2.系统仿真结果 3.核心程序与模型 版本&#xff1a;MATLAB2022a…

程序异常结束退出 无输出 无显式报错日志 爆栈

需求 开一个很大的数组&#xff08;300万&#xff09; ❗ 错误示例 #include <stdio.h>int main() {int size 3000000;int a[size];a[size-1] 999;printf("%d",a[size-1]);return 0; }&#x1f60b; 解决方案 局部变量存储在栈空间 &#xff08;较小&…

国家积极推进长城国家文化公园建设

长城脚下&#xff0c;文化绽放——国家积极推进长城国家文化公园建设 在中华大地的北方&#xff0c;横亘着一条巨龙&#xff0c;它见证着中华民族的沧桑岁月&#xff0c;承载着我们的民族记忆&#xff0c;它就是——长城。这座千年的雄关&#xff0c;不仅是中国的象征&#xf…

【漏洞复现】-用友CRM系统存在逻辑漏洞直接登录后台

免责声明&#xff1a; 本文内容为学习笔记分享&#xff0c;仅供技术学习参考&#xff0c;请勿用作违法用途&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。任何个人和组织利用此文所提供的信息而造成的直接或间接后果和损失&#xff0c;…

CentOS网络故障排查秘笈:实战指南

前言 作为一名热爱折腾 Linux 的技术达人&#xff0c;我深知网络故障会让人抓狂&#xff01;在这篇文章里&#xff0c;我和你分享了我的心得体会&#xff0c;从如何分析问题、识别瓶颈&#xff0c;到利用各种神器解决网络难题。不管你是新手小白还是老鸟大神&#xff0c;这里都…

opengl 学习(二)-----你好,三角形

你好&#xff0c;三角形 分类demo效果解析 分类 opengl c demo #include "glad/glad.h" #include "glfw3.h" #include <iostream> #include <cmath> #include <vector>using namespace std;/** * 在学习此节之前&#xff0c;建议将这…

javascript操作BOM的方法

目录 1.window.alert() 2.window.confirm() 3.window.prompt() 4.window.location() 5.window.navigator() 6.window.screen() 7.window.history() 8.window.setTimeout() 和 window.clearTimeout() 9.window.setInterval() 和 window.clearInterval() BOM&#xff08…