用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)键,快速失败,进行测试
地图数据只做了三关,所以最后报空错误了
相关文章:

用QFramework来重构 祖玛游戏
资料 Unity - 祖玛游戏 GitHub 说明 用QF一个场景就够了,在UIRoot下切换预制体达到面板切换。 但测试中当然要有一个直接跳到测试面板的 测试脚本,保留测试Scene(不然初学者也不知道怎么恢复测试Scene),所以全文按S…...

生活杂记-显示器尺寸
以下是常见显示器尺寸的对角线长度换算成厘米的结果(已经四舍五入到最接近的厘米数): 19英寸显示器 ≈ 48.26厘米21.5英寸显示器 ≈ 54.61厘米24英寸显示器 ≈ 60.96厘米27英寸显示器 ≈ 68.58厘米32英寸显示器 ≈ 81.28厘米34英寸显示器 ≈…...

在CSDN学Golang云原生(Kubernetes Pod无状态部署)
一,静态pod Kubernetes中的Pod是可以动态创建、销毁的,如果希望Pod只使用静态的IP地址而不是自动生成一个IP地址,那么就需要使用静态Pod。 静态Pod是在kubelet启动时通过指定文件夹路径来加载的。当kubelet检测到这些配置文件变化后&#x…...

@Bean的作用
Bean通常和Configuration注解一起使用 Bean可以用在方法上,方法返回的对象交给spring容器管理,和提供给其他程序组件使用 Bean是一个注解,用于将方法标记为Spring容器中的一个Bean。具体来说,Bean注解可以用于方法上,…...

