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

C项目 天天酷跑(下篇)

上篇再博客里面有,接下来我们实现我们剩下要实现的功能


文章目录 

碰撞检测

血条的实现

积分计数器


 

前言

我们现在要继续优化我们的程序才可以使这个程序更加的全面


碰撞的检测

定义全局变量

实现全局变量

void checkHit() {for (int i = 0; i < OBSTACLE_CUONT; i++) {if (obstacles[i].exist && obstacles[i].hited == false) {int ax1, ay1, ax2, ay2;//角色的碰撞宽度高度设置if (!heroDown) {ax1 = heroX;ay1 = heroY;ax2 = heroX + imgHero[i].getwidth();ay2 = heroY - imgHero[i].getheight();}else {ax1 = heroX;ay1 = 397 - imgHeroDown[i].getheight();ax2 = heroX + imgHeroDown[i].getwidth();ay2 = 397;}//障碍物的碰撞宽度高度设置int bx1 = obstacles[i].x;int by1 = obstacles[i].y;int bx2 = obstacles[i].x + obstacleImags[obstacles[i].type][obstacles[i].imgIndex].getwidth();int by2 = obstacles[i].y - obstacleImags[obstacles[i].type][obstacles[i].imgIndex].getheight()-10;if (rectIntersect(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2)) {//写到这里,只要我们有图片和障碍物相交在一起就会扣血,因为在屏幕里面,怪是要到屏幕之外才是结束存在的heroBoold -= obstacles[i].power;printf("血量剩余%d\n", heroBoold);obstacles[i].hited = true;}}}}

我们来看到这个代码是实现碰撞检测的,我们来画一个图

我们要找出这两个人的x1,x2,y1,y2的坐标后面的by-10是因为我这图片的问题,就是kunkun和别的尺寸有问题才-10,一般是不需要减10的,正常写就好接下来我们就要判断是否发生碰撞了

接下里我们就要学习是否发生碰撞这个判断条件了

bool rectIntersect(int x01, int y01, int x02, int y02,int x11, int y11, int x12, int y12)
{int zx = abs(x01 + x02 - x11 - x12);int x = abs(x01 - x02) + abs(x11 - x12);int zy = abs(y01 + y02 - y11 - y12);int y = abs(y01 - y02) + abs(y11 - y12);return  (zx <= x && zy <= y);
}

这个是我们要用到的函数,这个函数参数

x01--人的x1    y01--人的y1   x02--人的x2   y02--人的y2   x11--障碍物的x1   y11--障碍物的y1

x12--障碍物的x2  y12--障碍物的y2 

zx和x的理解

这个就是zx和x之间的原理 

 

这个是zy和y的原理跟x差不多

当我们实现这个碰撞检测的时候,我们就可以继续写了,我们就利用这个碰撞检测来实现这个血条的扣血

在run函数里面实现进行每一次的检测

这里我们打开了hitd这个开关,我们不需要写一个关闭这个开关的程序,因为每一次创建一个障碍物的时候,他都会进行一次初始化,这个开关它会关闭,碰到之后再继续打开

血条的扣血

我们定义一个这个函数来显示血条 

 这个是血条扣除的函数

void drawBloodBar(int x, int y, int width, int height, int lineWidth, int boardColor, int emptyColor, int fillColor, float percent) {LINESTYLE lineStyle;getlinestyle(&lineStyle);int lineColor = getlinecolor();int fileColor = getfillcolor();if (percent < 0) {percent = 0;}setlinecolor(BLUE);setlinestyle(PS_SOLID | PS_ENDCAP_ROUND, lineWidth);setfillcolor(emptyColor);fillrectangle(x, y, x + width, y + height);setlinestyle(PS_SOLID | PS_ENDCAP_FLAT, 0);setfillcolor(fillColor);setlinecolor(fillColor);if (percent > 0) {fillrectangle(x + 0.5 * lineWidth, y + lineWidth * 0.5, x + width * percent, y + height - 0.5 * lineWidth);}setlinecolor(lineColor);setfillcolor(fillColor);setlinestyle(&lineStyle);
}

参数部分:

  • x, y: 血条左上角的坐标
  • width, height: 血条的宽度和高度
  • lineWidth: 边框的宽度
  • boardColor: 背景色(未使用,但可以用于描边)
  • emptyColor: 进度条背景(未填充部分)的颜色
  • fillColor: 进度条已填充部分的颜色
  • percent: 进度条已填充部分的百分比,取值范围为0到1

 接下来分析这个函数里面的代码内容

LINESTYLE 是一个数据类型,用于表示线条的样式。它通常在图形编程库(比如 EasyX)中用来存储与线条相关的属性,比如线条的宽度、样式、端点样式等

典型的 LINESTYLE 结构体可能包含:

  1. 线条宽度width):指定线条的宽度
  2. 线条样式style):指定线条的样式,常见的样式包括实线、虚线等
  3. 线条端点样式cap):设置线条的端点样式,比如圆形端点、方形端点等
  4. 线条连接样式join):设置线段连接点的样式,如圆形连接、尖角连接等

示例:

在 EasyX 中,LINESTYLE 的定义可能类似于:

typedef struct _LINESTYLE {int width;   // 线条宽度int style;   // 线条样式int cap;     // 端点样式int join;    // 连接点样式
} LINESTYLE;

这个是eaxyx里面的

 

总结来说,LINESTYLE 是一个结构体,用来存储和管理与线条绘制相关的多种样式设置

LINESTYLE lineStyle;
getlinestyle(&lineStyle);
int lineColor = getlinecolor();
int fileColor = getfillcolor();

这个代码是

  • getlinestyle(&lineStyle):获取当前的线条样式
  • getlinecolor():获取当前的线条颜色
  • getfillcolor():获取当前的填充颜色

这个是获取你系统自带的默认的颜色,避免你后面没有颜色和样例

