7 Replies - 840 Views - Last Post: 30 September 2015 - 09:58 AM Rate Topic: -----

#1 JekasG  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 26-September 15

C++ Win32 FPS and DeltaTime Implementation

Posted 26 September 2015 - 09:47 PM

I'm trying to implement FPS and DeltaTime for my program (C++ Win32). Below is the current code that I have. FPS and DeltaTime should have implemented int the right manner. If not, please tell me how I may fix my problem.

The current problem I am facing is how I should use DeltaTime. That is to Update and Render. And yes I did use a wrapper class.
Before I implemented this, I was using WindowProcedure to handle my messages and I no problem with that. But now, trying to implement this is tilting me. So before I was using a back buffer and WM_PAINT to draw and i had to take in hwnd in order to draw. And updated is via input from WindowProcedure which had to take in arguments like LPARAM and WPARAM But after reading articles and forums on this topic. Update and Render is needed but they didnt have to take in hwnd for the Render Method. As for update they didnt have to take that in.

So basically i just want to know how do i write the Update and Render Method ?

    bool BaseWindow::HandleMessages() {
    	
    	// Counts Per Second
    	INT64 counts_per_sec = 0;
    	QueryPerformanceFrequency( ( LARGE_INTEGER* ) &counts_per_sec );
    	// Seconds Per Count
    	float sec_per_count = 1.0f / ( float ) counts_per_sec;
    	// Pervious Time
    	INT64 prev_time = 0;
    	QueryPerformanceCounter( ( LARGE_INTEGER* ) &prev_time );
    
    	MSG message = { 0 };
    
    	if ( PeekMessage( &message, NULL, 0, 0, PM_REMOVE )) {
    		TranslateMessage( &message );
    		DispatchMessage( &message );
    
    		if ( message.message == WM_QUIT ) {
    			OnDestroy();
    			return false;
    		}
    	}
    	else {
    		// Get current count
    		INT64 current_time = 0;
    		QueryPerformanceCounter( ( LARGE_INTEGER* ) &current_time );
    		// DeltaTime
    		float delta_time = ( current_time - prev_time ) * sec_per_count;
    
    		// Update
    
    		// Render
    	}
    	return true;
    }



Is This A Good Question/Topic? 0
  • +

Replies To: C++ Win32 FPS and DeltaTime Implementation

#2 CTphpnwb  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3717
  • View blog
  • Posts: 13,493
  • Joined: 08-August 08

Re: C++ Win32 FPS and DeltaTime Implementation

Posted 27 September 2015 - 04:59 AM

There are time functions available:
http://www.cplusplus...ctime/difftime/
...scratch that.

After reading through your code I see why no one else responded. You can't just ask how to write a function and then not show your attempt! (Showing another function doesn't count.)

This post has been edited by CTphpnwb: 27 September 2015 - 05:06 AM

Was This Post Helpful? 0
  • +
  • -

#3 JekasG  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 26-September 15

Re: C++ Win32 FPS and DeltaTime Implementation

Posted 27 September 2015 - 06:35 AM

View PostCTphpnwb, on 27 September 2015 - 04:59 AM, said:

There are time functions available:
http://www.cplusplus...ctime/difftime/
...scratch that.

After reading through your code I see why no one else responded. You can't just ask how to write a function and then not show your attempt! (Showing another function doesn't count.)


Its not that i didn't or haven't attempted to solve the problem myself. Its because i have tried to solve the problem myself but all the attempts i have made arent working and it may seem really foolish to post them. In addition, arent question supposed to be brief and not in long detail ?

Furthermore, i just dont understand how to not take in hwnd for render in particular.
I could just simply upload the general framework of my code. If thats what you want
Was This Post Helpful? 0
  • +
  • -

#4 JekasG  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 26-September 15

Re: C++ Win32 FPS and DeltaTime Implementation

Posted 27 September 2015 - 06:55 AM

Here is the code that i have.

If you find the method from above. From the below Basewindow.cpp
I would i have commented out what i have problems with


**Main.cpp**

    #include "Basewindow.h"
    #include "Childwindow.h"
    
    int APIENTRY WinMain( HINSTANCE h_instance, HINSTANCE h_prev_instance, LPSTR lp_cmd_line, int n_cmd_show ) {
    
    	ChildWindow child_window( h_instance, TEXT( "Child Window" ) );
    	BaseWindow base_window( TEXT( "Base Window" ), child_window.ClassName() );
    
    	while ( base_window.HandleMessages() );
    	return 0;
    }


