【用unity实现100个游戏之6】制作一个战旗自走棋类游戏(附源码)

文章目录

  • 前言
  • 导入素材
  • 开始
      • 1. 设置瓦片间隙
      • 2. 放置全图瓦片
      • 3. 美化瓦片地图
      • 4. 添加树木障碍物
      • 5. 设定不同的排序图层
      • 6. 瓦片交互
      • 6. 瓦片交互优化
      • 6. 瓦片是否允许角色
      • 7. 添加角色
      • 8. 新增游戏管理脚本
      • 9. 角色移动范围逻辑
      • 10. 角色移动范围可视化
      • 11. 角色移动
      • 12. 重置瓦片颜色
      • 12. 限制移动次数
      • 13. 最终效果
  • 其他
  • 源码下载
  • 参考
  • 完结

前言

探索战争与策略的无穷魅力,让我们一同踏入一个充满战旗的世界!战旗游戏作为战棋类游戏的翘楚,引领了一股独特的战斗风潮。你是否曾经想过,如果能够自己设计并实现一个属于自己的战旗游戏,该是何等的创造与乐趣?

在本文中,我们将使用Unity引擎,探索如何快速构建一个简单而富有策略的战旗游戏Demo。通过本教程的指引,你将学习如何使用Unity的强大功能和库,创造出一个令人着迷的战旗世界。

在这个Demo中,我们将以一个虚拟的大陆为背景,玩家将担任敌对阵营的指挥官,通过战略布局和英勇的决策,争夺控制权。你可以选择完善这个demo,如每个棋子具有独特的能力和特点,如守护剑士的高生命值、魔法师的强大攻击力等,通过购买、升级和精心安排棋子的位置,引领你的队伍战胜对手,达到最终的胜利目标!

另外,最近很火的自走棋也属于战旗游戏的一种。自走棋是战棋类游戏的变种,它保留了战旗游戏的核心元素,如策略布局和战斗对抗,同时加入了自动化的棋子行动机制。

为了帮助你更好地理解,我们特别准备了一些战旗游戏的精彩截图和GIF动画,展示了战旗游戏的精彩瞬间。这些截图将带你亲身体验游戏的视觉效果和紧张的战斗氛围。

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

无论是战旗游戏爱好者还是对Unity开发感兴趣的朋友,本教程都将为你揭开战旗游戏的奥秘,帮助你构建一个引人入胜的战旗游戏Demo。

照例先来看看本文实现的最终效果,以觉得你是否还要看下去
在这里插入图片描述

好了,让我们开始我们的战旗之旅吧!
源码放在文章底部了

导入素材

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

开始

1. 设置瓦片间隙

新建一个2d项目,打开以后,将所需要的【图片】拖入到项目中
我们首先将这张【Tile瓦片】拖入场景窗口中
由于这张图片的原始大小过大,我们可以手动的去调整图片的大小
至于这个瓦片大小,究竟要调整到什么样的程度,我建议确保四周的相邻瓦片他们之间的
相对距离为【一个单位】就可以了,并留一点点的间隙就好了
具体的原因会和之后的角色【移动范围】有关
在这里插入图片描述
为了达到这个效果,我们要先去设置Snap Setting,我们希望当我们按住【cmd/Ctrl】后,拖拽物体能够移动【一个单位】长度
2021之前Snap Setting是在Edit栏最下面,我在Unity2021菜单栏里找了半天没找到,最后发现在Scene窗口里
在这里插入图片描述
按下【Cmd/Ctrl+D克隆】当前瓦片游戏对象
然后,当我们要移动该对象时,(首先)按住【cmd/ctrl】按钮
然后拖拽,实现"Snap Moving”,即【一个单位】距离长度的移动
在这里插入图片描述
如果你觉得,相邻的两个瓦片之间的间隙,还是稍微有一点大的
我们还可以稍微放大一点,这张图片的大小

2. 放置全图瓦片

设置瓦片为预制体,如下图,配置好全图的瓦片地图
在这里插入图片描述

3. 美化瓦片地图

现在我们的(地图)图片,看上去还是有一点【枯燥】的,我们希望每次运行游戏后,地图上的【每一张瓦片】,他都能够随机生成不一样的瓦片图片,供我们欣赏

在Sprites文件夹中,将Tilesi这张图片设置为多图模式以后
在精灵编辑器中进行【自动的裁切】
在这里插入图片描述
在Scripts文件夹中,新建一个C#脚本:Tile

public class Tile : MonoBehaviour
{private SpriteRenderer spriteRenderer;//瓦片[SerializeField] private Sprite[] sprites;//瓦片集private void Start(){spriteRenderer = GetComponent<SpriteRenderer>();int randomNum = Random.Range(0, sprites.Length);//随机获取0-9下标spriteRenderer.sprite = sprites[randomNum];//赋值给瓦片}
}

挂载脚本和对象,运行游戏,现在每次开始游戏我们都会(随机)生成不一样的地图了
在这里插入图片描述

4. 添加树木障碍物

我们现在希望在图片上添加更多的树木,而有的树木他会作为实体,有的会作为【障碍物】的形式
障碍物在之后的角色移动当中起到【阻止角色移动】到这个瓦片上的功能

我们新建三个空物体树木,背景,障碍物,负责管理所有树木以及障碍物
将树木游戏对象作为它们的【父物体】来使用

我们先建立一些美观的树木
选择【多图模式】后进行裁剪
在这里插入图片描述

5. 设定不同的排序图层

由于之后还会创建人物,我们希望所有【有关背景的图片】,都会渲染在人物的后方
在这里插入图片描述
配置不同的排序层级
在这里插入图片描述
瓦片和树木排序图层我们都设置为background,因为树木肯定显示在瓦片前面,我们可以把图层排序设置为50,放置不同的树木,丰富一下场景,如下
在这里插入图片描述

6. 瓦片交互

为了能够更好的交互,我们希望当我们的鼠标【选择到】每一个瓦片时,瓦片能给我们一定的反馈,我们希望鼠标【进入瓦片】时,瓦片能放大,当我们【离开瓦片】时,瓦片能回到原来的大小

我们可以使用Unity内置的【OnMouseEnter】和【OnMouseExit】方法来实现
大家只要记住一点,实现这两个方法呢,是有一个前提的,那就是我们鼠标要检测的对象,也就是这里的瓦片,他必须添加【Collider2D】碰撞器组件

我们先给瓦片添加碰撞器,记得应用全部预制体
在这里插入图片描述
完善Tile脚本代码

private void OnMouseEnter()
{transform.localScale += Vector3.one * 0.05f;}private void OnMouseExit(){transform.localScale -= Vector3.one * 0.05f;}

效果
在这里插入图片描述

6. 瓦片交互优化

我们还可以去观察一个细节,现在部分放大的瓦片时,还是会被相邻的瓦片渲染在下方
为了能够保证当我们放大每一个瓦片时,这个瓦片都可以渲染在【最上方】,我们还可以调整它的渲染层顺序

瓦片位于Background层的0号位置(顺序)
而实体的树木呢,顺序是50号
我们只需要去保证放大的瓦片顺序
在其他瓦片之上,实体树木之下就可以了(即在0到50之间),我们这里设置为【25】

完善Tile脚本代码

private void OnMouseEnter()
{transform.localScale += Vector3.one * 0.05f;spriteRenderer.sortingOrder = 25;}private void OnMouseExit(){transform.localScale -= Vector3.one * 0.05f;spriteRenderer.sortingOrder = 0;}

最终效果
在这里插入图片描述

6. 瓦片是否允许角色

我们就要开始最重要的第一步判断了,这个瓦片是否允许角色去行走
如果这个瓦片上有【树木】,那我们的角色是不能够行走到这个瓦片上的
我们判断的依据是,如果瓦片上存在【树木】或者【人】,那么这个瓦片【不允许】再站人,玩家是不能够移动到这个瓦片上的

完善Tile脚本代码

public bool canWalk;//是否能走
public LayerMask obLayerMask;//检测层private void Start()
{CheckObstacle();
}private void CheckObstacle()
{//参数1:圆形检测的中心点位置,那也就是我们瓦片的中心点位置//参数2:范围,spriteRenderer.bounds.extents.x获取图片一半的长度//参数3:检测层Collider2D collider = Physics2D.OverlapCircle(transform.position, spriteRenderer.bounds.extents.x, obLayerMask);if (collider != null)//检测不为空,说明有障碍物在这个瓦片上呀canWalk = false;elsecanWalk = true;//这个瓦片,我们的角色是可以行走的
}

