Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [Solved] sf::CircleShape in vector not rendering on calling `&Window.draw()`  (Read 2764 times)

0 Members and 2 Guests are viewing this topic.

dd

  • Newbie
  • *
  • Posts: 10
    • View Profile
 For context, I have 3 classes: `AsteroidClass`, `RocketClass`, and `Spaceship`. Spaceship is the player controlled spaceship, whilst `AsteroidClass` are the asteroids, and `RocketClass` is the class for all projectiles shot by the player.
Shooting is checked inside the `Spaceship` classes' `Update()` function. When it detects space key pressed, it creates a new `RocketClass` instance and pushes it to the private vector `GlobalRockets`. At the end of the update function, this vector is looped through and individually calls the `Update` function on each `RocketClass` instance, and then drawing it to the window.
However, I never see any projectile rendered. I have tried manually creating a new `RocketClass` instance inside of the `main`
function, calling it's `Update`, then rendering it manually and no problems there. The only issue is rendering it inside of the Player's `Update`. Here is my code:
#include <iostream>
#include <SFML/Graphics.hpp>
#include <cmath>
#include <vector>

enum Turn {
        Static,
        Glide
};

enum AsteroidType {
        Small,
        Medium,
        Large
};

const int WINDOW_LENGTH = 800;
const int WINDOW_HEIGHT = 600;

class RocketClass {
        private:
                const double MOVE_SPD=3.5;
                double ROTATION_RAD;
                const double OUTLINE_THICKNESS=1.5;
                const float SIZE=3;
        public:
                sf::CircleShape Rocket;
                RocketClass(sf::Vector2f StartPos, double Rotation){
                        Rocket.setRadius(SIZE);
                        Rocket.setFillColor(sf::Color(0, 0, 0, 0));
                        Rocket.setPosition(StartPos);
                        Rocket.setRotation(Rotation);
                        Rocket.setOutlineThickness(OUTLINE_THICKNESS);
                        ROTATION_RAD = Rotation*180/3.14159265;
                }
                void Update(double TimeFrame){
                        Rocket.move(MOVE_SPD*TimeFrame*cos(ROTATION_RAD), MOVE_SPD*TimeFrame*sin(ROTATION_RAD));
                        if (Rocket.getPosition().y > WINDOW_HEIGHT){
                                Rocket.setPosition(sf::Vector2f(Rocket.getPosition().x, 0));
                        }
                        if (Rocket.getPosition().y < 0){
                                Rocket.setPosition(sf::Vector2f(Rocket.getPosition().x, WINDOW_HEIGHT));
                        }
                        if (Rocket.getPosition().x > WINDOW_LENGTH){
                                Rocket.setPosition(sf::Vector2f(0, Rocket.getPosition().y));
                        }
                        if (Rocket.getPosition().x <0){
                                Rocket.setPosition(sf::Vector2f(WINDOW_LENGTH, Rocket.getPosition().y));
                        }
                }
};

