Creating multiple rectangles using SDL_Rect - c

I'm creating a simulation for Conway's game of life using C and SDL. To represent the alive cells I would like to create multiple rectangles in the window which I have created. Is there any way to call SDL_Rect in a for loop without redefintion of SDL_Rect and output the result of the for loop all on the same renderer? Thank you.
My Code:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
#include <SDL.h>
#define main SDL_main
#undef main
double CreateRectanglesX()
{
double x; double x_max = 640; double x_min = 20;
x = rand() / (x_max - x_min) / (double)RAND_MAX + x_min;
return x;
}
double CreateRectanglesY()
{
double y; double y_max = 480; double y_min = 20;
y = rand() / (y_max - y_min) / (double)RAND_MAX + y_min;
return y;
}
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_VIDEO); //initializes the SDL/SDL2 window
SDL_Window *screen; //SDL window created with pointer
screen = SDL_CreateWindow("My Program Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_OPENGL);
//definition for pointer - dimensions of SDL window
SDL_Renderer *renderer; //Renderer created with pointer
renderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED); //definition for pointer - still to learn
if (screen == NULL) //checks if window exists or not
{
printf("Could not create window: %s\n", SDL_GetError()); //returns error if window doesn't exsit
return 1;
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); //changes color of renderer
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer); //displays the renderer with the changed color
for (int i = 0; i < 5; i++)
{
double x = CreateRectanglesX();
double y = CreateRectanglesY();
printf("%lf %lf", x, y);
SDL_Rect a;
a.x = x;
a.y = y;
a.w = 20;
a.h = 20;
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
SDL_RenderFillRect(renderer, &a);
SDL_RenderPresent(renderer);
}
SDL_Delay(5000); //wait time for window
SDL_DestroyWindow(screen);
SDL_QUIT;
return EXIT_SUCCESS;
}

The mistake was the fact that my random number generation formula with CreateRectanglesX() and CreateRectanglesY was wrong. It was
v = rand() / (x_max - x_min) / RAND_MAX + x_min;
Should have been:
v = rand() * (x_max - x_min) / RAND_MAX + x_min;
Only one rectangle was being displayed because the random numbers being produced with the random generation function were too close (due to wrong formula). Fixing the formula resolved the issue!

Related

Scaling a point from one 2d-space to another

