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管理擴展包下載,這里的源碼你直接復制會報錯,你得自己學習調節屬性和安裝插件還有文件的學習,因為天底下哪有免費的午餐

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/64093.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/64093.shtml
英文地址,請注明出處:http://en.pswp.cn/web/64093.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

論文解讀——掌紋生成網絡 RPG-Palm升級版PCE-Palm

該文章是2023年論文RPG-Palm的升級版 論文&#xff1a;PCE-Palm: Palm Crease Energy Based Two-Stage Realistic Pseudo-Palmprint Generation 作者&#xff1a;Jin, Jianlong and Shen, Lei and Zhang, Ruixin and Zhao, Chenglong and Jin, Ge and Zhang, Jingyun and Ding,…

代碼隨想錄算法【Day2】

Day2 1.掌握滑動窗口法 2.模擬題&#xff0c;堅持循環不變量原則 209 長度最小的子數組 暴力法&#xff1a; class Solution { public:int minSubArrayLen(int target, vector<int>& nums) {//暴力法int i, j; //i代表起始點&#xff0c;j代表終止點int sum; //…

android——屏幕適配

一、屏幕適配的重要性 在 Android 開發中&#xff0c;屏幕適配是非常關鍵的。因為 Android 設備具有各種各樣的屏幕尺寸、分辨率和像素密度。如果沒有進行良好的屏幕適配&#xff0c;應用可能會出現顯示不完整、元素拉伸或壓縮變形、字體大小不合適等問題&#xff0c;極大地影響…

oscp學習之路,Kioptix Level2靶場通關教程

oscp學習之路&#xff0c;Kioptix Level2靶場通關教程 靶場下載&#xff1a;Kioptrix Level 2.zip 鏈接: https://pan.baidu.com/s/1gxVRhrzLW1oI_MhcfWPn0w?pwd1111 提取碼: 1111 搭建好靶場之后輸入ip a看一下攻擊機的IP。 確定好本機IP后&#xff0c;使用nmap掃描網段&…

第二十六周機器學習筆記:PINN求正反解求PDE文獻閱讀——正問題

第二十六周周報 摘要Abstract文獻閱讀《Physics-informed neural networks: A deep learning framework for solving forward and inverse problems involving nonlinear partial differential equations》1. 引言2. 問題的設置3.偏微分方程的數據驅動解3.1 連續時間模型3.1.1 …

【安全編碼】Web平臺如何設計防止重放攻擊

我們先來做一道關于防重放的題&#xff0c;答案在文末 防止重放攻擊最有效的方法是&#xff08; &#xff09;。 A.對用戶密碼進行加密存儲使用 B.使用一次一密的加密方式 C.強制用戶經常修改用戶密碼 D.強制用戶設置復雜度高的密碼 如果這道題目自己拿不準&#xff0c;或者…

中關村科金智能客服機器人如何解決客戶個性化需求與標準化服務之間的矛盾?

客戶服務的個性化和標準化之間的矛盾一直是一個挑戰。一方面&#xff0c;企業需要提供標準化的服務以保持運營效率和成本控制&#xff1b;另一方面&#xff0c;為了提升客戶滿意度和忠誠度&#xff0c;企業又必須滿足客戶的個性化需求。為此&#xff0c;中關村科金推出了智能客…

OPPO Android面試題及參考答案 (上)

性能優化方面,講一下圖片內存占用計算,以及如何避免持有不必要的引用。 在 Android 中,計算圖片內存占用主要與圖片的尺寸和像素格式有關。對于一張位圖(Bitmap),其內存占用大小可以通過以下方式估算:內存占用 = 圖片寬度 圖片高度 每個像素占用字節數。例如,常見的 …

Agent 案例分析:金融場景中的智能體-螞蟻金服案例(10/30)

Agent 案例分析&#xff1a;金融場景中的智能體 —螞蟻金服案例 一、引言 在當今數字化時代&#xff0c;金融行業正經歷著深刻的變革。隨著人工智能技術的飛速發展&#xff0c;智能體&#xff08;Agent&#xff09;在金融場景中的應用越來越廣泛。螞蟻金服作為金融科技領域的…

ElasticSearch 的工作原理