**Abstractwindow.h**
    #ifndef __ABSTRACTWINDOW_H__
    #define __ABSTRACTWINDOW_H__
    #pragma once
    
    #include <Windows.h>
    
    class AbstractWindow {
    
    	#pragma region Methods
    		public:
    			AbstractWindow();
    			~AbstractWindow();
    
    			virtual bool Create();
    				static LRESULT CALLBACK MessageHandler( HWND, UINT, WPARAM, LPARAM );
    			protected:
    				virtual LRESULT CALLBACK WindowProcedure( HWND, UINT, WPARAM, LPARAM ) = 0;
    	#pragma endregion
    
    	#pragma region Variables
    		protected:
    			HWND hwnd_;
    			DWORD style_ex_;
    			LPCTSTR class_name_;
    			LPCTSTR window_name_;
    			DWORD style_;
    			int x_;
    			int y_;
    			int width_;
    			int height_;
    			HWND parent_;
    			HMENU menu_;
    			HINSTANCE instance_;
    
    	#pragma endregion
    
    };
    #endif // !__ABSTRACTWINDOW_H__


**Abstractwindow.cpp**
    #include "Abstractwindow.h"
    
    AbstractWindow::AbstractWindow() {}
    
    AbstractWindow::~AbstractWindow() {}
    
    bool AbstractWindow::Create() {
    	// Default Create Method
    
    	hwnd_ = CreateWindowEx(
    		style_ex_,
    		class_name_,
    		window_name_,
    		style_,
    		x_,
    		y_,
    		width_,
    		height_,
    		parent_,
    		menu_,
    		instance_,
    		this
    		);
    
    	return ( hwnd_ ? true : false );
    
    }
    
    LRESULT CALLBACK AbstractWindow::MessageHandler( HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param ) {
    
    	AbstractWindow* abstract_window = 0;
    
    	if ( message == WM_NCCREATE ) {
    		abstract_window = ( AbstractWindow* ) ( ( LPCREATESTRUCT( l_param ) )->lpCreateParams );
    		SetWindowLong( hwnd, GWL_USERDATA, long( abstract_window ) );
    	}
    
    	abstract_window = ( AbstractWindow * ) ( GetWindowLong( hwnd, GWL_USERDATA ) );
    
    	if ( abstract_window ) {
    		return abstract_window->WindowProcedure( hwnd, message, w_param, l_param );
    	}
    	else {
    		return DefWindowProc( hwnd, message, w_param, l_param );
    	}
    
    }


**Basewindow.h**
    #ifndef __BASEWINDOW_H__
    #define __BASEWINDOW_H__
    #pragma once
    
    #include "Abstractwindow.h"
    #include "Childwindow.h"
    
    class BaseWindow : public AbstractWindow {
    
    	#pragma region Test Methods
    		private:
    			void Update();
    			void Render();
    	#pragma endregion
    
    	#pragma region Methods
    		public:
    			BaseWindow();
    			~BaseWindow();
    
    			bool HandleMessages();
    			BaseWindow( const TCHAR*, const TCHAR* );
    			void Show();
    			virtual LRESULT CALLBACK WindowProcedure( HWND, UINT, WPARAM, LPARAM );
    			#pragma region Handles
    				private:
    					bool CreateBackBuffer( HWND );
    					bool OnPaint( HWND );
    					bool PaintManager();
    					bool OnDestroy();
    			#pragma endregion
    	#pragma endregion
    
    	#pragma region Variables
    		private:
    			RECT window_rect_;				// Structure for window width and height
    			int client_width_;
    			int client_height_;
    			POINT mouse_pos_;
    			#pragma region Back Buffer
    					HDC hdc_;					// Handle to Device Context
    					HDC back_buffer_;			// Back Buffer
    					HBITMAP bitmap_;				// Current bitmap
    			#pragma endregion
    	#pragma endregion
    
    };
    #endif // !__BASEWINDOW_H__