The input to my program is a (x, y) integer coordinate inside the blue region of this circle of radius 100. I want to scale the input coordinate from the blue area to the red area, maintaining the the x and y ratios.
(link to the Desmos plot: https://www.desmos.com/calculator/61f4y2r7r4)
I know how to do this with one dimension - this answer gives a good overview on performing linear scaling. I attempted to apply this approach to the x and y axes separately. Here is some example code that I wrote to model the image.
#include <math.h>
#include <stdio.h>
#define RADIUS 100
static int find_point_on_circumference(int val) {
return sqrt(RADIUS * RADIUS - val * val);
}
static int scale(int val, int min_old, int max_old, int min_new, int max_new) {
return (max_old == min_old)
? val
: (((val - min_old) * (max_new - min_new)) / (max_old - min_old) + min_new);
}
int main() {
int x = 15;
int y = 96;
int boundary_old_x = 10;
int boundary_old_y = 10;
int boundary_new_x = 30;
int boundary_new_y = 20;
int new_x = scale(
x,
boundary_old_x,
find_point_on_circumference(y),
boundary_new_x,
find_point_on_circumference(y));
int new_y = scale(
y,
boundary_old_y,
find_point_on_circumference(x),
boundary_new_y,
find_point_on_circumference(x));
if (sqrt(new_x * new_x + new_y * new_y) <= RADIUS) {
printf("SUCCESS\n");
} else {
printf("FAIL\n");
}
return 0;
}
For this particular input, (15, 96), the result is outside of the circle. I can see that the reason for that is that my max-x bound is less than my min-x bound. I'm just not sure how I should be applying this scaling correctly in the first place.

C Graphics - How to move an object with specific angle

I am working on C graphics program, where I will ask for Projection Angle from end user and then will use that angle to launch the rocket from earth (circle) surface.
But I am not able to do so.
Here what I found on google:
x1 = x + cos(angle) * distance;
y1 = y + sin(angle) * distance;
where x1 y1 are the new pixel position for object.
I tried this but it doesn't seem like working. Also I want rocket to move constantly till the end of screen, but the above code will directly print the object from position A to position B.
Complete Program Code
#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <dos.h>
#include <math.h>
#include <stdlib.h>
#include <iostream.h>
#define cld cleardevice()
int _moonRadius = 20, _earthRadius = 40, _marsRadius = 25;
void mars () {
setfillstyle(9, BROWN);
setcolor(BROWN);
circle(getmaxx() - 25, 50, _marsRadius);
floodfill(getmaxx() - 27, 52, BROWN);
}
void moon () {
setfillstyle(9, WHITE);
setcolor(WHITE);
circle(getmaxx()/2, getmaxy()/2, _moonRadius);
floodfill(getmaxx()/2, getmaxy()/2, WHITE);
// Moon's gravitational area
setfillstyle(SOLID_FILL, DARKGRAY);
setcolor(DARKGRAY);
circle(getmaxx()/2, getmaxy()/2, _moonRadius * 5);
}
void earth () {
setfillstyle(9, GREEN);
setcolor(GREEN);
circle(40, getmaxy() - 100, _earthRadius);
floodfill(42, getmaxy() - 102, GREEN);
}
void rocket (int x, int y) {
setcolor(WHITE);
rectangle(x, y - 105, x + 70, y - 95);
}
void rocket_clear (int x, int y) {
setcolor(BLACK);
rectangle(x, y - 105, x + 70, y - 95);
}
void main () {
clrscr();
int angle, speed;
printf("Please provide input parameters.");
printf("Enter projection angle (range from 5 to 90)\n");
scanf("%d", &angle);
printf("Enter projection speed (range from 10 to 100)\n");
scanf("%d", &speed);
int gd=DETECT, gm, i, j, k;
initgraph(&gd, &gm, "C:\\TURBOC3\\BGI");
// Planets and rocket
mars();
moon();
earth();
rocket(80, 550); // let say initial pixel position x = 80, y = 550
// Moving the rocket
// Right now its only moving towards horizontal line, with speed implementation
// Now here I want to implement the angle of projection
for (i = 81; i < getmaxx() + 100; i++) {
// Also I am not sure about this loop's final range, should it go to getmaxx() or some other range
rocket(i, 550);
rocket_clear(i - 1, 550); // 550 is hard coded right now, so rocket will move only horizontally
delay(500 / speed);
}
getch();
}
Need your help guys, please.
(For reference: you can also think of a moving bullet from killer position to the position of person with some angle)
Thanks :)
Please read the comments starting with //=====
#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <dos.h>
#include <math.h>
#include <stdlib.h>
#include <iostream.h>
#define cld cleardevice()
//===== making these values as constants
static const int _moonRadius = 20, _earthRadius = 40, _marsRadius = 25;
static double projection_angle = 0.0;
void mars () {
setfillstyle(9, BROWN);
setcolor(BROWN);
circle(getmaxx() - _marsRadius, 50, _marsRadius);
floodfill(getmaxx() - 27, 52, BROWN);
}
void moon () {
setfillstyle(9, WHITE);
setcolor(WHITE);
circle(getmaxx()/2, getmaxy()/2, _moonRadius);
floodfill(getmaxx()/2, getmaxy()/2, WHITE);
// Moon's gravitational area
setfillstyle(SOLID_FILL, DARKGRAY);
setcolor(DARKGRAY);
circle(getmaxx()/2, getmaxy()/2, _moonRadius * 5);
}
void earth () {
setfillstyle(9, GREEN);
setcolor(GREEN);
circle(40, getmaxy() - 100, _earthRadius);
floodfill(42, getmaxy() - 102, GREEN);
}
void rocket (int x, int y) {
setcolor(WHITE);
//===== a box of size 10x10
rectangle(x, y, x + 10, y - 10);
}
void rocket_clear (int x, int y) {
setcolor(BLACK);
//===== a box of size 10x10
rectangle(x, y, x + 10, y - 10);
}
void main () {
clrscr();
int angle, speed;
printf("Please provide input parameters.");
printf("Enter projection angle (range from 5 to 90)\n");
scanf("%d", &angle);
//===== angle validation
if (angle < 5 || angle > 90)
{
printf("Please provide angle in range [5, 90]\n");
getch();
return;
}
//===== calculate angle in radians
projection_angle = (angle * 3.14) / 180.0;
printf("projection_angle = %d\n", projection_angle);
printf("Enter projection speed (range from 10 to 100)\n");
scanf("%d", &speed);
//===== speed validation
if (speed < 10 || speed > 100)
{
printf("Please provide speed in range [10, 100]\n");
getch();
return;
}
int gd=DETECT, gm, i, j, k;
initgraph(&gd, &gm, "C:\\TURBOC3\\BGI");
// Planets and rocket
mars();
moon();
earth();
rocket(80, 550); // let say initial pixel position x = 80, y = 550
// Moving the rocket
// Right now its only moving towards horizontal line, with speed implementation
// Now here I want to implement the angle of projection
//===== to store prev position
int prev_i = 0, prev_j = 0;
//===== increments will be constant for a given angle and speed
const int x_inc = cos(projection_angle) * speed;
const int y_inc = sin(projection_angle) * speed;
//===== i and j will be updated with their respective increments
for (i = 90, j = getmaxy() - 100; i < getmaxx() + 100 && j >= -10; i += x_inc, j -= y_inc) {
// Also I am not sure about this loop's final range, should it go to getmaxx() or some other range
//===== clear the previous position
rocket_clear(prev_i, prev_j); // 550 is hard coded right now, so rocket will move only horizontally
//===== draw rocket at current position
rocket(i, j);
//===== make current position as previous position
prev_i = i;
prev_j = j;
//printf("x_inc = %lf, y_inc = %lf\n", cos(projection_angle) * speed, sin(projection_angle) * speed);
delay(500 / speed);
}
getch();
}
Note: You can replace 3.14 with actual Pi. Refer this.
Be sure that you are passing the angle in radians. To convert from degrees: radians=degrees*PI/180 (PI is defined in math.h which should be included by graphics.h) Make sure your variables are doubles.
Next you will probably want to bundle your X/Y coordinates in a struct so you can return the new position from a function:
typedef struct {
double x;
double y
} coord_t;
coord_t new_pos(double x, double y, double distance, double angle_deg) {
coord_t result;
double angle_rad = angle_deg * PI / 180;
result.x = x + cos(angle_rad) * distance;
result.y = y + sin(angle_rad) * distance;
return result;
}
Or you could handle all the angles in radians so the function doesn't have to do the extra calculation.

