广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++怎么利用easyx图形库实现天天酷跑小游戏
  • 682
分享到

C++怎么利用easyx图形库实现天天酷跑小游戏

2023-07-05 08:07:35 682人浏览 安东尼
摘要

这篇文章主要介绍“c++怎么利用easyx图形库实现天天酷跑小游戏”,在日常操作中,相信很多人在C++怎么利用easyx图形库实现天天酷跑小游戏问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++怎么利用ea

这篇文章主要介绍“c++怎么利用easyx图形库实现天天酷跑小游戏”,在日常操作中,相信很多人在C++怎么利用easyx图形库实现天天酷跑小游戏问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++怎么利用easyx图形库实现天天酷跑小游戏”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

开发日志

创建项目

导入素材

创建游戏界面

从用户界面入手

选择图形库或者其他引擎,酷跑是基于“easyx”图形库的

1)创建游戏窗口

2)设计游戏背景

a.三重背景不同的速度移动

b.循环滚动背景的实现

3)实现游戏背景

a.加载背景资源

b.渲染(实现打印图片的效果)背景知识:坐标

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

实现玩家奔跑

实现玩家跳跃

实现随机小乌龟

创建结构体结构类型

使用障碍物结构体后重新初始化

封装后多个障碍物的显示

实现玩家的下蹲技能

添加柱子障碍物

代码实现

