当前位置: 首页 > news >正文

【Unity学习心得】如何制作俯视角射击游戏

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

文章目录

  • 前言
  • 一、导入素材
  • 二、制作流程
    • 1.制作地图
    • 2.实现人物动画和移动脚本
    • 3.制作单例模式和对象池
    • 4.制作手枪pistol和子弹bullet和子弹壳bulletShell
    • 5.制作散弹枪shotgun
  • 总结


前言

俯视角射击游戏类似元气骑士那种,懂的都懂好吧。

本节课我们将要实现:制作地图,实现人物动画和移动脚本,制作单例模式和对象池,制作手枪pistol和子弹bullet和子弹壳bulletShell,制作散弹枪shotgun。


一、导入素材

素材链接: 、

https://o-lobster.itch.io/simple-dungeon-crawler-16x16-pixel-pack https://humanisred.itch.io/weapons-and-bullets-pixel-art-asset

二、制作流程

1.制作地图

        还是要用我们的老朋友Tilemap来做这种像素地图:

可以看到,我们创建了三个层级的Grid,记得在Sorting Layer分别给它们排好选择顺序,除了Ground的那一层以外其它记得要给 tilemap Collider2D和Composite Collider2D,Rigibody2D记得设置成静态,这些后面都要用到的。 

2.实现人物动画和移动脚本

绘制完简单地图后,我们就要开始导入人物素材了。公式化三件套:Sprite Renderer,Rb2D设置为Kinematic被动检测碰撞,别忘了锁Z轴旋转,Animator自己根据素材创建Idle,Walk

接下来创建PlayerController.cs给Player对象 

代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PlayerController : SingletonMono<PlayerController>
{public float speed = 3f;public bool enabledInput = true;private Rigidbody2D rb2d;private Animator anim;private Camera mainCamera;private Vector2 input;private Vector2 mousePosition;private new void Awake(){rb2d = GetComponent<Rigidbody2D>();anim = GetComponent<Animator>();mainCamera = Camera.main;}void Update(){if (enabledInput){mousePosition = mainCamera.ScreenToWorldPoint(Input.mousePosition);input.x = Input.GetAxisRaw("Horizontal");input.y = Input.GetAxisRaw("Vertical");rb2d.velocity = input.normalized * speed;if(input != Vector2.zero){anim.SetBool("isMoving", true);}else{anim.SetBool("isMoving", false);}if(mousePosition.x >= transform.position.x){transform.rotation = Quaternion.Euler(new Vector3(0f, 0f, 0f));}else{transform.rotation = Quaternion.Euler(new Vector3(0f, 180f, 0f));}}}}

这些大伙都应该懂了就获取X和Y上的Input,方向化后经典给rb2d设置velocity,然后根据鼠标位置判断玩家是否要沿Y轴翻转。

顺便给camera搞个cinemachine,让相机跟随玩家移动:

至此,我们实现了实现人物动画和移动脚本,接下来该开始制作单例模式和对象池模式了。

3.实现单例模式和对象池模式

单例模式大伙肯定也懂的,但这几天重温C#知识我突然就想用泛型<T>来做个泛型单例类,让所有MONOBehaviour的类都能继承:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour
{public static T _instance;public static T Instance{get{if(_instance == null){GameObject gameObject = new GameObject();_instance = gameObject.AddComponent<T>();DontDestroyOnLoad(gameObject);}return _instance;}}public void Awake(){if (_instance == null){_instance = (gameObject as T);DontDestroyOnLoad(gameObject);return;}if (this != _instance){DestroyImmediate(gameObject);return;}}
}

单例模式随便完成咯,接下来开始做对象池模式,很多人对对象池的编写还是比较陌生的,这里先写出主要思想:

在Unity中,实时创建(GameObject.Instantiate())和销毁游戏对象(GameObject.Destory ())会造成相当大的开销。

对于一些简单的,可以复用的物体,我们可以考虑用Enable/Disable来代替创建与销毁,这是因为Enable/Disable对性能的消耗搞更小。

我们可以采用对象池的思想实现这个功能。

所谓对象池,就是把所有相同的对象放在一个池子中,每当要使用到一个对象时,就从池子中找找看有没有之前创建过但现在空闲的物体可以直接拿来用,如果没有的话我们再创建物体并扔进池子里。

想要销毁一个物体,我们只需要标记其“空闲”即可,并不会直接销毁它。

 理解过后我们就可以编写一个脚本ObjectPool.cs