这个是一个浮点数,就是血条的百分比含量 ,当为小于0的时候,就归属0,避免异常值的出现

 setlinecolor(BLUE);setlinestyle(PS_SOLID | PS_ENDCAP_ROUND, lineWidth);setfillcolor(emptyColor);fillrectangle(x, y, x + width, y + height);setlinestyle(PS_SOLID | PS_ENDCAP_FLAT, 0);setfillcolor(fillColor);setlinecolor(fillColor);
  • setlinecolor(BLUE);

    • 这行代码设置 线条的颜色为蓝色。通常,这会影响矩形的边框颜色(即轮廓)。
    • BLUE 是 EasyX 图形库中的预定义颜色常量,表示蓝色。
  • setlinestyle(PS_SOLID | PS_ENDCAP_ROUND, lineWidth);

    • 这行代码设置 线条的样式
      • PS_SOLID 表示线条是 实线(不是虚线或点线)。
      • PS_ENDCAP_ROUND 表示线条的端点是 圆形,即线段的两端是圆头,而不是方头或平头。
      • lineWidth 是线条的宽度,通常是一个整数,表示线条的粗细(例如 2 表示线条宽度为 2 像素)。
  • setfillcolor(emptyColor);

    • 这行代码设置 填充颜色,即矩形内部的颜色。
    • emptyColor 是传入的一个变量,表示血条的背景颜色,通常是透明或灰色,表示血条没有被填充的部分。
  • fillrectangle(x, y, x + width, y + height);

    • 这行代码用于 绘制矩形
    • x, y 是矩形的左上角坐标,x + width, y + height 是矩形的右下角坐标。这样,矩形的大小和位置就由这些坐标确定了。
    • 这个矩形会被 填充为之前设置的 emptyColor,即矩形的背景颜色。

这个下一个就是恢复样例和颜色了,避免下一次使用不是默认的样例和颜色

  • setlinestyle(PS_SOLID | PS_ENDCAP_FLAT, 0);

    • 这行代码 恢复线条样式
      • PS_SOLID 表示线条是 实线
      • PS_ENDCAP_FLAT 表示线条的端点是 平头,即线段的两端是直角,而不是圆形端点。
      • 0 表示 线宽为 0,这意味着不会显示边框,这通常用于消除矩形或其他图形的外部轮廓,只显示填充

这个后面就是填充血条的颜色,上面那个是空血条的颜色

  • setfillcolor(fillColor);

    • 这行代码设置 填充颜色fillColor,也就是血条的 实际填充颜色,即显示血量的颜色。通常这个颜色是 红色绿色 或其他表示血量的颜色。
  • setlinecolor(fillColor);

    • 这行代码将 线条颜色 设置为 fillColor,即设置血条边框的颜色为填充颜色。这个通常是为了确保血条的边框与填充颜色一致,给人一致的视觉效果。

核心句子

if (percent > 0) {fillrectangle(x + 0.5 * lineWidth, y + lineWidth * 0.5, x + width * percent, y + height - 0.5 * lineWidth);
}
  • 左上角坐标x + 0.5 * lineWidthy + lineWidth * 0.5
    • x + 0.5 * lineWidth:由于在绘制矩形时需要考虑线条宽度,所以 x 坐标偏移了 0.5 * lineWidth,确保边框的线宽(lineWidth)不会影响矩形的显示位置,确保绘制的矩形与边框之间有一定的间隔。
    • y + lineWidth * 0.5:同样,y 坐标也进行了偏移,确保矩形的上边界与线条宽度相适应。
  • 右下角坐标x + width * percenty + height - 0.5 * lineWidth
    • x + width * percent:这里的 x + width * percent 计算了矩形的 实际宽度,它是根据当前血量的百分比 percent 来决定的。如果 percent 为 0,矩形的宽度为 0;如果 percent 为 1,矩形的宽度将是血条的最大宽度 width
    • y + height - 0.5 * lineWidthy + height 为矩形的下边界,减去 0.5 * lineWidth 是为了避免线条的宽度影响矩形的底部显示。

我们这里不需要修改这个左上角标的值的,只需要修改右下角标的值,这样就可以实现动态绘画这个血条了

setlinecolor(lineColor);
setfillcolor(fillColor);
setlinestyle(&lineStyle);

这个是恢复之前的颜色,避免下一次使用不是默认的值,我们之前就把初始化的东西用变量储存起来了

积分计数器

void checkpassed() {for (int i = 0; i < OBSTACLE_CUONT; i++) {if (obstacles[i].exist &&obstacles[i].passed == false &&obstacles[i].x + obstacleImags[obstacles[i].type][0].getwidth()) {score++;obstacles[i].passed = true;printf("%d", score);}}
}

这个就是我们来检测是否跳过这个障碍物,我们只需要检测这个开关是否关闭,还有这个长度是否超过这个图片的长度还有这个障碍物是否存在,执行完成之后,就打开这个开关,防止一直加分,然后就是我们要加一个分数绘制在这个窗口

void updateScore() {//ASCLL码值 ‘5’-‘0’=5char str[8];sprintf(str, "%d", score);int x = 20;int y = 25;for (int i = 0; str[i] != 0; i++) {int num = str[i] - '0';putimage(x, y, &imgSZ[num]);x += imgSZ[num].getwidth();}
}

我们只需要把这个score格式化一下从int到char类型,然后利用sprintf来读取对应的数字到数组里面,然后就是用for循环来来便利 ,这里也运用了ASCII值的转换,后买你x+=这一个代码是为了是图片连起来

源码

