【用unity实现100个游戏之8】用Unity制作一个炸弹人游戏

文章目录

  • 前言
  • 素材
  • 开始
    • 一、绘制地图
    • 二、玩家设置
    • 三、玩家移动
    • 四、玩家四方向动画运动切换
  • 五、放置炸弹
    • 六、生成爆炸效果
    • 七、墙壁和可破坏障碍物的判断
    • 八、道具生成和效果
    • 九、玩家死亡
    • 十、简单的敌人AI
    • 十一、简单敌人AI
    • 十二、随机绘制地图
    • 十三、虚拟摇杆
  • 最终效果
  • 待续
  • 源码
  • 完结

前言

我们将在这个视频中,学习如何在Unity中制作《炸弹人心》,《炸弹人》是—个游戏系列,最初于1983年7月在日本发行,《炸弹人》的游戏玩法包括策略性地放炸弹,在一定时间后以多个方向爆炸,以摧毁障碍物和杀死敌人。

本文重点介绍了实现瓦片地图精灵动画的方法,你可以用许多不同的方式自定义游戏,
想出独特的游戏模式并建立自己的关卡。

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

素材

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

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

开始

一、绘制地图

使用tilemap绘制地图,其实挺简单的,这里我就不再介绍如何使用了,节省大家时间,tilemap还不会用的,可以看我之前的tilemap文章:【Unity小技巧】Unity2D TileMap的探究(最简单,最全面的TileMap使用介绍)

绘制的最终效果,你也可以按自己的喜欢绘制不同的地图
在这里插入图片描述

二、玩家设置

给玩家添加刚体和碰撞器,重力设置为0,注意添加圆形的碰撞器,这样可以有效防止角色转弯时卡在墙角
在这里插入图片描述

新建2d物理材质,设置角摩擦力和弹力为0,防止角色卡墙
在这里插入图片描述
刚体和碰撞器都挂载刚才的2d物理材质
在这里插入图片描述

三、玩家移动

Player代码

public class Player : MonoBehaviour
{Rigidbody2D rb;Vector2 movement;private float horizontalInput;private float verticalInput;public float speed;//移动速度private void Start(){rb = GetComponent<Rigidbody2D>();}void Update(){        horizontalInput = Input.GetAxisRaw("Horizontal");verticalInput = Input.GetAxisRaw("Vertical");movement = new Vector2(horizontalInput, verticalInput).normalized;}private void FixedUpdate(){//移动代码rb.MovePosition(rb.position + movement * speed * Time.fixedDeltaTime);}
}

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

四、玩家四方向动画运动切换

这里我们使用2D混合动画实现(2D Simple Directional),混合动画的基础使用我之前有说过,不懂得可以回去先看:
零基础带你从小白到超神27——混合状态,混合动画,动画分类
Run混合动画配置(down动画片段是默认人物站立面向观众)
在这里插入图片描述
修改人物移动代码

//控制动画
animator.SetFloat("Horizontal", horizontalInput);
animator.SetFloat("Vertical", verticalInput);

运行效果
在这里插入图片描述
问题
如果你的游戏对细节要求不高,其实到这里就已经算完成了。
但是我本着严谨的态度,会发现人物移动停止时都会面向屏幕(也就是前面的down站立动画),这显然不符合逻辑,我们希望人物最终停止面向对应的位置

那么要如何做呢?方法其实有很多,最简单的方法呢,就是在Run混合动画前面再加一个Idle混合动画
我们通过isRun参数来控制动画的切换
在这里插入图片描述
Run混合动画配置(所有动画片段都是人物不同方向的站立动画)
在这里插入图片描述

修改代码

//控制动画
if (horizontalInput == 0 && verticalInput == 0){animator.SetBool("isRun", false);
} else {animator.SetBool("isRun", true);animator.SetFloat("Horizontal", horizontalInput);animator.SetFloat("Vertical", verticalInput);
}

效果
在这里插入图片描述

五、放置炸弹

炸弹控制脚本

using System.Collections;
using UnityEngine;public class Bomb : MonoBehaviour
{[Header("Bomb")]private KeyCode inputKey = KeyCode.Space;  // 输入的按键public GameObject bombPrefab;  // 炸弹预制体public float bombFuseTime = 3f;  // 炸弹引线时间public int bombAmount = 1;  // 炸弹数量private int bombsRemaining;  // 剩余炸弹数量private void OnEnable(){bombsRemaining = bombAmount;  // 初始化剩余炸弹数量}private void Update(){if (bombsRemaining > 0 && Input.GetKeyDown(inputKey))  // 如果还有剩余炸弹且按下了指定按键{StartCoroutine(PlaceBomb());  // 放置炸弹}}private IEnumerator PlaceBomb(){Vector2 position = transform.position;  // 获取当前位置position.x = Mathf.Round(position.x)-0.5f;  // 四舍五入x坐标-0.5偏移量position.y = Mathf.Round(position.y)-0.5f;  // 四舍五入y坐标-0.5偏移量GameObject bomb = Instantiate(bombPrefab, position, Quaternion.identity);  // 实例化炸弹bombsRemaining--;  // 剩余炸弹数量减一yield return new WaitForSeconds(bombFuseTime);  // 等待炸弹引线时间Destroy(bomb.gameObject);  // 销毁炸弹游戏对象bombsRemaining++;  // 剩余炸弹数量加一}//炸弹默认是触发器 角色离开时开启碰撞效果private void OnTriggerExit2D(Collider2D other){if (other.gameObject.layer == LayerMask.NameToLayer("Bomb"))  // 如果离开触发器的物体属于Bomb层{other.isTrigger = false;  // 取消触发器属性}}
}

角色绑定脚本,配置参数,记得Bomb预制体开启触发器,并指定图层为Bomb
在这里插入图片描述
运行效果
在这里插入图片描述

六、生成爆炸效果

新增爆炸效果代码

[Header("爆炸")]
public GameObject explosionEnd; // 爆炸结束
public GameObject explosionMiddle; // 爆炸中间
public GameObject explosionStart; // 爆炸结束
public int explosionRange;//爆炸范围//生成爆炸效果
public void createExplosion(Vector2 position)
{//爆炸中心GameObject explosionStartData = Instantiate(explosionStart, position, Quaternion.identity);Destroy(explosionStartData, 0.5f);for (int i = 1; i <= explosionRange; i++){ClearDestructible(new Vector2(position.x + i, position.y), i, 0);ClearDestructible(new Vector2(position.x - i, position.y), i, 180);ClearDestructible(new Vector2(position.x, position.y + i), i, 90);ClearDestructible(new Vector2(position.x, position.y -i), i, -90);}
}private bool ClearDestructible(Vector2 position, int i, int rotate)
{//是不是最后爆炸区if (i == explosionRange){GameObject explosionEndData = Instantiate(explosionEnd, position, Quaternion.identity);//设置爆炸效果的方向explosionEndData.transform.eulerAngles = new Vector3(0, 0, rotate);Destroy(explosionEndData, 0.5f);}else{GameObject explosionMiddleData = Instantiate(explosionMiddle, position, Quaternion.identity);//设置爆炸效果的方向explosionMiddleData.transform.eulerAngles = new Vector3(0, 0, rotate);Destroy(explosionMiddleData, 0.5f);}return true;
}

效果
在这里插入图片描述

七、墙壁和可破坏障碍物的判断

修改代码

