24项目-黄金矿工

 tools.hpp

#pragma once
#include<easyx.h>

void drawImg(int x, int y,IMAGE *src)
{
	// 变量初始化
	DWORD* pwin = GetImageBuffer();			//窗口缓冲区指针
	DWORD* psrc = GetImageBuffer(src);		//图片缓冲区指针
	int win_w = getwidth();				//窗口宽高
	int win_h = getheight();
	int src_w = src->getwidth();				//图片宽高
	int src_h = src->getheight();
	
	// 计算贴图的实际长宽
	int real_w = (x + src_w > win_w) ? win_w - x : src_w;			// 处理超出右边界
	int real_h = (y + src_h > win_h) ? win_h - y : src_h;			// 处理超出下边界
	if (x < 0) { psrc += -x;			real_w -= -x;	x = 0; }	// 处理超出左边界
	if (y < 0) { psrc += (src_w * -y);	real_h -= -y;	y = 0; }	// 处理超出上边界


	// 修正贴图起始位置
	pwin += (win_w * y + x);

	// 实现透明贴图
	for (int iy = 0; iy < real_h; iy++)
	{
		for (int ix = 0; ix < real_w; ix++)
		{
			byte a = (byte)(psrc[ix] >> 24);//计算透明通道的值[0,256) 0为完全透明 255为完全不透明
			if (a > 100)
			{
				pwin[ix] = psrc[ix];
			}
		}
		//换到下一行
		pwin += win_w;
		psrc += src_w;
	}
}

void drawImg(int x, int y, int dstW, int dstH, IMAGE* src, int srcX, int srcY)
{
	// 变量初始化
	DWORD* pwin = GetImageBuffer();			//窗口缓冲区指针
	DWORD* psrc = GetImageBuffer(src);		//图片缓冲区指针
	int win_w = getwidth();				//窗口宽高
	int win_h = getheight();
	int src_w = src->getwidth();				//图片宽高
	int src_h = src->getheight();


	// 计算贴图的实际长宽
	int real_w = (x + dstW > win_w) ? win_w - x : dstW;			// 处理超出右边界
	int real_h = (y + dstH > win_h) ? win_h - y : dstH;			// 处理超出下边界
	if (x < 0) { psrc += -x;			real_w -= -x;	x = 0; }	// 处理超出左边界
	if (y < 0) { psrc += (dstW * -y);	real_h -= -y;	y = 0; }	// 处理超出上边界

	// 修正贴图起始位置
	pwin += (win_w * y + x);

	// 实现透明贴图
	for (int iy = 0; iy < real_h; iy++)
	{
		for (int ix = 0; ix < real_w; ix++)
		{
			byte a = (byte)(psrc[ix + srcX + srcY * src_w] >> 24);//计算透明通道的值[0,256) 0为完全透明 255为完全不透明
			if (a > 100)
			{
				pwin[ix] = psrc[ix + srcX + srcY * src_w];
			}
		}
		//换到下一行
		pwin += win_w;
		psrc += src_w;
	}
}
/*
 *@Easyx B站学习地址:https://www.bilibili.com/video/BV11p4y1i74A?from=search&seid=15227723645663445849
 *@微信公众号:C语言Plus		
 *@png透明贴图
*/

main.cpp

#include<stdio.h>
#include<easyx.h>
#include"tools.hpp"
#include<math.h>
#include<stdlib.h>
#include<time.h>
/*
* 项目内容:黄金矿工
* 课程讲师:顽石老师
* 开发环境:vs2019 + EasyX图形库
*/

//资源
IMAGE img_bk;
IMAGE imgs[4];
void loadResource()
{
	//加载图片 记得修改字符集
	loadimage(&img_bk, "./res/bk.jpg",0,getheight() - 120);
	for (int i = 0; i < 4; i++)
	{
		char buf[20] = { 0 };
		sprintf(buf,"./res/%d.png", i);
		loadimage(imgs + i, buf);
	}
}

/* @老人*/
struct Role
{
	int x;
	int y;
	int width;
	int height;
	int coin;	//总金币数量
};
//初始化角色
void role_init(Role* role, int x, int y)
{
	role->x = x;
	role->y = y;
	role->width = imgs[3].getwidth();
	role->height = imgs[3].getheight();
	role->coin = 0;
}
//绘制角色
void role_draw(Role* role)
{
	drawImg(role->x,role->y, imgs + 3);
	//绘制分数
	//设置文字样式
	settextstyle(48, 0, "华文行楷");
	//设置文字颜色
	settextcolor(BLACK);
	//设置背景模式
	setbkmode(TRANSPARENT);

	char str[50] = { 0 };
	sprintf(str, "金币数:%d", role->coin);
	outtextxy(20, (role->height - textheight(str)) / 2, str);
}

/* @钩子*/
#define HOOK_SWING_MAX_ANGLE 80	//钩子最大摆动角度
#define MANHATTAN_DIS(hook) sqrt((hook->x - hook->endx) * (hook->x - hook->endx) + (hook->y - hook->endy)*(hook->y - hook->endy))
enum  Dir{Left,Right};
enum State{Normal,Long,Short};
struct Hook
{
	double x;		
	double y;
	int len;	//长度
	double endx;	//结束点坐标
	double endy;
	double angle;	//摆动角度
	int swingDir;	//摆动方向,左,右
	double dx;			//速度变化量
	double dy;
	int state;		//钩子状态
	int index;		//抓取到的矿的下标
};

void hook_init(Hook* hook, int x, int y)
{
	hook->x = x;
	hook->y = y;
	hook->len = 50;
	hook->endx = hook->x;
	hook->endy = hook->y + hook->len;
	hook->angle = 0.0;
	hook->swingDir = Right;
	hook->dx = 0;
	hook->dy = 0;
	hook->state = Normal;
	hook->index = -1;
}

void hook_draw(Hook* hook)
{
	//设置线条的样式
	setlinestyle(PS_SOLID, 3);
	//设置线条的颜色
	setlinecolor(BROWN);
	line(hook->x,hook->y,hook->endx,hook->endy);
	//画个坨
	setfillcolor(GREEN);
	solidcircle(hook->endx, hook->endy, 5);
}

void hook_swing(Hook* hook, double angleStep)
{
	if (hook->state == Normal)
	{
		//限制摆动角度
		if (hook->angle >= HOOK_SWING_MAX_ANGLE)	//大于最大角度
		{
			hook->swingDir = Left;
		}
		else if (hook->angle <= -HOOK_SWING_MAX_ANGLE)//小于最小的角度
		{
			hook->swingDir = Right;
		}

		if (hook->swingDir == Right)
		{
			hook->angle += angleStep;
		}
		else if (hook->swingDir == Left)
		{
			hook->angle -= angleStep;
		}
		//更新一下endx,endy sin cos 需要的不是角度而是弧度
		hook->endx = hook->x + sin(3.1415 / 180 * hook->angle) * hook->len;
		hook->endy = hook->y + cos(3.1415 / 180 * hook->angle) * hook->len;
	}
}

void hook_control(Hook* hook,int speed)
{
	//按空格键钩子伸长
	if (GetAsyncKeyState(VK_SPACE) & 0x8000 && hook->state == Normal)
	{
		hook->state = Long;
		//求dx,dy
		hook->dx = sin(3.14 / 180 * hook->angle)* speed;
		hook->dy = cos(3.14 / 180 * hook->angle)* speed;
	}
	if (hook->state == Long)
	{
		hook->endx += hook->dx;
		hook->endy += hook->dy;
		//printf("%d %d  %lf %lf\n", hook->endx, hook->endy,hook->dx,hook->dy);
	}
	else if (hook->state == Short)
	{
		hook->endx -= hook->dx;
		hook->endy -= hook->dy;
		//缩短到什么时候恢复正常状态
		if (MANHATTAN_DIS(hook) <= hook->len && hook->index == -1)
		{
			hook->state = Normal;
			printf("up over\n");
		}	
	}

	//碰到边界缩回
	if (hook->endx <= 0 || hook->endx >= getwidth() || hook->endy >= getheight())
	{
		hook->state = Short;
	}
	//抓到东西之后也缩短
}