Animating a trajectory of Cannon Shells C-program

I am unable to see what I did wrong with my code. I am supposed to determine the trajectory that two cannon shells will take when fired at 500 m/s at an angle of 50 degrees above the horizontal. One of the shells is assumed to experience no drag and the other experiences a drag coefficient of 0.0001. I was wondering as to why my code wasn't plotting correctly. Any help would be great!
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "philsplot.h"
// Number of shells
#define N 2
// Defining the value of PI
#define PI 3.1415926535
int main()
{
double xmin, xmax, ymin, ymax, theta = (50 * (PI/180));
int color, style;
double expand;
// philsplot function to open an x-window
open_plot("800x600");
int i,j;
double vx[N], vy[N], x[N], y[N], h, ax[N], ay[N];
h = 0.01;
// philsplot function erases the canvas after flushpoint is called
erase_plot();
// plot using km for distance
xmin = 0; xmax = 1;
ymin = 0; ymax = 1;
expand = 1.1;
color = 1;
// philsplot function to set limits of the plotting canvas
box_plot(xmin,xmax,ymin,ymax,expand,color,"Distance (km)","Height (km)","RRRR","TTTT");
// philsplot function that maps the plotting canvas onto the screen
flush_plot();
style = 2;
color = 3;
expand = 1.0;
// The initial values
for(i=0; i<N; i++) {
// want the initial x-position to be this
x[i] = 0;
// want the initial y-position to be this
y[i] = 0;
// want the initial x-velocity to be this
vx[i] = 0.5*cos(theta);
// want the initial y-velocity to be this
vy[i] = 0.5*sin(theta);
}
for(j=0; j<N-1; j++) {
// Using Euler's method you get this:
ax[j] = (-0.0001) * (0.5) * vx[j];
ay[j] = (-0.00981) - (0.0001) * (0.5) * vy[j];
vx[j] = vx[j] - ax[j] * h;
vy[j] = vy[j] - ay[j] * h;
x[j] = x[j] + vx[j] * h;
y[j] = y[j] + vy[j] * h;
putpoint_plot(x[j],y[j],10, style, color, expand, 1);
flush_plot();
delay_plot(1000);
}
printf("hit enter for next plot: ");
getchar();
return 0;
}

Turtle drawing fractal with openGl

I'm trying to do Koch snowflake for a computer graphics course. Searching on the web i've found that a sequence named Thue-morse can approximate the Koch snowflake by using a turtle drawing method.
Here is the code i have so far:
#include <GLUT/glut.h>
#include <math.h>
#include <string.h>
//screen size
#define WIDTH 1024
#define HEIGHT 800
float x, y,mUx,mUy;
//init the turtle environment
void turtleInit(){
x = WIDTH/2; // this is the starting point for the x
y = HEIGHT/2; // this is the starting point for the y
mUx = 1;
mUy = 0;
}
//move the turtle ds units
void turtleMove(float ds){
x += mUx * ds;
y += mUy * ds;
}
//turn left by "ang" radians if positive and right if negative.
void turtleTurn(float ang){
float ux = mUx;
float uy = mUy;
mUx = ux * cos(ang) - uy * sin(ang);
mUy = uy * cos(ang) + ux * sin(ang);
}
//thue morse sequence used to approximate the Koch snowflake
char thue_memoization[10000000];
int thueMorseRecurrenceRelation(int i){
if( thue_memoization[i] != -1 )
return thue_memoization[i];
if ( i % 2 != 0 )
return thue_memoization[i] = 1 - thueMorseRecurrenceRelation(i / 2);
else
return thue_memoization[i] = thueMorseRecurrenceRelation(i / 2);
}
void display( void ){
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-WIDTH, WIDTH, -HEIGHT, HEIGHT, -50, 50);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(GL_POINTS);
glColor3f(0, 0, 1);
turtleInit();
for (int i = 0; i < 1000000; ++i) {
const static float p = 1;//turtle's step
if ( thueMorseRecurrenceRelation(i) )
turtleTurn(M_PI/3.0);
turtleMove(p);
glVertex2f(x, y);
}
glEnd();
glFlush();
}
int main(int argc,char **argv){
memset(thue_memoization,-1,sizeof(thue_memoization));
thue_memoization[0] = 0; //stop condition for the recurrence relation
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(0,0);
glutInitWindowSize(WIDTH, HEIGHT);
glutCreateWindow("Koch snowflake. The winter is comming ...");
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
It worked quite well here.
But i don't understand how the turtleTurn function works. Someone can help me ?
This is the formula for a 2d rotation:
(mUx, mUy) contains the coordinates of the "heading vector" of the turtle, then what turtleTurn(float ang) does is turning this vector by an angle (ang).
If you want a nice explanation of this formula, in particular where the sine and cosine come from, you can take a look at the following page, that
has some drawings that will make it clearer:
https://www.siggraph.org/education/materials/HyperGraph/modeling/mod_tran/2drota.htm

Why is my ray-traced image entirely black?

I had to generate an image that's a black circle, black being (0, 0 , 0) and white being (1, 1, 1), but I keep getting a completely black image. Here's all my code:
#include "cast.h"
#include "collisions.h"
#include <stdio.h>
#include "math.h"
int cast_ray(struct ray r, struct sphere spheres[], int num_spheres)
{
int isFound;
struct maybe_point mp;
isFound = 0;
for (int i = 0; i < num_spheres; i++)
{
mp = sphere_intersection_point(r, spheres[i]);
if (mp.isPoint == 1)
{
isFound = 1;
}
else
{
isFound = 0;
}
}
return isFound;
}
void print_pixel(double a, double b, double c)
{
int i, j, k;
i = a * 255;
j = b * 255;
k = c * 255;
printf("%d %d %d ", i, j, k);
}
void cast_all_rays(double min_x, double max_x, double min_y, double max_y,
int width, int height, struct point eye,
struct sphere spheres[], int num_spheres)
{
double width_interval, height_interval, y, x;
int intersect;
width_interval = (max_x - min_x)/width;
height_interval = (max_y - min_y)/height;
for (y = max_y; y > min_y; y = y - height_interval)
{
for (x = min_x; x < max_x; x = x + width_interval)
{
struct ray r;
r.p = eye;
r.dir.x = x;
r.dir.y = y;
r.dir.z = 0.0;
intersect = cast_ray(r, spheres, num_spheres);
if (intersect != 0)
{
print_pixel (0, 0, 0);
}
else
{
print_pixel (1, 1, 1);
}
}
I already had functions that I know are correct which find whether or not the ray intersects with a sphere. The function that I used to find intersection points was in the function cast_ray.
sphere_intersection_point(r, spheres[i]);
The print_pixel function translates the integer values by multiplying them with the max color value, which is 255.
And the cast_all_rays function casts rays into the whole scene from our eyes (going through all the x coordinates before changing the y). If the ray intersects with a sphere, the pixel is black, thus, forming a black circle in the end.
And here are the limits for the x, y, and radius (NOTE: I'M USING THE PPM FORMAT):
Eye at <0.0, 0.0, -14.0>.
A sphere at <1.0, 1.0, 0.0> with radius 2.0.
A sphere at <0.5, 1.5, -3.0> with radius 0.5.
min_x at -10, max_x at 10, min_y of -7.5, max_y at 7.5, width=1024, and height=768.
I need to generate an image of a black circle, but I keep getting an image that's completely black. I have a feeling that the problem lies inside the cast_all_rays function, but I just can't seem to find what it is. Help is appreciated! Thanks.
And just in case something went wrong with my testing, here's my test.c file for cast_all_rays:
#include "collisions.h"
#include "data.h"
#include "cast.h"
#include <stdio.h>
void cast_all_rays_tests(void)
{
printf("P3\n");
printf("%d %d\n", 1024, 768);
printf("255\n");
double min_x, max_x, min_y, max_y;
int width, height;
struct point eye;
struct sphere spheres[2];
eye.x = 0.0;
eye.y = 0.0;
eye.z = -14.0;
spheres[0].center.x = 1.0;
spheres[0].center.y = 1.0;
spheres[0].center.z = 0.0;
spheres[0].radius = 2.0;
spheres[1].center.x = 0.5;
spheres[1].center.y = 1.5;
spheres[1].center.z = -3.0;
spheres[1].radius = 0.5;
min_x = -10;
max_x = 10;
min_y = -7.5;
max_y = 7.5;
cast_all_rays(min_x, max_x, min_y, max_y, width, height, eye, spheres, num_spheres);
}
int main()
{
cast_all_rays_tests();
return 0;
}
Not sure if this is the problem you're having, but you should only set isFound if you intersect a sphere. Don't set it if you don't intersect. Otherwise your image will be governed by only the last sphere in the list.
if (mp.isPoint == 1)
{
isFound = 1;
}
//else
//{
// isFound = 0;
//}
Since your image is entirely black, it seems like your intersection code is bung or your field of view is too narrow. If you don't have any joy with the above change, maybe you should post details on your x- and y-limits, the eye position, and the position and radius of the sphere.
One more thing I noticed is r.dir.z = 0.0. Do you subtract the eye position from this to get a direction, or is that your true ray direction? Surely you need to give a non-zero z-direction. Normally you set the x and the y based on your view plane and provide a constant z such as 1 or -1.
[edit]
To make it clearer from the comments below, I believe that you haven't correctly set up your ray direction. Instead you have simply set the direction to be the view-plane's pixel position, ignoring the eye position. The following would be more usual:
struct ray r;
r.p = eye;
r.dir.x = x - eye.x;
r.dir.y = y - eye.y;
r.dir.z = 0.0 - eye.z;

Resources