class AsteroidClass {
        private:
                double ROTATE_SPD =0.8;
                double VELOCITY =70;
                double DIRECTION=0;
                double SIZE_MULTIP=0.25;
                const double OUTLINE_THICKNESS = 1;
                AsteroidType Type = AsteroidType::Large;
        public:
                sf::ConvexShape Asteroid;
                AsteroidClass(AsteroidType ConstType){
                        srand(time(NULL));
                        Type = ConstType;
                        switch(Type){
                                case AsteroidType::Small:
                                        SIZE_MULTIP =3.75;
                                        break;
                                case AsteroidType::Medium:
                                        SIZE_MULTIP= 6.25;
                                        break;
                                case AsteroidType::Large:
                                        SIZE_MULTIP=8.75;
                                        break;
                                }
                        switch(rand()%2+1){
                                case 1:
                                        Asteroid.setPointCount(11);
                                        Asteroid.setPoint(0, sf::Vector2f(-2*SIZE_MULTIP, -5*SIZE_MULTIP));
                                        Asteroid.setPoint(1, sf::Vector2f(0*SIZE_MULTIP, -5*SIZE_MULTIP));
                                        Asteroid.setPoint(2, sf::Vector2f(0*SIZE_MULTIP, -4*SIZE_MULTIP));
                                        Asteroid.setPoint(3, sf::Vector2f(2*SIZE_MULTIP, -4*SIZE_MULTIP));     
                                        Asteroid.setPoint(4, sf::Vector2f(4*SIZE_MULTIP, -2*SIZE_MULTIP));
                                        Asteroid.setPoint(5, sf::Vector2f(4*SIZE_MULTIP, 2*SIZE_MULTIP));
                                        Asteroid.setPoint(6, sf::Vector2f(2*SIZE_MULTIP, 4*SIZE_MULTIP));
                                        Asteroid.setPoint(7, sf::Vector2f(1*SIZE_MULTIP, 4*SIZE_MULTIP));
                                        Asteroid.setPoint(8, sf::Vector2f(0*SIZE_MULTIP, 3*SIZE_MULTIP));
                                        Asteroid.setPoint(9, sf::Vector2f(-3*SIZE_MULTIP, 3*SIZE_MULTIP));
                                        Asteroid.setPoint(10, sf::Vector2f(-2*SIZE_MULTIP, 2*SIZE_MULTIP));
                                        Asteroid.setPoint(11, sf::Vector2f(-2*SIZE_MULTIP, 1*SIZE_MULTIP));
                                        Asteroid.setPoint(12, sf::Vector2f(-4*SIZE_MULTIP, 0*SIZE_MULTIP));
                                        Asteroid.setPoint(13, sf::Vector2f(-4*SIZE_MULTIP, -4*SIZE_MULTIP));
                                        Asteroid.setPoint(14, sf::Vector2f(-3*SIZE_MULTIP, -4*SIZE_MULTIP));
                                        Asteroid.setPoint(15, sf::Vector2f(-2*SIZE_MULTIP, -5*SIZE_MULTIP));
                                        Asteroid.setOutlineThickness(OUTLINE_THICKNESS);
                                        Asteroid.setPosition(sf::Vector2f(100, 100));
                                        Asteroid.setFillColor(sf::Color(0, 0, 0, 0));
                                        break;
                               
                                case 2:
                                        Asteroid.setPointCount(17);
                                        Asteroid.setPoint(0, sf::Vector2f(-3*SIZE_MULTIP, -4*SIZE_MULTIP));
                                        Asteroid.setPoint(1, sf::Vector2f(2*SIZE_MULTIP, -4*SIZE_MULTIP));
                                        Asteroid.setPoint(2, sf::Vector2f(2*SIZE_MULTIP, -3*SIZE_MULTIP));
                                        Asteroid.setPoint(3, sf::Vector2f(4*SIZE_MULTIP, -1*SIZE_MULTIP));
                                        Asteroid.setPoint(4, sf::Vector2f(4*SIZE_MULTIP, 2*SIZE_MULTIP));
                                        Asteroid.setPoint(5, sf::Vector2f(3*SIZE_MULTIP, 3*SIZE_MULTIP));
                                        Asteroid.setPoint(6, sf::Vector2f(2*SIZE_MULTIP, 3*SIZE_MULTIP));
                                        Asteroid.setPoint(7, sf::Vector2f(1*SIZE_MULTIP, 4*SIZE_MULTIP));
                                        Asteroid.setPoint(8, sf::Vector2f(-2*SIZE_MULTIP, 4*SIZE_MULTIP));
                                        Asteroid.setPoint(9, sf::Vector2f(-2*SIZE_MULTIP, 3*SIZE_MULTIP));
                                        Asteroid.setPoint(10, sf::Vector2f(-3*SIZE_MULTIP, 3*SIZE_MULTIP));
                                        Asteroid.setPoint(11, sf::Vector2f(-4*SIZE_MULTIP, 2*SIZE_MULTIP));
                                        Asteroid.setPoint(12, sf::Vector2f(-3*SIZE_MULTIP, 1*SIZE_MULTIP));
                                        Asteroid.setPoint(13, sf::Vector2f(-3*SIZE_MULTIP, -1*SIZE_MULTIP));
                                        Asteroid.setPoint(14, sf::Vector2f(-4*SIZE_MULTIP, -2*SIZE_MULTIP));
                                        Asteroid.setPoint(15, sf::Vector2f(-4*SIZE_MULTIP, -3*SIZE_MULTIP));
                                        Asteroid.setPoint(16, sf::Vector2f(-3*SIZE_MULTIP, -4*SIZE_MULTIP));
                                        Asteroid.setOutlineThickness(OUTLINE_THICKNESS);
                                        Asteroid.setPosition(sf::Vector2f(100, 100));
                                        Asteroid.setFillColor(sf::Color(0, 0, 0, 0));
                        }
                }
                void Update(double FrameTime){
                        Asteroid.rotate(ROTATE_SPD);
                        const int Degrees_Rotation = DIRECTION*180/3.14159265;
                        Asteroid.move(VELOCITY*FrameTime*cos(Degrees_Rotation), VELOCITY*FrameTime*sin(Degrees_Rotation));
                        if (Asteroid.getPosition().y > WINDOW_HEIGHT){
                                Asteroid.setPosition(sf::Vector2f(Asteroid.getPosition().x, 0));
                        }
                        if (Asteroid.getPosition().y < 0){
                                Asteroid.setPosition(sf::Vector2f(Asteroid.getPosition().x, WINDOW_HEIGHT));
                        }
                        if (Asteroid.getPosition().x > WINDOW_LENGTH){
                                Asteroid.setPosition(sf::Vector2f(0, Asteroid.getPosition().y));
                        }
                        if (Asteroid.getPosition().x <0){
                                Asteroid.setPosition(sf::Vector2f(WINDOW_LENGTH, Asteroid.getPosition().y));
                        }
                }
};


