DNF类游戏动作实现(C语言)

news/2024/11/28 7:48:26/

没有接触制作小游戏前,感觉做游戏很不可思议,游戏里的人物是怎么移动的,怎么攻击,释放技能。。。。。。现在逐渐了解到之后,发现2d游戏人物的动作更多是图片的拼接,动作是否精细,由这个动作的帧数决定。这篇博客会简单实现2d人物的动作,效果如下。

2d人物动作展示

想实现这个效果其实很简单,思路如下:
1.创建图形库程序

#include<graphics.h>initgraph(int宽, int高);closegraph();//关闭窗口


2.导入图片素材

将装图片素材的文件导入到程序的同一文件夹下,需要素材的小伙伴可以私信我

 这是导入图片的步骤

给图片起一个名字IMAGE 图片名字;
加载图片loadimage(&图片名字,"图片路径",显示的宽,显示的高);
显示图片putimage(int x,int y,int w,int h,&图片名字,int xx,int yy);xx,yy表示在图片中取区域的起始位置w,h表示取的图片区域的大小x,y表示在图形界面显示的坐标

这里拿导入背景举例

#include<stdio.h>
#include<conio.h>//防止闪屏
#include<graphics.h>
int main()
{initgraph(1000, 650);IMAGE background;loadimage(&background, "Background\\background.bmp");putimage(0, 0, &background);_getch();closegraph();return 0;}

 导入人物需要用到透明贴图技术(原理大家可以自行搜索,这里就不写了)

        背景图:黑色实物


        掩码图:白底黑洞


    具体过程
        先贴掩码图 AND方式 SRCAND

        putimage(int x,int y,&图片名,SRCAND);


        再贴背景图 PAINT方式 SRCPAINT

      putimage(int x,int y,&图片名,SRCAND);

因为我们的图片是长条形的,我们只需要取一部分,这里取宽400px,高300px的第一部分

 在上面背景图的代码中加入人物站立的代码,其中role.position控制人物的朝向

#include<stdio.h>
#include<conio.h>//防止闪屏
#include<graphics.h>
IMAGE background;
IMAGE standImg[2];//这里是2的原因是,我们人物需要左右各有一个站立的动作 背景图:0表示左边 1表示右边
IMAGE standImgY[2];//掩码图
struct actor {int x;int y;int position;//人物朝向
};
struct actor role = { 0,250,1 };void loadResource()
{loadimage(&standImg[0], "Stand\\left.bmp");loadimage(&standImg[1], "Stand\\right.bmp");loadimage(&standImgY[0], "Stand\\lefty.bmp");loadimage(&standImgY[1], "Stand\\righty.bmp");
}void drawRoleStand()
{putimage(0, 0, &background);putimage(role.x, role.y, 400, 300, &standImgY[role.position], 0, 0, SRCAND);putimage(role.x, role.y, 400, 300, &standImg[role.position], 0, 0, SRCPAINT);
}
int main()
{initgraph(1000, 650);loadimage(&background, "Background\\background.bmp");putimage(0, 0, &background);loadResource();drawRoleStand();_getch();closegraph();return 0;}

3.给图片做位移:左右移动,挥砍,跳跃这些动作其实都是图片变换,这里拿左右移动举例

加上这部分代码实现人物左右移动,其余动作都是同理,关键部分已经在代码中注释

