My ship fires bullets but they don't move

Started by
1 comment, last by c2k2k11 7 years ago

I'm writing an Asteroids clone for my own education. I have classes for Bullet and PlayerShip. The main function created a PlayerShip called playerShip. I can fly this around the screen, all working well. I have made it so that when you fly off the edge you appear on the opposite edge. When you press Space, the PlayerShip's fire() event is called. This creates a Bullet object, passes it position and velocity of the PlayerShip, then returns it to be stored in a List.

All this seems to work perfectly, except that I can't get the bullets to move.

I tried with just a single bullet, not in a list - this moved but I could only have 1 bullet :(

Any ideas how to get my bullets moving?

Bullet.cpp:


Bullet::Bullet()
{
	bulletShape.setPointCount(4);
	bulletShape.setRadius(2);
	bulletShape.setFillColor(sf::Color::White);
}

sf::Vector2f Bullet::getVelocity()
{
	return velocity;
}
sf::Vector2f Bullet::getPosition()
{
	return bulletShape.getPosition();
}
sf::CircleShape Bullet::getShape()
{
	return bulletShape;
}

void Bullet::setPosition(sf::Vector2f pos)
{
	bulletShape.setPosition(pos);
}
void Bullet::setVelocity(sf::Vector2f vel)
{
	velocity = vel;
}

void Bullet::update()
{
	bulletShape.setPosition(sf::Vector2f(Bullet::getPosition().x + Bullet::getVelocity().x, Bullet::getPosition().y + Bullet::getVelocity().y));
}



PlayerShip.cpp:




#define PI 3.14159265

PlayerShip::PlayerShip(sf::Vector2f position)
{
	size = 20;
	accel = sf::Vector2f(0,0);
	velocity = sf::Vector2f(0,0);

	shipShape.setPointCount(4);
	shipShape.setPoint(0, sf::Vector2f(size / 2, 0));
	shipShape.setPoint(1, sf::Vector2f(size, size));
	shipShape.setPoint(2, sf::Vector2f(size / 2,2 * size / 3));
	shipShape.setPoint(3, sf::Vector2f(0, size));
	

	shipShape.setPosition(position);
	shipShape.setFillColor(sf::Color::Black);
	shipShape.setOutlineThickness(3);
	shipShape.setOutlineColor(sf::Color::White);

	shipShape.setOrigin(sf::Vector2f(size / 2, size * 2 / 3));

	thrustShape.setPointCount(4);
	thrustShape.setPosition(position);
	thrustShape.setPoint(0, sf::Vector2f(size / 2,0));
	thrustShape.setPoint(1, sf::Vector2f(size, size / 4));
	thrustShape.setPoint(2, sf::Vector2f(size / 2, size));
	thrustShape.setPoint(3, sf::Vector2f(0, size / 4));

	thrustShape.setOrigin(sf::Vector2f(size / 2, 0));

	thrustShape.setFillColor(sf::Color::White);
	thrustShape.setOutlineThickness(1);
	thrustShape.setOutlineColor(sf::Color::White);

}
sf::ConvexShape PlayerShip::getThrustShape()
{
	return thrustShape;
}
void PlayerShip::setPosition(sf::Vector2f newPosition)
{
	shipShape.setPosition(newPosition);
	thrustShape.setPosition(newPosition);

}
void PlayerShip::setVelocity(sf::Vector2f newVelocity)
{
	velocity = newVelocity;
}
void PlayerShip::rotate(float angle)
{
	shipShape.rotate(angle);
	thrustShape.rotate(angle);
}
void PlayerShip::thrust(float thrust)
{
	accel = sf::Vector2f(thrust * 0.01 * sin(shipShape.getRotation() * PI / 180), thrust * -0.01 * cos(shipShape.getRotation() * PI / 180));
	velocity += accel;

}
Bullet PlayerShip::fire()
{
	Bullet bullet;
	bullet.setPosition(getPosition());
	bullet.setVelocity(getVelocity());
	return bullet;
}

sf::ConvexShape PlayerShip::getShape()
{
	return shipShape;

}

sf::Vector2f PlayerShip::update()
{
	shipShape.move(velocity);
	thrustShape.move(velocity);
	return velocity;
}

sf::Vector2f PlayerShip::getPosition()
{
	return shipShape.getPosition();
}
float PlayerShip::getRotation()
{
	return shipShape.getRotation();
}
sf::Vector2f PlayerShip::getVelocity()
{
	return velocity;
}


Asteroids.cpp:



int main()
{
	int screenWidth = 800;
	int screenHeight = 600;
	
	// Prepare HUD

	sf::Text hud;
	sf::Font font;
	font.loadFromFile("ComputerFont.ttf");
	hud.setFont(font);
	hud.setCharacterSize(15);
	hud.setFillColor(sf::Color::Cyan);
	




	// Create window
	sf::RenderWindow window(sf::VideoMode(screenWidth, screenHeight), "Asteroids");


	// Create player ship
	PlayerShip playerShip(sf::Vector2f(screenWidth/2, screenHeight/2));

	// List for bullets to populate
	std::vector<Bullet> bullets;


	bool flag = false;



	while (window.isOpen()) // Game Loop
	{

		std::stringstream ss;
		sf::Event event;
		window.clear();

		while (window.pollEvent(event))
		{
			if (event.type == sf::Event::Closed)
				window.close();
		}

		if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
		{
			playerShip.rotate(-0.3);
		}
		if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
		{
			playerShip.rotate(0.3);
		}
		if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
		{
			playerShip.thrust(0.05);
			window.draw(playerShip.getThrustShape());
		}
		else
		{
			playerShip.thrust(0);
		}

		if (sf::Keyboard::isKeyPressed(sf::Keyboard::F1))
		{
			playerShip.setPosition(sf::Vector2f(screenWidth / 2, screenHeight / 2));
			playerShip.setVelocity(sf::Vector2f(0, 0));
			
		}
		if (!flag && sf::Keyboard::isKeyPressed(sf::Keyboard::Space))
		{
			flag = true;
			bullets.push_back(playerShip.fire());
		}
		else if (flag && !sf::Keyboard::isKeyPressed(sf::Keyboard::Space))
		{
			flag = false;
		}

		ss << "pos: " << playerShip.getPosition().x << " , " << playerShip.getPosition().y << "\n";
		ss << "rot: " << playerShip.getRotation() << "\n";
		ss << "vel: " << playerShip.getVelocity().x << " , " << playerShip.getVelocity().y << "\n\n";

		playerShip.update();
		
		for(Bullet bullet : bullets)
		{
			ss << "Pos: " << bullet.getPosition().x << " , " << bullet.getPosition().y << "\n";
			ss << "Vel: " << bullet.getVelocity().x << " , " << bullet.getVelocity().y << "\n\n";
			bullet.update();
			window.draw(bullet.getShape());
		}
		
		hud.setString(ss.str());

		// Keep ship on screen
		if (playerShip.getPosition().x < 0)
		{
			playerShip.setPosition(sf::Vector2f(playerShip.getPosition().x + screenWidth, playerShip.getPosition().y));
		}
		else if (playerShip.getPosition().x > screenWidth)
		{
			playerShip.setPosition(sf::Vector2f(0, playerShip.getPosition().y));
		}
		if (playerShip.getPosition().y < 0)
		{
			playerShip.setPosition(sf::Vector2f(playerShip.getPosition().x, playerShip.getPosition().y + screenHeight));
		}
		else if (playerShip.getPosition().y > screenHeight)
			{
				playerShip.setPosition(sf::Vector2f(playerShip.getPosition().x, 0));
			}
		// ////////////////////

		window.draw(playerShip.getShape());
		window.draw(hud);
		window.display();
	}
	return 0;
}

Obviously I've got the relevant header files too, but don't think I need to include these

I'm using C++ and the SFML library

As you can see from the code I've put some debug text in, showing the pos and vel of each bullet. These show that position and velocity are being set.

Can anyone help get my bullets moving?? Any help would be much appreciated.

Advertisement

for(Bullet bullet : bullets)
{
  ss << "Pos: " << bullet.getPosition().x << " , " << bullet.getPosition().y << "\n";
  ss << "Vel: " << bullet.getVelocity().x << " , " << bullet.getVelocity().y << "\n\n";
  bullet.update();
  window.draw(bullet.getShape());
}

What would happen if that loop used a reference to the elements of the list instead of a copy of the elements?

Stephen M. Webb
Professional Free Software Developer

Thanks Bregma, that did the trick


		for(Bullet& bullet : bullets)
		{
			ss << "Pos: " << bullet.getPosition().x << " , " << bullet.getPosition().y << "\n";
			ss << "Vel: " << bullet.getVelocity().x << " , " << bullet.getVelocity().y << "\n\n";
			bullet.update();
			window.draw(bullet.getShape());
		}

Now my bullets move!

So in the previous version,

for(Bullet& bullet : bullets)

was creating new bullet objects instead of manipulating the current ones? That explains why they were not moving!
Still getting my head around references yet, this is the first time I've had to use them

Thanks again for the solution :)

This topic is closed to new replies.

Advertisement