FNAF同人:简陋的测试
前提:Visual studio 2022 c++17标准 EasyX库、
#include <graphics.h> // EasyX 图形库
#include <random>
#include <vector>
#include <thread>
#include <string>
#include <sstream>
#include <conio.h>using namespace std;// 节点结构体
typedef struct mynode {vector<mynode*> next;int data;int x, y; // 节点的屏幕坐标TCHAR name[32]; // 节点名称(TCHAR 类型)
} mynode;// 初始化节点
mynode r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12;
mynode att1, att2, att3;
mynode che1, che2, che3;// 界面参数
const COLORREF PANEL_COLOR = RGB(100, 100, 100); // 控制面板底色
const COLORREF PANEL_BORDER_COLOR = RGB(150, 150, 150); // 控制面板边框色
const COLORREF RED_BUTTON_COLOR = RGB(200, 50, 50); // 红色按钮颜色
const COLORREF ROOM_BUTTON_COLOR = RGB(80, 80, 120); // 房间控制按钮颜色
const COLORREF LIGHT_BUTTON_COLOR = RGB(200, 200, 100); // 灯光按钮颜色
const int PANEL_HEIGHT = 60; // 控制面板高度
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 700; // 增加窗口高度
const int NODE_RADIUS = 20; // 节点半径
const int CHAR_RADIUS = 15; // 角色半径
int roomid = 0;//0~2bool camerab = false;
bool redButtonActive = false; // 红色按钮状态
bool light = false;
bool Hack = false;// 生成随机移动时间
int generateSpecialRandom(std::mt19937& gen) {std::bernoulli_distribution prob_dist(0.1);if (prob_dist(gen)) {std::uniform_int_distribution<> dist(200, 400); // 小概率快速移动return dist(gen);}else {std::uniform_int_distribution<> dist(500, 700); // 大概率慢速移动return dist(gen);}
}// 随机移动(避免回头)
mynode* get_random_move_with_memory(mynode* current, mynode* previous, mt19937& mt) {if (current->next.empty()) {return nullptr;}vector<mynode*> candidates;for (auto node : current->next) {if (node != previous) {candidates.push_back(node);}}if (!candidates.empty()) {uniform_int_distribution<int> dist(0, candidates.size() - 1);return candidates[dist(mt)];}uniform_int_distribution<int> dist(0, current->next.size() - 1);return current->next[dist(mt)];
}// 判断两个节点是否为同一组合节点
bool isSameGroup(mynode* a, mynode* b) {if (a == b) return true;if ((a == &r10 || a == &r11) && (b == &r10 || b == &r11)) return true;if ((a == &r6 || a == &r7) && (b == &r6 || b == &r7)) return true;if ((a == &r8 || a == &r9) && (b == &r8 || b == &r9)) return true;return false;
}// 检测是否点击了节点
mynode* isNodeClicked(int mouseX, int mouseY, mynode* nodes[], int count) {for (int i = 0; i < count; i++) {int dx = mouseX - nodes[i]->x;int dy = mouseY - nodes[i]->y;if (dx * dx + dy * dy <= NODE_RADIUS * NODE_RADIUS) {// 处理合并节点if (nodes[i] == &r10 || nodes[i] == &r11) return &r10;if (nodes[i] == &r6 || nodes[i] == &r7) return &r6;if (nodes[i] == &r8 || nodes[i] == &r9) return &r8;return nodes[i];}}return nullptr;
}// 绘制监控画面
void drawCameraView(mynode* nodes[], int count, mynode* b, mynode* c, mynode* f, mynode* camera) {// 绘制连接线setlinecolor(WHITE);for (int i = 0; i < count; i++) {for (auto next_node : nodes[i]->next) {line(nodes[i]->x, nodes[i]->y, next_node->x, next_node->y);}}// 绘制节点for (int i = 0; i < count; i++) {// 高亮当前camera节点if (isSameGroup(nodes[i], camera)) {setfillcolor(GREEN);}else {setfillcolor(LIGHTGRAY);}fillcircle(nodes[i]->x, nodes[i]->y, NODE_RADIUS);outtextxy(nodes[i]->x - 10, nodes[i]->y - 10, nodes[i]->name);}// 绘制角色(Bonnie、Chica、Freddy)auto drawCharacter = [](mynode* charNode, mynode* camNode, COLORREF color, const TCHAR* name, int offset) {if (isSameGroup(charNode, camNode) || Hack) {setfillcolor(color);fillcircle(charNode->x, charNode->y + offset, CHAR_RADIUS);outtextxy(charNode->x - 25, charNode->y + offset - 15, name);}};// 计算偏移量int b_offset = (b == &r10 || b == &r6 || b == &r8) ? -30 : 30;int c_offset = (c == &r10 || c == &r6 || c == &r8) ? -30 : 30;int f_offset = (f == &r10 || f == &r6 || f == &r8) ? -30 : 30;drawCharacter(b, camera, RED, _T("Bonnie"), b_offset);drawCharacter(c, camera, YELLOW, _T("Chica"), c_offset);drawCharacter(f, camera, BLUE, _T("Freddy"), f_offset);// 显示当前状态TCHAR status[256];_stprintf_s(status, _T("当前监控: %s | Bonnie: %s | Chica: %s | Freddy: %s"),camera->name, b->name, c->name, f->name);outtextxy(10, 10, status);// 显示操作提示outtextxy(10, 30, _T("点击节点切换监控视角"));
}// 绘制控制面板
void drawControlPanel() {setfillcolor(PANEL_COLOR);setlinecolor(PANEL_BORDER_COLOR);fillrectangle(0, WINDOW_HEIGHT - PANEL_HEIGHT, WINDOW_WIDTH, WINDOW_HEIGHT);rectangle(0, WINDOW_HEIGHT - PANEL_HEIGHT, WINDOW_WIDTH, WINDOW_HEIGHT);// 绘制红色按钮(左侧)setfillcolor(redButtonActive ? RGB(150, 50, 50) : RED_BUTTON_COLOR);fillrectangle(10, WINDOW_HEIGHT - PANEL_HEIGHT + 10, 100, WINDOW_HEIGHT - 10);outtextxy(25, WINDOW_HEIGHT - PANEL_HEIGHT + 25, _T("MASK"));// 在控制面板中间显示camerab状态TCHAR camStatus[32];_stprintf_s(camStatus, _T("CAMERA B: %s"), camerab ? _T("ON") : _T("OFF"));settextcolor(WHITE);outtextxy(350, WINDOW_HEIGHT - PANEL_HEIGHT + 20, camStatus);// 绘制房间控制按钮(右侧)setfillcolor(ROOM_BUTTON_COLOR);fillrectangle(650, WINDOW_HEIGHT - PANEL_HEIGHT + 10, 700, WINDOW_HEIGHT - 10);outtextxy(660, WINDOW_HEIGHT - PANEL_HEIGHT + 25, _T("-"));fillrectangle(710, WINDOW_HEIGHT - PANEL_HEIGHT + 10, 760, WINDOW_HEIGHT - 10);outtextxy(720, WINDOW_HEIGHT - PANEL_HEIGHT + 25, _T("+"));// 在drawControlPanel()函数中添加:setfillcolor(Hack ? RGB(0, 255, 0) : RGB(255, 0, 0));fillrectangle(150, WINDOW_HEIGHT - PANEL_HEIGHT + 10, 200, WINDOW_HEIGHT - 10);outtextxy(160, WINDOW_HEIGHT - PANEL_HEIGHT + 25, _T("HACK"));// 显示当前房间IDTCHAR roomText[32];_stprintf_s(roomText, _T("Room: %d"), roomid);outtextxy(600, WINDOW_HEIGHT - PANEL_HEIGHT + 25, roomText);
}// 检测点击位置(节点或控制面板)
bool isControlPanelClicked(int mouseX, int mouseY) {return mouseY >= (WINDOW_HEIGHT - PANEL_HEIGHT);
}// 检测是否点击了红色按钮
bool isRedButtonClicked(int mouseX, int mouseY) {return (mouseX >= 10 && mouseX <= 100) &&(mouseY >= (WINDOW_HEIGHT - PANEL_HEIGHT + 10) && mouseY <= (WINDOW_HEIGHT - 10));
}// 检测是否点击了房间减按钮
bool isRoomMinusClicked(int mouseX, int mouseY) {return (mouseX >= 650 && mouseX <= 700) &&(mouseY >= (WINDOW_HEIGHT - PANEL_HEIGHT + 10) && mouseY <= (WINDOW_HEIGHT - 10));
}// 检测是否点击了房间加按钮
bool isRoomPlusClicked(int mouseX, int mouseY) {return (mouseX >= 710 && mouseX <= 760) &&(mouseY >= (WINDOW_HEIGHT - PANEL_HEIGHT + 10) && mouseY <= (WINDOW_HEIGHT - 10));
}// 绘制灯光按钮
void drawLightButton() {setfillcolor(light ? RGB(255, 255, 150) : LIGHT_BUTTON_COLOR);fillrectangle(10, 10, 100, 50);outtextxy(25, 25, _T("LIGHT"));
}// 检测是否点击了灯光按钮
bool isLightButtonClicked(int mouseX, int mouseY) {return (mouseX >= 10 && mouseX <= 100) &&(mouseY >= 10 && mouseY <= 50);
}// 绘制棕色遮挡物
void drawBrownOverlay() {setfillcolor(RGB(101, 67, 33)); // 棕色fillrectangle(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT / 2);
}// 新增函数
bool isHackButtonClicked(int mouseX, int mouseY) {return (mouseX >= 150 && mouseX <= 200) &&(mouseY >= (WINDOW_HEIGHT - PANEL_HEIGHT + 10) && mouseY <= (WINDOW_HEIGHT - 10));
}int main() {// 初始化 EasyX 窗口initgraph(WINDOW_WIDTH, WINDOW_HEIGHT);setbkcolor(BLACK);cleardevice();BeginBatchDraw();// 设置节点名称_tcscpy_s(r1.name, _T("R1"));_tcscpy_s(r2.name, _T("R2"));_tcscpy_s(r3.name, _T("R3"));_tcscpy_s(r4.name, _T("R4"));_tcscpy_s(r5.name, _T("R5"));_tcscpy_s(r6.name, _T("R6/7"));_tcscpy_s(r7.name, _T("R6/7"));_tcscpy_s(r8.name, _T("R8/9"));_tcscpy_s(r9.name, _T("R8/9"));_tcscpy_s(r10.name, _T("R10/11"));_tcscpy_s(r11.name, _T("R10/11"));_tcscpy_s(r12.name, _T("R12"));_tcscpy_s(att1.name, _T("ATT1"));_tcscpy_s(att2.name, _T("ATT2"));_tcscpy_s(att3.name, _T("ATT3"));_tcscpy_s(che1.name, _T("CHE1"));_tcscpy_s(che2.name, _T("CHE2"));_tcscpy_s(che3.name, _T("CHE3"));// 设置节点坐标(优化布局)r1.x = 400; r1.y = 80;r2.x = 400; r2.y = 150;r3.x = 300; r3.y = 200;r4.x = 350; r4.y = 200;r5.x = 450; r5.y = 200;r6.x = 400; r6.y = 250;r7.x = 400; r7.y = 250;r8.x = 450; r8.y = 300;r9.x = 450; r9.y = 300;r10.x = 300; r10.y = 350;r11.x = 300; r11.y = 350;r12.x = 400; r12.y = 350;att1.x = 300; att1.y = 450;att2.x = 500; att2.y = 450;att3.x = 200; att3.y = 450;che1.x = 300; che1.y = 500;che2.x = 500; che2.y = 500;che3.x = 200; che3.y = 500;// 设置节点连接关系r1.next = { &r2 };r2.next = { &r3, &r4, &r5, &r6, &r8, &r10 };r3.next = { &r2 };r4.next = { &r2 };r5.next = { &r2 };r6.next = { &r2, &r12, &r7 };r7.next = { &r6, &att1 };r8.next = { &r2, &r9 };r9.next = { &r8, &att2 };r10.next = { &r2, &r11 };r11.next = { &r10, &att3 };r12.next = { &r6 };att1.next = { &che1 };att2.next = { &che2 };att3.next = { &che3 };che1.next = { &r6 };che2.next = { &r8 };che3.next = { &r10 };att1.data = -1; att2.data = -2;att3.data = -3;che1.data = 1; che2.data = 2;che3.data = 3;// 初始化角色位置mynode* b = &r1, * c = &r1, * f = &r1;mynode* b_prev = nullptr, * c_prev = nullptr, * f_prev = nullptr;mynode* camera = &r1;// 随机数生成器std::random_device rd;std::mt19937 gen(rd());// 初始化移动计时器int bx = generateSpecialRandom(gen);int cx = generateSpecialRandom(gen);int fx = generateSpecialRandom(gen);// 所有节点数组mynode* nodes[] = { &r1, &r2, &r3, &r4, &r5, &r6, &r7, &r8, &r9, &r10, &r11, &r12, &att1, &att2, &att3, &che1, &che2, &che3 };int node_count = sizeof(nodes) / sizeof(nodes[0]);while (true) {cleardevice();// 处理鼠标事件if (MouseHit()) {MOUSEMSG msg = GetMouseMsg();if (msg.uMsg == WM_LBUTTONDOWN) {// 检测灯光按钮点击if (isLightButtonClicked(msg.x, msg.y)) {light = !light;}else if (isControlPanelClicked(msg.x, msg.y)) {if (isRedButtonClicked(msg.x, msg.y)) {if (!camerab) redButtonActive = !redButtonActive;}else if (isRoomMinusClicked(msg.x, msg.y)) {if (roomid > 0) {roomid--;}}else if (isRoomPlusClicked(msg.x, msg.y)) {if (roomid < 2) {roomid++;}}else if (isHackButtonClicked(msg.x, msg.y)) {Hack = !Hack;}else {if (!redButtonActive) camerab = !camerab;}}else if (camerab && !redButtonActive) {mynode* clickedNode = isNodeClicked(msg.x, msg.y, nodes, node_count);if (clickedNode) {if (clickedNode->data >= 0) camera = clickedNode;}}}}// 绘制灯光按钮drawLightButton();// 绘制棕色遮挡物(如果红色按钮被激活)if (redButtonActive) {drawBrownOverlay();}if (camerab == false) {// 只有当灯光打开时才显示门口的角色if (light) {if (roomid == 0) {if (b->data == -1 || (b->data == 1 && redButtonActive)) {setfillcolor(BLUE);fillcircle(400, 350, 100);}if (c->data == -1) {setfillcolor(YELLOW);fillcircle(400, 350, 100);}if (f->data == -1) {//setfillcolor(BROWN);//fillcircle(400, 350, 100);}}else if (roomid == 1) {if (b->data == -2 || (b->data == 2 && redButtonActive)) {setfillcolor(BLUE);//bonnie为戴面具防御 所以要加上后面的条件fillcircle(400, 350, 100);}if (c->data == -2) {setfillcolor(YELLOW);fillcircle(400, 350, 100);}if (f->data == -2) {//setfillcolor(BROWN);//fillcircle(400, 350, 100);}}else if (roomid == 2) {if (b->data == -3 || (b->data == 3 && redButtonActive)) {setfillcolor(BLUE);fillcircle(400, 350, 100);}if (c->data == -3) {setfillcolor(YELLOW);fillcircle(400, 350, 100);}if (f->data == -3) {//setfillcolor(BROWN);//fillcircle(400, 350, 100);}}}// 无论灯光是否打开,都显示房间内的角色else {// 这里可以添加其他显示逻辑}}// 角色移动逻辑if (bx == 0) {bx = generateSpecialRandom(gen);mynode* new_b = get_random_move_with_memory(b, b_prev, gen);if (new_b) b_prev = b, b = new_b;}else bx--;if (cx == 0) {cx = generateSpecialRandom(gen);mynode* new_c = get_random_move_with_memory(c, c_prev, gen);if (new_c) c_prev = c, c = new_c;}else cx--;if (fx == 0) {fx = generateSpecialRandom(gen);mynode* new_f = get_random_move_with_memory(f, f_prev, gen);if (new_f) f_prev = f, f = new_f;}else fx--;// 绘制当前状态if (camerab) {drawCameraView(nodes, node_count, b, c, f, camera);}drawControlPanel();FlushBatchDraw();std::this_thread::sleep_for(std::chrono::milliseconds(1));// 检测退出键if (_kbhit() && _getch() == 27) break;}// 关闭图形窗口EndBatchDraw();closegraph();return 0;
}
部分UI使用了DeepSeek AI
仅为测试使用