用QFramework来重构 祖玛游戏

资料

Unity - 祖玛游戏
GitHub

说明

用QF一个场景就够了,在UIRoot下切换预制体达到面板切换。
但测试中当然要有一个直接跳到测试面板的 测试脚本,保留测试Scene(不然初学者也不知道怎么恢复测试Scene),所以全文按Scene划分
在这里插入图片描述
在这里插入图片描述

----------------------------------------------------

01 Scene 开始进入(面板脚本,主要是 动(功能)静(UI引用)分离)

01 先创建一个UIRoot(QF里面有的)

在这里插入图片描述

02 做好UI,给需要引用的UI加 Bind脚本(默认设置看图)

在这里插入图片描述

03 拖出来做预制体,并且 CreateUICode,会生成两个脚本(自动生成位置是上一级目录的Scripts/UI),一个管UI引用(xxx.Designer),一个管功能(xxx),管功能的会自动加到预制体上

在这里插入图片描述

在这里插入图片描述

xxxPanelData 、xxxPanel(不叫Panel,叫xxxWindow,xxxUI随便)

using UnityEngine;
using UnityEngine.UI;
using QFramework;
using UnityEngine.SceneManagement;namespace QFramework.Example
{public class StartGamePanelData : UIPanelData{}public partial class StartGamePanel : UIPanel{protected override void OnInit(IUIData uiData = null){mData = uiData as StartGamePanelData ?? new StartGamePanelData();// please add init code hereScreen.SetResolution(640, 1136, false);//宽,高,不可修改BtnStart.onClick.AddListener(() => {Debug.Log("StartGamePanel");SceneManager.LoadScene("01 SelectLevel");});}protected override void OnOpen(IUIData uiData = null){}protected override void OnShow(){}protected override void OnHide(){}protected override void OnClose(){}}
}

xxxPanel.Designer

using System;
using UnityEngine;
using UnityEngine.UI;
using QFramework;namespace QFramework.Example
{// Generate Id:29cfe4a1-ad1e-4350-a490-3bdf8cf34278public partial class StartGamePanel{public const string Name = "StartGamePanel";[SerializeField]public UnityEngine.UI.Button BtnStart;private StartGamePanelData mPrivateData = null;protected override void ClearUIComponents(){BtnStart = null;mData = null;}public StartGamePanelData Data{get{return mData;}}StartGamePanelData mData{get{return mPrivateData ?? (mPrivateData = new StartGamePanelData());}set{mUIData = value;mPrivateData = value;}}}
}

04 调用,RrsKit.Init();必须调用

/****************************************************文件:GameStart.cs作者:lenovo邮箱: 日期:2023/7/2 22:59:41功能:
*****************************************************/using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;namespace QFramework.Example
{public class GameStart : MonoBehaviour{#region 生命/// <summary>首次载入</summary>void Awake(){ResKit.Init();UIKit.OpenPanel<StartGamePanel>();GameObject.DontDestroyOnLoad(gameObject);}#endregion }}

06 写包名,标记(ResKit才有它在打包的列表中),做AB包(QF有个相关示例中不打包运行不了;剪辑了,实际没那么快)

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

06 效果

在这里插入图片描述

---------------------------------------------------------------

02 Scene 选择

世界选择

关卡选择

stars Plugins文件夹名

unity中,Plugins文件夹下,会被变成firstpass程序集

--------------------------------------------------------

03 Scene 游戏界面

modify 拆分Enum

对初学者有好点。但实际Unity的内置脚本,有枚举写在类内部的
在这里插入图片描述

GameUI拆成 Pass面板、Fail面板

Pass面板

using UnityEngine;
using UnityEngine.UI;
using QFramework;
using UnityEngine.SceneManagement;namespace QFramework.Example
{public class SuccPanelData : UIPanelData{}public partial class SuccPanel : UIPanel{protected override void OnInit(IUIData uiData = null){mData = uiData as SuccPanelData ?? new SuccPanelData();// please add init code hereBtnNext.onClick.AddListener(() => { GameData.LevelIndex++;SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);			});}protected override void OnOpen(IUIData uiData = null){}protected override void OnShow(){}protected override void OnHide(){}protected override void OnClose(){}}
}

Fail面板

using UnityEngine;
using UnityEngine.UI;
using QFramework;
using UnityEngine.SceneManagement;namespace QFramework.Example
{public class GameOverPanelData : UIPanelData{}public partial class GameOverPanel : UIPanel{protected override void OnInit(IUIData uiData = null){mData = uiData as GameOverPanelData ?? new GameOverPanelData();// please add init code hereBtnReset.onClick.AddListener(()=>{GameManager.Instance.StartBack();CloseSelf();});BtnReplay.onClick.AddListener(() => {SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);});BtnHome.onClick.AddListener(() => {UIKit.OpenPanel<StartGamePanel>();CloseSelf();});}protected override void OnOpen(IUIData uiData = null){}protected override void OnShow(){}protected override void OnHide(){}protected override void OnClose(){}}
}

watch QF中获取一个资源

new ResLoader()这种过时了
爆炸特效
球的预制体

			//在扫雷案例中测试的,用到WhiteChessResKit.Init();ResLoader loader = ResLoader.Allocate();GameObject prefab = loader.LoadSync<GameObject>("WhiteChess");Instantiate(prefab , transform);

处理GameManager成GamePanel

01 首先将子节点的所有脚本上提到父节点 GamePanel
02 将脚本中引用的节点 进行提取,重命名(和节点名字相同),添加Bind脚本。到脚本最上面,方便看
03 因为用到UI,SpriteRenderer该改成Image

watch Awake的特点

脚本中只用Awake方法,前面就不会有勾选选项
在这里插入图片描述

bug AB资源不存在

明明有,重新打

bug 3D转UGUI

SpriteRenderer转Image后(想要用QF的调用面板的方式),球移动很小。
方法 生成地图文件之前用同样用UIRoot,也就是UGUI,而不是原来的世界坐标。此时小心注意父节点的Scale、预制体小球Ball的RectTranfrom的Scale都调为1,不然球与球之间的距离会有问题(问题就是要么球之间的距离有问题,要么轨道不重合)

modify 转UGUI Image

3000是球沿着曲线移动的平滑度
0.3也相当于球的直径,这个直径就是你要实例的那个球预制体的直径
在这里插入图片描述

方法 生成地图文件之前用同样用UIRoot,也就是UGUI,而不是原来的世界坐标。同时需要乘以倍率(试230合适)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class MapConfig : ScriptableObject
{public float EndPoint { get; private set; }public List<Vector3> pathPointList = new List<Vector3>();public void InitMapConfig(){EndPoint = pathPointList.Count - 2;}public Vector3 GetPosition(float progress){Camera ui=Camera.main.gameObject.FindComponentWithTag<Camera>("UI");int index = Mathf.FloorToInt(progress);//return Vector3.Lerp(pathPointList[index], pathPointList[index + 1], progress - index);Vector3 v1 = Vector3.Lerp(pathPointList[index], pathPointList[index + 1], progress - index);return v1*230f;}}

效果 轨道球

在这里插入图片描述

-------------------------------------

modify 发射球的发射位置、速度和终点超界判定

发射球的位置

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

速度

在这里插入图片描述

超界的判定

就是把Canvas上的 球 ,拖到Canvas的边界,看坐标
在这里插入图片描述

效果

在这里插入图片描述

-------------------------------------------

bug 销毁特效的大小和位置

using QFramework;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ResLoader = QFramework.ResLoader;public class FXManager :MonoSingleton<FXManager>
{Transform FXs;//GameObject destroyFXPrefab;ObjectPool<GameObject> destroyFXPool;public void Init(Transform FXs){this.FXs = FXs;//ResKit.Init();QFramework.ResLoader loader =  QFramework.ResLoader.Allocate();destroyFXPrefab = loader.LoadSync<GameObject>("DestroyFX"); destroyFXPool = new ObjectPool<GameObject>(InstantiateFX, 10);}private GameObject InstantiateFX(){GameObject go = Instantiate(destroyFXPrefab, FXs);go.Hide();return go;}public void ShowDestroyFX(Vector3 pos){GameObject go = destroyFXPool.GetObject();go.Show();go.transform.localPosition = pos;//延时0.5f执行回收操作ScheduleOnce.Start(this, () =>{go.Hide();destroyFXPool.AddObject(go);}, 0.5f);}
}

bug 发射器旋转一次就固定朝向左下方

后面又自动好了,可能改掉了循环调用打开GamePanel,导致存在多个GamePanel?
在这里插入图片描述

bug 自动刷新

点了几下没反应,因为原来没加自动刷新
在这里插入图片描述

bug 三个mapConfig不能放Resources,生成时空白

不放Resources,又会
GameManager.Instance.mapConfig运行后为空。这是因为
public class GameSceneConfig : MonoSingleton中的mapconfigArr有的为空

bug 抬起发射时不灵敏

关掉这个
在这里插入图片描述

watch 消球后不回退

小球后回退需要
小球后还能存在继续消球的情况在

bug 复活后回退太狠

modify SoundManager

看了示例,不需要类似于UIkit的ResKit.Init()的初始化
AudioKit.PlaySound(“resources://Sound/”+clipName );
AudioKit.PlayMusic(“resources://Sound/”+name,volume:volume);

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using QFramework;public class SoundManager : MonoSingleton<SoundManager>
{static AudioSource bgAudio;public void Init(){bgAudio = gameObject.GetOrAddComponent<AudioSource>();}private static void PlaySound(string clipName){//  AudioSource.PlayClipAtPoint(GetAudioClip(clipName), Vector3.zero);AudioKit.PlaySound("resources://Sound/"+clipName );}public static AudioClip GetAudioClip(string clipName){return Resources.Load("Sound/" + clipName, typeof(AudioClip)) as AudioClip;}public static void PlayDestroy() { PlaySound("Eliminate");  }public static void PlayShoot()   { PlaySound("Shoot"); }public static void PlayInsert()  { PlaySound("BallEnter"); }public static void PlayBomb()    { PlaySound("Bomb"); }public static void PlayFail()    { PlaySound("Fail"); }public static void PlayFastMove(){ PlaySound("FastMove"); }public static void PlayMusic(string name,float volume=0.3f) {                                                   //bgAudio.clip = SoundManager.GetAudioClip(name);//*-//bgAudio.volume = volume;//bgAudio.loop = true;//bgAudio.Play();AudioKit.PlayMusic("resources://Sound/"+name,volume:volume);}}

bug shooterSO数据丢失

发生里面的Vector3丢失的情况,所以用了以下。暂时不知道管不管用

        EditorUtility.SetDirty(fromAsset);

在这里插入图片描述

bug Object的AB包命名

原本我命名AB为 0_mapconfig,打包出也有这个ABbao1
但是右面自动出现了 0_asset,并且自动把 文件标记为 0)_asset,导致后面打包出现 0_asset
在这里插入图片描述

bug 通关下一关球没被销毁,只是progress==0

这是开始初始化的一段小球,不动是因为此时的GmaeState==Succ。重新进入游戏,需要重置 GameState
在这里插入图片描述

modify Manager拆分

将Manager从GamePanel中拆分出来
在这里插入图片描述

--------------------------------------------------------

Panel两个面板说明

也是采用QF的UI脚本自动生成,往里面填代码
。。。。
复活时回退得太多了(3D转UGUI的原因),需要调数值(里面有个回退时间是3秒)
。。。。
两个面板的效果在文章最后

Panel 成功

using UnityEngine;
using UnityEngine.UI;
using QFramework;
using UnityEngine.SceneManagement;
using QFramework.PointGame;namespace QFramework.Example
{public class SuccPanelData : UIPanelData{}public partial class SuccPanel : UIPanel{protected override void OnInit(IUIData uiData = null){mData = uiData as SuccPanelData ?? new SuccPanelData();// please add init code hereBtnNext.onClick.AddListener(() => {UIKit.OpenPanel<GamePanel>(new GamePanelData() { LevelCount=GameData.GetLevelIndex() });CloseSelf();});BtnHome.onClick.AddListener(() => {UIKit.OpenPanel<StartGamePanel>();CloseSelf();});}protected override void OnOpen(IUIData uiData = null){}protected override void OnShow(){}protected override void OnHide(){}protected override void OnClose(){}}
}

Panel 失败

主要是复活,不能Close,所以失败后先Hide,后面
01 复活,就Show
02 再来一次,就Close,在Open
03 回主页

using UnityEngine;
using UnityEngine.UI;
using QFramework;
using UnityEngine.SceneManagement;namespace QFramework.Example
{public class GameOverPanelData : UIPanelData{}public partial class GameOverPanel : UIPanel{protected override void OnInit(IUIData uiData = null){mData = uiData as GameOverPanelData ?? new GameOverPanelData();// please add init code hereBtnReset.onClick.AddListener(()=>{ //复活GameManager.Instance.GameRevive();CloseSelf();});BtnReplay.onClick.AddListener(() => { //再来一次UIKit.ClosePanel<GamePanel>();UIKit.OpenPanel<GamePanel>( new GamePanelData() { LevelCount=GameData.GetLevelIndex() });CloseSelf();});BtnHome.onClick.AddListener(() => {	 //主页UIKit.ClosePanel<GamePanel>();UIKit.OpenPanel<StartGamePanel>();CloseSelf();});}protected override void OnOpen(IUIData uiData = null){}protected override void OnShow(){}protected override void OnHide(){}protected override void OnClose(){}}
}

---------------------------------------------------------

Tool 轨道制作

modify BezierPathController

制作Ball预制体(我用了红球(可以用别的)的sprite(UGUI),原本的是MeshRender(3D世界中))
节点“Map”是BezierPathController.Awake()中用到的,是演示蓝色球坐标的,可以注释掉

01 拖一个到“1”节点(带有BezierPathController脚本)下
01 不断Ctrl+D复制节点下的预制体(每4个(基本2个控制弯曲度,2个在轨道上)红球预制体就有生成一段蓝色球)
02 Control Point List里面就是红球的坐标数据(世界坐标)
06 每4个红色球后,Scene中会生成一段蓝色球
03 04 全部做完,点击“生成地图文件”,“Path Point List”里面就是蓝色球的位置(世界坐标)
05 Map文件夹下也保存了一份坐标数据

在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using UnityEditor;
using System;
using UnityEngine.UI;public class BezierPathController : MonoBehaviour
{#region 字属public int segmentsPerCurve = 3000;/// <summary>连线上求和球之间的举例,也就是比直径大一点</summary>public float BallAndBallDis = 0.3f;public bool Debug = true;public GameObject ballPrefab;/// <summary>贝塞尔曲线的节点。控制弯曲度的白球</summary>public List<GameObject> ControlPointList = new List<GameObject>();/// <summary>贝塞尔曲线的的线段。连线的蓝球的坐标</summary>public List<Vector3> pathPointList = new List<Vector3>();#endregion//private void Awake()//{//    Debug = true;//    foreach (var item in pathPointList)//    {//        GameObject ball = Instantiate(ballPrefab, GameObject.Find("Map").transform);//        ball.transform.position = item;//    }//}private void OnDrawGizmos(){//节点ControlPointList.Clear();foreach (Transform item in transform)//没错,就是遍历子节点{ControlPointList.Add(item.gameObject);}//线段List<Vector3> controlPointPos = ControlPointList.Select(point => point.transform.position).ToList();var points = GetDrawingPoints(controlPointPos, segmentsPerCurve);Vector3 startPos = points[0];pathPointList.Clear();pathPointList.Add(startPos);for (int i = 1; i < points.Count; i++){if (Vector3.Distance(startPos, points[i]) >= BallAndBallDis){startPos = points[i];pathPointList.Add(startPos);}}foreach (var item in ControlPointList){item.GetComponent<Image>().enabled = Debug;//相当于将物体隐身,并不会影响物体的脚本运行,物体的碰撞体也依然存在。}if (Debug == false){ return;} //01 画连线球的球Gizmos.color = Color.blue;foreach (var pos in pathPointList){Gizmos.DrawSphere(pos, BallAndBallDis / 2);}//02 画连线球的线Gizmos.color = Color.yellow;for (int i = 0; i < points.Count - 1; i++){Gizmos.DrawLine(points[i], points[i + 1]);}//03 画连线球的的弯曲度控制线//绘制贝塞尔曲线控制点连线,红,色Gizmos.color = Color.red;for (int i = 0; i < controlPointPos.Count - 1; i++){Gizmos.DrawLine(controlPointPos[i], controlPointPos[i + 1]);}}#region 辅助/// <summary>贝塞尔线段</summary>List<Vector3> GetDrawingPoints(List<Vector3> controlPoints, int segmentsPerCurve){List<Vector3> points = new List<Vector3>();for (int i = 0; i < controlPoints.Count - 3; i += 3){var p0 = controlPoints[i];var p1 = controlPoints[i + 1];var p2 = controlPoints[i + 2];var p3 = controlPoints[i + 3];for (int j = 0; j <= segmentsPerCurve; j++){var t = j / (float)segmentsPerCurve;points.Add(CalculateBezierPoint(t, p0, p1, p2, p3));}}return points;}/// <summary>/// <summary>贝塞尔曲线的三次方公式</summary>/// </summary>/// <param name="t"></param>/// <param name="p0">起点</param>/// <param name="p1">一侧的平滑度调节点</param>/// <param name="p2">另一侧的平滑度调节点</param>/// <param name="p3">终点</param>/// <returns></returns>Vector3 CalculateBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3){var x   = 1 - t;var xx  = x * x;var xxx = x * x * x;var tt  = t * t;var ttt = t * t * t;return p0 * xxx +   3 * p1 * t * xx +   3 * p2 * tt * x +  p3 * ttt;}#if UNITY_EDITOR/// <summary>/// pathPointList写入"Assets/Map/map.asset"/// 但没有覆盖功能,删掉再创建就看得见效果了/// </summary> public void CreateMapAsset(){string assetPath =String.Format(  "Assets/Map/{0}.asset",gameObject.name);  //写这Vector3数据的MapConfig mapConfig = new MapConfig();foreach (Vector3 item in pathPointList){mapConfig.pathPointList.Add(item);}AssetDatabase.CreateAsset(mapConfig, assetPath);AssetDatabase.SaveAssets();}
#endif#endregion}#if UNITY_EDITOR
[CustomEditor(typeof(BezierPathController))]
public class BezierEditor : Editor
{public override void OnInspectorGUI(){base.OnInspectorGUI();if (GUILayout.Button("生成地图文件"))//详情面板下的按钮{(target as BezierPathController).CreateMapAsset();}AssetDatabase.Refresh();}
}
#endif

modify 保存位置,文件命名

保存位置放在Resources会报错
文件命名改为gameObject.name,不写死

string assetPath =String.Format( “Assets/Map/{0}.asset”, gameObject.name); //写这Vector3数据的

watch 遍历子节点

Transform 内部实现了迭代器,所以就可以这样写

        //节点ControlPointList.Clear();foreach (Transform item in transform)//没错,就是遍历子节点{ControlPointList.Add(item.gameObject);}

Tool 青蛙Shooter的位置

GameMapConfig来控制,里面有个Vector3数组

modify 修改图片的名字(-1),方便对应

在这里插入图片描述

modify 制作Shooter位置的一个工具

/****************************************************文件:MakeShooterPos.cs作者:lenovo邮箱: 日期:2023/7/19 15:37:17功能:
*****************************************************/using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using Random = UnityEngine.Random;public class MakeShooterPos : MonoBehaviour
{
#if UNITY_EDITOR/// <summary>/// pathPointList写入"Assets/Map/map.asset"/// 但没有覆盖功能,删掉再创建就看得见效果了/// </summary> public void RecordeShooterPos(){MapConfig fromAsset= AssetDatabase.LoadAssetAtPath<MapConfig>("Assets/Map/shooter.asset");int idx = int.Parse( gameObject.name);Transform shooter = GameObject.Find("ShooterTrans").transform;fromAsset.pathPointList[idx] = shooter.localPosition;AssetDatabase.SaveAssets();AssetDatabase.Refresh();}
#endif}#if UNITY_EDITOR
[CustomEditor(typeof(MakeShooterPos))]
public class MakeShooterPosEditor : Editor
{public override void OnInspectorGUI(){base.OnInspectorGUI();if (GUILayout.Button("生成Shooter位置"))//详情面板下的按钮{(target as MakeShooterPos).RecordeShooterPos();}AssetDatabase.Refresh();}
}
#endif

效果

在这里插入图片描述

---------------------------------------------------------

总的效果

01 主要按 S(Success)键,快速通关,进行测试。
02 主要按F(Fail)键,快速失败,进行测试
地图数据只做了三关,所以最后报空错误了
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

宋浩线性代数笔记(二)矩阵及其性质

更新线性代数第二章——矩阵&#xff0c;本章为线代学科最核心的一章&#xff0c;知识点多而杂碎&#xff0c;务必仔细学习。 重难点在于&#xff1a; 1.矩阵的乘法运算 2.逆矩阵、伴随矩阵的求解 3.矩阵的初等变换 4.矩阵的秩 &#xff08;去年写的字&#xff0c;属实有点ugl…

多态及其原理

文章目录 构成多态的条件虚函数作用&#xff1a;完成重写 重写重载 重写 隐藏为什么析构函数要搞成符合多态?原理预热对于基类指针或引用指向父类或者子类的成员函数是如何调用不同的函数呢&#xff1f; 一个类如果是基类&#xff0c;它的析构函数最好加上virtual 构成多态的条…

AlSD 系列智能安全配电装置是安科瑞电气有限公司专门为低压配电侧开发的一款智能安全用电产 品-安科瑞黄安南

一、应用背景 电力作为一种清洁能源&#xff0c;给人们带来了舒适、便捷的电气化生活。与此同时&#xff0c;由于使用不当&#xff0c;维护 不及时等原因引发的漏电触电和电气火灾事故&#xff0c;也给人们的生命和财产带来了巨大的威胁和损失。 为了防止低压配电系统发生漏…

2022 China Open Source Report

| 翻译&#xff1a;黄绍雅、岳扬、刘文涛、李思颖 | 编辑&#xff1a;胡欣元 | 设计&#xff1a;胡欣元 As 2022 finally came to an end, we also emerged from the challenging years of the three-year-long COVID pandemic. The new edition of the "China Open Sourc…

06.计算机网络——IP协议

文章目录 网络层IP协议基本概念协议头格式如何解包如何交付网段划分子网掩码特殊的IP地址IP地址的数量限制私有IP地址和公网IP地址路由 网络层 IP协议 IP协议提供一种将数据从A主机送达到B主机的能力&#xff0c;进行网络层的通信。 ​ IP协议 基本概念 主机 —— 配有IP地址…

MQ - 闲聊MQ一二事儿 (Kafka、RocketMQ 、Pulsar )

文章目录 MQ的发展史阶段一&#xff1a;追求解耦阶段二&#xff1a;追求吞吐量与一致性阶段三&#xff1a;追求平台化 MQ的通用架构主题topic、生产者producer、消费者consumer分区partition MQ 存储KafkaGood Design ---> 磁盘顺序写盘Poor Impact---> topic 数量不能过…

LabVIEW可重入VI,VI模板和动态VI之间的差异

LabVIEW可重入VI&#xff0c;VI模板和动态VI之间的差异 应该在何时使用可重入VI、模板VI和动态调用VI&#xff1f;这三种类型之间有什么区别&#xff1f; 可重入VI 当想要同时运行同一VI的多个实例时&#xff0c;将使用可重入VI。当VI不可重入时&#xff0c;VI只有一个数据空…

lama cleaner

这里写自定义目录标题 安装参数包含的额外plugins 安装 conda create --name lamacleaner python3.10 pip install -r requirements.txt pip install gfpgan pip install realesrgan pip install rembg pip install .如果安装本package报错&#xff0c;可以尝试改&#xff1…

后端(四):博客系统项目

咱们在这里实现的是后端项目&#xff0c;前端代码就提一提&#xff0c;不全做重点介绍&#xff0c;在开始讲解这个博客系统项目之前&#xff0c;我们先看看这个项目的前端界面&#xff1a; 登录界面&#xff1a; 个人主页&#xff1a; 博客详情页&#xff1a; 写博客页&#x…

常用API学习07(Java)

Date 在jdk1.8之前,java中的日期和时间是一类的&#xff0c;从1.8之后对日期和时间体系重新做了规划&#xff0c;划分出一个新的包 - java.time包&#xff0c;这个包中包含了日期、时间、时区、日历、单位。 Date&#xff0c;是java中最老的日期和时间类&#xff0c;后续退出…

Arcgis之 KML/KMZ文件转shp

一般我们在Goole Earth上勾画的区域导出后都为KML或者KMZ格式的&#xff0c;但无法在arcgis等软件上直接应用&#xff0c;故需进行一定的转换 1.打开ArcMap&#xff0c;选择ArcToolbox->Conversion Tools->From KML->KML To Layer 得到如下结果&#xff08;由于本KML…

pytest自动化测试框架tep环境变量、fixtures、用例三者之间的关系

tep是一款测试工具&#xff0c;在pytest测试框架基础上集成了第三方包&#xff0c;提供项目脚手架&#xff0c;帮助以写Python代码方式&#xff0c;快速实现自动化项目落地。 在tep项目中&#xff0c;自动化测试用例都是放到tests目录下的&#xff0c;每个.py文件相互独立&…

自动驾驶分级和技术架构

标题SAE 和 NHTSA自动驾驶分级 当前全球汽车行业中两个最权威的分级系统由美国国家公路交通安全管理局&#xff08;NHTSA&#xff09;和国际自动化工程师协会(SAE)提出。2013年&#xff0c;NHTSA将驾驶自动化的描述分为5个层级。2014年1月&#xff0c;SAE制定J3016自动驾驶分级…

Mybatis基础模块-日志管理

文章目录 1. 适配器模式2. Log2.1 默认实现StdOutImpl2.2 Log4jImpl 3. LogFactory4. 解析配置和应用4.1 settings配置4.2 解析 5. jdbc日志5. 1 类图5.2 BaseJdbcLogger5.3 ConnectionLogger5.4 ConnectionLogger的具体应用 1. 适配器模式 适配器使接口不兼容的对象可以相互合…

IDEA常用高效开发工具—screw一键生成数据库文档(仅需三步)

1.配置 引入screw核心... <!-- screw核心 --> <dependency><groupId>cn.smallbun.screw</groupId><artifactId>screw-core</artifactId><version>1.0.3</version> </dependency><!-- HikariCP --> <dependency…

VuePress在生产环境跳转子页报错 Failed to execute ‘appendChild‘ on ‘Node‘

记录一个使用VuePress时遇到的问题 使用VuePress做了一个文档网页&#xff0c;在开发环境的时候一切正常&#xff0c;但是发布到生产环境后&#xff0c;直接跳转二级页面会报错Failed to execute appendChild on Node 比如主页是http://sun/docs/.vuepress/dist/index.html#/…

【C语言项目】三子棋

文章目录 项目思路一、分文件进行创建二、进入游戏前的目录2.1 目录的功能&#xff1a;2.2 目录界面&#xff1a;2.3 选择进入或退出游戏2.4 多次重玩功能 三、画出棋盘3.1 写出棋子3.2 初始化棋盘3.2 画出棋盘的框架3.3 代码实现 四、玩家落子4.1 落子逻辑4.2具体情况分类讨论…

抖斗音直播间评论引流助手,支持直播间喊话+视频评论区喊话=到指定直播间引流精准粉丝【永久脚本+详细教程】

如果你觉得直播间发言手动太麻烦了&#xff0c;或许这个自动工具能帮到你&#xff01; 1.开始运行前&#xff0c;需要手动去打开打开直播间或者视频评论区&#xff0c;再运行脚本。 2.脚本就是模拟人工操作&#xff0c;在相应的APP里进行评论&#xff0c;无突破APP限制功能。…

【Kubernetes运维篇】ingress-nginx实现业务灰度发布详解

文章目录 一、理论&#xff1a;实现灰度发布的几种场景1、场景一&#xff1a;将新版本灰度给部分用户2、场景二&#xff1a;按照比例流程给新版本3、实现灰度发布字段解释 二、实践&#xff1a;1、实验前提环境2、基于Request Header(请求头)进行流量分割3、基于Cookie进行流量…

93.qt qml-自定义Table优化(新增:水平拖拽/缩放自适应/选择使能/自定义委托)

之前我们更新了90.qt qml-Table表格组件(支持表头表尾固定/自定义颜色/自定义操作按钮/排序)_qml 表格_诺谦的博客-CSDN博客 但是一直没出源码,是因为该demo还存在问题,那就是表头表尾固定下,如果是半透明状态下,会看到表头表尾固定后的内容,所以只能重构代码,不能使用重…