四、综合案例(Unity2D)

news2025/2/25 4:42:02

一、2D渲染

1、2D相机基本设置

上面是透视,下面是正交

2、图片资源

在Unity中,常规图片导入之后,一般不在Unity中直接使用,而是转为精灵图Sprite

将图片更改为即可使用Unity内置的图片切割功能

无论精灵图片是单个的还是多个的,都可以选择中心点

3、相关组件

 

在排序图层中,越靠下的,越先渲染

也就是说,靠近摄像机的因该是最下方的图层

二、Unity输入系统

1、按键检测

关于键盘的

if (Input.GetKeyDown(KeyCode.A))
{
    Debug.Log("A按下了!");
}
if (Input.GetKey(KeyCode.A))
{
	Debug.Log("A持续按住!");
}
if (Input.GetKeyUp(KeyCode.A))
{
	Debug.Log("A弹起了!");
}

 

2、鼠标检测

和键盘区别不大,只是调用的API不同

注:0是左键;1是右键;2是鼠标中键

if (Input.GetMouseButtonDown(0))
{
	Debug.Log("鼠标左键按下");
}
if (Input.GetMouseButton(0))
{
	Debug.Log("鼠标左键按住");
}
if (Input.GetMouseButtonUp(0))
{
	Debug.Log("鼠标左键抬起");
}

 

3、InputManager

在Unity的设置中找到输入部分,即可看到默认绑定的按键

一个简单的移动代码

float inputX = Input.GetAxis("Horizontal");
float inputY = Input.GetAxis("Vertical");
float speed = 5;
transform.Translate(Time.deltaTime * speed * new Vector3(inputX, inputY, 0));

注:这里的速度乘以时间,放在前面,避免一些不必要的消耗

三、Unity2D动画概览

1、Animator组件

先在窗口上添加一个动画组件

一定是下面这个。上面这个是比较老的技术了

2、AnimatorController:动画控制器

3、AnimationClip:动画片段 

四、动画录制 

在Unity内制作动画

在录制时,必须开启录制按钮,可以选择数据,也可以修改数据,录制时会自动记录下来

也可以添加颜色

 五、动画切换

 

通过参数进行切换,小于或者大于

 2D人物的简单移动代码

public Animator animator;
public float movespeed = 0.00001f;
public SpriteRenderer spriteRenderer;
private void Start()
{
	spriteRenderer= gameObject.GetComponent<SpriteRenderer>();
}

// Update is called once per frame
void Update()
{
	animator.GetComponent<Animator>();
	float inputX = Input.GetAxis("Horizontal");
    float inputY = Input.GetAxis("Vertical");
	//修改动画
    bool isMove = inputX != 0 || inputY!=0;
	animator.SetBool("Move", isMove);
    //转向
    if (inputX > 0) spriteRenderer.flipX = false;
    else if (inputX < 0) spriteRenderer.flipX = true;

	//位移
	Vector3 pos =
            new Vector3(inputX * Time.deltaTime * movespeed,
                        inputY * Time.deltaTime * movespeed,
                        0);
    transform.Translate(pos, Space.Self);
}

六、动画事件

在动画的某一帧触发某个函数;

原理是:在当前动画物体上的脚本里面 是否有一个事件;必须是公开的

在此处添加动画事件;

选择动画事件代码

public void Colore()
{
    transform.localScale=new Vector3(3, 3, 3);
    Debug.Log("1");
}

 

执行到这个事件时,会执行这个函数 

七、2D物理系统

每个人都需要有碰撞器,只要有一个有刚体

事件触发函数

private void OnCollisionEnter2D(Collision2D collision)
{
	
}
private void OnCollisionStay2D(Collision2D collision)
{
	
}
private void OnCollisionExit2D(Collision2D collision)
{
	
}

碰撞与触发不能共存

触发函数代码

private void OnTriggerEnter2D(Collider2D collision)
{
	
}
private void OnTriggerStay2D(Collider2D collision)
{
	
}
private void OnTriggerExit2D(Collider2D collision)
{
	
}

 八、主角控制(综合案例)