class SpaceShip {
        private:
                std::vector<RocketClass> GlobalRockets = {};
                const Turn TURN_TYPE = Turn::Static;
                const int OUTLINE_THICKNESS = 1;
                const int SIZE_MULTIP=4;
                const double ACCELERATION_SPD=0.02;
                const double DECELERATION_SPD=0.018;
                const double MAX_SPD = 4;
                double TURN_SPD=2.5;
                const double GLIDE_TURN_SPD = 0.07;
                const double MAX_TURN_SPD = 7.5;
                double Velocity =0;
                double TurnVelocity =0;
                double Degrees_Rad = 0;
                const double FRAME_TIME_MULTIP=75;
        public:
                sf::ConvexShape Ship{(5)};
                SpaceShip(){
                        Ship.setPoint(0, sf::Vector2f(4*SIZE_MULTIP, 0));
                        Ship.setPoint(1, sf::Vector2f(-4*SIZE_MULTIP, -3*SIZE_MULTIP));
                        Ship.setPoint(2, sf::Vector2f(-2*SIZE_MULTIP, 0));
                        Ship.setPoint(3, sf::Vector2f(-4*SIZE_MULTIP, 3*SIZE_MULTIP));
                        Ship.setPoint(4, sf::Vector2f(4*SIZE_MULTIP, 0));
                        Ship.setOutlineThickness(OUTLINE_THICKNESS);
                        Ship.setPosition(sf::Vector2f(100, 100));
                        Ship.setFillColor(sf::Color(0, 0, 0, 0));
                        if (TURN_TYPE == Turn::Glide){
                                TURN_SPD = GLIDE_TURN_SPD;
                        }
                }
                void Update(double FrameTime, sf::RenderWindow &Window){
                        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Keyboard::isKeyPressed(sf::Keyboard::W)){
                                Velocity+=ACCELERATION_SPD;    
                                if (Velocity > MAX_SPD){
                                        Velocity = MAX_SPD;
                                }
                        }
                        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) || sf::Keyboard::isKeyPressed(sf::Keyboard::S)){
                                Velocity-=DECELERATION_SPD;
                                if (Velocity < MAX_SPD*-1){
                                        Velocity=MAX_SPD*-1;
                                }
                        }
                        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right) || sf::Keyboard::isKeyPressed(sf::Keyboard::D)){
                        TurnVelocity+=TURN_SPD;
                                if (TurnVelocity >= MAX_TURN_SPD){
                                        TurnVelocity = MAX_TURN_SPD;
                                }
                        }
                        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Keyboard::isKeyPressed(sf::Keyboard::A)){
                                TurnVelocity -= TURN_SPD;
                                if (TurnVelocity <= MAX_TURN_SPD*-1){
                                        TurnVelocity = MAX_TURN_SPD*-1;
                                }
                        }
                        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space)){
                                RocketClass Projectile(Ship.getPosition(), Ship.getRotation());
                                GlobalRockets.push_back(Projectile);
                        }
                        switch (TURN_TYPE){
                                case Turn::Static:
                                        Ship.rotate(TurnVelocity*(FrameTime*FRAME_TIME_MULTIP));
                                        TurnVelocity = 0;
                                        break;
                                case Turn::Glide:
                                        Ship.rotate(TurnVelocity*(FrameTime*FRAME_TIME_MULTIP));
                                        break;
                        }
                        Degrees_Rad = Ship.getRotation() *3.14159/180;
                        Ship.move(sf::Vector2f(Velocity*FrameTime*FRAME_TIME_MULTIP*cos(Degrees_Rad), Velocity*FrameTime*FRAME_TIME_MULTIP*sin(Degrees_Rad)));

                        if (Ship.getPosition().y > WINDOW_HEIGHT){
                                Ship.setPosition(sf::Vector2f(Ship.getPosition().x, 0));
                        }
                        if (Ship.getPosition().y < 0){
                                Ship.setPosition(sf::Vector2f(Ship.getPosition().x, WINDOW_HEIGHT));
                        }
                        if (Ship.getPosition().x > WINDOW_LENGTH){
                                Ship.setPosition(sf::Vector2f(0, Ship.getPosition().y));
                        }
                        if (Ship.getPosition().x <0){
                                Ship.setPosition(sf::Vector2f(WINDOW_LENGTH, Ship.getPosition().y));
                        }
                        for (int i=0;i<GlobalRockets.size();i++){
                                GlobalRockets.at(i).Update(FrameTime);
                                Window.draw(GlobalRockets.at(i).Rocket);
                        }
                }
};

