【用unity实现100个游戏之12】unity制作一个俯视角2DRPG《类星露谷物语》资源收集游戏demo

文章目录

  • 前言
  • 加快编辑器运行速度
  • 素材
    • (1)场景人物
    • (2)工具
  • 一、人物移动和动画切换
  • 二、走路灰尘粒子效果
    • 探究
    • 实现
  • 三、树木排序设计
    • 方法一
    • 方法二
  • 四、绘制拿工具的角色动画
  • 五、砍树实现
  • 六、存储拾取物品
    • 引入Unity 的可序列化字典类
  • 七、实现靠近收获物品自动吸附
  • 八、树木被砍掉的粒子效果
  • 九、新增更多可收集物
  • 十、更多工具切换
  • 十一、扩展
  • 源码
  • 完结

前言

采集收集生存类游戏一直是我的最爱,今天就来用unity制作一个俯视角2DRPG类星露谷物语资源收集游戏

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

加快编辑器运行速度

修改项目配置
在这里插入图片描述
这样,运行时我们就不需要再等待很久了

素材

(1)场景人物

https://cypor.itch.io/12x12-rpg-tileset
在这里插入图片描述

(2)工具

https://dantepixels.itch.io/tools-asset-16x16
在这里插入图片描述

一、人物移动和动画切换

这个直接功能实现我之前炸弹人那期文章已经说过了,直接抄答案就行了,这里就不再重复介绍了,具体实现可以看文章:
【用unity实现100个游戏之8】用Unity制作一个炸弹人游戏
在这里插入图片描述

最终效果(这里用TileMap简单绘制了一下地图,TileMap的使用可以看我主页之前的文章)
在这里插入图片描述

在这里插入图片描述

二、走路灰尘粒子效果

探究

要实现走路灰尘效果,Unity的粒子系统(Particle System)中有属性RateOverDistance:根据移动距离发射粒子,不移动时不发射。恰好可满足当前需求

实际使用时发现,不管怎么移动都不发射粒子,但RateOverTime(随时间推移发射粒子)的功能是正常的

解决方案
粒子系统有一属性:EmitterVelocity(发射器速度模式),它有2种模式

Transform:通过Transform中Position的变化计算粒子系统的移动速度
Rigidbody:将刚体(若有)的速度作为粒子系统的移动速度

看了上述解释即可想到,若EmitterVelocity设置为Rigidbody模式,当该粒子系统没有刚体时,系统会认为该发射器是不动的,因此移动速度为0,因此移动距离为0:因此RateOverDistance不会发射粒子

所以将EmitterVelocity(发射器速度模式)设置为Transform(变换)即可

实现

素材图片
在这里插入图片描述
材质
在这里插入图片描述

完整粒子系统配置
在这里插入图片描述

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

三、树木排序设计

我们希望实现人物走到树前,人物遮挡树木,当人物走到树后,树又遮挡玩家

如果我们直接修改图层排序方式肯定是不行的,玩家要么直接被遮挡,要么直接遮挡树木

当然你可以通过代码的方式,动态的修改人物图层排序值,当时太麻烦了,这里我们就不探讨了

方法一

最简单的方法就是将树叶和树根分开,树叶图层排序比人物高,树根图层排序比人物低,当然这样绘制会比较麻烦一些
在这里插入图片描述
效果
在这里插入图片描述

方法二

使用透视排序。也就是“伪造”透视图。根据直觉,玩家希望角色在立方体前面时首先绘制角色,而角色在立方体后面时最后绘制角色。

如果用更技术性的语言来说,你需要做的是指示 Unity 根据游戏对象的 y 坐标来绘制游戏对象。屏幕上位置较低的游戏对象(y 坐标较小)应在屏幕上位置较高的游戏对象(y 坐标较大)之后绘制。这样将使位置较低的对象显示在上层。

要指示 Unity 根据游戏对象的 y 坐标来绘制游戏对象,请执行以下操作

  • 选择 Edit > Project Settings。

  • 在左侧类别菜单中,单击 Graphics

  • 在 Camera Settings 中,找到 Transparency Sort Mode (透明度排序模式)字段。此字段决定了精灵的绘制顺序。使用下拉菜单将此设置从 Default 更改为 Custom Axis(自定义轴),修改Transparency Sort Axis(透明排序轴)为(0,1,0),告诉Unity y轴绘制精灵