using System.Collections.Generic;
using UnityEngine;public class ObjectPool : SingletonMono<ObjectPool>
{private Dictionary<string, Queue<GameObject>> objectPool = new Dictionary<string, Queue<GameObject>>();private GameObject pool;private new void Awake(){objectPool = new Dictionary<string, Queue<GameObject>>();}//从对象池中获取对象public GameObject GetObject(GameObject prefab){GameObject gameObject;
//先从name判断是否存在对应的键值或者队列的内容数量为0if (!objectPool.ContainsKey(prefab.name) || objectPool[prefab.name].Count == 0){
//如果没有就新建从Object Pool -> Child Pool -> PrefabgameObject = GameObject.Instantiate(prefab);PushObject(gameObject);if (pool == null)pool = new GameObject("ObjectPool");GameObject childPool = GameObject.Find(prefab.name + "Pool");if (!childPool){childPool = new GameObject(prefab.name + "Pool");childPool.transform.SetParent(pool.transform);}gameObject.transform.SetParent(childPool.transform);}gameObject = objectPool[prefab.name].Dequeue();gameObject.SetActive(true); //可视化return gameObject;}
//从对象池中取出对象public void PushObject(GameObject prefab){
//要保证名字和objectPool的名字相等,因此我们要用空的字符串取代Unity新建游戏对象会有个"(Clone)"string name = prefab.name.Replace("(Clone)", string.Empty);if (!objectPool.ContainsKey(name))objectPool.Add(name, new Queue<GameObject>());objectPool[name].Enqueue(prefab); //创建该prefab名字的队列并让prefab入栈prefab.SetActive(false);//默认为不可见}
}

4.制作手枪pistol和子弹bullet和子弹壳bulletShell

终于来到了重点制作这些东西,当一些事物存在共性的时候我们会想使用抽象类来减少代码的耦合度,同样这些手枪火箭筒啥的都输入枪,我们可以创建一个Gun的Prefab,让这些枪都成为Gun的Varient。

其中muzzle是子弹发射位置,bulletshell是生成弹壳的位置。

我们Varient第一个目标是pistol手枪,如图我们给它sprite和animator

制作两个动画并连接即可

别忘了动态调整muzzle和bulletshell的位置

回到脚本当中,新建一个基类脚本Gun.cs,我们打算让所有的枪械类都继承这个脚本:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Gun : MonoBehaviour
{public GameObject bulletPrefab;public GameObject bulletShellPrefab;public float interval = 0.5f;protected Animator animator;protected Camera mainCamera;protected Transform muzzleTrans;protected Transform bulletShellTrans;protected float flipY;protected Vector2 mousePos;protected Vector2 direction;private float timer;protected virtual void Start(){animator = GetComponent<Animator>();mainCamera = Camera.main;muzzleTrans = transform.Find("Muzzle"); ;bulletShellTrans = transform.Find("BulletShell");flipY = transform.localScale.y;}protected virtual void Update(){mousePos = mainCamera.ScreenToWorldPoint(Input.mousePosition);if(mousePos.x >= transform.position.x){transform.localScale = new Vector3(transform.localScale.x, flipY, 1);}else{transform.localScale = new Vector3(transform.localScale.x, -flipY, 1);}Shoot();}//控制枪械发射间隔protected virtual void Shoot(){direction = (mousePos - new Vector2(transform.position.x, transform.position.y)).normalized;transform.right = direction;if (timer != 0){timer -= Time.deltaTime;if (timer < 0)timer = 0;}if (Input.GetKeyDown(KeyCode.Mouse0)) //按下鼠标左键{if(timer == 0){timer = interval;Fire();}}}
//控制开火protected virtual void Fire(){animator.SetTrigger("Shoot");
//生成子弹预制体GameObject bullet = ObjectPool.Instance.GetObject(bulletPrefab);bullet.transform.position = muzzleTrans.position;
//发射子弹角度偏差float angle = UnityEngine.Random.Range(-5f, 5f);bullet.GetComponent<Bullet>().SetSpeed(Quaternion.AngleAxis(angle , Vector3.forward) * direction);
//生成子弹壳预制体GameObject bulletShell = ObjectPool.Instance.GetObject(bulletShellPrefab);bulletShell.transform.position = bulletShellTrans.position;bulletShell.transform.rotation = bulletShellTrans.rotation;}
}

