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;
}
资源文件