在玩家身上挂载一个触发器,不需要碰撞

挂载脚本

public class Game : MonoBehaviour
{
    public Animator animator;
    public float movespeed;
    public SpriteRenderer spriteRenderer;
    bool Big=false;
	private void Start()
	{
		spriteRenderer= gameObject.GetComponent<SpriteRenderer>();
	}

	// Update is called once per frame
	void Update()
    {
		animator.GetComponent<Animator>();
		float inputX = Input.GetAxis("Horizontal");
        float inputY = Input.GetAxis("Vertical");
		//修改动画
        bool isMove = inputX != 0 || inputY!=0;
		animator.SetBool("Move", isMove);
        //转向
        if (inputX > 0) spriteRenderer.flipX = false;
        else if (inputX < 0) spriteRenderer.flipX = true;

		//位移
		Vector3 pos =
                new Vector3(inputX * Time.deltaTime * movespeed,
                            inputY * Time.deltaTime * movespeed,
                            0);
        transform.Translate(pos, Space.Self);
    }
   
}

由于人物比较小,调节一下摄像机距离

九、发射子弹

子弹一般都是预制体;

需要一个公开获取预制体;一个生成子弹的点位;一个if循环判断按键和实例化

子弹飞行是自己的逻辑;挂载在预制体上面;

private void Shoot()
{
	if (Input.GetKeyDown(KeyCode.J))
	{
		//实例化
		GameObject star=GameObject.Instantiate(starPrefab);
		star.transform.position = starShootPoint.position;
	}
}

创建一个动画,模拟子弹射出

旋转360° 然后旋转720°

将动画勾选为循环

在预制体子弹上面挂在一个动画状态机,放入旋转动画

挂载子弹的代码


    public float moveSpeed;
    private Vector3 moveDir;
    public float destroyTime=3;
    private float destroyTimer;//计时器
    public void Init(Vector3 dir)
    {
        moveDir = dir;
        destroyTimer = destroyTime;
    }

    // Update is called once per frame
    void Update()
    {
        transform.Translate(moveSpeed * Time.deltaTime * moveDir,Space.World);
        if (destroyTimer <= 0)
        {
            Destroy(gameObject);
        }else
        {
            destroyTimer-=Time.deltaTime;
        }
    }

由于子弹自身有旋转,所以坐标会一直更改,需要传入一个方向初始化

在玩家代码中调用

//实例化
GameObject star=GameObject.Instantiate(starPrefab);
star.transform.position = starShootPoint.position;
bool isRightDir = spriteRenderer.flipX == false;
Vector3 moveDir = isRightDir ? transform.right : -transform.right;
Debug.Log(moveDir);
star.GetComponent<Star>().Init(moveDir);

先实例化这个预制体;把生成点赋值给预制体的当前坐标

通过bool判断是左还是右

然后获取预制体代码中的初始化方法,并传入方向

然后写一个计时器,让子弹销毁

public class Game : MonoBehaviour
{
    public Animator animator;
    public float movespeed;
    public SpriteRenderer spriteRenderer;
	public GameObject starPrefab;
	public Transform starShootPoint;

	//CD
	private float shootCD = 1;
	private float shootCDTimer;
	private void Start()
	{
		spriteRenderer= gameObject.GetComponent<SpriteRenderer>();
	}

	// Update is called once per frame
	void Update()
    {
		Move(); Shoot();

	}
   private void Move()
    {
		animator.GetComponent<Animator>();
		float inputX = Input.GetAxis("Horizontal");
		float inputY = Input.GetAxis("Vertical");
		//修改动画
		bool isMove = inputX != 0 || inputY != 0;
		animator.SetBool("Move", isMove);
		//转向
		if (inputX > 0) spriteRenderer.flipX = false;
		else if (inputX < 0) spriteRenderer.flipX = true;

		//位移
		Vector3 pos =
				new Vector3(inputX * Time.deltaTime * movespeed,
							inputY * Time.deltaTime * movespeed,
							0);
		transform.Translate(pos, Space.Self);
	}
	private void Shoot()
	{
		if (shootCDTimer > 0)
		{
			shootCDTimer-= Time.deltaTime;
			return;
		}
		if (Input.GetKeyDown(KeyCode.J))
		{
			shootCDTimer = shootCD;
			//实例化
			GameObject star=GameObject.Instantiate(starPrefab);
			star.transform.position = starShootPoint.position;
			bool isRightDir = spriteRenderer.flipX == false;
			Vector3 moveDir = isRightDir ? transform.right : -transform.right;
			Debug.Log(moveDir);
			star.GetComponent<Star>().Init(moveDir);
		}
	}
}

