Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!

1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Member Since 06 Jan 2013
Offline Last Active Jan 11 2013 12:46 PM

Posts I've Made

In Topic: SFML sprite movement (think super meat boy's rocket levels)

07 January 2013 - 12:11 PM

Another version someone posted on /r/gamedev:


while(game_is_running) {


    //get vector
    vx = player.x - zombie.x;
    vy = player.y - zombie.y;

    //get length of vector (distance from zombie to player)
    length = sqrt(vx*vx + vy*vy);

    //check length is above the hit distance from player to zombie here 
    //if it's below the distance then the zombie has eaten the player
    //length must be above zero or the normalisation will error (divide by zero)

    vx = vx/length;
    vy = vy/length;

    zombie.x += vx*zombie.speed*frame_time;
    zombie.y += vy*zombie.speed*frame_time;

    //draw everything


Which also works.

In Topic: SFML sprite movement (think super meat boy's rocket levels)

07 January 2013 - 11:26 AM

While I also suggest you use a vector difference like Jutaris suggested (though sf::Vector2 doesn't have ANY functions to normalize),

I think your original code's error is quite simple.


You're converting the result of your atan2 into degrees, but sin and cos are designed to accept radians. Remove the * 180 / M_PI which converts your angle to degrees. 

Storing your angle should only look like this:



angle = atan2(rany - player1.sprite.getPosition().y, ranx - player1.sprite.getPosition().x);


I'm not sure how accurate BeerNutts analysis is - I thought all of that works as you indended, but the human controlled player is player2, and the zombie is player1.

Best 'o luck to ya though.

This worked :D

In Topic: SFML sprite movement (think super meat boy's rocket levels)

07 January 2013 - 03:59 AM

So I attempted to do what you said and I had to make the speed the same for the player and the zombie.


Problem/Question 1: It seems I can't make both units on the screen different velocities (eg.: player1 = zombie with a speed of 2 and player2 = player with a speed of 3 [slightly faster]), if I do this and I go in a diagonal direction my player1 sprite will go in weird circular patterns unless I stop moving.


Problem/Question 2: It seems that if I allow diagonal movement (holding W and D or A & S, etc...) it will do this small curl up until I stop moving.  What's the best way to approach this problem?  


Problem/Question 3: There's also the issue when holding just down or right (S or D) and the sprite will just sit on the X or Y axis until I stop moving the unit on the screen and then proceed to move towards my unit.  How do I sort this?


Try what I'm talking about: http://morezombies.net/Zoms.zip (Virus Total Link: https://www.virustotal.com/url/1bb28babfa7e3049adc0f11e3f85c4a063728b799c20d4968e1c6c25921fc474/analysis/1357552685/)



#include "GameApp.h"

void GameApp::Setup() {

	//setup the game window
	window.create(VideoMode(width, height), "Zoms");

	//set framerate

	player1.setSize(10, 20);
	player1.setPos(10, 10);


	//lets say theg ames running now
	running 	= true;

void GameApp::Run() {

	//Setup game
	//used to get the current angle of the line between the two points
	//then we can properly move the sprite to the player
	double angle, x, y, newx, newy;

	//sprite speed 
	int speed 	= 2;

	//are the wasd buttons pressed?
	bool mw = false;
	bool ma = false;
	bool ms = false;
	bool md = false;

	//setup the player2 location
	int ranx 	= 300;
	int rany 	= 300;

	player2.setPos(ranx, rany);

	float timeprev, timecurr;

	while(window.isOpen()) {
		//loop through the active events (keyboard, mouse, etc...)
		while(window.pollEvent(event)) {

			if(event.type == Event::Closed) {

			if(event.type == Event::KeyPressed) {
				switch(event.key.code) {
					case Keyboard::W:
						mw = true;
					case Keyboard::A:
						ma = true;
					case Keyboard::S:
						ms = true;
					case Keyboard::D:
						md = true;

			if(event.type == Event::KeyReleased) {
				switch(event.key.code) {
					case Keyboard::W:
						mw = false;
					case Keyboard::A:
						ma = false;
					case Keyboard::S:
						ms = false;
					case Keyboard::D:
						md = false;

		//did we move the player?
		if(mw) {
			rany -= speed;

		if(ma) {
			ranx -= speed;

		if(ms) {
			rany += speed;

		if(md) {
			ranx += speed;

		//get the angle of the line between both player locations (zombie/player)
		angle 	= (atan2(rany - player1.sprite.getPosition().y, ranx - player1.sprite.getPosition().x) * 180) / M_PI;

		//steps between movement
		x 		= cos(angle) * speed;
		y 		= sin(angle) * speed;

		newx = player1.sprite.getPosition().x + x;
		newy = player1.sprite.getPosition().y + y;

		//move the sprites on the screen
		player1.sprite.setPosition(Vector2f(newx, newy));
		player2.sprite.setPosition(Vector2f(ranx, rany));


		//update the screen




Pastie link: http://pastie.org/private/dfjwphmllmhnqdh0htyhdg

In Topic: SFML sprite movement (think super meat boy's rocket levels)

07 January 2013 - 02:57 AM

You should be multiplying the cos() and sin() by a velocity, and adding it to the x and y location every loop, like this:



// Let's assume we've set float zombie.velocity = 5, which it seem is defined as pixels per frame
angle = (atan2(player.y - zombie.y, player.x - zombie.x) * 180) / M_PI; 
zombie.x += cos(angle)*zombie.velocity; 
zombie.y += sin(angle)*zombie.velocity;</pre>


Eventually you should define the velocity to be in some units/second (like pixels/second), so it will move better with other machine speeds.

Thank you, I will try this ^_^