C++黄金矿工

基本思路

  1. 定义钩子、物品、人物结构体,包含初始坐标,结束坐标,变化坐标,物品金币等。
  2. 随机数义物品初始坐标,实现初始化地图时物品随机散布。
  3. 随机定义物品价值或指定某物品价值,其中金块大小与价值正相关。
  4. 让钩子实现摆动,按下空格伸长,伸长到屏幕边缘或碰到物品后携带物品返回初始坐标。

教学视频📺

尚未实现的功能

  • 物品勾回来,显示 “+$coin” 金币的文字渐隐动画。
  • 分数、关卡设置。
  • 商店、大力药水、炸弹、移动💎地鼠等丰富游戏内容。

源码

main.cpp

#include "gold.hpp"

  

IMAGE imgs[6];

IMAGE IMGS[3];

IMAGE Hook_imgs[160];

IMAGE Hook_imgs_b;

  
  

void loadResource();        //加载素材

void draw();                //绘制画面

  
  

Hook hook;

  

void init();                                         //初始化

void hook_init(Hook *hook, int x, int y, int len);

  

void hook_draw(Hook *hook);                          //绘制钩子

  

void hook_swing(Hook *hook);                         //钩子摆动

  

void hook_contorl(Hook *hook);                       //下钩,收钩

  

void JudgeGrap();

  
  
  

Mine mine[MINE_NUM];

  

int main()

{

  initgraph(1080, 640);

  loadResource();

  init();

  
  

  while (1)

  {

    BeginBatchDraw();       //双缓冲

  

    draw();

    FlushBatchDraw();       //刷新

  

    hook_swing(&hook);

    hook_contorl(&hook);

    JudgeGrap();

    int m=0;

      for (int i = 0; i < 10; i++)

      {

          if(mine[i].flag == 0)

          {

              m++;

              if(m>=10)

              {

                  init();

              }

          }

      }

  }

  

  return 0;

  

}

  

void loadResource()             //加载素材

{

  for (int i = 0; i < 5; i++)

  {

    char str[50] = {0};

    sprintf_s(str, "./assets/images/%d.png", i);

    loadimage(&imgs[i], str);

  }

  loadimage(&imgs[5], "./assets/images/bk.jpg", 1080, 640 - 120);

  int x[3] = {xmall, medium, large};

  for (int k = 0; k < 3; ++k)

  {

    loadimage(&IMGS[k], "./assets/images/0.png", x[k] + 8, x[k]);

  }

    double R = -80;

  for (int m = 0; m < 160; ++m)

    {

        rotateimage(&Hook_imgs[m],&imgs[4],PI/180*R);

        ++R;

    }

    loadimage(&Hook_imgs_b,"./hgkg/assets/imagess/hook_b.png");

  
  
  

}

  

void init()                                         //初始化钩子

{

  loadResource();

  hook_init(&hook, 500, 100, 60);

  

  srand((unsigned) time(NULL));                    //初始化矿物

  for (int i = 0; i < MINE_NUM; i++)

  {

    mine[i].x = rand() % (getwidth() - 80);

    mine[i].y = rand() % (getheight() - 240) + 160;

    mine[i].flag = 1;

    mine[i].type = rand() % 3;

    mine[i].size = rand() % 3;

    if (mine[i].type == gold)

    {

      switch (mine[i].size)

      {

        case 0 :mine[i].gold = 150;

          break;

        case 1 :mine[i].gold = 300;

          break;

        case 2 :mine[i].gold = 500;

          break;

      }

    }

    else if (mine[i].type == bag)

    {

        mine[i].gold = rand()%300;

    }

    else if (mine[i].type == stone)

    {

        mine[i].gold = rand()%50;

    }

  

  }

}

  

void draw()                     //绘制画面

{

  setfillcolor(RGB(245, 204, 132));

  solidrectangle(0, 0, 1080, 120);

  putimage(0, 120, &imgs[5]);

  drawImg(getwidth() / 2 - 80, 0, &imgs[3]);

  hook_draw(&hook);

  

  for (int i = 0; i < MINE_NUM; i++)

  {

    if (mine[i].flag == 1)

    {

      if (mine[i].type == gold)

      {

        if (mine[i].gold == 150)

        {

          drawImg(mine[i].x, mine[i].y, &IMGS[0]);

        }

        if (mine[i].gold == 300)

        {

          drawImg(mine[i].x, mine[i].y, &IMGS[1]);

        }

        if (mine[i].gold == 500)

        {

          drawImg(mine[i].x, mine[i].y, &IMGS[2]);

        }

      } else if (mine[i].type == stone)

      {

        drawImg(mine[i].x, mine[i].y, &imgs[stone]);

      } else if (mine[i].type == bag)

      {

        drawImg(mine[i].x, mine[i].y, &imgs[bag]);

      }

    }

  

  }

}

  