在这里插入图片描述

  • 找到树木的 Sprite Sort Point (Sprite 排序点)字段。目前,此字段设置为 Center,这意味着会使用精灵的中心点来决定这个游戏对象应该在另一个游戏对象的前面还是后面。将 Sprite Sort Point (Sprite 排序点)更改为 Pivot(轴心)
    注意:记得树木图层排序顺序要和主角人物设置为一样
    在这里插入图片描述
  • 修改树木图片的轴心位置到树木根部
    在这里插入图片描述
    这样就实现了人物在树木轴心下面,先绘制树木,人物在轴心以上,先绘制角色
    在这里插入图片描述

四、绘制拿工具的角色动画

记得配置好动画后,修改为横定曲线,让动画过渡更加丝滑
在这里插入图片描述
效果
在这里插入图片描述
其他配置同理,并加入攻击动画和代码控制切换

if(Input.GetKeyDown(KeyCode.F)){animator.SetBool("isAttack", true);
}
if(Input.GetKeyUp(KeyCode.F)){animator.SetBool("isAttack", false);
}

动画控制器
在这里插入图片描述

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

五、砍树实现

给树木添加代码,我已经加了详细注释就不过多解释了,其中使用了DOTween实现生成资源的弹出动画,不懂DOTween的小伙伴可以看我之前的文章

using UnityEngine;
using DG.Tweening;public class TreeController : MonoBehaviour
{public GameObject woodPrefab;   // 木头预制体public int minWoodCount = 2;    // 随机掉落的最小木头数量public int maxWoodCount = 3;    // 随机掉落的最大木头数量public int maxAttackCount = 3;  // 最大攻击次数public int maxCreateCount = 3;  // 最大生成物品次数public float maxOffsetDistance = 1f;  // 随机偏移的最大距离private int currentCreateCount; // 生成物品次数private int currentAttackCount; // 当前攻击次数void Start(){currentAttackCount = 0;currentCreateCount = 0;}private void OnTriggerEnter2D(Collider2D other) {//碰到带Axe标签物体if(other.CompareTag("Axe")){//攻击三次生成物品if(currentAttackCount >= maxAttackCount){TakeDamage();currentAttackCount = 0;}currentAttackCount ++;}}public void TakeDamage(){// 每次受到攻击时,生成随机数量的木头int woodCount = Random.Range(minWoodCount, maxWoodCount + 1);for (int i = 0; i < woodCount; i++){Vector3 randomOffset = new Vector3(Random.Range(-maxOffsetDistance, maxOffsetDistance), Random.Range(-maxOffsetDistance, maxOffsetDistance), 0f);GameObject wood = Instantiate(woodPrefab, transform.position + randomOffset, Quaternion.identity);// 使用DOJump方法实现物体的弹跳wood.transform.DOJump(wood.transform.position + new Vector3(randomOffset.x, randomOffset.y, 0f), 2, 1, 1).SetEase(Ease.OutSine);}currentCreateCount++;// 如果生成物品次数达到最大值,则销毁木头并重置生成物品次数if (currentCreateCount >= maxCreateCount){Destroy(gameObject);currentCreateCount = 0;}}
}

效果
在这里插入图片描述

六、存储拾取物品

使用ScriptableObject定义物品

using UnityEngine;[CreateAssetMenu(fileName = "Resource", menuName = "GathererTopDownRPG/Resource")]
public class Resource : ScriptableObject
{[field: SerializeField] public string DisplayName { get; private set; }[field: SerializeField] public Sprite Icon { get; private set; }[field: SerializeField] public string Description { get; private set; }[field: SerializeField] public float Value { get; private set; }
}

新建ScriptableObject物品,配置参数
在这里插入图片描述
物品脚本

using UnityEngine;public class ResourcePickup : MonoBehaviour
{[field: SerializeField] public Resource ResourceType { get; private set; }
}

木头挂载脚本,并配置对应的ScriptableObject
在这里插入图片描述

引入Unity 的可序列化字典类

Unity 无法序列化标准词典。这意味着它们不会在检查器中显示或编辑,
也不会在启动时实例化。一个经典的解决方法是将键和值存储在单独的数组中,并在启动时构造字典。

