目录
前言:
花两天边看easyx文档边学边写的期末小作业。
学校挂c++的课教c语言入门:)
时间仓促没优化啥,摆了不找了。欢迎大佬帮忙指出不足。
欢迎c+v应付作业
有小小的bug,开局时切换为英文输入法,开局时切换为英文输入法,开局时切换为英文输入法
需要配合地图素材 素材和exe文件的打包下载在结尾。
一、游戏玩法
该游戏将操作主角完成一些小小的任务以脱离密闭的房间。
W A S D移动开局时切换为英文输入法
玩家将借助游戏中的门进出不同的房间
完成推箱子小游戏关后,玩家可从出口处出门完成游戏全部流程。
卧室

客厅

小游戏关

出口

二、完整代码
#include <easyx.h>
#include <conio.h>
#include<Windows.h>
#include<iostream>
using namespace std;
//设置房间链表的节点
typedef struct map {
int number;
struct map* up;
struct map* down;
struct map* left;
struct map* right;
struct map* next;
char* src;
}mapnode;
void rungame();
mapnode* createmaplist();//创建地图函数
void showmainmenu();//展示主菜单函数
int peng(int x, int y, mapnode* nowroom, int xpx[], int xpy[]);//碰撞检测函数
int ifwin( int* xpx,int* xpy);//游戏胜负条件检测函数
int main()
{
showmainmenu();
_getch();
closegraph();
return 0;
}
//创建地图函数
mapnode* createmaplist() {
mapnode* head = (mapnode*)malloc(sizeof(mapnode));
mapnode* p, * tail = head;
p = (mapnode*)malloc(sizeof(mapnode));
p->number = 1;
p->down = NULL;
p->up = NULL;
p->right = NULL;
p->left = NULL;
p->src = (char*)"./MAP001.jpg";
tail->next = p;
tail = tail->next;
p = (mapnode*)malloc(sizeof(mapnode));
p->number = 2;
p->down = NULL;
p->up = tail;
p->right = NULL;
p->left = NULL;
p->src = (char*)"./MAP002.jpg";
tail->down = p;
tail = tail->down;
p = (mapnode*)malloc(sizeof(mapnode));
p->number = 3;
p->down = NULL;
p->up = NULL;
p->right = tail;
p->left = NULL;
p->src = (char*)"./MAP003.jpg";
tail->left = p;
p = (mapnode*)malloc(sizeof(mapnode));
p->number = 4;
p->down = NULL;
p->up = NULL;
p->right = NULL;
p->left = tail;
p->src = (char*)"./MAP004.jpg";
tail->right = p;
return head;
}
//展示主菜单函数
void showmainmenu() {
//初始化窗口
initgraph(528, 528);
setbkcolor(WHITE);
cleardevice();
//初始化标题字体
settextcolor(BLACK);
settextstyle(80, 0, "楷体");
setbkmode(TRANSPARENT);
char* arr = (char*)"李华传";
int x, y;
x=264-textwidth(arr)/2;
y=100-textheight(arr)/2;
outtextxy(x,y,arr);
//加了层阴影
settextcolor(RGB(154, 167, 177));
outtextxy(x+5, y+5, arr);
settextcolor(BLACK);
//开始游戏按钮和字体初始化
setfillcolor(WHITE);
setlinecolor(BLACK);
setlinestyle(PS_SOLID);
arr= (char*)"开始游戏";
settextstyle(40, 0, "微软雅黑");
x = 264 - textwidth(arr) / 2;
y = 250 - textheight(arr) / 2;
fillroundrect(x - 20, y - 20, x + textwidth(arr)+20, y + textheight(arr)+20, 20, 20);
outtextxy(x,y,arr);
arr = (char*)"version 0.1";
settextstyle(20, 0, "微软雅黑");
outtextxy(450, 500,arr);
settextstyle(40, 0, "微软雅黑");
arr = (char*)"开始游戏";
//接收鼠标信息
ExMessage msg;
int flag = 0;
while (1) {
if (peekmessage(&msg, EM_MOUSE)) {
switch (msg.message) {
case WM_LBUTTONUP:
if (msg.x >= x - 20 && msg.x <= x + textwidth(arr) + 20 && msg.y >= y - 20 && msg.y <= y + textheight(arr) + 20) {
flag = 1;
rungame();
break;
}
case WM_MOUSEMOVE:
if (msg.x >= x - 20 && msg.x <= x + textwidth(arr) + 20 && msg.y >= y - 20 && msg.y <= y + textheight(arr) + 20) {
setfillcolor(RGB(154, 167, 177));
fillroundrect(x - 20+1, y - 20+1, x + textwidth(arr) + 21, y + textheight(arr) + 21, 20, 20);
outtextxy(x, y, arr);
}
else {
setfillcolor(WHITE);
fillroundrect(x - 20, y - 20, x + textwidth(arr) + 20, y + textheight(arr) + 20, 20, 20);
outtextxy(x, y, arr);
}
break;
}
}
if (flag == 0) {
}
else {
break;
}
}
}
void rungame() {
//初始化窗口
clearrectangle(0, 0, 600, 600);
setbkcolor(YELLOW);
cleardevice();
//初始化地图链表
mapnode* head = createmaplist();
mapnode* now = head->next;
//初始化人物及背景对象
IMAGE nowroombk;
IMAGE xiang;
loadimage(&nowroombk, now->src, 0, 0);
IMAGE character1, character2, character3;
loadimage(&character1, "./原.jpg", 48, 48);
loadimage(&character2, "a.png", 48, 48);
loadimage(&character3, "b.png", 48, 48);
loadimage(&xiang, "xian.png", 48, 48);
int x = 240, y = 240;
ExMessage msg;
int a;
int xpx[3] = { 6 * 48 ,8 * 48, 6 * 48 };
int xpy[3] = { 4 * 48 ,5 * 48 ,6 * 48 };
//开始主循环
while (1) {
putimage(0, 0, &nowroombk);
putimage(x, y, &character3, SRCAND);
putimage(x, y, &character2, SRCPAINT);
if (now->number == 3) {
putimage(xpx[0], xpy[0], &xiang);
putimage(xpx[1], xpy[1], &xiang);
putimage(xpx[2], xpy[2], &xiang);
}
int i,win=0;
//检测是否碰撞
//这里会不好看 看我文章
if (peekmessage(&msg, EM_KEY)) {
switch (msg.message) {
case WM_KEYDOWN:
a = _getch();
if (a == 'w' || a == 'W') {
//SetWorkingImage(&character);
i = peng(x, y - 48, now, xpx, xpy);
if (i) {
if (i > 5) {
i = i - 10;
if (peng(xpx[i], xpy[i] - 48, now, xpx, xpy)) {
}
else {
switch (i) {
case 0:xpy[0] -= 48;break;
case 1:xpy[1] -= 48;break;
case 2:xpy[2] -= 48;break;
}
}
}
}
else {
y -= 48;
}
}
else if (a == 'a' || a == 'A') {
i = peng(x - 48, y, now, xpx, xpy);
if(i){
if (i > 5) {
i = i - 10;
if (peng(xpx[i] - 48, xpy[i], now, xpx, xpy)) {
}
else {
switch (i) {
case 0:xpx[0] -= 48;break;
case 1:xpx[1] -= 48;break;
case 2:xpx[2] -= 48;break;
}
}
}
}
else {
x -= 48;
}
}
else if (a == 's' || a == 'S') {
i = peng(x, y + 48, now, xpx, xpy);
if (i) {
if (i > 5) {
i = i - 10;
if (peng(xpx[i], xpy[i] + 48, now, xpx, xpy)) {
}
else {
switch (i) {
case 0:xpy[0] += 48;break;
case 1:xpy[1] += 48;break;
case 2:xpy[2] += 48;break;
}
}
}
}
else {
y += 48;
}
}
else if (a == 'd' || a == 'D') {
i = peng(x + 48, y, now, xpx, xpy);
if (i) {
if (i > 5) {
i = i - 10;
if (peng(xpx[i] + 48, xpy[i], now, xpx, xpy)) {
}
else {
switch (i) {
case 0:xpx[0] += 48;break;
case 1:xpx[1] += 48;break;
case 2:xpx[2] += 48;break;
}
}
}
}
else {
x += 48;
}
}
else if (a == 32) {
//cleardevice();
}
cleardevice();
break;
}
}
//房间移动
if (x >= 5 * 48 && x <= 6 * 48 && y >= 10 * 48 && y <= 11 * 48) {
if (now->down) {
now = now->down;
x = 5 * 48;
y = 2 * 48;
loadimage(&nowroombk, now->src, 0, 0);
}
}
if (x >= 5 * 48 && x <= 6 * 48 && y >= 0 * 48 && y < 1 * 48) {
if (now->up) {
now = now->up;
x = 5 * 48;
y = 9 * 48;
loadimage(&nowroombk, now->src, 0, 0);
}
}
if (x >= 0 * 48 && x <= 1 * 48 && y >= 5 * 48 && y <= 6 * 48) {
if (now->left) {
now = now->left;
x = 9 * 48;
y = 5 * 48;
loadimage(&nowroombk, now->src, 0, 0);
}
}
if (x >= 10 * 48 && x <= 11 * 48 && y >= 5 * 48 && y <= 6 * 48) {
if (now->right) {
now = now->right;
x = 2 * 48;
y = 5 * 48;
loadimage(&nowroombk, now->src, 0, 0);
}
}
if (ifwin(xpx, xpy)) {
if (now->number == 4, x == 5 * 48, y == 1 * 48) {
break;
}
}
}
}
//碰撞检测函数
int peng(int x,int y,mapnode* nowroom,int xpx[],int xpy[]){
int flag=0;
int i = 0;
if (x<0||y<0||x>10*48||y>10*48) {
flag = 1;
}
if (nowroom->number == 1) {
if (y <= 3 * 48 && x <= 10 * 48 || y == 6 * 48 && x == 2 * 48 || y == 4 * 48 && x == 9 * 48) {
flag = 1;
}
}
if (nowroom->number == 2) {
if (y <= 1 * 48 && x <= 4 * 48|| y <= 1 * 48 && x >= 6 * 48&& x <= 10 * 48){
flag = 1;
}
}
if (nowroom->number == 3) {
if (y==0||y==10 * 48 ||x==0||x<=3 * 48 &&y<=3 * 48 ||x<=3 * 48 &&y>=7 * 48 ||x>=7 * 48 &&y<=4 * 48 ||x>=7 * 48 &&y>=6 * 48) {
flag = 1;
}
for (i=0;i < 3;i++) {
if (x == xpx[i] && y == xpy[i]) {
flag = i+10;
}
}
}
if (nowroom->number == 4) {
if (y <= 1 * 48 && x <= 4 * 48 || y <= 1 * 48 && x >= 6 * 48 && x <= 10 * 48) {
flag = 1;
}
}
return flag;
}
//游戏胜负条件检测函数
int ifwin( int* xpx, int* xpy) {
int i = 0;
if (6*48 == xpx[0] && 1 * 48 == xpy[0]&& 1 * 48 == xpx[1] && 5 * 48 == xpy[1] && 6 * 48 == xpx[2] && 9 * 48 == xpy[2]) {
return 1;
}
return 0;
}
三、部分细节
透明化人物背景
IMAGE character1, character2, character3;
loadimage(&character1, "./原.jpg", 48, 48);
loadimage(&character2, "a.png", 48, 48);
loadimage(&character3, "b.png", 48, 48);
loadimage(&xiang, "xian.png", 48, 48);
关于easyx库中怎样贴出透明图片
原文链接:https://blog.youkuaiyun.com/weixin_45848751/article/details/106983700
地图的链表实现
mapnode* createmaplist() {
mapnode* head = (mapnode*)malloc(sizeof(mapnode));
mapnode* p, * tail = head;
p = (mapnode*)malloc(sizeof(mapnode));
p->number = 1;
p->down = NULL;
p->up = NULL;
p->right = NULL;
p->left = NULL;
p->src = (char*)"./MAP001.jpg";
tail->next = p;
tail = tail->next;
p = (mapnode*)malloc(sizeof(mapnode));
p->number = 2;
p->down = NULL;
p->up = tail;
p->right = NULL;
p->left = NULL;
p->src = (char*)"./MAP002.jpg";
tail->down = p;
tail = tail->down;
p = (mapnode*)malloc(sizeof(mapnode));
p->number = 3;
p->down = NULL;
p->up = NULL;
p->right = tail;
p->left = NULL;
p->src = (char*)"./MAP003.jpg";
tail->left = p;
p = (mapnode*)malloc(sizeof(mapnode));
p->number = 4;
p->down = NULL;
p->up = NULL;
p->right = NULL;
p->left = tail;
p->src = (char*)"./MAP004.jpg";
tail->right = p;
return head;
}
没啥好说的src存放地图位置
移动检测
利用了easyx中的ExMessage对象
由于每次循环初都会重新绘制画面上所有东西,所以在循环尾只需要对坐标做处理就会改变下次图形的位置。
if (peekmessage(&msg, EM_KEY)) {
switch (msg.message) {
case WM_KEYDOWN:
a = _getch();
if (a == 'w' || a == 'W') {
//SetWorkingImage(&character);
i = peng(x, y - 48, now, xpx, xpy);
if (i) {
if (i > 5) {
i = i - 10;
if (peng(xpx[i], xpy[i] - 48, now, xpx, xpy)) {
}
else {
switch (i) {
case 0:xpy[0] -= 48;break;
case 1:xpy[1] -= 48;break;
case 2:xpy[2] -= 48;break;
}
}
}
}
else {
y -= 48;
}
}
else if (a == 'a' || a == 'A') {
i = peng(x - 48, y, now, xpx, xpy);
if(i){
if (i > 5) {
i = i - 10;
if (peng(xpx[i] - 48, xpy[i], now, xpx, xpy)) {
}
else {
switch (i) {
case 0:xpx[0] -= 48;break;
case 1:xpx[1] -= 48;break;
case 2:xpx[2] -= 48;break;
}
}
}
}
else {
x -= 48;
}
}
else if (a == 's' || a == 'S') {
i = peng(x, y + 48, now, xpx, xpy);
if (i) {
if (i > 5) {
i = i - 10;
if (peng(xpx[i], xpy[i] + 48, now, xpx, xpy)) {
}
else {
switch (i) {
case 0:xpy[0] += 48;break;
case 1:xpy[1] += 48;break;
case 2:xpy[2] += 48;break;
}
}
}
}
else {
y += 48;
}
}
else if (a == 'd' || a == 'D') {
i = peng(x + 48, y, now, xpx, xpy);
if (i) {
if (i > 5) {
i = i - 10;
if (peng(xpx[i] + 48, xpy[i], now, xpx, xpy)) {
}
else {
switch (i) {
case 0:xpx[0] += 48;break;
case 1:xpx[1] += 48;break;
case 2:xpx[2] += 48;break;
}
}
}
}
else {
x += 48;
}
}
else if (a == 32) {
//cleardevice();
}
碰撞检测
int peng(int x,int y,mapnode* nowroom,int xpx[],int xpy[]){
int flag=0;
int i = 0;
if (x<0||y<0||x>10*48||y>10*48) {
flag = 1;
}
if (nowroom->number == 1) {
if (y <= 3 * 48 && x <= 10 * 48 || y == 6 * 48 && x == 2 * 48 || y == 4 * 48 && x == 9 * 48) {
flag = 1;
}
}
if (nowroom->number == 2) {
if (y <= 1 * 48 && x <= 4 * 48|| y <= 1 * 48 && x >= 6 * 48&& x <= 10 * 48){
flag = 1;
}
}
if (nowroom->number == 3) {
if (y==0||y==10 * 48 ||x==0||x<=3 * 48 &&y<=3 * 48 ||x<=3 * 48 &&y>=7 * 48 ||x>=7 * 48 &&y<=4 * 48 ||x>=7 * 48 &&y>=6 * 48) {
flag = 1;
}
for (i=0;i < 3;i++) {
if (x == xpx[i] && y == xpy[i]) {
flag = i+10;
}
}
}
if (nowroom->number == 4) {
if (y <= 1 * 48 && x <= 4 * 48 || y <= 1 * 48 && x >= 6 * 48 && x <= 10 * 48) {
flag = 1;
}
}
return flag;
}
这段先调用了一次碰撞检测函数peng()将人物是否碰上设定的物体或箱子返回,由于无法返回是哪个箱子,就自作聪明,将返回值改为对应的箱子号+10,这样在上一层函数中-10就能知道是哪个箱子。又调用了一次peng()函数判断箱子是否碰到物体或其他箱子,只要会碰上就不移动。这次返回0以外的其他数就没有什么区别了。
按理说这里应该再写个函数,使代码没那么臃肿,但是我感觉代码量应该不会差太多,加上赶时间。
资源
链接: https://pan.baidu.com/s/1mQCH5MHm24O-P5tuU1Od8g?pwd=58w6 提取码: 58w6 复制这段内容后打开百度网盘手机App,操作更方便哦
站内资源easyx图形库自制RPG类型小游戏配套资源-其他文档类资源-优快云下载
总结
部分资源使用了rpgmaker的免费素材
本文介绍了一款使用EasyX库开发的小游戏,涉及透明人物图片的加载、地图通过链表结构管理以及角色移动和碰撞检测的详细代码。作者分享了关键部分的实现细节,并附带了资源下载链接。
570