**Basewindow.cpp**
    #include "Basewindow.h"
    
    BaseWindow::BaseWindow() {}
    
    BaseWindow::~BaseWindow() {}
    
    BaseWindow::BaseWindow( const TCHAR* window_name, const TCHAR* class_name ) {
    
    	style_ex_ = NULL;
    	class_name_ = class_name;
    	window_name_ = window_name;
    	style_ = WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
    	x_ = CW_USEDEFAULT;
    	y_ = CW_USEDEFAULT; CW_USEDEFAULT;
    	width_ = CW_USEDEFAULT;
    	height_ = CW_USEDEFAULT;
    	parent_ = NULL;
    	menu_ = NULL;
    	instance_ = GetModuleHandle( NULL );
    
    	Create();
    	Show();
    
    }
    
    void BaseWindow::Show() {
    	ShowWindow( hwnd_, SW_SHOW );
    	UpdateWindow( hwnd_ );
    }
    
    LRESULT CALLBACK BaseWindow::WindowProcedure( HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param ) {
    
    	switch ( message ) {
    		case WM_CREATE:
    			CreateBackBuffer(hwnd);
    			return true;
    		case WM_ERASEBKGND:
    			return true;
    		case WM_DESTROY:
    			return OnDestroy();
    		default:
    			return DefWindowProc( hwnd, message, w_param, l_param );
    	}
    }
    
    bool BaseWindow::HandleMessages() {
    
    	// Counts Per Second
    	INT64 counts_per_sec = 0;
    	QueryPerformanceFrequency( ( LARGE_INTEGER* ) &counts_per_sec );
    	// Seconds Per Count
    	float sec_per_count = 1.0f / ( float ) counts_per_sec;
    	// Pervious Time
    	INT64 prev_time = 0;
    	QueryPerformanceCounter( ( LARGE_INTEGER* ) &prev_time );
    
    	MSG message = { 0 };
    
    	if ( PeekMessage( &message, NULL, 0, 0, PM_REMOVE ) ) {
    		TranslateMessage( &message );
    		DispatchMessage( &message );
    
    		if ( message.message == WM_QUIT ) {
    			OnDestroy();
    			return false;
    		}
    	}
    	else {
    		// Get current count
    		INT64 current_time = 0;
    		QueryPerformanceCounter( ( LARGE_INTEGER* ) &current_time );
    		// DeltaTime
    		float delta_time = ( current_time - prev_time ) * sec_per_count;
    
    		// Update
    
    		// Render
    		// I need to call for OnPaint()
    		// I need to take in hwnd
    		// But how ?
    		// Or do i not take in hwnd ?
    		// But hoe ?
    
    	}
    	return true;
    }
    
    #pragma region Handles
    
    bool BaseWindow::CreateBackBuffer( HWND hwnd ) {
    
    	GetClientRect( hwnd, &window_rect_ );
    	client_width_ = window_rect_.right;
    	client_height_ = window_rect_.bottom;
    
    	back_buffer_ = CreateCompatibleDC( NULL );	// Create Back Buffer
    	hdc_ = GetDC( hwnd );	// Get the Device Context
    	bitmap_ = CreateCompatibleBitmap( hdc_, client_width_, client_height_ );	// Create Bitmap
    	SelectObject( back_buffer_, bitmap_ );	// Select Bitmap
    
    	ReleaseDC( hwnd, hdc_ );	// Release
    
    	return true;
    }
    
    bool BaseWindow::OnPaint( HWND hwnd ) {
    
    	PAINTSTRUCT paint_struct;
    
    	hdc_ = BeginPaint( hwnd_, &paint_struct );		// Get the Device Context
    
    	BitBlt( back_buffer_, 0, 0, client_width_, client_height_, NULL, NULL, NULL, WHITENESS );
    
    	// Paint
    	PaintManager();
    
    	BitBlt( hdc_, 0, 0, client_width_, client_height_, back_buffer_, 0, 0, SRCCOPY );		// Display the back buff
    	InvalidateRect( hwnd, NULL, true );		// Repaint the screen
    
    	EndPaint( hwnd, &paint_struct );
    
    	return true;
    }
    
    bool BaseWindow::PaintManager() {
    
    	HBRUSH brush = ( HBRUSH ) ( GetStockObject( WHITE_BRUSH ) );
    	SelectObject( back_buffer_, brush );		// Select Brush
    
    	Rectangle( back_buffer_, 200, 200, 500, 500 );
    
    	DeleteObject( brush );
    
    	return true;
    
    }
    
    bool BaseWindow::OnDestroy() {
    	PostQuitMessage( 0 );
    	return true;
    }
    
    #pragma endregion


**Childwindow.h**
        #ifndef __CHILDWINDOW_H__
    #define __CHILDWINDOW_H__
    #pragma once
    
    #include "Abstractwindow.h"
    #include "Basewindow.h"
    
    class ChildWindow : protected WNDCLASSEX {
    
    	#pragma region Methods
    		public:
    			ChildWindow();
    			~ChildWindow();
    
    			ChildWindow( HINSTANCE, const TCHAR* );
    			bool Register();
    			const TCHAR* ClassName() const;
    	#pragma endregion
    
    };
    #endif // !__CHILDWINDOW_H__
    


**Childwindow.cpp**
    #include "Childwindow.h"
    
    ChildWindow::ChildWindow() {}
    
    ChildWindow::~ChildWindow() {}
    
    ChildWindow::ChildWindow( HINSTANCE h_instance, const TCHAR* class_name ) {
    
    	cbSize = sizeof( WNDCLASSEX );
    	style = NULL;
    	lpfnWndProc = AbstractWindow::MessageHandler;
    	cbClsExtra = NULL;
    	cbWndExtra = NULL;
    	hInstance = h_instance;
    	hIcon = LoadIcon( NULL, IDI_APPLICATION );
    	hCursor = LoadCursor( NULL, IDC_ARROW );
    	//hbrBackground = ( HBRUSH ) ( GetStockObject( DKGRAY_BRUSH ) );
    	hbrBackground = ( HBRUSH ) NULL;
    	lpszMenuName = NULL;
    	lpszClassName = class_name;
    	hIconSm = LoadIcon( NULL, IDI_APPLICATION );
    
    	Register();
    	
    }
    
    bool ChildWindow::Register() {
    	return ( ( RegisterClassEx( this ) ) ? true : false );
    }
    
    const TCHAR* ChildWindow::ClassName() const {
    	return lpszClassName;
    }



Was This Post Helpful? 0
  • +
  • -

#5 snoopy11  Icon User is offline

  • Engineering ● Software
  • member icon

Reputation: 1393
  • View blog
  • Posts: 4,410
  • Joined: 20-March 10

Re: C++ Win32 FPS and DeltaTime Implementation

Posted 27 September 2015 - 09:21 AM

Oh well here goes,

If this is for a game you will find win32 gdi or gdi+ too slow.

That's why direct x was introduced after all.

Try directx 2d which is easier or 3d which can do more but is slightly more abstract.

The way you would do your update is to raise a function called Update and in its parameters
have the things in it you need to Update like positions etc like this.

Update(int posX, int posY...........etc);

for your render function all you need is to set a boolean flag variable to true or false then call InvalidateRect after it in your message loop.

call the flag
bool Render;
for example

Then in WM_PAINT: routine if the flag variable is true then draw if its false do not draw.

in your WM_PAINT: do not call InvalidateRect that is just redundant and will slow the drawing process.

In your message loop call

TranslateMessage( &message );
DispatchMessage( &message );


last of all do everything else before it.

TranslateMessage and DispatchMessage deal with all the other OS related functions to your program like clicking minimize etc.

Overall you have a poor understanding of how a win32 program works and thats going to affect your program.
I would get a good book ie Petzold's book on win32 programming.

Also you should have a Game Class that encapsulates all the data of your game.

That way you eliminate all the nasty global variables that are sometimes necessary in designing a game without classes.

Good Luck.

Snoopy.
Was This Post Helpful? 0
  • +
  • -

#6 JekasG  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 26-September 15

Re: C++ Win32 FPS and DeltaTime Implementation

Posted 27 September 2015 - 03:09 PM

Here is my updated code. Although i think i didnt do it right.
There is some slight problems with it.
1) The FPS is incredibly high, its as if its calculated wrong.
2) The program is taking a while to load even though the window is open. The draw is slow aswell at the start. And since im not updating draw for now i dont know if redrawing will be slow aswell. (Im only drawing a rectangle)
3. The program still runs even thought the Red Cross Button (Close) is pressed

Main.cpp
#include "Basewindow.h"
#include "Childwindow.h"

int APIENTRY WinMain( HINSTANCE h_instance, HINSTANCE h_prev_instance, LPSTR lp_cmd_line, int n_cmd_show ) {

	ChildWindow child_window( h_instance, TEXT( "Child Window" ) );
	BaseWindow base_window( TEXT( "Base Window" ), child_window.ClassName() );

	base_window.MessagePoll();
	return 0;
}


Abstractwindow.h
#ifndef __ABSTRACTWINDOW_H__
#define __ABSTRACTWINDOW_H__
#pragma once

#include <Windows.h>

class AbstractWindow {

	#pragma region Methods
		public:
			AbstractWindow();
			~AbstractWindow();

			virtual bool Create();
				static LRESULT CALLBACK MessageHandler( HWND, UINT, WPARAM, LPARAM );
			protected:
				virtual LRESULT CALLBACK WindowProcedure( HWND, UINT, WPARAM, LPARAM ) = 0;
	#pragma endregion