IMAGE moveImg[2];
IMAGE moveImgY[2];void loadResource()//加载左右移动图片
{loadimage(&moveImg[0], "Move\\left.bmp");loadimage(&moveImg[1], "Move\\right.bmp");loadimage(&moveImgY[0], "Move\\lefty.bmp");loadimage(&moveImgY[1], "Move\\righty.bmp");
}void moveRole()//当role.position=0时,每次向左移动5像素 向右同理
{switch (role.position){case 0:role.x -= 5;break;case 1:role.x += 5;break;}
}void drawRoleMove(int zhenshu)//根据position的值向左或者向右移动 因为我们的图片有8帧,每次选图片中400*(i-1)px开始的位置
{for (int i = 0; i < zhenshu; i++){BeginBatchDraw();//双缓冲绘图防止闪屏putimage(0, 0,  &background);putimage(role.x, role.y, 400, 300, &moveImgY[role.position], 400 * i, 0, SRCAND);putimage(role.x, role.y, 400, 300, &moveImg[role.position], 400 * i, 0, SRCPAINT);moveRole();Sleep(20);//设置延迟EndBatchDraw();//双缓冲绘图}
}void keyDown()//这里输入键盘按键和程序交互
{char userKey = _getch();  //C语言的原本的函数是getch() VS对它做了优化switch (userKey){case'A':case'a':case 75:role.position = 0;drawRoleMove(8);//drawRoleMove(8)里面8的原因是,我们move的图片素材有8帧printf("左");//为了程序思路更清楚,可以不要break;case'd':case'D':case 77:role.position = 1;drawRoleMove(8);printf("右");break;}
}
int main()
{initgraph(1000, 650);loadimage(&background, "Background\\background.bmp");putimage(0, 0, &background);loadResource();while (true){drawRoleStand();keyDown();}_getch();closegraph();return 0;}

 

 加上上面代码,人物实现左右移动

剩余的跳跃,攻击......代码与移动基本无差(所以素材很重要,有素材基本就是换皮哈哈)

看到这的小伙伴记得点赞,收藏哦

下面附上完整代码,需要素材的小伙伴可以评论或者私信联系我

#include<stdio.h>
#include<conio.h>//防止闪屏
#include<graphics.h>
#include<easyx.h>
//数据设计-->基础知识+资源+游戏分析(角色的要素)
//透明贴图
IMAGE background;
IMAGE standImg[2];//背景图:0表示左边 1表示右边
IMAGE standImgY[2];
IMAGE moveImg[2];
IMAGE moveImgY[2];
IMAGE jumpImg[2];
IMAGE jumpImgY[2];
IMAGE jumpCut[2];
IMAGE jumpCutY[2];
IMAGE cutImg[2];
IMAGE cutImgY[2];
//角色属性
struct actor {int x;int y;int position;//人物朝向
};
//背景属性
struct bground{int x;int y;
};
struct bground bgInfo = { 0,0 };
struct actor role = { 0,250,1 };
//初始化变量
void loadResource()
{//加载资源loadimage(&background, "Background\\background.bmp");//loadimage(&图片名字, "图片路径",1000,650); 加载图片loadimage(&standImg[0], "Stand\\left.bmp");loadimage(&standImg[1], "Stand\\right.bmp");loadimage(&standImgY[0], "Stand\\lefty.bmp");loadimage(&standImgY[1], "Stand\\righty.bmp");loadimage(&moveImg[0], "Move\\left.bmp");loadimage(&moveImg[1], "Move\\right.bmp");loadimage(&moveImgY[0], "Move\\lefty.bmp");loadimage(&moveImgY[1], "Move\\righty.bmp");loadimage(&jumpImg[0], "Jump\\left.bmp");loadimage(&jumpImg[1], "Jump\\right.bmp");loadimage(&jumpImgY[0], "Jump\\lefty.bmp");loadimage(&jumpImgY[1], "Jump\\righty.bmp");loadimage(&jumpCut[0], "JumpCut\\left.bmp");loadimage(&jumpCut[1], "JumpCut\\right.bmp");loadimage(&jumpCutY[0], "JumpCut\\lefty.bmp");loadimage(&jumpCutY[1], "JumpCut\\righty.bmp");loadimage(&cutImg[0], "Cut\\left.bmp");loadimage(&cutImg[1], "Cut\\right.bmp");loadimage(&cutImgY[0], "Cut\\lefty.bmp");loadimage(&cutImgY[1], "Cut\\righty.bmp");
}
//布局
void drawRoleStand()
{putimage(0, 0,1000,650, &background,bgInfo.x,bgInfo.y);putimage(role.x, role.y, 400, 300, &standImgY[role.position], 0,0,SRCAND);putimage(role.x, role.y, 400, 300, &standImg[role.position],0,0, SRCPAINT);
}
//逻辑-->用户逻辑//根据人物方向做位移变化
void moveRole()
{switch (role.position){case 0:if (role.x > -160){role.x -= 5;}else{role.x = -160;}if (bgInfo.x > 0){bgInfo.x -= 10;}else{bgInfo.x = 0;}break;case 1:role.x += 5;bgInfo.x += 10;break;}
}
//描述人物动作
void drawRoleMove(int zhenshu)
{for (int i = 0; i < zhenshu; i++){BeginBatchDraw();putimage(0, 0, 1000, 650, &background, bgInfo.x, bgInfo.y);putimage(role.x, role.y, 400, 300, &moveImgY[role.position], 400*i, 0, SRCAND);putimage(role.x, role.y, 400, 300, &moveImg[role.position], 400*i, 0, SRCPAINT);moveRole();Sleep(20);EndBatchDraw();}
}
//跳跃
void drawRoleJump(int zhenshu)
{for (int i = 0; i < zhenshu; i++){BeginBatchDraw();putimage(0, 0, 1000, 650, &background, bgInfo.x, bgInfo.y);putimage(role.x, role.y, 400, 300, &jumpImgY[role.position], 400 * i, 0, SRCAND);putimage(role.x, role.y, 400, 300, &jumpImg[role.position], 400 * i, 0, SRCPAINT);moveRole(); //跳跃时不做横向位移就不写这行Sleep(20);EndBatchDraw();}
}
void drawRoleCut(int franmeNum)
{for (int i = 0; i < franmeNum; i++){BeginBatchDraw();putimage(0, 0, 1000, 650, &background, bgInfo.x, bgInfo.y);putimage(role.x, role.y, 400, 300, &cutImgY[role.position], 400 * i, 0, SRCAND);putimage(role.x, role.y, 400, 300, &cutImg[role.position], 400 * i, 0, SRCPAINT);moveRole();  //跳跃不做位移变化Sleep(50);EndBatchDraw();}
}
void drawRoleJumpCut(int frameNum)
{for (int i = 0; i < frameNum; i++){BeginBatchDraw();putimage(0, 0, 1000, 650, &background, bgInfo.x, bgInfo.y);putimage(role.x, role.y, 400, 300, &jumpCutY[role.position], 400 * i, 0, SRCAND);putimage(role.x, role.y, 400, 300, &jumpCut[role.position], 400 * i, 0, SRCPAINT);moveRole();  //跳跃不做位移变化Sleep(50);EndBatchDraw();}
}
//操作游戏-->按键操作
//鼠标操作
void keyDown()
{char userKey = _getch();  //C语言的原本的函数是getch() VS对它做了优化switch (userKey){case'A':case'a':case 75:role.position = 0;drawRoleMove(8);printf("左");break;case'd':case'D':case 77:role.position = 1;drawRoleMove(8);printf("右");break;case'j':case'J':drawRoleJumpCut(6);printf("跳砍");break;case'k':drawRoleCut(7);printf("跳砍");break;case' ':drawRoleJump(8);printf("跳");break;}
}
int main()
{loadResource();initgraph(1000, 650);while (true){drawRoleStand();keyDown();}closegraph();return 0;}


http://www.ppmy.cn/news/350503.html

相关文章

从汇编代码探究函数栈帧的创建和销毁的底层原理

人&#xff0c;只有在放弃战斗的时候才算输&#xff0c;只要坚持战斗&#xff0c;就还没输 本文收录于青花雾气-计算机基础 往期回顾 从0到1搞定在线OJ 数据在内存中的存储 计算机存储的大小端模式 目录 一、先导知识 二、函数调用堆栈 三、函数栈帧的创建 1.创建函数…

Vue2模拟俄罗斯方块小游戏

目录 一、效果展示 二、代码分享 三、原理分析 3.1、界面搭建 3.2、方块创建 3.3、方块旋转 3.4、方块移动 3.5、移动判断 3.6、下落判断与清除 3.7、得分计算 一、效果展示 二、代码分享 <template><div class"game"><div class"ga…

ipv6端口阻塞(例如比特彗星黄灯)

如果是tplink路由器&#xff0c;可能会遇到路由器自带的ipv6防火墙&#xff0c;不关闭的话永远是黄灯&#xff0c;win10系统关闭防火墙、upnp、虚拟服务器、DMZ都是没用的。5430已经在最新固件中新增手动关闭防火墙功能。5480等暂时没有&#xff0c;官方表示后续固件会更新此功…

win10,使用bitcomet外网阻塞(黄灯)的解决方法

2019独角兽企业重金招聘Python工程师标准>>> 1.路由开启UPNP功能&#xff0c;各自路由情况不一。 2.开启网络发现。 3.打开相应的端口。 转载于:https://my.oschina.net/u/261479/blog/738041

bitcomet端口阻塞解决方案

看了很多方法尝试了都不行。因为他们的环境跟我的都不一样。我比大部分网上的教程多了一个自购路由器且PC是直接用网线连接自购路由器。 因此&#xff0c;我的方法是在两个地方添加端口映射。一个是天翼网关&#xff0c;一个是附赠的路由器。 前期准备是请打电话去电信客服获取…

Windows Upnp 服务补丁——UpnpFix V1.0

先来介绍下Upnp服务是干啥的&#xff08;迅雷官网摘录&#xff09;&#xff1a; UPNP的英文全称是Universal Plug and Play&#xff0c;即通用即插即用协议,是为了实现电脑与智能的电器设备对等网络连接的体系结构。而内网地址与网络地址的转换就是基于此协议的&#xff0c;因此…

【工具】BT - 比特彗星(端口监听(UPnP、ipv6、防火墙)、反吸血、tracker、杀毒)

【比特彗星】官方文档&#xff1a; archive - http://www.bitcomet.com/en/archive全局设置 - http://wiki-zh.bitcomet.com/bitcomet全局选项 相关 【官方】BitComet(比特彗星)软件使用帮助 【官方】BT中常见术语解释 BT 比特彗星 优化教程 BT 比特彗星 设置指南、选项释义…

UPNP 相关资料(转)

UPNP的全称是 Universal plug-and-play( 通用即插即用).UPnP 是针对智能家电、无线设备以及各种外观尺寸的个人电脑的普遍对等&#xff08;peer-to-peer&#xff09;网络连接而设计的一种架构。它旨在为家庭、小型企业、公共场所中或连接到互联网的ad-hoc 网或未管理网络提供易…