void hook_init(Hook *hook, int x, int y, int len)

{

  hook->x = x;

  hook->y = y;

  hook->len = len;

  hook->ex = hook->x;

  hook->ey = hook->y + hook->len;

  hook->angle = 0.0;

  hook->dir = Right;

  hook->dx = 0;

  hook->dy = 0;

  hook->state = ST_Normal;

  hook->index = -1;

  

}

  

void hook_draw(Hook *hook)                        //绘制钩子

{

  setlinestyle(PS_SOLID, 3);

  setlinecolor(BROWN);

  line(hook->x, hook->y, hook->ex, hook->ey);

  

  //setfillcolor(WHITE);

  //solidcircle(hook->ex, hook->ey, 5);

  

    putimage(hook->ex-20,hook->ey-2,43,31,&Hook_imgs_b,(int)hook->angle*43,31,SRCAND);

    putimage(hook->ex-20,hook->ey-2,&Hook_imgs[(int)hook->angle+80],SRCPAINT);

  

    char score[30] = "";

    sprintf_s(score,"分数:%d",hook->coin);

    settextcolor(RGB(9,138,9));

    setbkmode(TRANSPARENT);

    settextstyle(50,0,"等线",0,0,620,0,0,0,0,100,0,10,0);

    outtextxy(20,30,score);

  

}

  

void hook_swing(Hook *hook)                       //摆动钩子

{

  if (hook->state == ST_Normal)

  {

  

    if (hook->dir == Right)

    {

      hook->angle += 0.15;

    } else if (hook->dir == Left)

    {

      hook->angle -= 0.15;

    }

  

    if (hook->angle > 80)

    {

      hook->dir = Left;

    } else if (hook->angle < -80)

    {

      hook->dir = Right;

    }

    hook->ex = hook->x + sin(PI / 180 * hook->angle) * hook->len;

    hook->ey = hook->y + cos(PI / 180 * hook->angle) * hook->len;

  }

}

  

void hook_contorl(Hook *hook)

{

  double speed = 0.5;

  

  if (GetAsyncKeyState(VK_SPACE))

  {

    hook->state = ST_Long;

    hook->dx = sin(PI / 180 * hook->angle) * speed;

    hook->dy = cos(PI / 180 * hook->angle) * speed;

  }

  if (hook->state == ST_Long)

  {

    hook->ex += hook->dx;

    hook->ey += hook->dy;

    if (hook->ex < 0 || hook->ex > getwidth() || hook->ey > getheight())

    {

      hook->state = ST_Short;

    }

  } else if (hook->state == ST_Short)

  {

    hook->ex -= hook->dx;

    hook->ey -= hook->dy;

    double dis = sqrt(pow(hook->x - hook->ex, 2) + pow(hook->y - hook->ey, 2));

    if (dis <= hook->len)

    {

      hook->state = ST_Normal;

    }

  }

}

  

void JudgeGrap()