回到Unity当中,新建一个Layer层,命名为Obstacle,全选中所有【实体树木】游戏对象,设置为Obstacle层
在这里插入图片描述
回忆一下有关【Physics:2D.Raycast】或者【Physics:2D.OverlapCircle】的定义
他们的方法检测的都是添加了【Collider组件】的游戏对象

还有别忘记了,要给每个树木加碰撞体
在这里插入图片描述

7. 添加角色

添加角色,随便找个人物角色图片就可以了,也可以用我准备的
在这里插入图片描述
注意:角色裁剪时记得把锚点设置在人物脚的位置,这个很关键,开始我就是没注意,当设置人物位置时,会发生偏移
在这里插入图片描述
直接拖拽锚点肯定是不精准,每张图片不同位置锚点的偏差会使角色出现晃得的情况,所以最好是手动修改锚点的位置,我这里设置的是0.5x0.15
在这里插入图片描述

想默认把角色放在哪个瓦片上,就设置角色xy坐标为对应即可,切记不要拖拽,不然xy坐标会不准确,后面渲染行走路线会不准确
在这里插入图片描述
给角色添加对应动画和碰撞器,记得修改排序图层为Forground
在这里插入图片描述

8. 新增游戏管理脚本

我们希望的是当鼠标点击角色时,角色能够显示相应的可移动范围,有障碍物,则这个瓦片呢不可以移动

我们首先需要遍历所有的瓦片
然后去筛选出所有满足要求的瓦片
然后对这些瓦片呢进行高亮
然后就可以显示出:我们角色可以移动的这些瓦片了
由于需要遍历所有的瓦片
之后呢,我们也会去需要对所有的瓦片进行高亮和重置等操作
我们会反反复复的一遍一遍的去用到所有瓦片这一数组

我们新建一个C#脚本GameManager
来管理游戏中的一些核心的变量和一些常用的方法
tiles其实可以通过动态生成比较好,这里为了方便我就直接使用拖拽了

设置为单例

public class GameManager : MonoBehaviour
{public static GameManager instance;public Tile[] tiles;//在这个游戏中所有的贴图public Unit selectedUnit;//被选中的角色private void Awake(){if(instance == null){instance = this;}else{if(instance != this){Destroy(gameObject);}}DontDestroyOnLoad(gameObject);}
}

新建一个C#脚本Unit将Unit脚本,添加到角色游戏对象中
鼠标要点击的呢,是Unit对象(所以写在Unit脚本中)

我们鼠标是点击我们的角色
当我们鼠标进入角色Collider范围
并且按下鼠标左键时,则会调用这个方法(OnMouseDown】
所以方法内部呢
当我们点击这个角色后,显示可移动的瓦片

声明一个整数类型,int类型的变量moveRange
表示当前角色可移动的格子数
我们先设置为三
如果之后我们创建不同的角色
我们还可以去使用
【ScriptableObject】)或者【继承】
的方式来进行代码上的重构

我们还可以利用特性【Range】
将这个变量的可选择范围呢,控制在1~7这几个整数当中
在【ShowWalkableTiles】)方法中
我们要获取角色周围以自身为中心的一个菱形
菱形的大小呢,由角色的移动范围来决定
Unit代码
在这里插入图片描述

9. 角色移动范围逻辑

我们应该如何去获取,角色移动可行走的瓦片呢

我们可以先做一个这样的判断

如果我们的角色移动范围等于1
那么我们角色可以行走范围呢,应该是这个样子的
在这里插入图片描述
如果我们的角色移动范围等于2
那么我们可以行走的范围,可以到达额外的这八个点
在这里插入图片描述
我们将所有可移动的瓦片位置坐标,标示在了图片上
我们可以发现,我们可达到的瓦片的位置坐标呢X和Y值相加会小于等于角色的移动范围
在这里插入图片描述
我们可以分别去通过角色与每个瓦片之间的x轴的距离
角色与每个瓦片之间Y轴的距离,相加进行比较
如果X轴和Y轴的距离相加之后,小于等于角色的移动范围
那么这些瓦片呢,就是我们可以移动的范围了
其他的瓦片就是在我们角色移动范围之外的这些瓦片

10. 角色移动范围可视化

完善Unit代码