十、怪物生成

1、配置一些坐标生成怪物

创建一个空物体,挂载怪物的代码

对怪物的基础配置进行设置:

这里有一个方法;使用class类,然后把这个类作为一个数组,公开这个数组为public即可

/// <summary>
/// 怪物生成点
/// </summary>
[Serializable]
public class MonsterSpawnPoint
{
    public Transform spawnPoint;//生成点
    public GameObject monsterPrefab;//怪物预制体
    public float spawnInterval;//怪物生成间隔
    //这里的计时器不想序列化,但是需要获取,所以改为属性
    public float SpawnTimer { get; set; }
}
public MonsterSpawnPoint[] monsterSpawnPoints;

 

小技巧:把动画片段全部选中拖拽进入层级面板中,可以快速地生成动画和动画状态

2、按照一个频率生成怪物

现在面板上设置了预制体和生成间隔

我们做一个计时器,计时器命名为Timer

用一个for循环遍历这5个数组

声明一个局部变量类,让每一次循环都赋值给这个局部变量类,也就是每一次循环Point都获取了数组中的参数;

使用计时器,先让他小于零;

做一个判断如果小于零,那么就把生成间隔赋值给计时器;

并且实例化类中的预制体,把类中的生成点赋值给怪物的当前位置;

private void Update()
{
    for (int i=0;i< monsterSpawnPoints.Length;i++)
    {
		MonsterSpawnPoint point= monsterSpawnPoints[i];
        point.SpawnTimer-=Time.deltaTime;//这里的计时器一开始就会小于零
        if (point.SpawnTimer <= 0)//一定会小于零
        {
            point.SpawnTimer = point.spawnInterval;//就把生成间隔赋值给计时器
            GameObject monster = GameObject.Instantiate(point.monsterPrefab);
            monster.transform.position = point.spawnPoint.position;
        }
	}
}

现在对代码进行一下优化,

public class MonsterManager : MonoBehaviour
{
    /// <summary>
    /// 怪物生成点
    /// </summary>
    [Serializable]
    public class MonsterSpawnPoint
    {
        public Transform spawnPoint;//生成点
        public GameObject monsterPrefab;//怪物预制体
        public float spawnInterval;//怪物生成间隔
        //这里的计时器不想序列化,但是需要获取,所以改为属性
        public float SpawnTimer { get; set; }

       public void Update(float deltaTime)
        {
			SpawnTimer -= Time.deltaTime;//这里的计时器一开始就会小于零
			if (SpawnTimer <= 0)//一定会小于零
			{
				SpawnTimer = spawnInterval;//就把生成间隔赋值给计时器
				GameObject monster = GameObject.Instantiate(monsterPrefab);
				monster.transform.position = spawnPoint.position;
			}
		}
    }
    public MonsterSpawnPoint[] monsterSpawnPoints;
	private void Update()
	{
        for (int i=0;i< monsterSpawnPoints.Length;i++)
        {
			monsterSpawnPoints[i].Update(Time.deltaTime);
           
		}
	}
}

因为update中调用其他类中的变量,不如直接调用update封装起来

所以在Update中定义一个参数(时间),因为调用这个update传入的参数是Time.deltatime

把生成的逻辑封装起来在Update中

在主update中,每一个for循环之后,数组的第i次循环调用这个UPdate,并传入每时每秒。

十一、怪物移动逻辑

一直去追玩家,如果解除了玩家则玩家失败;

首先把玩家设置成单例;在怪物类中先设置一个判断;判断玩家是否为空,也就是死亡状态