/* @矿*/
#define MAX_MINE_NUM 10	
enum MineType { Gold, Wallet,Stone,Max_Type};	//0 1 2 
struct Mine
{
	int x;
	int y;
	int width;
	int heihgt;
	bool isDie;	//是否被抓了
	int gold;	//值多少钱
	int type;	//矿的类型
};

void mine_init(Mine* mine, int x, int y,int type)
{
	mine->x = x;
	mine->y = y;
	mine->type = type;
	mine->isDie = false;
	mine->gold = rand() % 100;

	mine->width = imgs[mine->type].getwidth();
	mine->heihgt = imgs[mine->type].getheight();
}

void mine_draw(Mine* mine)
{
	if(!mine->isDie)
		drawImg(mine->x, mine->y, imgs + mine->type);
}
//钩子抓矿,矿跟着钩子走
void hookGrapMines(Hook* hook, Mine* mines,Role*oldMan)
{
	if (hook->state == Normal)
	{
		return;
	}

	//找抓到的矿
	for (int i = 0; i < MAX_MINE_NUM; i++)
	{
		if (!mines[i].isDie && 
			hook->endx > mines[i].x&& hook->endx < mines[i].x + mines[i].width &&
			hook->endy >mines[i].y && hook->endy< mines[i].y+ mines[i].heihgt)
		{
			hook->index = i;
			break;	//找到了就退出
		}
	}

	//抓到之后处理
	if (hook->index != -1)
	{
		//钩子缩短
		hook->state = Short;	 
		//矿跟着钩子跑
		mines[hook->index].x = hook->endx - mines[hook->index].width / 2;
		mines[hook->index].y = hook->endy - mines[hook->index].heihgt / 2;
		
		//如果钩子恢复到正常长度
		if (MANHATTAN_DIS(hook) <= hook->len)
		{
			hook->state = Normal;
			mines[hook->index].isDie = true;			//矿挂掉
			oldMan->coin += mines[hook->index].gold;	//加钱
			hook->index = -1;	
			printf("down over\n");
		}
	}

}


Role oldMan;
Hook hook;
Mine mines[MAX_MINE_NUM];

void init()
{
	//设置随机数种子
	srand(time(NULL));

	loadResource();
	role_init(&oldMan, (getwidth() - imgs[3].getwidth()) / 2, 0);
	hook_init(&hook, oldMan.x + 40, oldMan.y + 100);
	for (int i = 0; i < MAX_MINE_NUM; i++)
	{
		int x = rand() % (getwidth() - 40) +20;
		int y = oldMan.height + rand() % (getheight() - oldMan.height);
		mine_init(mines + i, x, y, rand() % Max_Type);
	}
}

void draw()
{
	//绘制背景图
	putimage(0, 120, &img_bk);
	//绘制老头所在的位置的背景颜色
	setfillcolor(YELLOW);
	solidrectangle(0, 0, getwidth(), imgs[3].getheight());
	//绘制老头
	role_draw(&oldMan);
	//绘制钩子
	hook_draw(&hook);
	//绘制矿
	for (int i = 0; i < MAX_MINE_NUM; i++)
	{
		mine_draw(mines + i);
	}
}

int main()
{
	initgraph(1080, 640,EW_SHOWCONSOLE);
	
	init();

	while (true)
	{
		BeginBatchDraw();//开始双缓冲
		draw();
		EndBatchDraw();//结束双缓冲

		hook_swing(&hook, 0.1);
		hook_control(&hook,1);
		hookGrapMines(&hook, mines,&oldMan);
	}



	getchar();
	return 0;
}

资源文件

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值