	#pragma region Variables
		protected:
			HWND hwnd_;
			DWORD style_ex_;
			LPCTSTR class_name_;
			LPCTSTR window_name_;
			DWORD style_;
			int x_;
			int y_;
			int width_;
			int height_;
			HWND parent_;
			HMENU menu_;
			HINSTANCE instance_;

	#pragma endregion

};
#endif // !__ABSTRACTWINDOW_H__




Abstractwindow.cpp
#include "Abstractwindow.h"

AbstractWindow::AbstractWindow() {}

AbstractWindow::~AbstractWindow() {}

bool AbstractWindow::Create() {
	// Default Create Method

	hwnd_ = CreateWindowEx(
		style_ex_,
		class_name_,
		window_name_,
		style_,
		x_,
		y_,
		width_,
		height_,
		parent_,
		menu_,
		instance_,
		this
		);

	return ( hwnd_ ? true : false );

}

LRESULT CALLBACK AbstractWindow::MessageHandler( HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param ) {

	AbstractWindow* abstract_window = 0;

	if ( message == WM_NCCREATE ) {
		abstract_window = ( AbstractWindow* ) ( ( LPCREATESTRUCT( l_param ) )->lpCreateParams );
		SetWindowLong( hwnd, GWL_USERDATA, long( abstract_window ) );
	}

	abstract_window = ( AbstractWindow * ) ( GetWindowLong( hwnd, GWL_USERDATA ) );

	if ( abstract_window ) {
		return abstract_window->WindowProcedure( hwnd, message, w_param, l_param );
	}
	else {
		return DefWindowProc( hwnd, message, w_param, l_param );
	}

}


Basewindow.h
#ifndef __BASEWINDOW_H__
#define __BASEWINDOW_H__
#pragma once

#include <sstream>

#include "Abstractwindow.h"
#include "Childwindow.h"

class BaseWindow : public AbstractWindow {

	#pragma region Test Methods
		private:
			void Update();
			void Render();
	#pragma endregion

	#pragma region Methods
		public:
			BaseWindow();
			~BaseWindow();

			void MessagePoll();
			void CalculateFPS(float);
			BaseWindow( const TCHAR*, const TCHAR* );
			void Show();
			virtual LRESULT CALLBACK WindowProcedure( HWND, UINT, WPARAM, LPARAM );
			#pragma region Handles
				private:
					bool CreateBackBuffer( HWND );
					bool OnPaint( HWND );
					bool PaintManager();
					bool OnDestroy();
			#pragma endregion
	#pragma endregion

	#pragma region Variables
		private:
			bool paint_;
			int fps_;
			RECT window_rect_;				// Structure for window width and height
			int client_width_;
			int client_height_;
			POINT mouse_pos_;
			#pragma region Back Buffer
					HDC hdc_;					// Handle to Device Context
					HDC back_buffer_;			// Back Buffer
					HBITMAP bitmap_;				// Current bitmap
			#pragma endregion
	#pragma endregion

};
#endif // !__BASEWINDOW_H__





Basewindow.cpp
#include "Basewindow.h"

BaseWindow::BaseWindow() {}

BaseWindow::~BaseWindow() {}

BaseWindow::BaseWindow( const TCHAR* window_name, const TCHAR* class_name ) {

	style_ex_ = NULL;
	class_name_ = class_name;
	window_name_ = window_name;
	style_ = WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
	x_ = CW_USEDEFAULT;
	y_ = CW_USEDEFAULT; CW_USEDEFAULT;
	width_ = CW_USEDEFAULT;
	height_ = CW_USEDEFAULT;
	parent_ = NULL;
	menu_ = NULL;
	instance_ = GetModuleHandle( NULL );

	paint_ = false;

	Create();
	Show();

}

void BaseWindow::Show() {
	ShowWindow( hwnd_, SW_SHOW );
	UpdateWindow( hwnd_ );
}

LRESULT CALLBACK BaseWindow::WindowProcedure( HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param ) {

	if (paint_) {
		OnPaint(hwnd);
		paint_ = false;
	}

	switch ( message ) {
		case WM_CREATE:
			return CreateBackBuffer(hwnd);			
		case WM_ERASEBKGND:
			return true;
		default:
			return DefWindowProc( hwnd, message, w_param, l_param );
	}

}

