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

文章目录

​​​​​​​

目录

一、游戏逻辑与设计

二、游戏场景搭建

1.游戏背景

2.玩家模块

3.敌人模块

三、游戏代码模块

1.小鸟(包括特殊小鸟)

2.敌人(包括小猪、木块等障碍物)

3.游戏管理器

4.地图选择

5.关卡选择

6.暂停界面

四、场景间的组合搭配

五、游戏的发布

总结


前言

这个游戏算是本Unity菜鸡真正意义上从头到尾跟着教程,一步步踩坑到完成的游戏了。

写这篇博客主要是用于总结学习该游戏项目,嗯,下面开始吧。

(PS:这个游戏是跟着siki学院的愤怒的小鸟教程做的,b站地址:【SiKi学院Unity】Unity初级案例 - 愤怒的小鸟_哔哩哔哩_bilibili

官网的课程资料、源码及笔记下载地址:http:// http://www.sikiedu.com/course/134)


提示:以下是本篇文章正文内容,下面案例可供参考

一、游戏逻辑与设计

本款游戏作为一个入门级的Unity项目,它的实现逻辑并不复杂,首先把游戏场景分为三个:

  • 加载界面
  • 关卡选择界面
  • 游戏界面

其中,加载界面和关卡选择界面,可以选择Unity自带的UI功能进行实现,也就是用Image来显示背景图片和各个按键等组件布局;

关于游戏界面,例如小鸟、小猪、木块、背景和草地等对象,这里是通过新建一个空物体,然后添加图片的形式进行实现,然后例如暂停窗口、胜利窗口、失败窗口就可以使用UI进行实现,把所有窗口放在一个Canvas里,然后默认取消显示,当达成目标功能时(例如关卡胜利、失败,点击暂停按键等),就将它对应的组件设置为激活状态,这样就达成了界面显示的功能;

然后是关于游戏的逻辑了,由于愤怒的小鸟它主要的游戏核心,其实就是——碰撞。

所以在这里,绝大部分的游戏逻辑其实都是通过碰撞和触发进行实现,我们把小鸟、小猪、障碍物等组件加上刚体和碰撞器,然后根据需求针对特殊的个体组件添加触发器,然后我们可以通过判断碰撞和触发的状态,来决定是否发生了游戏对象的逻辑碰撞,然后选择执行对应代码。

二、游戏场景搭建

1.游戏背景

游戏背景就是由几个图片(背景图片、地面、草丛)拼接而成,并给地面添加一个碰撞器(BoxCollider2D),以便小鸟和敌方单位不会一直落下。

2.玩家模块

玩家模块由以下几个对象组成:

  • 弹弓左部
  • 弹弓右部
  • 当前小鸟
  • 预备小鸟

对于小鸟,需要添加其刚体与碰撞器组件,并根据不同小鸟的大小,调整碰撞范围;

关于小鸟的“弹弓模拟”操作,这里使用了Spring Joint2D组件进行实现,中心点为小鸟中心,左右两个点分别设置在左弹弓和右弹弓上的合适位置,然后可以根据情况调整距离和频率,这样就可以初步实现类似弹弓弹簧的效果(目前还无法飞出);

接下来关于拖拽小鸟,形成画线的功能,这里使用LineRender进行画线操作,在脚本中,当可以进行画线操作时(当前小鸟已经激活,但是还没有飞行),设置其每一段Line的两点并画线;

    /// <summary>/// 划线/// </summary>public void Line(){right.enabled = true;left.enabled = true;right.SetPosition(0, rightPos.position);right.SetPosition(1, this.transform.position);left.SetPosition(0, leftPos.position);left.SetPosition(1, this.transform.position);}

3.敌人模块

敌人模块就是靠自己进行发挥了,针对不同的物体对象(小猪、木块、木条、铁块、柱子...)设置其刚体和碰撞器(主要是碰撞体大小),然后设置其血量(最小和最大承受速度),受伤图片等等其它的变量,然后根据自己的想象和设计,设计出不同的关卡;

三、游戏代码模块

1.小鸟(包括特殊小鸟)

通过控制canMove来区分当前小鸟和等待小鸟的状态,当该小鸟为激活状态时,canMove为true,可以执行Line(弹弓画线)和Fly(飞行过程)方法,进行弹弓的操控与飞行操作,当飞行状态时,重新置canMove为false(防止重复操作),其中控制小鸟的操作由鼠标来执行,在代码中即是,在OnMouseUp、OnMouseDown来进行监听;

当飞行过程中,可以通过点击鼠标调用ShowSkill方法执行特殊小鸟的技能操作,这个方法可以写成虚方法,在后面的特殊小鸟中,进行重写并调用;当该小鸟飞出后,通过延时调用Next方法,重新销毁当前小鸟,并激活下一个等待小鸟;

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;public class Bird : MonoBehaviour
{public bool isClick = false;public float maxDis = 1.5f;[HideInInspector]public SpringJoint2D sp;protected Rigidbody2D rg;public LineRenderer right;public LineRenderer left;public Transform rightPos;public Transform leftPos;public GameObject boom;protected TestMyTrail myTrail;[HideInInspector]public bool canMove = false;public float amooth = 3;public AudioClip select;public AudioClip fly;private bool isFlay;public bool isReleased = false;public Sprite hurt;public SpriteRenderer render;public void Awake(){sp = GetComponent<SpringJoint2D>();rg = GetComponent<Rigidbody2D>();render = GetComponent<SpriteRenderer>();myTrail = GetComponent<TestMyTrail>();}private void OnMouseDown(){if (canMove){AudioPlay(select);isClick = true;rg.isKinematic = true;}}private void OnMouseUp(){if (canMove){isClick = false;rg.isKinematic = false;Invoke("Fly", 0.1f);right.enabled = false;left.enabled = false;canMove = false;}}public void Update(){//如果点击的是UI界面,则直接返回if (EventSystem.current.IsPointerOverGameObject()){return;}if (isClick){this.transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition);this.transform.position += new Vector3(0, 0, -Camera.main.transform.position.z);if(Vector3.Distance(this.transform.position,rightPos.position) > maxDis){Vector3 pos = (this.transform.position - rightPos.position).normalized;pos *= maxDis;this.transform.position = pos + rightPos.position;}Line();}//相机跟随CamereMove();//飞行时,点击左键if (isFlay){if (Input.GetMouseButtonDown(0)){ShowSkill();}}}public void CamereMove(){float posX = this.transform.position.x;Camera.main.transform.position = Vector3.Lerp(Camera.main.transform.position, new Vector3(Mathf.Clamp(posX,0,17),Camera.main.transform.position.y,Camera.main.transform.position.z), amooth*Time.deltaTime);}public void Fly(){isReleased = true;isFlay = true;AudioPlay(fly);myTrail.StartTrail();sp.enabled = false;Invoke("Next", 3);}/// <summary>/// 划线/// </summary>public void Line(){right.enabled = true;left.enabled = true;right.SetPosition(0, rightPos.position);right.SetPosition(1, this.transform.position);left.SetPosition(0, leftPos.position);left.SetPosition(1, this.transform.position);}public virtual void Next(){Gamemanager._instance.birds.Remove(this);Destroy(this.gameObject);Instantiate(boom, this.transform.position, Quaternion.identity);Gamemanager._instance.NextBird();}public void OnCollisionEnter2D(Collision2D collision){isFlay = false;myTrail.ClearTrail();}public void AudioPlay(AudioClip clip){AudioSource.PlayClipAtPoint(clip,this.transform.position);}public virtual void ShowSkill(){isFlay = false;}public void Hurt(){render.sprite = hurt;}
}

剩下的黄鸟(加速)、绿鸟(回旋)和黑鸟(爆炸),就是继承了redbird这个类,然后根据需求,重写ShowSkill方法即可;

public class YellowBird : Bird
{public override void ShowSkill(){base.ShowSkill();rg.velocity *= 2;}
}
public class GreenBird : Bird
{public override void ShowSkill(){base.ShowSkill();Vector3 speed = rg.velocity;speed.x *= -1;rg.velocity = speed;}
}

其中,BlackBird因为要通过触发判断爆炸效果,并且爆炸后直接进行销毁,所以要额外多写几个方法进行实现

public class BlackBird : Bird
{public List<Pig> blocks = new List<Pig>();/// <summary>/// 进入触发区域/// </summary>/// <param name="collision"></param>private void OnTriggerEnter2D(Collider2D collision){if(collision.gameObject.tag == "Enemy"){blocks.Add(collision.gameObject.GetComponent<Pig>());}}/// <summary>/// 退出触发区域/// </summary>/// <param name="collision"></param>private void OnTriggerExit2D(Collider2D collision){if (collision.gameObject.tag == "Enemy"){blocks.Remove(collision.gameObject.GetComponent<Pig>());}}public override void ShowSkill(){base.ShowSkill();if( blocks!=null && blocks.Count > 0){for(int i = 0; i < blocks.Count; i++){blocks[i].Dead();}}OnClear();}public void OnClear(){rg.velocity = Vector3.zero;Instantiate(boom, this.transform.position, Quaternion.identity);render.enabled = false;GetComponent<CircleCollider2D>().enabled = false;myTrail.ClearTrail();}public override void Next(){Gamemanager._instance.birds.Remove(this);Destroy(this.gameObject);Gamemanager._instance.NextBird();}
}

2.敌人(包括小猪、木块等障碍物)

这里主要就是调整敌方的“血量”,但是这里的血量并不是一点一点扣除的,而是进行一个判断,当该物体碰撞的对象是Player(小鸟),并且当

  • 碰撞速度>maxspeed时,敌方死亡
  • minspeed<碰撞速度<maxspeed时,敌方调整为受伤状态
  • 碰撞速度<minspeed时,敌方不受伤

然后写一个Dead方法,用于处理死亡后的操作(播放死亡音乐、爆炸特效、销毁物体等)

public class Pig : MonoBehaviour
{public float maxSpeed = 10;public float minSpeed = 4;private SpriteRenderer render;public Sprite hurt;public GameObject boom;public GameObject score;public bool isPig = false;public AudioClip hurtClip;public AudioClip dead;public AudioClip birdCollision;private void Awake(){render = GetComponent<SpriteRenderer>();}private void OnCollisionEnter2D(Collision2D collision){if(collision.gameObject.tag == "Player"){AudioPlay(birdCollision);collision.transform.GetComponent<Bird>().Hurt();}if(collision.relativeVelocity.magnitude > maxSpeed){Dead();}else if( collision.relativeVelocity.magnitude>minSpeed && collision.relativeVelocity.magnitude < maxSpeed){AudioPlay(hurtClip);render.sprite = hurt;}}public void Dead(){if (isPig){Gamemanager._instance.pigs.Remove(this);}AudioPlay(dead);Destroy(this.gameObject);Instantiate(boom, this.transform.position, Quaternion.identity);GameObject go = Instantiate(score, this.transform.position + new Vector3(0,0.5f,0), Quaternion.identity);Destroy(go, 1.5f);}public void AudioPlay(AudioClip clip){AudioSource.PlayClipAtPoint(clip, this.transform.position);}
}

3.游戏管理器

游戏管理器用于控制游戏逻辑,这里定义两个列表,用于存储所有小鸟和所有小猪,

在开始时,激活小鸟列表的第一个对象为当前小鸟,其它小鸟等待,当当前小鸟飞行完成后,调用Next方法,删除已发射小鸟,并激活下一个等待小鸟进行操纵;

当小鸟数量=0或是小猪数量=0时,进行逻辑判断

  • 当小猪数量=0时,胜利!
  • 当小猪数量<0,并且小鸟数量=0时,失败!

然后显示对应的UI界面,其中当胜利时,获得的星星个数为 当前剩余小鸟个数+1,以此逻辑进行得分判断,并通过Unity自带的PlayerPrefs类,以键值对的形式(key为当前的关卡名称),进行数据的存储;

剩下的就是定义一些UI按键的绑定方法,例如

  • Next     下一关
  • SaveData   当游戏胜利时,保存当前关卡得分(取最大)
  • Home    返回游戏首页
  • RePlay   重新开始当前游戏关卡
public class Gamemanager : MonoBehaviour
{public List<Bird> birds;public List<Pig> pigs;public static Gamemanager _instance;public Vector3 originPos; //初始位置public GameObject win;public GameObject lose;public GameObject[] starts;public int starsNum = 0;public int totalNum = 5;public void Start(){Initialized();}public void Awake(){_instance = this;originPos = birds[0].transform.position;}/// <summary>/// 初始化小鸟/// </summary>private void Initialized(){for(int i = 0; i < birds.Count; i++){if (i == 0)//第一只小鸟{birds[0].transform.position = originPos;birds[i].enabled = true;birds[i].sp.enabled = true;birds[i].canMove = true;}else{birds[i].enabled = false;birds[i].sp.enabled = false;}}}public void NextBird(){if (pigs.Count > 0){if (birds.Count > 0){//下一只小鸟Initialized();}else{//输了lose.SetActive(true);}}else{//赢了win.SetActive(true);}}public void ShowStarts(){StartCoroutine("show");//Debug.Log("胜利!!!" + birds.Count);}IEnumerator show(){for (; starsNum < birds.Count + 1; starsNum++){if(starsNum >= starts.Length){break;}yield return new WaitForSeconds(0.2f);//Debug.Log(starts[i].name);starts[starsNum].SetActive(true);}}public void RePlay(){SaveData();SceneManager.LoadScene(2);}public void Home(){SaveData();SceneManager.LoadScene(1);}public void Next(){SaveData();string currentLevel = PlayerPrefs.GetString("nowLevel");Debug.Log(currentLevel);int num = int.Parse(currentLevel.Substring(5,1)) + 1;string nextLevel = currentLevel.Substring(0, currentLevel.Length - 1) + System.Convert.ToString(num);Debug.Log("下一关为: " + nextLevel);//加载下一关PlayerPrefs.SetString("nowLevel", nextLevel);SceneManager.LoadScene(2);}public void SaveData(){Debug.Log("当前关卡的星星数量为: " + starsNum);//当前的星星数目大于已存储星星数目时,进行更新存储if (starsNum > PlayerPrefs.GetInt(PlayerPrefs.GetString("nowLevel"))){PlayerPrefs.SetInt(PlayerPrefs.GetString("nowLevel"), starsNum);}//存储所有的星星个数int sum = 0;for(int i = 1; i <= totalNum; i++){sum += PlayerPrefs.GetInt("level" + i.ToString());//Debug.Log("第"+ i.ToString() +"关的星星为: " + PlayerPrefs.GetInt("level" + i.ToString()));//Debug.Log("sum为: " + sum);}Debug.Log("将要存储的星星总数为: " + sum);PlayerPrefs.SetInt("totalNum", sum);}
}

4.地图选择

地图UI设计为以下四个部分,其中最后一个部分没有功能实现,所以真正的关卡其实只有前面三部分

在开始时,我们先读取所有已通关关卡的星星数目总和,当星星综合大于设定的map星星数目时,该map才进行解锁,设置isSelect=true,否则锁定该关卡,设置isSelect=false;

当点击该map时,隐藏map视图,显示关卡视图level

public class MapSelect : MonoBehaviour
{public int starsNum;public bool isSelect = false;public GameObject locks;public GameObject starts;public GameObject map;public GameObject panel;public Text startsText;public int startNum = 1;public int endNum = 5;public void Start(){//清除所有游戏数据//PlayerPrefs.DeleteAll();if(PlayerPrefs.GetInt("totalNum",0) >= starsNum){Debug.Log("星星总数为: " + PlayerPrefs.GetInt("totalNum"));isSelect = true;}if (isSelect){locks.SetActive(false);starts.SetActive(true);//TODO:Text显示TextShow();}}public void TextShow(){int count = 0;for (int i = startNum; i <= endNum; i++){          count += PlayerPrefs.GetInt("level" + i.ToString(), 0);}startsText.text = count.ToString() + "/15";}public void Selected(){if (isSelect){panel.SetActive(true);map.SetActive(false);}}public void PanelSelect(){panel.SetActive(false);map.SetActive(true);}
}

5.关卡选择

当激活关卡视图时,首先激活第一关,设置isSelect = true,然后遍历剩下的关卡,通过PlayerPrefs获取已存储的数据,当目标关卡的星星数目>0时,激活该关卡,否则进行锁定;

当激活某一关时,要通过PlayerPrefs得到该关卡的星星数目,然后通过控制star[i](星星列表)进行星星的显示;

然后定义一个Slect方法,用于选择关卡,当点击某个关卡时,通过PlayerPrefs设置当前关卡为点击关卡,并通过SceneManager读取场景

public class LevelSelect : MonoBehaviour
{public bool isSelect = false;public Sprite levelBG;public Image img;public GameObject[] stars;public void Awake(){img = GetComponent<Image>();}public void Start(){//是第一关if(this.transform.name == this.transform.parent.GetChild(0).name){isSelect = true;}else{int beforeNum = int.Parse(this.gameObject.name) - 1;if( PlayerPrefs.GetInt("level"+beforeNum.ToString()) > 0){isSelect = true;}}//激活关卡if (isSelect){img.overrideSprite = levelBG;this.transform.Find("num").gameObject.SetActive(true);//读取星星个数int count = PlayerPrefs.GetInt("level" + this.gameObject.name);if (count > 0){for(int i = 0; i < count; i++){stars[i].SetActive(true);}}}}public void Selected(){if (isSelect){PlayerPrefs.SetString("nowLevel", "level" + this.gameObject.name);SceneManager.LoadScene(2);//Debug.Log("选择成功");}}
}

6.暂停界面

通过UI设计一个暂停界面,当为激活时,它在游戏窗口外,当激活时,通过动画,将UI界面移入游戏窗口;

定义方法Pause,当点击暂停按钮时,调用该方法,然后调用暂停动画,将UI窗口移入游戏界面,

设置Time.timeScale = 0,以达到暂停游戏的效果,并隐藏该暂停按钮;

然后定义Resume方法,当点击还原按钮时,调用该方法,调用还原动画,重新将UI窗口移除游戏界面,并设置第一个小鸟为激活状态,并显示暂停按钮;

接下来定义Home方法和Retry方法,分别实现返回首页,和重新开始该关卡的操作,这里可以调用Gamemaneger中的Home和Retry方法,不过要注意提前设置Time.timeScale = 1,以免游戏继续暂停;

public class PausePanel : MonoBehaviour
{private Animator anim;public GameObject button;public void Awake(){anim = GetComponent<Animator>();}/// <summary>/// Home按键/// </summary>public void Home(){Time.timeScale = 1;Gamemanager._instance.Home();}/// <summary>/// Retry按键/// </summary>public void Retry(){Time.timeScale = 1;Gamemanager._instance.RePlay();}/// <summary>/// Pause按键/// </summary>public void Pause(){anim.SetBool("isPause", true);button.SetActive(false);//暂停if (Gamemanager._instance.birds.Count > 0){if(Gamemanager._instance.birds[0].isReleased == false){Gamemanager._instance.birds[0].canMove = false;}}}/// <summary>/// Resume按键/// </summary>public void Resume(){Time.timeScale = 1;anim.SetBool("isPause", false);//还原if (Gamemanager._instance.birds.Count > 0){if (Gamemanager._instance.birds[0].isReleased == false){Gamemanager._instance.birds[0].canMove = true;}}}/// <summary>/// pause动画结束后调用/// </summary>public void PauseAnimEnd(){Time.timeScale = 0;}/// <summary>/// resume动画结束后调用/// </summary>public void ResumeAnimEnd(){button.SetActive(true);}
}

四、场景间的组合搭配

一个游戏场景由以下几个模块构成:

  • Main Camera        主摄像机
  • Player          玩家模块,包括弹弓、当前小鸟、准备小鸟
  • Enemy         敌人模块,包括所有敌方单位:小猪、木块等障碍物
  • env               游戏背景:背景图片,地面,草丛
  • Cavas          UI画布,所有的UI组件都放在这里,用于管理UI的所有操作
  • UICamera    UI摄像机,查看UI镜头
  • Gamemenager    游戏管理器,挂载Gamemaneger脚本,管理几乎所有的游戏逻辑与功能模块

五、游戏的发布

关于游戏的发布,首先在项目设置里,设置你的游戏画面、游戏图标、鼠标图标等设置

然后进入Build Settings,设置需要发布的场景画面Scenes,根据需求,在不同的平台上发布游戏,在这里我选择发布的平台是Windows和Android(安卓发布,需要设置例如jdk、sdk,ndk等环境配置)

最后点击Build,铛铛,大功告成~


总结

以上就是一个Unity入门菜鸡开发的入门级2D游戏项目,本文主要用于自己学习总结,如有不对的地方望各位大佬指正。

下面是已发布成功的游戏本体:

PC和安卓:https://pan.baidu.com/s/1Q6SH-YWx7u4qF5DFDjOVqw       提取码:9xpx

安卓(蓝奏云):愤怒的小鸟    密码:2zp4

Unity新手入门项目——AngryBird(愤怒的小鸟)相关推荐

  1. Unity 新手入门 如何理解协程 IEnumerator yield

    Unity 新手入门 如何理解协程 IEnumerator 本文包含两个部分,前半部分是通俗解释一下Unity中的协程,后半部分讲讲C#的IEnumerator迭代器 协程是什么,能干什么? 为了能通 ...

  2. Unity新手入门必备书籍和教程推荐

    纵观整个游戏市场,Unity3D游戏开发已经称霸当下,Unity3D是一款3D游戏引擎,提供了3D游戏的大部分基础功能实现,比如物理碰撞.3D模型显示.光照等功能.市面上有超过一半以上的游戏,都是利用 ...

  3. Unity新手入门与进阶学习书籍与教程推荐

    读研的时候喜欢做游戏,最开始在诺基亚N9手机上开发过几款产品,有APP也有游戏.用的是Qt Quick,最先在N9上发布,之后又了解到黑莓的BB10系统,也可以用Qt Quick开发,所以就把几个产品 ...

  4. python新手入门项目推荐_推荐:一个适合于Python新手的入门练手项目

    随着人工智能的兴起,国内掀起了一股Python学习热潮,入门级编程语言,大多选择Python,有经验的程序员,也开始学习Python,正所谓是人生苦短,我用Python 有个Python入门练手项目, ...

  5. ThinkJS框架入门详细教程(二)新手入门项目

    一.准备工作 参考前一篇:ThinkJS框架入门详细教程(一)开发环境 安装thinkJS命令 npm install -g think-cli 监测是否安装成功 thinkjs -v 二.创建项目 ...

  6. Vue 新手入门项目 在线翻译

    用的有道的API,最后效果是这样的 需要两个组件,一个是需要翻译的内容和目标语言TranslateFrom.vue,还有一个是翻译成功显示的内容TranslateText.vue 项目结构是这样的 H ...

  7. python新手入门项目推荐_适合初学者练手的 10 个 有趣Python项目

    Python Python开发 Python语言 适合初学者练手的 10 个 有趣Python项目 想成为一个优秀的开发者,没有捷径可走,势必要花费大量时间在键盘后. 而不断地进行各种小项目开发,可以 ...

  8. python新手入门项目推荐_Python新手入门70个练手项目

    打开UC浏览器 查看更多精彩图片打开UC浏览器 查看更多精彩图片 不管学习哪门语言都希望能做出实际的东西来,这个实际的东西当然就是项目啦,不用多说大家都知道学编程语言一定要做项目才行. 这里整理了70 ...

  9. dt测试软件的学习心得,无线网络优化dt测试心得_适合新手入门,高手进阶_5年项目经验实战经验.docx...

    无线网络优化DT测试心得_适合新手入门,高手进阶_5年项目经验实战经验 无线网络优化DT测试心得_适合新手入门,高手进阶_5年项目经验实战经验 路测中不常见的问题和个人心得 1.深井子镇投诉测试报告 ...

最新文章

  1. 神奇的问题记录【SqlDataAdapter Fill DataSet】
  2. Linux自动备份MySQL数据库脚本代码
  3. Node.js实现Excel转JSON
  4. 从逻辑回归到最大熵模型
  5. fatal: HttpRequestException encountered (附:网盘下载地址)
  6. 《Ray Tracing in One Weekend》——Chapter 11: Defocus Blur
  7. 2020行政区划重新划分_邯郸市的20年,2000年-2020年区划对比,你觉得成绩如何?...
  8. web项目开发的基本流程
  9. 敏捷团队章程的实践精要
  10. JAVA修炼秘籍第三章《绝地反击》
  11. 喜马拉雅xm格式转化mp3_MTS视频格式转化
  12. 本题要求从输入的N个整数中查找给定的X。如果找到,输出X的位置(从0开始数);如果没有找到,输出“Not Found”
  13. js实现粒子特效,particles.js的使用
  14. 基于socket.io的php扩展介绍---phpsocket.io
  15. 科大讯飞语音识别和语音合成//////2020-08-17
  16. 用c 语言求纸对折的次数,纸张对折新纪录:13次
  17. 在线超级查询大全,没有什么是查不到的(个人收集)
  18. 卧听夏蝉---傲娇的xmlhttp.responseText和JSON传值问题
  19. CREO:CREO软件之工程图【布局】之一般视图、投影视图、详细视图、局部剖视图、向视图、局部放大视图、旋转剖视图的简介及其使用方法(图文教程)之详细攻略
  20. JAVA项目之苹果IAP内购JAVA服务器验证流程详解

热门文章

  1. 转载]Linux Gstreamer and GST-OMX插件
  2. 登录页获取短信验证码 读取短信验证码到键盘
  3. 洛谷 P2031 脑力达人之分割字串
  4. android小米手机拍照功能介绍,小米9相机使用技巧
  5. HCIE认证的含金量怎么样,和CCIE认证相比还有软考相比哪个好?
  6. 【Python\Matlab】计算风管摩擦阻力系数
  7. [网络工具] 个人密盘(Z盘)官网免费版 文件加密软件 加密文件夹
  8. Heritrix的order.xml详细介绍
  9. USTC-TFC2016的使用教程
  10. 复刻一台Zynthian便携式合成器音源