Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Smoothly move towards mouse

Credits go to Edgar Reynaldo, Michael Moffitt, and StevenVI for helping out!
This thread is locked; no one can reply to it. rss feed Print
Smoothly move towards mouse
Matias Persson
Member #15,093
May 2013

Hi there folks, I'm trying to create a smooth movement from the player to the mouse but there are suddenly two players instead of one and not to mention that the player flickers and moves weirdly.

Here is all the relevant code:

#SelectExpand
1Game.h 2#include "Mouse.h" 3#include "Player.h" 4 5class Game 6{ 7public: 8 Game(); 9 ~Game(); 10 11 void gameLoop(); 12 13private: 14 Mouse mouse; 15 16};

Game.cpp

#SelectExpand
1while (gameLooping) 2 { 3 ALLEGRO_EVENT ev; 4 al_wait_for_event(event_queue, &ev); 5 6 mouse.checkPos(ev); 7 8 if (ev.type == ALLEGRO_EVENT_TIMER) 9 { 10 player.update(mouse); 11 12 redraw = true; 13 } 14 if (redraw && al_is_event_queue_empty(event_queue)) 15 { 16 redraw = false; 17 18 al_clear_to_color(al_map_rgb(0, 0, 0)); 19 20 // Draw 21 al_draw_filled_circle(player.getX(), player.getY(), player.getMass(), al_map_rgb(0, 255, 0)); 22 23 al_flip_display(); 24 }

Player.h

#SelectExpand
1#pragma once 2 3#include <iostream> 4#include <string> 5#include <math.h> 6 7#include "Entity.h" 8#include "Mouse.h" 9 10class Player : 11 public Entity 12{ 13public: 14 Player(); 15 ~Player(); 16 17 void update(Mouse mouse); 18 19private: 20 std::string name; 21 int speed; 22 float xDistance, yDistance, distance, easingAmount; 23 24};

Player.cpp

#SelectExpand
1#include "Player.h" 2 3Player::Player() 4{ 5 speed = 10; 6 7 xDistance = 0; 8 yDistance = 0; 9 distance = 0; 10 easingAmount = 10.0; 11 12 x = 100; 13 y = 100; 14 mass = 16; 15} 16 17Player::~Player() 18{ 19} 20 21void Player::update(Mouse mouse) 22{ 23 xDistance = mouse.getX() - x, 24 yDistance = mouse.getY() - y; 25 distance = sqrt(xDistance * xDistance + yDistance * yDistance); 26 if (distance > speed) 27 { 28 xDistance = xDistance * speed / distance; 29 yDistance = yDistance * speed / distance; 30 } 31 if (distance > 1) 32 { 33 x += xDistance * easingAmount; 34 y += yDistance * easingAmount; 35 } 36}

Mouse.h

#SelectExpand
1#pragma once 2 3#include <allegro5/allegro.h> 4 5class Mouse 6{ 7public: 8 Mouse(); 9 ~Mouse(); 10 11 void checkPos(ALLEGRO_EVENT &ev); 12 float getX() 13 { 14 return x; 15 } 16 float getY() 17 { 18 return y; 19 } 20 21private: 22 float x, y; 23 24};

Mouse.cpp

#SelectExpand
1#include "Mouse.h" 2 3Mouse::Mouse() 4{ 5} 6 7Mouse::~Mouse() 8{ 9} 10 11void Mouse::checkPos(ALLEGRO_EVENT &ev) 12{ 13 if (ev.type == ALLEGRO_EVENT_MOUSE_AXES) 14 { 15 x = ev.mouse.x; 16 y = ev.mouse.y; 17 } 18}

Here's a video of what I'm talking about
https://www.youtube.com/watch?v=2t9FDl7aWP4&feature=youtu.be

Okay on the video there's no flickering and double player, but I swear it's there in the program itself. But the movement is still weird on the video as you can see..
I have attached the full source files to the thread, just in case :)

Can't figure it out :-/ Any help is much apprechiated :)

Edgar Reynaldo
Member #8,592
May 2007
avatar

void Player::update(Mouse mouse) {
 xDistance = mouse.getX() - x,
 yDistance = mouse.getY() - y;
 distance = sqrt(xDistance * xDistance + yDistance * yDistance);
 if (distance > speed) {
  xDistance = xDistance * speed / distance;
  yDistance = yDistance * speed / distance;
 }
 if (distance > 1) {
  x += xDistance * easingAmount;
  y += yDistance * easingAmount;
 }
 }

What effect are you trying to achieve? Moving at a constant speed towards the mouse on every timer event? What you are doing is more like an exponential decay

D=R*T (distance equals rate times time)

You want to subtract distance moved from distance away and recalculate how far away you are.

Michael Moffitt
Member #15,246
July 2013

If you want a really cheap smooth towards-mouse movement, but not at a constant speed, you can do this:

new_x = (old_x + mouse_x) / 2;
new_y = (old_y + mouse_y) / 2;

This will give you a rough asymptotic approach towards the mouse fairly quickly.

Matias Persson
Member #15,093
May 2013

What I'm trying to achieve is constant speed with a smooth movement towards the mouse, whether the player changes mouse position or not the player should smoothly change direction and still be moving towards the mouse.
And I want to update each frame.

StevenVI
Member #562
July 2000
avatar

Broad, not hand-holding at all solution:

  1. Add vx, vy properties to Player.

  2. Every frame, update these for each player so that they move at the same speed, but change direction to face the mouse using trigonometry knowledge.

  3. Every frame, increment the player x and y values by vx and vy, respectively

  4. If the update makes the player overshoot the mouse, stick it right on the mouse position

  5. If the player is already at the mouse's position, set vx and vy to zero.

__________________________________________________
Skoobalon Software
[ Lander! v2.5 ] [ Zonic the Hog v1.1 ] [ Raid 2 v1.0 ]

Matias Persson
Member #15,093
May 2013

Thanks Steven, got it working now :)

Go to: