CODE:
/*****************************************************************************************************
* File name: Game.cpp
* Create time: 2015/03/28
* Module: View
* Author: zengqh
* Blog: http://blog.youkuaiyun.com/aimyton
* ---------------------------------------------------------------------------------------------------
* Memo:
*
*****************************************************************************************************/
#include "Game.h"
/*****************************************************************************************************
* Macro and Struct definition
*****************************************************************************************************/
#define DYNAMIC_RANGE (200)
#define ACCELERATION (1000)
/*****************************************************************************************************
* Global variables
*****************************************************************************************************/
extern HINSTANCE HInstance;
f32 g_start_speed = 0.0f;
f32 g_circle_time = 0.0f;
/*****************************************************************************************************
* Global function declare
*****************************************************************************************************/
/*****************************************************************************************************
* Global function definition
*****************************************************************************************************/
/*****************************************************************************************************
* Class declare
******************************************************************************************************/
Game::Game()
: m_surface_width(640)
, m_surface_height(480)
, m_hwnd(0)
, m_backbuff_bitmap(0)
, m_back_buffer(NULL)
, m_should_exit_game(false)
, m_start_render_time(0)
, m_min_y(480)
{
g_circle_time = 2 * sqrtf(2 * DYNAMIC_RANGE / (float)ACCELERATION);
g_start_speed = ACCELERATION * (g_circle_time / 2.0f);
}
Game::~Game()
{
}
bool Game::Initalize()
{
if(!initDriver()) return false;
return true;
}
bool Game::UnInitialize()
{
return true;
}
bool Game::Loop()
{
handleMessage();
return true;
}
void Game::handleMessage()
{
MSG msg;
::ZeroMemory(&msg, sizeof(MSG));
static float lastTime = (float)timeGetTime();
while(msg.message != WM_QUIT)
{
if(m_should_exit_game)
{
PostMessage(m_hwnd, WM_QUIT, 0, 0);
}
if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
else
{
float timeLog=1.0f / 100.0f;
float currTime =(float)timeGetTime();
float timeDelta =(currTime-lastTime) * 0.001f;
if(timeDelta < timeLog)
{
float sleep=1000 * (timeLog - timeDelta);
Sleep(sleep);
}
currTime =(float)timeGetTime();
timeDelta =(currTime-lastTime)*0.001f;
gameLoop(timeDelta);
lastTime = currTime;
}
}
}
void Game::gameLoop(float time_delta)
{
frameStarted();
render();
frameEnded();
swap();
}
void Game::frameStarted()
{
memset(m_back_buffer, 0x0, m_surface_width * m_surface_height * 4);
}
void Game::render()
{
renderTextFixed(m_surface_width / 2 - 200, m_surface_height / 2, "hello world");
renderTextBottom(m_surface_width / 2, m_surface_height / 2, "hello world");
renderTextCenter(m_surface_width / 2 - 100, m_surface_height / 2, "hello world");
}
void Game::frameEnded()
{
}
void Game::swap()
{
BitBlt(m_hdc, 0, 0, m_surface_width, m_surface_height, m_bdc, 0, 0, SRCCOPY);
}
bool Game::initDriver()
{
createWindow();
createBackBuffer();
return true;
}
bool Game::createWindow()
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = HInstance;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = "GameDemo";
if( !RegisterClass(&wc) )
{
::MessageBox(0, "RegisterClass() - FAILED", 0, 0);
return false;
}
RECT rect = {0, 0, m_surface_width, m_surface_height};
::AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
HWND hwnd = 0;
hwnd = ::CreateWindow("GameDemo", "GameDemo",
WS_OVERLAPPEDWINDOW,
0, 0, rect.right - rect.left, rect.bottom - rect.top,
0 /*parent hwnd*/, 0 /* menu */, HInstance, 0 /*extra*/);
if( !hwnd )
{
::MessageBox(0, "CreateWindow() - FAILED", 0, 0);
return false;
}
m_hwnd = hwnd;
m_hdc = ::GetDC(m_hwnd);
::ShowWindow(hwnd, SW_SHOW);
::UpdateWindow(hwnd);
return true;
}
bool Game::createBackBuffer()
{
BITMAPINFO bitmap_info = {0};
bitmap_info.bmiHeader.biSize = sizeof(bitmap_info);
bitmap_info.bmiHeader.biWidth = m_surface_width;
bitmap_info.bmiHeader.biHeight = m_surface_height;
bitmap_info.bmiHeader.biPlanes = 1;
bitmap_info.bmiHeader.biSizeImage = 0;
bitmap_info.bmiHeader.biXPelsPerMeter = 0;
bitmap_info.bmiHeader.biYPelsPerMeter = 0;
bitmap_info.bmiHeader.biClrUsed = 0;
bitmap_info.bmiHeader.biClrImportant = 0;
bitmap_info.bmiHeader.biBitCount = 32;
bitmap_info.bmiHeader.biCompression = BI_RGB;
m_bdc = CreateCompatibleDC(m_hdc);
m_backbuff_bitmap = CreateDIBSection(
NULL,
&bitmap_info,
0,
(void**)&m_back_buffer,
0,
0);
::SelectObject(m_bdc, m_backbuff_bitmap);
return (m_back_buffer != NULL ? true : false);
}
void Game::renderTextFixed(int x, int y, char* str)
{
::TextOutA(m_bdc, x, y, str, strlen(str));
}
void Game::renderTextBottom(int x, int y, char* str)
{
if(m_start_render_time == 0)
{
m_start_render_time = GetTickCount();
}
else
{
u32 curr_time = GetTickCount();
float time_delta = (curr_time - m_start_render_time) / 1000.0f;
float one_circle_time = time_delta - (u32)(time_delta / g_circle_time) * g_circle_time;
float accer = ACCELERATION;
y += -g_start_speed * one_circle_time + 0.5f * accer * one_circle_time * one_circle_time;
::TextOutA(m_bdc, x, y, str, strlen(str));
}
}
void Game::renderTextCenter(int x, int y, char* str)
{
if(m_start_render_time == 0)
{
m_start_render_time = GetTickCount();
}
else
{
u32 curr_time = GetTickCount();
float time_delta = (curr_time - m_start_render_time) / 1000.0f;
float one_circle_time = time_delta - (u32)(time_delta / g_circle_time) * g_circle_time;
float accer = ACCELERATION;
y += -g_start_speed * one_circle_time + 0.5f * accer * one_circle_time * one_circle_time;
if(y < m_min_y)
{
m_min_y = y;
}
y += (DYNAMIC_RANGE >> 1);
::TextOutA(m_bdc, x, y, str, strlen(str));
}
}
LRESULT CALLBACK Game::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch( msg )
{
case WM_DESTROY:
::PostQuitMessage(0);
break;
}
return ::DefWindowProc(hwnd, msg, wParam, lParam);
}
/*****************************************************************************************************
* Class definition
*****************************************************************************************************/
/***********************************End of File*******************************************************/