|
More efficient way to capture mouse position? |
Mishtiff
Member #15,776
October 2014
|
Currently I am updating mouse positions whenever the mouse is moved: //prev ev.type code else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES) however this completely shuts off: if(render && al_is_event_queue_empty(event_queue)) whenever the mouse moves for a period of time. Is there a more efficient way of capturing the mouse location? The only time i need to save its location would be on right mouse click or a key press. UPDATE: I did find that if I use mouse_event_button_down it will save the data, but using the keyboard to save the data does not seem to work. |
pkrcel
Member #14,001
February 2012
|
Mishtiff said: Currently I am updating mouse positions whenever the mouse is moved If you need to value the mouse position against a specific coordinate (i.e. to check if it's on some GUI element) this is basically overkill. Quote: Well, that completely puts me a bit off...I guess you get a lot of stutter, but not a complete rendering stop. Quote: I did find that if I use mouse_event_button_down it will save the data, but using the keyboard to save the data does not seem to work. What does "using the keyboard to save the data" mean exactly? It is unlikely that Google shares your distaste for capitalism. - Derezo |
Mishtiff
Member #15,776
October 2014
|
pkrcel said: If you need to value the mouse position against a specific coordinate (i.e. to check if it's on some GUI element) this is basically overkill. Agreed, that is why i present the question. I suppose my problem is that I am unaware how i can save the mouse position when an event is calling for it outside of a ev.type == mouse_event pkrcel said: Well, that completely puts me a bit off...I guess you get a lot of stutter, but not a complete rendering stop. Yeah at the moment my coding needs some tweaking for efficiency. So if i constantly move the mouse in the display, the display never updates (since it is constantly updating the mouse_pos every single pixel. pkrcel said: What does "using the keyboard to save the data" mean exactly? example: 1if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
2{
3 switch(ev.keyboard.keycode)
4 {
5 case ALLEGRO_KEY_SPACE:
6 [SPACE] = true;
7 mousex = ev.mouse.x;
8 mousey = ev.mouse.y;
9 break;
10 }
11}
|
pkrcel
Member #14,001
February 2012
|
Mishtiff said: example: AH now I got it....uhm I guess it wouldn't work by design, since the trapped event is NOT related to the mouse, so (on windows, I suppose...but logically on every system oculd be like that) the trapped OS event message should not contain this info. This is my speculation of course, but I'm quite confident that you aren't expected to use the event mouse fields when trapping a keystroke.... I may stand corrected of course. On the other hand why would you do so? just curious...I might imagine but still... Anyway at any time you should be able to interrogate the mouse through the input API....lesseee.... I guess al_get_mouse_state should do for you. I suppose you example could read as if(ev.type == ALLEGRO_EVENT_KEY_DOWN){ switch(ev.keyboard.keycode){ case ALLEGRO_KEY_SPACE: [SPACE] = true; // I kind of like this syntax ^___^ ALLEGRO_MOUSE_STATE state; al_get_mouse_state(&state) mousex = state.x; mousey = state.y; break; } }
It is unlikely that Google shares your distaste for capitalism. - Derezo |
Elias
Member #358
May 2000
|
Can you show more code? A typical mouse shouldn't produce more events than say 1000 per second - I can't see how that would affect your rendering in any way even on the slowest and most ancient CPU. -- |
Mishtiff
Member #15,776
October 2014
|
pkrcel said:
1. On the other hand why would you do so?
1A. currently in the game i'm making, you move your ships to mouse_pos with the space bar(which i have now changed to the right click on mouse, making it much more simple...) 2A. this seems to be exactly what i am looking for. However, by the way you are talking it sounds like this is a bad way to go about it? Elias said: Can you show more code? of course. Ill post my code here soon. its pretty messy so let me clean it up and get some better comments into it. |
Thomas Fjellstrom
Member #476
June 2000
|
Mishtiff said: 2A. this seems to be exactly what i am looking for. However, by the way you are talking it sounds like this is a bad way to go about it? Store the mouse pos in the mouse events, then only move the ships when space is pressed. could have a next_shipx, next_shipy pair, and then only set the ship's coords after space is pressed? Quote: However, saving the mouse position every pixel movement was causing too many event calls and would shut down my rendering because of all the mouse updates. Mouse events alone won't case that to happen. Just store the mouse coords on mouse update. then once a "tick" (ie: timer tick) run your collision detection, not when ever the mouse is moved. -- |
pkrcel
Member #14,001
February 2012
|
Thomas Fjellstrom said: Mouse events alone won't case that to happen. Just store the mouse coords on mouse update. then once a "tick" (ie: timer tick) run your collision detection, not when ever the mouse is moved. This. Absolutely this. I didn't understand fully what was the problem here, and I didn't think it could be related to your other thread about Collision detection. But if you are running collision detection at each mouse axis event, THEN you're surely wasting a TON of CPU cycles (*even* if the collision detection is perfectly optimized). Why wasted? Because no object has yet moved when you process the events. On the other hand: Mishtiff said: 2A. this seems to be exactly what i am looking for. However, by the way you are talking it sounds like this is a bad way to go about it? Well, polling the state API while handling events is sort of double-defeating the purpose of both....BUT in this simple case it should work flawlessly so it might be good enuff. Nevertheless, Tomasu suggestion is the way to go in my opinion, store the mouse coords and use'em as a "next frame prediction". Quote: I am still trying to figure out how in the heck KD-Trees work. they are pretty confusing to me at the moment. So what i have done in my game is: At the very heart of the problem, what you have done is the SEED of space partitioning. I woudl say good job, nevertheless. It is unlikely that Google shares your distaste for capitalism. - Derezo |
Mishtiff
Member #15,776
October 2014
|
Thomas Fjellstromson said: Store the mouse pos in the mouse events, then only move the ships when space is pressed. could have a next_shipx, next_shipy pair, and then only set the ship's coords after space is pressed? this was my coding for the mouse update, so i dont see a reason for the slowdown to occur, yet it did: 1else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES)
2{
3 mousex = ev.mouse.x;
4 mousey = ev.mouse.y;
5}
Thomas Fjellstromson said: Mouse events alone won't case that to happen. Just store the mouse coords on mouse update. then once a "tick" (ie: timer tick) run your collision detection, not when ever the mouse is moved. I already run my collision detection only in the timer tick. I will just attach my code here and see if you guys can find what exactly is causing such dramatic slow downs. pkrcel said: This. Absolutely this. I didn't understand fully what was the problem here, and I didn't think it could be related to your other thread about Collision detection. But if you are running collision detection at each mouse axis event, THEN you're surely wasting a TON of CPU cycles (*even* if the collision detection is perfectly optimized). Why wasted? Because no object has yet moved when you process the events. yeah, but as i have stated above, it was not in the same block of code. pkrcel said: Well, polling the state API while handling events is sort of double-defeating the purpose of both....BUT in this simple case it should work flawlessly so it might be good enuff. Nevertheless, Tomasu suggestion is the way to go in my opinion, store the mouse coords and use'em as a "next frame prediction". ok i understand, and it is beginning to sound like it is due to my coding that is more of the problem, rather than the updating and saving of the mouse coords. pkrcel said:
At the very heart of the problem, what you have done is the SEED of space partitioning. I woudl say good job, nevertheless. Thank you, i was pretty happy with how my old collision detection worked. i have, however, found an amazing post with a |
pkrcel
Member #14,001
February 2012
|
....a cliffhanger? It is unlikely that Google shares your distaste for capitalism. - Derezo |
Trent Gamblin
Member #261
April 2000
|
I wouldn't use that code. Use: while (!al_event_queue_is_empty()) { // process events } if (render) { // render } Otherwise you could skip a frame sometimes, even if it's just 1 it's not right.
|
Mishtiff
Member #15,776
October 2014
|
pkrcel said: ....a cliffhanger? I guess it cut out the rest of what i wrote... What i had said was: Thank you, i was pretty happy with how my old collision detection worked. i have, however, found an amazing post with a adaptive quadtree. I think i have implemented it well, im just unsure if i am using it efficiently. Ill let you be the judge. Trent Gamblin said:
while (!al_event_queue_is_empty()) { if (render) { Where am i supposed to put this? in the timer tick? that doesnt make sense to me, sorry. |
Edgar Reynaldo
Major Reynaldo
May 2007
|
Mishtiff said:
Trent Gamblin said:
while (!al_event_queue_is_empty()) { if (render) { Where am i supposed to put this? in the timer tick? that doesnt make sense to me, sorry. No put it around your event processing loop. do { if (ev.type == ALLEGRO_EVENT_*_*) {/*...do stuff...*/} } while (!al_is_event_queue_empty(queue)); if (render) {draw();render = false;}
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 |
Mishtiff
Member #15,776
October 2014
|
Okay i have put it around all of my event queues, but it is not drawing any frames now. probably because by the time it makes it through all of the events in timer.tick, it already has a timer.tick in the queue? heres what it looks like: 1while(!done)
2 {
3 ALLEGRO_EVENT ev;
4 al_wait_for_event(event_queue, &ev);
5
6 //==============================================
7 //INPUT
8 //==============================================
9 do {
10 if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
11 {
12 switch(ev.keyboard.keycode)
13 {
14 case ALLEGRO_KEY_ESCAPE:
15 done = true;
16 break;
17 case ALLEGRO_KEY_A:
18 keys[A] = true;
19 break;
20 case ALLEGRO_KEY_D:
21 keys[D] = true;
22 break;
23 case ALLEGRO_KEY_W:
24 keys[W] = true;
25 break;
26 case ALLEGRO_KEY_S:
27 keys[S] = true;
28 break;
29 case ALLEGRO_KEY_SPACE:
30 if(state == TITLE)
31 ChangeState(state, PLAYING);
32 else if(state == PLAYING)
33 {
34 keys[SPACE] = true;
35 }
36 else if(state == LOST)
37 ChangeState(state, PLAYING);
38 break;
39 }
40 }
41 else if(ev.type == ALLEGRO_EVENT_KEY_UP)
42 {
43 switch(ev.keyboard.keycode)
44 {
45 case ALLEGRO_KEY_ESCAPE:
46 done = true;
47 break;
48 case ALLEGRO_KEY_A:
49 keys[A] = false;
50 break;
51 case ALLEGRO_KEY_D:
52 keys[D] = false;
53 break;
54 case ALLEGRO_KEY_W:
55 keys[W] = false;
56 break;
57 case ALLEGRO_KEY_S:
58 keys[S] = false;
59 break;
60 case ALLEGRO_KEY_SPACE:
61 keys[SPACE] = false;
62 break;
63 }
64 }/*
65 else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN)
66 {
67 keys[SPACE] = true;
68 mousex = ev.mouse.x;
69 mousey = ev.mouse.y;
70 }
71 else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP)
72 {
73 keys[SPACE] = false;
74 }*/
75 else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES)
76 {
77 mousex = ev.mouse.x;
78 mousey = ev.mouse.y;
79 }
80 //==============================================
81 //GAME UPDATE
82 //==============================================
83 else if(ev.type == ALLEGRO_EVENT_TIMER)
84 {
85 render = true;
86 quad->Clear();
87
88 //UPDATE FPS===========
89
90 //=====================
91
92 if(state == PLAYING)
93 {
94 if(al_current_time() - gameTime >= 1)
95 {
96 gameTime = al_current_time();
97 gameFPS = frames;
98 frames = 0;
99 }
100
101
102 //Spawn More Ships
103 spawner++;
104 if (spawner >= 60)
105 {
106 for(Baseiter = Bases.begin(); Baseiter != Bases.end(); ++Baseiter)
107 {
108 if((*Baseiter)->GetShipCount() > 9) continue; //increase this number to spawn more ships
109 Ship *ship = new Ship();
110 ship->Init();
111 ship->SetPlayerID((*Baseiter)->GetPlayerID());
112 ship->SetX(rand() % 40 + (*Baseiter)->GetX() - 20);
113 ship->SetY(rand() % 40 + (*Baseiter)->GetY() - 20);
114 ship->SetColor((*Baseiter)->GetColor());
115
116 (*Baseiter)->SetShipCount(1); //increase base ship count
117 objects.push_back(ship); //add ship to objects and to ships
118 ships.push_back(ship);
119 }
120 spawner = 0;
121 }
122
123 //used to upgrade ships (VERY BASIC----later will be used after leveling)
124 if(keys[SPACE]) //used to move ships to location of mouse
125 {
126
127 for(Shipiter = ships.begin(); Shipiter != ships.end(); ++Shipiter)
128 {
129 if((*Shipiter)->GetPlayerID() != 1) continue;
130 (*Shipiter)->SetDestX(mousex);
131 (*Shipiter)->SetDestY(mousey);
132 (*Shipiter)->setMoving(true);
133 }
134 }
135 if(keys[W]) //increase ship speed
136 {
137
138 for(Shipiter = ships.begin(); Shipiter != ships.end(); ++Shipiter)
139 {
140 if((*Shipiter)->GetPlayerID() != 1) continue;
141 (*Shipiter)->setSpeed(.05);
142 }
143 }
144
145 if(keys[S]) //increase ship damage
146 {
147
148 for(Shipiter = ships.begin(); Shipiter != ships.end(); ++Shipiter)
149 {
150 if((*Shipiter)->GetPlayerID() != 1) continue;
151 (*Shipiter)->setAttack(5);
152 }
153 std::cout << std::endl;
154 }
155
156 if(keys[A]) //increase ship range
157 {
158
159 for(Shipiter = ships.begin(); Shipiter != ships.end(); ++Shipiter)
160 {
161 if((*Shipiter)->GetPlayerID() != 1) continue;
162 (*Shipiter)->setRange(5);
163 }
164 std::cout << std::endl;
165 }
166
167 if(keys[D]) //increase ship health
168 {
169
170 for(Shipiter = ships.begin(); Shipiter != ships.end(); ++Shipiter)
171 {
172 if((*Shipiter)->GetPlayerID() != 1) continue;
173 (*Shipiter)->setHealth(5);
174 }
175 std::cout << std::endl;
176 }
177
178
179 //Update objects positions/animations and add to quad tree.
180 for(iter = objects.begin(); iter != objects.end(); ++iter)
181 {
182 (*iter)->Update();
183 if((*iter)->GetID() == BASE) continue;
184 quad->AddObject(*iter);
185 }
186
187 //used for collision detection (if this is even somewhat correct) //At the moment, i just randomly move units until there is no collision
188 for(iter = objects.begin(); iter != objects.end(); ++iter)
189 {
190 if((*iter)->GetID() == BASE) continue;
191 vector<GameObject*> returnedObjects;
192 returnedObjects = quad->GetObjectsAt((*iter)->GetX(), (*iter)->GetY());
193 if(returnedObjects.size() < 2) continue;
194 for(int i = 0; i != returnedObjects.size(); i++)
195 {
196 if((*iter) == returnedObjects[i]) continue;
197 if((*iter)->CheckCollisions(returnedObjects[i]))
198 {
199 returnedObjects[i]->SetX(returnedObjects[i]->GetX() + (-5 + rand() % 10));
200 returnedObjects[i]->SetY(returnedObjects[i]->GetY() + (-5 + rand() % 10));
201 }
202 }
203 }
204
205
206
207
208 //cull the dead
209 for(Shipiter = ships.begin(); Shipiter != ships.end(); )
210 {
211 if(!(*Shipiter)->GetAlive())
212 {
213 Shipiter = ships.erase(Shipiter); //remove from ships
214 }
215 else
216 Shipiter++;
217 }
218 for(iter = objects.begin(); iter != objects.end(); ) //remove from objects and give credit to base that killed
219 {
220 if(! (*iter)->GetAlive())
221 {
222 if((*iter)->GetID() == SHIP)
223 {
224 int id = (*iter)->GetPlayerID();
225 for(Baseiter = Bases.begin(); Baseiter != Bases.end(); Baseiter++)
226 {
227 if((*Baseiter)->GetPlayerID() == id)
228 {
229 (*Baseiter)->SetShipCount(-1);
230 int killer = (*iter)->GetShipKiller();
231 for(Baseiter2 = Bases.begin(); Baseiter2 != Bases.end(); )
232 {
233 if((*Baseiter2)->GetPlayerID() == killer)
234 {(*Baseiter2)->setScore(1); break;}
235 else
236 Baseiter2++;
237 }
238 break;
239 }
240 }
241
242 }
243 (*iter)->Destroy();
244 delete (*iter);
245 iter = objects.erase(iter);
246
247 }
248 else
249 iter++;
250 }
251 }
252 }
253 } while (!al_is_event_queue_empty(event_queue));
254
255
256 //==============================================
257 //RENDER
258 //==============================================
259
260 if(render)
261 {
262 render = false;
263 frames++;
264
265
266 //BEGIN PROJECT RENDER================
267 if(state ==TITLE)
268 {}
269 else if(state == PLAYING)
270 {
271 al_draw_textf(font18, al_map_rgb(255, 0, 255), 5, 35, 0, "FPS: %i mouse: %f,%f", gameFPS, mousex, mousey); //display FPS on screen
272
273
274
275 for(iter = objects.begin(); iter != objects.end(); ++iter)
276 (*iter)->Render();
277
278 //quad->draw(); //used to draw visual for quadrants
279 }
280 else if(state == LOST)
281 {}
282
283 //FLIP BUFFERS========================
284 al_flip_display();
285 al_clear_to_color(al_map_rgb(0,0,0));
286 }
287 }
EDIT:: Trent Gamblin said: The al_wait_for_event should be in the do-while loop too, otherwise if there are any events in the queue that loop will never end because they never get removed. This corrected the problem. Going to see how it runs now if i add more units. |
Trent Gamblin
Member #261
April 2000
|
The al_wait_for_event should be in the do-while loop too, otherwise if there are any events in the queue that loop will never end because they never get removed.
|
Mishtiff
Member #15,776
October 2014
|
After changing the code to what we have discussed, it freezes at loading ~9-10 units. I checked to see the amount of time it takes for the code to run through the timer.tick part, and it takes around ~.005. im running the game at 60 fps, which means the timer should be every .0166. not sure what is going on to make it stop rendering. ill try to add some std::cout to see why it is not reaching the render state. EDIT:: after checking, it seems that the game gets stuck with the al_is_event_queue_empty(). After 9 to 10 units have been spawned per base (90-100 ships) the game stays in the do while loop |
Trent Gamblin
Member #261
April 2000
|
Ok, what you want to do is use al_get_next_event instead of al_wait_for_event. Something like I had posted before: while (!al_event_queue_is_empty(queue)) { ALLEGRO_EVENT event; al_get_next_event(queue, &event); // process your events } Change your do-while loop to this while loop.
|
Mishtiff
Member #15,776
October 2014
|
Trent Gamblin said: Ok, what you want to do is use al_get_next_event instead of al_wait_for_event. Something like I had posted before: This makes a lot of sense, thank you. Ill mess around some more now that it is running correctly and update on anything further |
Thomas Fjellstrom
Member #476
June 2000
|
If you call that function instead, you'll have to make sure to check that there is actually a new event because al_get_next_event always returns right away, even if there is no new event. Ie: if(!al_get_next_event(&event)) continue; Otherwise you'll be attempting to handle invalid data (the first time) and old events (any time after the first event). Or even make that loop: ALLEGRO_EVENT event; while(al_get_next_event(&event)) { ... } Personally, I prefer the layout of the loop I used in the tutorials on the wiki. Keeps from having nested loops. But its just a personal preference. -- |
Mishtiff
Member #15,776
October 2014
|
Thomas Fjellstrom said: Personally, I prefer the layout of the loop I used in the tutorials on the wiki. Keeps from having nested loops. But its just a personal preference. May i have a link to this? Sorry i'm unsure where to look for this (other than on wiki, not sure what to search for exactly). Ill probably go with a layout that does not require a nested loop. The way it is currently set up doesnt seem to work anyways, since my game will not update unless i move the mouse... interesting. Hard to understand why that is occurring. the timer loop is running and everything, but until i move the mouse, it wont render, and as long as i move the mouse it will, unless i stop moving. |
Thomas Fjellstrom
Member #476
June 2000
|
Try this code. -- |
Mishtiff
Member #15,776
October 2014
|
Thank you for the link, i could not seem to locate it (i did find the camera tut that added a new depth for me to try ) Is the program I am trying to create just too much for A5 to handle, or am I just writing awful code? Having frame rate issues still, which is disappointing considering how little i am actually trying to do. |
Thomas Fjellstrom
Member #476
June 2000
|
It's probably your code, or your hardware. -- |
pkrcel
Member #14,001
February 2012
|
Allegro5 is production-grade software (go look at factorio game for a very good indication), so basically we have to find the culprit in your code (which not necessarily has to be that awful ). I am also under the impression that we are circling around the problem in framerate but are looking at the input handling, which honestly SHOULDN'T be the issue-dealer. It is unlikely that Google shares your distaste for capitalism. - Derezo |
Thomas Fjellstrom
Member #476
June 2000
|
The thing that tends to cause framerate issues the most with A5 projects is loading bitmaps before you create the display. That creates memory bitmaps which are much slower to draw than display bitmaps. -- |
|
|