[Unity Demo]从零开始制作空洞骑士Hollow Knight第十七集:制作第二个BOSS燥郁的毛里克

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、制作游戏第二个BOSS燥郁的毛里克
    • 1.导入素材和制作相关动画
    • 1.5处理玩家受到战吼相关行为逻辑处理
    • 2.制作相应的行为控制和生命系统管理
    • 3.制作战斗场景和战斗门
    • 4.制作BOSS死亡行为
  • 总结


前言

         hello大家好久没见,之所以隔了这么久才更新并不是因为我又放弃了这个项目,而是接下来要制作的工作太忙碌了,每次我都花了很长的时间解决完一个部分,然后就没力气打开CSDN写文章就直接睡觉去了,现在终于有时间整理下我这半个月都做了什么内容

        废话少说,接下来我将介绍我做的第二个BOSS苍蝇之母,因为我上一期制作的苍蝇之母反响还不错,大晚上的还有一百来人在看,那么直接乘胜追击制作第二个BOSS燥郁的毛里克。

        另外,我的Github已经更新了,想要查看最新的内容话请到我的Github主页下载工程吧:

GitHub - ForestDango/Hollow-Knight-Demo: A new Hollow Knight Demo after 2 years!


一、制作游戏第二个BOSS燥郁的毛里克

1.导入素材和制作相关动画 

还是先制作好tk2dsprite和tk2dspriteanimator吧:

  

可能你已经注意到了,提供的tk2dsprite有毛里克的不同躯干,没错,我们要做的就是类似于骨骼动画一样的,每一个部分处理对应部分的行为,在这里我们分为四个部分:分别是左右手臂,嘴巴,身体,先来制作隐藏状态下的动画:

  

  

  

   

然后是手臂:

  

  

   

   身体方面的动画:

  

   

头部动画:

     

还有就是作为整体的跳跃动画:

  

  

作为整体的喷射子弹动画:

  

  

 作为整体的战吼动画:

  

死亡动画;

  1.5处理玩家受到战吼相关行为逻辑处理

        可能你看到这标题不知道我想表达什么,其实这也是我自己打这个BOSS的时候突然发现的,就是玩家在面临强大的BOSS时,会被BOSS的气场给震住,被迫失去控制的朝向BOSS,然后BOSS发射阵阵战吼冲击波,其实你看到下图小骑士的动画你就明白是什么了:

然后给小骑士一个playmakerFSM叫“Roar Lock”来实现相关行为:

 

初始阶段找到特效文件夹和里面需要的特效:

 

 通过Tag名字叫 Roar的判断是否进入下一个状态

 判断是否允许进入Roar行为:

玩家锁定状态下,发送事件,同时RelinquishControl取消控制以及AffectedByGravity受到重力影响,停止播放其他动画,使玩家朝向敌人

 自定义playmakerFSM脚本:

using System;
using UnityEngine;namespace HutongGames.PlayMaker.Actions
{[ActionCategory(ActionCategory.Logic)][Tooltip("Tests if all the given Bool Variables are are equal to thier Bool States.")]public class BoolTestMulti : FsmStateAction{[RequiredField][UIHint(UIHint.Variable)][Tooltip("This must be the same number used for Bool States.")]public FsmBool[] boolVariables;[RequiredField][Tooltip("This must be the same number used for Bool Variables.")]public FsmBool[] boolStates;public FsmEvent trueEvent;public FsmEvent falseEvent;[UIHint(UIHint.Variable)]public FsmBool storeResult;public bool everyFrame;public override void Reset(){boolVariables = null;boolStates = null;trueEvent = null;falseEvent = null;storeResult = null;everyFrame = false;}public override void OnEnter(){DoAllTrue();if (!everyFrame){Finish();}}public override void OnUpdate(){DoAllTrue();}private void DoAllTrue(){if (boolVariables.Length == 0 || boolStates.Length == 0){return;}if (boolVariables.Length != boolStates.Length){return;}bool flag = true;for (int i = 0; i < boolVariables.Length; i++){if(boolVariables[i].Value != boolStates[i].Value){flag = false;break;}}storeResult.Value = flag;if (flag){Fsm.Event(trueEvent);return;}Fsm.Event(falseEvent);}}
}

