|
Mouse event position X/Y doesn't update with al_use_transform |
nerfherder
Member #15,009
March 2013
|
Having a little problem with mouse eventing. I am drawing a bitmap with al_draw_rotated_bitmap() which rotates the player bitmap towards where the mouse cursor is pointing. It works nicely until I scroll the map, in which the coordinates seem to be stuck at the screen where the player "spawned". This causes the player bitmap to not respond towards mouse movement as soon as I scroll the map in X or Y direction. 1hero->setAngle(atan2(float(mouseAxesY - pos_y),float(mouseAxesX - pos_x))); // Radiens = arc tangent of mouseAxesX/Y - Player positionX/Y Set angle for player rotation on hero->update()
This is the code where I get the mouse cursor position: 1ALLEGRO_EVENT ev;
2
3if (ev.type == ALLEGRO_EVENT_MOUSE_AXES) {
4 mouseAxesX = ev.mouse.x;
5 mouseAxesY = ev.mouse.y;
6}
And the code which scrolls the map: 1// Update camera position
2
3map->setOffsetX(0);
4map->setOffsetY(0);
5
6map->setOffsetX(map->getOffsetX() - (screenW / 2) + (pos_x + hero->getPBitmapWidth() / 2));
7map->setOffsetY(map->getOffsetY() - (screenH / 2) + (pos_y + hero->getPBitmapHeight() / 2));
8
9if (map->getOffsetX() < 0)
10 map->setOffsetX(0);
11if (map->getOffsetY() < 0)
12 map->setOffsetY(0);
13
14al_identity_transform(&camera);
15al_translate_transform(&camera, -map->getOffsetX(), -map->getOffsetY());
16al_use_transform(&camera);
For reference, here is the entire function: 1void BasicGameEngine::start() {
2
3 al_start_timer(timer); // Start timer. This operates at the industry standard 60 FPS, see constructor
4 hero = new OurHero(50, 50);
5
6 // Initialize 5 projectiles for our hero
7
8 hero->initProjectile(Projectile, 5);
9
10 // Get X/Y position of player
11
12 float pos_y = hero->getPosY();
13 float pos_x = hero->getPosX();
14
15 // Maximum speed player can move (value = pixel pr. second)
16
17 hero->setSpeed(3);
18
19 // Generate our map
20
21 map = new OurMap(10,10);
22
23 // Initiate main game loop
24
25 while (!done) {
26 ALLEGRO_EVENT ev;
27 al_wait_for_event(eQueue, &ev);
28
29 if (ev.type == ALLEGRO_EVENT_MOUSE_AXES) {
30 mouseAxesX = ev.mouse.x;
31 mouseAxesY = ev.mouse.y;
32 }
33
34 if (ev.type == ALLEGRO_EVENT_KEY_DOWN) {
35 switch (ev.keyboard.keycode) {
36 case ALLEGRO_KEY_W:
37 key[UP] = true;
38 break;
39 case ALLEGRO_KEY_S:
40 key[DOWN] = true;
41 break;
42 case ALLEGRO_KEY_D:
43 key[RIGHT] = true;
44 break;
45 case ALLEGRO_KEY_A:
46 key[LEFT] = true;
47 break;
48 case ALLEGRO_KEY_SPACE:
49 hero->fireProjectile(Projectile, 5, mouseAxesX, mouseAxesY);
50 key[SPACE] = true;
51 break;
52 case ALLEGRO_KEY_RSHIFT:
53 key[SHIFT] = true;
54 break;
55 case ALLEGRO_KEY_LSHIFT:
56 key[SHIFT] = true;
57 break;
58 }
59 } else if (ev.type == ALLEGRO_EVENT_KEY_UP) {
60 switch(ev.keyboard.keycode) {
61 case ALLEGRO_KEY_W:
62 key[UP] = false;
63 break;
64 case ALLEGRO_KEY_S:
65 key[DOWN] = false;
66 break;
67 case ALLEGRO_KEY_D:
68 key[RIGHT] = false;
69 break;
70 case ALLEGRO_KEY_A:
71 key[LEFT] = false;
72 break;
73 case ALLEGRO_KEY_SPACE:
74 key[SPACE] = false;
75 break;
76 case ALLEGRO_KEY_RSHIFT:
77 key[SHIFT] = false;
78 break;
79 case ALLEGRO_KEY_LSHIFT:
80 key[SHIFT] = false;
81 break;
82 case ALLEGRO_KEY_ESCAPE:
83 done = true;
84 break;
85 }
86 } else if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
87 done = true;
88 } else if (ev.type == ALLEGRO_EVENT_TIMER) {
89
90 // If player holds shift, increse speed by 4 pixels/s
91 // this simulates run, but will drain players stamina
92 // stamina will regenerate at 30% / s when the player
93 // is not running
94
95 if (key[SHIFT] && hero->getStamina() > 0) {
96 pos_y -= key[UP] * (hero->getSpeed() + 4);
97 pos_y += key[DOWN] * (hero->getSpeed() + 4);
98 pos_x -= key[LEFT] * (hero->getSpeed() + 4);
99 pos_x += key[RIGHT] * (hero->getSpeed() + 4);
100 hero->setStamina(hero->getStamina() - 1);
101
102 } else {
103 pos_y -= key[UP] * hero->getSpeed();
104 pos_y += key[DOWN] * hero->getSpeed();
105 pos_x -= key[LEFT] * hero->getSpeed();
106 pos_x += key[RIGHT] * hero->getSpeed();
107 }
108
109 if (!key[SHIFT] && hero->getStamina() < 1000)
110 hero->setStamina(hero->getStamina() + 0.3);
111
112 // Update projectile
113
114 hero->updateProjectile(Projectile, 5, 640, 480);
115
116
117 redraw = true;
118 }
119
120
121 if (redraw && al_event_queue_is_empty(eQueue)) {
122 redraw = false;
123
124 // redraw map sprites
125
126 map->draw();
127
128 // Update player position
129
130 hero->setPosX(pos_x);
131 hero->setPosY(pos_y);
132 hero->setAngle(atan2(float(mouseAxesY - pos_y),float(mouseAxesX - pos_x))); // Radiens = arc tangent of mouseAxesX/Y - Player positionX/Y
133 // Set angle for player rotation on hero->update()
134 hero->update();
135
136 // Update camera position
137
138 map->setOffsetX(0);
139 map->setOffsetY(0);
140
141 map->setOffsetX(map->getOffsetX() - (screenW / 2) + (pos_x + hero->getPBitmapWidth() / 2));
142 map->setOffsetY(map->getOffsetY() - (screenH / 2) + (pos_y + hero->getPBitmapHeight() / 2));
143
144 if (map->getOffsetX() < 0)
145 map->setOffsetX(0);
146 if (map->getOffsetY() < 0)
147 map->setOffsetY(0);
148
149 al_identity_transform(&camera);
150 al_translate_transform(&camera, -map->getOffsetX(), -map->getOffsetY());
151 al_use_transform(&camera);
152
153 // Draw projectiles if projectiles are fired
154 hero->drawProjectile(Projectile, 5);
155
156 al_flip_display();
157 al_clear_to_color(al_map_rgb(0, 0, 0));
158
159 }
160
161 }
162
163 delete map;
164}
Any help would be appreciated with this |
Thomas Fjellstrom
Member #476
June 2000
|
I didn't take a close look at the code, but are you mapping the coords to the transform (see: al_transform_coordinates )? Allegro can't do that for you, as is has absolutely no idea when/where to do that for you. -- |
nerfherder
Member #15,009
March 2013
|
Thanks for the reply, Thomas No, I wasn't, I where not even aware of that function I tried using it, like this: 1 // Update player position
2
3 float *mAX_p = &mAX, *mAY_p = &mAY;
4 *mAX_p = mouseAxesX;
5 *mAY_p = mouseAxesY;
6
7 hero->setPosX(pos_x);
8 hero->setPosY(pos_y);
9 hero->setAngle(atan2(float(*mAY_p - pos_y),float(*mAX_p - pos_x))); // Radiens = arc tangent of mouseAxesX/Y - Player positionX/Y
10 // Set angle for player rotation on hero->update()
11 hero->update();
12
13 // Update camera position
14
15 map->setOffsetX(0);
16 map->setOffsetY(0);
17
18 map->setOffsetX(map->getOffsetX() - (screenW / 2) + (pos_x + hero->getPBitmapWidth() / 2));
19 map->setOffsetY(map->getOffsetY() - (screenH / 2) + (pos_y + hero->getPBitmapHeight() / 2));
20
21 if (map->getOffsetX() < 0)
22 map->setOffsetX(0);
23 if (map->getOffsetY() < 0)
24 map->setOffsetY(0);
25
26 al_identity_transform(&camera);
27 al_translate_transform(&camera, -map->getOffsetX(), -map->getOffsetY());
28 al_transform_coordinates(&camera, mAX_p, mAY_p);
29 al_use_transform(&camera);
But it still doesn't map the mouse coordinates, I got the same result as before |
gnolam
Member #2,030
March 2002
|
The problem is that you're mixing screen coordinates (the mouse coordinates) and world coordinates (the player position). Transform the player coordinates into screen coordinates before doing the subtraction and atan2(). Also: why are you using all those pointers? Also #2: "radians", not "radiens". -- |
nerfherder
Member #15,009
March 2013
|
Doh! It becomes pretty obvious when you mention it. Thanks, I'll give it a whirl then edit: But won't I need to transform the mouse coordinates aswell? edit2: Any good documentation/tutorials I can read up on transformation? I've tried to mend the code with the proposals but it seems to fall short, and I really want to learn to get a decent grasp on this. |
Edgar Reynaldo
Major Reynaldo
May 2007
|
All you need is the formulas for the transformation. camx + msx = worldx screenx = worldx - camx You don't need to use allegro's transformations here, but if you did you would use translate transforms : 1ALLEGRO_TRANSFORM ToWorldCoords;
2ALLEGRO_TRANSFORM ToScreenCoords;
3
4al_identity_transform(&ToWorldCoords);
5al_identity_transform(&ToScreenCoords);
6
7int camx = 0;
8int camy = 0;
9int mapw = 0;
10int maph = 0;
11
12void set_camera(int cx , int cy , int width , int height) {
13
14 camx = cx - width/2;
15 camy = cy - height/2;
16 if (camx < 0) {camx = 0;}
17 if (camy < 0) {camy = 0;}
18 if (camx + width >= mapw) {camx = mapw - width;}
19 if (camy + height >= maph) {camy = maph - height;}
20
21 al_identity_transform(&ToWorldCoords);
22 al_identity_transform(&ToScreenCoords);
23 al_translate_transform(&ToWorldCoords , camx , camy);
24 al_translate_transform(&ToScreenCoords , -camx , -camy);
25}
And then use al_transform_coordinates to get coords in or out of each one. 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 |
|