天天酷跑游戏开发日志及源码

**

纯c语言开发的游戏项目,与天天酷跑玩法与贴图类似,日志中有着详细的开发过程,从零开始手把手带你,解决游戏开发的问题;体验开发的乐趣!!!

ps:源码在文章最下面,有详细的注释内容。

**

1.创建项目

2.导入素材

3.创建游戏界面

基于C语言和Easyx图形库
1)创建游戏窗口
2)设计游戏背景
a)三重背景以不同的速度同时移动
b)循环滚动背景的实现
3)实现游戏背景
a)加载背景资源
b)打印背景图片(背景知识:坐标)

​ 遇到问题:背景图片的png格式图片出现黑色

​ 解决方案:导入tools.h和tools.cpp,包含到头文件并引用putimagePNG2

c)滚动效果加循环fly

​ 遇到问题:背景闪烁抖动(不断打印与渲染)

​ 解决方案:双缓冲机制(一次性准备好后一起渲染)

​ BeginBatchDraw();EndBatchDraw();

4.实现角色奔跑效果

1)加载角色奔跑的图片素材
2)设置角色的初始位置
a) 定义并取值角色X坐标,Y坐标,图片帧序号
3)实现角色跑动效果
a) 图片帧序号数组+1取余实现

​ heroIndex = (heroIndex + 1) % 12;

5.实现角色跳跃效果

1)处理用户输入的按键
a)如果有按键按下,kbhit()返回 ture
b)_getch不需要按回车即可直接读取,如果是 ‘ ’ 引用jump
2)实现跳跃
a)定义跳跃开关:跳跃Y坐标最大高度,偏移量(值为负)
b)打开跳跃开关

​ 1> 角色Y坐标 > 最大高度,则向上偏移

​ 2> 角色Y坐标 < 最大高度,将偏移量改为正,则向下偏移

c)关闭跳跃开关:当角色Y坐标 > 角色自身高度(最小高度),偏移量还原默认值
3)优化帧等待效果
a)sleep缺点:会导致程序休眠失去响应,在30s内无法触发按键响应
b)getDelay优化:返回距离上一次调用间隔的时间,第一次调用时返回。在30s内可以触发按键响应
c)update开关:用来实时刷新画面

6.实现敌人和障碍物

1)实现小乌龟的随机出现
a)加载小乌龟素材
b)出现小乌龟:(每3s刷新一个小乌龟)同时保证窗口只存在一个乌龟
c)渲染小乌龟

​ 1> 定义并取值小乌龟X坐标,Y坐标,图片帧序号

​ 2> 图片帧序号数组+1取余实现小乌龟旋转效果

​ 3>实现小乌龟水平移动,当小乌龟移出窗口后消失

​ 4>定义小乌龟的出现频率,使小乌龟随2s~5s随机出现、

2)使用结构体封装障碍物
a)定义结构体obstacle_t
b)用枚举存放障碍物类型,并定义为obstacle_type
c)使用c++中vector定义动态数组用来存储各障碍物图片(相当于c中:IMAGE obstacleImgs【3】【12】)
3)封装后障碍物的初始化
a)用结构体加载小乌龟素材
b)用结构体加载狮子素材
C)定义并初始化障碍物池
4)显示多个障碍物
a)出现障碍物:每隔一段时间刷新一个障碍物
b)创建障碍物的各个参数

​ 1>定义exist,imgIndex,type,x,y

​ 2>乌龟的数值,狮子的数值

c)更新所有障碍物的坐标
d)实现障碍物动态效果

7.实现玩家下蹲技能

1)加载下蹲素材
2)下蹲按键实现
3)定义下蹲开关和更新下蹲
a)用updateHero封装更新跳跃和下蹲
b)如果不下蹲则实现跳跃,否则实现下蹲
c)在滚动效果中实现下蹲

​ 遇到问题:下蹲速度太快

​ 解决方案:使用count增加帧数让图片变慢,增加delay延时

8.添加柱子障碍物

1)加载柱子障碍物素材
2)创建柱子障碍物的各个参数
3)优化障碍物的出现频率
a)对3取余降低柱子出现概率

9.实现碰撞检测

1)计算角色和障碍物的矩形大小(在tool.h中)
2)角色的矩形计算
a)奔跑与跳跃状态(通过偏移量来计算)
b)下蹲状态
2)障碍物的矩形计算
3)检测玩家与障碍物是否相交
a)相交:玩家掉血+碰撞声音