{

    //判断抓到哪个物品

  

    for (int i = 0; i <= MINE_NUM; ++i)

    {

        if(mine[i].flag == true)

        {

            switch (mine[i].type)

            {

                case stone :

                    if(hook.ex>mine[i].x && hook.ex<mine[i].x+73 &&

                    hook.ey>mine[i].y && hook.ey< mine[i].y+62)

                    {

                        hook.index = i;

                    }

                    if(hook.index != -1)

                    {

                        hook.state = ST_Short;

                        mine[hook.index].x = hook.ex;

                        mine[hook.index].y = hook.ey;

                        if (int(sqrt(pow(hook.x - hook.ex, 2) + pow(hook.y - hook.ey, 2))) <= hook.len)

                        {

                            mine[hook.index].flag = false;

                            hook.coin+=mine[hook.index].gold;

                            hook.index = -1;

                            hook.state = ST_Normal;

  

                        }

                    }

                    break;

                case bag :

                    if(hook.ex>mine[i].x && hook.ex<mine[i].x+73 &&

                       hook.ey>mine[i].y && hook.ey< mine[i].y+62)

                    {

                        hook.index = i;

                    }

                    if(hook.index != -1)

                    {

                        hook.state = ST_Short;

                        mine[hook.index].x = hook.ex;

                        mine[hook.index].y = hook.ey;

                        if (int(sqrt(pow(hook.x - hook.ex, 2) + pow(hook.y - hook.ey, 2))) <= hook.len)

                        {

                            mine[hook.index].flag = false;

                            hook.coin+=mine[hook.index].gold;

                            hook.index = -1;

                            hook.state = ST_Normal;

  

                        }

                    }

                    break;

                case gold :

                    if (mine[i].gold == 150)

                    {

                        if (hook.ex > mine[i].x && hook.ex < mine[i].x + xmall + 8 &&

                            hook.ey > mine[i].y && hook.ey < mine[i].y + xmall)

                        {

                            hook.index = i;

                        }

                        if (hook.index != -1)

                        {

                            hook.state = ST_Short;

                            mine[hook.index].x = hook.ex;

                            mine[hook.index].y = hook.ey;

                            if (int(sqrt(pow(hook.x - hook.ex, 2) + pow(hook.y - hook.ey, 2))) <= hook.len)

                            {

                                mine[hook.index].flag = false;

                                hook.coin+=mine[hook.index].gold;

                                hook.index = -1;

                                hook.state = ST_Normal;

  

                            }

                        }

                    }

                    else if (mine[i].gold == 300)

                    {

                        if (hook.ex > mine[i].x && hook.ex < mine[i].x + medium + 8 &&

                            hook.ey > mine[i].y && hook.ey < mine[i].y + medium)

                        {

                            hook.index = i;

                        }

                        if (hook.index != -1)

                        {

                            hook.state = ST_Short;

                            mine[hook.index].x = hook.ex;

                            mine[hook.index].y = hook.ey;

                            if (int(sqrt(pow(hook.x - hook.ex, 2) + pow(hook.y - hook.ey, 2))) <= hook.len)

                            {

                                mine[hook.index].flag = false;

                                hook.coin+=mine[hook.index].gold;

                                hook.index = -1;

                                hook.state = ST_Normal;

  

                            }

                        }

                    }

                    else if (mine[i].gold == 500)

                    {

                        if (hook.ex > mine[i].x && hook.ex < mine[i].x + large + 8 &&

                            hook.ey > mine[i].y && hook.ey < mine[i].y + large)

                        {

                            hook.index = i;

                        }

                        if (hook.index != -1)

                        {

                            hook.state = ST_Short;

                            mine[hook.index].x = hook.ex;

                            mine[hook.index].y = hook.ey;

                            if (int(sqrt(pow(hook.x - hook.ex, 2) + pow(hook.y - hook.ey, 2))) <= hook.len)

                            {

                                mine[hook.index].flag = false;

                                hook.coin+=mine[hook.index].gold;

                                hook.index = -1;

                                hook.state = ST_Normal;

  

                            }

                        }

                    }

                    break;

  

            }

  

        }

  

    }

}

gold.hpp

#include <stdio.h>

#include <easyx.h>

#include <math.h>

#include "tools.hpp"

#include <time.h>

#include <stdlib.h>

  

#define PI 3.14159265359

#define MINE_NUM 10

  

enum Dir{Left,Right};

enum Status{ST_Normal,ST_Long,ST_Short};

enum Size{xmall=70,medium=90,large=120};

  
  
  

struct  Hook                //定义钩子

{

    double x,y;        //初始坐标

    double ex,ey;      //变化坐标

    double len;        //钩绳长度

    double angle;   //钩子旋转角度

    int dir;        //摆动方向

    double dx,dy;      //速度分量

    int state;      //当前状态

    int index;      //记录抓到的物品的下标

    int swing;      //钩子是否在摆动

    int coin=0;       //角色积分

};

  

struct Mine

{

    int x;

    int y;

    int size;

    int type;

    int flag;

    int gold;

};

  

enum Type

{

    gold,

    bag,

    stone,

};

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; }    // 处理超出上边界

  

    //printf("realw,h(%d,%d)\n", real_w, real_h);

    // 修正贴图起始位置

    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;

    }

}
comments powered by Disqus