理解 ElasticSearch 的工作原理需要從索引、搜索、以及其背后的核心機制幾個方面來探討。 1. ElasticSearch 是什么&#xff1f; ElasticSearch 是一個分布式搜索和分析引擎&#xff0c;適用于各種類型的數據&#xff0c;例如文本、數值、地理位置、結構化或非結構化數據。它基…

STM32F407 | Embedded IDE01 - vscode搭建Embedded IDE開發環境(支持JLINK、STLINK、DAPLINK)

導言 Embedded IDE官網:https://em-ide.com/docs/intro 我猜肯定有部分人使用SI Keil開發STM32項目&#xff0c;也有vscode Keil開發STM32程序。SI或vscode編寫代碼&#xff0c;然后切換Keil編譯、下載、調試程序。有一段時間&#xff0c;我也是這么干的。但是&#xff0c;程…

光譜相機的工作原理

光譜相機的工作原理主要基于不同物質對不同波長光的吸收、反射和透射特性存在差異&#xff0c;以下是其具體工作過程&#xff1a; 一、光的收集 目標物體在光源照射下&#xff0c;其表面會對光產生吸收、反射和透射等相互作用。光譜相機的光學系統&#xff08;如透鏡、反射鏡…

ThinkPHP接入PayPal支付

ThinkPHP 5接入PayPal 支付&#xff0c;PayPal的流程是服務器請求Paypal的接口下單&#xff08;需要傳訂單id/支付成功的重定向地址/支付失敗的重定向地址&#xff09;&#xff0c;接會返回一個支付地址&#xff0c;項目服務器把地址返給用戶&#xff0c;用戶打開鏈接登錄Paypa…

stream流的toMap

假設有這么一個類: import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors;public class Student {private int id;private String name;public Student(int id, String name) {this.id id;…

html + css 淘寶網實戰

之前有小伙伴說&#xff0c;淘寶那么牛逼你會寫代碼&#xff0c;能幫我做一個一樣的淘寶網站嗎&#xff0c;好呀&#xff0c;看我接下來如何給你做一個淘寶首頁。hahh,開個玩笑。。。學習而已。 在進行html css編寫之前 先了解下網頁的組成和網頁元素的尺寸吧 1.網頁的組成 …

神經網絡、深度學習、卷積神經網絡

好的&#xff01;我會盡量詳細且易懂地為你解釋這些概念&#xff0c;并在最后用簡單直白的語言總結一下。 1. 神經網絡思想 神經網絡是靈感來自于生物大腦神經元的工作原理&#xff0c;是一種模仿人類大腦處理信息的方式來設計的數學模型。我們的大腦由億萬個神經元組成&…

設計模式01:創建型設計模式之單例、簡單工廠的使用情景及其基礎Demo

一、單例模式 1.情景 連接字符串管理 2.好處 代碼簡潔&#xff1a;可全局訪問連接字符串。性能優化&#xff1a;一個程序一個連接實例&#xff0c;避免反復創建對象&#xff08;連接&#xff09;和銷毀對象&#xff08;連接&#xff09;。線程安全&#xff1a;連接對象不會…

【不太正常的題】LeetCode.232:用棧的函數接口實現隊列

&#x1f381;個人主頁&#xff1a;我們的五年 &#x1f50d;系列專欄&#xff1a;初階數據結構刷題 &#x1f389;歡迎大家點贊&#x1f44d;評論&#x1f4dd;收藏?文章 &#x1f697; 1.問題描述&#xff1a; 題目中說了只能使用兩個棧實現隊列&#xff0c;并且只能使用…

Linux搭建text-generation-webui框架,安裝通義千問大模型,開放對外api,voxta測試對話圖文教程

目錄 text-generation-webui部分 開放對外API 通義千問部分 遠程API對話測試部分 text-generation-webui部分 本來不想發這個文章的&#xff0c;但是自己部署的時候看了挺多人的帖子&#xff0c;很多發的不全面&#xff0c;要么就是跟著他們流程走有些小問題啥的&#xff…

QT程序發布后,mysql在其它電腦設備無法連接數據庫

QT程序發布后&#xff0c;mysql在其它電腦設備無法連接數據庫 D:\mysql-5.7.24-winx64\lib, mysql-5.7.24-winx64是一個壓縮包&#xff0c;用于啟動mysql服務&#xff0c;創建數據庫 壓縮包 解決方法&#xff1a; 拷貝庫到exe的相同目錄&#xff0c;libmysql.dll,libmysql.li…