public class Unit : MonoBehaviour
{[SerializeField] [Range(1,7)]private int moveRange = 3;private void OnMouseDown(){ShowWalkableTiles();}private void ShowWalkableTiles(){for (int i = 0; i < GameManager.instance.tiles.Length; i++){float distX = Mathf.Abs(transform.position.x - GameManager.instance.tiles[i].transform.position.x);float distY = Mathf.Abs(transform.position.y - GameManager.instance.tiles[i].transform.position.y);if(distX + distY <= moveRange){//Tile is Walkable or not (without obstacle)if (GameManager.instance.tiles[i].canWalk)GameManager.instance.tiles[i].HighlightTile();}}}

Tile脚本定义可行走区域高亮显示方法

public void HighlightTile()
{if (canWalk){spriteRenderer.color = highlightColor;}else{spriteRenderer.color = Color.white;}}

挂载脚本,绑定参数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果发现一切设置都没错,但是点击没有效果,也没有调用OnMouseDown方法,可以将角色z轴适当调高,防止遮挡
在这里插入图片描述
效果,可以看到,被障碍物树木占据的瓦片禁止行走,是我们想要的效果
在这里插入图片描述

11. 角色移动

下一步就是:我们要让我们的角色能够真正的移动到我们想要移动到的点
当我们选中角色后,点击瓦片时,角色才能移动
意思就是说,我们移动的方法应该写在Tile瓦片脚本内部
我们可以在瓦片这个Tile脚本当中,使用OnMouseDown方法来执行角色的移动
我们的角色,会移动到我们点击的这个瓦片位置上

由于之后呢
我们可能会不止有一个角色
我们在GameManager脚本当中呢
声明一个Unit类型的变量selectedUnit
表示我们当前鼠标点击的这个角色

public Unit selectedUnit;//被选中的角色

在Unit脚本中,创建一个Move方法

由于角色的移动,是需要一个【过程】的,并且,我们希望角色的移动是根据瓦片的路线来进行移动的,而不是点对点的直接移动,这里我们就需要去使用协程函数,【协程函数】可以将一个函数分割成多个帧去执行(按一定顺序去执行),优先去进行【水平方向】的移动

在这里插入图片描述
在这里插入图片描述

[SerializeField] private float moveSpeed;//MARKER 这个方法会在【Tile脚本】中OnMouseDown函数中被【调用】
public void Move(Transform _trans)
{StartCoroutine(MoveCo(_trans));
}IEnumerator MoveCo(Transform _trans)
{//角色先水平方向移动while (transform.position.x != _trans.position.x){transform.position = Vector2.MoveTowards(transform.position, new Vector2(_trans.position.x, transform.position.y), moveSpeed * Time.deltaTime);yield return new WaitForSeconds(0);}//水平方向到达目的地X后,再垂直方向移动while (transform.position.y != _trans.position.y){transform.position = Vector2.MoveTowards(transform.position, new Vector2(transform.position.x, _trans.position.y), moveSpeed * Time.deltaTime);yield return null;}
}

12. 重置瓦片颜色

在角色完成移动后,我们当然希望将我们一开始【高亮】的瓦片,能够重置回原本的颜色,来保证之后的所有操作

我们可以在Tile脚本中,创建一个ResetTile方法
对【颜色属性】进行一次修改

public void ResetTile()
{spriteRenderer.color = Color.white;
}

在Unit脚本中创建一个ResetTiles方法
遍历所有瓦片,将他们重置回原本的颜色

private void ResetTiles()
{for (int i = 0; i < GameManager.instance.tiles.Length; i++){GameManager.instance.tiles[i].ResetTile();}
}

在角色完成移动后再调用这个方法

IEnumerator MoveCo(Transform _trans)
{//。。。ResetTiles();
}

在tile脚本中调用move方法

private void OnMouseDown()
{//Player Move to "this" TILE 当我们选择了角色,点击这块瓦片,那么角色就会移动到这个瓦片上!if (GameManager.instance.selectedUnit != null)GameManager.instance.selectedUnit.Move(this.transform);}

最后别忘了一点,我们还需要在这个角色的Unit脚本当中的OnMouseDown中指明
GameManager.instance.selectedUnit = this;

private void OnMouseDown()
{GameManager.instance.selectedUnit = this;//。。。
}

效果
在这里插入图片描述
ps:上图演示有个瓦片没有显示,是因为我下面的障碍物树木碰撞体设置过大,影响了上面的瓦片,我自己调整了,这里说明一下

12. 限制移动次数

最后还遗留了一个问题,我们的角色可以进行无限次数的移动

在Tile引入canMove参数,判断哪个瓦片人物是可移动的,以此来限制角色的移动次数

public bool canMove;public void HighlightTile()
{if (canWalk){canMove = true;spriteRenderer.color = highlightColor;}else{spriteRenderer.color = Color.white;}
}public void ResetTile()
{spriteRenderer.color = Color.white;//重置所有的canMove为falsecanMove = false;
}
private void OnMouseDown()
{//Player Move to "this" TILE 当我们选择了角色,点击这块瓦片,那么角色就会移动到这个瓦片上!if (canMove && GameManager.instance.selectedUnit != null)GameManager.instance.selectedUnit.Move(this.transform);
}

13. 最终效果

在这里插入图片描述

其他

其实后面还有很多开发的空间,比如增加不同的角色、敌人,完善角色移动和攻击动画等,这里我就不在赘述了,留给大家自由去扩展,结束

源码下载

https://gitcode.net/unity1/battleflag
在这里插入图片描述

参考

【视频】https://www.bilibili.com/video/BV1vQ4y1M7gy/

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言必会题目(2)

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; 今天继续分享C语言必会的题目&#xff0c;上一篇文章主要是一些选择题&#xff0c;而今天我们主要内容为编程题的推荐与讲解 准备好迎接下面的题了吗&#xff1f;开始发车了&#xff01;&#xff01;&#xff01; 输入…

Linux源码剖析匿名共享内存shmem原理

如下问题如果都清楚了就不用看本文了&#xff1a; 1. shmem ram文件系统的初始化流程是怎样的 2. shmem思想上想复用基于文件的操作流程&#xff0c;实现上shmem也引入了一个文件&#xff0c;那么类似文件open会生成struct file&#xff0c;shmem的struct file怎么生成的 3.…

Ansible Playbook快速部署一主多从MySQL集群

部署目标&#xff1a; 1、快速部署一套一主两从的mysql集群 2、部署过程中支持交互式定义安装目录及监听端口号 部署清单目录结构&#xff1a; rootmaster:/opt/mysql# tree . . ├── group_vars │ └── all.yml ├── hosts ├── mysql.yml └── roles└── mys…

【Spring Cloud +Vue+UniApp】智慧建筑工地平台源码

智慧工地源码 、智慧工地云平台源码、 智慧建筑源码支持私有化部署&#xff0c;提供SaaS硬件设备运维全套服务。 前言&#xff1a;互联网建筑工地&#xff0c;是将互联网的理念和技术引入建筑工地&#xff0c;从施工现场源头抓起&#xff0c;最大程度的收集人员、安全、环境、材…

C++的六大“天选之子“拷贝构造与与运算符重载

&#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶 &#x1f43b;推荐专栏2: &#x1f354;&#x1f35f;&#x1f32f;C语言进阶 &#x1f511;个人信条: &#x1f335;知行合一 &#x1f…

MySql(干货)

写这篇博客的目的不是为了将介绍原理&#xff0c;而是为了Sql中的代码操作属实太多了&#xff0c;在这里进行一个汇总&#xff0c;方便查阅&#xff01;&#xff01;&#xff01; Sql分类 分类全称说明 DDL Data Definintion Language数据定义语言&#xff0c;用来定义数据库对…

Docker知识(详细笔记)

概览图 文章目录 概览图docker 知识速查1. 初识 Docker1.1 概念1.2 特点1.3 架构1.4 应用场景1.5 安装 Docker1.6 配置 Docker 镜像 2. Docker 命令2.1 Docker 进程相关命令2.2 Docker 镜像相关命令2.3 Docker 容器相关命令 3. Docker 容器的数据卷3.1 数据卷概念及作用3.1.1 概…

jvm里的内存溢出

目录 堆溢出 虚拟机栈和本地方法栈溢出&#xff08;栈溢出很少出现&#xff09; 方法区和运行时常量池溢出 本机内存直接溢出&#xff08;实际中很少出现、了解即可&#xff09; 堆溢出 堆溢出&#xff1a;最常见的是大list&#xff0c;list里面有很多元素 堆溢出该怎么解决…

修改IDEA的idea.vmoptions参数导致IDEA无法打开(ReservedCodeCacheSize)

事发原因 Maven导依赖的时候OOM&#xff0c;因此怀疑是内存太小&#xff0c;尝试修改idea.vmoptions的参数&#xff0c;然后发现IDEA重启后打不开了&#xff0c;卸载重装后也无法打开。。。 实际上如果导包爆出OOM的话应该调整下图参数&#xff0c;不过这都是后话了 解决思路…

52.Linux学习day02 基础命令详解2

目录 Linux常见的基础命令 1.cp 2.mv 3.rm 4.find 5.grep 6.管道 | 7.wc 8.su 9.关机与重启 10.runleve Linux常见的基础命令 1.cp 用于复制文件或目录 使用 cp 命令的基本格式如下&#xff1a; cp [选项] 源文件 目标文件或目录选项&#xff1a;cp 命令支持一些选…

Spring5新功能

文章目录 前言一、整合日志功能二、Nullable注解三、函数式风格编程四、JUnit5单元测试框架总结 前言 整合日志、Nullable注解、函数式风格编程、整合JUnit5、Webflux 一、整合日志功能 Spring5移除了Log4jConfigListener&#xff0c;官方建议使用Log4j2. 依赖&#xff1a; &…

k8s 滚动更新控制(一)

在传统的应用升级时&#xff0c;通常采用的方式是先停止服务&#xff0c;然后升级部署&#xff0c;最后将新应用启动。这个过程面临一个问题&#xff0c;就是在某段时间内&#xff0c;服务是不可用的&#xff0c;对于用户来说是非常不友好的。而kubernetes滚动更新&#xff0c;…

研发工程师玩转Kubernetes——PVC使用Label和storage选择PV

在《研发工程师玩转Kubernetes——local型PV和PVC绑定过程中的状态变化》和《研发工程师玩转Kubernetes——使用local型PV在不同Pod上共享数据》中&#xff0c;我们介绍了指定VPC的spec.volumeName为PV名称来绑定它们的方法。本文将介绍PVC在创建时&#xff0c;系统自动选择绑定…

什么是DNS欺骗及如何进行DNS欺骗

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、什么是 DNS 欺骗&#xff1f;二、开始1.配置2.Ettercap启动3.操作 总结 前言 我已经离开了一段时间&#xff0c;我现在回来了&#xff0c;我终于在做一个教…

[vscode]vscode运行cmake时候exe不执行而且前面多一些字符

遇到一个奇怪问题,你单独打开cmd去执行vscode编译过程序没问题&#xff0c;但是你在vscode确不会执行&#xff0c;这是因为vscode没有读取到电脑环境变量导致加载DLL失败&#xff0c;但是在vscode终端不会给你提示少DLL&#xff0c;需要你自己把DLL复制到exe目录即可解决问题。…

Vue.js 生命周期详解

Vue.js 是一款流行的 JavaScript 框架&#xff0c;它采用了组件化的开发方式&#xff0c;使得前端开发更加简单和高效。在 Vue.js 的开发过程中&#xff0c;了解和理解 Vue 的生命周期非常重要。本文将详细介绍 Vue 生命周期的四个阶段&#xff1a;创建、挂载、更新和销毁。 …

计算机视觉的应用9-视觉领域中的61个经典数据集【大集合】的应用与实战

大家好,我是微学AI,今天给大家介绍一下计算机视觉的应用9-视觉领域中的61个经典数据集【大集合】的应用与实战,我们都知道计算机视觉是一门研究如何使计算机能够理解和解释数字图像或视频的技术和方法。在计算机视觉领域中,数据集是非常重要的资源,它们可以用于训练和评估…

从源码Debug深入spring事件机制,基于观察者模式仿写spring事件监听骨架

文章目录 1.测试案例2.DEBUG源码分析3. 异步监听4.ApplicationListener子接口5. 注解支持6. 基于观察者模式高仿spring事件监听6.1 先定义自定义一个事件6.2 定义两个监听器6.3 定义一个持有所有监听器的对象&#xff0c;类似spring的SimpleApplicationEventMulticaster6.4 事件…

什么是响应式设计?列举几种实现响应式设计的方法。

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是响应式设计&#xff1f;⭐ 实现响应式设计的方法⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏…

Python实现图片文本支持中文,自定义字体

Python实现图片文本支持中文&#xff0c;自定义字体 # 支持中文 import matplotlib #用下载好的字体文件设置字体&#xff0c;从而正确显示中文 myfont matplotlib.font_manager.FontProperties(fnamer"./simsun.ttc") # 自定义的字体文件 plt.figure(figsize (1…