我们使用gitthub大佬的源码即可,此项目提供了一个通用字典类及其自定义属性抽屉来解决此问题。
源码地址:https://github.com/azixMcAze/Unity-SerializableDictionary

你可以选择下载源码,也可以直接复制我下面的代码,我把主要代码提出来了
SerializableDictionary.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using UnityEngine;public abstract class SerializableDictionaryBase
{public abstract class Storage {}protected class Dictionary<TKey, TValue> : System.Collections.Generic.Dictionary<TKey, TValue>{public Dictionary() {}public Dictionary(IDictionary<TKey, TValue> dict) : base(dict) {}public Dictionary(SerializationInfo info, StreamingContext context) : base(info, context) {}}
}[Serializable]
public abstract class SerializableDictionaryBase<TKey, TValue, TValueStorage> : SerializableDictionaryBase, IDictionary<TKey, TValue>, IDictionary, ISerializationCallbackReceiver, IDeserializationCallback, ISerializable
{Dictionary<TKey, TValue> m_dict;[SerializeField]TKey[] m_keys;[SerializeField]TValueStorage[] m_values;public SerializableDictionaryBase(){m_dict = new Dictionary<TKey, TValue>();}public SerializableDictionaryBase(IDictionary<TKey, TValue> dict){	m_dict = new Dictionary<TKey, TValue>(dict);}protected abstract void SetValue(TValueStorage[] storage, int i, TValue value);protected abstract TValue GetValue(TValueStorage[] storage, int i);public void CopyFrom(IDictionary<TKey, TValue> dict){m_dict.Clear();foreach (var kvp in dict){m_dict[kvp.Key] = kvp.Value;}}public void OnAfterDeserialize(){if(m_keys != null && m_values != null && m_keys.Length == m_values.Length){m_dict.Clear();int n = m_keys.Length;for(int i = 0; i < n; ++i){m_dict[m_keys[i]] = GetValue(m_values, i);}m_keys = null;m_values = null;}}public void OnBeforeSerialize(){int n = m_dict.Count;m_keys = new TKey[n];m_values = new TValueStorage[n];int i = 0;foreach(var kvp in m_dict){m_keys[i] = kvp.Key;SetValue(m_values, i, kvp.Value);++i;}}#region IDictionary<TKey, TValue>public ICollection<TKey> Keys {	get { return ((IDictionary<TKey, TValue>)m_dict).Keys; } }public ICollection<TValue> Values { get { return ((IDictionary<TKey, TValue>)m_dict).Values; } }public int Count { get { return ((IDictionary<TKey, TValue>)m_dict).Count; } }public bool IsReadOnly { get { return ((IDictionary<TKey, TValue>)m_dict).IsReadOnly; } }public TValue this[TKey key]{get { return ((IDictionary<TKey, TValue>)m_dict)[key]; }set { ((IDictionary<TKey, TValue>)m_dict)[key] = value; }}public void Add(TKey key, TValue value){((IDictionary<TKey, TValue>)m_dict).Add(key, value);}public bool ContainsKey(TKey key){return ((IDictionary<TKey, TValue>)m_dict).ContainsKey(key);}public bool Remove(TKey key){return ((IDictionary<TKey, TValue>)m_dict).Remove(key);}public bool TryGetValue(TKey key, out TValue value){return ((IDictionary<TKey, TValue>)m_dict).TryGetValue(key, out value);}public void Add(KeyValuePair<TKey, TValue> item){((IDictionary<TKey, TValue>)m_dict).Add(item);}public void Clear(){((IDictionary<TKey, TValue>)m_dict).Clear();}public bool Contains(KeyValuePair<TKey, TValue> item){return ((IDictionary<TKey, TValue>)m_dict).Contains(item);}public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex){((IDictionary<TKey, TValue>)m_dict).CopyTo(array, arrayIndex);}public bool Remove(KeyValuePair<TKey, TValue> item){return ((IDictionary<TKey, TValue>)m_dict).Remove(item);}public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator(){return ((IDictionary<TKey, TValue>)m_dict).GetEnumerator();}IEnumerator IEnumerable.GetEnumerator(){return ((IDictionary<TKey, TValue>)m_dict).GetEnumerator();}#endregion#region IDictionarypublic bool IsFixedSize { get { return ((IDictionary)m_dict).IsFixedSize; } }ICollection IDictionary.Keys { get { return ((IDictionary)m_dict).Keys; } }ICollection IDictionary.Values { get { return ((IDictionary)m_dict).Values; } }public bool IsSynchronized { get { return ((IDictionary)m_dict).IsSynchronized; } }public object SyncRoot { get { return ((IDictionary)m_dict).SyncRoot; } }public object this[object key]{get { return ((IDictionary)m_dict)[key]; }set { ((IDictionary)m_dict)[key] = value; }}public void Add(object key, object value){((IDictionary)m_dict).Add(key, value);}public bool Contains(object key){return ((IDictionary)m_dict).Contains(key);}IDictionaryEnumerator IDictionary.GetEnumerator(){return ((IDictionary)m_dict).GetEnumerator();}public void Remove(object key){((IDictionary)m_dict).Remove(key);}public void CopyTo(Array array, int index){((IDictionary)m_dict).CopyTo(array, index);}#endregion#region IDeserializationCallbackpublic void OnDeserialization(object sender){((IDeserializationCallback)m_dict).OnDeserialization(sender);}#endregion#region ISerializableprotected SerializableDictionaryBase(SerializationInfo info, StreamingContext context) {m_dict = new Dictionary<TKey, TValue>(info, context);}public void GetObjectData(SerializationInfo info, StreamingContext context){((ISerializable)m_dict).GetObjectData(info, context);}#endregion
}public static class SerializableDictionary
{public class Storage<T> : SerializableDictionaryBase.Storage{public T data;}
}[Serializable]
public class SerializableDictionary<TKey, TValue> : SerializableDictionaryBase<TKey, TValue, TValue>
{public SerializableDictionary() {}public SerializableDictionary(IDictionary<TKey, TValue> dict) : base(dict) {}protected SerializableDictionary(SerializationInfo info, StreamingContext context) : base(info, context) {}protected override TValue GetValue(TValue[] storage, int i){return storage[i];}protected override void SetValue(TValue[] storage, int i, TValue value){storage[i] = value;}
}[Serializable]
public class SerializableDictionary<TKey, TValue, TValueStorage> : SerializableDictionaryBase<TKey, TValue, TValueStorage> where TValueStorage : SerializableDictionary.Storage<TValue>, new()
{public SerializableDictionary() {}public SerializableDictionary(IDictionary<TKey, TValue> dict) : base(dict) {}protected SerializableDictionary(SerializationInfo info, StreamingContext context) : base(info, context) {}protected override TValue GetValue(TValueStorage[] storage, int i){return storage[i].data;}protected override void SetValue(TValueStorage[] storage, int i, TValue value){storage[i] = new TValueStorage();storage[i].data = value;}
}

