Barufaruku 12
Barufaruku 12

Reputation: 13

C++ SDL2 circular motion

I am currently making a simple solar system orbit program. So far I have managed to display the planets and sun in the window however I have yet to figure out how to get the time based circular motion needed for the planets. The motion is just a simple circle no in depth physics. My code below will show the class for the earth (no other planets at the moment) and how the time function works and the original straight motion I also found online to see how motion could work in c++. I have seen many different equations online but I am unsure on how to implement them into the code.

Earth Header:

#ifndef Earth_H_
#define Earth_H_

#include "Entity.h"
#include <math.h>

// Define a Sun speed in pixels per second
//const double Degree= 180/ M_PI;

class Earth : public Entity {

    const float Earth_Speed = 100;
public:
    Earth(SDL_Renderer* renderer);
    ~Earth();

    void Update(float delta);
    void Render(float delta);

    void SetDirection(float dirx, float diry);
    const double Degree = 180 / M_PI;
    /*float Orbital_Speed=0.01;*/
    double Angle;

    /*float Speed= 900;*/
    double Radius=100;

    float dirx, diry;

private:
    SDL_Texture* texture;

};

    #endif  

Earth cpp:

#include "Earth.h"


Earth::Earth(SDL_Renderer* renderer) : Entity(renderer) {
    SDL_Surface* surface = IMG_Load("Earth.png");
    texture = SDL_CreateTextureFromSurface(renderer, surface);
    SDL_FreeSurface(surface);

    x = 0;
    y = 0;
    width = 20;
    height = 20;


}

Earth::~Earth() {
    // Clean resources
    SDL_DestroyTexture(texture);
}

void Earth::Update(float delta) {
    // Move the Sun, time based
    x +=  dirx  * delta;
    y += diry * delta; 

    //Angle = atan2(diry / Degree, dirx / Degree);
    //x += ((dirx*Degree) - cos(Angle)*Radius)* delta;
    //y += ((diry*Degree) - sin(Angle)*Radius)* delta;
}

void Earth::Render(float delta) {
    SDL_Rect rect;
    rect.x = (int)(x + 0.5f); // Round the float to the nearest integer
    rect.y = (int)(y + 0.5f); // Round the float to the nearest integer
    rect.w = width;
    rect.h = height;
    SDL_RenderCopy(renderer, texture, 0, &rect);
}

void Earth::SetDirection(float dirx, float diry) {


    //Angle = atan2(diry/ Degree, dirx/ Degree);

    //this->dirx = ((dirx*Degree) - cos(Angle)*Radius)*Earth_Speed;
    //this->diry = ((diry*Degree) - sin(Angle)*Radius)*Earth_Speed;
    float length = sqrt(dirx * dirx + diry * diry);
    this->dirx = Earth_Speed * (dirx / length);
    this->diry = Earth_Speed * (diry / length);

 }

Simulation Header:

#ifndef Simulation_H_
#define Simulation_H_

#include "SDL.h"
#include "SDL_image.h"
#include <iostream>
#include <vector>



#include "Sun.h"
#include "Mercury.h"
#include "Venus.h"
#include "Earth.h"
#include "Mars.h"
#include "Jupiter.h"
#include "Saturn.h"
#include "Uranus.h"
#include "Neptune.h"

#define FPS_DELAY 500


class Simulation {
public:
    Simulation();
    ~Simulation();

    bool Init();
    void Run();

private:
    SDL_Window* window;
    SDL_Renderer* renderer;

    // Timing
    unsigned int lasttick, fpstick, fps, framecount;

    float width= 650, height= 650;



    Sun* sun;
    Mercury* mercury;
    Venus* venus;
    Earth* earth;
    Mars* mars;
    Jupiter* jupiter;
    Saturn* saturn;
    Uranus* uranus;
    Neptune* neptune;

    void Clean();
    void Update(float delta);
    void Render(float delta);

    void NewSimulation();


};

#endif

Simulation cpp:

#include "Simulation.h"

Simulation::Simulation() {
    window = 0;
    renderer = 0;
}

Simulation::~Simulation() {

}

