Acessing same class object throughout whole game.

The Partridge Family were neither partridges nor a family. Discuss.
NaturalDemon
Posts: 97
Joined: October 28th, 2012, 8:28 pm

Re: Acessing same class object throughout whole game.

Post by NaturalDemon » November 9th, 2012, 4:12 pm

i´m trying another aproach.

i´m using threads and callbacks and each of the "intelligent" objects has it's own while loop.

http://www.tek-tips.com/viewthread.cfm?qid=1068278

Code: Select all

static DWORD _stdcall SomeClass::NewThread(void *param)
{
   SomeClass* self = (SomeClass*) param;
   return self->NewThread ();
}

SomeClass::SomeClass()
{
    ....code....
    hThread=CreateThread (NULL, 0, SomeClass::NewThread, this, 0, &dwThreadID));
}

// This is called from the static function and has no parameters
DWORD SomeClass::NewThread ()
{
   while(true)
    {
     .
     ..
     ...
     }
   return whatever;
}


};
more info:
http://www.codeguru.com/cpp/w-d/dislog/ ... erview.htm


http://msdn.microsoft.com/en-us/library ... s.85).aspx <--- correced link
(this example show how to pass initial arguments/parameters to a thread funcion, but you need to upper example using the (this) parameter to run a class itßs it own thread.

Code: Select all

#include <windows.h>
#include <tchar.h>
#include <strsafe.h>

#define MAX_THREADS 3
#define BUF_SIZE 255

DWORD WINAPI MyThreadFunction( LPVOID lpParam );
void ErrorHandler(LPTSTR lpszFunction);

// Sample custom data structure for threads to use.
// This is passed by void pointer so it can be any data type
// that can be passed using a single void pointer (LPVOID).
typedef struct MyData {
    int val1;
    int val2;
} MYDATA, *PMYDATA;


int _tmain()
{
    PMYDATA pDataArray[MAX_THREADS];
    DWORD   dwThreadIdArray[MAX_THREADS];
    HANDLE  hThreadArray[MAX_THREADS]; 

    // Create MAX_THREADS worker threads.

    for( int i=0; i<MAX_THREADS; i++ )
    {
        // Allocate memory for thread data.

        pDataArray[i] = (PMYDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
                sizeof(MYDATA));

        if( pDataArray[i] == NULL )
        {
           // If the array allocation fails, the system is out of memory
           // so there is no point in trying to print an error message.
           // Just terminate execution.
            ExitProcess(2);
        }

        // Generate unique data for each thread to work with.

        pDataArray[i]->val1 = i;
        pDataArray[i]->val2 = i+100;

        // Create the thread to begin execution on its own.

        hThreadArray[i] = CreateThread( 
            NULL,                   // default security attributes
            0,                      // use default stack size  
            MyThreadFunction,       // thread function name
            pDataArray[i],          // argument to thread function 
            0,                      // use default creation flags 
            &dwThreadIdArray[i]);   // returns the thread identifier 


        // Check the return value for success.
        // If CreateThread fails, terminate execution. 
        // This will automatically clean up threads and memory. 

        if (hThreadArray[i] == NULL) 
        {
           ErrorHandler(TEXT("CreateThread"));
           ExitProcess(3);
        }
    } // End of main thread creation loop.

    // Wait until all threads have terminated.

    WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);

    // Close all thread handles and free memory allocations.

    for(int i=0; i<MAX_THREADS; i++)
    {
        CloseHandle(hThreadArray[i]);
        if(pDataArray[i] != NULL)
        {
            HeapFree(GetProcessHeap(), 0, pDataArray[i]);
            pDataArray[i] = NULL;    // Ensure address is not reused.
        }
    }

    return 0;
}


DWORD WINAPI MyThreadFunction( LPVOID lpParam ) 
{ 
    HANDLE hStdout;
    PMYDATA pDataArray;

    TCHAR msgBuf[BUF_SIZE];
    size_t cchStringSize;
    DWORD dwChars;

    // Make sure there is a console to receive output results. 

    hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    if( hStdout == INVALID_HANDLE_VALUE )
        return 1;

    // Cast the parameter to the correct data type.
    // The pointer is known to be valid because 
    // it was checked for NULL before the thread was created.
 
    pDataArray = (PMYDATA)lpParam;

    // Print the parameter values using thread-safe functions.

    StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d\n"), 
        pDataArray->val1, pDataArray->val2); 
    StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);
    WriteConsole(hStdout, msgBuf, (DWORD)cchStringSize, &dwChars, NULL);

    return 0; 
} 



void ErrorHandler(LPTSTR lpszFunction) 
{ 
    // Retrieve the system error message for the last-error code.

    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError(); 

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );

    // Display the error message.

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
        (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 40) * sizeof(TCHAR)); 
    StringCchPrintf((LPTSTR)lpDisplayBuf, 
        LocalSize(lpDisplayBuf) / sizeof(TCHAR),
        TEXT("%s failed with error %d: %s"), 
        lpszFunction, dw, lpMsgBuf); 
    MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK); 

    // Free error-handling buffer allocations.

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
}

the Game class is on top of other classes and the Game class has easy acces subclasses ... but it's harder for the subclass to acces to top class ... that's is why you need a callback to send a message back up.
So the callback from the Enemy class fires in the Game class and from there you can send a message to any subclass again.
the tread stuff isn't that hard ... my enemy pixel follows the mouse autonomously (hence it´s own while loop) .... but i still need input on how to creatre stuff (classes) dynamic ... old enemies die and new appear.

about the asset folder ... i did spend some time looking the project settings and open the *.vproj in notepad to see if anything can be adjusted there ... but only briefly ... and sofar i ddn't see anything that could be adjusted easily.
Last edited by NaturalDemon on December 16th, 2012, 1:41 am, edited 1 time in total.

cameron
Posts: 794
Joined: June 26th, 2012, 5:38 pm
Location: USA

Re: Acessing same class object throughout whole game.

Post by cameron » November 9th, 2012, 10:27 pm

I dont quite understand what your saying. But I was going to try to make my game with linked lists but I was having problems with class objects so im not sure what to do Ill upload what I tryed to do and failed.
Computer too slow? Consider running a VM on your toaster.

cameron
Posts: 794
Joined: June 26th, 2012, 5:38 pm
Location: USA

Re: Acessing same class object throughout whole game.

Post by cameron » November 10th, 2012, 4:42 pm

Here is what I tried to do.
Attachments
new - Copy (2).rar
(794.68 KiB) Downloaded 144 times
Computer too slow? Consider running a VM on your toaster.

NaturalDemon
Posts: 97
Joined: October 28th, 2012, 8:28 pm

Re: Acessing same class object throughout whole game.

Post by NaturalDemon » November 11th, 2012, 1:14 pm

cameron wrote:I dont quite understand what your saying.
you need to read about delegates/callback's and obey the "class hierarchy".
a class initiated in the game object is a sister class.

[img]
http://www.ccs.neu.edu/research/demeter ... Image1.gif
[/img]
Mamal can´t send a message to Oviparous, it doesn´t know it's there .. but Animal does.
you have to relay all the message via Animal

the Game class can send messages to any sister class ... provided you made those functions or public variables.

i.e. enemy::GetPosition()

the sister class can´t send any messages back to it's "host".
but with a callback/delegate you can send a message back.

but with the use of a callback in case of an event in the sister class
you can trigger a function in the host class and making inter comunication possible.
http://www.functionx.com/vcnet/topics/delevents.htm

http://www.codeguru.com/cpp/cpp/cpp_mfc ... torial.htm

http://www.codeproject.com/Articles/123 ... ks-and-thr

for example:
in my setup ... my enemy has it's own loop(thread), just like the windows class above of the game class that triggers the Game::go() function millions of times a second.
If you put all the logic in the Game::go() function .... it wil get very complex and still do one thing after another.
So the if you have 10 enemy on the screen moving around ... (think in slow motion) ... if the enemies are moving enemy 1 would advance 1 pixel .. then check if there is a colision .. then enemy 2 would advance one pixel .. then check if there is a colision and ... so on ... perfecly in SYNC ... but that is not what you want ... limiting your program .... hence being mono thread.
Every programming language works from top to bottom ... line for line ... accept assembler in some what fashion.

Code: Select all

game::Go()
{
... (cpu cycle/tik)
... (cpu cycle/tik)
... (cpu cycle/tik)
}
With the use of Threads you can use the second core or whatever number of cores you have on your CPU ( that's not exacly true ... but .. close).
effectively doing multiple calculations @ the same time.

So the enemy object has it's own intelligence ( it's own while loop one you program) ... so itself can move, attack, check if it colided against a wall or other object.
If so ... it can send a message back to it's host class via a delegate / callback (Asynchronous programming) ... hey ... i colided!

