Icebound

icebound-area

cloudfight云打架源代码分析

前几天写了一个sb一般的小游戏,然后没人玩,然后很难过。但是坑得填。

源代码已经上传至GitHub

下面开始正经

第一部分 总述

cloudfight是我脑子里抽风了想出来的一个想法,基于C++ rand()做的一个小游戏。

【说是云打架。。其实没有云】

cloudfight【以下简称cf】完全由windows sdk开发 没有使用任何其他的库,开发环境为VS 社区版。

全部文件:

gui.cpp管理cf的ui界面,work.cpp管理计算部分 stdafx.h写了包含所需的头文件。

主要运行流程:

gui.cpp启动WinMain 由WinMain注册并创建主窗体。

Winproc处理消息,得到输入后由work.cpp执行操作

work.cpp先交由 init() initconf()创建随机种子并且读取配置文件。再由相关函数获得两人战斗力、hp等

最后由fight()获得战斗过程,并传给Winproc。

Winproc获得战斗过程后,创建新线程Paint,并打印战斗过程。

打印结束后回收相关内存,等待下一次输入。

【所以说麻雀虽小五脏俱全】

第二部分 细节分析

1.UI方面

全部UI基于win32 SDK 所以很丑

窗口创建啊,改背景颜色就不说了

控件部分:

LOGFONT fontRect;
memset(&fontRect,0,sizeof fontRect);
fontRect.lfHeight=25;
fontRect.lfWeight=400;
lstrcpy(fontRect.lfFaceName,L"黑体");
hFont=CreateFontIndirect(&fontRect);
hwndTemp=CreateWindow(L"STATIC",L"输入姓名A",WS_CHILD|WS_VISIBLE|SS_SIMPLE,40,80,200,200,hwnd,NULL,clf,NULL);
SendMessage(hwndTemp,WM_SETFONT,(WPARAM)hFont,(LPARAM)true);
hwndTemp=CreateWindow(L"STATIC",L"输入姓名B",WS_CHILD|WS_VISIBLE|SS_SIMPLE,40,160,200,200,hwnd,NULL,clf,NULL);
SendMessage(hwndTemp,WM_SETFONT,(WPARAM)hFont,(LPARAM)true);
hwndEditA=CreateWindow(L"EDIT",L"",WS_CHILD|WS_VISIBLE|WS_BORDER,160,78,200,30,hwnd,NULL,clf,NULL);
SendMessage(hwndEditA,WM_SETFONT,(WPARAM)hFont,(LPARAM)true);
hwndEditB=CreateWindow(L"EDIT",L"",WS_CHILD|WS_VISIBLE|WS_BORDER,160,158,200,30,hwnd,NULL,clf,NULL);
SendMessage(hwndEditB,WM_SETFONT,(WPARAM)hFont,(LPARAM)true);
hwndBtn=CreateWindow(L"BUTTON",L" FIGHT ",WS_CHILD|WS_VISIBLE,160,250,120,120,hwnd,NULL,clf,NULL);
SendMessage(hwndBtn,WM_SETFONT,(WPARAM)hFont,(LPARAM)true);
hwndOut=CreateWindow(L"EDIT",NULL,WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_BORDER|ES_LEFT|ES_MULTILINE|ES_NOHIDESEL|ES_AUTOVSCROLL,440,20,420,400,hwnd,NULL,clf,NULL);
fontRect.lfHeight=18;hFont=CreateFontIndirect(&fontRect);
SendMessage(hwndOut,WM_SETFONT,(WPARAM)hFont,(LPARAM)true);

 

文字均用静态控件呈现,这样效率高

EDIT用WS_VSCROLL|WS_BORDER|ES_LEFT|ES_MULTILINE|ES_NOHIDESEL|ES_AUTOVSCROLL实现自动换行

比较值得说的一点就是字体的控制

想了半天用了这种方法,用CreateFontIndirect直接创建字体,然后再通过SendMessage改变字体

这样似乎是一种很好的方法?也许有更好的。

文字信息的输出:

为提高效率,在EDIT里采用追加方式输出文本

具体实现就是,跳转到最后一行,再输出文本

void inline makeout(HWND hwnd,char ss[])
{
	int len=strlen(ss),lst=0;
	for(int i=0;i<len;i++)
	{
		if(ss[i]=='#')
		{
			Sleep(1000);
			char output[500];memset(output,0,sizeof output);
			WCHAR Buf[500];memset(Buf,0,sizeof Buf);
			for(int j=lst,k=0;j<i;j++,k++)output[k]=ss[j];
			strcat_s(output,"\r\n");
			MultiByteToWideChar(CP_ACP,0,output,strlen(output)+1,Buf,  
				sizeof(Buf)/sizeof(Buf[0])); 
			SendMessage(hwnd,EM_SETSEL,-1,-1);
			SendMessage(hwnd,EM_REPLACESEL,0,(LPARAM)Buf);
			SendMessage(hwnd,WM_VSCROLL,SB_BOTTOM,0);
			lst=i+1;
		}
	}
}

还有一件事,就是宽字符与窄字符互相转化,这里不多赘述

我也云里雾里,贴一下代码过几天学吧。

//宽字符转窄字符
int sz=WideCharToMultiByte(CP_ACP,0,Buf1,-1,NULL,0,NULL,NULL);
WideCharToMultiByte(CP_ACP,0,Buf1,-1,BufA,sz,NULL,NULL);
//窄字符转宽字符
MultiByteToWideChar(CP_ACP,0,output,strlen(output)+1,Buf,sizeof(Buf)/sizeof(Buf[0]));

 

“关于”对话框的实现:

用的VS的对话框编辑器,然后自己写一个控制函数就行了

我叫他 AbtProc 23333

有一点不理解 为什么必须return (INT_PTR)FALSE;

要不然会卡死。。以后再研究

特别说一下网页的打开

用默认浏览器打开直接open url就行,但是有些情况下会失效?

于是判断一下是否打开成功,如果不行,就用IE打开

void OpenUrl(LPCWSTR url)
{
	HINSTANCE result=ShellExecute(NULL, L"open", url, NULL, NULL, SW_SHOW);
	if((int)result<=HINSTANCE_ERROR)
		result=ShellExecute(NULL, NULL, L"iexplore.exe", url, NULL, SW_SHOW);
}

菜单栏实现:

用的VS的菜单编辑器 这里不提了

2.游戏方面

先计算随机数。。再得到power值。。再获取打架过程

代码太丑 不好意思说

可以透露的是,用的一个随机数种子是我的生日。

 

似乎没啥可说的。。悲伤

  1. TZG说道:

    应该叫(雾)打架