int main(){
        const double MAX_FPS = 60;
        SpaceShip Player;
        AsteroidClass AsteroidInstance(AsteroidType::Large);
        sf::RenderWindow Window(sf::VideoMode(WINDOW_LENGTH, WINDOW_HEIGHT), "Asteroids");
        sf::Clock FrameTime;

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

                if (FrameTime.getElapsedTime().asSeconds() >= 1/MAX_FPS){
                        Player.Update(FrameTime.getElapsedTime().asSeconds(), Window);
                        AsteroidInstance.Update(FrameTime.getElapsedTime().asSeconds());
                        Window.clear();
                        Window.draw(Player.Ship);
                        Window.draw(AsteroidInstance.Asteroid);
                        Window.display();
                        FrameTime.restart();
                }
        }
}
 
I think the main focus is the contents of the `Spaceship` class, however the rest of the code is there for context.
« Last Edit: August 21, 2024, 08:48:17 pm by dd »

vokazoo

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: sf::CircleShape in vector not rendering on calling `&Window.draw()`
« Reply #1 on: August 21, 2024, 07:50:24 pm »
You're drawing in update function. So, when you call Update function on Player, rocket is drawn on the window, however, you then immediately clear the window before displaying it being drawn.

Quick fix would be to move the line `Windown.clear();` by 2 lines up, that way you're clearing the window before updating (which is also drawing in your case). But I suggest you separate logic and rendering as it may get more confusing as the game gets bigger.

(by the way, in AsteroidClass constructor on `switch (rand() % 2 + 1) {` line in case 1:, you're setting 12th point's position on a shape that has 11 points total, which sometimes results in a crash depending on rand() value)

dd

  • Newbie
  • *
  • Posts: 10
    • View Profile
Re: sf::CircleShape in vector not rendering on calling `&Window.draw()`
« Reply #2 on: August 21, 2024, 08:47:32 pm »
Worked. Thanks a lot