【论文阅读22】Label prompt for multi-label text classification
论文相关 论文标题:Label prompt for multi-label text classification(基于提示学习的多标签文本分类) 发表时间:2023 领域:多标签文本分类 发表期刊:Applied Intelligence(SCI二区࿰…...

EasyExcel数据导出功能封装
起因: 最近需要用到excel导出功能,使用EasyExcel可以快速实现导出,又需要优雅的对EasyExcel进行封装,在实现自己的导出功能时又可以制定一定的规则,让其他同事方便使用,最近研究了下网上的常规写法,站在巨人的肩上重新添加了自己的思路,供大家参考,有任何问题请多指教…...

通过web.xml来配置servlet程序
IDEA 2022.3.3 tomcat-9.0.27 Java EE8 JDK-16 配置访问的虚拟路径 web.xml <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi"http://www.w3.org/2001/XMLSchema-insta…...

umi 创建的项目中,如何配置多个环境变量
创建env.js 在config.js中配置 在页面中使用 env.js和config.js的目录顺序 package.json中的配置...

Mysql 5.7 连接数爆满 清理连接数
Mysql 5.7 连接数爆满 清理连接数 我在做项目的时候遇到了这个报错,然后搜了半天也没有在网上找到mysql清理连接数的方案,后面还是自己写了一个 打开MySQL命令行或客户端,并使用管理员权限登录到MySQL服务器。 我这里使用的是navicat 输入…...

HTTPS工作原理
先简述一下什么是HTTPS,HTTPS就是在HTTP的基础上增加了SSL/TLS来完成加密传输,以免敏感信息被第三方获取,所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。 一、客户端发起HTTPS请求 这个没什么好说的,就是…...

十大基础算法
一、选择排序 过程简单描述: 首先,找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。其次,在剩下的元素中找到最小的元素,将它与数组的第二…...

Java---第八章(字符串-----String,StringBuilder 和 StringBuffer)
Java---第八章 字符串String字符串的常用方法StringBuilder和StringBuffer常用方法 对比String 和StringBuilder 和 StringBuffer 字符串 String 特性: String 类位于java.lang包中,无需引入,可直接使用String 类是由final修饰的ÿ…...

k8s集群的部署
【1】安装docker systemctl enable docker所有节点均需要安装docker,并且使其开机自启,每个节点均部署镜像加速器 【2】配置k8s的yum文件 [rootk8s1 ~]# cd /etc/yum.repos.d/ [rootk8s1 yum.repos.d]# vim k8s.repo [rootk8s1 yum.repos.d]# cat k8s.repo [k8s…...

设计模式——观察者模式
文章目录 1 概述2 实现3 总结 1 概述 观察者模式可以分为观察者和被观察者,观察者通过注册到一个被观察者中,也可视为订阅,当被观察者的数据发生改变时,会通知到观察者,观察者可以据此做出反应。 可以类比订阅报纸&am…...

在Debian 12 上安装 PHP 5.6, 7.4
环境:Debian 12 Debian 12 默认的PHP版本为 8.2 如果直接安装php7.4就出现下面的报错: sudo apt-get install libapache2-mod-php7.4 php7.4 php7.4-gd php7.4-opcache php7.4-mbstring php7.4-xml php7.4-json php7.4-zip php7.4-curl php7.4-imap p…...

微服务——统一网关Getway
为什么需要网关? 网关的两种实现: 网关Getway——快速入门 步骤一 网关背身也是一个微服务,需要注册到nacos中去 步骤二 成功运行后 可以通过网关进行请求转发到对应服务。 流程如下: 路由断言工厂 网关路由可以配置的东西有如下。 spri…...

[ELK安装篇]:基于Docker虚拟容器化(主要LogStash)
文章目录 一:前置准备-(参考之前博客):1.1:准备Elasticsearch和Kibana环境:1.1.1:地址:https://blog.csdn.net/Abraxs/article/details/128517777 二:Docker安装LogStash(数据收集引擎ÿ…...

纪录片《打铁文艺社》:从全美高中生电影节到多项国际赞誉,聚焦城市公共艺术的蜕变之路
7月21日,在全美高中生电影节(All American High School Film Festival,AAHSFF)公布的入围名单中,一部取材于中国深圳的纪录片《打铁文艺社Datie: The Art Tribe of Tiegang》以其深刻的主题和精良的制作,引…...

VLAN---虚拟局域网
VLAN— 虚拟局域网 LAN—局域网 MAN—城域网 WAN—广域网 1.一个VLAN相当于是一个广播域 VLAN—通过路由器和交换机协同工作后,将原本的一个广播域逻辑上,拆 分为多个虚拟的广播域。 VLAN配置: 1.创建VLAN VID—VLAN ID------用来区分和…...

新的CoolSiC™槽沟MOSFET技术,用于低栅氧化物应力和高性能
标题:The new CoolSiC™ Trench MOSFET Technology for Low Gate Oxide Stress and High Performance UPS(Uninterruptible Power Supply)系统也称不间断电源系统,是一种能够提供电力备用的设备,当主电源出现故障或停…...

【开源项目】低代码数据可视化开发平台-Datav
Datav 基本介绍 Datav是一个Vue3搭建的低代码数据可视化开发平台,将图表或页面元素封装为基础组件,无需编写代码即可完成业务需求。 它的技术栈为:Vue3 TypeScript4 Vite2 ECharts5 Axios Pinia2 在线预览 账号: admin 密码: 123123预…...

【自动话化运维】Ansible常见模块的运用
目录 一、Ansible简介二、Ansible安装部署2.1环境准备 三、ansible 命令行模块3.1.command 模块3.2.shell 模块3.3.cron 模块3.4.user 模块3.5.group 模块3.6.copy 模块3.7.file 模块8ÿ…...

深入理解C语言中的字符指针初始化与用法
字符指针初始化 - C 语言详解 目录 1. 介绍 2. 字符指针初始化的基础 3. 使用 const 关键字的字符指针初始化 4. C 语言与 C 在字符指针初始化的差异 5. 常见陷阱与最佳实践 6. 进阶概念:指针算术与动态内存分配 7. 字符串函数与字符指针 8. 结论介绍 在 C 语言中…...

es添加索引命令行和浏览器添加索引--图文详解
一、添加索引 创建索引 curl -X PUT "localhost:9200/my-index-00001?pretty" 获取索引 curl -X GET "localhost:9200/my-index-000001?pretty" 获取全部的索引 curl -X GET "http://localhost:9200/_cat/indices?v" 获取索引映射 cur…...

Java 大数字运算之 BigDecimal 类
在 Java 中提供了用于大数字运算的类,即 java.math.BigInteger 类和 java.math.BigDecimal 类。这两个类用于高精度计算,其中 BigInteger 类是针对整型大数字的处理类,而 BigDecimal 类是针对大小数的处理类。今天主要讲一下 BigDecimal 类 …...

MySQL 8.0 OCP (1Z0-908) 考点精析-架构考点1:二进制日志文件(Binary log)
文章目录 MySQL 8.0 OCP (1Z0-908) 考点精析-架构考点1:二进制日志文件(Binary log)MySQL二进制日志(Binary log)二进制日志文件的相关配置二进制日志文件的相关参数的说明二进制日志的格式设置二进制日志的格式 二进制…...

MY.CNF
# [client] port 3306 socket /var/lib/mysql/mysql.sock [mysql] prompt "\umysqldb \R:\m:\s [\d]> " no_auto_rehash loose-skip-binary-as-hex [mysqld] user mysql port 3306 #主从复制或MGR集群中,server_id记得要不同 #另外…...

SpringBoot IOC与AOP(一)
IOC AOP 一、 分层解耦 内聚: 软件中各个功能模块内部的功能联系 耦合: 衡量软件中各个层/模块之间的依赖、关联的程度 软件设计原则:高内聚、低耦合 控制反转:Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到…...

JVM运行时数据区——方法区的垃圾回收
方法区的垃圾回收主要是两部分:运行时常量池中废弃的常量和不在使用的类。 类卸载(将不在使用的类回收)的条件: 该类的所有实例均被回收。 加载该类的类加载器被回收(一般很难满足)。 类对象不再引用,通过反射也获取不到。...

LeetCode213.House-Robber-II<打家劫舍II>
题目: 思路: 在版本一中增加了一个条件 那就是首尾相关联。那么只需要进行两次循环即可。 第一次是循环是偷第一家的 那么循环到n-1 截至 并且保存一个cmp 第二次循环是不偷第一家的 循环到n截至。然后比较cmp 与 dp [n] 的最大值即可。 代码是&#…...