you realy need to use threads.
if you where a winform programmer and you start a task that's takes a lot of cpu power and takes time to complete ... and no thread use ... the entire program would be useless waste of effort and time ... because the task takes up all the recources and USER INTERFACE will FREEZE (no button, menu or anything else will react to mouse hover or clicks) and not do anything until the task wil complete and you might even stop the program via the windows task mannager because you think the program crashed/bugged.
Also there entire program wil come to a halt .. when you move the window around the desktop.

i suggest you also peer into ...
C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Samples\SampleBrowser --> SampleBrowser.exe and check out some tuts.

Chili say's .. it's all about numbers ...but also about loops ....
even Windows is a LOOP ....

try the fupper code in previous post and see for yourself ... it works

NaturalDemon
Posts: 97
Joined: October 28th, 2012, 8:28 pm

Re: Acessing same class object throughout whole game.

Post by NaturalDemon » November 11th, 2012, 6:21 pm

i think ... after a few days of reading ... i found a solution!

http://www.codeguru.com/cpp/cpp/cpp_mf ... Class.htm

main.cpp

Code: Select all

//By Slavko Novak november 2002

#include <stdio.h>
#include "ClassWithEvents.h"

void myEvent(int &iNum)
{
	printf("Value of property 'i' = %d.\n", iNum);	
}

void main(void)
{
	ClassWithEvents objClassWithEvents(myEvent);

	objClassWithEvents.set_i(4);
}
ClassWithEvents.cpp

Code: Select all

//By Slavko Novak november 2002

#include "ClassWithEvents.h"

ClassWithEvents::ClassWithEvents()
{
	this->iChange = 0L;
	this->i = 0;
}

ClassWithEvents::ClassWithEvents(void (*iChangeHandler)(int &))
{
	this->iChange = iChangeHandler;
	this->i = 0;

	// added by NaturalDemon
	test();
}

void ClassWithEvents::set_i(int iNum)
{
	this->i = iNum;
	
	if(this->iChange)
	{
		this->iChange(this->i);
	}
}

int ClassWithEvents::get_i(void)
{
	return this->i;
}

// added by NaturalDemon
// imagine this is your enemy's intelligence loop
void ClassWithEvents::test()
{
	int j = 0;
	while(true)
	{
		j++;
		this->set_i(j); // trigger a event(function) in the Game class
	}
}
ClassWithEvents.h

Code: Select all

//By Slavko Novak november 2002

#if !defined(_CLASS_WITH_EWENTS_)
#define _CLASS_WITH_EWENTS_


class ClassWithEvents
{
private:
	int i;
	void (*iChange)(int &);
public:
	ClassWithEvents();
	ClassWithEvents(void (*iChange)(int &));
	void set_i(int);
	int get_i(void);


	// added by NaturalDemon
	void test(void);
};

#endif

this is what you are searching for.


i hope Chili wil shed some view on it

cameron
Posts: 794
Joined: June 26th, 2012, 5:38 pm
Location: USA

Re: Acessing same class object throughout whole game.

Post by cameron » November 11th, 2012, 9:47 pm

So I need to use function pointers and references right? I'm rusty on those.
Computer too slow? Consider running a VM on your toaster.

NaturalDemon
Posts: 97
Joined: October 28th, 2012, 8:28 pm

Re: Acessing same class object throughout whole game.

Post by NaturalDemon » November 12th, 2012, 9:20 pm

http://thepiratebay.tn/thepiratebay.se/ ... ample_Code

Chapter 13: Using Pointers

or ...
Beginner C++ DirectX Game Programming Tutorial: Lesson 16 (from our good friend Chili)
http://www.youtube.com/watch?v=jnHFZf4Q9bM @ 1m29

Intermediate C++ DirectX Game Programming Tutorial: Lesson 3
http://www.youtube.com/watch?v=xtCAEWMx ... ure=relmfu

it's not that hard ... but just as chili says ... a kind of remote acces to previously created stuff ... or the originals.
(i knew about pointers, because i tried c++ several times and i dind't understand them ... before i saw chili's videos)

