项目准备
任意版本的VS 或者 VC++
安装easyx图形库
项目演示
项目目标
使用C语言开发自定义“控件”
游戏引擎的开发和设计
算法在游戏开发中的设计
项目实现
- 创建项目
创建空项目
- 项目框架
#include <stdio.h>
#include <Windows.h>
#include <graphics.h>
#include <time.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
struct Button {
};
void moveButton(Button* btn) {
}
void drawButton(Button* btn) {
}
Button* checkButtonClick(MOUSEMSG* msg) {
return NULL;
}
void update() {
}
void checkSuccess() {
}
void init() {
}
int main(void) {
init();
update(); //重绘所有按钮
Button* btn = NULL;
while (1) {
MOUSEMSG m = GetMouseMsg();
switch (m.uMsg) {
case WM_LBUTTONDOWN:
btn = checkButtonClick(&m); // 计算选择了哪个按钮
break;
case WM_LBUTTONUP:
if (btn) {
/*btn->pressed = false;*/
moveButton(btn);
}
}
drawButton(btn);
checkSuccess();
}
system("pause");
closegraph();
return 0;
}
- 定义按钮的数据类型
struct Button {
IMAGE imgNormal;
IMAGE imgPress;
int width, highth;
int x, y;
int flag; // 按钮的int类型标记
bool pressed;
};
- 初始化游戏界面
准备项目的素材。
初始化游戏界面
IMAGE imgBg;
void init() {
initgraph(1080 * 0.4, 2400 * 0.4); //1080,2400
loadimage(&imgBg, "res/bg1.jpg", 1080 * 0.4, 2400 * 0.4, true);
}
更新游戏画面
- 初始化游戏数据
int data[3][3];
void initData() {
srand(time(NULL));
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
data[i][j] = i * 3 + j + 1;
}
}
data[2][2] = 0;
}
void init() {
initData();
initgraph(1080 * 0.4, 2400 * 0.4); //1080,2400
loadimage(&imgBg, "res/bg1.jpg", 1080 * 0.4, 2400 * 0.4, true);
}
打乱数据:
// 判断数字sz,能不能移动,如果不能返回false
// 如果能够移动,就返回true, 并让参数2和参数3返回具体移动的方向
// 参数x为0,表示水平方向不能移动,为1(-1),表示可以向右(向左)移动
// 参数y为0,表示垂直方向不能移动,为1(-1),表示可以向下(向上)移动
// 如果可以移动,就直接在data数组中,修改成移动后的数据情况
bool canMove(int sz, int *x, int *y) {
int flag = 0, i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
if (data[i][j] == sz) {
flag = 1;
break;
}
}
if (flag) break;
}
if (i > 0 && data[i - 1][j] == 0) {
*x = 0;
*y = -1;
data[i - 1][j] = sz;
data[i][j] = 0;
return true;
}
else if (i < 2 && data[i + 1][j] == 0) {
*x = 0;
*y = 1;
data[i + 1][j] = sz;
data[i][j] = 0;
return true;
}
else if (j > 0 && data[i][j - 1] == 0) {
*x = -1;
*y = 0;
data[i][j - 1] = sz;
data[i][j] = 0;
return true;
}
else if (j < 2 && data[i][j + 1] == 0) {
*x = 1;
*y = 0;
data[i][j + 1] = sz;
data[i][j] = 0;
return true;
}
return false;
}
void initData() {
srand(time(NULL));
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
data[i][j] = i * 3 + j + 1;
}
}
data[2][2] = 0;
int moveCount = 0;
while (moveCount < 100) {
int val = rand() % 9 + 1;
int x, y;
if (canMove(val, &x, &y)) moveCount++;
}
}
- 按钮初始化
创建一个接口,初始化一个按钮
void initButton(Button* btn, const char* normalFile, const char* pressFile,
int width, int highth, int flag) {
if (!btn) return;
loadimage(&btn->imgNormal, normalFile, width, highth, true);
loadimage(&btn->imgPress, pressFile, width, highth, true);
btn->width = width;
btn->highth = highth;
btn->pressed = false;
btn->flag = flag;
}
初始化所有按钮
Button btns[8];
int offX = 55;
int offY = 321;
void buttonsInit() {
int k = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (data[i][j] == 0) continue;
char name1[64];
char name2[64];
sprintf(name1, "res/sz%d.png", data[i][j]);
sprintf(name2, "res/sz%dp.png", data[i][j]);
initButton(&btns[k], name1, name2, 106, 106, data[i][j]);
btns[k].x = offX + j * (106 + 1);
btns[k].y = offY + i * (106 + 1);
k++;
}
}
}
void init() {
initgraph(1080 * 0.4, 2400 * 0.4); //1080,2400
loadimage(&imgBg, "res/bg1.jpg", 1080 * 0.4, 2400 * 0.4, true);
initData();
buttonsInit();
}
- 重绘所有按钮
绘制单个按钮
导入工具tools.h/tools.cpp, 绘制背景透明的PNG图片
#include "tools.h"
void drawButton(Button* btn) {
if (!btn) return;
if (btn->pressed) {
drawPNG(btn->x, btn->y, &btn->imgPress);
}
else {
drawPNG(btn->x, btn->y, &btn->imgNormal);
}
}
void update() {
//这个函数用于开始批量绘图
//执行后,任何绘图操作都将暂时不输出到屏幕上,
//直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。
BeginBatchDraw();
putimage(0, 0, &imgBg);
for (int i = 0; i < 8; i++) {
drawButton(&btns[i]);
}
EndBatchDraw();
}
- 检查单击了哪个按钮
bool checkButtonSelect(Button* btn, MOUSEMSG *msg) {
float margin = 0.1;
if (msg->x >= btn->x + btn->width * margin &&
msg->x <= btn->x + btn->width * (1 - margin) &&
msg->y >= btn->y + btn->highth * margin &&
msg->y <= btn->y + btn->highth * (1 - margin)) {
return true;
}
else {
return false;
}
}
Button* checkButtonClick(MOUSEMSG* msg) {
int count = sizeof(btns) / sizeof(btns[0]);
for (int i = 0; i < 8; i++) {
if (checkButtonSelect(&btns[i], msg)) {
btns[i].pressed = true;
return &btns[i];
}
}
return NULL;
}
- 按键抬起后,移动按钮
int main(void) {
......
while (1) {
......
case WM_LBUTTONDOWN:
......
case WM_LBUTTONUP:
if (btn) {
btn->pressed = false;
moveButton(btn);
}
}
......
}
......
return 0;
}
实现moveButton函数
void moveButton(Button *btn) {
int x, y;
if (canMove(btn->flag, &x, &y)) {
btn->x += x * (106 + 1);
btn->y += y * (106 + 1);
mciSendString("play res/move.mp3", 0, 0, 0);
update();
}
}
- 判断是否成功
void checkSuccess() {
int* p = &data[0][0];
for (int i = 1; i <= 8; i++, p++) {
if (*p != i) return;
}
loadimage(0, "res/suc.jpg");
mciSendString("play res/next.mp3", 0, 0, 0);
}
项目完善
- 渲染队列的设计
- 消息队列的设计
- 游戏主体循环的设计
- 联网功能
- 分享功能
- 多关卡功能
今天的分享就到这里了,大家要好好学C语言/C++哟~
欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!
对于准备学习C/C++编程的小伙伴,如果你想更好的提升你的编程核心能力(内功)不妨从现在开始!
C语言从入门到精通(C语言入门C语言教程C语言零基础C语言基础C语言学习C
整理分享(多年学习的源码、项目实战视频、项目笔记,基础入门教程)加君羊获取哦~
C语言C++编程学习交流圈子,企鹅君羊:763855696【点击进入】