if (Game.Instance == null) return;

计算玩家到敌人的距离,方法是使用向量,用敌人的当前坐标 减去 自己的当前坐标

Vector3 moveDir=Game.Instance.transform.position-transform.position;

 然后进行位移

transform.Translate(moveSpeed * Time.deltaTime * moveDir,Space.World);

 此时敌人背面朝着敌人移动,所以使用Bool判断玩家在左或者右

 如果玩家的坐标小于怪物的坐标,说明是在左侧,那么更改怪物的缩放值X

bool isRight=transform.position.x>Game.Instance.transform.position.x;
if (isRight) transform.localScale = new Vector3(-1, 1, 1);
else transform.localScale = new Vector3(1, 1, 1);

 

十二、子弹消灭怪物

1、怪物被攻击,减少血量

首先,把死亡的动画片段拖进两个敌人的动画控制器中

我选择使用触发 作为死亡的条件

//接触子弹
if (collision.gameObject.CompareTag("Bullet"))
{
	
	Destroy(collision.gameObject);//取消子弹穿透
	hp -= 1;
	if (hp == 0)
	{
		animator.SetTrigger("Death");
	}
}

如果血量为零,则播放死亡动画 

2、血量为0,播放死亡动画,销毁自己

#region 动画事件
	private void OnDeathAnimationEnd()
	{
		Destroy(gameObject);
	}
#endregion
	

 在死亡动画的最后一帧执行销毁

十三、鼠标指向为攻击方向 

使用屏幕坐标 到 世界坐标 

public new Camera camera;
		Vector3 mouseWorldPosition=camera.ScreenToWorldPoint(Input.mousePosition);

获取到的屏幕坐标,因为两个方法都需要,所以作为参数传进来 

十四、玩家生命值以及状态 

不适用UI;

把血条作为摄像机的子物体,防止血条跟随摄像机改变位置;

不让摄像机在玩家的子物体下,通过代码跟随

使用LateUpdate,让摄像机慢一帧追逐玩家

public Transform target;
private void LateUpdate()
{
	transform.position = target.position;
}

 此时,出现问题。

因为2d的,摄像机到玩家的距离是-10,运行后摄像机与玩家重合会看不见

修改代码,固定Z轴坐标

Vector3 pos=target.position;
pos.z = -10;
transform.position = pos;

因为血条是几张图片切换实现的

所以,在玩家身上公开一个变量HP,把Hp设置为字段,get无所谓,set设置切换 

[SerializeField]private int hp;
public int Hp 
{
	get => hp;
	set
	{ 
		hp = value;
	} 
}

然后引用血量图,做成一个数组 

public SpriteRenderer hpSpriteRenderer;
public Sprite[] spriteRenderers;

然后在字段中,把精灵图第几个赋值给血条上 

public int Hp 
{
	get => hp;
	set
	{ 
		hp = value;
		hpSpriteRenderer.sprite = hpSprites[hp];
	} 
}

初始化中,把数组长度作为血量值传进来

private void Awake()
{
	Instance = this;
	Hp = hpSprites.Length-1;
}

十五、怪物干掉玩家

怪物碰到玩家,掉血,玩家掉血为0则死亡

在此处遇到问题:怪物与玩家无法碰撞,碰撞代码逻辑未执行;

原因是刚体的数值未设置正确。

public class CameraController : MonoBehaviour
{
	public Transform target;
	private Game game1;
	
	private void Awake()
	{
		game1 = FindObjectOfType<Game>();
		if (game1 == null)
		{
			Debug.Log("没找到");
		}

	}
	private void LateUpdate()
	{
		int xue = game1.Hp;
		Debug.Log(xue);
		if (xue == 0)
		{
			return;
		}
		Vector3 pos=target.position;
		pos.z = -10;
		transform.position = pos;
	}
}

 

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//using UnityEngine.Windows;

public class Game : MonoBehaviour
{
	public static Game Instance;
    public Animator animator;
    public float movespeed;
    public SpriteRenderer spriteRenderer;
	public GameObject starPrefab;
	public Transform starShootPoint;

	public new Camera camera;