库存基类

TryGetValue 方法会尝试从字典中获取指定键 type 对应的值。如果找到了该键,它会将对应的值赋值给 currentCount 变量,并返回 true。

using UnityEngine;public class Inventory : MonoBehaviour
{[field: SerializeField] private SerializableDictionary <Resource, int> Resources { get; set;}//<summary>// 查找并返回字典中某个资源的数量///</summary>//<param name="type">要检查的资源类型</param>//<returns>如果有资源则返回其数量,否则返回0</returns>public int GetResourceCount(Resource type){if (Resources.TryGetValue(type, out int currentCount))return currentCount;elsereturn 0;}/// <summary>/// 向字典中添加资源/// </summary>/// <param name="type">要添加的资源类型</param>/// <param name="count">要添加的数量</param>/// <returns>成功添加的数量</returns>public int AddResources(Resource type, int count){if (Resources.TryGetValue(type, out int currentCount)){return Resources[type] += count;}else{Resources.Add(type, count);return count;}}
}

拾取物品
在这里插入图片描述
拾取物品代码,挂载在人物身上

using UnityEngine;public class PickupResources : MonoBehaviour
{[field: SerializeField] public Inventory Inventory { get; private set; }private void OnTriggerEnter2D(Collider2D collision){ResourcePickup pickup = collision.gameObject.GetComponent<ResourcePickup>();if (pickup){Inventory.AddResources(pickup.ResourceType, 1);Destroy(pickup.gameObject);}}
}

在这里插入图片描述
运行效果
在这里插入图片描述

检测是否入库,数量是否增加
在这里插入图片描述

七、实现靠近收获物品自动吸附