[Header("爆炸")]
public Tilemap wallTileMap; // 可破坏物墙壁的Tilemap组件
public GameObject explosionEnd; // 爆炸结束预制体
public GameObject explosionMiddle; // 爆炸中间预制体
public GameObject explosionStart; // 爆炸结束预制体
public GameObject brickWall;//破坏的墙
public int explosionRange;//爆炸范围
public LayerMask explosionLayerMask;  // 墙壁层级//生成爆炸效果
public void createExplosion(Vector2 position)
{//爆炸中心GameObject explosionStartData = Instantiate(explosionStart, position, Quaternion.identity);Destroy(explosionStartData, 0.5f);for (int i = 1; i <= explosionRange; i++){bool res = ClearDestructible(new Vector2(position.x + i, position.y), i, 0);if (!res) break;}for (int i = 1; i <= explosionRange; i++){bool res = ClearDestructible(new Vector2(position.x - i, position.y), i, 180);if (!res) break;}for (int i = 1; i <= explosionRange; i++){bool res = ClearDestructible(new Vector2(position.x, position.y + i), i, 90);if (!res) break;}for (int i = 1; i <= explosionRange; i++){bool res = ClearDestructible(new Vector2(position.x, position.y - i), i, -90);if (!res) break;} 
}private bool ClearDestructible(Vector2 position, int i, int rotate)
{if (Physics2D.OverlapBox(position, new Vector2(0.5f, 0.5f), 0f, explosionLayerMask))  // 如果爆炸位置有墙壁{return false;}Vector3Int cell = wallTileMap.WorldToCell(position);  // 将世界坐标转换为Tilemap的单元格坐标TileBase tile = wallTileMap.GetTile(cell);  // 获取指定单元格的Tileif (tile != null)  // 如果爆炸位置有可破坏障碍物{wallTileMap.SetTile(cell, null);  // 清除TileGameObject brickWallData = Instantiate(brickWall, position, Quaternion.identity);  // 实例化可破坏物体Destroy(brickWallData, 0.5f);return false;} else {//是不是最后爆炸区if (i == explosionRange){GameObject explosionEndData = Instantiate(explosionEnd, position, Quaternion.identity);//设置爆炸效果的方向explosionEndData.transform.eulerAngles = new Vector3(0, 0, rotate);Destroy(explosionEndData, 0.5f);} else {GameObject explosionMiddleData = Instantiate(explosionMiddle, position, Quaternion.identity);//设置爆炸效果的方向explosionMiddleData.transform.eulerAngles = new Vector3(0, 0, rotate);Destroy(explosionMiddleData, 0.5f);}return true;}
}

效果,记得先设置和配置好墙壁的层级
在这里插入图片描述

八、道具生成和效果

新建破坏的墙脚本

public class BrickWall : MonoBehaviour
{public float destructionTime = 1f;[Range(0f, 1f)]public float itemSpawnChance = 0.2f;//生成道具的概率public GameObject[] spawnableItems;private void Start(){Destroy(gameObject, destructionTime);}//销毁时按比例生成道具private void OnDestroy(){if (spawnableItems.Length > 0 && Random.value < itemSpawnChance){int randomIndex = Random.Range(0, spawnableItems.Length);Instantiate(spawnableItems[randomIndex], transform.position, Quaternion.identity);}}
}

新增道具代码

