Unity3D仿星露谷物语开发37之浇水动画

1、目标

当点击水壶时,实现浇水的动画。同时有一个水从水壶中流出来的特效。

假如某个grid被浇过了,则不能再浇水了。。

如果某个grid没有被dug过,也不能被浇水。

2、优化Settings.cs脚本

增加如下内容:

  public static float liftToolAnimationPause = 0.4f;public static float afterLiftToolAnimationPause = 0.4f;

3、优化Player.cs脚本

添加以下代码:

private WaitForSeconds afterLiftToolAnimationPause;
private WaitForSeconds liftToolAnimationPause;// 在Start函数中添加如下代码
liftToolAnimationPause = new WaitForSeconds(Settings.liftToolAnimationPause);
afterLiftToolAnimationPause = new WaitForSeconds(Settings.afterLiftToolAnimationPause);

在ProcessPlayerClickInput的switch中增加如下一行代码:

在ProcessPlayerClickInputTool中增加如下代码:

添加如下代码:

 private void WaterGroundAtCursor(GridPropertyDetails gridPropertyDetails, Vector3Int playerDirection) { // Trigger animationStartCoroutine(WaterGroundAtCursorRoutine(playerDirection, gridPropertyDetails));}

添加如下代码:

private IEnumerator WaterGroundAtCursorRoutine(Vector3Int playerDirection, GridPropertyDetails gridPropertyDetails) 
{PlayerInputIsDisabled = true;playerToolUseDisabled = true;// Set tool animation to watering can in override animationtoolCharacterAttribute.partVariantType = PartVariantType.wateringCan;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(toolCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);toolEffect = ToolEffect.watering;if(playerDirection == Vector3Int.right){isLiftingToolRight = true;}else if(playerDirection == Vector3Int.left){isLiftingToolLeft = true;}else if(playerDirection == Vector3Int.up){isLiftingToolUp = true;}else if(playerDirection == Vector3Int.down){isLiftingToolDown = true;}yield return liftToolAnimationPause;// Set Grid property details for watered groundif(gridPropertyDetails.daysSinceWatered == -1){gridPropertyDetails.daysSinceWatered = 0;}// Set grid property to wateredGridPropertiesManager.Instance.SetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY, gridPropertyDetails);// After animation pauseyield return afterLiftToolAnimationPause;PlayerInputIsDisabled = false;playerToolUseDisabled = false;
}

其中:

ToolEffect.watering是枚举值,值为1.

watering的触发条件:

Player.cs完整代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : SingletonMonobehaviour<Player>
{private WaitForSeconds afterUseToolAnimationPause;private WaitForSeconds useToolAnimationPause;private WaitForSeconds afterLiftToolAnimationPause;private WaitForSeconds liftToolAnimationPause;private bool playerToolUseDisabled = false;  // 如果玩家正在使用某个道具,其他道具将被禁用private AnimationOverrides animationOverrides;  // 动画重写控制器private GridCursor gridCursor;private List<CharacterAttribute> characterAttributeCustomisationList;  // 目标动作列表[Tooltip("Should be populated in the prefab with the equippped item sprite renderer")][SerializeField] private SpriteRenderer equippedItemSpriteRenderer = null; // 武器的图片// Player attributes that can be swappedprivate CharacterAttribute armsCharacterAttribute;private CharacterAttribute toolCharacterAttribute;private float xInput;private float yInput;private bool isWalking;private bool isRunning;private bool isIdle;private bool isCarrying = false;private ToolEffect toolEffect = ToolEffect.none;private bool isUsingToolRight;private bool isUsingToolLeft;private bool isUsingToolUp;private bool isUsingToolDown;private bool isLiftingToolRight;private bool isLiftingToolLeft;private bool isLiftingToolUp;private bool isLiftingToolDown;private bool isPickingRight;private bool isPickingLeft;private bool isPickingUp;private bool isPickingDown;private bool isSwingToolRight;private bool isSwingToolLeft;private bool isSwingToolUp;private bool isSwingToolDown;private Camera mainCamera;private Rigidbody2D rigidbody2D;private Direction playerDirection;private float movementSpeed;private bool _playerInputIsDisabled = false;public bool PlayerInputIsDisabled { get => _playerInputIsDisabled; set => _playerInputIsDisabled = value; }protected override void Awake(){base.Awake();rigidbody2D = GetComponent<Rigidbody2D>();animationOverrides = GetComponentInChildren<AnimationOverrides>();// Initialise swappable character attributesarmsCharacterAttribute = new CharacterAttribute(CharacterPartAnimator.arms, PartVariantColour.none, PartVariantType.none);// Initialise character attribute listcharacterAttributeCustomisationList = new List<CharacterAttribute>();mainCamera = Camera.main;}private void Start(){gridCursor = FindObjectOfType<GridCursor>();useToolAnimationPause = new WaitForSeconds(Settings.useToolAnimationPause);afterUseToolAnimationPause = new WaitForSeconds(Settings.afterUseToolAnimationPause);liftToolAnimationPause = new WaitForSeconds(Settings.liftToolAnimationPause);afterLiftToolAnimationPause = new WaitForSeconds(Settings.afterLiftToolAnimationPause);}private void Update(){#region  Player Inputif (!PlayerInputIsDisabled){ResetAnimationTrigger();PlayerMovementInput();PlayerWalkInput();PlayerClickInput();PlayerTestInput();// Send event to any listeners for player movement inputEventHandler.CallMovementEvent(xInput, yInput, isWalking, isRunning, isIdle, isCarrying, toolEffect,isUsingToolRight, isUsingToolLeft, isUsingToolUp, isUsingToolDown,isLiftingToolRight, isLiftingToolLeft, isLiftingToolUp, isLiftingToolDown,isPickingRight, isPickingLeft, isPickingUp, isPickingDown,isSwingToolRight, isSwingToolLeft, isSwingToolUp, isSwingToolDown,false, false, false, false);}#endregion Player Input}private void FixedUpdate(){PlayerMovement();}/// <summary>/// 展示拿东西的动画/// </summary>/// <param name="itemCode"></param>public void ShowCarriedItem(int itemCode){ItemDetails itemDetails = InventoryManager.Instance.GetItemDetails(itemCode);if(itemDetails != null){equippedItemSpriteRenderer.sprite = itemDetails.itemSprite;equippedItemSpriteRenderer.color = new Color(1f, 1f, 1f, 1f);// Apply 'carry' character arms customisationarmsCharacterAttribute.partVariantType = PartVariantType.carry;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(armsCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);isCarrying = true;}}public void ClearCarriedItem(){equippedItemSpriteRenderer.sprite = null;equippedItemSpriteRenderer.color = new Color(1f, 1f, 1f, 0f);// Apply base character arms customisationarmsCharacterAttribute.partVariantType = PartVariantType.none;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(armsCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);isCarrying = false;}private void PlayerMovement(){Vector2 move = new Vector2(xInput * movementSpeed * Time.deltaTime, yInput * movementSpeed * Time.deltaTime);rigidbody2D.MovePosition(rigidbody2D.position + move);}private void ResetAnimationTrigger(){toolEffect = ToolEffect.none;isUsingToolRight = false;isUsingToolLeft = false;isUsingToolUp = false;isUsingToolDown = false;isLiftingToolRight = false;isLiftingToolLeft = false;isLiftingToolUp = false;isLiftingToolDown = false;isPickingRight = false;isPickingLeft = false;isPickingUp = false;isPickingDown = false;isSwingToolRight = false;isSwingToolLeft = false;isSwingToolUp = false;isSwingToolDown = false;}private void PlayerMovementInput(){xInput = Input.GetAxisRaw("Horizontal");yInput = Input.GetAxisRaw("Vertical");// 斜着移动if (xInput != 0 && yInput != 0) {xInput = xInput * 0.71f;yInput = yInput * 0.71f;}// 在移动if (xInput != 0 || yInput != 0) {isRunning = true;isWalking = false;isIdle = false;movementSpeed = Settings.runningSpeed;// Capture player direction for save gameif (xInput < 0){playerDirection = Direction.left;}else if (xInput > 0){playerDirection = Direction.right;}else if (yInput < 0){playerDirection = Direction.down;}else{playerDirection = Direction.up;}}else if(xInput == 0 && yInput == 0){isRunning = false;isWalking = false;isIdle = true;}}// 按住Shift键移动为walkprivate void PlayerWalkInput(){if(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)){isRunning = false;isWalking = true;isIdle = false;movementSpeed = Settings.walkingSpeed;}else{isRunning = true;isWalking = false;isIdle = false;movementSpeed = Settings.runningSpeed;}}private void PlayerClickInput(){if (!playerToolUseDisabled){if (Input.GetMouseButton(0)){if (gridCursor.CursorIsEnabled){// Get Cursor Grid PositionVector3Int cursorGridPosition = gridCursor.GetGridPositionForCursor();// Get Player Grid PositionVector3Int playerGridPosition = gridCursor.GetGridPositionForPlayer();ProcessPlayerClickInput(cursorGridPosition, playerGridPosition);}}}}private void ProcessPlayerClickInput(Vector3Int cursorGridPosition, Vector3Int playerGridPosition){ResetMovement();Vector3Int playerDirection = GetPlayerClickDirection(cursorGridPosition, playerGridPosition);// Get Selected item detailsItemDetails itemDetails = InventoryManager.Instance.GetSelectedInventoryItemDetails(InventoryLocation.player);// Get Grid property details at cursor position (the GridCursor validation routine ensures that grid property details are not null)GridPropertyDetails gridPropertyDetails = GridPropertiesManager.Instance.GetGridPropertyDetails(cursorGridPosition.x, cursorGridPosition.y);if(itemDetails != null){switch (itemDetails.itemType){case ItemType.Seed:if (Input.GetMouseButtonDown(0)){ProcessPlayerClickInputSeed(itemDetails);}break;case ItemType.Commodity:if (Input.GetMouseButtonDown(0)){ProcessPlayerClickInputCommodity(itemDetails);}break;case ItemType.Watering_tool:case ItemType.Hoeing_tool:ProcessPlayerClickInputTool(gridPropertyDetails, itemDetails, playerDirection);break;case ItemType.none:break;case ItemType.count:break;default:break;}}}private Vector3Int GetPlayerClickDirection(Vector3Int cursorGridPosition, Vector3Int playerGridPosition) {if(cursorGridPosition.x > playerGridPosition.x){return Vector3Int.right;}else if(cursorGridPosition.x < playerGridPosition.x){return Vector3Int.left;}else if(cursorGridPosition.y > playerGridPosition.y){return Vector3Int.up;}else{return Vector3Int.down;}}private void ProcessPlayerClickInputSeed(ItemDetails itemDetails){if(itemDetails.canBeDropped && gridCursor.CursorPositionIsValid){EventHandler.CallDropSelectedItemEvent();}}private void ProcessPlayerClickInputCommodity(ItemDetails itemDetails){if(itemDetails.canBeDropped && gridCursor.CursorPositionIsValid){EventHandler.CallDropSelectedItemEvent();}}private void ProcessPlayerClickInputTool(GridPropertyDetails gridPropertyDetails, ItemDetails itemDetails, Vector3Int playerDirection){// Switch on toolswitch (itemDetails.itemType){case ItemType.Hoeing_tool:if (gridCursor.CursorPositionIsValid){HoeGroundAtCursor(gridPropertyDetails, playerDirection);}break;case ItemType.Watering_tool:if (gridCursor.CursorPositionIsValid){WaterGroundAtCursor(gridPropertyDetails, playerDirection);}break;default:break;}}private void WaterGroundAtCursor(GridPropertyDetails gridPropertyDetails, Vector3Int playerDirection) { // Trigger animationStartCoroutine(WaterGroundAtCursorRoutine(playerDirection, gridPropertyDetails));}private IEnumerator WaterGroundAtCursorRoutine(Vector3Int playerDirection, GridPropertyDetails gridPropertyDetails) {PlayerInputIsDisabled = true;playerToolUseDisabled = true;// Set tool animation to watering can in override animationtoolCharacterAttribute.partVariantType = PartVariantType.wateringCan;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(toolCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);toolEffect = ToolEffect.watering;if(playerDirection == Vector3Int.right){isLiftingToolRight = true;}else if(playerDirection == Vector3Int.left){isLiftingToolLeft = true;}else if(playerDirection == Vector3Int.up){isLiftingToolUp = true;}else if(playerDirection == Vector3Int.down){isLiftingToolDown = true;}yield return liftToolAnimationPause;// Set Grid property details for watered groundif(gridPropertyDetails.daysSinceWatered == -1){gridPropertyDetails.daysSinceWatered = 0;}// Set grid property to wateredGridPropertiesManager.Instance.SetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY, gridPropertyDetails);// After animation pauseyield return afterLiftToolAnimationPause;PlayerInputIsDisabled = false;playerToolUseDisabled = false;}private void HoeGroundAtCursor(GridPropertyDetails gridPropertyDetails, Vector3Int playerDirection) {// Trigger animationStartCoroutine(HoeGroundAtCursorRoutine(playerDirection, gridPropertyDetails));}private IEnumerator HoeGroundAtCursorRoutine(Vector3Int playerDirection, GridPropertyDetails gridPropertyDetails){PlayerInputIsDisabled = true;playerToolUseDisabled = true;// Set tool animation to hoe in override animationtoolCharacterAttribute.partVariantType = PartVariantType.hoe;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(toolCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);if(playerDirection == Vector3Int.right){isUsingToolRight = true;}else if(playerDirection == Vector3Int.left){isUsingToolLeft = true;}else if(playerDirection == Vector3Int.up){isUsingToolUp = true;}else if(playerDirection == Vector3Int.down){isUsingToolDown = true;}yield return useToolAnimationPause;// Set Grid property details for dug groundif(gridPropertyDetails.daysSinceDug == -1){gridPropertyDetails.daysSinceDug = 0;}// Set grid property to dugGridPropertiesManager.Instance.SetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY, gridPropertyDetails);// Display dug grid tilesGridPropertiesManager.Instance.DisplayDugGround(gridPropertyDetails);// After animation pauseyield return afterUseToolAnimationPause;PlayerInputIsDisabled = false;playerToolUseDisabled = false;}public Vector3 GetPlayerViewportPosition(){// Vector3 viewport position for player (0,0) viewport bottom left, (1,1) viewport top rightreturn mainCamera.WorldToViewportPoint(gameObject.transform.position);}public void DisablePlayerInputAndResetMovement(){DisablePlayerInpupt();ResetMovement();// Send event to any listeners for player movement inputEventHandler.CallMovementEvent(xInput, yInput, isWalking, isRunning, isIdle, isCarrying, toolEffect,isUsingToolRight, isUsingToolLeft, isUsingToolUp, isUsingToolDown,isLiftingToolRight, isLiftingToolLeft, isLiftingToolUp, isLiftingToolDown,isPickingRight, isPickingLeft, isPickingUp, isPickingDown,isSwingToolRight, isSwingToolLeft, isSwingToolUp, isSwingToolDown,false, false, false, false);}private void ResetMovement(){// Reset movementxInput = 0f;yInput = 0f;isRunning = false;isWalking = false;isIdle = true;}public void DisablePlayerInpupt(){PlayerInputIsDisabled = true;}public void EnablePlayerInput(){PlayerInputIsDisabled = false;}/// <summary>/// Temp routine for test input/// </summary>private void PlayerTestInput(){// Trigger Advance Timeif (Input.GetKeyDown(KeyCode.T)){TimeManager.Instance.TestAdvanceGameMinute();}// Trigger Advance Dayif (Input.GetKeyDown(KeyCode.G)){TimeManager.Instance.TestAdvanceGameDay();}// Test scene unload / loadif (Input.GetKeyDown(KeyCode.L)){SceneControllerManager.Instance.FadeAndLoadScene(SceneName.Scene1_Farm.ToString(), transform.position);}}
}

4、优化GridCursor.cs脚本

1)调整SetCursorValidity的逻辑。

增加如下一行代码:

2)调整IsCursorValidForTool的逻辑。

添加如下代码:

其完整代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class GridCursor : MonoBehaviour
{private Canvas canvas; // 存储白色画布,UI光标位于其中private Grid grid;  // tilemap地图private Camera mainCamera; // 对主相机的引用[SerializeField] private Image cursorImage = null;[SerializeField] private RectTransform cursorRectTransform = null;  // 光标对象的引用[SerializeField] private Sprite greenCursorSprite = null;[SerializeField] private Sprite redCursorSprite = null;private bool _cursorPositionIsValid = false;public bool CursorPositionIsValid { get => _cursorPositionIsValid; set => _cursorPositionIsValid = value; }private int _itemUseGridRadius = 0;public int ItemUseGridRadius { get => _itemUseGridRadius; set => _itemUseGridRadius = value; }private ItemType _selectedItemType;public ItemType SelectedItemType { get => _selectedItemType; set => _selectedItemType = value; }private bool _cursorIsEnabled = false;public bool CursorIsEnabled { get => _cursorIsEnabled; set => _cursorIsEnabled = value; }private void OnDisable(){EventHandler.AfterSceneLoadEvent -= SceneLoaded;}private void OnEnable(){EventHandler.AfterSceneLoadEvent += SceneLoaded;}// Start is called before the first frame updatevoid Start(){mainCamera = Camera.main;canvas = GetComponentInParent<Canvas>();}// Update is called once per framevoid Update(){if (CursorIsEnabled){DisplayCursor();}}private Vector3Int DisplayCursor(){if (grid != null){   // 之所以需要Grid是因为某些定位是基于grid的// Get grid position for cursorVector3Int gridPosition = GetGridPositionForCursor();// Get grid position for playerVector3Int playerGridPosition = GetGridPositionForPlayer();// Set cursor sprite,基于gridPosition和playerGridPosition设置光标的有效性SetCursorValidity(gridPosition, playerGridPosition);// Get rect transform position for cursorcursorRectTransform.position = GetRectTransformPositionForCursor(gridPosition);return gridPosition;}else{return Vector3Int.zero;}}public Vector3Int GetGridPositionForCursor(){// z is how far the objects are in front of the camera - camera is at -10 so objects are(-)-10 in front = 10Vector3 worldPosition = mainCamera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, -mainCamera.transform.position.z));return grid.WorldToCell(worldPosition);}public Vector3Int GetGridPositionForPlayer(){return grid.WorldToCell(Player.Instance.transform.position);}public Vector2 GetRectTransformPositionForCursor(Vector3Int gridPosition){Vector3 gridWorldPosition = grid.CellToWorld(gridPosition);Vector2 gridScreenPosition = mainCamera.WorldToScreenPoint(gridWorldPosition);return RectTransformUtility.PixelAdjustPoint(gridScreenPosition, cursorRectTransform, canvas);}private void SceneLoaded(){grid = GameObject.FindObjectOfType<Grid>();}private void SetCursorValidity(Vector3Int cursorGridPosition, Vector3Int playerGridPosition){SetCursorToValid();// Check item use radius is validif(Mathf.Abs(cursorGridPosition.x -  playerGridPosition.x) > ItemUseGridRadius|| Mathf.Abs(cursorGridPosition.y - playerGridPosition.y) > ItemUseGridRadius){SetCursorToInvalid();return;}// Get selected item details ItemDetails itemDetails = InventoryManager.Instance.GetSelectedInventoryItemDetails(InventoryLocation.player);if(itemDetails == null){SetCursorToInvalid();return;}// Get grid property details at cursor positionGridPropertyDetails gridPropertyDetails = GridPropertiesManager.Instance.GetGridPropertyDetails(cursorGridPosition.x, cursorGridPosition.y);if(gridPropertyDetails != null){// Determine cursor validity based on inventory item selected and grid property detailsswitch (itemDetails.itemType){case ItemType.Seed:if (!IsCursorValidForSeed(gridPropertyDetails)){SetCursorToInvalid();return;}break;case ItemType.Commodity:if (!IsCursorValidForCommodity(gridPropertyDetails)){SetCursorToInvalid();return;}break;case ItemType.Watering_tool:case ItemType.Hoeing_tool:if(!IsCursorValidForTool(gridPropertyDetails, itemDetails)){SetCursorToInvalid();return;}break;case ItemType.none:break;case ItemType.count:break;default:break;}}else{SetCursorToInvalid();return;}}private bool IsCursorValidForSeed(GridPropertyDetails gridPropertyDetails){return gridPropertyDetails.canDropItem;}private bool IsCursorValidForCommodity(GridPropertyDetails gridPropertyDetails){return gridPropertyDetails.canDropItem;}/// <summary>/// Sets the cursor as either valid or invalid for the tool for the target gridPropertyDetails. /// Returns true if valid or false if invalid/// </summary>/// <param name="gridPropertyDetails"></param>/// <param name="itemDetails"></param>/// <returns></returns>private bool IsCursorValidForTool(GridPropertyDetails gridPropertyDetails, ItemDetails itemDetails){// Switch on toolswitch (itemDetails.itemType){case ItemType.Hoeing_tool:if (gridPropertyDetails.isDiggable == true && gridPropertyDetails.daysSinceDug == -1){#region Need to get any items at location so we can check if they are reapable// Get world position for cursorVector3 cursorWorldPosition = new Vector3(GetWorldPositionForCursor().x + 0.5f, GetWorldPositionForCursor().y + 0.5f, 0f);// Get list of items at cursor locationList<Item> itemList = new List<Item>();HelperMethods.GetComponentsAtBoxLocation<Item>(out itemList, cursorWorldPosition, Settings.cursorSize, 0f);#endregion// Loop through items found to see if any are reapable type - we are not goint to let the player dig where there are reapable scenary itemsbool foundReapable = false;foreach(Item item in itemList){if(InventoryManager.Instance.GetItemDetails(item.ItemCode).itemType == ItemType.Reapable_scenary){foundReapable = true;break;}}if (foundReapable){return false;}else{return true;}}else{return false;}case ItemType.Watering_tool:if(gridPropertyDetails.daysSinceDug > -1 && gridPropertyDetails.daysSinceWatered == -1){return true;}else{return false;}default:return false;}}private void SetCursorToValid(){cursorImage.sprite = greenCursorSprite;CursorPositionIsValid = true;}private void SetCursorToInvalid(){cursorImage.sprite = redCursorSprite;CursorPositionIsValid = false;}/// <summary>/// DisableCursor is called in the UIInventorySlot.ClearCursors() method when an inventory slot item is no longer selected/// </summary>public void DisableCursor(){cursorImage.color = Color.clear;CursorIsEnabled = false;}/// <summary>/// EnableCursor is called in the UIInventorySlot.SetSelectedItem() method when an inventory slot item is selected and its itemUseGrid radius>0/// </summary>public void EnableCursor(){cursorImage.color = new Color(1f, 1f, 1f, 1f);CursorIsEnabled = true;}public Vector3 GetWorldPositionForCursor(){return grid.CellToWorld(GetGridPositionForCursor());}}

5、设置浇水半径

默认情况下也是1,无需改动。

6、运行游戏

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

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

相关文章

【2】Kubernetes 架构总览

Kubernetes 架构总览 主节点与工作节点 主节点 Kubernetes 的主节点&#xff08;Master&#xff09;是组成集群控制平面的关键部分&#xff0c;负责整个集群的调度、状态管理和决策。控制平面由多个核心组件构成&#xff0c;包括&#xff1a; kube-apiserver&#xff1a;集…

如何对docker镜像存在的gosu安全漏洞进行修复——筑梦之路

这里以mysql的官方镜像为例进行说明&#xff0c;主要流程为&#xff1a; 1. 分析镜像存在的安全漏洞具体是什么 2. 根据分析结果有针对性地进行修复处理 3. 基于当前镜像进行修复安全漏洞并复核验证 # 镜像地址mysql:8.0.42 安全漏洞现状分析 dockerhub网站上获取该镜像的…

【Tauri2】026——Tauri+Webassembly

前言 不多废话 直言的说&#xff0c;笔者看到这篇文章大佬的文章 【04】Tauri 入门篇 - 集成 WebAssembly - 知乎https://zhuanlan.zhihu.com/p/533025312尝试集成一下WebAssembly&#xff0c;直接开始 正文 准备工作 新建一个项目 安装 vite的rsw插件和rsw pnpm instal…

OpenHarmony Camera开发指导(五):相机预览功能(ArkTS)

预览是在相机启动后实时显示场景画面&#xff0c;通常在拍照和录像前执行。 开发步骤 创建预览Surface 如果想在屏幕上显示预览画面&#xff0c;一般由XComponent组件为预览流提供Surface&#xff08;通过XComponent的getXcomponentSurfaceId方法获取surfaceid&#xff09;&…

puzzle(0531)脑力航迹

目录 脑力航迹 规则 解法 简单模式 中等模式 困难模式 专家模式 脑力航迹 规则 2条航迹会产生一个相对航迹&#xff1a; 根据相对航迹和其中一个航迹推导另外一个航迹。 解法 没有任何需要推理的地方&#xff0c;就是纯粹的2个矢量相加。 简单模式 中等模式 困难模…

在win上安装Ubuntu安装Anaconda(linx环境)

一&#xff0c;安装Ubuntu 1. 在 Microsoft 商城去下载Ubuntu(LTS:是长期维护的版本) 2.安装完之后启动程序&#xff0c;再重新打开一个黑窗口&#xff1a; wsl --list --verbose 3.关闭Ubuntu wsl --shutdown Ubuntu-22.04 WSL2 Ubuntu-20.04文件太占c盘空间&#xff0c;…

NEAT 算法解决 Lunar Lander 问题:从理论到实践

NEAT 算法解决 Lunar Lander 问题:从理论到实践 0. 前言1. 定义环境2. 配置 NEAT3. 解决 Lunar lander 问题小结系列链接0. 前言 在使用 NEAT 解决强化学习问题一节所用的方法只适用于较简单的强化学习 (reinforcement learning, RL) 环境。在更复杂的环境中使用同样的进化解…

【KWDB 创作者计划】_上位机知识篇---ESP32-S3Arduino

文章目录 前言1. ESP32-S3核心特性2. 开发环境搭建(1) 安装Arduino IDE(2) 添加ESP32-S3支持(3) 选择开发板(4) 关键配置3. 基础代码示例(1) 串口通信(USB/硬件串口)(2) Wi-Fi连接(3) 蓝牙LE广播4. 高级功能开发(1) USB OTG功能(2) AI加速(MicroTensorFlow)(3) 双核任务处理…

JavaScript学习教程,从入门到精通,DOM节点操作语法知识点及案例详解(21)

DOM节点操作语法知识点及案例详解 一、语法知识点 1. 获取节点 // 通过ID获取 const element document.getElementById(idName);// 通过类名获取&#xff08;返回HTMLCollection&#xff09; const elements document.getElementsByClassName(className);// 通过标签名获取…

PCA 降维实战:从原理到电信客户流失数据应用

一、简介 在机器学习领域&#xff0c;数据的特征维度往往较高&#xff0c;这不仅会增加计算的复杂度&#xff0c;还可能导致过拟合等问题。主成分分析&#xff08;Principal Component Analysis&#xff0c;简称 PCA&#xff09;作为一种经典的降维技术&#xff0c;能够在保留数…

信创时代编程开发语言选择指南:国产替代背景下的技术路径与实践建议

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家、CSDN平台优质创作者&#xff0c;高级开发工程师&#xff0c;数学专业&#xff0c;10年以上C/C, C#, Java等多种编程语言开发经验&#xff0c;拥有高级工程师证书&#xff1b;擅长C/C、C#等开发语言&#xff0c;熟悉Java常用开…

Arcgis10.1的汉化包及破解文件分享

Arcgis10.1的汉化包分享 网上有好多10.2的汉化包&#xff0c;但是10.1的汉化包很少&#xff0c;特在此分析出来给大家 Arcgis10.1破解文件及汉化包: (访问密码: 9784) license manager破解安装文件 另外也分享了license manager破解安装文件&#xff0c;也在相同的分享链接里…

CrewAI Community Version(一)——初步了解以及QuickStart样例

目录 1. CrewAI简介1.1 CrewAI Crews1.2 CrewAI Flows1.3 Crews和Flows的使用情景 2. CrewAI安装2.1 安装uv2.2 安装CrewAI CLI 3. 官网QuickStart样例3.1 创建CrewAI Crews项目3.2 项目结构3.3 .env3.4 智能体角色及其任务3.4.1 agents.yaml3.4.2 tasks.yaml 3.5 crew.py3.6 m…

word选中所有的表格——宏

Sub 选中所有表格()Dim aTable As TableApplication.ScreenUpdating FalseActiveDocument.DeleteAllEditableRanges wdEditorEveryoneFor Each aTable In ActiveDocument.TablesaTable.Range.Editors.Add wdEditorEveryoneNextActiveDocument.SelectAllEditableRanges wdEdito…

Tkinter与ttk模块对比:构建现代 Python GUI 的进化之路

在 Python GUI 开发中&#xff0c;标准库 tkinter 及其子模块 ttk&#xff08;Themed Tkinter&#xff09;常被同时使用。本文通过功能对比和实际案例&#xff0c;简单介绍这两个模块的核心差异。 1. 区别 Tkinter&#xff1a;Python 标准 GUI 工具包&#xff08;1994年集成&…

Linux系统之部署Dillinger个人文本编辑器

Linux系统之部署Dillinger个人文本编辑器 一、Dillinger介绍1.1 Dillinger简介1.2 Dillinger特点1.3 使用场景二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍三、检查本地环境3.1 检查本地操作系统版本3.2 检查系统内核版本四、部署Node.js 环境4.1 下载Node.js安装包4.2 解…

从malloc到free:动态内存管理全解析

1.为什么要有动态内存管理 我们已经掌握的内存开辟方法有&#xff1a; int main() {int val 20;//在栈空间上开辟四个字节char arr[20] { 0 };//在栈空间上开辟10个字节的连续空间return 0; }上述开辟的内存空间有两个特点&#xff1a; 1.空间开辟的时候大小已经固定 2.数组…

健身房管理系统设计与实现(springboot+ssm+vue+mysql)含万字详细文档

健身房管理系统设计与实现(springbootssmvuemysql)含万字详细文档 健身房管理系统是一个全面的解决方案&#xff0c;旨在帮助健身房高效管理日常运营。系统主要功能模块包括个人中心、会员管理、员工管理、会员卡管理、会员卡类型管理、教练信息管理、解聘管理、健身项目管理、…

seate TCC模式案例

场景描述 用户下单时&#xff0c;需要创建订单并从用户账户中扣除相应的余额。如果订单创建成功但余额划扣失败&#xff0c;则需要回滚订单创建操作。使用 Seata 的 TCC 模式来保证分布式事务的一致性。 1. 项目结构 假设我们有两个微服务&#xff1a; Order Service&#x…

【Linux】Rhcsa复习5

一、Linux文件系统权限 1、文件的一般权限 文件权限针对三类对象进行定义&#xff1a; owner 属主&#xff0c;缩写u group 属组&#xff0c; 缩写g other 其他&#xff0c;缩写o 每个文件针对每类访问者定义了三种主要权限&#xff1a; r&#xff1a;read 读 w&…