新增两个节点,一个为吸附范围,一个为拾取物品范围,同时去除原本角色的PickupResources脚本挂载
在这里插入图片描述
在这里插入图片描述

编写吸附脚本PickupGravity

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PickupGravity : MonoBehaviour
{public float GravitySpeed = 5f;private List<ResourcePickup> _nearbyResources = new();private void FixedUpdate(){foreach (ResourcePickup pickup in _nearbyResources){Vector2 directionToCenter = (transform.position - pickup.transform.position).normalized;pickup.transform.Translate(directionToCenter * GravitySpeed * Time.fixedDeltaTime);}}private void OnTriggerEnter2D(Collider2D collision){ResourcePickup pickup = collision.gameObject.GetComponent<ResourcePickup>();if (pickup) _nearbyResources.Add(pickup);}private void OnTriggerExit2D(Collider2D collision){ResourcePickup pickup = collision.gameObject.GetComponent<ResourcePickup>();if (pickup) _nearbyResources.Remove(pickup);}
}

也可以使用DOtween实现,会更加简单

using UnityEngine;
using DG.Tweening;
public class PickupGravity : MonoBehaviour
{public float speed = 0.6f;private void OnTriggerEnter2D(Collider2D collision){ResourcePickup pickup = collision.gameObject.GetComponent<ResourcePickup>();if (pickup){pickup.transform.DOMove(transform.position, speed);}}
}

挂载脚本
在这里插入图片描述
在这里插入图片描述
运行效果
在这里插入图片描述

八、树木被砍掉的粒子效果

粒子效果配置,材质和颜色选择自己想要的就行
在这里插入图片描述

在这里插入图片描述
代码调用

public GameObject cutDownParticleSystem;//粒子效果//生成特效
Instantiate(cutDownParticleSystem, transform.position, Quaternion.identity);

效果
在这里插入图片描述

九、新增更多可收集物

直接按前面的树木生成预制体变体
在这里插入图片描述
修改相应的配置即可,最终效果
在这里插入图片描述

十、更多工具切换

新增ScriptableObject Tool类,定义不同类型的工具

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;[CreateAssetMenu(fileName = "Tool", menuName = "GathererTopDownRPG/Tool")]
public class Tool : ScriptableObject
{[field: SerializeField] public string DisplayName { get; private set; }[field: SerializeField] public Sprite sprite { get; private set; }[field: SerializeField] public Sprite Icon { get; private set; }[field: SerializeField] public string Description { get; private set; }[field: SerializeField] public ToolType toolType { get; private set; }[field: SerializeField] public int minCount { get; private set; } = 1;//随机掉落的最小资源数量[field: SerializeField] public int maxCount { get; private set; } = 1;//随机掉落的最大资源数量
}// 在此添加其他工具类型
public enum ToolType
{Axe,//斧头Pickaxe,//镐子
}

在这里插入图片描述
新增工具代码,挂载在工具节点上

public class ToolController : MonoBehaviour
{public Tool tool;
}

修改可破坏物(树,石头)的代码,及TreeController脚本

public ToolType toolType;private void OnTriggerEnter2D(Collider2D other)
{//碰到带Axe标签物体if (other.CompareTag("Axe")){//只有对应的工具才可以if (other.GetComponent<ToolController>().tool.toolType == toolType){//。。。TakeDamage(other.GetComponent<ToolController>().tool);//。。。}else{Debug.Log("工具不对");}}
}public void TakeDamage(Tool tool)
{int minWoodCount = tool.minCount;    // 随机掉落的最小木头数量int maxWoodCount = tool.maxCount;    // 随机掉落的最大木头数量
}

ps:我这里只配置了不同武器的 随机掉落的数量,你可以将其他数据也进行不同的工具配置,如最大攻击次数,最大生成物品次数

页面绘制不同武器的切换按钮
在这里插入图片描述
切换工具按钮脚本,脚本挂载各个按钮上即可

