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

news2024/11/21 0:30:33

没有接触制作小游戏前,感觉做游戏很不可思议,游戏里的人物是怎么移动的,怎么攻击,释放技能。。。。。。现在逐渐了解到之后,发现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.coloradmin.cn/o/502033.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

鲲鹏展翅 信安高飞 | 鲲鹏开发者峰会2023-麒麟信安技术论坛成功举办!

2023年5月6日-7日&#xff0c;以“创未来 享非凡”为主题的鲲鹏开发者峰会2023在东莞松山湖举办。鲲鹏产业生态繁荣&#xff0c;稳步发展&#xff0c;正在成为行业核心场景及科研领域首选&#xff0c;加速推动数字化转型。 作为鲲鹏生态重要合作伙伴&#xff0c;麒麟信安受邀举…

企企通:B2B商城四种“玩法”,一站式解决端到端全链路需求!

商城系统在电商零售领域中&#xff0c;一直是助力商家搭建商城的核心工具&#xff0c;随着电商行业的发展&#xff0c;各种新模式随即出现&#xff0c;与此同时也出现了各种各样的商城系统&#xff0c;而B2B商城是这其中最为常见的商城系统。 近年来&#xff0c;由于电子商务的…

相遇于此,相交链表的解题心得

本篇博客会讲解力扣“160. 相交链表”的解题思路&#xff0c;这是题目链接。 老规矩&#xff0c;先来审题。这道题的题干有点长&#xff0c;简而言之&#xff0c;就是判断2个链表是否相交&#xff0c;如果相交就返回第一个相交结点&#xff0c;不相交就返回NULL。看看题目原文…

【C++中可调用对象和function】

C中有如下几种可调用对象&#xff1a;函数、函数指针、lambda表达式、bind对象、仿函数。其中&#xff0c;lambda表达式和bind对象是C11标准中提出的(bind机制并不是新标准中首次提出&#xff0c;而是对旧版本中bind1st和bind2st的合并)。个人认为五种可调用对象中&#xff0c;…

FM33A048B LPUART

概述 LPUART 是一个低功耗UART 接口&#xff0c;其工作仅需32768Hz 时钟&#xff0c;可以支持到最高9600 波特率的数据接收。LPUART 功耗极低&#xff0c;可以在Sleep/DeepSleep 模式下工作。 特点&#xff1a; ⚫ 异步数据收发 ⚫ 标准UART帧格式 ◼ 1bit起始位 ◼ 7或8bit数据…

【ChatGPT Prompt Engineering】面向Java开发者的ChatGPT提示词工程(1)

各位Java开发者们&#xff0c;欢迎来到万猫学社&#xff01;在这里&#xff0c;我将和大家分享ChatGPT提示词工程的系列文章&#xff0c;希望能够和大家一起学习和探讨提示词的最佳实践。 虽然互联网上已经有很多有关提示词的材料&#xff0c;比如那些“每个人都必须知道的30个…

lua是什么?lua的基本语法知识点

目录 一、lua是什么&#xff1f; 二、lua的基本语法 1.运行lua脚本文件 2.注释 3.标示符 4.关键词 5.全局变量 三、数据类型 8个基本类型 1.nil(空&#xff09; 2.boolean&#xff08;布尔&#xff09; 3.number(数字&#xff09; 4.string(字符串&#xff09; 5…

一图看懂 six 模块:最常见的 POSIX 系统调用, 资料整理+笔记(大全)

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 six 模块&#xff1a;最常见的 POSIX 系统调用, 资料整理笔记&#xff08;大全&#xff09; 摘要模块图类关系图模块全展开【six】统计常量intboolstrtuplelist 模块24 fun…

电脑屏幕开机后一直闪不停怎么办?电脑屏幕闪烁的解决方法

不少电脑用户经常会遇到的一种情况&#xff0c;就是开机后&#xff0c;发现电脑屏幕一直闪不停&#xff0c;十分伤眼。驱动人生就为大家带来电脑屏幕闪烁的解决方法。 首先&#xff0c;驱动人生建议可以排查一下出现电脑屏幕闪烁的原因&#xff0c;从而更加针对性的解决故障。…

SpringBoot 整合第三方技术Junit+MyBatis+Druid

测试类中加两个注解就行 SpringBootTest(classes Application.class)//添加SpringBoot 的启动类&#xff0c;万无一失 RunWith(SpringJUnit4ClassRunner.class) public class SpringBootJunitTest {Testpublic void test(){System.out.println("ddddddddddddddddddd&quo…

四象限法则定量分析法,如何客观划分需求优先级?

四象限法按照重要和紧急程度&#xff0c;划分为4个象限&#xff1a;重要且紧急、重要不紧急、不重要但紧急、不重要不紧急。那么我们如何客观地对需求进行评估&#xff0c;并将其放到对应的象限&#xff1f; 我们可以使用定量分析方法对象限进行划分和定值。在横纵坐标中&#…

php+mysql求职招聘人才网站

1&#xff0e;系统登录&#xff1a;系统登录是用户访问系统的路口&#xff0c;设计了系统登录界面&#xff0c;包括用户名、密码和验证码&#xff0c;然后对登录进来的用户判断身份信息&#xff0c;判断是管理员用户还是普通用户[10]。 2&#xff0e;系统用户管理&#xff1a;不…

温湿度换算绝对含水量

常压下 公式如下 y z * ( 8.0141786694E-09*x^5 2.3071566385E-06*x^4 1.3157923494E-04*x^3 1.1376256438E-02*x^2 3.1867343275E-01*x 4.9021104226E00 ) 式子中 z 相对湿度 单位百分比 x 摄氏度 单位度 取值范围 5-100度 y 绝对湿度 单位 克每立方…

OSPF原理—详细!!

OSPF&#xff08;open shortest path first&#xff09;&#xff1a;开放式最短路径优先 定义&#xff1a;是基于链路状态算法的路由协议 为什么要用OSPF&#xff1f; 网络发生变化&#xff0c;静态路由需要手动配置&#xff0c;太麻烦无法响应网络变化&#xff0c;需要手动更…

鸟哥的Linux私房菜——基础学习篇(第三版) (11-17章)

基础学习篇 第十一章 &#xff1a;认识和学习bash第十二章 &#xff1a;正则表达式与文件格式化处理第十三章 &#xff1a;学习shell script第十四章 &#xff1a;Linux账号管理与ACL权限设定第十五章 &#xff1a;磁盘配额(Quota)与进阶文件系统管理第十六章 &#xff1a;例行…

C++List类详解

目录 1.List介绍 2.List的常见使用 2.1 list的构造函数 2.2 list iterator的使用 2.3 list capacity 2.4 list element access 2.5 list modifiers 2.6 list的迭代器失效 3.List的模拟实现 3.1 list模拟实现&#xff08;可跳过&#xff09; 3.2 反向迭代器实现 3.2.1 list反…

100天精通Python(可视化篇)——第86天:matplotlib绘制不同种类炫酷热力图参数说明+代码实战

文章目录 专栏导读一、热力图介绍1. 介绍2. 参数说明 二、绘制热力图1. 普通热力图2. 添加坐标轴和标题3. 添加热力标尺4. 添加色块数值5. 修改热力图颜色6. 突出特殊数据 三、应用场景1. 适用场景2. 不适用场景 专栏导读 &#x1f525;&#x1f525;本文已收录于《100天精通P…

如何提高亚马逊卖家订单量?这些建议和技巧值得收藏

作为全球最大的电商平台之一&#xff0c;亚马逊拥有庞大的客户基础和丰富的销售渠道&#xff0c;这对于亚马逊卖家来说是一个非常宝贵的机会。但是&#xff0c;如何提高亚马逊卖家订单量是一个非常重要的问题。在本文中&#xff0c;我将分享一些提高亚马逊卖家订单量的建议和技…

【软考备战·希赛网每日一练】2023年5月8日

文章目录 一、今日成绩二、错题总结第一题第二题 三、知识查缺 题目及解析来源&#xff1a;2023年05月08日软件设计师每日一练 一、今日成绩 二、错题总结 第一题 解析&#xff1a; 题目中存在一个 指向链表尾元素的指针&#xff0c;所以插入操作直接通过该指针进行后续操作即…

MySQL数据库用户管理以及数据库用户授权

一、数据库用户管理 1、新建用户 CREATE USER 用户名来源地址 [IDENTIFIED BY [PASSWORD] 密码]; ---------------------------------------------------------------------------------------------------------- 用户名&#xff1a;指定将创建的用户名 来源地址&#xff1a…