EeayX是针对 C/C++ 的简单图形库插件,本项目基于easyX游戏框架下实现俄罗斯方块游戏。
俄罗斯方块功能实现中主要运用了二维数组的循环遍历。能够实现基本功能,暂未实现旋转
c语言系列专栏:c语言之路重点知识整合
更多【c语言】小项目:
【c语言】贪吃蛇游戏
【c语言小项目】基于easyX实现的《是男人就下一百层》小游戏
创作不易,本篇文章如果帮助到了你,还请点赞支持一下♡><)!!
主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步!
给大家跳段街舞感谢支持!ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ
目录
运行结果:
代码:
main.cpp
game_function.cpp
date_type.h
game_function.h
global_var.h
图片文件:
EasyX游戏框架:
运行结果:
代码:
main.cpp
#define _CRT_SECURE_NO_WARNINGS 1#include #include #include #include#include#include#include#include#include "game_function.h"/*游戏界面绘制*/void gamePaint();/*游戏初始化绘制*/void gameInit();/*游戏定时处理*/void gameInterval();/*游戏键盘按下*/void gameKeypress(int key);/*游戏鼠标按下*/void gameMouseDown(int mouseX, int mouseY);/*游戏鼠标右键按下*/void gameMouseRightDown(int mouseX, int mouseY);/*游戏鼠标抬起*/void gameMouseUp(int mouseX, int mouseY);/*游戏鼠标移动*/void gameMousemove(int mouseX, int mouseY);/*含透明的图的绘制x为要载入图片的X坐标,y为Y坐标*/void drawImage(intpicture_x, int picture_y, IMAGE* picture);/*调整图片透明度角度转弧度:PI/180*角度弧度转角度:180/PI*弧度*/void drawImageAlpha(int x0, int y0, IMAGE* img, double f);/*两个矩形碰撞检测即两个矩形是否相交。 x1, y1, w1, h1是第一个矩形的xy宽高的四个参数 x2, y2, w2, h2是第二个矩形的xy宽高的四个参数 返回0代表不相交 返回1代表相交*/int testHit(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2);/*设置100即每隔100毫秒刷新以下界面绘图。*/int interval = 100;//TODO: 1 设置定时器时间间隔(单位毫秒)// TODO: 1 设置窗口: 宽度 高度int screenWidth = 470;int screenHeight = 616;int stop = 0;//是否停止游戏//-----------------------------------//int times = 0;/*初始化游戏 */void initgame(){srand((unsigned)time(NULL));//随机数初始化setbkcolor(NULL);//背景色setbkmode(TRANSPARENT);// 设置背景混合模式: TRANSPARENT为透明gameInit();}/*界面绘图演示案例*//*绘制显示游戏界面*/void paint(){BeginBatchDraw();//打开双缓冲cleardevice();// 清屏gamePaint();//-----------------------------//EndBatchDraw();//关闭双缓冲}/*游戏运行*/void run(){ExMessage msg;//ExMessage key;while (1)// 游戏主循环可借助break 结束循环{if (peekmessage(&msg, -1, true)){switch (msg.message){case WM_MOUSEMOVE://鼠标移动gameMousemove(msg.x, msg.y);break;case WM_LBUTTONDOWN://左键按下gameMouseDown(msg.x, msg.y);break;case WM_LBUTTONUP://左键抬起gameMouseUp(msg.x, msg.y);break;case WM_LBUTTONDBLCLK://左键双击break;case WM_RBUTTONDOWN://右键按下break;case WM_RBUTTONUP://右键抬起gameMouseRightDown(msg.x, msg.y);break;case WM_RBUTTONDBLCLK://右键双击break;case WM_KEYDOWN:gameKeypress(msg.vkcode);break;}paint();continue;}//------时间处理 勿动-----------//Sleep(1);times++;if (times % (interval / 10) != 0) {continue;}times = 0;if (stop){break;}gameInterval();//-------------------------------//paint();// 刷新显示游戏界面}}/*绘制透明背景图*/void drawImage(intpicture_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 > 24); //0xAArrggbb;AA是透明度int sr = ((src[srcX] & 0xff0000) >> 16); //获取RGB里的Rint sg = ((src[srcX] & 0xff00) >> 8); //Gint sb = src[srcX] & 0xff;//Bif (ix >= 0 && ix = 0 && iy <= graphHeight && dstX <= graphWidth * graphHeight){dstX = (ix + picture_x) + (iy + picture_y) * graphWidth; //在显存里像素的角标if (dstX > 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) <getwidth();qheight = img->getheight();//P图为背景图,RS为目标图片static IMAGE RS(qwidth, qheight);static IMAGE P(qwidth, qheight);//背景图的绘制getimage(&P, x0, y0, qwidth, qheight);//获取指针,作为透明度计算DWORD* M = GetImageBuffer(&P);DWORD* N = GetImageBuffer(img);DWORD* R = GetImageBuffer(&RS);// 开启批量绘图模式,解决闪烁问题BeginBatchDraw();//计算与赋值int i, j;for (i = 0; i < qheight; i++) {for (j = 0; j < qwidth; j++) {int r, g, b;int ij;//计算ij = i * qwidth + j;r = (int)((GetRValue(N[ij])) * (1 - f) + GetRValue(M[ij]) * f);g = (int)((GetGValue(N[ij])) * (1 - f) + GetGValue(M[ij]) * f);b = (int)((GetBValue(N[ij])) * (1 - f) + GetBValue(M[ij]) * f);R[ij] = RGB(r, g, b);}}//贴出图片并释放内存putimage(x0, y0, &RS);FlushBatchDraw();// 绘制}//检测两个矩形是否相碰撞int testHit(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2){return !(x1 + w1 < x2 ||y1 + h1 < y2 ||x2 + w2 < x1 ||y2 + h2 < y1);}// 主函数,开启游戏int main(){initgraph(screenWidth, screenHeight, EW_DBLCLKS | EW_SHOWCONSOLE);initgame();// 初始化游戏paint();// 刷新显示游戏界面flushmessage();// 清空鼠标缓冲区while (_kbhit()) _getch();// 清空键盘缓冲区run();// 开始游戏closegraph();//关闭图形环return 0;}//--------------优雅的警戒线 以上为雷区 非专业 勿进------------------// //TODO: 2 全局变量声明位置 //TODO: 2 全局变量声明位置 IMAGE imgbg;//背景色IMAGE imgfk[11];//方块图片TCHAR imgPath[100];int luoKuai[20][10] = { 0 };//下落的方块int shiKuai[20][10] = { 0 };//落实不动的方块int color;int score = 0;//得分int level = 1;//TODO: 3 游戏初始化位置void gameInit(){loadimage(&imgbg, L".\\images\\2\\bg-3.png"); //自己的图片路径for (int c = 0; c < 11; c++){_stprintf(imgPath, L".\\images\\2\\%d.png", c);//自己的的图片路径loadimage(&imgfk[c], imgPath);}//color = rand() % 10 + 1;//随机颜色 1~10//luoKuai[0][3] = luoKuai[0][4] = luoKuai[0][5] = color;//luoKuai[1][4] = color;createNewLuoKuai();}//TODO: 4 绘图处理位置void gamePaint(){putimage(0, 0, &imgbg);//---------显示下落方块-------------//int h, l;for (h = 0; h < 20; h++){for (l = 0; l < 10; l++){if (luoKuai[h][l] != 0){drawImage(30 + l * 30, 5 + h * 30, &imgfk[luoKuai[h][l]]);}if (shiKuai[h][l] != 0){drawImage(30 + l * 30, 5 + h * 30, &imgfk[shiKuai[h][l]]);}}}//---------显示得分 等级-------------//settextstyle(18, 0, _T("黑体"));settextcolor(0xffffff);TCHAR str[100];_stprintf(str, L"%d分", score);outtextxy(390, 228, str);_stprintf(str, L"Level %d", level);outtextxy(390, 294, str);}//TODO: 5 定时处理位置void gameInterval(){if (downNotOut()&&downNotStop()){downMove();}else{merge();updateScore(clearLine());if (isOver()){gameover();}else{createNewLuoKuai();}}}//TODO: 6 处理键盘控制位置void gameKeypress(int key){switch (key){case VK_LEFT:if (leftNotOut() && leftNotStop()){leftMove(); }break;case VK_RIGHT:if (rightNotOut() && rightNotStop()){rightMove();}break;case VK_UP: break;case VK_DOWN: break;} }//TODO: 7 处理鼠标控制位置void gameMouseDown(int mouseX, int mouseY){ }void gameMouseUp(int mouseX, int mouseY){}void gameMousemove(int mouseX, int mouseY){}void gameMouseRightDown(int mouseX, int mouseY){}
game_function.cpp
#include "game_function.h"#include /*向左移动*/void leftMove(){for (int k = 1; k < 10; k++){for (int h = 0; h < 20; h++){luoKuai[h][k - 1] = luoKuai[h][k];luoKuai[h][k] = 0;}}}/* 左不出界 */_BOOL_ leftNotOut(){for (int h = 0; h < 20; h++){if (luoKuai[h][0]){return FALSE;}}return TRUE;}/*左不阻挡*/_BOOL_ leftNotStop(){for (int k = 1; k < 10; k++){for (int h = 0; h = 0; k--){for (int h = 0; h < 20; h++){luoKuai[h][k+1] = luoKuai[h][k];luoKuai[h][k] = 0;}}}/* 右不出界 */_BOOL_ rightNotOut(){for (int h = 0; h = 0; k--){for (int h = 0; h = 0; h--){for (int k = 0; k < 10; k++){luoKuai[h + 1][k] = luoKuai[h][k];luoKuai[h][k] = 0;}}}/*下不出界*/_BOOL_ downNotOut(){for (int k = 0; k = 0; h--){for (int k = 0; k < 10; k++){if (luoKuai[h][k] && shiKuai[h+1][k]){return FALSE;}}}return TRUE;}/* 合并 */void merge(){for (int h = 0; h < 20; h++){for (int k = 0; k < 10; k++){if (luoKuai[h][k]){shiKuai[h][k] = luoKuai[h][k];luoKuai[h][k] = 0;}}}}/*消除行*/int clearLine(){int count = 0;//记录消除了多少行for (int xh = 0; xh < 20; xh++){//检验本行是否能消除_BOOL_ can = TRUE;//假设能消除//验证假设for (int i = 0; i = 0; h--){for (int k = 0; k = 6){score +=200;}}_BOOL_ isOver(){for (int k = 0; k < 8; k++){if (shiKuai[0][k] != 0){return TRUE;}}return FALSE;}/* 创建新落块 */void createNewLuoKuai(){//1方块种类随机BLOCK_TYPE bt = (BLOCK_TYPE)(rand() % 7);//2方块颜色随机color = rand() % 10 + 1;switch (bt){case L:luoKuai[0][3] = luoKuai[1][3] = luoKuai[2][3] =luoKuai[2][4]= color;break;case Z:luoKuai[0][3] = luoKuai[0][4] = luoKuai[1][4] = luoKuai[1][5] = color;break;case TIAN:luoKuai[0][3] = luoKuai[0][4] = luoKuai[1][3] = luoKuai[1][4] = color;break;case T:luoKuai[0][3] = luoKuai[0][4] = luoKuai[1][4] = luoKuai[0][5] = color;break;case I:luoKuai[0][3] = luoKuai[1][3] = luoKuai[2][3] = luoKuai[3][3] = color;break;case YI:luoKuai[0][3] = luoKuai[0][4] = luoKuai[0][5] = luoKuai[0][6] = color;break;case J:luoKuai[0][4] = luoKuai[1][4] = luoKuai[2][3] = luoKuai[2][4] = color;break;}}void gameover(){stop = TRUE;}
date_type.h
#pragma once//创建逻辑布尔类型#define TRUE 1#define FALSE 0typedef int _BOOL_;//枚举类型:方块样式typedef enum block_type { L,Z,TIAN,T,I,YI,J } BLOCK_TYPE;
game_function.h
#pragma once#include "date_type.h"#include "global_var.h"//功能模块/*左移动*/void leftMove();/**/_BOOL_ leftNotOut();/*左不阻挡*/_BOOL_ leftNotStop();/*右移动*/void rightMove();/*右*/_BOOL_ rightNotOut();/*右不阻挡*/_BOOL_ rightNotStop();/*下移动*/void downMove();/*下*/_BOOL_ downNotOut();/*下不阻挡*/_BOOL_ downNotStop();/*合并*/void merge();/*消除行 返回消除的行数*/int clearLine();/*更新得分lines:消除的行数*/void updateScore(int lines);_BOOL_ isOver();/*创建新方块*/void createNewLuoKuai();void gameover();
global_var.h
#pragma once#include "game_function.h"#include"date_type.h"//集中管理全局变量声明 共享使用extern int luoKuai[20][10];//下落的方块extern int shiKuai[20][10];//落实不动的方块extern int color;extern int stop;//是否停止游戏extern int score;extern int level;
图片文件:
EasyX游戏框架:
#define _CRT_SECURE_NO_WARNINGS 1#include #include #include #include#include#include#include#include /*游戏界面绘制*/void gamePaint();/*游戏初始化绘制*/void gameInit();/*游戏定时处理*/void gameInterval();/*游戏键盘按下*/void gameKeypress(int key);/*游戏鼠标按下*/void gameMouseDown(int mouseX,int mouseY);/*游戏鼠标右键按下*/void gameMouseRightDown(int mouseX,int mouseY);/*游戏鼠标抬起*/void gameMouseUp(int mouseX,int mouseY);/*游戏鼠标移动*/void gameMousemove(int mouseX,int mouseY); /*含透明的图的绘制x为要载入图片的X坐标,y为Y坐标*/void drawImage(intpicture_x, int picture_y,IMAGE* picture);/*调整图片透明度角度转弧度:PI/180*角度弧度转角度:180/PI*弧度*/void drawImageAlpha(int x0, int y0, IMAGE* img, double f);/*两个矩形碰撞检测即两个矩形是否相交。 x1, y1, w1, h1是第一个矩形的xy宽高的四个参数 x2, y2, w2, h2是第二个矩形的xy宽高的四个参数 返回0代表不相交 返回1代表相交*/int testHit(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2 ); /*设置100即每隔100毫秒刷新以下界面绘图。*/int interval = 100;//TODO: 1 设置定时器时间间隔(单位毫秒)// TODO: 1 设置窗口: 宽度 高度int screenWidth = 800;int screenHeight=600;int stop = 0;//是否停止游戏//-----------------------------------//int times = 0; /*初始化游戏 */void initgame(){srand((unsigned)time(NULL));//随机数初始化setbkcolor(NULL);//背景色setbkmode(TRANSPARENT);// 设置背景混合模式: TRANSPARENT为透明gameInit();}/*界面绘图演示案例*//*绘制显示游戏界面*/void paint(){BeginBatchDraw();//打开双缓冲cleardevice();// 清屏 gamePaint();//-----------------------------//EndBatchDraw();//关闭双缓冲} /*游戏运行*/void run(){ExMessage msg ;//ExMessage key;while (1)// 游戏主循环可借助break 结束循环{if (peekmessage(&msg,-1,true)){switch (msg.message){case WM_MOUSEMOVE://鼠标移动gameMousemove(msg.x, msg.y);break;case WM_LBUTTONDOWN://左键按下gameMouseDown(msg.x, msg.y);break;case WM_LBUTTONUP://左键抬起gameMouseUp(msg.x, msg.y);break;case WM_LBUTTONDBLCLK://左键双击 break;case WM_RBUTTONDOWN://右键按下 break;case WM_RBUTTONUP://右键抬起gameMouseRightDown(msg.x, msg.y);break;case WM_RBUTTONDBLCLK://右键双击 break;case WM_KEYDOWN:gameKeypress(msg.vkcode);break;}paint();continue;} //------时间处理 勿动-----------//Sleep(1);times++;if(times%(interval/10)!=0){continue;}times=0;if(stop){break;}gameInterval(); //-------------------------------//paint();// 刷新显示游戏界面}} /*绘制透明背景图*/ void drawImage(intpicture_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 > 24); //0xAArrggbb;AA是透明度int sr = ((src[srcX] & 0xff0000) >> 16); //获取RGB里的Rint sg = ((src[srcX] & 0xff00) >> 8); //Gint sb = src[srcX] & 0xff;//Bif (ix >= 0 && ix = 0 && iy <= graphHeight && dstX <= graphWidth * graphHeight){dstX = (ix + picture_x )+ (iy + picture_y ) * graphWidth; //在显存里像素的角标if (dstX> 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) <getwidth();qheight = img->getheight();//P图为背景图,RS为目标图片static IMAGE RS(qwidth, qheight);static IMAGE P(qwidth, qheight);//背景图的绘制getimage(&P, x0, y0, qwidth, qheight);//获取指针,作为透明度计算DWORD* M = GetImageBuffer(&P);DWORD* N = GetImageBuffer(img);DWORD* R = GetImageBuffer(&RS);// 开启批量绘图模式,解决闪烁问题BeginBatchDraw();//计算与赋值int i, j;for (i = 0; i < qheight; i++) {for (j = 0; j < qwidth; j++) {int r, g, b;int ij;//计算ij = i * qwidth + j;r = (int)((GetRValue(N[ij])) * (1 - f) + GetRValue(M[ij]) * f);g = (int)((GetGValue(N[ij])) * (1 - f) + GetGValue(M[ij]) * f);b = (int)((GetBValue(N[ij])) * (1 - f) + GetBValue(M[ij]) * f);R[ij] = RGB(r, g, b);}}//贴出图片并释放内存putimage(x0, y0, &RS);FlushBatchDraw();// 绘制}//检测两个矩形是否相碰撞int testHit(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2 ){ return !(x1 + w1 < x2|| y1 + h1 < y2 || x2 + w2 <x1 || y2 + h2<y1 );}// 主函数,开启游戏int main(){initgraph(screenWidth, screenHeight,SHOWCONSOLE);initgame();// 初始化游戏paint();// 刷新显示游戏界面 flushmessage();// 清空鼠标缓冲区while (_kbhit()) _getch();// 清空键盘缓冲区run();// 开始游戏closegraph();//关闭图形环return 0;}//--------------------------------// //TODO: 2 全局变量声明位置 //TODO: 3 游戏初始化位置 void gameInit(){ } //TODO: 4 绘图处理位置void gamePaint(){} //TODO: 5 定时处理位置void gameInterval(){ }//TODO: 6 处理键盘控制位置void gameKeypress(int key){switch (key ){case VK_LEFT:printf("按 左\n");break;case VK_RIGHT:printf("按 右\n");break;case VK_UP:printf("按 上\n");break;case VK_DOWN:printf("按 下\n");break;} switch (key ){case 'A':case 'a':printf("按 A\n");break;case 'B':case 'b':printf("按 B\n");break;case 'c':case 'C':printf("按 C\n");break;case 'D':case 'd':printf("按 d\n");break;}} //TODO: 7 处理鼠标控制位置void gameMouseDown(int mouseX,int mouseY){printf("按下鼠标左键\n"); }void gameMouseUp(int mouseX,int mouseY){ }void gameMousemove (int mouseX,int mouseY){ } void gameMouseRightDown(int mouseX,int mouseY){ }