|
This thread is locked; no one can reply to it. |
1
2
|
[A5] Threading a game |
J-Gamer
Member #12,491
January 2011
|
I have been trying to wrap my head around threads and I have come up with two questions: Also, according to this thread, threading can make modularising your application way easier if you got the mutexes right. Did I understand that correctly? Any help? " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
weapon_S
Member #7,859
October 2006
|
1. Send them all to a 'global' queue. "Listening" is a big word. I don't know what the link is about. Just fiddle around until you understand it |
J-Gamer
Member #12,491
January 2011
|
weapon_S said: Send them all to a 'global' queue. How do you mean? What I thought of doing was having an event queue in a data class(where you can put a mutex on) and sending costum events to it so that the parent thread can get informed about what happened. Example of usage: " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
Thomas Fjellstrom
Member #476
June 2000
|
Yes, I believe event queues were explicitly designed to be thread safe. So you can send events from one thread and receive events in another. -- |
J-Gamer
Member #12,491
January 2011
|
I just came up with this to let this happen: Is my logic sound/should this work? " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
Thomas Fjellstrom
Member #476
June 2000
|
Yup, though you may also have the option of emitting fake input events. Which ever works best for your case. -- |
J-Gamer
Member #12,491
January 2011
|
I think the AI will want to just say what he wants to do, instead of faking a mouse click or something like that. I'm also thinking of putting user input in another thread with the same principle: as soon as the player really chooses to send a unit(scout,bomb,other upgrade) to the field, the main thread will be noticed trough a user event. " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
Thomas Fjellstrom
Member #476
June 2000
|
Some people prefer to simulate input events for AI, so it can be recorded in the same way user input is recorded, for replays, save games, and cheat detection. But I think if you're emitting user events for the player as well, you can use those to do all that instead of raw input. -- |
J-Gamer
Member #12,491
January 2011
|
Yeah... I think it is easier to let the user input thread figure out what the user wants to do and then send the corresponding event to the main thread. Otherwise, I would have to put extra code in at the AI output part to calculate all the coordinates of mouse clicks etc. One technical question that still hasn't been answered: How do I make a function pointer to a member function? Because that's what I'll need if I want to use the AI's Think() function as main function of the thread. " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
Edgar Reynaldo
Major Reynaldo
May 2007
|
J-Gamer said: 2. Is it possible to use functions of an object as the main function of a thread? I could than have a AI::Think function which would try to find the other player's cannons etc. Yes, you can use class methods, they just have to be static, and you have to bind the parameters somehow. 1
2class ArgumentBinder {
3private :
4 int p1;
5 Data* d;
6public :
7 static void Process(ALLEGRO_THREAD* thread , void* this) {
8 ((ArgumentBinder*)this)->ClassMethod();
9 }
10
11 void ClassMethod() {
12 // do stuff with members
13 }
14}
15
16ArgumentBinder bound_data;
17ALLEGRO_THREAD* thread = al_create_thread(ArgumentBinder::Process , &bound_data);
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
J-Gamer
Member #12,491
January 2011
|
Thanks! I'll try that. EDIT: 1#ifndef __THREADED_H__
2#define __THREADED_H__
3class Threaded;
4
5class ThreadedData
6{
7 public:
8 ALLEGRO_MUTEX* mutex;
9 ALLEGRO_COND* cond;
10 bool ready;
11 Threaded* thr; //used in Threaded::InitThread
12 ThreadedData() : mutex(al_create_mutex()),cond(al_create_cond()),ready(false);
13};
14
15class Threaded
16{
17 private:
18 public:
19 static void InitThread(ALLEGRO_THREAD* thr, void* data)
20 {
21 (ThreadedData*)data->thr->Thread_function((ThreadedData*)data);
22 };
23 virtual void Thread_function(ALLEGRO_THREAD* thr,ThreadedData* data) {};
24};
25#endif
These are classes you should derive from, like this: 1class ThreadedUIData : public ThreadedData
2{
3 public:
4 //other variables you need to be shared between your class and the parent thread
5};
6
7class ThreadedUI : public ThreadedData
8{
9 private:
10 ALLEGRO_EVENT_QUEUE* event_queue;
11
12 public:
13 void Thread_function(ALLEGRO_THREAD* thr,ThreadedData* data);
14};
15
16void ThreadedUI::Thread_function(ALLEGRO_THREAD* thr, ThreadedData* data)
17{
18 //initialize variables
19 event_queue = al_create_event_queue();
20 al_register_event_source(event_queue,al_get_mouse_event_source());
21 al_register_event_source(event_queue,al_get_keyboard_event_source());
22
23
24 al_lock_mutex(data->mutex);
25 ThreadedUIData* ui_data = (ThreadedUIData*)data;
26 //do something with the fields of ThreadedUIData* ui_data
27 al_signal_cond(data->cond);
28 data->ready = true;
29 al_unlock_mutex(data->mutex);
30
31 //main thread loop
32 while(!al_thread_should_stop(thr))
33 {
34 //check the event queue for input events and send a costum event if something important has been selected
35 }
36};
Or am I doing something terribly wrong here? " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
BAF
Member #2,981
December 2002
|
Thomas Fjellstrom said: Some people prefer to simulate input events for AI, so it can be recorded in the same way user input is recorded, for replays, save games, and cheat detection. Err, what? I've never heard of that before. Even if you did do that, how would you prevent the user input from affecting the AI player? |
Arthur Kalliokoski
Second in Command
February 2005
|
IIRC that's how they did it in Quake, all actors have the same input interface, some are controlled by AI. They all watch too much MSNBC... they get ideas. |
Thomas Fjellstrom
Member #476
June 2000
|
BAF said: Even if you did do that, how would you prevent the user input from affecting the AI player? The AI is essentially just another player with access to no more control or information as the player is. -- |
BAF
Member #2,981
December 2002
|
Okay, but why would you simulate input events? How would you prevent the user from making those same inputs, thereby screwing wth the AI? |
Arthur Kalliokoski
Second in Command
February 2005
|
The "inputs" to an actor are just software interfaces, not actually hardwired to the mouse or anything. They all watch too much MSNBC... they get ideas. |
BAF
Member #2,981
December 2002
|
Yes, but TF was talking about emitting fake input events. If you're faking input events to control the AI, then it looks the same as normal input events. |
Arthur Kalliokoski
Second in Command
February 2005
|
The AI actors inputs are sent "events" by the AI. Your protagonist actor is sent "events" from the mouse and keyboard, etc. Think of a computer controlled car that has servos hooked to the steering wheel and pedals, and you're not in it. You race this car by driving another car normally. They all watch too much MSNBC... they get ideas. |
Thomas Fjellstrom
Member #476
June 2000
|
BAF said: Yes, but TF was talking about emitting fake input events. If you're faking input events to control the AI, then it looks the same as normal input events. Depends. If you went that low level, you could simulate a second mouse/keyboard. But "Input Events" does not necessarily mean low level input events. But yeah, if Allegro doesn't have a way to distinguish between multiple low level input devices, that would make it difficult to go that low level. -- |
BAF
Member #2,981
December 2002
|
Yes, I understand. I am questioning TF's solution of handling threading by putting fake input events into the queue from the other thread. |
Matthew Leverton
Supreme Loser
January 1999
|
This: Thomas Fjellstrom said: But "Input Events" does not necessarily mean low level input events It's not a very hard concept to grasp. |
BAF
Member #2,981
December 2002
|
The original description was ambiguous at best, and that was what I was referring to. I understand the intended meaning... Thomas Fjellstrom said: Some people prefer to simulate input events for AI, so it can be recorded in the same way user input is recorded, for replays, save games, and cheat detection. |
Trent Gamblin
Member #261
April 2000
|
I don't think you would put them on the same queue. For example, you could have an Entity class that has a ALLEGRO_EVENT *GetInput(void) method that could return ALLEGRO_EVENTS like key presses and releases and the "Game" class would handle them. Then you can do things like: for (i = 0; i < num_entities; i++) { ALLEGRO_EVENT *e = entity[i]->GetInput(); if (e) { if (e->type == ALLEGRO_EVENT_KEYBOARD) { switch (e->keyboard.keycode) { ... } } } } And you could have some typedef: typedef ALLEGRO_EVENT *(input_getter)(void); Then your player class could have private:
input_getter input;
And when you wanted to change input you could just set 'input' to PhysicalInput(), ScriptInput(), NoInput() or whatever. None of this really relies on using ALLEGRO_EVENTs though. But generally having a standard interface to get input from can be useful.
|
Thomas Fjellstrom
Member #476
June 2000
|
BAF said: The original description was ambiguous at best, and that was what I was referring to. I understand the intended meaning... It was meant to cover both low level injecting, and using higher level events, but both would still be input simulation as far as the engine is concerned. -- |
J-Gamer
Member #12,491
January 2011
|
Bugfix: The code I posted had 2 errors, which are fixed in this renewed code: 1#ifndef __THREADED_H__
2#define __THREADED_H__
3class Threaded;
4
5class ThreadedData
6{
7 public:
8 ALLEGRO_MUTEX* mutex;
9 ALLEGRO_COND* cond;
10 bool ready;
11 Threaded* thr; //used in Threaded::InitThread
12 ThreadedData() : mutex(al_create_mutex()),cond(al_create_cond()),ready(false) {};
13};
14
15class Threaded
16{
17 private:
18 public:
19 static void InitThread(ALLEGRO_THREAD* thr, void* data)
20 {
21 ((ThreadedData*)data)->thr->Thread_function(thr,(ThreadedData*)data);
22 };
23 virtual void Thread_function(ALLEGRO_THREAD* thr,ThreadedData* data) = 0;
24};
25
26class ThreadedUIData : public ThreadedData
27{
28 public:
29 //other variables you need to be shared between your class and the parent thread
30};
31
32class ThreadedUI : public ThreadedData
33{
34 private:
35 ALLEGRO_EVENT_QUEUE* event_queue;
36
37 public:
38 void Thread_function(ALLEGRO_THREAD* thr,ThreadedData* data);
39};
40
41void ThreadedUI::Thread_function(ALLEGRO_THREAD* thr, ThreadedData* data)
42{
43 //initialize variables
44 event_queue = al_create_event_queue();
45 al_register_event_source(event_queue,al_get_mouse_event_source());
46 al_register_event_source(event_queue,al_get_keyboard_event_source());
47
48
49 ThreadedUIData* ui_data = (ThreadedUIData*)data;
50 al_lock_mutex(ui_data->mutex);
51 //do something with the fields of ThreadedUIData
52 ui_data->ready = true;
53 al_signal_cond(ui_data->cond);
54 al_unlock_mutex(ui_data->mutex);
55
56 //main thread loop
57 while(!al_get_thread_should_stop(thr))
58 {
59 //do stuff
60 }
61};
62
63#endif
EDIT: about input, I'm thinking of making costum events for using upgrades(scout,bomb,tunneler,...) so that those can be sent to the main game logic thread instead of raw input. I'll let the UI thread find out which upgrade the player wants to place where.(High-level input FTW ) EDIT2: Are allegro calls thread-safe?(Like al_get_display_width/height,...) " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
|
1
2
|