​ 遇到问题:角色碰撞后持续掉血

​ 解决方案:新定义hited,控制其开关来解决持续掉血

10.解决音效BUG–优化下蹲–增加血条

1)预加载音效,解决音效BUG
2)优化下蹲
3)使用封装好的血条

11.实现游戏结束,增加初始界面

1)播放背景音乐
2)判断游戏结束

a)血量<= 0,加载结束图片,0表示加载到界面;关闭背景音乐;游戏暂停

b)暂停以后,直接开始下一局;血量回复;播放背景音乐

3)增加初始界面

12.解决死亡障碍(柱子与狮子同时出现)

1)记录上一次障碍物,如果上一次障碍物时柱子&&下一次出现狮子&&上一个障碍物没走远
则将下一次障碍物替换成乌龟

13.通过障碍物后自动加分机制

1)比较x坐标:障碍物x坐标 + 障碍物第一章图片的宽度 < 玩家坐标
2)障碍物通过玩家加一分

14.实现界面界面显示分数

1)加载得分数字图片
2)显示分数
a)实现方法:50 =>‘50’ ‘5’ ‘5’-‘0’=5

15.判断游戏胜利

1)当分数 > 100分,播放胜利音效及图片
2)回复玩家血条,清零分数
3)注意:胜利前最后一分不显示就胜利,用”手动“刷新解决

注意:错误 C4996 'sprintf’要改为sprintf_s

右键文件名->属性->C/C++中常规->SDL检查关闭

源码如下:

#include <stdio.h>
#include <graphics.h>
#include <conio.h>
#include <vector>
#include "tools.h"using namespace std;    //声明命名空间#define WIN_SCORE  3#define WIN_WIDTH 1012
#define WIN_HEIGHT 396  //宏定义,便于维护和更改
#define OBSTACLE_COUNT 10   //宏定义障碍物池数量IMAGE imgBgs[3]; //(全局数组)存放背景图片
int bgX[3];     //背景图片的x坐标
int bgSpeed[3] = {2, 3, 5};        //三张图不同的速度IMAGE imgHeros[12];       //存放角色奔跑图片
int heroX;  //角色的x坐标
int heroY;  //角色的y坐标
int heroIndex;  //角色奔跑的图片帧序号bool heroJump;  //表示角色正在跳跃开关
int jumpHeighetMax; //跳跃的最大值
int heroJumpOff;    //表示偏移量
int update; //表示是否马上刷新画面//  IMAGE imgTortoise[7];   //小乌龟
//  int torToiseX;  //小乌龟的水平坐标
//  int torToiseY;  //小乌龟的垂直坐标
//  bool torToiseExist; //当前窗口是否存在小乌龟
//  int tortoiseIndex;//小乌龟旋转的图片帧序号int heroBlood;   //玩家血量
int score;  //得分//枚举封装障碍物的类型
typedef enum {TORTOISE, //乌龟 0LION, //狮子 1HOOK1,    //四个柱子障碍物HOOK2,HOOK3,HOOK4,OBSTACLE_TYPE_CONST // 6 便于查看枚举数
}obstacle_type; vector<vector<IMAGE>>obstacleImgs;//c++存放所用障碍物的各个图片
//相当于c中:IMAGE obstacleImgs[3][12]//结构体封装障碍物
typedef struct obstacle {int type;  //障碍物的类型int imgIndex;   //当前显示图片的序号int x, y;    //障碍物坐标int speed;   //障碍物速度int power;   //障碍物杀伤力bool exist; //障碍物存在bool hited;  //表示是否已经发生碰撞bool passed;//表示是否被通过}obstacle_t;obstacle_t obstacles[OBSTACLE_COUNT];  //定义障碍物池
int lastObsIndex;   //记录上一次障碍物IMAGE imgHeroDown[2]; //角色下蹲
bool heroDown;  //表示玩家正在下蹲开关IMAGE imgSZ[10];//得分数字图片//游戏初始化
void init() {initgraph(WIN_WIDTH, WIN_HEIGHT, EW_SHOWCONSOLE);  //创建游戏窗口//加载背景资源char name[64];for (int i = 0; i < 3; i++) {//"res/bg001.png"   "res/bg002.png"   "res/bg003.png"   sprintf(name, "res/bg%03d.png", i + 1);loadimage(&imgBgs[i],name);    bgX[i] = 0;}//加载Hero奔跑的图片素材for (int i = 0; i < 12; i++) {//  "res/hero1.png"   ... "res/hero12.png"sprintf(name, "res/hero%d.png", i+1);loadimage(&imgHeros[i], name);}//设置角色的初始位置heroX = WIN_WIDTH * 0.5 - imgHeros[0].getwidth() * 0.5;heroY = 355 - imgHeros[0].getheight();heroIndex = 0;heroJump = false;jumpHeighetMax = 355 - imgHeros[0].getheight() - 120;heroJumpOff = -5;update = true;//   6.1 加载小乌龟素材//   for (int i = 0; i < 7; i++) {//       //  "res/t1.png" ... "res/t7.png"//     sprintf(name, "res/t%d.png", i + 1);//       loadimage(&imgTortoise[i], name);// }// torToiseExist = false;//   torToiseY = 355 - imgTortoise[0].getheight();//用结构体加载小乌龟素材IMAGE imgTort;vector<IMAGE> imgTortArray;for (int i = 0; i < 7; i++) {// "res/t1.png" ... "res/t7.png"sprintf(name, "res/t%d.png", i + 1);loadimage(&imgTort, name);imgTortArray.push_back(imgTort);  //存放到一维}obstacleImgs.push_back(imgTortArray);   //存放到二维//用结构体加载狮子素材IMAGE imgLion;vector<IMAGE> imgLionArray;for (int i = 0; i < 6; i++) {// "res/p1.png" ... "res/p6.png"sprintf(name, "res/p%d.png", i + 1);loadimage(&imgLion, name);imgLionArray.push_back(imgLion);  //存放到一维}obstacleImgs.push_back(imgLionArray);   //存放到二维//初始化障碍物池for (int i = 0; i < OBSTACLE_COUNT; i++) {obstacles[i].exist = false;}//加载下蹲素材loadimage(&imgHeroDown[0], "res/d1.png");loadimage(&imgHeroDown[1], "res/d2.png");heroDown = false;//加载柱子素材IMAGE imgH;for (int i = 0; i < 4; i++) {vector<IMAGE> imgHookArray;sprintf(name,"res/h%d.png",i+1);loadimage(&imgH,name, 63, 260, true);imgHookArray.push_back(imgH);obstacleImgs.push_back(imgHookArray);}//玩家血量heroBlood = 100;//预加载音效preLoadSound("res/hit.mp3");//播放背景音乐mciSendString("play res/bg.mp3 repeat", 0, 0, 0);lastObsIndex = -1;score = 0;//加载得分数字图片for (int i = 0; i < 10; i++) {sprintf(name, "res/sz/%d.png", i);loadimage(&imgSZ[i],name);}
}//创建障碍物的各个参数
void createObstacle() {int i;for (i = 0; i < OBSTACLE_COUNT; i++) {if (obstacles[i].exist == false) {break;}}if (i >= OBSTACLE_COUNT) {return;}obstacles[i].exist = true;obstacles[i].hited = false;obstacles[i].imgIndex = 0;//obstacles[i].type = (obstacle_type)(rand() % OBSTACLE_TYPE_CONST);  //使障碍物随机出现obstacles[i].type = (obstacle_type)(rand() % 3); //对3取余降低柱子出现概率if (lastObsIndex >= 0 &&obstacles[lastObsIndex].type >= HOOK1 &&obstacles[lastObsIndex].type <= HOOK4 &&obstacles[i].type == LION &&obstacles[lastObsIndex].x > (WIN_WIDTH - 500)) {obstacles[i].type = TORTOISE;}lastObsIndex = i;if (obstacles[i].type == HOOK1) {obstacles[i].type += rand() % 4;   //0...3}obstacles[i].x = WIN_WIDTH;    obstacles[i].y = 355 - obstacleImgs[obstacles[i].type][0].getheight();//乌龟的数值if (obstacles[i].type == TORTOISE) {obstacles[i].speed = 1;    //乌龟速度值obstacles[i].power = 5; //乌龟伤害值}//狮子数值else if (obstacles[i].type == LION) {obstacles[i].speed = 4;   //狮子速度值obstacles[i].power = 20;    //狮子伤害值}else if (obstacles[i].type >= HOOK1 && obstacles[i].type <= HOOK4) {obstacles[i].speed = 0;        //柱子速度值obstacles[i].power = 20;    //柱子伤害值obstacles[i].y = 0;}obstacles[i].passed = false;
}//碰撞检测
void checkHit() {for (int i = 0; i < OBSTACLE_COUNT; i++) {if (obstacles[i].exist && obstacles[i].hited == false) {int a1x, a1y, a2x, a2y;      //a1x,a1y为左上角坐标:a2x,a2y为右下角坐标int off = 30;  //偏移量//角色碰撞检测if (!heroDown) {   //非下蹲状态(奔跑,跳跃状态)a1x = heroX + off;a1y = heroY + off;a2x = heroX + imgHeros[heroIndex].getwidth() - off;a2y = heroY + imgHeros[heroIndex].getheight();}else {a1x = heroX + off;a1y = 355 - imgHeroDown[heroIndex].getheight();a2x = heroX + imgHeroDown[heroIndex].getwidth() - off;a2y = 355;}//障碍物碰撞检测IMAGE img = obstacleImgs[obstacles[i].type][obstacles[i].imgIndex];int b1x = obstacles[i].x + off;int b1y = obstacles[i].y + off;int b2x = obstacles[i].x + img.getwidth() - off;int b2y = obstacles[i].y + img.getheight() - 10;//检测角色与障碍物是否相交if (rectIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y)) {heroBlood -= obstacles[i].power; //玩家掉血、printf("血量剩余 %d\n", heroBlood);playSound("res/hit.mp3"); //碰撞声音obstacles[i].hited = true;}}}
}//滚动效果
void go()
{for (int i = 0; i < 3; i++) {bgX[i] -= bgSpeed[i];if (bgX[i] < -WIN_WIDTH) {bgX[i] = 0;     //循环实现}}//实现跳跃if (heroJump) {if (heroY < jumpHeighetMax) {heroJumpOff = 6;}heroY += heroJumpOff;if (heroY > 355 - imgHeros[0].getheight()) {heroJump = false;heroJumpOff = -6;}}else if (heroDown) { //实现下蹲static int count = 0;int delays[2] = {6, 30};count++;if (count >= delays[heroIndex]) {count = 0;heroIndex++;if (heroIndex >= 2) {heroIndex = 0;heroDown = false;}}}else{ //不跳跃heroIndex = (heroIndex + 1) % 12;    //实现角色跑动效果}//出现障碍物static int frameCount = 0;static int enemyFre = 50; //小乌龟出现频率frameCount++;if (frameCount > enemyFre) {     //25ms刷新一次,刷新一个障碍物frameCount = 0;enemyFre = 50 + rand() % 50; //障碍物在50 ~ 99随机出现createObstacle();}//更新所有障碍物的坐标for (int i = 0; i < OBSTACLE_COUNT; i++) {if (obstacles[i].exist) {obstacles[i].x -= obstacles[i].speed + bgSpeed[2];    //障碍物位移=障碍物位移-障碍物速度+背景速度if (obstacles[i].x < -obstacleImgs[obstacles[i].type][0].getwidth()*2) {   //当障碍物移出窗口后消失obstacles[i].exist = false;}//实现障碍物动态效果int len = obstacleImgs[obstacles[i].type].size(); //取各个障碍物中的成员个数值obstacles[i].imgIndex = (obstacles[i].imgIndex + 1) % len;}}// 6.1 出现小乌龟//if (!torToiseExist) {//  torToiseExist = true;//    torToiseX = WIN_WIDTH; //小乌龟从窗口宽度边缘出现//    enemyFre = 200 + rand() % 300;    //小乌龟在200 ~ 500(2s~5s)随机出现//}//   6.1 实现小乌龟水平移动// if (torToiseExist) {//  tortoiseIndex = (tortoiseIndex + 1) % 7;  //实现乌龟旋转效果//    torToiseX -= bgSpeed[2];// if (torToiseX < -imgTortoise[0].getwidth()) {    //当小乌龟移出窗口后消失//     torToiseExist = false;//   }//}//玩家和障碍物的“碰撞检测”处理checkHit();}//渲染游戏背景
void updateBg()
{putimagePNG2(bgX[0], 0, &imgBgs[0]);putimagePNG2(bgX[1], 119, &imgBgs[1]);putimagePNG2(bgX[2], 330, &imgBgs[2]);
} void jump() {heroJump = true;    //打开跳跃开关update = true;
}void down() {heroDown = true; //打开下蹲开关update = true;heroIndex = 0;
}//处理用户输入的按键
void keyEvent()
{char ch;if (_kbhit()) {        //如果有按键按下,kbhit()返回 turech = _getch();        //_getch不需要按回车即可直接读取if (ch == ' ') {jump();}else if (ch == 'z') {   //按z下蹲down();}}
}void updateEnemy() {//渲染所有障碍物for (int i = 0; i < OBSTACLE_COUNT; i++) {if (obstacles[i].exist) {putimagePNG2(obstacles[i].x, obstacles[i].y, WIN_WIDTH,&obstacleImgs[obstacles[i].type][obstacles[i].imgIndex]);}}
}// 6.1 渲染小乌龟// if (torToiseExist) {//      putimagePNG2(torToiseX, torToiseY, WIN_WIDTH, &imgTortoise[tortoiseIndex]);//   }//更新跳跃和下蹲
void updateHero() {if (!heroDown) {putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);}else {int y = 355 - imgHeroDown[heroIndex].getheight();putimagePNG2(heroX, y, &imgHeroDown[heroIndex]);}}//添加血条
void updateBloodBar() {drawBloodBar(10, 10, 200, 10, 2, BLUE, DARKGRAY, RED, heroBlood / 100.0);
}//判断游戏结束
void checkOver() {if (heroBlood <= 0) {loadimage(0,"res/over.png");   //加载结束图片,0表示加载到界面FlushBatchDraw();mciSendString("stop res/bg.mp3", 0, 0, 0);   //  关闭背景音乐system("pause");    //游戏暂停//暂停以后,直接开始下一局heroBlood = 100;score = 0;mciSendString("play res/bg.mp3 repeat", 0, 0, 0);}
}//添加初始界面
void checkStart() {loadimage(0, "res/over.png");system("pause");
}//越过障碍物自动得分机制
void checkScore() {for (int i = 0; i < OBSTACLE_COUNT; i++) {if (obstacles[i].exist &&obstacles[i].passed == false &&obstacles[i].hited == false &&obstacles[i].x + obstacleImgs[obstacles[i].type][0].getwidth() < heroX) {score++;obstacles[i].passed = true;printf("score: %d\n", score);}}
}//显示分数
void updateScore() {//实现方法:50 =>'50' '5'   '5'-'0'=5char str[8];sprintf(str, "%d", score);int x = 20;int y = 25;for (int i = 0; str[i]; i++) {int sz = str[i] - '0';putimagePNG(x, y, &imgSZ[sz]);x += imgSZ[sz].getwidth() + 5;}
}//检测胜利
void checkWin() {if (score >= WIN_SCORE) {FlushBatchDraw(); //手动刷新胜利前最后一分mciSendString("play res/win.mp3", 0, 0, 0);Sleep(2000);loadimage(0,"res/win.png");FlushBatchDraw();    //刷新界面  mciSendString("stop res/bg.mp3", 0, 0, 0);system("pause");heroBlood = 100;score = 0;mciSendString("play res/bg.mp3", 0, 0, 0);}
}int main(void)
{init();checkStart();int timer = 0;while (1) {keyEvent();timer += getDelay();    //返回距离上一次调用间隔的时间(单位:ms),第一次调用时返回0if (timer > 25) {      //实现sleep25ms循环效果timer = 0;update = true;}if (update) {   //如果没到30ms触发按键,直接刷新update = false;BeginBatchDraw(); //双缓冲机制(防背景闪屏)updateBg();//putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);updateHero();updateEnemy();updateBloodBar();updateScore();checkWin();EndBatchDraw();checkOver();checkScore();go();}//Sleep(25);   //导致休眠}system("pause");return 0;
}

实机演示:

【C语言】实现天天酷跑游戏相关推荐

  1. 天天酷跑java_利用Java怎么实现一个天天酷跑游戏

    利用Java怎么实现一个天天酷跑游戏 发布时间:2020-12-15 17:25:03 来源:亿速云 阅读:102 作者:Leah 利用Java怎么实现一个天天酷跑游戏?很多新手对此不是很清楚,为了帮 ...

  2. 【Python游戏】基于Python的pygame模块实现的天天酷跑游戏 | 附带源码

    前言 我相信很多小伙伴都玩过的第一个腾讯游戏,那就是天天酷跑,还记得之前为了凑齐钻石买小单车.人物.坐骑,小编可是花费了老长时间去弄这个的!!不过现在的天天酷跑随便冲个钱都能上大几百万分,没有了以前的 ...

  3. C语言仿天天酷跑小游戏

    前言:全文代码是模仿程序员rock开发的游戏代码思路,如果大家想根据视频一步步进行制作可以直接去b站进行搜索.全文代码主要分为两个部分,一个是完整版的开发代码(博主根据视频进行一步一步制作而成,素材也 ...

  4. 用C语言写一个类似天天酷跑游戏(图形库用easyx)

    1.头文件.全局变量和结构体 a.玩家结构体 b.枚举玩家三种状态:奔跑.跳跃.滑行 c.障碍物结构体 d.障碍物结点 e.枚举出障碍物类型 #include<stdio.h> #incl ...

  5. 模拟天天酷跑游戏java_cocos2d 简单高仿天天酷跑游戏

    1.先直接上视频来看下这个游戏的样子(GIF已经不能满足这个游戏的展示了) 跑酷游戏最纠结的是地图,碰撞倒是简单,可以自己写或者使用box2d等物理引擎.跑酷游戏地图的特点就是随机性.但是随机中又有策 ...

  6. cocos2d 简单高仿天天酷跑游戏

    1.先直接上视频来看下这个游戏的样子(GIF已经不能满足这个游戏的展示了) 跑酷游戏最纠结的是地图,碰撞倒是简单,可以自己写或者使用box2d等物理引擎.跑酷游戏地图的特点就是随机性.但是随机中又有策 ...

  7. ▷Scratch课堂丨在Scratch上制作天天酷跑游戏

    "在之前作品基础上进行修改,文尾有福利哦,点击阅读原文获取源码." 01 - -效果展示- 其实这篇文章和之前发过的奔跑吧小恐龙很类似有没有? 其实就是在那个版本的基础之上▷Scr ...

  8. 模拟天天酷跑游戏java_Java学习笔记_17 项目实战之天天酷跑(四):游戏主界面...

    package cn.sqc.runday.model; import java.awt.Graphics; import java.awt.Image; import java.io.File; i ...

  9. C语言开发 天天酷跑 用到的 graphics.h

    我是C开发的小白,才开始学.这些库需要单独引入,自己操作了一遍,可以实现引入了.就写个博客,记录一下. 下载easyx 下载完安装,如下图: 软件会自动检测你当前的VS版本,点击安装,会弹出提示安装成 ...

最新文章

  1. 使用pydub实现训练声音数据集加噪
  2. android staticlayout使用讲解,可实现文本绘制换行处理
  3. 数据结构 快速排序(详解)
  4. NEW RToax logo
  5. 记录——《C Primer Plus (第五版)》第十一章编程练习第二题
  6. 腾讯回应“QQ 冻结”;高德上线“家人地图”惹争议;Linux 内核讨论引入 Rust 代码| 极客头条...
  7. python dataframe 重命名列_Python-重命名pandas列
  8. nyoj 122 Triangular Sums
  9. eb8000软件怎样上传_威纶通触摸屏 如何上传程序 到电脑需要怎么处理
  10. 《从零开始的 RPG 游戏制作教程》第八期:对话、按钮、变量、马甲
  11. 联想电脑安装黑苹果全教程
  12. 通用线性模型(GLMs,Generalized Linear Models)
  13. 计算机远程控制安全吗,远程控制电脑危险吗?向日葵远程控制软件安全吗?
  14. OSPF路由器类型 ABR与ASBR路由聚合区别
  15. C# .net 集合-并发处理之文件读写处理
  16. Xu_Learning_to_Restore_Low-Light_Images_via_Decomposition-and-Enhancement_CVPR_2020_paper
  17. MiniGUI原理分析GAL
  18. USB OTG原理简述
  19. 软件测试之实用小工具推荐
  20. MissingServletRequestPartException: Required request part ‘file‘ is not pres

热门文章

  1. ubuntu之lrzsz文件传输工具
  2. ubuntu16.04下安装GVIM,亲测可用
  3. Linux系统之ping命令
  4. linux安装 msf,Centos下安装msf
  5. Oracle必备知识
  6. android studio 测试连接夜神模拟器
  7. Android(4.2) Sensors 学习——G-sensor,Gyroscope驱动移植
  8. mysql数据库原理分析
  9. 如何选择云计算培训机构
  10. 项目中全局异常设置?