然后我们再给pistol添加同名脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Pistol : Gun 
{}

 写到这里我们注意到还要接着制作子弹Bullet和子弹壳BulletShell的预制体:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Bullet : MonoBehaviour
{public float bulletSpeed = 15f;public GameObject explosionPrefab;private Rigidbody2D rb2d;private void Awake(){rb2d = GetComponent<Rigidbody2D>();}
//在这里,我们用通过给子弹的rb2d设置速度velocity控制其移动速度和方向public void SetSpeed(Vector2 direction){rb2d.velocity = bulletSpeed * direction;}
//最后当子弹碰到墙壁时对象池回收该对象并生成爆炸对象private void OnTriggerEnter2D(Collider2D other){if (other.gameObject.layer == LayerMask.NameToLayer("Wall")){GameObject exp = ObjectPool.Instance.GetObject(explosionPrefab);exp.transform.position = transform.position;ObjectPool.Instance.PushObject(gameObject);}}}

新建一个bullet的prefab

新建一个Explosion的prefab

 

给它制作一个爆炸的动画

在它的同名脚本中回收爆炸游戏对象:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Explosion : MonoBehaviour
{private Animator anim;private AnimatorStateInfo info;private void OnEnable(){anim = GetComponent<Animator>();}private void Update(){info = anim.GetCurrentAnimatorStateInfo(0);if(info.normalizedTime >= 1){ObjectPool.Instance.PushObject(gameObject);}}}

 同样的操作也给bulletshell

同名脚本中:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class BulletShell : MonoBehaviour
{public float speed;public float stopTime = 0.5f;public float fadeSpeed = 0.01f;private Rigidbody2D rb2d;private SpriteRenderer sprite;void Awake(){rb2d = GetComponent<Rigidbody2D>();sprite = GetComponent<SpriteRenderer>();}private void OnEnable(){float angel = Random.Range(-30f, 30f);rb2d.velocity = Quaternion.AngleAxis(angel, Vector3.forward) * Vector3.up * speed;sprite.color = new Color(sprite.color.r, sprite.color.g, sprite.color.b, 1);rb2d.gravityScale = 3;StartCoroutine(Stop());}private IEnumerator Stop(){yield return new WaitForSeconds(stopTime);rb2d.velocity = Vector2.zero;rb2d.gravityScale = 0;
//通过spriterenderer的透明度来渐变颜色淡出直到0while (sprite.color.a > 0){sprite.color = new Color(sprite.color.r, sprite.color.g, sprite.color.g, sprite.color.a - fadeSpeed);yield return new WaitForFixedUpdate();}
//然后回收该游戏对象ObjectPool.Instance.PushObject(gameObject);}
}

5.制作散弹枪shotgun

有了前车之鉴,我们就可以照着葫芦画瓢。还是老配方先生成varient:

别忘了调整muzzle和bulletshell的位置。

创建同名脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class ShotGun : Gun
{public int bulletNum = 3;public float bulletAngle = 15f;
//我们只需要重写fire脚本protected override void Fire(){animator.SetTrigger("Shoot");int med = bulletNum / 2;for (int i = 0; i < bulletNum; i++){GameObject bullet = ObjectPool.Instance.GetObject(bulletPrefab);bullet.transform.position = muzzleTrans.position;if (bulletNum % 2 == 1){
//这段代码的意思是如果有奇数个bulletnum那给这个bulletshell设置的角度应该是bulletAngle * (i - //med)bullet.GetComponent<Bullet>().SetSpeed(Quaternion.AngleAxis(bulletAngle * (i - med), Vector3.forward) * direction);}else if(bulletNum % 2 == 0){
//这段代码的意思是如果有偶数个bulletnum那给这个bulletshell设置的角度应该是bulletAngle * (i - //med) + bulletAngle / 2fbullet.GetComponent<Bullet>().SetSpeed(Quaternion.AngleAxis(bulletAngle * (i - med) + bulletAngle / 2f, Vector3.forward) * direction);}}GameObject shell = ObjectPool.Instance.GetObject(bulletShellPrefab);shell.transform.position = bulletShellTrans.transform.position;shell.transform.rotation = bulletShellTrans.transform.rotation;}
}

可以看到奇数个子弹:

偶数个子弹:你看是不是还要再加偏转角的一半即bulletAngle / 2

最后我们还想要根据键盘的Q和E键切换武器,回到playerController.cs当中:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PlayerController : SingletonMono<PlayerController>
{public float speed = 3f;public bool enabledInput = true;public GameObject[] guns;private int currentGun;private Rigidbody2D rb2d;private Animator anim;private Camera mainCamera;private Vector2 input;private Vector2 mousePosition;private new void Awake(){rb2d = GetComponent<Rigidbody2D>();anim = GetComponent<Animator>();mainCamera = Camera.main;guns[0].SetActive(true);}void Update(){if (enabledInput){SwitchGun();mousePosition = mainCamera.ScreenToWorldPoint(Input.mousePosition);input.x = Input.GetAxisRaw("Horizontal");input.y = Input.GetAxisRaw("Vertical");rb2d.velocity = input.normalized * speed;if(input != Vector2.zero){anim.SetBool("isMoving", true);}else{anim.SetBool("isMoving", false);}if(mousePosition.x >= transform.position.x){transform.rotation = Quaternion.Euler(new Vector3(0f, 0f, 0f));}else{transform.rotation = Quaternion.Euler(new Vector3(0f, 180f, 0f));}}}
//切换武器private void SwitchGun(){if (Input.GetKeyDown(KeyCode.Q)){guns[currentGun].SetActive(false);if(--currentGun < 0){currentGun = guns.Length - 1;}guns[currentGun].SetActive(true);}else if (Input.GetKeyDown(KeyCode.E)){guns[currentGun].SetActive(false);if (++currentGun > guns.Length - 1){currentGun = 0;}guns[currentGun].SetActive(true);}}
}

给这两个武器添加上去(其它三个是下一期要讲的先别在意):


总结

最后的效果如图所示:

相关文章:

【Unity学习心得】如何制作俯视角射击游戏

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、导入素材二、制作流程 1.制作地图2.实现人物动画和移动脚本3.制作单例模式和对象池4.制作手枪pistol和子弹bullet和子弹壳bulletShell5.制作散弹枪shotgun总…...

【资料分析】常见的坑

in 比较或计数类问题 差别大的基期比较&#xff0c;可以直接用现期进行比较 注意单位可能不同&#xff01; 注意顺序是从小到大还是从大到小 以及老问题&#xff0c;名字本身就叫XX增量&#xff0c;XX增加值&#xff0c;而非还要另外去算的东东 给出的图表可能是不完整的 2…...

GitLab权限及设置

之前很少关注这些&#xff0c;项目的权限&#xff0c;一般由专门的管理人员设置。 但自己创建的项目自己可以设置权限。下面是一些笔记。 GitLab中用户权限_gitlab 权限-CSDN博客 开发中遇到要将自己这块的代码上传到Git&#xff0c;由其他组的同事拉取后继续开发。上传代码后…...

算法练习题24——查找杨辉三角中的组合数

题目描述 杨辉三角中的每个元素是一个组合数。第 ( i ) 行的第 ( j ) 个元素表示组合数 ( C(i, j) ) &#xff0c;即从 ( i ) 个元素中选 ( j ) 个元素的组合方式。已知一个正整数 ( N )&#xff0c;要求在杨辉三角中找到这个数&#xff0c;并输出它在杨辉三角中的具体位置。位…...

string类的模拟实现

实现string的模拟实现分为三个文件&#xff0c;分别为&#xff1a;string.h、sting.cpp、test.cpp string.h 其中包含一些短小常用的函数的实现&#xff0c;头文件&#xff0c;函数的声明 #include<iostream> #include<string> #include<assert.h>using n…...

如何训练机器学习力场

机器学习力场&#xff08;MLFF&#xff09;的训练主要依赖于通过量子力学计算生成的高质量训练数据集&#xff0c;并利用不同的机器学习算法来拟合分子系统中的势能面&#xff08;Potential Energy Surface, PES&#xff09;和原子间作用力。这种训练过程包括数据准备、特征提取…...

AI创作新手册:精通Prompt提示词的提问策略

文章目录 &#x1f34a;AI创作核心&#xff1a;提示词 Prompt 的重要性1. 什么是提示词工程&#xff1f;1.1 提示词的作用原理1.2 提示词工程师的薪资与行业前景1.3 提示词工程的适用性 2. 提示词的编写技巧3. 常见的提示词框架3.1 CO-STAR 框架3.2 BORKE 框架 4. 提示词的实际…...

gingivitis

gingivitis 牙龈炎 1&#xff09;这个是啥不知道 2&#xff09;七叶莲片 3&#xff09;甲硝唑芬布芬胶囊 4&#xff09;盐酸左氧氟沙星胶囊 5&#xff09;纳珍 开始学习记录医生开的药。日常备药记录一下。【不要乱吃药哈】...

开源 AI 智能名片小程序:开启内容营销新境界

摘要&#xff1a;本文深入探讨了在当今数字化时代&#xff0c;内容营销的重要性以及如何实现让用户主动找你的最佳效果。通过引入开源 AI 智能名片小程序这一创新工具&#xff0c;阐述了其在明确目标用户群体、迎合用户需求痛点和打造风格特色方面的独特优势&#xff0c;为企业…...

p12docker 进入容器的命令和拷贝的命令

进入当前正在运行的容器 第一种方式是执行docker exec -it 8d57ffda7a29 /bin/bash这个时候可以根据docker容器的id进入到指定id的容器当中***(这个是比较常用的)*** 老师的笔记 第二种方式是docker attach 8d57ffda7a29 这里还是直接引用老师的笔记吧 从容器内部拷贝文…...

代码随想录Day 45|leetcode题目:115.不同的子序列、583. 两个字符串的删除操作、72. 编辑距离

提示&#xff1a;DDU&#xff0c;供自己复习使用。欢迎大家前来讨论~ 文章目录 题目题目一&#xff1a; 115.不同的子序列解题思路&#xff1a;1. 确定dp数组&#xff08;dp table&#xff09;以及下标的含义2. 确定递推公式3. dp数组如何初始化4. 确定遍历顺序5. 举例推导dp数…...

浮点数在内存中的存储详解(超详细)

目录 1. 浮点数存储规则 2. IEEE754规定&#xff1a; 3. 关于M的说明&#xff1a; 4. 关于E的说明&#xff1a; 5. 关于S的说明&#xff1a; 6.浮点数从内存中取出&#xff08;三种情况&#xff09; 情况1&#xff1a;E不全为0或不全为1 情况2&#xff1a;E全为0 情况3&a…...

Maven下载安装

下载 下载地址&#xff1a;Maven – Download Apache Maven 选择合适的版本进行下载 windows&Linux安装 1, 解压apache-maven-3.6.1.rar即安装完成 2&#xff0c; 配置环境变量MAVEN_HOME为安装路径&#xff0c;并将MAVEN_HOME的bin目录配置到PATH下 3&#xff0c;…...

Qt:Q_GLOBAL_STATIC实现单例(附带单例使用和内存管理)

前言 本文主要写Q_GLOBAL_STATIC实现单例以及单例的释放&#xff0c;网上很多教程只有单例的创建&#xff0c;但是并没有告诉我们单例的内存管理&#xff0c;这就很头疼。 正文 使用 Qt 的 Q_GLOBAL_STATIC // Singleton.h #ifndef SINGLETON_H #define SINGLETON_H#includ…...

URL.createObjectURL 与 FileReader:Web 文件处理两大法宝的对比

URL.createObjectURL 与 FileReader&#xff1a;Web 文件处理两大法宝的对比 在Web开发中&#xff0c;处理用户上传的文件是一项常见且重要的任务。URL.createObjectURL和FileReader是两种常用于此目的的Web API&#xff0c;它们各有特点&#xff0c;适用于不同的场景。本文将…...

零基础考过软考信息系统项目管理师经验分享

选择适合的课程&#xff1a;如果你是零基础&#xff0c;建议找一些专门针对新手的课程&#xff0c;讲解通俗易懂。 刷题至关重要&#xff1a;软考的题库很庞大&#xff0c;多做题是必须的。 做好笔记和复习&#xff1a;上课时要做好笔记&#xff0c;课后及时复习&#xff0c;…...

机器学习课程学习周报十二

机器学习课程学习周报十二 文章目录 机器学习课程学习周报十二摘要Abstract一、机器学习部分1.1 fGAN: General Framework of GAN1.2 CycleGAN1.3 Auto-Encoder1.4 概率论复习&#xff08;一&#xff09; 总结 摘要 本周的学习内容涵盖了fGAN框架、CycleGAN、自编码器以及概率…...

python多线程程序设计 之二

python多线程程序设计 之二 线程同步机制lock对象acquirereleaselocked RLock对象条件变量条件变量应用实列实列代码 线程同步机制 lock对象 原语锁是一种同步原语&#xff0c;锁定时不属于特定线程。在Python中&#xff0c;它是目前可用的最低级别的同步原语&#xff0c;由_…...

k8s用StatefulSet部署redis

redis-config.yaml &#xff08;配置文件&#xff09; apiVersion: v1 kind: ConfigMap metadata:name: redis-config data:redis.conf: |# Redis general configuration​ bind 0.0.0.0 ​ protected-mode no ​ port 6379 ​ dir /data ​ appendonly yesse…...

flink on k8s

1.修改host文件 vi /etc/hosts 添加如下内容 这样搭集群的时候就不用记ip了 #::1 localhost localhost.localdomain localhost6 localhost6.localdomain6127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 165.154.221.97 tlb-001 k8s01 k8s-m…...

Java集合(八股)

这里写目录标题 Collection 接口List 接口ArrayList 简述 1. ArrayList 和 LinkedList 区别&#xff1f;⭐️⭐️⭐️⭐️2. ArrayList 和 Array 的区别&#xff1f;⭐️⭐️⭐️ArrayList 和 Vector 区别&#xff1f;⭐️⭐️ArrayList 的扩容机制&#xff1f;⭐️⭐️⭐️ Qu…...

python+adb

#!/usr/bin/python env # -*- coding: utf-8 -*- import os import sys import subprocess from time import sleepimport logging logging.basicConfig(levellogging.DEBUG) class ScreenCapture():def get_screen_size(self):"""获取手机分辨率""&q…...

AIGC文本生成

文本生成是一种人工智能技术&#xff0c;它基于深度学习算法&#xff0c;根据给定的提示信息创作出有逻辑、连贯的文本内容。 文本生成所需的输入&#xff08;提示或Prompt&#xff09;可以是简单的关键词、一句话概述或是更复杂的指令和上下文信息。文本生成模型通过分析大量…...

系统架构设计师教程 第5章 5.4 软件测试 笔记

5.4 软件测试 5.4.1 测试方法 ★★★★★ 软件测试方法的分类有很多种&#xff0c; 以测试过程中程序执行状态为依据可分为静态测试 (Static Testing,ST) 和动态测试 (Dynamic Testing,DT); 以具体实现算法细节和系统内部结构的相关情况为根据可分黑盒测试、白盒测试和灰盒测…...

ASPICE评估全流程解析:汽车软件开发组织能力的系统化评估

ASPICE&#xff08;Automotive SPICE&#xff09;评估的过程是一个系统化和详尽的流程&#xff0c;旨在评估汽车软件开发组织在软件开发过程方面的能力。 以下是ASPICE评估过程的详细描述&#xff1a; 1. 评估准备阶段 a. 确定评估目标和范围 明确评估的目标&#xff0c;如评…...

合并RAR分卷压缩包

因为文件压缩之后体积仍然过大&#xff0c;大家可能会选择进行分卷压缩&#xff0c;那么rar分卷压缩包之后如何合并成一个压缩包文件呢&#xff1f;今天我们来学习rar分卷压缩包&#xff0c;合并成一个的方法。 最基础的方法就是将分卷压缩包解压出来之后&#xff0c;再将文件…...

重生奇迹MU 想去哪就去哪玩 轻松玩转翅膀属性

在重生奇迹MU这个游戏中&#xff0c;玩家需要扫荡各种怪物&#xff0c;勇斗BOSS&#xff0c;与其他玩家激战。在这个充满冒险的旅程中&#xff0c;翅膀是最重要的装备之一。拥有一个属性强大的翅膀&#xff0c;代表着玩家的成长与强大。穿上它&#xff0c;加速你的冒险之旅吧&a…...

Lnux-gcc/g++使用

目录 1.gcc/g介绍 1.什么是 gcc / g 2.gcc/g指令格式 2. gcc / g 实现程序翻译的过程 1.预处理(进行宏替换) 2.编译(生成汇编&#xff09; 3.汇编&#xff08;生成机器可识别代码&#xff09; 4.连接&#xff08;生成可执行文件或库文件&#xff09; 1.gcc/g介绍 1.什么…...

用Python创建一个键盘输入捕获程序

目录 简介 环境准备 安装依赖 项目结构 编写代码 1. 导入库 2. 定义回调函数 3. 启动键盘监听器 4. 整合代码 运行程序 结论 简介 在这篇博文中,我们将探索如何使用Python编写一个简单的键盘输入捕获程序。这个程序将实时捕获用户的键盘输入并在控制台中显示出来。…...

Mybatis中Like模糊查询三种处理方式

目录 Mybatis中Like模糊查询三种处理方式 1.通过单引号拼接${} 1&#xff09;mapper接口 2&#xff09;Mapper.xml 3&#xff09;测试代码 4) 测试结果 2.通过concat()函数拼接(个人推荐使用这种) 1&#xff09;mapper接口 2&#xff09;Mapper.xml 3&#xff09;测试代码 4) 测…...