void BaseWindow::MessagePoll() {

	bool is_running = true;

	// Counts Per Second
	__int64 counts_per_sec = 0;
	QueryPerformanceFrequency((LARGE_INTEGER*)&counts_per_sec);
	// Seconds Per Count
	float sec_per_count = 1.0f / counts_per_sec;
	// Pervious Time
	__int64 prev_time = 0;
	QueryPerformanceCounter((LARGE_INTEGER*)&prev_time);

	MSG message = {};
	while (is_running) {
		if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) {
			TranslateMessage(&message);
			DispatchMessage(&message);

			if (message.message == WM_QUIT) {
				is_running = false;
				OnDestroy();
			}
		}
		else {
			// Get current count
			__int64 current_time = 0;
			QueryPerformanceCounter((LARGE_INTEGER*)&current_time);
			// DeltaTime
			float delta_time = (current_time - prev_time) * sec_per_count;

			// Update 
			CalculateFPS(delta_time);
			// Render
			paint_ = true;

			prev_time = current_time;
		}
	}
}


void BaseWindow::CalculateFPS(float delta_time) {

	static int frame_count;
	static float elapsed_time;

	frame_count++;
	elapsed_time += delta_time;

	// Frams Per Second
 	if (elapsed_time >= 1.0f) {
		fps_ = frame_count;

		// Output to Window Title
		std::stringstream ss;
		ss << window_name_ << " FPS " << fps_;
		SetWindowText(hwnd_, ss.str().c_str());

		frame_count = 0;
		elapsed_time = 0;
	}
}

#pragma region Handles

bool BaseWindow::CreateBackBuffer( HWND hwnd ) {

	GetClientRect( hwnd, &window_rect_ );
	client_width_ = window_rect_.right;
	client_height_ = window_rect_.bottom;

	back_buffer_ = CreateCompatibleDC( NULL );	// Create Back Buffer
	hdc_ = GetDC( hwnd );	// Get the Device Context
	bitmap_ = CreateCompatibleBitmap( hdc_, client_width_, client_height_ );	// Create Bitmap
	SelectObject( back_buffer_, bitmap_ );	// Select Bitmap

	ReleaseDC( hwnd, hdc_ );	// Release

	return true;
}

bool BaseWindow::OnPaint( HWND hwnd ) {

	PAINTSTRUCT paint_struct;

	hdc_ = BeginPaint( hwnd_, &paint_struct );		// Get the Device Context

	BitBlt( back_buffer_, 0, 0, client_width_, client_height_, NULL, NULL, NULL, WHITENESS );

	// Paint
	PaintManager();

	BitBlt( hdc_, 0, 0, client_width_, client_height_, back_buffer_, 0, 0, SRCCOPY );		// Display the back buff
	InvalidateRect( hwnd, NULL, true );		// Repaint the screen

	EndPaint( hwnd, &paint_struct );

	return true;
}

bool BaseWindow::PaintManager() {

	HBRUSH brush = ( HBRUSH ) ( GetStockObject( WHITE_BRUSH ) );
	SelectObject( back_buffer_, brush );		// Select Brush

	Rectangle( back_buffer_, 200, 200, 500, 500 );

	DeleteObject( brush );

	return true;

}

bool BaseWindow::OnDestroy() {
	PostQuitMessage( 0 );
	return true;
}

#pragma endregion



Childwindow.h
#ifndef __CHILDWINDOW_H__
#define __CHILDWINDOW_H__
#pragma once

#include "Abstractwindow.h"
#include "Basewindow.h"

class ChildWindow : protected WNDCLASSEX {

	#pragma region Methods
		public:
			ChildWindow();
			~ChildWindow();

			ChildWindow( HINSTANCE, const TCHAR* );
			bool Register();
			const TCHAR* ClassName() const;
	#pragma endregion

};
#endif // !__CHILDWINDOW_H__



Childwindow.cpp
#include "Childwindow.h"

ChildWindow::ChildWindow() {}

ChildWindow::~ChildWindow() {}

ChildWindow::ChildWindow( HINSTANCE h_instance, const TCHAR* class_name ) {

	cbSize = sizeof( WNDCLASSEX );
	style = NULL;
	lpfnWndProc = AbstractWindow::MessageHandler;
	cbClsExtra = NULL;
	cbWndExtra = NULL;
	hInstance = h_instance;
	hIcon = LoadIcon( NULL, IDI_APPLICATION );
	hCursor = LoadCursor( NULL, IDC_ARROW );
	//hbrBackground = ( HBRUSH ) ( GetStockObject( DKGRAY_BRUSH ) );
	hbrBackground = ( HBRUSH ) GetStockObject(NULL_BRUSH);
	lpszMenuName = NULL;
	lpszClassName = class_name;
	hIconSm = LoadIcon( NULL, IDI_APPLICATION );

	Register();
	
}