//#undef UNICODE//#undef _UNICODE#include <stdio.h>#include <graphics.h>#include <coNIO.h>#include <vector> //c++ 长度可变的数组#include "tools.h"using namespace std; //声明命名空间#define WIN_SCORE 10#define WIN_WIDTH 1012 //定义宏 便于后期维护与处理#define WIN_HEIGHT 396#define OBSTACLE_COUNT 10IMAGE imgBgs[3];//背景图片——创建图片数组int bgX[3];//背景图片的X坐标(不断变化)int bgSpeed[3] = { 1,2,4 };//控制3个背景不同速度IMAGE imgHeros[12];//人物不断奔跑的实现int heroX;//玩家的X坐标int heroY;//玩家的Y坐标int heroIndex;//玩家奔跑的图片帧序号bool heroJump;//表示玩家正在跳跃int jumpHeightMax;//跳跃的最大高度int heroJumpOff;//跳跃偏移量int update;//表示是否需要马上刷新画面//IMAGE imgTortoise; //小乌龟//int torToiseX; //小乌龟的水平坐标//int torToiseY; //小乌龟的竖直坐标//bool torToiseExist; //当前窗口是否有小乌龟int heroBlood; //定义玩家血量int score;typedef enum {TORTOISE, //乌龟 0LION, //狮子 1HOOK1,HOOK2,HOOK3,HOOK4,OBSTACLE_TYPE_COUNT //边界 6}obstacle_type;// 相当于 IMAGE obstacleImgs[3][5]vector<vector<IMAGE>>obstacleImgs; //二维数组 存放所有障碍物的各个图片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;//解决障碍物bug(柱子与狮子在一起)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);//%03d占3位,不足3位自动补0//#undef _UNICODE  loadimage(&imgBgs[i], name);//把3个图片加载到了图片数组的位置bgX[i] = 0;}//加载Hero奔跑的图片帧素材for (int i = 0; i < 12; i++) {sprintf(name, "res/hero%d.png", i + 1);loadimage(&imgHeros[i], name);} //设置玩家的初始位置heroX = WIN_WIDTH * 0.5 - imgHeros[0].getwidth() * 0.5;//X坐标:屏幕宽度的一半减去人物宽度的一半heroY = 345 - imgHeros[0].getheight();//Y坐标:脚底坐标减去人物高度heroIndex = 0;heroJump = false;jumpHeightMax = 345 - imgHeros[0].getheight() - 120;heroJumpOff = -4;update = true;加载小乌龟素材//loadimage(&imgTortoise, "res/t1.png");//torToiseExist = false;//torToiseY = 345 - imgTortoise.getheight() + 5;IMAGE imgTort;loadimage(&imgTort, "res/t1.png");vector<IMAGE>imgTortArray;imgTortArray.push_back(imgTort);//添加图片obstacleImgs.push_back(imgTortArray);IMAGE imgLion;vector<IMAGE>imgLionArray;for (int i = 0; i < 6; i++) {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, 250, 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 creatObstacle() {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_COUNT);obstacles[i].type = (obstacle_type)(rand() % 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 = 345 + 5 - obstacleImgs[obstacles[i].type][0].getheight();if (obstacles[i].type == TORTOISE) {obstacles[i].speed = 0;obstacles[i].power = 5; //随意}else if (obstacles[i].type == LION) {obstacles[i].speed = 1;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;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 = 345 - imgHeroDown[heroIndex].getheight();a2x = heroX + imgHeroDown[heroIndex].getwidth() - off;a2y = 345;}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 run() {for (int i = 0; i < 3; i++) {bgX[i] -= bgSpeed[i];//3个背景移动的速度不同if (bgX[i] < -WIN_WIDTH) {bgX[i] = 0;}}//实现跳跃if (heroJump) {if (heroY < jumpHeightMax) //达到最大跳跃高度 跳跃偏移量为正 向下跳跃{ heroJumpOff = 4;}heroY += heroJumpOff;if (heroY > 345 - imgHeros[0].getheight()) //到达地面 跳跃结束{  heroJump = false;heroJumpOff = -4; // 偏移量初始化}}else if (heroDown) { //人物下蹲static int count = 0;int delays[2] = { 8,30 }; //设置下蹲的时间不一样count++;if (count >= delays[heroIndex]) {count = 0;heroIndex++;if (heroIndex >= 2) {heroIndex = 0;heroDown = false;}}}else{ //不跳跃heroIndex = (heroIndex + 1) % 12; //12张图片循环播放完成一系列动作}//创建障碍物static int frameCount = 0;static int enemyFre = 50;frameCount++;if (frameCount > enemyFre){frameCount = 0;//if (!torToiseExist) { //避免屏幕同时出现多个小乌龟//torToiseExist = true;//torToiseX = WIN_WIDTH;//enemyFre=rand()%301+200; //每200-500帧随机出现一只龟//}enemyFre = rand() % 50 + 50;creatObstacle();}//if (torToiseExist) {////更新小乌龟位置//torToiseX -= bgSpeed[2];//if (torToiseX < -imgTortoise.getwidth()) {//torToiseExist = false;//}//}//更新所有障碍物的坐标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;}}//玩家和障碍物的“碰撞检测”处理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() {update = true;heroDown = true;heroIndex = 0;}//处理用户按键的输入void keyEvent() {//char c;//scanf("%c", &c);   会直接阻塞程序的执行if (GetAsyncKeyState(VK_UP)){ //虚拟键jump();}else if (GetAsyncKeyState(VK_DOWN)) {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]);}}}void updateHero() {if (!heroDown) { //不处于下蹲状态——奔跑跳跃putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);}else {int y = 345 - 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");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 checkScore() {for (int i = 0; i < OBSTACLE_COUNT; i++) {if (obstacles[i].exist && obstacles[i].passed == false && obstacles[i].x + obstacleImgs[obstacles[i].type][0].getwidth() < heroX && obstacles[i].hited == false) {score++; obstacles[i].passed = true;printf("score:%d\n", score);}}}void updateScore() {char 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 repeat", 0, 0, 0);}}int main(void){init();//显示初始化面loadimage(0, "res/over.png");system("pause");int timer = 0;while (1) {keyEvent();timer += getDelay();//此函数返回距离上一次调用间隔的时间,第一次返回0if (timer > 30) { //30毫秒刷新时间timer = 0;update = true;}if (update) {update = false;BeginBatchDraw();//这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到绘图窗口上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。updateBg();//putimagePNG2(heroX, heroY, &imgHeros[heroIndex]);updateHero();updateEnemy();updateBloodBar();updateScore();checkWin();EndBatchDraw();//这个函数用于结束批量绘制,并执行未完成的绘制任务。   这两个函数主要为了消除闪烁。checkOver();checkScore();run();}//Sleep(30); //休眠}system("pause");return 0;}##  tool头文件```javascript#include <stdio.h>#include <windows.h>#include "tools.h"#include <mmsystem.h>#pragma comment(lib, "winmm.lib")int getDelay() {    static unsigned long long lastTime = 0;    unsigned long long currentTime = GetTickCount();    if (lastTime == 0) {        lastTime = currentTime;        return 0;    }    else {        int ret = currentTime - lastTime;        lastTime = currentTime;        return ret;    }}// 载入PNG图并去透明部分void putimagePNG(int  picture_x, int picture_y, IMAGE* picture) //x为载入图片的X坐标,y为Y坐标{    DWord* dst = GetImageBuffer();    // GetImageBuffer()函数,用于获取绘图设备的显存指针,EASYX自带    DWORD* draw = GetImageBuffer();    DWORD* src = GetImageBuffer(picture); //获取picture的显存指针    int picture_width = picture->getwidth(); //获取picture的宽度,EASYX自带    int picture_height = picture->getheight(); //获取picture的高度,EASYX自带    int graphWidth = getwidth();       //获取绘图区的宽度,EASYX自带    int graphHeight = getheight();     //获取绘图区的高度,EASYX自带    int dstX = 0;    //在显存里像素的角标    // 实现透明贴图 公式: Cp=αp*FP+(1-αp)*BP , 贝叶斯定理来进行点颜色的概率计算    for (int iy = 0; iy < picture_height; iy++)    {        for (int ix = 0; ix < picture_width; ix++)        {            int srcX = ix + iy * picture_width; //在显存里像素的角标            int sa = ((src[srcX] & 0xff000000) >> 24); //0xAArrggbb;AA是透明度            int sr = ((src[srcX] & 0xff0000) >> 16); //获取RGB里的R            int sg = ((src[srcX] & 0xff00) >> 8);   //G            int sb = src[srcX] & 0xff;              //B            if (ix >= 0 && ix <= graphWidth && iy >= 0 && iy <= graphHeight && dstX <= graphWidth * graphHeight)            {                dstX = (ix + picture_x) + (iy + picture_y) * graphWidth; //在显存里像素的角标                int dr = ((dst[dstX] & 0xff0000) >> 16);                int dg = ((dst[dstX] & 0xff00) >> 8);                int db = dst[dstX] & 0xff;                draw[dstX] = ((sr * sa / 255 + dr * (255 - sa) / 255) << 16)  //公式: Cp=αp*FP+(1-αp)*BP  ; αp=sa/255 , FP=sr , BP=dr                    | ((sg * sa / 255 + dg * (255 - sa) / 255) << 8)         //αp=sa/255 , FP=sg , BP=dg                    | (sb * sa / 255 + db * (255 - sa) / 255);              //αp=sa/255 , FP=sb , BP=db            }        }    }}// 适用于 y <0 以及x<0的任何情况void putimagePNG2(int x, int y, IMAGE* picture) {    IMAGE imgTmp;    if (y < 0) {        SetWorkingImage(picture);        getimage(&imgTmp, 0, -y,            picture->getwidth(), picture->getheight() + y);        SetWorkingImage();        y = 0;        picture = &imgTmp;    }    if (x < 0) {        SetWorkingImage(picture);        getimage(&imgTmp, -x, 0, picture->getwidth() + x, picture->getheight());        SetWorkingImage();        x = 0;        picture = &imgTmp;    }     putimagePNG(x, y, picture);}// 适用于 y <0 以及y>0的任何情况void putimagePNG2(int x, int y, int winWidth, IMAGE* picture) {    IMAGE imgTmp;    if (y < 0) {        SetWorkingImage(picture);        getimage(&imgTmp, 0, -y,            picture->getwidth(), picture->getheight() + y);        SetWorkingImage();        y = 0;        picture = &imgTmp;    }    if (x < 0) {        SetWorkingImage(picture);        getimage(&imgTmp, -x, 0, picture->getwidth() + x, picture->getheight());        SetWorkingImage();        x = 0;        picture = &imgTmp;    }    else if (x >= winWidth) {        return;    }    else if (x > winWidth-picture->getwidth()) {        SetWorkingImage(picture);        getimage(&imgTmp, 0, 0, winWidth - x, picture->getheight());        SetWorkingImage();        picture = &imgTmp;    }    putimagePNG(x, y, picture);}//设A[x01,y01,x02,y02]  B[x11,y11,x12,y12].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);}void  preLoadSound(const char* name) {    char cmd[512];    sprintf_s(cmd, sizeof(cmd), "open %s alias %s-1", name, name);    mciSendString(cmd, 0, 0, 0);    sprintf_s(cmd, sizeof(cmd), "open %s alias %s-2", name, name);    mciSendString(cmd, 0, 0, 0);}void  playSound(const char* name) {    static int index = 1;    char cmd[512];    if (index == 1) {        sprintf_s(cmd, sizeof(cmd), "play %s-1", name);        mciSendString(cmd, 0, 0, 0);        sprintf_s(cmd, sizeof(cmd), "close %s-2", name);        mciSendString(cmd, 0, 0, 0);        sprintf_s(cmd, sizeof(cmd), "open %s alias %s-2", name, name);        mciSendString(cmd, 0, 0, 0);        index++;    }    else if (index == 2) {        sprintf_s(cmd, sizeof(cmd), "play %s-2", name);        mciSendString(cmd, 0, 0, 0);        sprintf_s(cmd, sizeof(cmd), "close %s-1", name);        mciSendString(cmd, 0, 0, 0);        sprintf_s(cmd, sizeof(cmd), "open %s alias %s-1", name, name);        mciSendString(cmd, 0, 0, 0);        index = 1;    }}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);}

