Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Mouse event position X/Y doesn't update with al_use_transform

This thread is locked; no one can reply to it. rss feed Print
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.

#SelectExpand
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:

#SelectExpand
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:

#SelectExpand
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:

#SelectExpand
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
avatar

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.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

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:

#SelectExpand
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
avatar

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".

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

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
avatar

All you need is the formulas for the transformation.

camx + msx = worldx
camy + msy = worldy

screenx = worldx - camx
screeny = worldy - camy

You don't need to use allegro's transformations here, but if you did you would use translate transforms :

#SelectExpand
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.

Go to: