示例二 2048.zip
立即下载
资源介绍:
EGE专栏中的示例程序二 2048游戏, 包含所用素材,源代码和EXE文件,下载解压后,双击EXE文件即可直接运行。压缩包中有三个版本,分别是基础功能实现版,完整版和无音乐流畅完整版。 使用EGE图形库制作
//#define SHOW_CONSOLE
#include
#include
#include
#include
void load(); //加载资源
void loadImage(); //加载图片
void loadRecord(); //读取游戏记录
void loadMusic(); //加载音乐
void gameSave(); //游戏保存
void releaseImage(); //释放图片资源
void releaseMusic(); //关闭音乐文件,释放资源
void draw(); //绘制画面
void drawGameInfo(); //绘制游戏信息
void addRandomNum(int n); //增加随机数字
bool move(int direct); //按方向移动格子
void drawBlocks(); //绘制格子
void restart(); //重新游戏
void gameOverCheck(); //游戏结束检测
//界面布局参数
const int AREA_LEFT = 20, AREA_TOP = 178, AREA_WIDTH = 500, AREA_HEIGHT = 500;
const int GRID_WIDTH = 106, DEVIDE = 15;
const int SCR_WIDTH = AREA_WIDTH + AREA_LEFT * 2, SCR_HEIGHT = AREA_HEIGHT + AREA_TOP + AREA_LEFT;
//颜色参数
#define COLOR_TEXT_SCORE EGERGB(241, 231, 214)
#define COLOR_BACKGROUD EGERGB(250,248, 239)
//动画参数
#define SPEED 25
#define FPS 60
//按钮点击判断
inline bool clickBtnRestart(int x, int y) {
return (20 < x && x < 20 + 222) && (110 < y && y < 110 + 50);
}
//图片
#define NUM_BLOCK 18
PIMAGE blockImgs[NUM_BLOCK];
#define NUM_IMG 5
PIMAGE pimgs[NUM_IMG];
const int ID_IMG_BACKGROUND = 0, ID_IMG_LOGO = 1, ID_IMG_SCORE_BG = 2, ID_IMG_RESTART = 3;
const int ID_IMG_GAMEOVER = 4;
//图片文件位置
const char* imgFiles[NUM_IMG] = {
"resource\\image\\background.png",
"resource\\image\\gamelogo.png",
"resource\\image\\scorebg.png",
"resource\\image\\restart.png",
"resource\\image\\gameOver.png",
};
//数据文件
const char* recordFile = "game2048Record.txt";
//音乐
MUSIC mergeMusic;
MUSIC startMusic;
const char* mergeMusicFile = "resource\\music\\merge.mp3";
const char* startMusicFile = "resource\\music\\start.mp3";
//方向偏移
const int LEFT = 0, UP = 1, RIGHT = 2, DOWN = 3;
const int dx[4] = { -1, 0, 1, 0 };
const int dy[4] = { 0, -1, 0, 1 };
struct GameInfo
{
int score;
int topScore;
int maxNum;
};
GameInfo gameInfo;
int grid[4][4]; //格子
int emptyBlock = 16; //空格子数
bool gameOver = false;
int main()
{
//注意要INIT_NOFORCEEXIT, 即关闭窗口不强制退出程序,以便进行游戏保存工作
setinitmode(INIT_RENDERMANUAL | INIT_NOFORCEEXIT, 100, 50);
initgraph(SCR_WIDTH, SCR_HEIGHT);
setcaption("2048");
setbkcolor(COLOR_BACKGROUD);
setbkmode(TRANSPARENT);
delay_ms(0); //刷新窗口
srand((unsigned int)time(0));
load();
startMusic.Play(0);
draw();
gameOverCheck();
int xClick, yClick;
for (; is_run(); delay_fps(FPS)) {
//按键检测
int direction = -1;
while (kbmsg()) {
key_msg keyMsg = getkey();
if (keyMsg.msg == key_msg_down) {
switch (keyMsg.key) {
case 'A': case key_left: direction = 0; break;
case 'W': case key_up: direction = 1; break;
case 'D': case key_right: direction = 2; break;
case 'S': case key_down: direction = 3; break;
}
}
}
//鼠标点击检测
bool leftClick = false;
while (mousemsg()) {
mouse_msg mouseMsg = getmouse();
if (mouseMsg.is_left() && mouseMsg.is_down()) { //左键按下
leftClick = true;
xClick = mouseMsg.x;
yClick = mouseMsg.y;
}
}
//移动
if (!gameOver && direction != -1 && move(direction)) {
addRandomNum(1);
cleardevice();
draw();
gameOverCheck();
}
//鼠标点击判断
if (leftClick && clickBtnRestart(xClick, yClick)) {
restart();
startMusic.Play(0);
cleardevice();
draw();
}
}
gameSave();
releaseImage();
releaseMusic();
closegraph();
return 0;
}
void drawGameInfo()
{
putimage_withalpha(NULL, pimgs[ID_IMG_LOGO], AREA_LEFT + 14, 30); //图标
putimage_withalpha(NULL, pimgs[ID_IMG_SCORE_BG], 260, 10); //游戏分数背景
putimage_withalpha(NULL, pimgs[ID_IMG_RESTART], 20, 110); //重新开始安妮
//游戏分数
setcolor(COLOR_TEXT_SCORE);
setfont(30, 0, "黑体");
xyprintf(370, 24, "%8d", gameInfo.topScore);
xyprintf(370, 72, "%8d", gameInfo.score);
xyprintf(370, 120, "%8d", gameInfo.maxNum);
}
void draw()
{
drawGameInfo();
drawBlocks();
}
void restart()
{
gameInfo.score = 0;
gameOver = false;
memset(grid, 0, sizeof(int) * 16);
emptyBlock = 16;
addRandomNum(2);
}
void drawBlocks()
{
putimage_withalpha(NULL, pimgs[ID_IMG_BACKGROUND], AREA_LEFT, AREA_TOP);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
int x = AREA_LEFT + (j + 1) * DEVIDE + j * GRID_WIDTH;
int y = AREA_TOP + (i + 1) * DEVIDE + i * GRID_WIDTH;
if (grid[i][j] != 0)
putimage_withalpha(NULL, blockImgs[grid[i][j]], x, y);
}
}
}
void gameOverCheck()
{
if (emptyBlock != 0)
return;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if ((j + 1 < 4 && grid[i][j] == grid[i][j + 1])
|| (i + 1 < 4 && grid[i][j] == grid[i + 1][j]))
return;
}
}
gameOver = true;
setfillcolor(EGEACOLOR(0x60, WHITE));
ege_fillrect(AREA_LEFT, AREA_TOP, AREA_WIDTH, AREA_HEIGHT);
putimage_withalpha(NULL, pimgs[ID_IMG_GAMEOVER], 120, 400);
}
void addRandomNum(int n)
{
while (n-- > 0) {
if (emptyBlock == 0)
break;
int r = rand() % emptyBlock--; //随机选取一个空位
int* p = &grid[0][0] - 1, i = 0;
do { //找到目标空位
while (*++p);
} while (i++ < r);
*p = (rand() % 10 == 0) + 1; //随机数字,0.9概率是1,0.1概率是2
}
}
bool move(int direction)
{
//0~3对应移动方向左上右下
//初始检测位置及检测偏移
static int x0[4] = {0, 0, 3, 0}, y0[4] = {0, 0, 0, 3};
static int firstOffset[4][2] = { {1, 0},{0, 1},{-1, 0}, {0, -1} };
static int secondOffset[4][2] = { {0, 1}, {1, 0}, {0, 1}, {1, 0} };
bool changed = false;
bool hasMoved[4] = { true, true, true, true };
bool merged[4][4] = { false }/*合并标记*/, mergeMusic_flag = false, move_flag;
for (int check = 3; check > 0; --check) {
int lastGrid[4][4]; //上次格子存储
bool moving[4][4] = { false }; //移动标记
memcpy(lastGrid, grid, sizeof(int) * 4 * 4);
int xLast = x0[direction], yLast = y0[direction];
move_flag = false;
//整体单格移动
for (int i = 0; i < 4; i++) {
if (!hasMoved[i])
continue;
hasMoved[i] = false;
int xCur = x0[direction] + i * secondOffset[direction][0];
int yCur = y0[direction] + i * secondOffset[direction][1];
for (int j = 1; j < 4; j++) {
xLast = xCur;
yLast = yCur;
xCur += firstOffset[direction][0];
yCur += firstOffset[direction][1];
if (grid[yCur][xCur] != 0) {
if (grid[yLast][xLast] == 0) {
grid[yLast][xLast] = grid[yCur][xCur];
grid[yCur][xCur] = 0;
moving[yCur][xCur] = hasMoved[i] = move_flag = true;
changed = true;
}
//合并
else if (grid[yCur][xCur] == grid[yLast][xLast]
&& (!merged[yLast][xLast] && !merged[yCur][xCur])) {
++grid[yLast][xLast];
grid[yCur][xCur] = 0;
moving[yCur][xCur] = merged[yLast][xLast] = hasMoved[i] = true;
changed = mergeMusic_flag = move_flag = true;
emptyBlock++;
int score = 1 << grid[yLast][xLast];
if (score > gameInfo.maxNum)
gameInfo.maxNum = score;
if ((gameInfo.score += score) > gameInfo.topScore)
gameInfo.topScore = gameInfo.score;
}
}
}
}
if (!move_flag)
break;
//移动动画
cleardevice();
drawGameInfo();
setfillcolor(getbkcolor());
for (int dist = SPEED; dist < GRID_WIDTH + DEVIDE ; delay_fps(FPS), dist += SPEED) {
bar(AREA_LEFT, AREA_TOP, AREA_LEFT + AREA_WIDTH, AREA_TOP + AREA_HEIGHT); //清除区域
putimage_withalpha(NULL, pimgs[ID_IMG_BACKGROUND], AREA_LEFT, AREA_TOP); //绘制背景
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (lastGrid[i][j] != 0){
int x = AREA_LEFT + (j + 1) * DEVIDE + j * GRID_WIDTH;
int y = AREA_TOP + (i + 1) * DEVIDE + i * GRID_WIDTH;
if (moving[i][j]) {
x
资源文件列表:
示例二 2048.zip 大约有396个文件