bool ChildWindow::Register() {
	return ( ( RegisterClassEx( this ) ) ? true : false );
}

const TCHAR* ChildWindow::ClassName() const {
	return lpszClassName;
}


Was This Post Helpful? 0
  • +
  • -

#7 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 5928
  • View blog
  • Posts: 20,267
  • Joined: 05-May 12

Re: C++ Win32 FPS and DeltaTime Implementation

Posted 28 September 2015 - 07:29 PM

Your FPS computation is wrong. You are only sampling the clock when you don't have any messages in the message queue. So you effectively have the idle time per second, not frames per second. If you really want to get the frame per second, you need to sample the clock at the time when you paint.
Was This Post Helpful? 0
  • +
  • -

#8 snoopy11  Icon User is offline

  • Engineering ● Software
  • member icon

Reputation: 1393
  • View blog
  • Posts: 4,410
  • Joined: 20-March 10

Re: C++ Win32 FPS and DeltaTime Implementation

Posted 30 September 2015 - 09:58 AM

Well,

Your updated code is still a bit of a mess isn't it ?

As you say there are some problems with it.

1. The fps is incredibly high as if it is calculated wrong.

This has more to do with local variables and you are resetting them to zero every time the function is called putting static in front of everything won't solve this moving them into the class definition and setting them to zero in the constructor will solve your problems.

2. The program is taking a while to load..

Yes, you don't say, this is because you dont really understand to a level that you should before writing window classes how win32 programs work.

3. The program wont close.

Again this is a mixture of not understanding how win32 programs work and not understanding how windows classes operate.

Overall it looks like you cobbled together some code you found online and threw it at the computer screen and hoped it would stick. Well it didn't it fell apart.

Get a good book on win32 programming.

Here is your fixed code.

Now as a disclaimer I would never write code like this but this is my interpretation on how to fix your code as it currently stands.

main.cpp
#include "Basewindow.h"
#include "Childwindow.h"

int APIENTRY WinMain(HINSTANCE h_instance, HINSTANCE h_prev_instance, LPSTR lp_cmd_line, int n_cmd_show) {

	ChildWindow child_window(h_instance, TEXT("Child Window"));
	BaseWindow base_window(TEXT("Base Window"), child_window.ClassName());
	bool exitprogram = true;
	while (exitprogram !=false)
	{
		exitprogram = base_window.MessagePoll();
	}
	return 0;
}



Basewindow.h

#ifndef __BASEWINDOW_H__
#define __BASEWINDOW_H__
#pragma once

#include <sstream>

#include "Abstractwindow.h"
#include "Childwindow.h"
#include <cmath>
class BaseWindow : public AbstractWindow {

#pragma region Test Methods
private:
	void Update();
	void Render();
#pragma endregion

#pragma region Methods
public:
	BaseWindow();
	~BaseWindow();
	bool MessagePoll();
	void CalculateFPS();
	BaseWindow(const TCHAR*, const TCHAR*);
	void Show();
	virtual LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
#pragma region Handles
private:
	bool CreateBackBuffer(HWND);
	bool OnPaint(HWND);
	
	
#pragma endregion
#pragma endregion

#pragma region Variables
private:
	bool paint_;
	bool is_running = true;
	int fps_;
	int rectX;
	int rectY;
	int direction;
	RECT window_rect_;				// Structure for window width and height
	int client_width_;
	int client_height_;
	POINT mouse_pos_;
	float delta_time;
	int frame_count;
	float elapsed_time;
	__int64 prev_time;
	__int64 current_time;
	__int64 counts_per_sec;
#pragma region Back Buffer
	HDC hdc_;					// Handle to Device Context
	HDC back_buffer_;			// Back Buffer
	HBITMAP bitmap_;           // Current bitmap
#pragma endregion
#pragma endregion

};
#endif // !__BASEWINDOW_H__



Basewindow.cpp

#include "Basewindow.h"

BaseWindow::BaseWindow() {}

BaseWindow::~BaseWindow() {}

BaseWindow::BaseWindow(const TCHAR* window_name, const TCHAR* class_name) {

	style_ex_ = NULL;
	class_name_ = class_name;
	window_name_ = window_name;
	style_ = WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
	x_ = CW_USEDEFAULT;
	y_ = CW_USEDEFAULT; CW_USEDEFAULT;
	width_ = CW_USEDEFAULT;
	height_ = CW_USEDEFAULT;
	parent_ = NULL;
	menu_ = NULL;
	instance_ = GetModuleHandle(NULL);
	paint_ = false;
	rectX = 100;
	rectY = 100;
	delta_time = 0.0f;
	elapsed_time = 0.0f;
	frame_count = 0;
	prev_time = 0;
	current_time = 0;
	__int64 counts_per_sec;
	Create();
	Show();

}