// use alot of comments in your code and make sure you do
// because ... and it happend to me ... after 6 months or so ... you don't even know what your
// own code does or means!

i'm not trying to be a prophet or something, but i just wanna help people ... doing it right!

Code: Select all

while( msg.message != WM_QUIT )
    {
        if( PeekMessage( &msg,NULL,0,0,PM_REMOVE ) )
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
        else
		{
			theGame.Go();
		}
    }
this is your main loop, without this loop the entire program wouildn't be possible.
It recieves messages from the Operation system windows X.
If there are no messages to dispatch ... it wil trigger the Go() function in the game class ...
the Go() function wil trigger a function you made, whom will trigger another function you made and maybe a gazillion more and finaly the putpixel(....) function (basicly ... like it say's ... a thread kinda structure).
@ some time your funcions wil get complex and take more time(cpu cycles) to execute ... until it finishes ... even the mainloop shown above ... is kinda frozen until your function is done.
Nothing wil go ... no mouse input or keyboard strokes ... totaly nothing!

Sure ... you can make a mono thread game, like probally 99% of the games on the forum here ... but a Call of Duty Modern warfare 3 type of game is totaly out of the question.
what i'm trying to say here ... before you actuall try to think of a game ... make sure the backend is done right!

if you put all the logic in the Go() function ... you have to ask yourself?
what about a new level in the game? ... and the tasks of the enemy, other animated objects in the scene ... etc, etc

I'm no c++ expert or whatever, but i do have 2 years of visual C# experience( and made some cash with it) and faced the same problem on winform programs ... and i rapidly found out ... you program is basicly a piece of #?!# ... without threads.
I'm just an electrician.

the past 2 days ... i basicly spend my time ... learning about callback/eevents in c++ ... downloading vs 2012 and vs 2010 on my mom's pc and updating it ... because i'm not @ home.
in the next few days ... i'll post an example on this thread to help on the way

i hope Chili wil make a video about events, delegate, callbacks and a video threads and threadsafety.
me needs some more input!
Last edited by NaturalDemon on November 12th, 2012, 11:45 pm, edited 1 time in total.

NaturalDemon
Posts: 97
Joined: October 28th, 2012, 8:28 pm

Re: Acessing same class object throughout whole game.

Post by NaturalDemon » November 12th, 2012, 11:45 pm

this program contains a endles loop and demostrates ... you should never code without threads ... try to push the stop task button or hover the mouse over the menu

Code: Select all

	static bool endlesloop = true;
	private: System::Void button_Start_Task_Click(System::Object^  sender, System::EventArgs^  e) {
				 int i = 0;
				 while(endlesloop)
				 {
					 i++; // some meaningless cpu load 
				 }
			 }
p.s. i was watching Mad Max and found out .. how to show you
Attachments
monothread.zip
(17.11 KiB) Downloaded 135 times

cameron
Posts: 794
Joined: June 26th, 2012, 5:38 pm
Location: USA

Re: Acessing same class object throughout whole game.

Post by cameron » November 13th, 2012, 2:45 am

Interesting. Are function pointers actually necessary for me to access the objects in my game right? Or are there other ways?
Computer too slow? Consider running a VM on your toaster.

indus
Posts: 35
Joined: November 7th, 2012, 12:35 am

Re: Acessing same class object throughout whole game.

Post by indus » November 17th, 2012, 6:42 pm

Ill try to give you an advice on your code and coding style.
First of all you should follow some naming conventions. http://en.wikipedia.org/wiki/Naming_con ... nd_C.2B.2B

It is a bit hard to read a code where class names and instances are both mixed lower and upper case.
One other thing I would advise you is to write small pieces of code and test them before going on with the coding. For example code your base and try drawing it. Than code the enemy base and try drawing it. Than code the marine and try drawing it. Than code the button and try drawing the marines when the mouse is over that button. In your code you call the SpawnMarine function and pass it the adress of marine but in the whole process till the end you never load the sprite for the marine.
I dont know if you have the same issue but when I ran your code and tried to place a break point somewhere in the compose frame function it never went inside it. It is a piece of code that never gets executed. I than used a fresh copy of chillis framework. Removed all the headers and cpp files from the project, deleted them from the Assert folder and copied the ones from your projects Assert folder there. Selected all of the files dragged and dropped them on the projects name and than everything worked fine.

Post Reply