• Zero

    openssl genrsa -out key.pem 2048
    openssl rsa -in key.pem -pubout -out key.pub
    openssl req -x509 -new -days 365 -key key.pem -out cert.crt
    

    posted in GuaiK实验室 read more
  • Zero

    macOS Catalina将不再使用bashrc改用zshrc,所以需要修改下命令行前面提示部分,让它变得精简一些:

    sudo vi /etc/zshrc
    # 替换以下指令
    #PS1="%n@%m %1~ %# "
    PS1="%m@%1~ # "
    

    安装命令行工具:

    xcode-select --install
    

    posted in GuaiK机房 read more
  • Zero

    你去了解下GLAD的使用方法:
    https://glad.dav1d.de/


    然后你只需要用导入以下头文件就可以了

    #include <glad/glad.h> 
    

    关于类怎么设计,你最好去看看游戏的设计模式,通常我会把纹理对象作为独立的类型,然后将数据和渲染器分开设计,比如游戏精灵Sprite类,和对应的渲染器SpriteRenderer类。

    posted in GuaiK故障处理 read more
  • Zero

    导入头文件:

    #include <QDateTime>
    

    初始化代码:

    /* 将startTime设置为全局变量或放在类中作为属性 */
    /* 确保渲染代码能够访问到 */
    /* startTime记录程序启动的时刻 */
    qint64 startTime;    
    startTime = QDateTime::currentDateTime().toMSecsSinceEpoch();
    

    渲染代码

    // 计算出程序已经运行的时间(秒)
    qint64 timestamp = QDateTime::currentDateTime().toMSecsSinceEpoch();
    float t = (timestamp - startTime) / 1000.0;
    qDebug() << t;
    
    // 旋转 
    glm::mat4 model = glm::mat4(1.0f);
    model = glm::rotate(model, glm::radians(cos(t)*60.0f), glm::vec3(1.0f, 1.0f, 1.0f));
    

    posted in GuaiK故障处理 read more
  • Zero

    打开文件

    Box2d/Dynamics/Contacts/b2Contact.cpp

    修改文件

    找到void b2Contact::Update(b2ContactListener* listener)方法

    注释以下代码:

    m_flags |= e_enabledFlag;
    

    posted in GuaiK实验室 read more
  • Zero

    在使用OpenGL开发的时候遇到了这样一个问题,当程序通过Mac电脑显示的时候,只显示了左下角的1/4画面,但是移动到扩展屏的时候却恢复正常。这是因为屏幕DPI的问题,实际测试下来Mac屏幕的DPI是普通屏幕的2倍,这意味着创建一个800 * 600的窗口在Mac电脑中实际的DPI是 1600 * 1200。

    那么如何获取到实际的DPI呢?

    GLFWwindow *window;
    int width, height;
    window = glfwCreateWindow(800, 600, "GuaiK Window", nullptr, nullptr);
    glfwGetFramebufferSize(window, &width, &height);
    

    以上代码会把屏幕实际的DPI写入到width和height中。


    那么如何让画面显示正常呢?

    使用glViewport告诉OpenGL实际的DPI,可以理解成设置一个画布的大小以供绘画吧。所以需要使用实际的DPI。

    glViewport(0, 0, width, height);
    

    通常会把glfwGetFramebufferSize和glViewport放在渲染循环中,这样可以确保在窗口切换的时候可以实时调节画布大小,就像这样:

    while(!glfwWindowShouldClose(window){
        ......
        // 设置画布大小
        glfwGetFramebufferSize(window, &width, &height);
        glViewport(0, 0, width, height);
        // 开始渲染
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        ........
        glfwSwapBuffers(window);
    }
    

    投影计算

    glm::ortho(0.0f, static_cast<GLfloat>(800), 
            0.0f, static_cast<GLfloat>(600), -1.0f, 1.0f);
    

    这里将左下角设置为原点(0, 0),并且设置窗口大小为(800, 600),这里直接使用了glfwCreateWindow创建窗口时的大小,我们在开发的时候也以这个为标准,可绘制的区域是从(0, 0)到(800, 600)的范围,那么在高DPI的环境下会怎么办呢?因为我们已经动态获取了屏幕DPI并设置了Viewport,所以OpenGL会自动将(800, 600)通过投影映射到实际DPI的大小而不需要我们做多余的处理。

    posted in GuaiK实验室 read more
  • Zero

    Mac电脑TypeC接口失效解决方案


    重置 Mac 上的系统管理控制器 (SMC):

    • 给电脑插上充电线
    • 将电脑关机
    • 同时按住Shift + Control + Option + 电源键
    • 保持以上动作10秒
    • 开机

    如果是硬件故障将无法修复

    posted in GuaiK机房 read more
  • Zero

    Injection-DLL


    DLL注入工具是信息安全相关领域的常用工具,在Windows系统下将动态库注入到一个正在运行的进程中,这样DLL就属于该进程所以可以调用该进程的函数以及获取进程中的数据。大多数游戏内存外挂就会使用DLL注入技术去读取游戏数据和控制游戏人物的行为。这工具是早期学习WIN32汇编时写的。


    Download

    链接:https://pan.baidu.com/s/1LpRYvGgnf7R4sk-I93CD9g

    密码:n3k6


    相关代码⤵⤵⤵

    Into.asm

    ;*************************************************
    ; https://bbs.guaik.org
    ;*************************************************
    			.386
    			.model flat,stdcall
    			option casemap:none
    ;*************************************************
    include			windows.inc
    include			user32.inc
    includelib		user32.lib
    include			kernel32.inc
    includelib		kernel32.lib
    include			advapi32.inc
    includelib		advapi32.lib
    include			comdlg32.inc
    includelib		comdlg32.lib
    include			shell32.inc
    includelib		shell32.lib
    include			into.inc
    
    ;*************************************************
    .data?
    hInstance	dd	?
    hWinMain	dd	?
    lpLoadLibrary	dd	?
    lpFreeLibrary	dd	?
    hProcess	dd	?
    lpDllName	dd	?
    szDllName	db MAX_PATH dup (?)
    .const
    szText		db	'[GuaikBBS]:https://bbs.guaik.org',0
    szCaption	db	'[GhostHand]Message',0
    szSetDebug	db	'SeDebugPrivilege',0
    szATPErr	db	'[AdjustTokenPrivileges]:Error!!',0
    szLPVErr	db	'[LookupPrivilegeValue]:Error!',0
    szOPTErr	db	'[OpenProcessToken]:Error!',0
    szFilter	db	'Dll Files(*.dll)',0,'*.dll',0,0
    szOpenCaption	db	'Select a dll',0
    szOD		db	'[_OpenDll]:请选择Dll文件!',0
    szDllKernel	db	'Kernel32.dll',0
    szLoadLibrary	db	'LoadLibraryA',0
    szFreeLibrary	db	'FreeLibraryAndExitThread',0
    szCRTErr	db	'[CreateRemoteThread]:Error!',0
    szVAEErr	db	'[VirtualAllocEx]:Error!',0
    szOPErr		db	'[OpenProcess]:Error!',0
    szCRTOk		db	'[CreateRemoteThread]:Success!',0
    szEmail		db	'mailto:luting.gu@gmail.com',0
    szNtDll		db	'ntdll.dll',0
    szNtQueryInformationThread	db	'NtQueryInformationThread',0
    .code
    _SetWinPos	proc	_hWnd
    		
    		LOCAL x_screen:dword
    		LOCAL y_screen:dword
    		LOCAL rtWinMain:RECT
    		
    		invoke GetSystemMetrics,SM_CXSCREEN
    		mov edx,0
    		mov cx,2
    		div cx      ;商在ax中,余数在dx中
    		mov x_screen,eax
    		invoke GetSystemMetrics,SM_CYSCREEN
    		mov edx,0
    		mov cx,2
    		div cx
    		mov y_screen,eax
    		invoke GetWindowRect,_hWnd,addr rtWinMain
    		mov edx,0
    		mov eax,rtWinMain.right
    		mov cx,2
    		div cx
    		mov edx,x_screen
    		sub edx,eax
    		mov x_screen,edx
    		mov edx,0
    		mov eax,rtWinMain.bottom
    		mov cx,2
    		div cx
    		mov edx,y_screen
    		sub edx,eax
    		mov y_screen,edx
    		invoke SetWindowPos,_hWnd,NULL,x_screen,y_screen,NULL,NULL,SWP_NOSIZE
    		
    		ret
    
    _SetWinPos endp
    
    _EnableDebug	proc
    		
    		LOCAL hToken:dword
    		LOCAL tkp:TOKEN_PRIVILEGES
    		LOCAL @luid:LUID
    		invoke GetCurrentProcess
    		lea ebx,hToken
    		invoke OpenProcessToken,eax,TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,ebx
    		.if	eax
    			invoke LookupPrivilegeValue,NULL,offset szSetDebug,addr tkp.Privileges.Luid
    			.if	eax
    				mov tkp.PrivilegeCount,1
    				mov tkp.Privileges.Attributes,SE_PRIVILEGE_ENABLED
    				invoke AdjustTokenPrivileges,hToken, FALSE,addr tkp,sizeof tkp,NULL,NULL
    				.if !eax
    					invoke CloseHandle,hToken
    					invoke MessageBox,hWinMain,offset szATPErr,offset szCaption,MB_OK
    				.endif
    			.else
    				invoke CloseHandle,hToken
    				invoke MessageBox,hWinMain,offset szLPVErr,offset szCaption,MB_OK
    			.endif
    		.else
    			invoke MessageBox,hWinMain,offset szOPTErr,offset szCaption,MB_OK
    		.endif
    		ret
    
    _EnableDebug endp
    
    _OpenDll	proc
    	
    		LOCAL @stOF:OPENFILENAME
    		
    		invoke RtlZeroMemory,addr @stOF,sizeof @stOF
    		mov @stOF.lStructSize,sizeof @stOF
    		push hWinMain
    		pop  @stOF.hwndOwner
    		mov @stOF.lpstrFilter,offset szFilter
    		mov @stOF.lpstrFile,offset szDllName
    		mov @stOF.nMaxFile,MAX_PATH
    		mov @stOF.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST
    		mov @stOF.lpstrTitle,offset szOpenCaption
    		invoke GetOpenFileName,addr @stOF
    		.if	eax
    			invoke SetDlgItemText,hWinMain,IDC_DLLPATH,offset szDllName
    		.endif
    		ret
    
    _OpenDll endp
    
    _GetProcessList proc	_hWnd
    		LOCAL @stProcess:PROCESSENTRY32
    		LOCAL @hSnapShot
    		
    		invoke RtlZeroMemory,addr @stProcess,sizeof @stProcess
    		invoke SendDlgItemMessage,_hWnd,IDC_PROCESSLIST,LB_RESETCONTENT,0,0
    		mov @stProcess.dwSize,sizeof @stProcess
    		invoke CreateToolhelp32Snapshot,TH32CS_SNAPPROCESS,0
    		mov @hSnapShot,eax
    		invoke Process32First,@hSnapShot,addr @stProcess
    		.while eax
    			invoke SendDlgItemMessage,_hWnd,IDC_PROCESSLIST,LB_ADDSTRING,0,addr @stProcess.szExeFile
    			invoke SendDlgItemMessage,_hWnd,IDC_PROCESSLIST,LB_SETITEMDATA,eax,@stProcess.th32ProcessID
    			invoke Process32Next,@hSnapShot,addr @stProcess
    		.endw
    		invoke CloseHandle,@hSnapShot
    		ret
    
    _GetProcessList endp
    
    _GetModelList	proc	_dwProcessId,_hWnd,_hModule
    	
    		LOCAL @stModule:MODULEENTRY32
    		LOCAL @hSnapShot
    		LOCAL @ModuleSize
    		
    		mov @ModuleSize,0
    		invoke RtlZeroMemory,addr @stModule,sizeof @stModule
    		invoke SendDlgItemMessage,_hWnd,IDC_MODELLIST,LB_RESETCONTENT,0,0
    		mov @stModule.dwSize,sizeof @stModule
    		invoke CreateToolhelp32Snapshot,TH32CS_SNAPMODULE,_dwProcessId	;枚举进程模块
    		mov @hSnapShot,eax
    		invoke Module32First,@hSnapShot,addr @stModule
    		.while	eax
    			mov eax,_hModule
    			.if	eax == @stModule.modBaseAddr
    				push @stModule.modBaseSize
    				pop  @ModuleSize
    			.endif
    			invoke SendDlgItemMessage,_hWnd,IDC_MODELLIST,LB_ADDSTRING,0,addr @stModule.szModule
    			invoke SendDlgItemMessage,_hWnd,IDC_MODELLIST,LB_SETITEMDATA,eax,@stModule.modBaseAddr
    			invoke Module32Next,@hSnapShot,addr @stModule
    		.endw
    		invoke CloseHandle,@hSnapShot
    		mov eax,@ModuleSize
    		ret
    
    _GetModelList endp
    
    _KillThread	proc	_ProcessId,_lpModelBase,dwModelSize
    	
    		LOCAL @stThread:THREADENTRY32
    		LOCAL @hSnapShot
    		LOCAL @hThread
    		LOCAL @NtQueryInformationThread
    		LOCAL @ThreadBase
    		invoke GetModuleHandle,offset szNtDll
    		invoke GetProcAddress,eax,offset szNtQueryInformationThread
    		mov @NtQueryInformationThread,eax
    		
    		invoke RtlZeroMemory,addr @stThread,sizeof @stThread
    		mov @stThread.dwSize,sizeof @stThread
    		invoke CreateToolhelp32Snapshot,TH32CS_SNAPTHREAD,_ProcessId
    		mov @hSnapShot,eax
    		invoke Thread32First,@hSnapShot,addr @stThread
    		.while	eax
    			invoke OpenThread,THREAD_ALL_ACCESS,FALSE,@stThread.th32ThreadID
    			mov @hThread,eax
    			
    			lea	edx,@ThreadBase
    			mov	ecx,@NtQueryInformationThread
    			push	NULL
    			push	4h
    			push	edx
    			push	9
    			push	@hThread
    			call	ecx
    			
    			mov eax,@ThreadBase
    			sub eax,_lpModelBase
    			.if	(eax < dwModelSize) || (eax == dwModelSize)
    				invoke TerminateThread,@hThread,0
    			.endif
    			invoke CloseHandle,@hThread
    			invoke Thread32Next,@hSnapShot,addr @stThread
    		.endw
    		invoke CloseHandle,@hSnapShot
    		ret
    
    _KillThread endp
    
    _Into		proc	dwProcessId,_hWnd
    
    		LOCAL	@hThread
    	
    		invoke GetModuleHandle,offset szDllKernel
    		invoke GetProcAddress,eax,offset szLoadLibrary
    		mov	lpLoadLibrary,eax
    		invoke SendDlgItemMessage,_hWnd,IDC_PROCESSLIST,LB_GETCURSEL,0,0
    		invoke SendDlgItemMessage,_hWnd,IDC_PROCESSLIST,LB_GETITEMDATA,eax,0
    		invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,eax
    		.if eax
    			mov hProcess,eax
    			invoke lstrlen,offset szDllName
    			inc eax
    			invoke VirtualAllocEx,hProcess,NULL,eax,MEM_COMMIT,PAGE_READWRITE
    			.if eax
    				mov lpDllName,eax
    				;将DLL路径写入目标进程
    				invoke lstrlen,offset szDllName
    				inc eax
    				invoke WriteProcessMemory,hProcess,lpDllName,offset szDllName,eax,NULL
    				invoke CreateRemoteThread,hProcess,NULL,0,lpLoadLibrary,lpDllName,0,NULL
    				.if eax
    					mov @hThread,eax
    					invoke WaitForSingleObject,eax,INFINITE;等待线程执行
    					invoke CloseHandle,@hThread
    					invoke SetDlgItemText,hWinMain,IDC_MSG,offset szCRTOk
    				.else
    					invoke SetDlgItemText,hWinMain,IDC_MSG,offset szCRTErr
    				.endif
    				invoke lstrlen,offset szDllName
    				inc eax
    				invoke VirtualFreeEx,hProcess,lpDllName,eax,MEM_DECOMMIT
    			.else
    				invoke SetDlgItemText,hWinMain,IDC_MSG,offset szVAEErr
    			.endif
    			invoke CloseHandle,hProcess
    		.else
    			invoke SetDlgItemText,hWinMain,IDC_MSG,offset szOPErr
    		.endif
    		ret
    
    _Into endp
    
    
    
    _Out		proc	_dwProcessId,_Model
    		
    		LOCAL @dwHandle:dword
    		LOCAL @hThread:dword
    		
    		invoke GetModuleHandle,offset szDllKernel
    		invoke GetProcAddress,eax,offset szFreeLibrary
    		mov lpFreeLibrary,eax
    		invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,_dwProcessId	;打开Services.exe的进程
    		.if	eax
    			mov hProcess,eax
    			invoke _GetModelList,_dwProcessId,hWinMain,_Model
    			invoke _KillThread,_dwProcessId,_Model,eax
    			invoke CreateRemoteThread,hProcess,NULL,0,lpFreeLibrary,_Model,0,NULL
    			.if	eax
    				mov @hThread,eax
    				invoke WaitForSingleObject,eax,INFINITE
    				invoke CloseHandle,@hThread
    				invoke SetDlgItemText,hWinMain,IDC_MSG,offset szCRTOk
    			.else
    				invoke SetDlgItemText,hWinMain,IDC_MSG,offset szCRTErr
    			.endif
    			invoke CloseHandle,hProcess
    		.else
    			invoke SetDlgItemText,hWinMain,IDC_MSG,offset szOPErr
    		.endif
    		ret
    
    _Out endp
    
    _MainThread	proc	uses edi esi hWnd,uMsg,wParam,lParam
    	
    		LOCAL	@dwProcessId
    		mov eax,uMsg
    		.if	eax == WM_COMMAND
    			mov eax,wParam
    			.if	ax == IDC_DLL
    				call _OpenDll
    			.elseif ax ==IDC_PROCESSLIST
    				shr eax,16
    				.if	ax == LBN_SELCHANGE
    					invoke SendDlgItemMessage,hWnd,IDC_PROCESSLIST,LB_GETCURSEL,0,0
    					invoke SendDlgItemMessage,hWnd,IDC_PROCESSLIST,LB_GETITEMDATA,eax,0
    					invoke _GetModelList,eax,hWnd,0
    					invoke GetDlgItem,hWnd,IDC_OUT
    					invoke EnableWindow,eax,FALSE
    					invoke SendDlgItemMessage,hWnd,IDC_MODELLIST,LB_GETCOUNT,0,0
    					.if	eax == 0
    						invoke GetDlgItem,hWnd,IDC_IN
    						invoke EnableWindow,eax,FALSE
    					.else
    						invoke GetDlgItem,hWnd,IDC_IN
    						invoke EnableWindow,eax,TRUE
    					.endif
    				.endif
    			.elseif	ax ==IDC_MODELLIST
    				shr eax,16
    				.if	ax == LBN_SELCHANGE
    					invoke GetDlgItem,hWnd,IDC_OUT
    					invoke EnableWindow,eax,TRUE
    				.endif
    			.elseif ax == IDC_IN
    				invoke lstrlen,offset szDllName
    				.if	eax
    					invoke SendDlgItemMessage,hWnd,IDC_PROCESSLIST,LB_GETCURSEL,0,0
    					invoke SendDlgItemMessage,hWnd,IDC_PROCESSLIST,LB_GETITEMDATA,eax,0
    					mov @dwProcessId,eax
    					invoke _Into,eax,hWnd
    					invoke _GetModelList,@dwProcessId,hWnd,0
    				.else
    					invoke MessageBox,hWinMain,offset szOD,offset szCaption,MB_OK
    				.endif
    			.elseif ax == IDC_OUT
    				invoke SendDlgItemMessage,hWnd,IDC_PROCESSLIST,LB_GETCURSEL,0,0
    				invoke SendDlgItemMessage,hWnd,IDC_PROCESSLIST,LB_GETITEMDATA,eax,0
    				mov @dwProcessId,eax
    				invoke SendDlgItemMessage,hWnd,IDC_MODELLIST,LB_GETCURSEL,0,0
    				invoke SendDlgItemMessage,hWnd,IDC_MODELLIST,LB_GETITEMDATA,eax,0
    				invoke _Out,@dwProcessId,eax
    				invoke _GetModelList,@dwProcessId,hWnd,0
    			.elseif ax ==IDC_UPDATE
    				invoke _GetProcessList,hWnd
    				invoke SendDlgItemMessage,hWnd,IDC_MODELLIST,LB_RESETCONTENT,0,0
    				invoke GetDlgItem,hWnd,IDC_IN
    				invoke EnableWindow,eax,FALSE
    				invoke GetDlgItem,hWnd,IDC_OUT
    				invoke EnableWindow,eax,FALSE
    			.elseif ax == IDC_EMAIL
    				invoke ShellExecute,0,0,offset szEmail,0,0,SW_SHOW
    			.endif
    		.elseif	eax == WM_INITDIALOG
    			push hWnd
    			pop  hWinMain
    			invoke LoadIcon,hInstance,ICO_MAIN
    			invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax
    			invoke _SetWinPos,hWnd
    			call _EnableDebug
    			invoke _GetProcessList,hWnd
    			invoke GetDlgItem,hWnd,IDC_IN
    			invoke EnableWindow,eax,FALSE
    			invoke GetDlgItem,hWnd,IDC_OUT
    			invoke EnableWindow,eax,FALSE
    			invoke SetDlgItemText,hWinMain,IDC_MSG,offset szText
    		.elseif	eax == WM_CLOSE
    			invoke EndDialog,hWnd,-1
    		.else
    			mov eax,FALSE
    			ret
    		.endif
    		mov eax,TRUE
    		ret
    
    _MainThread endp
    
    start:
    	invoke GetModuleHandle,NULL
    	mov hInstance,eax
    	invoke DialogBoxParam,eax,IDD_MAIN,NULL,offset _MainThread,-1
    	invoke ExitProcess,0
    end start
    

    into.inc

    IDD_MAIN                equ 1000
    IDC_DLL                 equ 1004
    IDC_IN                  equ 1005
    IDC_OUT                 equ 1006
    IDC_UPDATE              equ 1007
    IDC_PROCESSLIST         equ 1001
    IDC_MODELLIST           equ 1002
    IDC_DLLPATH             equ 1003
    IDC_MSG                 equ 1008
    IDC_EMAIL               equ 1009
    ICO_MAIN                equ 1000
    

    into.rc

    #define ICO_MAIN 1000
    #define IDD_MAIN 1000
    #define IDC_DLL 1004
    #define IDC_IN 1005
    #define IDC_OUT 1006
    #define IDC_UPDATE 1007
    #define IDC_PROCESSLIST 1001
    #define IDC_MODELLIST 1002
    #define IDC_DLLPATH 1003
    #define IDC_MSG 1008
    #define IDC_EMAIL 1009
    
    #include "resource.h"
    
    ICO_MAIN ICON DISCARDABLE "main.ico"
    
    IDD_MAIN DIALOGEX 0,0,327,192
    CAPTION "GuaiK-DLL注入器"
    FONT 8,"MS Sans Serif",0,0,0
    STYLE WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU|DS_MODALFRAME
    BEGIN
      CONTROL "选择dll",IDC_DLL,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,9,156,54,15
      CONTROL "注入",IDC_IN,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,210,156,54,15
      CONTROL "卸载",IDC_OUT,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,267,156,54,15
      CONTROL "刷新",IDC_UPDATE,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,210,174,54,15
      CONTROL "",IDC_PROCESSLIST,"ListBox",WS_CHILDWINDOW|WS_VISIBLE|WS_BORDER|WS_VSCROLL|WS_TABSTOP|LBS_STANDARD|LBS_NOINTEGRALHEIGHT|LBS_HASSTRINGS,9,15,141,126,WS_EX_CLIENTEDGE
      CONTROL "",IDC_MODELLIST,"ListBox",WS_CHILDWINDOW|WS_VISIBLE|WS_BORDER|WS_VSCROLL|WS_TABSTOP|LBS_STANDARD|LBS_NOINTEGRALHEIGHT|LBS_HASSTRINGS,171,15,141,126,WS_EX_CLIENTEDGE
      CONTROL "",IDC_DLLPATH,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|ES_READONLY|ES_AUTOHSCROLL,69,156,138,15,WS_EX_CLIENTEDGE
      CONTROL "",IDC_MSG,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|ES_READONLY,69,174,138,15,WS_EX_CLIENTEDGE
      CONTROL "进程列表",-1,"Button",WS_CHILDWINDOW|WS_VISIBLE|BS_GROUPBOX,3,3,156,144
      CONTROL "模块列表",-1,"Button",WS_CHILDWINDOW|WS_VISIBLE|BS_GROUPBOX,165,3,156,144
      CONTROL "提示信息:",-1,"Static",WS_CHILDWINDOW|WS_VISIBLE,18,177,42,9
      CONTROL "联系作者",IDC_EMAIL,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,267,174,54,15
    END
    

    posted in GuaiK重灾区 read more
  • Zero

    Googletest


    下载地址

    https://github.com/google/googletest


    整合到CMake项目中:

    • 将googletext放入当前项目,目录改名为"gtest"
    • 在项目根目录的CMakeLists.txt中加入:
    # GTest
    set(gtest_dir ./gtest)
    include_directories(${gtest_dir}/include)
    add_subdirectory(${gtest_dir})
    
    • 列表进入gtext目录,在CMakelists.txt的头部添加(将生成的库放置在项目根目录的lib目录中):
    set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
    
    • 列表在链接时添加gtest库
    target_link_libraries(demp  gtest)
    

    函数介绍

    • 断言:分为ASSERT 和 EXPECT,ASSERT在失败后会退出程序,而EXPECT会继续向下执行,如果作为单元测试的话我选择使用ASSERT,这样发现问题后可以先把这个问题处理掉。

    bool断言

    ASSERT EXPECT 验证
    ASSERT_TRUE(x): EXPECT_TRUE(x); x是否为true
    ASSERT_FALSE(x): EXPECT_FALSE(x); x是否为fase

    数值断言

    ASSERT EXPECT 验证
    ASSERT_EQ(v1, v2); EXPECT_EQ(v1, v2); v1 == v2
    ASSERT_NE(v1, v2); EXPECT_NE(v1, v2); v1 != v2
    ASSERT_LT(v1, v2); EXPECT_LT(v1, v2); v1 < v2
    ASSERT_LE(v1, v2); EXPECT_LE(v1, v2); v1 <= v2
    ASSERT_GT(v1, v2); EXPECT_GT(v1, v2); v1 > v2
    ASSERT_GE(v1, v2); EXPECT_GE(v1, v2); v1 >= v2

    字符串比较

    ASSERT EXPECT 验证
    ASSERT_STREQ(s1, s2); EXPECT_STREQ(s1, s2); 两个字符串相等
    ASSERT_STRNE(s1, s2); EXPECT_STRNE(s1, s2); 两个字符串不等
    ASSERT_STRCASEEQ(s1, s2); EXPECT_STRCASEEQ(s1, s2); 两个字符串相等(忽略大小写)
    ASSERT_STRCASENE(s1, s2); EXPECT_STRCASENE(s1, s2); 两个字符串不等(忽略大小写)

    用例

    可以将单元测试都写入头文件中,然后全部导入到同一个cpp中。

    TestLogger.h

    #include "../gtest/include/gtest/gtest.h"
    #include "../logger.h"
    
    // 循环10次获取Logger实例
    // 通过条件:第一次获取实例会初始化静态变量,
    //         循环10次获取的实例与初始化时的变量地址相同
    TEST(Logger, TestGetInstance) {
        Logger &log = Logger::Instance();
        for (int i = 0; i< 10; i++){
            ASSERT_EQ((void*)&log, (void*)&Logger::Instance());
        }
    }
    
    // 测试日志初始化
    // 通过条件:第一个执行Init()无异常
    //         第二次执行Init()会调用assert()所以会触发死亡测试
    TEST(Logger, TestInit) {
        ASSERT_NO_THROW(Logger::Instance().Init());
        ASSERT_DEATH(Logger::Instance().Init(), "");
    }
    
    // 测试获取日志实例,通过条件:获取的日志实例不等于nullptr
    TEST(Logger, TestGetLogger) {
        ASSERT_NE(&Logger::Instance().GetLogger(), nullptr);
    }
    
    // 测试日志输出,通过条件:没有任何异常
    TEST(Logger, TestOutput) {
        ASSERT_NO_THROW(GKE2DLogDebug("1"));
    }
    

    Test.cpp

    #include "../gtest/include/gtest/gtest.h"
    #include "./TestLogger.h"
    
    int main(int argc, char *argv[]){
        // 进行单元测试
        ::testing::FLAGS_gtest_death_test_style="threadsafe";
        ::testing::InitGoogleTest(&argc, argv);
        return RUN_ALL_TESTS();
    }
    

    测试通过
    QQ20190901-112602@2x.png

    posted in GuaiK实验室 read more
  • Zero

    Bilibili

    (?:https?:\/\/)?(?:.+|m\.)?(?:bilibili|b23)\.(?:tv|com)(?:\/video)?\/av(\d+)(?:.*)?
    

    Youtube

    .*youtu(?:.*\/v\/|.*v\=|\.be\/)([A-Za-z0-9_\-]*).*
    

    posted in GuaiK实验室 read more
  • Zero

    使用方法:


    Bilibili

    [bilibili](https://www.bilibili.com/video/av28823167?from=search&seid=6046375130626082665)
    


    Youtube

    [youtube](https://www.youtube.com/watch?v=dKjCWfuvYxQ)
    

    posted in GuaiK新闻 read more
  • Zero

    rm -rf /tmp/mongodb-27017.sock
    

    posted in GuaiK机房 read more
  • Zero

    GKEngine

    logo

    引擎(GKE2D)

    使用单例模式封装设备(Device),处理器(Processor),处理各种回调函数以及信号。它用来初始化整个游戏引擎。

    /**
    * DEMO.CPP
    * 创建一个游戏窗口程序
    */
    #include "../gke2d.h"
    #include "../logger.h"
    
    int main(int argc, char *argv[]){
        GKE2D::Instance().InitEnv(800, 600, "GKE2D");
        GKE2D::Instance().SetLogLevel(GKE2D_LOG_LEVEL_DEBUG);
        GKE2DLogInfo("Hello, GEK2D!!!");
        GKE2D::Instance().Start();
        GKE2D::Instance().Release();
        return 0;
    }
    

    精灵(Sprite)

    游戏中所有可见的物件都是精灵(移动的背景,怪物,玩家等)。

    物理(Physics)

    可以将精灵添加入物理世界中,让精灵能够变得更加真实,拥有质量,摩擦系数,并且能够检测和处理碰撞。

    场景(Scene)

    每个场景都是独立的空间,它拥有自己的精灵和物理世界。

    渲染器(Renderer)

    负责游戏的所有渲染任务。

    窗口设备(WindowDevice)

    用来处理不同平台游戏窗口的显示,能够注册窗口事件(窗口大小变化,鼠标,键盘,手柄),负责渲染缓冲与窗口图形缓冲区的交换。

    资源管理器(ResourceManager)

    GKE2D的资源管理器有两个,一个提供给引擎内部使用(InternalResource),另一个提供给用户使用(UserResource),目前支持纹理和着色器的存储。

    // 获取资源管理器
    GKE2D::Resource()
    // 释放引擎使用的所有资源包括用户资源
    // 请在结束游戏循环时调用
    GKE2D::Release()
    

    日志

    GKE2D内部使用的日志工具,支持DEBUG, INFO, WARM, ERROR四种日志级别,日志在引擎初始化的时候被创建,所以在未初始化引擎的时候会触发assert(),日志支持格式化输入,以下是使用代码:

    GKE2DLogDebug("Hello, GKE2D!!!");
    GKE2DLogInfo("System Version {}.{}.{}", 1, 0, 1);
    GKE2DLogWarn("TCP disconnect, reconnect count: {}", counts);
    GKE2DLogError("Audio init error, code:{}", 100);
    

    更新概要

    日期 内容
    2019-09-12 添加InputDevice类,优化游戏主循环提升流畅度,物体碰撞位置计算
    2019-09-11 添加相机功能,Element可以设置是否使用相机
    2019-09-10 添加物理引擎碰撞检测回调函数
    2019-09-09 添加Scene类管理Element,支持场景切换和渲染
    2019-09-06 添加Font类,优化游戏循环(固定时间步长)
    2019-09-05 添加单元测试,添加Element基类(派生类Sprite/Text)
    2019-08-29 添加内部及外部资源管理器,添加Logger类
    2019-08-28 添加GKE2D类和WindowDevice类,清理Renderer类
    2019-08-27 添加Scene类
    2019-08-26 优化Sprite类,Physics类和Renderer类

    posted in GuaiK实验室 read more
  • Zero

    {
        "configurations": [
            {
                "name": "Mac",
                "includePath": [
                    "/usr/local/include/**",
                    "${workspaceFolder}/**"
                ],
                "browse": {
                    "limitSymbolsToIncludedHeaders": true,
                    "databaseFilename": "",
                    "path": [
                        "/usr/local/include/**",
                        "${workspaceFolder}/**"
                    ]
                },
                "defines": [],
                "macFrameworkPath": [
                    "/System/Library/Frameworks",
                    "/Library/Frameworks"
                ],
                "compilerPath": "/usr/local/bin/gcc-8",
                "cStandard": "c11",
                "cppStandard": "c++17",
                "intelliSenseMode": "clang-x64",
                "configurationProvider": "vector-of-bool.cmake-tools"
            }
        ],
        "version": 4
    }
    

    posted in GuaiK实验室 read more
  • Zero

    未命名.gif


    1、创建精灵

    Sprite *bg1;
    Sprite *bg2;
    bg1 = new Sprite(glm::vec2(0.0f, 0.0f), glm::vec2(R(600.0f),R(450.0F)),ResourceManager::GetTexture2D("bg"),glm::vec4(1.0f), glm::vec2(-200.0f,0.0f));
    bg2 = new Sprite(glm::vec2(R(-600.0f), 0.0f), glm::vec2(R(600.0f),R(450.0F)),ResourceManager::GetTexture2D("bg"),glm::vec4(1.0f), glm::vec2(-200.0f,0.0f));
    

    2、更新精灵位置数据(Update)

    if(bg1->Position.x < bg2->Position.x){
        bg1->Position = bg1->Position + m_deltaTime * bg1->Velocity;
        bg2->Position.x = bg1->Position.x + bg1->Size.x;
    }else{
        bg2->Position = bg2->Position + m_deltaTime * bg2->Velocity;
        bg1->Position.x = bg2->Position.x + bg2->Size.x;
    }
    if(bg1->Position.x + bg1->Size.x < 0.0f){
        bg1->Position.x = bg2->Position.x + bg2->Size.x;
    }
    if(bg2->Position.x + bg2->Size.x < 0.0f){
        bg2->Position.x = bg1->Position.x + bg1->Size.x;
    }
    

    3、渲染精灵(Render)

    bg1->Draw(*Renderer);
    bg2->Draw(*Renderer);
    

    posted in GuaiK实验室 read more
  • Zero

    在使用CMake管理项目时可以很方便的导入其他CMake的第三方代码,但是在第三方代码中可能不是以相对路径导入头文件而是以尖括号#include<>导入头文件,这样就造成了无法查找头文件的错误。


    — 解决方式 —

    解决方式在根目录的CMakeLists.txt中添加:

    include_directories(${CMAKE_CURRENT_SOURCE_DIR})
    

    posted in GuaiK实验室 read more
  • Zero

    给一段使用glfw创建窗口的代码:

    const GLuint SCREEN_WIDTH = 800;
    const GLuint SCREEN_HEIGHT = 600;
    GLFWwindow *window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "GuaikDemo", nullptr, nullptr);
    

    我想创建一个800 * 600 像素的窗口程序,然后使用默认的帧缓冲可以正常的绘制出三角形或者纹理。

    但是如果使用glGenFramebuffers等函数创建帧缓冲做后期处理,在MacOS中就出现问题了(只显示了左下角的1/4图像),效果图如下所示,在MacOS中仅显示部分图像,但是拖动到扩展屏后就一切正常。


    7CB72945-B274-421E-A1A6-B1E3364E9438.gif


    这是为什么呢?既然是像素问题,那就把一些数据打印出来看看吧,在glfwCreateWindow之后使用glfwGetFramebufferSize函数把窗口的长宽像素打印出来看下

    int ScreenX;
    int ScreenY;
    glfwGetFramebufferSize(window, &ScreenX, &ScreenY);
    std::cout << "Width: " << ScreenX << " Height: " << ScreenY << std::endl;
    

    结果跟想的一样,虽然设置了800 * 600,但是打印结果是 Width: 1600 Height: 1200,都翻了一倍,所以最后在使用像素的任何地方都用glfwGetFramebufferSize获取到的宽高作为参数,并且glViewport也设置了同样的像素。

    // 渲染
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glViewport(0, 0, ScreenX, ScreenY);
    ......
    glfwSwapBuffers(window);
    

    问题完美解决。


    但是,在MacOS中显示正常了,拖动到扩展屏显示却出现异常,要解决这个问题的话应该检测当前所激活的显示设备,然后动态设置像素参数并调用glViewport。

    posted in GuaiK实验室 read more
  • Zero

    设计理念:

    LOGO图形设计及字体设计,LOGO以乌鸦为设计原型,将带巫师帽的乌鸦拟人化成黑衣人形象,以怪化鸦及科学怪鸦为主轴。字体设计以乌鸦羽翼及乌鸦爪痕为原型。整体以黑白颜色为主,黑乌鸦及白底色,亦可白乌鸦及黑底色使用。

    设计师:

    @Joy

    版权申明:

    以下图案已注册版权保护,LOGO及字体设计可以免费非商业使用,若要使用需保留GuaiK、设计者及使用出处,否则视为侵权。


    白底LOGO

    GuaiK_white_画板 1.png


    黑底LOGO

    GuaiK_black_画板 1.png

    posted in GuaiK新闻 read more
  • Zero

    nginx configuration which uses SSL

    ### redirects http requests to https
    server {
        listen 80;
        server_name forum.example.org;
    
        return 302 https://$server_name$request_uri;
    }
    
    ### the https server
    server {
        # listen on ssl, deliver with speedy if possible
        listen 443 ssl spdy;
    
        server_name forum.example.org;
    
        # change these paths!
        ssl_certificate /path/to/cert/bundle.crt;
        ssl_certificate_key /path/to/cert/forum.example.org.key;
    
        # enables all versions of TLS, but not SSLv2 or 3 which are weak and now deprecated.
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    
        # disables all weak ciphers
        ssl_ciphers 'AES128+EECDH:AES128+EDH';
    
        ssl_prefer_server_ciphers on;
    
        location / {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Host $http_host;
            proxy_set_header X-NginX-Proxy true;
    
            proxy_pass http://127.0.0.1:8888;
            proxy_redirect off;
    
            # Socket.IO Support
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }
    }
    

    Nodebb config.json

    {
        "url": "https://xxx.domain.org",
        "secret": "UUID",
        "database": "mongo",
        "port": "8888",
        "mongo": {
            "host": "127.0.0.1",
            "port": "27017",
            "username": "",
            "password": "",
            "database": "nodebb",
            "uri": ""
        }
    }
    

    posted in GuaiK机房 read more
  • Zero

    通过对音频波形文件(PCM格式)进行自相关的计算,检测出音频基音所在的频率,最后通过查表将频率转换成MIDI格式的音符。


    # -*- coding: utf-8 -*-
    import wave
    import pyaudio
    import numpy as np
    import math
    import matplotlib.pyplot as pyplot
    from numpy.fft import rfft, rfftfreq
    import time
    import scipy.signal as signal
    import midi
    from midiutil import MIDIFile
    import pygame
    
    def play_music(music_file):
      clock = pygame.time.Clock()
      try:
        pygame.mixer.music.load(music_file)
        print("Music file {} loaded!".format(music_file))
      except pygame.error:
        print("File {} not found! {}".format(music_file, pygame.get_error()))
        return
      pygame.mixer.music.play()
      # check if playback has finished
      while pygame.mixer.music.get_busy():
        clock.tick(30)
    
    freq = 44100  # audio CD quality
    bitsize = -16  # unsigned 16 bit
    channels = 2  # 1 is mono, 2 is stereo
    buffer = 2048  # number of samples (experiment to get right sound)
    pygame.mixer.init(freq, bitsize, channels, buffer)
    # optional volume 0 to 1.0
    pygame.mixer.music.set_volume(0.8)
    
    
    midi_hz = [27.500, 29.135, 30.868, 32.703, 34.648, 36.708, 38.891,
                    41.203, 43.654, 46.249, 48.999, 51.913, 55.0, 58.270,
                    61.735, 65.406, 69.269, 73.416, 77.782, 82.407, 87.307,
                    92.499, 97.999, 103.83 ,110.00, 116.34, 123.47, 130.81, 138.59,
                    146.83, 155.36, 164.81, 174.61, 185.0, 196.0, 207.65,
                    220.0, 233.08, 246.94, 261.63, 277.18, 293.66, 311.13,
                    329.63, 349.23, 369.99, 392.0, 415.3, 440.0, 466.16,
                    493.88, 523.25, 554.37, 587.33, 622.23, 659.26, 698.46,
                    739.99, 783.99, 830.61, 880.0, 932.33, 987.77, 1046.5,
                    1108.7, 1174.7, 1244.5, 1318.5, 1396.9, 1480.0, 1568.0,
                    1661.2, 1760.0,1864.7, 1975.5, 2093.0, 2217.5, 2349.3,
                    2489.0, 2637.0, 2793.0, 2960.0, 3136.0, 3322.4, 3520.0,
                    3729.3, 3951.1, 4186.0]
    midi_num = [x for x in range(21, 21 + 88)]
    
    
    class Wave:
        def __init__(self, filename):
            self.f = wave.open(filename,"rb")
            self.nchannels, self.sampwidth, self.framerate, self.nframes = self.f.getparams()[0:4]
            print self.nchannels, self.sampwidth, self.framerate, self.nframes
            self.data = self.f.readframes(self.nframes)
            self.f.close()
            self.frame_size = self.sampwidth * self.nchannels
            self.frame_time = 1.0 / self.framerate
            self.len = self.nframes * self.frame_size
            self.player = pyaudio.PyAudio()
            self.stream = self.player.open(format=self.player.get_format_from_width(self.sampwidth),
                    channels=self.nchannels,
                    rate=self.framerate,
                    output=True)
    
        def play(self):
            pos = 0
            while pos + self.frame_size * self.framerate < self.len:
                print "current pos -> {}\t/{}".format(pos + self.frame_size * self.framerate, self.len)
                self.stream.write(self.data[pos:pos + self.frame_size * self.framerate])
                pos += self.frame_size * self.framerate
            print "current pos -> {}\t/{} over!".format(pos + self.frame_size * self.framerate, self.len)
    
    
        def make_spectrum(self, start, duration):
            dtype_map = {1:np.int8, 2:np.int16, 3:'special', 4:np.int32}
            ys = None
            if self.sampwidth not in dtype_map:
                raise ValueError('sampwidth %d unknown' % self.sampwidth)
            if self.sampwidth == 3:
                xs = np.fromstring(self.data, dtype=np.int8).astype(np.int32)
                ys = (xs[2::3] * 256 + xs[1::3]) * 256 + xs[0::3]
            else:
                ys = np.fromstring(self.data, dtype=dtype_map[self.sampwidth])
            print ys
            ys.shape = -1,2
            print ys
            ys = ys.T[0]
            print len(ys)
            start_frame = int(start * self.framerate)
            end_frame = int(start_frame + duration * self.framerate)
            ys = ys[start_frame:end_frame]
            n = len(ys)
            d = 1.0 / self.framerate
            fs = np.fft.rfftfreq(n, d)
            hs = np.fft.rfft(ys)
            hs = hs / (len(hs)) # 归一化处理
            return Spectrum(hs, fs, self.framerate)
    
        def ploat(self):
            wave_data = None
            if self.sampwidth == 1:
                wave_data = np.fromstring(self.data, dtype=np.int8)
            elif self.sampwidth == 2:
                wave_data = np.fromstring(self.data, dtype=np.int16)
            elif self.sampwidth == 3:
                data = []
                for i in range(len(self.data)):
                    if i % 3 == 0: data.append("\0")
                    data.append(self.data[i])
                wave_data = np.fromstring("".join(data), dtype=np.int32)
    
            t = np.arange(0, self.nframes) * self.frame_time
            if self.nchannels == 1:
                wave_data.shape = -1,1
                wave_data = wave_data.T
                pyplot.subplot(1,1,1)
                d = wave_data[0] * 1.0 / max(abs(wave_data[0]))
                pyplot.plot(t, wave_data[0], c="darkorange")
            elif self.nchannels == 2:
                wave_data.shape = -1,2
                wave_data = wave_data.T
                pyplot.subplot(2,1,1)
                d = wave_data[0] * 1.0 / max(abs(wave_data[0]))
                pyplot.plot(t, d, c="darkorange")
                pyplot.subplot(2,1,2)
                d = wave_data[1] * 1.0 / max(abs(wave_data[1]))
                pyplot.plot(t, d, c="g")
            pyplot.xlabel("time (seconds)")
    
    
    def corrcoef(xs, ys):
        return np.corrcoef(xs, ys, ddof=0)[0, 1]
    
    def serial_corr(wave, lag=1):
        n = len(wave)
        y1 = wave[lag:]
        y2 = wave[:n-lag]
        corr = corrcoef(y1, y2)
        return corr
    
    def autocorr(wave):
        lags = range(len(wave)//2)
        corrs = [serial_corr(wave, lag) for lag in lags]
        return lags, corrs
    
    # def autocorr(wave):
    #     lags = range(len(wave))
    #     corrs = np.correlate(wave, wave, mode='same')
    #     return lags, corrs
    
    def GetMidi(hz):
        for index,item in enumerate(midi_hz):
            if hz < midi_hz[0]: return 0
            if hz < item: return midi_num[index-1]
        return 0
    
    def ACFPitch(wave):
        wave_data = np.fromstring(wave.data, dtype=np.int16)
        # b, a = signal.butter(8, 0.02, 'lowpass')
        # wave_data = signal.filtfilt(b, a, wave_data)
        wave_data = signal.medfilt(wave_data, 401)
        wave_data = signal.detrend(wave_data,type='linear')
        frame_size = 4096
        frame_time = round(frame_size / 44100.0, 3)
        step_total = len(wave_data) / frame_size
    
        MyMIDI = MIDIFile(1)
        MyMIDI.addTempo(0, 0, 120)
        degrees = []
        for i in range(step_total-1):
            start = i * frame_size
            lags, corrs = autocorr(wave_data[start:start+frame_size])
            width = np.arange(10,30)
            peaks = signal.find_peaks_cwt(corrs, width)[1:]
            data = [corrs[x] for x in peaks]
            md = 0
            if data:
                index = np.argmax(data)
                hz = 1.0 / (float(lags[peaks[index]]) / 44100)
                md = GetMidi(hz)
            degrees.append(md)
    
        count = 1
        time = 0
        for i in range(len(degrees)-1):
            if degrees[i] == degrees[i+1]: count += 1
            else:
                if degrees[i] !=0:
                    MyMIDI.addNote(0, 0, degrees[i], time, count * frame_time, 100)
                count = 1
            time += frame_time
        if degrees[-1] != 0:
            MyMIDI.addNote(0, 0, degrees[-1], time, count * frame_time, 100)
    
        with open("~/test.mid", "wb") as output_file:
            MyMIDI.writeFile(output_file)
    
    if __name__ == "__main__":
        w = Wave("~/test.wav")
        w.play()
        ACFPitch(w)
        play_music("~/test.mid")
    
    

    posted in GuaiK实验室 read more