Question

This is the source file where the function setLocation() is called (that includes for the graphics header file should have angle brackets, but it disappeared, so I used quotes)

#include "SFML/Graphics.hpp"

#include "ship.h"


const int WINDOW_WIDTH = 500;
const int WINDOW_HEIGHT = 500;
//==============================================================================
int main()
{
   sf::RenderWindow window( sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), 
    "Delta Quadrant", sf::Style::Titlebar | sf::Style::Close);

   window.setFramerateLimit(120); 
   // this causes loop to execute 120 times a second at most.
   // (a delay is automatically added after screen is drawn)

   Ship obj;
   //ADD Code to set limits on ships location (call setMaxLocation);


   //sets position of the ship in the middle of the screen
   obj.setLocation(250, 250);

   while (window.isOpen())
   {
    //----------------------------------------------------------
    //handle user input (events and keyboard keys being pressed)
    sf::Event event;
    while (window.pollEvent(event)) {
        if (event.type == sf::Event::Closed)
            window.close();
    }

    //turn left with press of left button
    while (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        obj.rotateLeft();

    //turn right with press of right button
    while (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        obj.rotateRight();

    //apply thrust with press of up button
    while (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        obj.applyThrust();

    //----------------------------------------------------------
    //draw new frame
    window.clear();

    //draw ship
    obj.updateLocation();
    obj.draw(window);

    //redisplay window
    window.display();

   }

return 0;
}

This is setLocation()'s definition, in the ship source file (same issue with the angle brackets, used quotes again).

  #include"cmath"
  #include "SFML/Window.hpp"
  #include "SFML/Graphics.hpp"
  #include "vector.h"
  #include "ship.h"

  //Constants
  const double PI = 3.14159;
  const double THRUST = 0.005;
  const double TURN_SPEED = 1;

  //constructor
  Ship::Ship(){
        maxLocations.x = 500;
        maxLocations.y = 500;
        radius = 5;

        location.x = 0;
        location.y = 0;

        velocity.x = 0;
        velocity.y = 0;

        angleDeg = 5;
  }

    void Ship::setLocation(double x, double y){

         //Check and correct for the ship going out of bounds.
         if (x < 0)
            location.x = 0;
         else if (x > maxLocations.x)
            location.x -= maxLocations.x;
         else 
            location.x = x;

         if (y < 0)
            location.y = 0;
         else if (y > maxLocations.y)
            location.y -= maxLocations.y;
         else
            location.y = y;
    }
    void Ship::updateLocation(){
         location.x += velocity.x;
         location.y -= velocity.y;

         //Check and correct for the ship going out of bounds.
         if (location.x < 0)
             location.x = 0;
         else if (location.x > maxLocations.x)
             location.x -= maxLocations.x;

         if (location.y < 0)
             location.y = 0;
         else if (location.y > maxLocations.y)
             location.y -= maxLocations.y;
    }
    void Ship::draw(sf::RenderWindow& win) {
    //Initializes the Ship class to an object
    Ship obj;

         // draw ship
         sf::ConvexShape ship;
         ship.setPointCount(3);
         ship.setPoint(0, sf::Vector2f(10, 0));
         ship.setPoint(1, sf::Vector2f(0, 25));
         ship.setPoint(2, sf::Vector2f(20, 25));

         sf::Vector2f midpoint(10,15);
         ship.setOrigin(midpoint);

         ship.setFillColor(sf::Color(0, 0, 0));
         ship.setOutlineThickness(1);
         ship.setOutlineColor(sf::Color(255, 255, 255));

         ship.setPosition(obj.getLocation().x, obj.getLocation().y);
         obj.setAngle(obj.getAngle());
         win.draw(ship);
    }
    }

Finally this is the header file where the setLocation() prototype is located

    #ifndef SHIP_H
    #define SHIP_H

    #include "vector.h"

    class Ship {
    private: 
        Vector maxLocations;    //maximum allowable values for location
        Vector location;        //current location (x,y)
        Vector velocity;        //current velocity (in pixels/frame)
        double angleDeg;        //angle ship is facing, in degrees
        double radius;          //gross radius of ship (for collision detection)

    public:
        //constructor
        Ship();
        //=============================================
        //mutators
        void setLocation(double x, double y);
        void updateLocation();
        void draw(sf::RenderWindow& win);
        ...
        };
    #endif

My issue is when I call setLocation() it doesn't change the location vector (as defined in the second source file) from (0, 0). When compiled the ship remains at (0, 0). What I want to happen is when I call setLocation(), the ship needs to change from (0, 0) to (250, 250), thus the ship on compiling starts in the middle of the screen, not a corner.

Was it helpful?

Solution

The problem at hand is you are not using the Ship object that you believe you are using. What I mean by that is you aren't drawing the ship object in your main function, instead you are creating a temporary ship object in your Ship::draw() method and then using that ships position to draw your shape. So the position will always be (0, 0) because your temp ship object get's initialized every frame with the position (0, 0) and then you use that temporary ship's position to draw your shape.

To make this more clear let's look at your code.

void Ship::draw(sf::RenderWindow& win) {

    // This is a temporary object and is not the same as the one you defined in your
    // main.cpp file. When this object is constructed it's location is (0, 0) by
    // default.
    Ship obj;

         // draw ship
         sf::ConvexShape ship;
         ship.setPointCount(3);
         ship.setPoint(0, sf::Vector2f(10, 0));
         ship.setPoint(1, sf::Vector2f(0, 25));
         ship.setPoint(2, sf::Vector2f(20, 25));

         sf::Vector2f midpoint(10,15);
         ship.setOrigin(midpoint);

         ship.setFillColor(sf::Color(0, 0, 0));
         ship.setOutlineThickness(1);
         ship.setOutlineColor(sf::Color(255, 255, 255));


         // Here we are setting the shapes position to the position of the temporary          
         // Ship object that you defined above. Remember that it's default location is
         // (0, 0) when constructed and you never changed it's location in the draw
         // method.
         ship.setPosition(obj.getLocation().x, obj.getLocation().y);
         obj.setAngle(obj.getAngle());
         win.draw(ship);
    }

Now how do you fix this? That is easy. All you need to do is get rid of that temporary ship object in your draw method and instead use your location vector to set the position of the shape. Like this.

ship.setPosition(location.x, location.y);

It might be beneficial for your to study up on how objects and classes work in C++ before continuing on. It seems you might not understand exactly how they work and how different scopes of code work. But I will leave that for your to decide what to do.

Though I would like to point out a few other pointers for you.

1 - In your draw method you are updating the position of objects. This is generally a bad thing to do and you should avoid it. All updating code like when you change a objects position should happen in a update function/method. The drawing methods of entities should only have drawing code in them. The reason for this is because usually drawing and updating happen at different time steps in the main game loop.

2 - Your updateLocation method won't work like you think it will. The reason is because you are doing location.y -= velocity.y; when in reality you should be adding the velocity of y to location just like you did with x.

3 - I would advise against using sfml's setFrameRateLimit() method and instead use your own timestep which will be much more accurate (SFML's version uses sf::Sleep which is notorious for being inaccurate) and give you much more control over your time step. If you don't know about time steps I would highly suggest reading this great article on it. It will save you hours of headaches. http://gafferongames.com/game-physics/fix-your-timestep/

4 - Let's take a look at this line.

else if (x > maxLocations.x)
    location.x -= maxLocations.x;

Now let's say that maxLocations.x = 500 like in your example and let's also say that location.x = 550. Do you really want the location to be x = 50? Wouldn't a more logical step be to set x to x = maxLocations.x? Not sure if this is what you wanted but thought I would point it out.

Hopefully this will help you a bit and I would always be glad to answer any other questions you might have. Wish you the best of luck with your project.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top