void BaseWindow::Show() {
	ShowWindow(hwnd_, SW_SHOW);
	UpdateWindow(hwnd_);
}

LRESULT CALLBACK BaseWindow::WindowProcedure(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param) {

	

	switch (message) {
	case WM_CREATE:
		 CreateBackBuffer(hwnd);
		// MessageBox(hwnd, "TEXT", "caption", MB_OK);
		 return 0;
	case WM_PAINT:
		if (paint_) {
			
			OnPaint(hwnd);
			paint_ = false;
		}
		
		return 0;
	
		
	case WM_CLOSE:
		is_running = false;
		return 0;
	default:
		return DefWindowProc(hwnd, message, w_param, l_param);
	}

}

bool BaseWindow::MessagePoll() {

	

	// Counts Per Second
	
	QueryPerformanceFrequency((LARGE_INTEGER*)&counts_per_sec);
	// Seconds Per Count
	float sec_per_count = 1.0f / counts_per_sec;
	// Pervious Time
	
	QueryPerformanceCounter((LARGE_INTEGER*)&prev_time);

	MSG message = {};
	
	PeekMessage(&message,hwnd_, 0, 0,PM_REMOVE);
			

			
		
		
			// Get current count
			
			QueryPerformanceCounter((LARGE_INTEGER*)&current_time);
			// DeltaTime
			delta_time = (current_time - prev_time) * sec_per_count;

			
			elapsed_time += delta_time;
			
			// Render
			if (delta_time > 0.00002f)
			{
				
				Update();
				paint_ = true;
				InvalidateRect(hwnd_, NULL, false);
				CalculateFPS();
			}
			prev_time = current_time;
		
			

			TranslateMessage(&message);
			DispatchMessage(&message);
		return is_running;
	}



void BaseWindow::CalculateFPS() {

	

	frame_count++;
	

	// Frams Per Second
	if (elapsed_time >= 1.0f) {
		fps_ = frame_count;

		// Output to Window Title
		std::stringstream ss;
		ss << window_name_ << " FPS " << fps_;
		SetWindowText(hwnd_, ss.str().c_str());

		frame_count = 0;
		elapsed_time = 0.0f;
	}
}

#pragma region Handles

bool BaseWindow::CreateBackBuffer(HWND hwnd) {

	GetClientRect(hwnd, &window_rect_);
	client_width_ = window_rect_.right;
	client_height_ = window_rect_.bottom;

	hdc_ = GetDC(hwnd);	// Get the Device Context

	back_buffer_ = CreateCompatibleDC(hdc_);	// Create Back Buffer
	bitmap_ = CreateCompatibleBitmap(hdc_,client_width_, client_height_);
	
	
	SelectObject(back_buffer_, bitmap_);	// Select Bitmap

	

	return true;
}

bool BaseWindow::OnPaint(HWND hwnd) {

	PAINTSTRUCT paintstruct;

	hdc_ = BeginPaint(hwnd_, &paintstruct);		// Get the Device Context

	
	// Paint
	Render();
	
	BitBlt(hdc_, 0, 0,client_width_,client_height_,back_buffer_,0,0,SRCCOPY);		// Display the back buff
	

	EndPaint(hwnd, &paintstruct);
	
	return true;
}
void BaseWindow::Update()
{
	

	if (direction == 1)
	{
		rectX = rectX-1;
		if (rectX < 100)
		{direction = 0;}
	}
	else 
	{
		rectX = rectX + 1;
	}

	if (rectX > 300)
	{
		direction = 1;
	}
}
void BaseWindow::Render() {

	
	BitBlt(back_buffer_, 0, 0, client_width_, client_height_, NULL, NULL, NULL, WHITENESS);
	HBRUSH brush = (HBRUSH)(CreateSolidBrush(RGB(255,0,0)));
	SelectObject(back_buffer_, brush);		// Select Brush

	Rectangle(back_buffer_, rectX, rectY, rectX+100,rectY+100);

	DeleteObject(brush);

	

}



#pragma endregion



As you can now see animating something in gdi is not great its a bit slow in the rendering.

But as it stands its the best I can do with the way you have designed the classes and the rest of the program like the unnecessary functions that are only used once etc...

You are very lucky I was bored !

Snoopy.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1