//图片的长宽
#define _CRT_SECURE_NO_WARNINGS 1
#define WIN_LONG 1150
#define WIN_WIDTH 538
#define OBSTACLE_CUONT 20#include<time.h>
#include<stdio.h>
#include<graphics.h>
//这个是用来调用按键是否输入的
#include<conio.h>
//这个是用来使用变长数组的
#include<vector>
#include<windows.h>
//播放音乐的时候用的两行代码
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")#include"tools.h"
using namespace std;  //声明命名空间
/* 背 景 制 作 */
//背景图数组
IMAGE imgBgs[2];
//背景图的x
int bgX[2];
//用来存放速度
int bgspeed[2] = { 4,8 };
/* 角 色 制 作*/
//角色奔跑
IMAGE imgHero[12];
//玩家会被弹飞还有下蹲啥的,所以要设置全局变量
int heroX;   //x坐标
int heroY;   //y坐标
int heroIndex;  //玩家奔跑时图片的序号bool heroJump;  //表示玩家正在跳跃(跳跃开关)
bool heroDown;  //表示玩家正在下蹲(下蹲开关)int heroBoold;int jumpHeightMax;
int herojumpOff;
int update;      //表示是否需要马上刷新画面int score;/* 乌 龟 制 作*/
//IMAGE imgTortoise; //小乌龟
//int torToiseX;     //小乌龟的x坐标
//int torToiseY;     //小乌龟的y坐标
//bool torToiseExist;//当前窗口是否有小乌龟
//由于障碍物越来越多,则需要进行封装,这样就可以简化代码行数,实现代码不拥挤typedef enum {TORTOISE,   //奶龙0LION,       //狮子1//四个柱子HOOK1,HOOK2,HOOK3,HOOK4,OBSTACLE_TYPE_COUNT//常看有几种障碍物(因为是从0开始,所以更加方便看有几种类型)ho
}obstacle_type;//IMAGE obstacleImage[3][12];用这个的话会浪费些许内存,因为乌龟只有一个图片
vector<vector<IMAGE>>obstacleImags(OBSTACLE_TYPE_COUNT,vector<IMAGE>(12));//里面一个成员的又一个成员(可变数组)
//相当于int data[ int ]typedef struct obstacle {obstacle_type type;//障碍物的类型int imgIndex;       //当前显示的图片的序号//但是这样有障碍物的数字代表不是特别可读,所以我们可以利用枚举类型,更加可读int x, y;           //障碍物的x与y坐标int speed;int power;          //伤害bool exist;bool hited;        //碰撞bool passed;
}obstacle_t;//由于我们不可以把障碍物直接全部都是弄出来,要逐个逐个的,就像捕鱼达人一样,所以我们要建立一个池子来存储这个预备队员,就像篮球,一个上场一个下场
obstacle_t obstacles[OBSTACLE_CUONT];
//玩家下滑图片储存的数组
IMAGE imgHeroDown[2];
//创建窗口IMAGE imgSZ[10];void init() {//创建窗口//第三个参数是为了显示控制台的参数//第三个参数是为了显示控制台的参数//在initgraph后面, EX_SHOWCONSOLE这个在打包删除了initgraph(WIN_LONG, WIN_WIDTH);/*背 景 制 作*///加载背景图  loadimage函数(取地址,具体的文件名字)char name[64];for (int i = 0; i < 2; i++) {//"ret/bg001.png"  "ret/bg002.png"  "ret/bg003.png"sprintf(name, "ret/bg%03d.png", i + 1);//这个是要在win32平台和多字节字符串的情况下才可以运行loadimage(&imgBgs[i], name);//初始化背景图的x轴坐标bgX[i] = 0;}/*人 物 制 作*///加载玩家奔跑for (int i = 0; i < 12; i++) {//"跑步1"  "跑步2"sprintf(name, "ret/跑步%d.png", i + 1);loadimage(&imgHero[i], name);}//设置玩家初始位置//窗口宽度*0.5-自己宽度*0.5heroX = 600 * 0.5 - 200 * 0.5 - 80;heroY = 300;heroIndex = 0;//玩家跳跃heroJump = false;jumpHeightMax = 80;//记得是减,不是加,注意坐标原点herojumpOff = -6;update = true;/*小 乌 龟 制 作*///loadimage(&imgTortoise, "ret/奶龙.png");//torToiseExist = false;//torToiseY = 400;/*小 奶 龙 改 版*/IMAGE imgTort;loadimage(&imgTort, "ret/奶龙.png");vector<IMAGE>imgTorArray;imgTorArray.push_back(imgTort);obstacleImags[TORTOISE] = imgTorArray;/*kunkun 图片制作*/IMAGE imgLion;vector<IMAGE>imgLionArray;for (int i = 0; i < 12; i++) {sprintf(name, "ret/kun%d.png", i + 1);loadimage(&imgLion, name);imgLionArray.push_back(imgLion);}obstacleImags[LION] = imgLionArray;//初始化障碍物池for (int i = 0; i < OBSTACLE_CUONT; i++) {obstacles[i].exist = false;}//加载下蹲素材loadimage(&imgHeroDown[0], "ret/d1.png");loadimage(&imgHeroDown[1], "ret/d2.png");heroDown = false;//加载柱子// 创建单独的数组或 vector 存储每个障碍物的图片IMAGE imgH1;loadimage(&imgH1, "ret/hook1.png", 63, 310);vector<IMAGE> imgHook1Array;imgHook1Array.push_back(imgH1);obstacleImags[HOOK1] = imgHook1Array;IMAGE imgH2;loadimage(&imgH2, "ret/hook2.png", 63, 310);vector<IMAGE> imgHook2Array;imgHook2Array.push_back(imgH2);obstacleImags[HOOK2] = imgHook2Array;IMAGE imgH3;loadimage(&imgH3, "ret/hook3.png", 63, 310);vector<IMAGE> imgHook3Array;imgHook3Array.push_back(imgH3);obstacleImags[HOOK3] = imgHook3Array;IMAGE imgH4;loadimage(&imgH4, "ret/hook4.png", 63, 310);vector<IMAGE> imgHook4Array;imgHook4Array.push_back(imgH4);obstacleImags[HOOK4] = imgHook4Array;heroBoold = 100;mciSendString("open ret/bk.mp3", NULL, 0, NULL);mciSendString("play ret/bk.mp3 repeat", NULL, 0, NULL);//加载数字for (int i = 0; i < 10; i++) {sprintf(name, "ret/sz/%d.png", i);loadimage(&imgSZ[i], name);}
}void creatObstacle() {srand((unsigned)time(NULL));int i = 0;for ( i = 0; i < OBSTACLE_CUONT; i++) {if (obstacles[i].exist == false) {break;}}if (i >= OBSTACLE_CUONT) {return;}obstacles[i].exist = true;obstacles[i].hited = false;obstacles[i].imgIndex = 0;obstacles[i].passed = false;//obstacles[i].type = (obstacle_type)(rand() % OBSTACLE_TYPE_COUNT);//由于vs的语法要求比较严,所以我们进行强制转换为枚举类型obstacles[i].x = WIN_LONG;obstacles[i].y = 380;obstacles[i].type=(obstacle_type)(rand() % 3);if (obstacles[i].type == HOOK1) {obstacles[i].type = (obstacle_type)((int)(obstacles[i].type)+rand()%4);}//速度,伤害的配置的话,就是各有所需if (obstacles[i].type == TORTOISE) {obstacles[i].speed = 0;obstacles[i].power = 5;}else if (obstacles[i].type == LION) {obstacles[i].speed = 4;obstacles[i].power = 10;}else if (obstacles[i].type >= HOOK1 && obstacles[i].type <= HOOK4) {obstacles[i].speed = 0;obstacles[i].power = 10;obstacles[i].y = 0;}}//玩家和障碍物的碰撞检测处理void checkHit() {for (int i = 0; i < OBSTACLE_CUONT; i++) {if (obstacles[i].exist && obstacles[i].hited == false) {int ax1, ay1, ax2, ay2;//角色的碰撞宽度高度设置if (!heroDown) {ax1 = heroX;ay1 = heroY;ax2 = heroX + imgHero[i].getwidth();ay2 = heroY - imgHero[i].getheight();}else {ax1 = heroX;ay1 = 397 - imgHeroDown[i].getheight();ax2 = heroX + imgHeroDown[i].getwidth();ay2 = 397;}//障碍物的碰撞宽度高度设置int bx1 = obstacles[i].x;int by1 = obstacles[i].y;int bx2 = obstacles[i].x + obstacleImags[obstacles[i].type][obstacles[i].imgIndex].getwidth();int by2 = obstacles[i].y - obstacleImags[obstacles[i].type][obstacles[i].imgIndex].getheight()-10;if (rectIntersect(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2)) {//写到这里,只要我们有图片和障碍物相交在一起就会扣血,因为在屏幕里面,怪是要到屏幕之外才是结束存在的heroBoold -= obstacles[i].power;printf("血量剩余%d\n", heroBoold);obstacles[i].hited = true;}}}}void run() {srand((unsigned)time(NULL));for (int i = 0; i < 2; i++) {bgX[i] -= bgspeed[i];//用于返回到当时图片的位置,这样才可以在后面继续奔跑if (bgX[i] < -WIN_WIDTH) {bgX[i] = 0;}}//玩家帧序列heroIndex = (heroIndex + 1) % 12;//0~11的移动(因为就这么多图片)//实现跳跃(改变玩家的i坐标)//有个上升下降的过程()//因为这个是套在while里面的,随着函数的不断推进,他会一直跳跃,直到触发另外一个if开关if (heroJump) {//下降阶段if (heroY < jumpHeightMax) {herojumpOff = 6;}//一开始处于上升,后面处于下降heroY += herojumpOff;//280初始值if (heroY > 280) {heroJump = false;herojumpOff = -6;}}else if (heroDown) {static int count = 0;int delays[2] = { 15,20 };count++;//由于下蹲就两张图片,所以我们要延续时间(这里可以用静态变量,来延缓帧数)if (count >= delays[heroIndex]) {count = 0;heroIndex++;if (heroIndex >= 2) {heroIndex = 0;heroDown = false;}}}else{ heroIndex = (heroIndex + 1) % 12;}//生成障碍物(如果跟着系统的30ms来整出小奶龙的话,那就满篇小奶龙了)//我们可以计算,这个函数调用的次数*30ms来决定这个乌龟是否生成,比如我们要3s生成一次,那我们就调用100次*30ms就可以了进率1000//那我们要知道调用多少次,用静态变量,因为这样调用完之后销毁也会保存在静态区static int frameCount = 0;static int enemyFre = 50;frameCount++;if (frameCount > enemyFre) {frameCount = 0;enemyFre = 50 + rand() % 50; // 50~99creatObstacle();}//更新奶龙位置//if (torToiseExist) {//	torToiseX -= 4;//	//当奶龙完全让自己出去的时候//	if (torToiseX < -151) {//		torToiseExist = false;//	}//}//更新障碍物的坐标for (int i = 0; i < OBSTACLE_CUONT; i++) {if (obstacles[i].exist) {obstacles[i].x -= obstacles[i].speed + bgspeed[1];if (obstacles[i].x < -300) {obstacles[i].exist = false;}//由于我们的坤坤为了可以出现变动,所以哦我们要加这个变化图片int len = obstacleImags[obstacles[i].type].size();        //type为第几行obstacles[i].imgIndex = (obstacles[i].imgIndex + 1) % len;//(我们不用障碍物的图片数量不一样,所以我们要用len)}}//玩家和障碍物的碰撞检测处理checkHit();
}//渲染游戏背景
void updateBg() {//x轴是确定图片滚到哪里的  y轴是确定位置的//这里的滚动是有这个bgX来变化来进行图片的滚动//由于这个是一次一次吧图片加载出来的,但是我们想一次性一起加载出来这个时候就要添加//BeginBatchDraw()和EndBatchDraw()//一个是开始批量绘制图形,一个是结束开始批量绘制图形putimage(bgX[0], 0, &imgBgs[0]);putimage(bgX[1],397, &imgBgs[1]);}
void jump() {//实现跳跃的时候,坐标是慢慢移动的,而不是直接蹦上去瞬移了heroJump = true;//启动开关update = true;  //在30毫秒过程中,如果在30毫秒点击空格跳跃,则这个立马刷新,直接步入到下面那个if语句然后直接进入,这样可以接受按键
}
void down() {heroDown = true;update = true;heroIndex = 0;
}//处理用户按键输入
void keyEvent() {char ch;//如果有按键按下,则这个kbhit函数是返回为真,没有则反之if (_kbhit()) {/*scanf("%c", &c);*/  //这里用scanf的话这里是要按下回车才可以继续执行,降低了可玩性,所以不用scanfch = _getch();    //这个是scanf的pilus版,这个是不需要按下回车,直接读取这个输入的字符//由于vs版本,这个getch和kbhit都是要加_这个的,不加会报警告if (ch == ' ') {jump();//功能相对独立的要封装成一个函数}else if (ch == 's') {down();}}/*char c;scanf("%c", &c);*///这里会卡死直接这样写,因为他会等待这个玩家输入//解决方法就是判断玩家到底有没有按键按下去,写一个if语句
}void checkover() {if (heroBoold <= 0) {loadimage(0, "ret/kunkunjie.png");FlushBatchDraw();mciSendString("stop ret/bk.mp3", 0, 0, 0);system("pause");//暂停之后刷新游戏角色数据heroBoold = 100;score = 0;mciSendString("play ret/bk.mp3 repeat", 0, 0, 0);}
}void checkpassed() {for (int i = 0; i < OBSTACLE_CUONT; i++) {if (obstacles[i].exist &&obstacles[i].passed == false &&obstacles[i].x + obstacleImags[obstacles[i].type][0].getwidth()) {score++;obstacles[i].passed = true;printf("%d", score);}}
}void updatezhang() 
{//渲染奶龙//if (torToiseExist) {//	putimage(torToiseX, torToiseY, &imgTortoise);//}for (int i = 0; i < OBSTACLE_CUONT;i++) {if (obstacles[i].exist) {//我们要取走第几行呢?我们可以利用我们的枚举类型,这个是对应我们的图片的行数(type对应着枚举->行数)putimage(obstacles[i].x, obstacles[i].y, &obstacleImags[obstacles[i].type][obstacles[i].imgIndex]);}}}
void updateHero() {//这个奔跑和跳跃这个可以实现,但是下蹲不行了,所以需要加一个判断if (!heroDown) {putimage(heroX, heroY, &imgHero[heroIndex]);}else {int y = 395 - 15;putimage(heroX, y, &imgHeroDown[heroIndex]);}}void updateBoold() {drawBloodBar(10, 10, 200, 10, 2, BLUE, DARKGRAY, RED, heroBoold / 100.0);
}void updateScore() {//ASCLL码值 ‘5’-‘0’=5char str[8];sprintf(str, "%d", score);int x = 20;int y = 25;for (int i = 0; str[i] != 0; i++) {int num = str[i] - '0';putimage(x, y, &imgSZ[num]);x += imgSZ[num].getwidth();}
}int main() {init();//显示菜单loadimage(0, "ret/kunkunkai.png");system("pause");int timer = 0;while (1) {/*由于根据游戏设计,这里是要循环多次才可以跳好所以我们这里需要设计一个按键来执行立马跳跃,就不用循环多次了(按键跳跃)*/keyEvent();//这个的好处就是可以随时接受按键接受timer += getDelay();  //升级版sleepif (timer > 30) {timer = 0;update = true;//这里是sleep的升级版本,没进过30秒钟刷新一次,然后进入游戏,在30秒的过程中,这个画面在逐帧加载,这样就可以持续进行画面显示//没有这个,程序就没有逐帧的慢速显示,就会很快很快}if (update) {update = false;BeginBatchDraw();updateBg();//这个里面不要直接放图片,因为我们后续还有撞出窗外的操作要实现//所以不要直接放putimage()在这里//由于玩家需要下蹲则这个代码不行了/*putimage(heroX, heroY, &imgHero[heroIndex]);*/updateHero();updateBoold();updatezhang();updateScore();EndBatchDraw();//这个run是改变这个图片下一次所在的位置的checkover();checkpassed();run();}//这个休眠是让他暂停一会,要不然太快了显示的是一个快影子//休眠的话,如果在30毫秒钟之内按按键的话是不会响应得,所以这个sleep在这个小游戏里面没有什么实质的影响,但是在大型游戏里面是有影响的/*Sleep(30);*///所以我们一般不用sleep}//定义一个死循环不断的对图片进行滚动//system("pause");//用于暂停观察//int system(const char* 命令);return 0;
}

总结

接下来我们的项目就基本结束了,打包安装需要安装插件,感兴趣的可以取收一下微软本地的自带插件,可以在vs管理扩展包下载,这里的源码你直接复制会报错,你得自己学习调节属性和安装插件还有文件的学习,因为天底下哪有免费的午餐

相关文章:

C项目 天天酷跑(下篇)

上篇再博客里面有&#xff0c;接下来我们实现我们剩下要实现的功能 文章目录 碰撞检测 血条的实现 积分计数器 前言 我们现在要继续优化我们的程序才可以使这个程序更加的全面 碰撞的检测 定义全局变量 实现全局变量 void checkHit() {for (int i 0; i < OBSTACLE_C…...

认识Python语言

Python背景介绍 Python的作者是荷兰人 Guido van Rossum&#xff08;龟叔&#xff09;Python正是诞生于1991年Python目前有两个版本&#xff0c;Python2和Python3 代码不完全兼容源文件.py文件名后缀Python的解释如今有多个语言实现&#xff0c;我们常用的是Cpython或者IPytho…...

Python——day09

os模块 sys模块 time模块 logging模块...

机器视觉检测相机基础知识 | 颜色 | 光源 | 镜头 | 分辨率 / 精度 / 公差

注&#xff1a;本文为 “keyence 视觉沙龙中机器视觉检测基础知识” 文章合辑。 机器视觉检测基础知识&#xff08;一&#xff09;颜色篇 视觉检测硬件构成的基本部分包括&#xff1a;处理器、相机、镜头、光源。 其中&#xff0c;和光源相关的最重要的两个参数就是光源颜色和…...

在 CentOS 系统上安装 ClickHouse

在 CentOS 系统上安装 ClickHouse 数据库相对简单&#xff0c;可以通过官方提供的安装包来进行。以下是详细的安装步骤。 1. 更新系统 首先&#xff0c;确保你的系统是最新的&#xff0c;更新软件包和系统库&#xff1a; sudo yum update -y2. 安装依赖库 ClickHouse 需要一…...

FreeSql

官网 1、安装包 Install-Package FreeSql Install-Package FreeSql.Provider.SqlServer2、Program.cs 文件 using FreeSql; using Microsoft.OpenApi.Models; using System.Configuration;var builder WebApplication.CreateBuilder(args);builder.Services.AddController…...

webpakc介绍

介绍 因为不确定打出的前端包所访问的后端IP&#xff0c;需要对项目中IP配置文件单独拿出来&#xff0c;方便运维部署的时候对IP做修改。 因此&#xff0c;需要用webpack单独打包指定文件。 CommonsChunkPlugin module.exports {entry: {app: APP_FILE // 入口文件},outpu…...

自然语言处理基础

目录 一&#xff1a;文本表示 1&#xff1a;词的独热表示 2&#xff1a;词的分布式表示 &#xff08;1&#xff09;最初分布式表示 &#xff08;2&#xff09;&#xff1a;点互信息&#xff08;PMI&#xff09; &#xff08;3&#xff09;奇异值分解&#xff08;SVD&…...

创新引领,从零到一:陶氏减速机在高精密领域的深耕与突破

在高精密机械传动中&#xff0c;陶氏智能正以一款革命性的“第四类”减速机——环面包络多齿啮合减速机&#xff0c;书写着属于自己的传奇篇章。这款减速机不仅代表了技术的飞跃&#xff0c;更是对传统工业自动化领域的一次深刻革新&#xff0c;其影响力横跨航天航空、工业机器…...

神经网络-VggNet

2014年VggNet被推出&#xff0c;获取了ILSVRC2014比赛分类项目的第二名&#xff0c;第一名是GoogleNet&#xff0c;该网络在下节介绍&#xff0c;本节主要介绍VggNet。 VggNet可以称为是一个家族&#xff0c;根据层数的不同包括了A、A-LRN、B、C、D等网络结构&#xff0c;其中…...

服务器数据恢复—Lustre分布式文件系统下服务器节点进水的数据恢复案例

服务器数据恢复环境&故障&#xff1a; 5台节点服务器&#xff0c;每台节点服务器上有一组RAID5阵列。每组RAID5阵列上有6块硬盘&#xff08;其中1块硬盘设置为热备盘&#xff0c;其他5块硬盘为数据盘&#xff09;。上层系统环境为Lustre分布式文件系统。 机房天花板漏水导致…...

实战分享:开发设计文档模版及编写要点

总框架 一、需求类开发设计文档模版 1、PRD链接 PRD文档链接 2、后端设计 1&#xff09;流程图/代码逻辑描述 描述代码逻辑&#xff0c;要求清晰准确&#xff0c;尽量用图表描述 超过3人天工作量的需求必须有流程图 2&#xff09;库表设计 涉及数据库的改动&#xff0c…...

一文彻底拿捏DevEco Studio的使用小技巧

程序员Feri一名12年的程序员,做过开发带过团队创过业,擅长Java相关开发、鸿蒙开发、人工智能等,专注于程序员搞钱那点儿事,希望在搞钱的路上有你相伴&#xff01;君志所向,一往无前&#xff01; 0.安装DevEco Studio DevEco Studio面向HarmonyOS应用及元服务开发者提供的集成开…...

Linux文件目录 --- touch命令创建文件

四、touch命令 touch命令用于创建新文件或更改现有文件的时间戳。文件的时间戳包括最后访问时间、最后修改时间和最后更改时间。 touch [选项] 文件名称 选项作用- a改变档案的读取时间记录-c 假如目的档案不存在&#xff0c;不会建立新的档案-d 指定时间与日期-h影响每个…...

Scala课堂小结

(一)数组&#xff1a; 1.不可变数组 2.创建数组...

git分支与部署环境的关系以及开发规范

一 某金融机构 1.1 分支分类以及作用 1.master master分支为主分支,用于部署生产环境的分支,无论任何时候都要确保master分支的稳定性;master分支由feature及hotfix分支合并,任何时间都不能直接修改代码。目前用于老仿真和老生产,暂时不动。 2.prod 主分支,是master…...

前端入门之VUE--ajax、vuex、router,最后的前端总结

前言 VUE是前端用的最多的框架&#xff1b;这篇文章是本人大一上学习前端的笔记&#xff1b;欢迎点赞 收藏 关注&#xff0c;本人将会持续更新。本人不是学前端的&#xff0c;这个是大一的时候上学的和做的笔记&#xff0c;那个时候学的也蒙&#xff0c;故这里对前端做一个总…...

LabVIEW实现NB-IoT通信

目录 1、NB-IoT通信原理 2、硬件环境部署 3、程序架构 4、前面板设计 5、程序框图设计 6、测试验证 本专栏以LabVIEW为开发平台,讲解物联网通信组网原理与开发方法,覆盖RS232、TCP、MQTT、蓝牙、Wi-Fi、NB-IoT等协议。 结合实际案例,展示如何利用LabVIEW和常用模块实现物联网…...

蓝牙协议——音乐启停控制

手机播放音乐 手机暂停音乐 耳机播放音乐 耳机暂停音乐...

深入理解C++ 容器类

承接Qt/C软件开发项目&#xff0c;高质量交付&#xff0c;灵活沟通&#xff0c;长期维护支持。需求所寻&#xff0c;技术正适&#xff0c;共创完美&#xff0c;欢迎私信联系&#xff01; 引言 C 标准库提供了丰富的容器&#xff08;container&#xff09;类型&#xff0c;用于存…...

Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena

指令微调后的模型不一定在传统Benchmark上取得更好的结果&#xff0c;类似MMLU和HELM。根据人类爱好对齐后的模型&#xff0c;需要新的评测方法。 文章提出了两个主要内容&#xff1a;MT-bench和Chatbot Arena MT-bench是一系列开放式问题&#xff0c;用于评估聊天机器人的多回…...

Qt 的信号槽机制详解:之信号槽引发的 Segmentation Fault 问题拆析(下)

Qt 的信号槽机制详解&#xff1a;之信号槽引发的 Segmentation Fault 问题拆析&#xff08;下&#xff09; 前言一. 信号槽的误用导致崩溃的常见原因1.信号和槽连接的对象被提前释放案例解决方法 2.参数类型不匹配案例解决方法 3. 多线程信号槽使用不当案例解决方法 4. 信号重复…...

测试时计算策略(BON, stepwiseBON, beamsearch, lookahead,混合方法,计算最优扩展,过程奖励模型引导,多数投票)

、Step-wise BoN、Self-Refine、Agent Workflow 一 测试时计算 测试时计算&#xff08;test-time compute&#xff09;&#xff0c;也称为推理计算&#xff0c;是指 LLM 生成提示响应时使用的计算资源。与用于创建和完善模型本身的训练计算不同&#xff0c;每次使用模型时都会…...

设置postgreSQL字段自增

CREATE SEQUENCE ai_mirror_opcode_seq START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; nextval(ai_mirror_opcode_seq) 手动创建序列并设置默认值&#xff1a; 如果你需要更细粒度的控制&#xff0c;可以手动创建一个序列&#xff0c;并将其设置为某个字段的…...

flask-admin的modelview 实现list列表视图中扩展修改状态按钮

背景&#xff1a; 在flask-admin的模型视图&#xff08;modelview 及其子类&#xff09;中如果不想重构UI视图&#xff0c;那么就不可避免的出现默认视图无法很好满足需求的情况&#xff0c;如默认视图中只有“新增”&#xff0c;“编辑”&#xff0c;“选中的”三个按钮。 材…...

强大且灵活的终端工具Tabby的强大功能与详细配置指南

文章目录 前言1. Tabby下载安装2. Tabby相关配置3. Tabby简单操作4. ssh连接Linux4.1 ubuntu系统安装ssh4.2 Tabby远程ssh连接ubuntu 5. 安装内网穿透工具5.1 创建公网地址5.2 使用公网地址远程ssh连接 6. 配置固定公网地址 前言 大家好&#xff01;今天我要给大家安利一个超级…...

dns显示不可用是怎么回事?

在互联网的世界里&#xff0c;DNS(域名系统)扮演着至关重要的角色。它负责将用户输入的网址(域名)转换为服务器的IP地址&#xff0c;从而让用户能够访问到相应的网站。然而&#xff0c;有时用户可能会遇到DNS显示不可用的情况&#xff0c;这不仅影响上网体验&#xff0c;还可能…...

探索Flink动态CEP:杭州银行的实战案例

摘要&#xff1a;本文撰写自杭州银行大数据工程师唐占峰、欧阳武林老师。将介绍 Flink 动态 CEP的定义与核心概念、应用场景、并深入探讨其技术实现并介绍使用方式。主要分为以下几个内容&#xff1a; Flink动态CEP简介 Flink动态CEP的应用场景 Flink动态CEP的技术实现 Flin…...

单机服务和微服务

单体服务 一种软件开发模型&#xff0c;它将所有的服务组件集成在一个独立的系统单位中进行开发、部署和维护。在这种架构中&#xff0c;前端用户界面、后端服务器逻辑、数据库操作等组件通常紧密耦合在一起&#xff0c;形成一个统一的程序。这种架构模式易于开发和部署&#x…...

孔雀鱼和斑马鱼能一起养吗?

在观赏鱼的世界里&#xff0c;孔雀鱼和斑马鱼都是备受鱼友喜爱的热门品种。它们独特的外形和相对容易的饲养条件&#xff0c;使得不少养鱼新手跃跃欲试将它们混养在一起&#xff0c;但这其中实则有诸多因素需要考量。 从生存环境来看&#xff0c;孔雀鱼和斑马鱼有一定的兼容性…...

作业帮基于 Apache DolphinScheduler 3_0_0 的缺陷修复与优化

文|作业帮大数据团队&#xff08;阮文俊、孙建业&#xff09; 背 景 基于 Apache DolphinScheduler &#xff08;以下简称DolphinScheduler&#xff09;搭建的 UDA 任务调度平台有效支撑了公司的业务数据开发需求&#xff0c;处理着日均百万级别的任务量。 整个 UDA 的架构如…...

【LC】111. 二叉树的最小深度

题目描述&#xff1a; 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明&#xff1a;叶子节点是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;2示…...

HarmonyOS NEXT 实战之元服务:静态案例效果--- 歌手推荐

背景&#xff1a; 前几篇学习了元服务&#xff0c;后面几期就让我们开发简单的元服务吧&#xff0c;里面丰富的内容大家自己加&#xff0c;本期案例 仅供参考 先上本期效果图 &#xff0c;里面图片自行替换 效果图1完整代码案例如下&#xff1a; import { authentication } …...

selenium自动化测试(超详细~)

最近也有很多人私下问我&#xff0c;selenium学习难吗&#xff0c;基础入门的学习内容很多是3以前的版本资料&#xff0c;对于有基础的人来说&#xff0c;3到4的差别虽然有&#xff0c;但是不足以影响自己&#xff0c;但是对于没有学过的人来说&#xff0c;通过资料再到自己写的…...

Spring Boot教程之三十一:入门 Web

Spring Boot – 入门 Web 如今&#xff0c;大多数应用程序都需要模型-视图-控制器(MVC) 架构来满足各种需求&#xff0c;例如处理用户数据、提高应用程序效率、为应用程序提供动态特性。它主要用于构建桌面图形用户界面 (GUI)&#xff0c;但现在越来越流行用于构建基于 Web 的…...

【每日学点鸿蒙知识】指纹识别隐藏背面、数组内部值变化刷新UI、键盘输入类型、跨组件路由、C++20特性支持

1、HarmonyOS 指纹识别情况下&#xff0c;隐藏背面内容&#xff1f; 有一个场景&#xff0c;在指纹识别验证页面时候&#xff0c;此时需要用户看不到背面的内容&#xff0c;请问应该怎么处理这块。或者有什么方案&#xff0c;可以通过window&#xff0c;获取到当前页面的page&…...

Python数据处理——re库与pydantic的使用总结与实战,处理采集到的思科ASA防火墙设备信息

目录 Python正则表达式re库的基本用法 引入re库 各函数功能 总结 使用方法举例 正则表达式语法与书写方式 正则表达式的常用操作符 思科ASA防火墙数据 数据1 数据2 书写正则表达式 Python中pydantic的使用 导入基础数据模板 根据数据采集目标定义Pydantic数据类型…...

centos系统如何安装kubectl和部署kube-apiserver

1.使用 yum 安装&#xff08;推荐&#xff09; 添加 Kubernetes 软件源&#xff1a; 首先&#xff0c;你需要添加 Kubernetes 的官方 YUM 软件源。这可以通过下载并安装 kubernetes.repo 文件来实现。 shell cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo [k…...

【源码编译】windows下mingw64安装以及cmake调用

最近因为安装MIRTK库&#xff0c;太多第三方依赖了&#xff0c;太折磨了&#xff0c;学习了使用Cmake&#xff0c;有些库又需要Fortran编译器&#xff0c;VS2022里面装了但又调用不了&#xff0c;也不知道为什么&#xff0c;最后装的mingw64&#xff0c;记录一下。 1、mingw64安…...

HarmonyOS NEXT 实战之元服务:静态案例效果---最近播放音乐

背景&#xff1a; 前几篇学习了元服务&#xff0c;后面几期就让我们开发简单的元服务吧&#xff0c;里面丰富的内容大家自己加&#xff0c;本期案例 仅供参考 先上本期效果图 &#xff0c;里面图片自行替换 效果图1完整代码案例如下&#xff1a; Index import { authentica…...

【QT开发自制小工具】PDF/图片转excel---调用百度OCR API接口

前言 前几年WPS还可以免费处理5页以内的PDF转excel&#xff0c;现在必须付费了&#xff0c;而且百度其他在线的PDF转excel都是要收费的&#xff0c;刚好前几年调研过百度OCR的高精度含位置接口&#xff0c;依然是每天可以免费调用50次&#xff0c;本篇是基于此接口&#xff0c;…...

uniapp 基于xgplayer(西瓜视频) + renderjs开发,实现APP视频播放

背景&#xff1a;在uniapp中因原生video组件功能有限&#xff0c;选择引入xgplayer库来展示视频播放等功能。并且APP端无法操作dom&#xff0c;所以使用了renderjs。 其他的不多说&#xff0c;主要列举一下renderjs中需要注意的点&#xff1a; 1、使用&#xff1a;在标签后&…...

[1111].集成开发工具Pycharm安装与使用

所有博客大纲 后端学习大纲 Python大纲 1.下载&#xff1a; 官方下载地址 2.安装&#xff1a; 1.双击exe文件&#xff0c;然后下一步选择安装目录 2.选择桌面快捷方式及安装&#xff1a; 3.安装完成 3.启动&#xff1a; 4.设置&#xff1a; 4.1.设置运行时环境&#xff1a;…...

【玩转OCR】 | 腾讯云智能结构化OCR在多场景的实际应用与体验

文章目录 引言产品简介产品功能产品优势 API调用与场景实践图像增强API调用实例发票API调用实例其他场景 结语相关链接 引言 在数字化信息处理的时代&#xff0c;如何高效、精准地提取和结构化各类文档数据成为了企业和政府部门的重要需求。尤其是在面对海量票据、证件、表单和…...

红狮金业:2024年尾声,黄金市场需要关注的消息面

随着2024年的尾声渐近&#xff0c;全球金融市场在美联储的年度最后一次降息决策中迎来了新的波澜。上周&#xff0c;美联储宣布降息&#xff0c;而美联储主席鲍威尔随后的发言更是在市场上掀起了巨大波动。他透露&#xff0c;美联储计划在明年放缓降息步伐&#xff0c;可能仅实…...

使用BCrypt进行密码加密

1. 添加依赖&#xff1a; 在pom.xml文件中添加Spring Security依赖&#xff0c;以使用BCryptPasswordEncoder。 <!-- Spring Security 依赖 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-secu…...

《智启新材热学性能优化之路:人工智能的神奇力量》

在当今科技飞速发展的时代&#xff0c;材料科学与人工智能的融合正成为创新的前沿阵地。其中&#xff0c;利用人工智能优化材料的热学性能&#xff0c;为众多领域的突破带来了新的曙光&#xff0c;从航空航天的高效热防护到电子设备的散热管理&#xff0c;其影响深远且广泛&…...

IIC驱动EEPROM

代码参考正点原子 i2c_dri:主要是三段式状态机的编写 module iic_dri#(parameter SLAVE_ADDR 7b1010000 , //EEPROM从机地址parameter CLK_FREQ 26d50_000_000, //模块输入的时钟频率parameter I2C_FREQ 18d250_000 //IIC_SCL的时钟频率)( …...

目标检测——基于yolov8和pyqt的螺栓松动检测系统

目录 1.项目克隆和环境配置1.1 我这里使用的是v8.0.6版本1.2 项目代码结构介绍 2.数据集介绍2.1 数据集采集2.2采集结果介绍 3.模型训练4.pyqt界面设计4.1 界面内容介绍4.2 界面实现 5.操作中的逻辑实现5.1 图片检测5.2 文件夹检测5.3 视频检测和摄像头检测 6. 效果展示 1.项目…...

JVM系列(十三) -常用调优工具介绍

最近对 JVM 技术知识进行了重新整理&#xff0c;再次献上 JVM系列文章合集索引&#xff0c;感兴趣的小伙伴可以直接点击如下地址快速阅读。 JVM系列(一) -什么是虚拟机JVM系列(二) -类的加载过程JVM系列(三) -内存布局详解JVM系列(四) -对象的创建过程JVM系列(五) -对象的内存分…...