bool Simulation::Init() {
    // Initialize SDL and the video subsystem
    SDL_Init(SDL_INIT_VIDEO);

    // Create window
    window = SDL_CreateWindow("Suraj's Solar System Simulator",
        100, 100,
        width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
    if (!window) {
        // Error creating window
        return false;
    }

    // Create renderer
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if (!renderer) {
        // Error creating renderer
        return false;
    }

    // Initialize timing
    lasttick = SDL_GetTicks();


    return true;
}

void Simulation::Clean() {
    // Clean renderer and window
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
}

void Simulation::Run() {
    // Create Sun and Planets

    sun = new Sun(renderer);
    mercury = new Mercury(renderer);
    venus= new Venus(renderer);
    earth = new Earth(renderer);
    mars= new Mars(renderer);
    jupiter = new Jupiter(renderer);
    saturn = new Saturn(renderer);
    uranus = new Uranus(renderer);
    neptune = new Neptune(renderer);


    NewSimulation();

    // Main loop
    while (1) {
        // Handler events
        SDL_Event e;
        if (SDL_PollEvent(&e)) {
            if (e.type == SDL_QUIT) {
                break;
            }
        }

        // Calculate delta and fps
        unsigned int curtick = SDL_GetTicks();
        float delta = (curtick - lasttick) / 1000.0f;
        lasttick = curtick;

        // Update and render the Simulation
        Update(delta);
        Render(delta);
    }

    // Delete objects

    delete sun;
    delete mercury;
    delete venus;
    delete earth;
    delete mars;
    delete jupiter;
    delete saturn;
    delete uranus;
    delete neptune;

    Clean();

    SDL_Quit();
}

void Simulation::NewSimulation() {


    // Center the Sun horizontally and vertically
    sun->x = width / 2 - sun->width / 2;
    sun->y = height / 2 - sun->height / 2;

    mercury->x = width / 2.4 - mercury->width / 2.4;
    mercury->y = height / 2 - mercury->height / 2;

    venus->x = width / 2.7 - venus->width / 2.7;
    venus->y = height / 2 - venus->height / 2;

    earth->x = width / 3 - earth->width / 3;
    earth->y = height / 2 - earth->height / 2;

    mars->x = width / 3.4 - mars->width / 3.4;
    mars->y = height / 2 - mars->height / 2;

    jupiter->x = width / 5 - jupiter->width / 5;
    jupiter->y = height / 2 - jupiter->height / 2;

    saturn->x = width / 9- saturn->width / 9;
    saturn->y = height / 2 - saturn->height / 2;

    uranus->x = width / 15 - uranus->width / 15;
    uranus->y = height / 2 - uranus->height / 2;

    neptune->x = width / 50 - neptune->width / 50;
    neptune->y = height / 2 - neptune->height / 2;

    //// Set the initial direction of the planets
    /*mercury->SetDirection(1, -1);
    venus->SetDirection(1, -1);*/

    earth->SetDirection((earth->x - sun->x)*cos(M_PI/180)+ sun->x, - ((earth->x - sun->x)*sin(M_PI / 180) + sun->y));
    //mars->SetDirection(1, -1  );
    //jupiter->SetDirection(1, -1);
    //saturn->SetDirection(1, -1);
    //uranus->SetDirection(1, -1);
    //neptune->SetDirection(1, -1);

}

void Simulation::Update(float delta) {


    // Update Earth and Sun
    sun->Update(delta);
    mercury->Update(delta);
    venus->Update(delta);
    earth->Update(delta);
    mars->Update(delta);
    jupiter->Update(delta);
    saturn->Update(delta);
    uranus->Update(delta);
    neptune->Update(delta);
}


void Simulation::Render(float delta) {
    // Clear the screen to black
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);

    // Render board and Sun

    sun->Render(delta);
    mercury->Render(delta);
    venus->Render(delta);
    earth->Render(delta);
    mars->Render(delta);
    jupiter->Render(delta);
    saturn->Render(delta);
    uranus->Render(delta);
    neptune->Render(delta);

    // Update the screen
    SDL_RenderPresent(renderer);
}

Entity Header:

#ifndef ENTITY_H_
#define ENTITY_H_

#include "SDL.h"
#include "SDL_image.h"

class Entity {
public:
    Entity(SDL_Renderer* renderer);
    virtual ~Entity();

    float x, y, width, height;

    virtual void Update(float delta);
    virtual void Render(float delta);


protected:
    SDL_Renderer* renderer;

};

#endif

Enitity cpp:

#include "Entity.h"

Entity::Entity(SDL_Renderer* renderer) {
    this->renderer = renderer;

    x = 0;
    y = 0;
    width = 1;
    height = 1;
}

Entity::~Entity() {
}

void Entity::Update(float delta) {
}

void Entity::Render(float delta) {
}

Main Header:

#ifndef MAIN_H_
#define MAIN_H_

#include "Simulation.h"

int main(int argc, char* argv[]);

#endif

Main cpp:

#include "main.h"

int main(int argc, char* argv[]) {
    // Create the game object
    Simulation* simulation = new Simulation();

    // Initialize and run the game
    if (simulation->Init()) {
        simulation->Run();
    }

    // Clean up
    delete simulation;
    return 0;
}

Upvotes: 0

Views: 1902

Answers (1)

sp2danny
sp2danny

Reputation: 7644

circular motion is usually accomplished with:

angle += orbit_speed * delta_time;
x = center_x + radius * cos(angle);
y = center_y + radius * sin(angle);

Upvotes: 2

Related Questions