using UnityEngine;//道具代码
public class Prop : MonoBehaviour
{public enum ItemType{ExtraBomb,BlastRadius,SpeedIncrease,}public ItemType type;private void OnItemPickup(GameObject player){switch (type){case ItemType.ExtraBomb:player.GetComponent<Bomb>().bombAmount++;  // 炸弹数量加一player.GetComponent<Bomb>().bombsRemaining++;  // 剩余炸弹数量加一break;case ItemType.BlastRadius:player.GetComponent<Bomb>().explosionRange++;//爆炸范围增加break;case ItemType.SpeedIncrease:player.GetComponent<Player>().speed++;//移动速度增加break;}Destroy(gameObject);}private void OnTriggerEnter2D(Collider2D other){if (other.CompareTag("Player")) {OnItemPickup(other.gameObject);}}
}

挂载脚本和配置好道具参数,这里为了测试方便我就把生成道具的概率先设置为1
在这里插入图片描述
效果
在这里插入图片描述

九、玩家死亡

角色添加代码

//检测碰撞 玩家死亡
private void OnTriggerEnter2D(Collider2D other)
{if (other.gameObject.layer == LayerMask.NameToLayer("Explosion")) {animator.SetTrigger("isDeath");//播放死亡动画//TODO:结束游戏}
}

效果
在这里插入图片描述

十、简单的敌人AI

实现敌人碰壁随机往其他可移动的方向移动

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class EnemyAI : MonoBehaviour
{private float speed = 0.05f;private Rigidbody2D rig;private SpriteRenderer spriteRenderer;private Color color;/// <summary>/// 方向:0上 1下 2左 3右/// </summary>private int dirId = 0;private Vector2 dirVector;private float rayDistance = 0.7f;private float x;private float y;private void Awake(){Physics2D.queriesStartInColliders = false;spriteRenderer = GetComponent<SpriteRenderer>();color = spriteRenderer.color;rig = GetComponent<Rigidbody2D>();InitDir(Random.Range(0, 4));}private void Update(){//移动rig.MovePosition(rig.position + dirVector * speed);}private void InitDir(int dir){Debug.Log(dir);dirId = dir;switch (dirId){case 0:dirVector = Vector2.up;//控制偏移量x = Mathf.Round(rig.position.x) < rig.position.x ? Mathf.Round(rig.position.x) + 0.5f : Mathf.Round(rig.position.x) - 0.5f;transform.position = new Vector2(x, transform.position.y);break;case 1:dirVector = Vector2.down;x = Mathf.Round(rig.position.x) < rig.position.x ? Mathf.Round(rig.position.x) + 0.5f : Mathf.Round(rig.position.x) - 0.5f;transform.position = new Vector2(x, transform.position.y);break;case 2:dirVector = Vector2.left;y = Mathf.Round(rig.position.y) < rig.position.y ? Mathf.Round(rig.position.y) + 0.5f : Mathf.Round(rig.position.y) - 0.5f;transform.position = new Vector2(transform.position.x, y);break;case 3:dirVector = Vector2.right;y = Mathf.Round(rig.position.y) < rig.position.y ? Mathf.Round(rig.position.y) + 0.5f : Mathf.Round(rig.position.y) - 0.5f;transform.position = new Vector2(transform.position.x, y);break;default:break;}}private void ChangeDir(){List<int> dirList = new List<int>();if (Physics2D.Raycast(transform.position, Vector2.up, rayDistance).collider == null){dirList.Add(0);}if (Physics2D.Raycast(transform.position, Vector2.down, rayDistance).collider == null){dirList.Add(1);}if (Physics2D.Raycast(transform.position, Vector2.left, rayDistance).collider == null){dirList.Add(2);}if (Physics2D.Raycast(transform.position, Vector2.right, rayDistance).collider == null){dirList.Add(3);}if (dirList.Count > 0){int index = Random.Range(0, dirList.Count);InitDir(dirList[index]);}}//画辅助线private void OnDrawGizmos(){Gizmos.color = Color.red;Gizmos.DrawLine(transform.position, transform.position + new Vector3(0, rayDistance, 0));Gizmos.color = Color.blue;Gizmos.DrawLine(transform.position, transform.position + new Vector3(0, -rayDistance, 0));Gizmos.DrawLine(transform.position, transform.position + new Vector3(-rayDistance, 0, 0));Gizmos.DrawLine(transform.position, transform.position + new Vector3(rayDistance, 0, 0));}//碰撞检测private void OnCollisionEnter2D(Collision2D collision){//碰到层级if (collision.gameObject.layer == LayerMask.NameToLayer("Wall") || collision.gameObject.layer == LayerMask.NameToLayer("BrickWall") || collision.gameObject.layer == LayerMask.NameToLayer("Bomb")){ChangeDir();}}//检测敌人死亡private void OnTriggerEnter2D(Collider2D other){if (other.gameObject.layer == LayerMask.NameToLayer("Explosion")){Destroy(gameObject);}}
}

效果
在这里插入图片描述

十一、简单敌人AI

实现敌人随机移动

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class EnemyAI : MonoBehaviour
{private float speed = 0.05f;private Rigidbody2D rig;private SpriteRenderer spriteRenderer;private Color color;/// <summary>/// 方向:0上 1下 2左 3右/// </summary>private int dirId = 0;private Vector2 dirVector;private float rayDistance = 0.7f;private float x;private float y;private void Awake(){Physics2D.queriesStartInColliders = false;spriteRenderer = GetComponent<SpriteRenderer>();color = spriteRenderer.color;rig = GetComponent<Rigidbody2D>();InitDir(Random.Range(0, 4));}private void Update(){if (GameApp.instance.enemyMove){//移动rig.MovePosition(rig.position + dirVector * speed);}}private void InitDir(int dir){dirId = dir;switch (dirId){case 0:dirVector = Vector2.up;//控制偏移量x = Mathf.Round(rig.position.x) < rig.position.x ? Mathf.Round(rig.position.x) + 0.5f : Mathf.Round(rig.position.x) - 0.5f;transform.position = new Vector2(x, transform.position.y);break;case 1:dirVector = Vector2.down;x = Mathf.Round(rig.position.x) < rig.position.x ? Mathf.Round(rig.position.x) + 0.5f : Mathf.Round(rig.position.x) - 0.5f;transform.position = new Vector2(x, transform.position.y);break;case 2:dirVector = Vector2.left;y = Mathf.Round(rig.position.y) < rig.position.y ? Mathf.Round(rig.position.y) + 0.5f : Mathf.Round(rig.position.y) - 0.5f;transform.position = new Vector2(transform.position.x, y);break;case 3:dirVector = Vector2.right;y = Mathf.Round(rig.position.y) < rig.position.y ? Mathf.Round(rig.position.y) + 0.5f : Mathf.Round(rig.position.y) - 0.5f;transform.position = new Vector2(transform.position.x, y);break;default:break;}}private void ChangeDir(){List<int> dirList = new List<int>();if (Physics2D.Raycast(transform.position, Vector2.up, rayDistance).collider == null){dirList.Add(0);}if (Physics2D.Raycast(transform.position, Vector2.down, rayDistance).collider == null){dirList.Add(1);}if (Physics2D.Raycast(transform.position, Vector2.left, rayDistance).collider == null){dirList.Add(2);}if (Physics2D.Raycast(transform.position, Vector2.right, rayDistance).collider == null){dirList.Add(3);}if (dirList.Count > 0){int index = Random.Range(0, dirList.Count);InitDir(dirList[index]);}}//画辅助线private void OnDrawGizmos(){Gizmos.color = Color.red;Gizmos.DrawLine(transform.position, transform.position + new Vector3(0, rayDistance, 0));Gizmos.color = Color.blue;Gizmos.DrawLine(transform.position, transform.position + new Vector3(0, -rayDistance, 0));Gizmos.DrawLine(transform.position, transform.position + new Vector3(-rayDistance, 0, 0));Gizmos.DrawLine(transform.position, transform.position + new Vector3(rayDistance, 0, 0));}//碰撞检测private void OnCollisionEnter2D(Collision2D collision){//碰到层级if (collision.gameObject.layer == LayerMask.NameToLayer("Wall") || collision.gameObject.layer == LayerMask.NameToLayer("BrickWall") || collision.gameObject.layer == LayerMask.NameToLayer("Bomb")){ChangeDir();}}//检测敌人死亡private void OnTriggerEnter2D(Collider2D other){//碰到炸弹层级,换方向if (other.gameObject.layer == LayerMask.NameToLayer("Bomb")){ChangeDir();}if (other.gameObject.layer == LayerMask.NameToLayer("Explosion")){GameApp.instance.deathEnemyCount++;GameApp.instance.score++;Destroy(gameObject);}}
}

效果
在这里插入图片描述

十二、随机绘制地图

using System.Globalization;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Tilemaps;
using UnityEngine.UIElements;
using System.Collections.Generic;
using System.Collections;
//随机生成可破坏瓦片
public class MapController : MonoBehaviour
{public static MapController instance;[Range(0f, 1f)]public float itemSpawnChance = 0.2f;//生成瓦片的概率public Tilemap map;// 瓦片资源基类通过它可以得到瓦片资源public TileBase tileBase;private List<Vector3> emptyPosition;//保存所有的空位private List<Vector3> wallPosition;//保存所有的可破坏墙的位置public GameObject enemy;//怪物预制体public GameObject door;//门预制体public GameObject playerData;//主角预制体private int mapWidth;private int mapHeight;private void Awake(){if (instance == null){instance = this;}else{if (instance != this){Destroy(gameObject);}}DontDestroyOnLoad(gameObject);emptyPosition = new List<Vector3>();wallPosition = new List<Vector3>();mapWidth = 16;mapHeight = 8;}public void Init(){// 1.清空瓦片地图map.ClearAllTiles();for (int i = 0; i <= mapWidth; i++){for (int j = 0; j <= mapHeight; j++){//跳过砖块if (i % 2 != 0 && j % 2 != 0){continue;}Vector3 position = new Vector3(-7.5f + i, 3.5f - j, 0);Vector3Int cell = map.WorldToCell(position);  // 将世界坐标转换为Tilemap的单元格坐标if (Random.value < itemSpawnChance){map.SetTile(cell, tileBase); // 设置wallPosition.Add(position);}else{emptyPosition.Add(position);}}}addPlayer();addEnemy();addDoor();//清空地图的炸弹GameObject[] res = GameObject.FindGameObjectsWithTag("Bomb");foreach (GameObject item in res){Destroy(item);}//清空地图的道具res = GameObject.FindGameObjectsWithTag("Props");foreach (GameObject item in res){Destroy(item);}}//生成主角private void addPlayer(){GameObject res = GameObject.Find("Player(Clone)");if (res != null){Destroy(res);}GameObject player = Instantiate(playerData);//生成在左下角player.transform.position = new Vector2(-7.5f, -4.5f);//去除相邻的mapmap.SetTile(map.WorldToCell(new Vector2(-7.5f, -4.5f)), null);map.SetTile(map.WorldToCell(new Vector2(-6.5f, -4.5f)), null);map.SetTile(map.WorldToCell(new Vector2(-7.5f, -3.5f)), null);emptyPosition.Remove(new Vector3(-7.5f, -4.5f, 0));emptyPosition.Remove(new Vector3(-6.5f, -4.5f, 0));emptyPosition.Remove(new Vector3(-7.5f, -3.5f, 0));}//生成怪物private void addEnemy(){//清空地图上的所有敌人GameObject[] res = GameObject.FindGameObjectsWithTag("Enemy");foreach (GameObject item in res){Destroy(item);}if (emptyPosition.Count > 0){for (int i = 0; i < GameApp.instance.enemyCount; i++){int index = Random.Range(0, emptyPosition.Count);Instantiate(enemy, emptyPosition[index], Quaternion.identity);}}}
}

效果,每次进来地图都不一样
在这里插入图片描述

十三、虚拟摇杆

引入虚拟摇杆,实现玩家移动,不懂的可以看我这篇文章:3种实现虚拟移动摇杆控制人物移动的方法

效果
在这里插入图片描述

最终效果

在这里插入图片描述

待续

后面还准备了一些内容,有空再补充,包括音频管理器、随机生成地图和敌人、通关门效果、主角生命值,游戏开始和结束UI界面,关卡选择界面、保存主角属性到下一关、更多的敌人(可能加入boss)、优化代码架构、完善虚拟摇杆、发布游戏到微信小游戏

源码

后面整理好我会放上来

完结

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

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

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

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

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

相关文章

2023年行研行业研究报告

第一章 行业概述 1.1 行研行业 行业定义为同一类别的经济活动&#xff0c;这涉及生产相似产品、应用相同生产工艺或提供同类服务的集合&#xff0c;如食品饮料行业、服饰行业、机械制造行业、金融服务行业和移动互联网行业等。 为满足全球金融业的需求&#xff0c;1999年8月…

Linux之autofs自动挂载服务

目录 Linux之autofs自动挂载服务 产生原因 安装 配置文件分析 文件路径 作用 etc/auto.master文件内容格式 挂载参数 案例 案例1 --- 服务器创建共享目录&#xff0c;客户端实现自动挂载 案例2 --- 自动挂载光盘 Linux之autofs自动挂载服务 产生原因 在一般NFS文件系…

$attrs,$listeners

vue实现组件通信的方式有&#xff1a; 父子通信 父组件向子组件传递通过props定义各个属性来传递&#xff0c;子组件向父组件传递通过$emit触发事件 ref也可以访问组件实例跨级通信 vuex bus provide / inject $attrs / $listeners解释 $attrs / $listeners $attrs 将父组件中…

服务端请求伪造(SSRF)及漏洞复现

文章目录 渗透测试漏洞原理服务端请求伪造1. SSRF 概述1.1 SSRF 场景1.1.1 PHP 实现 1.2 SSRF 原理1.3 SSRF 危害 2. SSRF 攻防2.1 SSRF 利用2.1.1 文件访问2.1.2 端口扫描2.1.3 读取本地文件2.1.4 内网应用指纹识别2.1.5 攻击内网Web应用 2.2 SSRF 经典案例2.2.1 访问页面2.2.…

自然语言处理实战项目17-基于多种NLP模型的诈骗电话识别方法研究与应用实战

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下自然语言处理实战项目17-基于NLP模型的诈骗电话识别方法研究与应用&#xff0c;相信最近小伙伴都都看过《孤注一掷》这部写实的诈骗电影吧&#xff0c;电影主要围绕跨境网络诈骗展开&#xff0c;电影取材自上万起真…

基于Java+SpringBoot+Vue前后端分离善筹网(众筹)设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

vue3在路由route.js中获取不到仓库pinia中store里面的值

原因&#xff1a;小仓库(useUserStore )必须有大仓库(pinia)才能运行&#xff0c;在组件中能使用pinia仓库的数据&#xff0c;是因为在main.ts中已经在vue上面挂载了大仓库(pinia)&#xff0c;但是route.js不是vue组件&#xff0c;没有被挂载大仓库&#xff0c;所以不能运行 解…

使用(七牛云)为例子实现将文件上传到云服务器

目的 目前&#xff0c;用户的头像、分享生成的长图等文件都是存放在本地的&#xff0c;我们可以将他们存放在云服务器中&#xff0c;此处我们使用七牛云作为例子示范。 七牛云 创建账户并申请如下的两个bucket&#xff0c;分别是用户头像的存储空间和分享长图的存储空间。 …

数据库设计DDL

DDL&#xff1a;数据定义语言&#xff0c;用来定义数据库对象&#xff08;数据库、表&#xff09; DDL&#xff08;数据库操作&#xff09; 查询&#xff1a; 查询所有数据库&#xff1a;show databases; 查询当前数据库&#xff1a;select database(); 使用&#xff1a; 使用…

Python 之 match 表达式

Python 从 3.10 版本开始增加了 match 语句&#xff0c;和其他语言常见的 switch 语句极其相似&#xff0c;但功能更加强大。 本文通过实例&#xff0c;了解下其用法。 基本的 match 语句 def http_code(status): match status: case 400 | 404 | 418: …

java八股文面试[JVM]——JVM性能优化

JVM性能优化指南 JVM常用命令 jps 查看java进程 The jps command lists the instrumented Java HotSpot VMs on the target system. The command is limited to reporting information on JVMs for which it has the access permissions. jinfo &#xff08;1&#xff09;实时…

AIGC专栏3——Stable Diffusion结构解析-以图像生成图像(图生图,img2img)为例

AIGC专栏3——Stable Diffusion结构解析-以图像生成图像&#xff08;图生图&#xff0c;img2img&#xff09;为例 学习前言源码下载地址网络构建一、什么是Stable Diffusion&#xff08;SD&#xff09;二、Stable Diffusion的组成三、img2img生成流程1、输入图片编码2、文本编码…

SpringCloud(35):Nacos 服务发现快速入门

本小节,我们将演示如何使用Spring Cloud Alibaba Nacos Discovery为Spring cloud 应用程序与 Nacos 的无缝集成。 通过一些原生的spring cloud注解,我们可以快速来实现Spring cloud微服务的服务发现机制,并使用Nacos Server作为服务发现中心,统一管理所有微服务。 1 Spring…

vue3中TCplayer应用

环境win10:vitevue3elementUI 1 安装 npm install tcplayer.js2 使用 <template><div><video id"player-container-id" width"414" height"270" preload"auto" playsinline webkit-playsinline></video>&l…

联发科MTK6762/MT6762核心板_安卓主板小尺寸低功耗4G智能模块

MT6762安卓核心板是一款基于MTK平台的高性能智能模块&#xff0c;是一款工业级的产品。该芯片也被称为Helio P22。这款芯片内置了Arm Cortex-A53 CPU&#xff0c;最高可运行于2.0GHz。同时&#xff0c;它还提供灵活的LPDDR3/LPDDR4x内存控制器&#xff0c;此外&#xff0c;Medi…

【FreeRTOS】【应用篇】消息队列【下篇】

前言 本篇文章主要对 FreeRTOS 中消息队列的概念和相关函数进行了详解消息队列【下篇】详细剖析了消息队列中发送、接收时队列消息控制块中各种指针的行为&#xff0c;以及几个发送消息和接收消息的函数的运作流程笔者有关于 【FreeRTOS】【应用篇】消息队列【上篇】——队列基…

【链表OJ 11】复制带随机指针的链表

前言: &#x1f4a5;&#x1f388;个人主页:​​​​​​Dream_Chaser&#xff5e; &#x1f388;&#x1f4a5; ✨✨刷题专栏:http://t.csdn.cn/UlvTc ⛳⛳本篇内容:力扣上链表OJ题目 目录 leetcode138. 复制带随机指针的链表 1. 问题描述 2.代码思路: 2.1拷贝节点插入到…

【文心一言大模型插件制作初体验】制作面试错题本大模型插件

文心一言插件开发初体验 效果图 注意&#xff1a;目前插件仅支持在本地运行&#xff0c;虽然只能自用&#xff0c;但仍然是一个不错的选择。&#xff08;什么&#xff1f;你说没有用&#xff1f;这不可能&#xff01;文心一言app可以支持语音&#xff0c;网页端结合手机端就可…

计算机网络第三节物理层

一&#xff0c;第二章 物理层&#xff08;数据通信有关&#xff09; 1.物理层引入的目的 屏蔽掉传输介质的多样性&#xff0c;导致数据传输方式的不同&#xff1b;物理层的引入使得高层看到的数据都是统一的0,1构成的比特流 2.物理层如何实现屏蔽 物理层靠定义的不同的通信…

智慧园区用水用电信息管理系统:实现高效节能的现代化园区管理

随着科技的不断发展&#xff0c;各类产业园区在我国经济社会发展中发挥着越来越重要的作用。为了提高园区的运营效率、降低能源消耗、实现绿色可持续发展&#xff0c;智慧园区用水用电信息管理系统应运而生。本文将从系统背景、功能特点、应用优势等方面进行详细介绍。 一、系统…