看看是否要翻转玩家X方向:

 处理粒子系统相关:

判断玩家是否在地面:

在空中锁定:

在地面被锁定:

等待发送ROAR EXIT事件:玩家重新获得输入和动画控制

取消粒子播放效果:回到Detect状态中。

2.制作相应的行为控制和生命系统管理

终于来到我们最爱的处理BOSS相应行为的时候,但在此之前还是把该要的组件导入来:

然后再来看看它有什么子对象,首先自然是它的身体部件了,首先介绍头部:

然后是左右臂:

 

还有一个子对象Attack Range,给左右两只手检测玩家是否进入攻击范围的:

 右手同理:

接着是身体部分:

Boss的警戒范围:Alert Range New

 然后是一些粒子系统:

喷射效果:

 一个简单的playmakerFSM,叫你PLAY的时候你再play:

 我们先来看看毛里克的头部是怎么控制行为的,其实也很简单,就是不停的喷子弹就完事了,

 这个特别说明的变量是喷射速度,你可以根据情况自己调:

初始化阶段就是获得玩家,获得自己孩子和父母 

初始化完整后就进入待苏醒阶段:

苏醒阶段:设置攻击间隔为0.3-0.6秒之间 

 喷射准备阶段:播放动画,等一下会

检测玩家位置:

开喷! 

这里有个预制体叫做Shot Mawlek No Drip,也就是毛里克头部发射的子弹,

记得添加DamageHero.cs脚本,这样它才能伤害到玩家 

这里有一个新脚本叫:EnemyBullet.cs,代码段如下:主要分为Trigger碰到玩家,以及Collision碰到Terrian层级的墙壁和地面的行为

using System.Collections;
using UnityEngine;[RequireComponent(typeof(Rigidbody2D))]
public class EnemyBullet : MonoBehaviour
{public float scaleMin = 1.15f;public float scaleMax = 1.45f;private float scale;[Space]public float stretchFactor = 1.2f;public float stretchMinX = 0.75f;public float stretchMaxY = 1.75f;[Space]public AudioSource audioSourcePrefab;public AudioEvent impactSound;private bool active;private Rigidbody2D body;private tk2dSpriteAnimator anim;private Collider2D col;private void Awake(){body = GetComponent<Rigidbody2D>();anim = GetComponent<tk2dSpriteAnimator>();col = GetComponent<Collider2D>();}private void OnEnable(){active = true;scale = Random.Range(scaleMin, scaleMax);col.enabled = true;body.isKinematic = false;body.velocity = Vector2.zero;body.angularVelocity = 0f;anim.Play("Idle");}private void Update(){if (active){float rotation = Random.Range(body.velocity.y,body.velocity.x) * 57.295776f;transform.SetRotation2D(rotation);float num = 1f - body.velocity.magnitude * stretchFactor * 0.01f;float num2 = 1f + body.velocity.magnitude * stretchFactor * 0.01f;if (num2 < stretchMinX){num2 = stretchMinX;}if (num > stretchMaxY){num = stretchMaxY;}num *= scale;num2 *= scale;transform.localScale = new Vector3(num2, num, transform.localScale.z);}}private void OnCollisionEnter2D(Collision2D collision){if (active){active = false;StartCoroutine(Collision(collision.GetSafeContact().Normal, true));}}private void OnTriggerEnter2D(Collider2D collision){if(active && collision.tag == "HeroBox"){active = false;StartCoroutine(Collision(Vector2.zero, false));}}public void OrbitShieldHit(Transform shield){if (active){active = false;Vector2 normal = transform.position - shield.position;normal.Normalize();StartCoroutine(Collision(normal, true));}}private IEnumerator Collision(Vector2 normal, bool doRotation){transform.localScale = new Vector3(scale, scale, transform.localScale.z);body.isKinematic = true;body.velocity = Vector2.zero;body.angularVelocity = 0f;tk2dSpriteAnimationClip impactAnim = anim.GetClipByName("Impact");anim.Play(impactAnim);if (!doRotation || (normal.y >= 0.75f && Mathf.Abs(normal.x) < 0.5f)){transform.SetRotation2D(0f);}else if (normal.y <= 0.75f && Mathf.Abs(normal.x) < 0.5f){transform.SetRotation2D(180f);}else if (normal.x >= 0.75f && Mathf.Abs(normal.y) < 0.5f){transform.SetRotation2D(270f);}else if (normal.x <= 0.75f && Mathf.Abs(normal.y) < 0.5f){transform.SetRotation2D(90f);}impactSound.SpawnAndPlayOneShot(audioSourcePrefab, transform.position);yield return null;col.enabled = false;yield return new WaitForSeconds((impactAnim.frames.Length - 1) / impactAnim.fps);Destroy(gameObject);//TODO:}}

我们把它的tk2dSprite和tk2dSpriteAnimator完成一下吧:

最后再加个子对象,给它一点亮光:

然后我们来处理它的身体Dummy行为:没啥好说的,就是攻击的时候身体flash发光一下

所以它需要SpriteFlash.cs脚本。

然后是它的左右手行为处理:这里我以左手为例

 

我们通过SetProperty开启左右手臂的MeshRenderer

 在待苏醒阶段我们肯定要关闭它的Collider2d,否则你待苏醒阶段突然给玩家扣了一滴血玩家肯定要喷你的

 判断是否进入攻击距离:

 准备攻击:

攻击阶段:这时候就到了开启Collider2d的时候了

 然后再攻击冷却阶段再关上collider2d

 准备下一次攻击,回到Idle状态。

然后右手臂也同理,我就不贴出来了。

处理完各个部分的行为逻辑,接下来就是整体的逻辑行为处理了:

 

看到下面这两个变量你可能会好奇,我头部不是已经设置了Shot Speed了吗,怎么这里还有,这是因为头部的那个只能一次喷一颗子弹,而这个是作为整体开大招喷半个屏幕的子弹的,两者还是有差别的。

初始化阶段:找自己,找孩子,停止自己移动,播放动画 

休眠阶段:播放动画,如果是神居里的BOSS,不用等WAKE事件直接苏醒,否则就要等到Alert Range New发送WAKE事件 

回到Alert Range New,和上一期讲到的一样,还是等到Trigger2d检测到后发送WAKE事件给父对象

 

 苏醒阶段:给Battle Scene发送事件START,假身Dummy播放动画

 

苏醒跳跃阶段: 给正Y轴一个向上的速度

 苏醒在空中阶段:改变Z轴大小,检测是否落地面

 

 苏醒落地阶段:

 

 介绍BOSS阶段,但我还没做到这里,所以直接跳过

 苏醒战吼阶段:向小骑士发送事件ROAR ENTER,设置Roar Object为自己

战吼结束阶段:向小骑士发送事件ROAR EXIT

音乐起:

相关代码如下:

using System;
using UnityEngine;
using UnityEngine.Audio;[CreateAssetMenu(fileName = "MusicCue", menuName = "Hollow Knight/Music Cue", order = 1000)]
public class MusicCue : ScriptableObject
{[SerializeField] private string originalMusicEventName;[SerializeField] private int originalMusicTrackNumber;[SerializeField] private AudioMixerSnapshot snapshot;[SerializeField][ArrayForEnum(typeof(MusicChannels))]private MusicCue.MusicChannelInfo[] channelInfos;[SerializeField] private MusicCue.Alternative[] alternatives;public string OriginalMusicEventName{get{return originalMusicEventName;}}public int OriginalMusicTrackNumber{get{return originalMusicTrackNumber;}}public AudioMixerSnapshot Snapshot{get{return snapshot;}}public MusicChannelInfo GetChanelInfo(MusicChannels channel){if (channel < MusicChannels.Main || channel >= (MusicChannels)channelInfos.Length){return null;}return channelInfos[(int)channel];}public MusicCue ResolveAlternatives(PlayerData playerData){if (alternatives != null){int i = 0;while (i < alternatives.Length){MusicCue.Alternative alternative = alternatives[i];if (playerData.GetBool(alternative.PlayerDataBoolKey)){MusicCue cue = alternative.Cue;if (!(cue != null)){return null;}return cue.ResolveAlternatives(playerData);}else{i++;}}}return this;}[Serializable]public class MusicChannelInfo{[SerializeField] private AudioClip clip;[SerializeField] private MusicChannelSync sync;public AudioClip Clip{get{return clip;}}public bool IsEnabled{get{return clip != null;}}public bool IsSyncRequired{get{if(sync == MusicChannelSync.Implicit){return clip != null;}return sync == MusicChannelSync.ExplicitOn;}}}[Serializable]public struct Alternative{public string PlayerDataBoolKey;public MusicCue Cue;}
}

 

using UnityEngine;
using System;namespace HutongGames.PlayMaker.Actions
{[ActionCategory(ActionCategory.Audio)][ActionTarget(typeof(MusicCue), "musicCue", false)][Tooltip("Plays music cues.")]public class ApplyMusicCue : FsmStateAction{[Tooltip("Music cue to play.")][ObjectType(typeof(MusicCue))]public FsmObject musicCue;[Tooltip("Delay before starting transition")]public FsmFloat delayTime;[Tooltip("Transition duration.")]public FsmFloat transitionTime;public override void Reset(){musicCue = null;delayTime = 0f;transitionTime = 0f;}public override void OnEnter(){MusicCue x = musicCue.Value as MusicCue;GameManager instance = GameManager.instance;if (!(x == null)){if (instance == null){Debug.LogErrorFormat(Owner, "Failed to play music cue, because the game manager is not ready", Array.Empty<object>());}else{instance.AudioManager.ApplyMusicCue(x, delayTime.Value, transitionTime.Value, false);}}Finish();}}}

然后假身利用完了就设置为空白的动画 ,此时就从整体变成各个分部,自身设置为Body Idle动画

等个2到3秒钟准备开大招:

那么到底要到什么时候才能进入开大招阶段呢?你总不可能一边左右手攻击一边飞起来吧,所以我打算让它们三分之二同时满足条件,也就是active同时激活的时候才进入开大招阶段

关闭头部collider,同时经典二选一:

作为整体拥有两种攻击行为,一是吐半个屏幕的子弹,还有一种是跳到玩家头上,这里我先介绍前一种:

又是判断是否重复执行同一种攻击行为多次,和判断玩家位置

设置好假身大小朝向:

喷半个屏幕行为:这里的SLEEP事件是发送给是自己的其他分体部件的playmakerFSM上的,就是当整体在执行行为的时候其他部分是不能动的 

 

喷射子弹 

大招结束后的冷却时间:

这里我给了四分之一的概率是否重复释放大招 

重复执行大招:

否则的话回到Start状态重新  WAKE身体的各个部件,然后从此整体又变成了各个部件 

然后再来看看跳跃攻击行为:

判断玩家方向:

超级大跳行为状态: 

在空中行为状态:Collision判断是否落地

落地行为状态:

然后还要回到起跳点的位置: 

然后就是二段跳阶段:我们在前面记录的第一次起跳前x方向的位置,然后我们就故技重施重新调回去就好了,别忘了来点粒子效果和音效啥的

至此我们完成了一个完整的BOSS相应的行为控制

3.制作战斗场景和战斗门

我觉得战斗门就不用我多说了,因为我上一期已经讲过了,直接预制体一拖然后设置好位置就OK,

我们重点是制作战斗场景,首先创建同名,设置好tag,创建playmakerFSM名字叫:Battle Control

 

 这个heart piece就是游戏的面具碎片,由于我还没做到所以先空着不管:

如果是已经击败过的BOSS就进入activate状态,生成面具碎片以及效果boss房的camera lock

战斗开始后,设置好Camera lock和敌人数量为1,还有就是关门

战斗结束后设置为激活状态,等个五秒多:

 

 

结束后记得开门 

 

4.制作BOSS死亡行为

 最后我们还要制作BOSS的尸体:

首先我们来制作BOSS尸体爆炸后变成一堆躯干:

还有一些躯干掉落后的橙汁蒸汽之类的:

我们先隐藏好上述的躯干,回到主体当中,需要rb2d和box2d:同是别忘了设置好layer

它的playmaker也很简单,跟我们上期讲到苍蝇之母一样:

告诉battle Scene战斗结束的事件:BATTLE END

初始化生成好波澜:

冒气Steam阶段和上面的差不多:

 

 

准备阶段: 

 

 最后阶段:boss尸体爆炸,生成躯干和果冻:

 

果冻就是这个orange Glob:

 我们先把它的tk2dsprite和tk2dspriteanimator做好:

 

 

 这里为什么有两个collider2d呢?因为我要一个来判断果冻是否落地,另一个判断玩家是否用骨钉攻击它:

这个是用来判断有无敌人踩到它:踩到了就执行动画wobbleAnim

 攻击它后的效果:

 我们来写一个脚本名字就叫:

GlobControl.cs

using System.Collections;
using UnityEngine;[RequireComponent(typeof(Collider2D))]
public class GlobControl : MonoBehaviour
{public Renderer rend;[Space]public float minScale = 0.6f;public float maxScale = 1.6f;[Space]public string landAnim = "Glob Land";public string wobbleAnim = "Glob Wobble";public string breakAnim = "Glob Break";[Space]public AudioSource audioPlayerPrefab;public AudioEvent breakSound;public Color bloodColorOverride = new Color(1f, 0.537f, 0.188f);[Space]public GameObject splatChild;[Space]public Collider2D groundCollider;private bool landed;private bool broken;private tk2dSpriteAnimator anim;private void Awake(){anim = GetComponent<tk2dSpriteAnimator>();}private void OnEnable(){float num = Random.Range(minScale, maxScale);transform.localScale = new Vector3(num, num, 1f);if (splatChild){splatChild.SetActive(false);}landed = false;broken = false;}private void Start(){CollisionEnterEvent collision = GetComponent<CollisionEnterEvent>();if (collision){collision.OnCollisionEnteredDirectional += delegate (CollisionEnterEvent.Direction direction, Collision2D col){if (!landed){if(direction == CollisionEnterEvent.Direction.Bottom){landed = true;collision.doCollisionStay = false;if (CheckForGround()) //检测是否碰到地面{anim.Play(landAnim);return;}StartCoroutine(Break());return;}else{collision.doCollisionStay = true;}}};}TriggerEnterEvent componentInChildren = GetComponentInChildren<TriggerEnterEvent>();if (componentInChildren){componentInChildren.OnTriggerEntered += delegate (Collider2D col, GameObject sender){if (!landed || broken){return;}if (col.gameObject.layer == LayerMask.NameToLayer("Enemies")){anim.Play(wobbleAnim); //检测如果敌人碰到了执行动画wobbleAnim}};}}private void OnTriggerEnter2D(Collider2D col){if (!landed || broken){return;}if (col.tag == "Nail Attack") //如果是骨钉攻击,执行break函数{StartCoroutine(Break());return;}if (col.tag == "HeroBox") //如果是玩家碰到了执行wobble的动画{anim.Play(wobbleAnim);}}private IEnumerator Break(){broken = true;breakSound.SpawnAndPlayOneShot(audioPlayerPrefab, transform.position);GlobalPrefabDefaults.Instance.SpawnBlood(transform.position, 4, 5, 5f, 20f, 80f, 100f, new Color?(bloodColorOverride));if (splatChild){splatChild.SetActive(true); //生成一些效果和子对象splatChild}yield return anim.PlayAnimWait(breakAnim);if (rend){rend.enabled = false;}yield break;}private bool CheckForGround(){if (!groundCollider){return true;}Vector2 vector = groundCollider.bounds.min;Vector2 vector2 = groundCollider.bounds.max;float num = vector2.y - vector.y;vector.y = vector2.y;vector.x += 0.1f;vector2.x -= 0.1f;RaycastHit2D raycastHit2D = Physics2D.Raycast(vector, Vector2.down, num + 0.25f, LayerMask.GetMask("Terrain"));RaycastHit2D raycastHit2D2 = Physics2D.Raycast(vector2, Vector2.down, num + 0.25f, LayerMask.GetMask("Terrain"));return raycastHit2D.collider != null && raycastHit2D2.collider != null;}}

别忘了回到编辑器添加好参数:


总结

        至此我们完成了制作的第二个BOSS燥郁的毛里克,就在这里展示一下成果吧:

(顺便提一下我把血量设置太高了没打过,只能自己打二周目了)

这里我的spit speed设置太低了,因为我后面改了一下游戏的重力大小,所以喷不远,你们记得根据实际情况来填参数: 

右边的爪子也没有问题:

 

 

这里没生成躯干是因为不知道为什么我的相机不会渲染的sprite-default的material了,所以没办法只能换个material:

OK终于做完一期了,刚好最近有空整理一下最近做的内容。

 

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

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

相关文章

HarmonyOS开发 - 餐饮APP中多门店多窗口打开实例补充

specified启动模式为指定实例模式&#xff0c;有一些特殊场景&#xff0c;例如多门店应用中每次打开一个门店都希望能新建一个门店实例&#xff0c;而重复打开同一个门店都是同一门店实例。 此篇为餐饮APP中多门店实例的补充内容&#xff0c;以解决同一门店多次点击重复创建新窗…

FreeRTOS 13:FreeRTOS队列的读原理

队列读取消息 FreeRTOS 中用于从队列中读取消息的 API 函数如下表所示&#xff1a; xQueueReceive BaseType_t xQueueReceive( QueueHandle_t xQueue,void * const pvBuffer,TickType_t xTicksToWait ) {BaseType_t xEntryTimeSet pdFALSE;TimeOut_t xTimeOut;Queue_t * con…

山东路远生态科技有限公司竣工投产仪式暨产品发布会圆满举行

第二十届三中全会于2024年7月15日至18日在北京举行。全会审议通过了《关于进一步全面深化改革、推进中国式现代化的决定》。其中提到,“要健全因地制宜发展新质生产力体制机制”。 新质生产力是由技术革命性突破、生产要素创新性配置、产业深度转型升级而催生的当代先进生产力…

Vue + Vant Picker实现省市区三级联动

一、picker选择器的数据由columns属性控制&#xff0c;columns中有几个元素就代表该选择器有多少级&#xff0c;通过change方法来给对应列赋值 this.columns [{values: citys,className: "column1",defaultIndex: 0,flex: 1, //控制每列的宽度},{values: citys[0].…

[java][高级]FilterListenerAjax

Filter&Listener&Ajax 目标&#xff1a; 能够使用 Filter 完成登陆状态校验功能 能够使用 axios 发送 ajax 请求 熟悉 json 格式&#xff0c;并能使用 Fastjson 完成 java 对象和 json 串的相互转换 1&#xff0c;Filter 1.1 Filter概述 Filter 表示过滤器&#…

如何使用RabbitMQ和Python实现广播消息

使用 RabbitMQ 和 Python 实现广播消息的过程涉及设置一个消息队列和多个消费者&#xff0c;以便接收相同的消息。RabbitMQ 的 “fanout” 交换机允许你将消息广播到所有绑定的队列。以下是如何实现这一过程的详细步骤。 1、问题背景 在将系统从Morbid迁移到RabbitMQ时&#x…

java.lang.IllegalArgumentException: argument type mismatch问题排查汇总

java.lang.IllegalArgumentException: argument type mismatch 错误通常发生在方法调用时&#xff0c;传入的参数类型与方法签名中声明的参数类型不匹配&#xff0c;错误发生在堆栈跟踪中&#xff0c;MyBatis 反射调用方法设置 Bean 属性时。 以下是一些可能的原因和解决方法…

沉浸式学习新体验:3D虚拟展厅如何重塑教育格局!

3D虚拟展厅对于教育行业产生了深远的影响&#xff0c;主要体现在以下几个方面&#xff1a; 一、创新教学方式 3D虚拟展厅利用三维技术构建的虚拟展示空间&#xff0c;为教育行业带来了一种全新的教学方式。传统的教学方式往往局限于书本和课堂&#xff0c;而3D虚拟展厅则能够…

第107篇:国*攻防比赛中一个多层嵌套的java内存马的反混淆解密分析过程

Part1 前言 大家好&#xff0c;我是ABC_123。一年一度的“大型攻防比赛”已经过去2、3个月了&#xff0c;在此期间陆续收到了多名网友发来的内存马样本&#xff0c;ABC_123一直在抽时间进行分析解密工作。现在很多的内存马都进行了加密混淆&#xff0c;而且一个比一个复杂&…

火山引擎云服务docker 安装

安装 Docker 登录云服务器。 执行以下命令&#xff0c;添加 yum 源。 yum update -y yum install epel-release -y yum clean all yum list依次执行以下命令&#xff0c;添加Docker CE镜像源。更多操作请参考Docker CE镜像。 # 安装必要的一些系统工具 sudo yum install -y yu…

基于SpringBoot的“会员制医疗预约服务管理信息系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“会员制医疗预约服务管理信息系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统首页界面图 医院信息界面图…

从0开始linux(21)——文件(2)文件重定向

欢迎来到博主的专栏&#xff1a;从0开始linux 博主ID&#xff1a;代码小豪 文章目录 设备文件文件缓冲区重新认识文件描述符重定向 设备文件 在前一篇文章博主提到&#xff0c;当一个c/c进程运行时&#xff0c;会默认打开三个文件流&#xff0c;分别是stdin&#xff0c;stdout…

Claude 3.5 新功能 支持对 100 页的PDF 图像、图表和图形进行可视化分析

Claude 3.5 Sonnet发布PDF图像预览新功能&#xff0c;允许用户分析长度不超过100页的PDF中的视觉内容。 此功能使用户能够轻松上传文档并提取信息&#xff0c;特别适用于包含图表、图形和其他视觉元素的研究论文和技术文档。 视觉PDF分析&#xff1a;用户现在可以从包含各种视觉…

【SQL server】数据库远程连接配置

SQL server远程连接配置 1、数据库远程配置1.身份验证2. 建立入站规则3. SQLServer服务的启动 1、数据库远程配置 1.身份验证 所以在安装过程中需要注意涉及到的的身份验证中&#xff0c;要使用混合模式&#xff0c;并设置密码。2. 建立入站规则 在控制面板中的防火墙管理中…

【Vue 全家桶】5、Vuex(更新中)

目录 概念何时使用搭建vuex环境基本使用getter的使用四个map方法的使用vuex模块化命名空间 概念 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。使用 Vuex 可…

首推!AI大模型课程2024年最新版!从零基础到入行大模型算法工程师,看完这一篇就够了,学完来找我内推!

“ 技术学习无非涵盖三个方面&#xff0c;理论&#xff0c;实践和应用**”** 大模型技术爆火至今已经有两年的时间了&#xff0c;而且大模型技术的发展潜力也不言而喻。因此&#xff0c;很多人打算学习大模型&#xff0c;但又不知道该怎么入手&#xff0c;因此今天就来了解一下…

一站式搭建线上线下交友平台/全开源码交付前后端安装说明

功能亮点 灵魂匹配&#xff1a;基于个人喜好和兴趣&#xff0c;为你推荐最合适的交友对象。 真实认证&#xff1a;所有用户都经过严格认证&#xff0c;确保交友环境真实可靠。 隐私保护&#xff1a;强大的隐私设置&#xff0c;让你轻松掌控个人信息和交友动态。 互动便捷&…

基于数组实现的Huffman树和Huffman编码

一、Huffman树简介 1、定义 树的带权路径长度&#xff0c;就是树中所有的叶节点的权值乘上其到根节点的路径长度。 在含有n 个带权叶子结点的二叉树中&#xff0c;其中带权路径长度&#xff08;Weighted Path Length, WPL&#xff09;最小的二叉树称为哈夫曼树&#xff0c; 也…

图说复变函数论重大错误:将无穷多各异平面误为同一面

黄小宁 医学若将前所未知的“新冠”病毒误为已熟知的流感病毒&#xff0c;后果...&#xff1b;数学将前所未知的点集误为已熟知的集就会引出一连串的重大错误。 h定理&#xff1a;点集AB的必要条件是A≌B。 证&#xff1a;&#xff08;1&#xff09;任何图≌自己是几何学最起码…

SDL简介和初次尝试

文章目录 SDL的用途和概念SDL下载 SDL的用途和概念 SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台开发库 &#xff0c;使用C语言写成&#xff0c;SDL提供了数种 操作 图像 &#xff0c;声音输入输出的函数&#xff0c;让开发者使用 相识的代码 就能够开发出跨平台的…