using UnityEngine;
using UnityEngine.UI;//切换工具
public class SwitchTool : MonoBehaviour
{public Tool tool;private ToolController toolController;private void Start(){toolController = FindObjectOfType<PlayerController>().GetComponentInChildren<ToolController>();//修改当前按钮icon图片GetComponent<Image>().sprite = tool.Icon;//绑定点击事件GetComponent<Button>().onClick.AddListener(ChangeTool);}//切换工具public void ChangeTool(){if (toolController != null){if(toolController.GetComponent<SpriteRenderer>().sprite != tool.sprite){toolController.tool = tool;//修改工具角色手拿工具图片toolController.GetComponent<SpriteRenderer>().sprite = tool.sprite;}else{toolController.tool = null;toolController.GetComponent<SpriteRenderer>().sprite = null;}}else{Debug.LogWarning("没找到目标ToolController组件");}}
}

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

十一、扩展

音乐音效系统
背包系统
经验血量系统
制作系统,不同等级可以解锁不同品质的工具
种植系统
建造系统
钓鱼、烹饪系统
天气、四季变化系统
任务系统
打怪系统
种子、商城系统

后续大家可以自行扩展,这里就不过多赘述了。至于后续是否继续完善开发,就看大家想不想看了,点赞越多更新越快哦!

源码

整理好后我会放上来

完结

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

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

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

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

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

相关文章

【详细教程hexo博客搭建】1、从零开始搭建一个能用的博客

1、开始 2.环境与工具准备 本教程主要面对的是Windows用户 操作系统&#xff1a;Windows10NodeGitHexo文本编辑器(强烈推荐VSCODE)GitHub 帐号一个域名&#xff08;强烈推荐买个域名&#xff09;云服务器&#xff08;可选&#xff09; 3.Node的安装 打开Node官网&#xff0…

Error: error:0308010C:digital envelope routines::unsupported

文章目录 1, 问题背景2.解决方法13.解决方法2将 React 脚本升级到 5 以上版本 3.参考资料 1, 问题背景 最近在升级我之前的一个网站的过程中&#xff0c;由于使用了高版本的nodejs v18.0.0报错如下 (undefined) assets/js/styles.1dbb3634.js from Terser Error: error:03080…

LeetCode: 4. Median of Two Sorted Arrays

LeetCode - The Worlds Leading Online Programming Learning Platform 题目大意 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。 请你找出这两个有序数组的中位数&#xff0c;并且要求算法的时间复杂度为 O(log(m n))。 你可以假设 nums1 和 nums2 不会同时为空。 …

爆破shadow文件密码脚本(完成版)

在之前的博客Python爆破shadow文件密码脚本&#xff08;简化版&#xff09;中我们做了简化版的爆破shadow文件密码的python脚本&#xff0c;接下来在之前代码的基础上改进&#xff1a; import crypt shadow_line"root:$y$j9T$uEgezfJhn7Ov5naU8bzZt.$9qIqkWYObaXajS5iLDA…

Java 时间范围

前端使用Element-ui 时间范围组件 后端注意在Vo里面时间设置String类型不要设置Date类型 XMl组件字段映射成功性

Linux知识点 -- 网络基础(二)-- 应用层

Linux知识点 – 网络基础&#xff08;二&#xff09;-- 应用层 文章目录 Linux知识点 -- 网络基础&#xff08;二&#xff09;-- 应用层一、使用协议来实现一个网络版的计算器1.自定义协议2.守护进程3.使用json来完成序列化 二、HTTP协议1.概念2.HTTP协议请求和响应的报文格式3…

2023/9/18 -- C++/QT

作业 完善登录框 点击登录按钮后&#xff0c;判断账号&#xff08;admin&#xff09;和密码&#xff08;123456&#xff09;是否一致&#xff0c;如果匹配失败&#xff0c;则弹出错误对话框&#xff0c;文本内容“账号密码不匹配&#xff0c;是否重新登录”&#xff0c;给定两…

WebGL 视图矩阵、模型视图矩阵

目录 立方体由三角形构成 视点和视线 视点、观察目标点和上方向 视点&#xff1a; 观察目标点&#xff1a; 上方向&#xff1a; 在WebGL中&#xff0c;观察者的默认状态应该是这样的&#xff1a; 视图矩阵程序&#xff08;LookAtTriangles.js&#xff09; 实际上&…

仅做笔记用:Stable Diffusion 通过 ControlNet 扩展图片 / 扩图

发觉之前的 Outpainting 脚本效果仍旧不是很理想。这里又找了一下有没有效果更好的途径来扩图。于是就找到了通过 ControlNet 的方式来实现效果更好的扩图。这里临时记录一下在 Stable Diffusion 怎么使用 ControlNet 来扩展图片。 下载 control_v11p_sd15_inpaint_fp16.safet…

多线程详解(上)

文章目录 一、线程的概念1&#xff09;线程是什么2&#xff09;为甚要有线程&#xff08;1&#xff09;“并发编程”成为“刚需”&#xff08;2&#xff09;在并发编程中, 线程比进程更轻量. 3&#xff09;线程和进程的区别 二、Thread的使用1&#xff09;线程的创建继承Thread…

自定义类型:结构体

自定义类型&#xff1a;结构体 一&#xff1a;引入二&#xff1a;结构体类型的声明1&#xff1a;正常声明2&#xff1a;特殊声明 三&#xff1a;结构体变量的创建和初始化1:结构体变量的创建2&#xff1a;结构体变量的初始化 三&#xff1a;结构体访问操作符四&#xff1a;结构…

【C语言】每日一题(半月斩)——day3

目录 一&#xff0c;选择题 1.已知函数的原型是&#xff1a; int fun(char b[10], int *a); 2、请问下列表达式哪些会被编译器禁止【多选】&#xff08; &#xff09; 3、以下程序的输出结果为&#xff08; &#xff09; 4、下面代码段的输出是&#xff08; &#xff09;…

大数据学习1.1-Centos8虚拟机安装

1.创建新的虚拟机 2.选择稍后安装OS 3.选择Linux的CentOS8 4.选择安装路径 5.分配20g存储空间 6.自定义硬件 7.分配2g内存 8.分配2核处理器 9.选择镜像位置 10.开启虚拟机安装 推荐密码设置为root

61、SpringBoot -----跨域资源的设置----局部设置和全局设置

★ 跨域资源共享的意义 ▲ 在前后端分离的开发架构中&#xff0c;前端应用和后端应用往往是彻底隔离的&#xff0c;二者不在同一个应用服务器内、甚至不再同一台物理节点上。 因此前端应用和后端应用就不在同一个域里。▲ 在这种架构下&#xff0c;前端应用可能采用前端框架&a…

序列化和反序列化:将数据变得更加通用化

序列化与反序列化简介 序列化和反序列化是计算机领域中常用的概念&#xff0c;用于将对象或数据结构转换为字节序列&#xff08;序列化&#xff09;和将字节序列转换回对象或数据结构&#xff08;反序列化&#xff09;。 序列化是指将对象或数据结构转换为字节序列的过程。通…

前端VUE---JS实现数据的模糊搜索

实现背景 因为后端实现人员列表返回&#xff0c;每次返回的数据量在100以内&#xff0c;要求前端自己进行模糊搜索 页面实现 因为是实时更新数据的&#xff0c;就不需要搜索和重置按钮了 代码 HTML <el-dialogtitle"团队人员详情":visible.sync"centerDi…

uni-app跳转到另一个app

第一步&#xff1a; 首先要知道 app的包名 获取方式如下 第二步&#xff1a; 在第一个 demo1 app 一个页面中需要一个按钮去跳转 方法如下 <template><view class"content"><button click"tz">跳转</button></view> </…

如何在微软Edge浏览器上一键观看高清视频?

编者按&#xff1a;视频是当下最流行的媒体形式之一。但由于视频压缩、网络不稳定等原因&#xff0c;我们常常可以看到互联网上的很多视频其画面质量并不理想&#xff0c;尤其是在浏览器端&#xff0c;这极大地影响了观看体验。不过&#xff0c;近期微软 Edge 浏览器推出了一项…

FPGA纯verilog实现8路视频拼接显示,提供工程源码和技术支持

目录 1、前言版本更新说明免责声明 2、我已有的FPGA视频拼接叠加融合方案3、设计思路框架视频源选择OV5640摄像头配置及采集静态彩条视频拼接算法图像缓存视频输出 4、vivado工程详解5、工程移植说明vivado版本不一致处理FPGA型号不一致处理其他注意事项 6、上板调试验证并演示…

Jmeter接口测试简易步骤

使用Jmeter接口测试 1、首先右键添加一个线程组&#xff0c;然后我们重命名接口测试 2、在线程组上添加一个Http默认请求&#xff0c;并配置服务器的IP地址端口等信息 3、在线程组中添加一个HTTP请求&#xff0c;这里我们重命名“增加信用卡账户信息接口” 4、配置接口请求信息…