最终效果图
前言
小工具实现了三个基本功能:时钟,计时器和一个世界线探测功能【假】,会自动定位桌面的右下角,按钮功能设计上,左右箭头是功能选择键,左OK键是确认选择键,右OK键是功能键,最靠边的两个按钮分别是熄灯键和退出键。
源码全发出来的话有点长,所以只贴出来了部分源码以及结构,文章的目的也是方便大家快速理解下载的这坨代码。(下载按钮在文章开头)
下载的压缩包内分为工程文件夹和可执行文件夹,可执行文件夹内双击Stein;Gate.exe可直接运行。
设计思路
数据结构
文件结构
源码部分展示
main
init负责初始化操作,tick负责每帧的数据更新,draw负责图像的更新操作,sleep负责限制刷新速度从而减少cpu的占用,三个函数的具体内容都已在main函数上方声明定义
int main()
{
init();
while (true)
{
tick();
draw();
Sleep(1000/60);
}
}
Base
头文件中声明了所有需要全局使用的变量,Base.cpp文件只有在头文件中的两个extern的变量的初始化和drawAlpha函数的定义。
Base文件夹中声明了
UpdateLightData,UpdateButtonData
UpdateLightDraw,UpdateButtonDraw
四个函数再加上一个初始化按钮的InitButton函数以供对应的Light和Button文件定义和main函数调用使用。
drawAlpha函数用于在easyX中绘制具有透明背景的png图片,在本项目中用于绘制按钮的高亮效果,该函数引用自【使用 EASYX 载入PNG图并透明背景】博主「抱起老婆就跑」
//Base.h
#pragma once
#include "graphics.h"
#include <iostream>
#include "Screen.h"
using namespace std;
#define WIDTH 648//窗口大小
#define HEIGHT 256
#define MAXBTN 10//最大按钮数量
static string ImgPath = "./Image/";//默认图片路径
static IMAGE* bk = new IMAGE;//背景用的IMAGE容器
class Button;//前向声明
extern Button** Buttons;//指向Button指针数组的指针
static ExMessage m;//用来获取鼠标事件
static IMAGE* lightImg = new IMAGE;//灯光更新用的IMAGE容器
static int Lights[8] = { 10 };//初始化灯光数组
static int LightsTemp[8] = { 1, 11, 0, 4, 8, 5, 9, 6 };//初始世界线
static SYSTEMTIME systime;//时钟模式与计时器模式所需
static SYSTEMTIME Startsystime;//计时器模式所需
extern string WorldName_Temp;//世界线模式所需
static string WorldTime = "1.048596";//Steins;Gate世界线
static int TimeCount = 0;//世界线模式所需
//此处声明,Light文件中定义
//Draw
void UpdateLightDraw();
//Tick
void UpdateLightData();
//此处声明,Button文件中定义
//Init
void InitButton();
//Draw
void UpdateButtonDraw();
//Tick
void UpdateButtonData();
//绘制透明贴图函数
void drawAlpha(IMAGE* picture, int picture_x, int picture_y);
Light
Light.h中没有任何声明函数
最主要的函数是用于Tick的SelectMode与UpdateLightData
以及用于Draw的SelectLightImg与UpdateLightDraw
//Light.cpp
void SelectMode()
{
switch (Screen::Instance->ModeIndex)
{
case 0:
UpdateTimeData(); break;//时钟模式
case 1:
UpdateCountData(); break;//计时器模式
case 2:
UpdateWorldData(); break;//世界线模式
}
}
//----------------------------------main中Tick会调用的函数----------------------------------
void UpdateLightData()
{
if (dynamic_cast<PowerButton*>(Buttons[1])->isPress)
{
for (int i = 0; i < 8; i++)
Lights[i] = 10;
}
else
{
SelectMode();
}
}
void selectLightImg(int i)
{
string s = ImgPath + to_string(i) + ".png";
loadimage(lightImg, s.c_str(), 78, 153);
}
//----------------------------------------main中Draw会调用的函数--------------------------
void UpdateLightDraw()
{
for (int i = 0; i < 8; i++)
{
selectLightImg(Lights[i]);
putimage(i * 78 + 12, 34, lightImg, SRCPAINT);
}
}
Screen
Screen.h中定义了Screen类,Screen.cpp中初始化了Instance和show函数的定义
//Screen.h
#pragma once
#include <iostream>
#include "graphics.h"
using namespace std;
class Screen
{
public:
Screen()
{
ScreenIndex = 0;
ModeIndex = 0;
ModeMax = 3;
ModeList[0] = "时钟 模式";
ModeList[1] = "计时器 模式";
ModeList[2] = "世界线变动率探测 模式";
WorldLine = "Steins;Gate世界線";
icon = "Play";
}
void show();
static Screen* Instance;
int ModeIndex;
int ScreenIndex;
int ModeMax;
string ModeList[3];
string WorldLine;
string icon;
};
Button
Button中定义了抽象类与其子类,以及四个全局函数,在Button.cpp中不仅完成了这四个函数的定义,还完成了在Base中声明的InitButton,UpdateButtonDraw,UpdateButtonData的定义
//Button.h
#pragma once
#include "graphics.h"
#include "Base.h"
using namespace std;
class Button
{
public:
Button(int x, int y, int w, int h)
{
this->x = x;
this->y = y;
this->w = w;
this->h = h;
}
int x, y;
int w, h;
bool Once = false;
IMAGE* image = new IMAGE;
bool isInRange = false;
virtual void click() = 0;
virtual void reset() {};
};
//四个全局函数
void DrawButton(Button* b);
bool isInButton(Button* b, ExMessage& m);
bool isClickButton(Button* b, ExMessage& m);
void ResetButton();
class ExitButton : public Button;//退出程序功能
class PowerButton : public Button;//熄灭灯光功能
class LArrowButton : public Button;//向左选择
class RArrowButton : public Button;//向右选择
class LOKButton : public Button;//确认选择
class ROKButton : public Button;//模式功能按键,依具体模式而定