From 89befd110f7443824e35f6904c23424ed6ff3173 Mon Sep 17 00:00:00 2001 From: Barry Kane Date: Thu, 16 Mar 2023 00:27:43 +0000 Subject: [PATCH] Added a second ship to the simulation. --- .../Ship-Accelerating-Frame-2.png | Bin .../Ship-Accelerating.png | Bin .../Ship-Anticlockwise.png | Bin .../Ship-Clockwise.png | Bin .../Ship-Idle.png | Bin Spacewar.c | 280 +++++++++++------- 6 files changed, 173 insertions(+), 107 deletions(-) rename {Experiment-12-Images => Experiment-13-Images}/Ship-Accelerating-Frame-2.png (100%) rename {Experiment-12-Images => Experiment-13-Images}/Ship-Accelerating.png (100%) rename {Experiment-12-Images => Experiment-13-Images}/Ship-Anticlockwise.png (100%) rename {Experiment-12-Images => Experiment-13-Images}/Ship-Clockwise.png (100%) rename {Experiment-12-Images => Experiment-13-Images}/Ship-Idle.png (100%) diff --git a/Experiment-12-Images/Ship-Accelerating-Frame-2.png b/Experiment-13-Images/Ship-Accelerating-Frame-2.png similarity index 100% rename from Experiment-12-Images/Ship-Accelerating-Frame-2.png rename to Experiment-13-Images/Ship-Accelerating-Frame-2.png diff --git a/Experiment-12-Images/Ship-Accelerating.png b/Experiment-13-Images/Ship-Accelerating.png similarity index 100% rename from Experiment-12-Images/Ship-Accelerating.png rename to Experiment-13-Images/Ship-Accelerating.png diff --git a/Experiment-12-Images/Ship-Anticlockwise.png b/Experiment-13-Images/Ship-Anticlockwise.png similarity index 100% rename from Experiment-12-Images/Ship-Anticlockwise.png rename to Experiment-13-Images/Ship-Anticlockwise.png diff --git a/Experiment-12-Images/Ship-Clockwise.png b/Experiment-13-Images/Ship-Clockwise.png similarity index 100% rename from Experiment-12-Images/Ship-Clockwise.png rename to Experiment-13-Images/Ship-Clockwise.png diff --git a/Experiment-12-Images/Ship-Idle.png b/Experiment-13-Images/Ship-Idle.png similarity index 100% rename from Experiment-12-Images/Ship-Idle.png rename to Experiment-13-Images/Ship-Idle.png diff --git a/Spacewar.c b/Spacewar.c index 88f7d18..a7cb0de 100644 --- a/Spacewar.c +++ b/Spacewar.c @@ -1,4 +1,4 @@ -// SDL Experiment 12, Barra Ó Catháin. +// SDL Experiment 13, Barra Ó Catháin. // =================================== #include #include @@ -7,12 +7,22 @@ #include #include +// A 2D vector: typedef struct xyVector { double xComponent; double yComponent; } xyVector; +// A struct storing the needed data to draw a ship: +typedef struct ship +{ + SDL_Rect rectangle; + xyVector position; + xyVector velocity; + xyVector gravity; +} ship; + // Calculate the vector from point A to point B: static inline void xyVectorBetweenPoints(long ax, long ay, long bx, long by, xyVector * vector) { @@ -24,8 +34,11 @@ static inline void xyVectorBetweenPoints(long ax, long ay, long bx, long by, xyV static inline double normalizeXYVector(xyVector * vector) { double magnitude = sqrt(pow(vector->xComponent, 2) + pow(vector->yComponent, 2)); - vector->xComponent /= magnitude; - vector->yComponent /= magnitude; + if(magnitude != 0) + { + vector->xComponent /= magnitude; + vector->yComponent /= magnitude; + } return magnitude; } @@ -38,6 +51,7 @@ static inline double angleBetweenVectors(xyVector * vectorA, xyVector * vectorB) return atan2(dotProduct, determinant) / 0.01745329; } +// Rotate XY vector by a given number of degrees: static inline void rotateXYVector(xyVector * vector, double degrees) { double xComponent = vector->xComponent, yComponent = vector->yComponent; @@ -65,42 +79,94 @@ static inline void multiplyXYVector(xyVector * vector, double scalar) vector->xComponent *= scalar; vector->yComponent *= scalar; } + void DrawCircle(SDL_Renderer * renderer, int32_t centreX, int32_t centreY, int32_t radius) { - const int32_t diameter = (radius * 2); + const int32_t diameter = (radius * 2); - int32_t x = (radius - 1); - int32_t y = 0; - int32_t tx = 1; - int32_t ty = 1; - int32_t error = (tx - diameter); + int32_t x = (radius - 1); + int32_t y = 0; + int32_t tx = 1; + int32_t ty = 1; + int32_t error = (tx - diameter); - while (x >= y) - { - // Each of the following renders an octant of the circle - SDL_RenderDrawPoint(renderer, centreX + x, centreY - y); - SDL_RenderDrawPoint(renderer, centreX + x, centreY + y); - SDL_RenderDrawPoint(renderer, centreX - x, centreY - y); - SDL_RenderDrawPoint(renderer, centreX - x, centreY + y); - SDL_RenderDrawPoint(renderer, centreX + y, centreY - x); - SDL_RenderDrawPoint(renderer, centreX + y, centreY + x); - SDL_RenderDrawPoint(renderer, centreX - y, centreY - x); - SDL_RenderDrawPoint(renderer, centreX - y, centreY + x); + while (x >= y) + { + // Each of the following renders an octant of the circle + SDL_RenderDrawPoint(renderer, centreX + x, centreY - y); + SDL_RenderDrawPoint(renderer, centreX + x, centreY + y); + SDL_RenderDrawPoint(renderer, centreX - x, centreY - y); + SDL_RenderDrawPoint(renderer, centreX - x, centreY + y); + SDL_RenderDrawPoint(renderer, centreX + y, centreY - x); + SDL_RenderDrawPoint(renderer, centreX + y, centreY + x); + SDL_RenderDrawPoint(renderer, centreX - y, centreY - x); + SDL_RenderDrawPoint(renderer, centreX - y, centreY + x); - if (error <= 0) - { - ++y; - error += ty; - ty += 2; - } + if (error <= 0) + { + ++y; + error += ty; + ty += 2; + } - if (error > 0) - { - --x; - tx += 2; - error += (tx - diameter); - } - } + if (error > 0) + { + --x; + tx += 2; + error += (tx - diameter); + } + } +} + +void calculateGravity(xyVector * starPosition, ship * shipUnderGravity) +{ + // Calculate the vector between the star and ship: + xyVectorBetweenPoints(shipUnderGravity->position.xComponent, shipUnderGravity->position.yComponent, + starPosition->xComponent, starPosition->yComponent, &shipUnderGravity->gravity); + + // Make it into a unit vector: + double gravityMagnitude = normalizeXYVector(&shipUnderGravity->gravity); + double gravityAcceleration = 0; + + // Calculate the gravity between the star and ship: + if(gravityMagnitude != 0) + { + if(gravityMagnitude >= 116) + { + gravityAcceleration = 0.1 * (35000 / (pow(gravityMagnitude, 2))); + } + else + { + gravityAcceleration = 0; + } + } + else + { + gravityAcceleration = 1; + } + + if(gravityAcceleration < 0.01) + { + gravityAcceleration = 0.01; + } + + // Scale the vector: + multiplyXYVector(&shipUnderGravity->gravity, gravityAcceleration); +} + +// Create a ship with the given parameters: +ship createShip(int width, int height, double positionX, double positionY, double velocityX, double velocityY) +{ + ship newShip; + newShip.rectangle.w = width; + newShip.rectangle.h = height; + newShip.position.xComponent = positionX; + newShip.position.yComponent = positionY; + newShip.velocity.xComponent = velocityX; + newShip.velocity.yComponent = velocityY; + newShip.gravity.xComponent = 0; + newShip.gravity.yComponent = 0; + return newShip; } int main(int argc, char ** argv) @@ -112,8 +178,13 @@ int main(int argc, char ** argv) long positionX = 512, positionY = 512, starPositionX = 0, starPositionY = 0; double deltaTime = 0, gravityMagnitude = 0, gravityAcceleration = 0, frameAccumulator = 0; bool quit = false, rotatingClockwise = false, rotatingAnticlockwise = false, accelerating = false; - xyVector positionVector = {512, 512}, velocityVector = {1, 0}, gravityVector = {0, 0}, engineVector = {0.16, 0}, upVector = {0, 0.1}; + xyVector positionVector = {512, 512}, velocityVector = {1, 0}, gravityVector = {0, 0}, + engineVector = {0.04, 0}, upVector = {0, 0.1}, starPosition = {0, 0}; + // Get the initial + ship shipA = createShip(32, 32, 512, 512, 1, 0); + ship shipB = createShip(32, 32, -512, -512, 0, 1); + // Initialize the SDL library, video, sound, and input: if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { @@ -123,12 +194,7 @@ int main(int argc, char ** argv) // Initialize image loading: IMG_Init(IMG_INIT_PNG); SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2"); - - // Create a rectangle to put the ship in: - SDL_Rect shipRect; - shipRect.w = 32; - shipRect.h = 32; - + // Create an SDL window and rendering context in that window: SDL_Window * window = SDL_CreateWindow("SDL_TEST", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 700, 700, 0); SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, rendererFlags); @@ -137,11 +203,11 @@ int main(int argc, char ** argv) SDL_Texture * idleTexture, * acceleratingTexture, * clockwiseTexture, * anticlockwiseTexture, * currentTexture, * acceleratingTexture2; - idleTexture = IMG_LoadTexture(renderer, "./Experiment-12-Images/Ship-Idle.png"); - clockwiseTexture = IMG_LoadTexture(renderer, "./Experiment-12-Images/Ship-Clockwise.png"); - acceleratingTexture = IMG_LoadTexture(renderer, "./Experiment-12-Images/Ship-Accelerating.png"); - anticlockwiseTexture = IMG_LoadTexture(renderer, "./Experiment-12-Images/Ship-Anticlockwise.png"); - acceleratingTexture2 = IMG_LoadTexture(renderer, "./Experiment-12-Images/Ship-Accelerating-Frame-2.png"); + idleTexture = IMG_LoadTexture(renderer, "./Experiment-13-Images/Ship-Idle.png"); + clockwiseTexture = IMG_LoadTexture(renderer, "./Experiment-13-Images/Ship-Clockwise.png"); + acceleratingTexture = IMG_LoadTexture(renderer, "./Experiment-13-Images/Ship-Accelerating.png"); + anticlockwiseTexture = IMG_LoadTexture(renderer, "./Experiment-13-Images/Ship-Anticlockwise.png"); + acceleratingTexture2 = IMG_LoadTexture(renderer, "./Experiment-13-Images/Ship-Accelerating-Frame-2.png"); // Enable resizing the window: SDL_SetWindowResizable(window, SDL_TRUE); @@ -157,7 +223,7 @@ int main(int argc, char ** argv) { switch (event.type) { - case SDL_QUIT: + case SDL_QUIT: { quit = true; break; @@ -222,62 +288,55 @@ int main(int argc, char ** argv) } } - // Wrap the position if the ship goes interstellar: - if(positionVector.xComponent > 4096) + // Wrap the positions if the ship goes interstellar: + if(shipA.position.xComponent > 4096) { - positionVector.xComponent = -2000; - velocityVector.xComponent *= 0.9; + shipA.position.xComponent = -2000; + shipA.velocity.xComponent *= 0.9; } - else if(positionVector.xComponent < -4096) + else if(shipA.position.xComponent < -4096) { - positionVector.xComponent = 2000; - velocityVector.xComponent *= 0.9; + shipA.position.xComponent = 2000; + shipA.velocity.xComponent *= 0.9; + } + if(shipA.position.yComponent > 4096) + { + shipA.position.yComponent = -2000; + shipA.velocity.yComponent *= 0.9; + } + else if(shipA.position.yComponent < -4096) + { + shipA.position.yComponent = 2000; + shipA.velocity.yComponent *= 0.9; } - if(positionVector.yComponent > 4096) + if(shipB.position.xComponent > 4096) { - positionVector.yComponent = -2000; - velocityVector.yComponent *= 0.9; + shipB.position.xComponent = -2000; + shipB.velocity.xComponent *= 0.9; } - else if(positionVector.yComponent < -4096) + else if(shipB.position.xComponent < -4096) { - positionVector.yComponent = 2000; - velocityVector.yComponent *= 0.9; + shipB.position.xComponent = 2000; + shipB.velocity.xComponent *= 0.9; } - + if(shipB.position.yComponent > 4096) + { + shipB.position.yComponent = -2000; + shipB.velocity.yComponent *= 0.9; + } + else if(shipB.position.yComponent < -4096) + { + shipB.position.yComponent = 2000; + shipB.velocity.yComponent *= 0.9; + } + // Store the window's current width and height: SDL_GetWindowSize(window, &width, &height); - // Calculate the vector between the star and ship: - xyVectorBetweenPoints(positionVector.xComponent, positionVector.yComponent, starPositionX, starPositionY, &gravityVector); - - // Make it into a unit vector: - gravityMagnitude = normalizeXYVector(&gravityVector); - - // Calculate the gravity between the star and ship: - if(gravityMagnitude != 0) - { - if(gravityMagnitude >= 215) - { - gravityAcceleration = 10 * (9000 / (pow(gravityMagnitude, 2))); - } - else - { - gravityAcceleration = 0.5 * (5000 / (pow(gravityMagnitude, 2))); - } - } - else - { - gravityAcceleration = 1; - } - - if(gravityAcceleration < 0.01) - { - gravityAcceleration = 0.01; - } - - // Scale the vector: - multiplyXYVector(&gravityVector, gravityAcceleration); + // Calculate the gravity for the ships: + calculateGravity(&starPosition, &shipA); + calculateGravity(&starPosition, &shipB); // Set the texture to idle: currentTexture = idleTexture; @@ -295,10 +354,12 @@ int main(int argc, char ** argv) } // Calculate the new current velocity: - addXYVectorDeltaScaled(&velocityVector, &gravityVector, deltaTime); + addXYVectorDeltaScaled(&shipA.velocity, &shipA.gravity, deltaTime); + addXYVectorDeltaScaled(&shipB.velocity, &shipB.gravity, deltaTime); + if(accelerating) { - addXYVectorDeltaScaled(&velocityVector, &engineVector, deltaTime); + addXYVectorDeltaScaled(&shipA.velocity, &engineVector, deltaTime); frameAccumulator += deltaTime; currentTexture = acceleratingTexture; if((long)frameAccumulator % 4) @@ -308,14 +369,15 @@ int main(int argc, char ** argv) } // Calculate the new position: - addXYVectorDeltaScaled(&positionVector, &velocityVector, deltaTime); + addXYVectorDeltaScaled(&shipA.position, &shipA.velocity, deltaTime); + addXYVectorDeltaScaled(&shipB.position, &shipB.velocity, deltaTime); - positionX = (long)positionVector.xComponent; - positionY = (long)positionVector.yComponent; + // Calculate the position of the sprites: + shipA.rectangle.x = (width/2) - 16; + shipA.rectangle.y = (height/2) - 16; - // Calculate the position of the sprite: - shipRect.x = (width/2) - 15; - shipRect.y = (height/2) - 15; + shipB.rectangle.x = (long)(((shipB.position.xComponent - shipA.position.xComponent) - 32) + width/2); + shipB.rectangle.y = (long)(((shipB.position.yComponent - shipA.position.yComponent) - 32) + height/2); // Set the colour to black: SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); @@ -324,28 +386,32 @@ int main(int argc, char ** argv) SDL_RenderClear(renderer); // Draw the ship: - SDL_RenderCopyEx(renderer, currentTexture, NULL, &shipRect, angleBetweenVectors(&engineVector, &upVector) + 90, NULL, 0); + SDL_RenderCopyEx(renderer, currentTexture, NULL, &shipA.rectangle, + angleBetweenVectors(&engineVector, &upVector) + 90, NULL, 0); + SDL_RenderCopyEx(renderer, currentTexture, NULL, &shipB.rectangle, + angleBetweenVectors(&shipB.velocity, &upVector) + 90, NULL, 0); // Set the colour to yellow: SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255); // Draw a circle as the star: - DrawCircle(renderer, (long)(starPositionX - positionX) + width/2, (long)(starPositionY - positionY) + height/2 , 200); + DrawCircle(renderer, (long)(starPositionX - shipA.position.xComponent) + width/2, + (long)(starPositionY - shipA.position.yComponent) + height/2, 50); // Draw a line representing the velocity: SDL_RenderDrawLine(renderer, width/2, height/2, - (long)((width/2) + velocityVector.xComponent * 15), - (long)((height/2) + velocityVector.yComponent * 15)); + (long)((width/2) + shipA.velocity.xComponent * 15), + (long)((height/2) + shipA.velocity.yComponent * 15)); // Set the colour to blue: SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); // Draw a line representing the direction of the star: - normalizeXYVector(&gravityVector); - multiplyXYVector(&gravityVector, 100); + normalizeXYVector(&shipA.gravity); + multiplyXYVector(&shipA.gravity, 100); SDL_RenderDrawLine(renderer, width/2, height/2, - (long)((width/2) + gravityVector.xComponent), - (long)((height/2) + gravityVector.yComponent)); + (long)((width/2) + shipA.gravity.xComponent), + (long)((height/2) + shipA.gravity.yComponent)); // Present the rendered graphics: SDL_RenderPresent(renderer); @@ -354,5 +420,5 @@ int main(int argc, char ** argv) } // =========================================================================================== // Local Variables: -// compile-command: "gcc `sdl2-config --libs --cflags` SDL2-Experiment-12.c -lSDL2_image -lm" +// compile-command: "gcc `sdl2-config --libs --cflags` SDL2-Experiment-13.c -lSDL2_image -lm" // End: