I was thinking about Command & Conquer this morning, and realized that there’s a very simple feature in that game that I couldn’t work out in my head how to do myself: click on a location on the screen and have an object move towards that location.
There are lots of wrong ways to do this. I started trying to work out on paper how to move a coordinate along a diagonal line, but really that’s the wrong way to think about it. You’re have to add a value to the X and Y coordinate of your object such that it steadily goes towards the new location.
If you take the X and Y distances between the object and the new location, divide those distances by some constant (which is what we’ll just call the “speed” in this example), you have a value to increment X and Y by bit by bit until it reaches the destination (or close enough to the destination).
Completely on accident I implemented this idea such that the object slows down as it approaches the target – this is because I re-calculate the distance after every move of my object. The X and Y distances gets smaller, but the “speed” I divide by stays the same, so the incremental value I add to the X and Y position gets smaller and smaller (so it appears to be approaching slower and slower).
Anyways, here’s a small example using SFML to do the drawing.
#include <SFML/Graphics.hpp> int main() { sf::RenderWindow window(sf::VideoMode(640, 480), "Click to move"); //Variables to store the position of the chaser, the //target, and the mouse click sf::Vector2i clickPosition; sf::Vector2f targetPosition; sf::Vector2f chaserPosition; //variables to store distances between the //chaser and target float distanceX; float distanceY; float distance; //Speed of the chaser float chaserSpeed = 2000; //tracking is 1 when I click the mouse, and //0 when the chaser hits the target. bool tracking = 0; //target circle size, color, and initial //position sf::CircleShape targetCircle; targetCircle.setFillColor(sf::Color::Red); targetCircle.setRadius(10.f); targetCircle.setPosition(0.f, 0.f); //chaser circle size, color, and initial //position sf::CircleShape chaserCircle; chaserCircle.setFillColor(sf::Color::Blue); chaserCircle.setRadius(10.f); chaserCircle.setPosition(100.f, 100.f); while (window.isOpen()) { sf::Event event; while (window.pollEvent(event)) { if (event.type == sf::Event::Closed) window.close(); if (event.type == sf::Event::MouseButtonPressed) { //If the mouse is clicked, get the position clickPosition = sf::Mouse::getPosition(window); //Set the target circle to that mouse click position targetCircle.setPosition((float)clickPosition.x, (float)clickPosition.y); //set tracking to 1 to enable tracking tracking = 1; //print useful debug info printf("Tracking...\n"); //print useful debug info printf("click X: %i, click Y: %i\n", clickPosition.x, clickPosition.y); } } if (tracking) { //We'll need the target and chaser positions targetPosition = targetCircle.getPosition(); chaserPosition = chaserCircle.getPosition(); //get the X and Y distance between the chaser //and target distanceX = targetPosition.x - chaserPosition.x; distanceY = targetPosition.y - chaserPosition.y; //calculate the distance between the chaser //and target distance = sqrt(distanceX * distanceX + distanceY * distanceY); //update the position of the chaser by adding incremental //values to its current X and Y position. chaserCircle.setPosition(chaserPosition.x + (distanceX / chaserSpeed), chaserPosition.y + (distanceY / chaserSpeed)); //if the distance is close, stop tracking if (distance < 10) { tracking = 0; printf("End tracking, distance %f\n", distance); } } window.clear(); window.draw(chaserCircle); window.draw(targetCircle); window.display(); } return 0; }
Neat, huh? I found this site that has some examples of all kinds of movement, but it’s in Javascript: http://www.somethinghitme.com/2013/11/13/snippets-i-always-forget-movement/
I’m itching to make another small game so that I can put some of the ideas in this fantastic SFML game development book, SFML Game Development, into use. The only thing holding me back right now is solidifying my understanding of some of the more advanced C++ the book uses (templates, woof).