	[SerializeField]private int hp;
	public SpriteRenderer hpSpriteRenderer;
	public Sprite[] hpSprites;

	//CD
	private float shootCD = 0.1f;
	private float shootCDTimer;

	public int Hp 
	{
		get => hp;
		set
		{ 
			hp = value;
			hpSpriteRenderer.sprite = hpSprites[hp];
			if (hp == 0)
			{
				Dead();
			}
		} 
	}

	
	private void Awake()
	{
		Instance = this;
		Hp = hpSprites.Length-1;
	}
	private void Start()
	{
		spriteRenderer= gameObject.GetComponent<SpriteRenderer>();
		
	}

	// Update is called once per frame
	void Update()
    {
		Debug.Log(Hp);
		Vector3 mouseWorldPosition=camera.ScreenToWorldPoint(Input.mousePosition);
		//Debug.Log(mouseWorldPosition);
		Move(mouseWorldPosition); Shoot(mouseWorldPosition);

	}
   private void Move(Vector3 mouseWorldPosition)
    {
		animator.GetComponent<Animator>();
		float inputX = Input.GetAxis("Horizontal");
		float inputY = Input.GetAxis("Vertical");
		//修改动画
		bool isMove = inputX != 0 || inputY != 0;
		animator.SetBool("Move", isMove);
		//转向
		if (mouseWorldPosition.x > transform.position.x) spriteRenderer.flipX = false;
		else if (mouseWorldPosition.x < transform.position.x) spriteRenderer.flipX = true;

		//位移
		Vector3 pos =
				new Vector3(inputX * Time.deltaTime * movespeed,
							inputY * Time.deltaTime * movespeed,
							0);
		transform.Translate(pos, Space.Self);
	}
	private void Shoot(Vector3 mouseWorldPosition)
	{
		if (shootCDTimer > 0)
		{
			shootCDTimer-= Time.deltaTime;
			return;
		}
		if (Input.GetMouseButton(0))
		{
			shootCDTimer = shootCD;
			//实例化
			GameObject star=GameObject.Instantiate(starPrefab);
			star.transform.position = starShootPoint.position;
			Vector3 moveDir = (mouseWorldPosition - transform.position).normalized;
			star.GetComponent<Star>().Init(moveDir);
		}
	}

	internal void Hurt()
	{
		if (Hp <= 0) return;
		Hp -= 1;
	}
	private void Dead()
	{
		animator.SetTrigger("Dead");
	}
	private void DestroyPlayer()
	{
		Destroy(gameObject);
	}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Monster : MonoBehaviour
{
	public float moveSpeed;
	public int hp;
	public Animator animator;
	private void Update()
	{
		if (Game.Instance == null) return;
		Vector3 moveDir=Game.Instance.transform.position-transform.position;
		transform.Translate(moveSpeed * Time.deltaTime * moveDir,Space.World);
		bool isRight=transform.position.x>Game.Instance.transform.position.x;
		if (isRight) transform.localScale = new Vector3(-1, 1, 1);
		else transform.localScale = new Vector3(1, 1, 1);
	}
	private void OnTriggerEnter2D(Collider2D collision)
	{
		Debug.Log("碰撞对象标签:" + collision.gameObject.tag);
		if (hp == 0) return;
		//接触子弹
		if (collision.gameObject.CompareTag("Bullet"))
		{
			Debug.Log("子弹接触怪物了");
			Destroy(collision.gameObject);//取消子弹穿透
			hp -= 1;
			if (hp == 0)
			{
				animator.SetTrigger("Death");
			}
		}
		else
		{
			//接触玩家
			if (collision.gameObject.CompareTag("Player"))
			{
				Debug.Log("11");
				collision.gameObject.GetComponent<Game>().Hurt();
				Debug.Log("怪物接触玩家了");
			}
		}
		
	}
	
	#region 动画事件
	private void OnDeathAnimationEnd()
	{
		Destroy(gameObject);
	}
#endregion
	
}

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

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

相关文章

Codes 开源免费研发项目管理平台 2025年第一个大版本3.0.0 版本发布及创新的轻IPD实现

Codes 简介 Codes 是国内首款重新定义 SaaS 模式的开源项目管理平台&#xff0c;支持云端认证、本地部署、全部功能开放&#xff0c;并且对 30 人以下团队免费。它通过创新的方式简化研发协同工作&#xff0c;使敏捷开发更易于实施。并提供低成本的敏捷开发解决方案&#xff0…

Golang | 每日一练 (3)

&#x1f4a2;欢迎来到张胤尘的技术站 &#x1f4a5;技术如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 Golang | 每日一练 (3)题目参考答案map 实现原理hmapb…

Docker入门及基本概念

让我们从最基础的概念开始逐步理解。假设你已经准备好了docker 环境。 第一步&#xff0c;让我们先通过实际操作来看看当前系统中的镜像(images)和容器(containers)状态&#xff1a; docker images # 查看所有镜像 docker ps -a # 查看所有容器&#xff08;包括未运行…

设备唯一ID获取,支持安卓/iOS/鸿蒙Next(uni-device-id)UTS插件

设备唯一ID获取 支持安卓/iOS/鸿蒙(uni-device-id)UTS插件 介绍 获取设备唯一ID、设备唯一标识&#xff0c;支持安卓&#xff08;AndroidId/OAID/IMEI/MEID/MacAddress/Serial/UUID/设备基础信息&#xff09;,iOS&#xff08;Identifier/UUID&#xff09;&#xff0c;鸿蒙&am…

基于Springboot医院预约挂号小程序系统【附源码】

基于Springboot医院预约挂号小程序系统 效果如下&#xff1a; 小程序主页面 帖子页面 医生账号页面 留言内容页面 管理员主页面 用户管理页面 我的挂号页面 医生管理页面 研究背景 随着信息技术的飞速发展和互联网医疗的兴起&#xff0c;传统的医疗服务模式正面临着深刻的变…

如何手动设置u-boot的以太网的IP地址、子网掩码、网关信息、TFTP的服务器地址,并进行测试

设置IP地址 运行下面这条命令设置u-boot的以太网的IP地址&#xff1a; setenv ipaddr 192.168.5.9设置子网掩码 运行下面这条命令设置u-boot的以太网的子网掩码&#xff1a; setenv netmask 255.255.255.0设置网关信息 运行下面这条命令设置u-boot的网关信息&#xff1a; …

tortoiseGit的使用和上传拉取

tortoiseGit的使用和上传拉取 下载TortoiseGit 通过网盘分享的文件&#xff1a;tortoiseGit.zip 链接: https://pan.baidu.com/s/1EOT_UsM9_OysRqXa8gES4A?pwd1234 提取码: 1234 在电脑桌面新建文件夹并进入 右击鼠标 将网址复制上去 用户名和密码是在git注册的用户名和…

IDEA通过Maven使用JBLJavaToWeb插件创建Web项目

第一步&#xff1a;IDEA下载JBLJavaToWeb插件 File--->Settings--->Plugins--->Marketplace搜索: JBLJavaToWeb 第二步&#xff1a;创建普通Maven工程 第三步&#xff1a; 将普通Maven项目转换为Web项目

【新手初学】SQL注入之二次注入、中转注入

二次注入 一、概念 二次注入可以理解为&#xff0c;攻击者构造的恶意数据存储在数据库后&#xff0c;恶意数据被读取并进入到SQL查询语句所导致的注入。 二、原理 防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理&#xff0c;但在恶意数据插入到数据库时被处…

【第四节】C++设计模式(创建型模式)-Builder(建造者)模式

目录 引言 一、Builder 模式概述 二、Builder 模式举例 三、Builder 模式的结构 四、Builder 模式的实现 五、Builder 模式的优缺点 六、总结 引言 Builder 模式是一种创建型设计模式&#xff0c;旨在将复杂对象的构建过程与其表示分离。通过一步步构建对象&#xff0c;…

本地部署AI模型 --- DeepSeek(二)---更新中

目录 FAQ 1.Failed to load the model Exit code: 18446744072635812000 FAQ 1.Failed to load the model Exit code: 18446744072635812000 问题描述&#xff1a; &#x1f972; Failed to load the model Error loading model. (Exit code: 18446744072635812000). Unkn…

MariaDB 历史版本下载地址 —— 筑梦之路

MariaDB 官方yum源里面只有目前在维护的版本&#xff0c;而有时候对于老项目来说还是需要老版本的rpm包&#xff0c;国内很多镜像站都是同步的官方仓库&#xff0c;因此下载老版本也不好找&#xff0c;这里主要记录下从哪里可以下载到历史版本的MariaDB rpm包。 1. 官方归档网…

Qt中使用QPdfWriter类结合QPainter类绘制并输出PDF文件

一.类的介绍 1.QPdfWriter介绍 Qt中提供了一个直接可以处理PDF的类&#xff0c;这就是QPdfWriter类。 &#xff08;1&#xff09;PDF文件生成 支持创建新的PDF文件或覆盖已有文件&#xff0c;通过构造函数直接绑定文件路径或QFile对象&#xff1b; 默认生成矢量图形PDF&#…

使用 DeepSeek 生成流程图、甘特图与思维导图:结合 Typora 和 XMind 的高效工作流

在现代工作与学习中&#xff0c;可视化工具如流程图、甘特图和思维导图能够极大地提升信息整理与表达的效率。本文将详细介绍如何使用 DeepSeek 生成 Mermaid 文本&#xff0c;结合 Typora 快速生成流程图和甘特图&#xff0c;并通过 Markdown 格式生成思维导图&#xff0c;最终…

Oracle 连接报错:“ORA-12541:TNS:no listener ”,服务组件中找不到监听服务

一、 报错&#xff1a; navicat连接数据库报错&#xff1a;ORA-12541&#xff1a;TNS:no listener 二、排查问题 三、 解决问题 删除Oracle安装目录下选中的配置&#xff1a;listener.ora 及 listener*.bak相关的 cmd&#xff0c;用管理员打开 执行&#xff1a;netca 命…

一文详解U盘启动UEFI/Legacy方式以及GPT/MBR关系

对于装系统的老手而说一直想研究一下装系统的原理&#xff0c;以及面对一些问题时的解决思路&#xff0c;故对以前的方法进行原理上的解释&#xff0c;主要想理解其底层原理。 引导模式 MBR分区可以同时支持UEFI和Legacy引导&#xff0c;我们可以看一下微pe制作的启动盘&#…

计算机毕设-基于springboot的汽车配件销售管理系统的设计与实现(附源码+lw+ppt+开题报告)

博主介绍&#xff1a;✌多个项目实战经验、多个大型网购商城开发经验、在某机构指导学员上千名、专注于本行业领域✌ 技术范围&#xff1a;Java实战项目、Python实战项目、微信小程序/安卓实战项目、爬虫大数据实战项目、Nodejs实战项目、PHP实战项目、.NET实战项目、Golang实战…

嵌入式八股文(五)硬件电路篇

一、名词概念 1. 整流和逆变 &#xff08;1&#xff09;整流&#xff1a;整流是将交流电&#xff08;AC&#xff09;转变为直流电&#xff08;DC&#xff09;。常见的整流电路包括单向整流&#xff08;二极管&#xff09;、桥式整流等。 半波整流&#xff1a;只使用交流电的正…

C语言番外篇(3)------------>break、continue

看到我的封面图的时候&#xff0c;部分读者可能认为这和编程有什么关系呢&#xff1f; 实际上这个三个人指的是本篇文章有三个部分组成。 在之前的博客中我们提及到了while循环和for循环&#xff0c;在这里面我们学习了它们的基本语法。今天我们要提及的是关于while循环和for…

Mac下Python版本管理,适用于pyenv不起作用的情况

前言 声明&#xff1a;之前也在网上看到过可以使用pyenv来管理python版本&#xff0c;但由于作者的python安装路径实在是繁杂不堪&#xff0c;因此安装完成pyenv体验下来没有任何用处&#xff0c;但偶然发现vscode似乎可以看到各个python版本&#xff0c;因此写下这篇博客记录…