到此,关于“C++怎么利用easyx图形库实现天天酷跑小游戏”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: C++怎么利用easyx图形库实现天天酷跑小游戏

本文链接: https://www.lsjlt.com/news/350597.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++怎么利用easyx图形库实现天天酷跑小游戏
    这篇文章主要介绍“C++怎么利用easyx图形库实现天天酷跑小游戏”,在日常操作中,相信很多人在C++怎么利用easyx图形库实现天天酷跑小游戏问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++怎么利用ea...
    99+
    2023-07-05
  • C++利用easyx图形库实现创意天天酷跑小游戏
    目录天天酷跑开发日志代码实现天天酷跑 这是siren第一次编写基于 “easyx”图形库 的小游戏(需下载easyx)。如果你想学习如何使用各种图形库或者其他...
    99+
    2023-03-03
    C++ easyx实现酷跑游戏 C++ easyx 酷跑 C++ easyx游戏
  • c++使用Easyx图形库是怎么实现飞机大战
    这期内容当中小编将会给大家带来有关c++使用Easyx图形库是怎么实现飞机大战,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。公共的头文件        common...
    99+
    2023-06-22
  • 怎么利用C语言实现井字棋小游戏
    本篇内容主要讲解“怎么利用C语言实现井字棋小游戏”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么利用C语言实现井字棋小游戏”吧!推荐阅读顺序(不建议跳过)先看实现之后的界面 —— 然后看分析程...
    99+
    2023-06-20
  • Linux在怎么使用curses图形库实现一个贪吃蛇游戏
    这篇文章将为大家详细讲解有关Linux在怎么使用curses图形库实现一个贪吃蛇游戏,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。在ubuntu下安装curses图形库命令sudo ...
    99+
    2023-06-15
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作