180 to -180 motion in opengl c++? - c++

i'm using a glutTimerFunc(...) to achieve motion of robot arm, my problem is left side 0 degree to 90 is easily done,
when i try 0 to -90 degree, the arm is not stoping? i tried various methods, but all falied, can you suggest better options?
here's my timer function, void myTimerFunc(int var)
{
switch(var)
{
case 1: if(shoulder>=90)
stop=1;
if(!stop)
{
shoulder = (shoulder + 5);
glutPostRedisplay();
glutTimerFunc(100,myTimerFunc,1);
break;
}
if(shoulder<=0)
stop1=1;
if(!stop1)
{
shoulder = (shoulder - 5);
glutPostRedisplay();
glutTimerFunc(100,myTimerFunc,1);
break;
}
case 2: if(shoulder>=360)
stop2=1;
if(!stop2)
{
shoulder = (shoulder - 5);
glutPostRedisplay();
glutTimerFunc(100,myTimerFunc,2);
break;
}
// here robot arm is not stopping...........
if(shoulder<=270)
stop2 = 0;
stop3 = 1;
if(!stop3)
{
shoulder = (shoulder + 5);
glutPostRedisplay();
glutTimerFunc(100,myTimerFunc,2);
break;
}
default:break;
}
}
i'm calling this from keyboard function.......
void keyboard (unsigned char key, int x, int y)
{
switch (key)
{
case 's':
glutTimerFunc(100,myTimerFunc,1);
break;
glutTimerFunc(100,myTimerFunc,2);
break;

Looks to me like you're confused about how to treat angles. Are you using a [0, 360] scale for a full circle or [-180, +180]? I see a check against 270 in your code, but your prose mentions -90. Yes, they're "the same", but if it's not working perhaps some confusion has crept into your code.
If you're going with [-180, +180], with zero degrees as the neutral position for your robot arm, perhaps you can take advantage of symmetry and use the absolute value function. You only have to code it once that way. If it's successful for [0, +90] it'll also work for [-90, 0] as well.
It also seems to me that you're not taking advantage of object-oriented thinking. This method has motion and timing and graphical refresh all in the same method. Writing smaller methods and unit testing each one to be sure that it works is a better approach. It's called "decomposition". The moment you say "it's a big method", it suggests to me that perhaps it's too big and needs to be refactored.

Related

I don't get the expected feedback of a basic rectangle collision implementation in C++

Hi I am building a basic game in wich I have to detect collisions between an array of sprites. For now the sprites just move forward and change direction randomly or when reached a screen edge. The game is made in C++ with my college graphich library.
I implemented a basic algorithm for detecting collisions into this function:
bool DetectarColisionTanques(strTanque tanque1, strTanque tanque2) {
if(
(tanque1.px + tanque1.width >= tanque2.px) &&
(tanque1.px <= tanque2.px + tanque2.width) &&
(tanque1.py + tanque1.height >= tanque2.py) &&
(tanque1.py <= tanque2.py + tanque2.height)
) {
return true;
} else {
return false;
}
}
Sorry that code is in spanish, tanque1 and tanque2 are 2 structs containing each sprite coordinates wich I want to see if collide, px and py are the sprite origin at the upper left edge of the image.
But when I try to run the function i don't get the expected feedback:
void MoverEnemigos(){
for (int i=0;i<nEnemigos;i++) {
switch (enemigos[i].dir) {
case 0: enemigos[i].py-=enemigos[i].vel;break;
case 1: enemigos[i].px+=enemigos[i].vel;break;
case 2: enemigos[i].py+=enemigos[i].vel;break;
case 3: enemigos[i].px-=enemigos[i].vel;break;
for (int k= i+1; k<nEnemigos; k++) {
if(DetectarColisionTanques(enemigos[i],enemigos[k])) {
printf("Collision detected");
printf("\n");
}
}
}
enemigos[i].width= esat::SpriteWidth(spriteTanque[enemigos[i].dir]);
enemigos[i].height= esat::SpriteHeight(spriteTanque[enemigos[i].dir]);
}
}
In this function called MoverEnemigos() I move all the sprites px and py depending on their direction and then I try to call the function DetectarColisionTanques() to see if I get the printf at the same time I see in my graphic window that the sprites are obviously colliding. But I never ever get the printf.
PD: All the functions are running in a while at 60fps.

How to move car towards direction of tires in OpenGL

I am trying to get a car to move in OpenGL in a semi-realistic manner, with the car going roughly in the direction of it's front tires (which can turn, just like real car tires).
I don't know how to make the car go towards the tires. I am taking input from the keyboard (key down and key up) using SDL2 like this:
case SDLK_LEFT:
car.setTireRotationSpeed(-TIRE_ROTATION_SPEED);
break;
case SDLK_RIGHT:
car.setTireRotationSpeed(TIRE_ROTATION_SPEED);
break;
case SDLK_UP:
car.setCarForwardSpeed(CAR_MOVEMENT_SPEED);
break;
case SDLK_DOWN:
car.setCarForwardSpeed(-CAR_MOVEMENT_SPEED);
break;
And similarly for key release:
case SDLK_LEFT:
if (car.getTireRotationSpeed() == -TIRE_ROTATION_SPEED)
car.setTireRotationSpeed(0);
break;
case SDLK_RIGHT:
if (car.getTireRotationSpeed() == TIRE_ROTATION_SPEED)
car.setTireRotationSpeed(0);
break;
case SDLK_UP:
if (car.getCarForwardSpeed() == CAR_MOVEMENT_SPEED)
car.setCarForwardSpeed(0);
break;
case SDLK_DOWN:
if (car.getCarForwardSpeed() == -CAR_MOVEMENT_SPEED)
car.setCarForwardSpeed(0);
break;
This sets variables in the car that are used every frame to move the car/rotate the tires on the car (since the chasis and the tires are separately rendered) in a smooth fashion.
I am using glm-math (i.e. glm:vec3, glm::mat4, etc) to accomplish the transformations, and I am using shaders to draw and texture.
Every time the whole car is rendered, it goes through the following steps:
void Car::Render(Shader & shader, Camera & camera)
{
incrementFrontTireRotation(getTireRotationSpeed());
move();
chasisTexture.Bind(0);
shader.Update(getChasisTransform(), camera);
chasisMesh.Draw();
tireTexture.Bind(0);
shader.Update(getTireTransform(Car::FRONT_RIGHT), camera);
tireMesh.Draw();
//Repeated for the other tires
}
Each of the shader.Update() calls takes a custom Transform class, which is simply a wrapper for the glm::translate, glm::rotate, and glm::scale and returns the glm::mat4 that represents the model's matrix transformations, based on the transformations I specify.
The incrementFrontTireRotation method and the move method are where I am having trouble.
void Car::incrementFrontTireRotation(float amount)
{
if (amount > 0)
{
if (frontTireRotation.y + amount <= MAX_FRONT_TIRE_TURNED)
frontTireRotation.y += amount;
else
frontTireRotation.y = MAX_FRONT_TIRE_TURNED;
}
else if (amount < 0)
{
if (frontTireRotation.y + amount >= -MAX_FRONT_TIRE_TURNED)
frontTireRotation.y += amount;
else
frontTireRotation.y = -MAX_FRONT_TIRE_TURNED;
}
if (carForwardSpeed != 0)
carRotation += glm::vec3(0, -amount, 0);
}
frontTireRotation is a glm::vec3 that is used for calculating the rotation of the front tires, since they can turn side to side. carRotation is intended to be the rotation of the car.
void Car::move()
{
forward = glm::vec3(glm::rotate(-tireRotation, glm::vec3(0, 1.0f, 0)) * glm::vec4(forward, 1.0f));
position += forward * carForwardSpeed;
}
My intent is to try to get the car to move in the same direction in which the front tires are facing. I am trying to do this with the forward vector, but it is having some weird results. The car does indeed turn, but after too much turning the car no longer moves the way the tires are pointing.
I know this is a lot. Let me know if I need to clarify anything.
The tires of a car should be aligned such that their axes meet at a common pivot like so:
As you see, the two front tires must have a different angle. So the easiest way to handle turns is to consider a virtual central wheel whose angle you control via a steering variable.
This steering then lets you calculate the radius of the turn circle on which the car must move. This will depend on the length of the car. Given this radius, you can calculate the pivot point. Then, when updating the car's location and rotation, all you need to do is rotate the entire car about the pivot. The rotation angle should be chosen in a way that the resulting circle segment is equal to the way the car should travel in a given frame time (i.e. angle * r = velocity * t, angle in radians).
Some care must be taken when no or very little steering happens. In this case, the turn radius becomes infinite and you cannot do a reasonable rotation. Switching to a simple translation in this case can solve this problem.

OpenGL:How to make "Feet" go up and down?

I'm writing code that draws a polygon and gives it two feet, walks from the right until it gets to the middle, does a flip, and then lands and walks to the left. I'm having a lot of trouble figuring out how to animate his feet. All I want to do is make one go up, then come down, then the other go up, and then come down. I know all I have to do is change the Y values of his feet, but I can't figure out how.
My professor talks about key frames a lot, but wouldn't every step that my "Polyman" would take be a key frame leading to infinite amount of cases? Here is my timer function...
void TimerFunction(int value) //float plx = 7.0, ply=-3.0, linet=0.00;
{
switch(frame)
{
case 1:
dx-=0.15;
plx-=0.15; //dx=polygon, plx = one foot, pl2x = other foot
pl2x-=0.15;
if(dx<=0.0)
{
plx=0.0; //this case makes polyman walk to the middle
dx=0.0;
pl2x=0.0;
frame=2;
}
break;
case 2:
dxt+=0.05;
if (dxt<=-0.00) //this is a triangle I translate over polyman appearing as if he's opening his mouth
{
dxt=0.00;
frame=3;
}
break;
case 3:
dy+=0.2;
theta+=10.0;
thetat+=10.0;
dyt+=0.2; //this is the flip with polyman's mouth open
ply+=0.2;
pl2y+=0.2;
linet2+=10.0;
linet+=10.0;
if(dy>5.0 || theta>360.00)
{
dy=5.0;
dyt=5.0;
ply=5.0;
pl2y=5.0;
linet2=0.0;
theta=0.0;
thetat=0.0;
linet=0.0;
frame=4;
}
break;
case 4:
dy-=0.2;
dyt-=0.2;
ply-=0.2;
pl2y-=0.2;
if(dy<=-3.0) //this is polyman coming back down to earth
{
dy=-3.0;
dyt=-3.0;
ply=-3.0;
pl2y=-3.0;
frame=5;
}
break;
case 5:
dxt-=0.2;
if (dxt<-3)
{ //this is the triangle slowly translating left appearing as if he's closing his mouth
dxt-=3.0;
}
if (dxt<=-8)
{
dxt = -8;
frame = 6;
}
break;
case 6:
dx-= 0.15;
plx-= 0.15;
pl2x-=0.15; //this is polyman walking off the stage to the left
if(dx<=-8.0)
{
dx=-8.0;
plx=-8.0;
pl2x=-8.0;
}
break;
}
glutPostRedisplay();
glutTimerFunc(30, TimerFunction, 1);
}
All variables that are used in my timerfunction are global. Thanks for your time! If you need any more of my code just ask and i'll append.

trying to use switch statement to move an image in relation to mouse position c++ SFML

as I'm new to coding in general I'm sure that my thinking is just heading in the wrong direction with this however..
I'm trying to get a sprite to chase the mouse on left click. I had tried to use else if statements but only the first 2 statements would run even on multiple clicks.
I want to be able to say if mouseposition.x > playerposition.x then move playerimage right, and so one for the other directions.
as I'm using sfml, I've used the below to get the positions of both.
sf::Vector2i mousePosition = sf::Mouse::getPosition(window);
sf::Vector2f playerPosition = playerImage.getPosition();
I was hoping to use the switch statement as below but I'm at a loss as to how to create the argument and compare the cases to that argument.
if(sf::Mouse::isButtonPressed(sf::Mouse::Left))
switch()
{
case 1:
playerImage.move(0.02, 0);
case 2:
playerImage.move(-0.02, 0);
case 3:
playerImage.move(0, -0.02);
case 4:
playerImage.move(0, 0.02);
}
Maybe something like this?
if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
sf::Vector2f offset;
if (mousePosition.x > playerPosition.x) {
offset.x = 0.02f;
} else if (mousePosition.x < playerPosition.x) {
offset.x = -0.02f;
}
if (mousePosition.y > playerPosition.y) {
offset.y = 0.02f;
} else if (mousePosition.y < playerPosition.y) {
offset.y = -0.02f;
}
playerImage.move(offset);
}

creating combinations of obstacles in a 2D side scroller game

My first game in ALLEGRO 5 with c++.
It has a player that keeps moving continuously in right direction. From the right edge of the screen player faces obstacles like triangles and squares. These obstacles come alive at right edge of screen and die at left edge of screen.
Suppose X is triangle and O is square.
i want to create them in few combinations like
..{x} {xo} {xoox} {oxxo} {oxx}... And some variations(random maybe)
And after that I will randomize the occurence of these pattern.
SO I found a method to implement what i wanted. I used a switch() to randomly select various cases of combination. It works pretty well. But once in a while it overlaps even after I introduced a minimum gap xoff
Here is the code:
`//I have used srand(time(NULL)); once in main function too.
if(state == PLAYING)
{
ball->Moveball();
ball->Jumpball();
//Camera-----------
ball->Cameraupdate();
al_identity_transform(&camera);
al_translate_transform(&camera,-Cameraposition[0],-Cameraposition[1]);
al_use_transform(&camera);
if(rand() % 200==0)
{
xoff+=200;// to introduce a minimum gap between them but this also fail once in a while.
int ch;
ch=rand()%4;
switch(ch)
{
case 0:
//T
triangle = new Triangle(850 + Cameraposition[0]+xoff,319);
objects.push_back(triangle);
triangle->SetAlive(true);
break;
case 1:
//TT
triangle = new Triangle(850 + Cameraposition[0]+xoff,319);
objects.push_back(triangle);
triangle->SetAlive(true);
triangle = new Triangle(850 +30+ Cameraposition[0]+xoff,319);
objects.push_back(triangle);
triangle->SetAlive(true);
break;
case 2:
//S
square = new Square(850 + Cameraposition[0]+xoff,310);
objects.push_back(square);
square->SetAlive(true);
break;
case 3:
//SS
square = new Square(850 + Cameraposition[0]+xoff,310);
objects.push_back(square);
square->SetAlive(true);
square = new Square(850 +82+ Cameraposition[0]+xoff,310);
objects.push_back(square);
square->SetAlive(true);
break;
}
}
`
Problem solved :(For those who experienced similar doubt)The above code solves the problem of creating random combination of obstacles and generating those combinations randomly. But do check for collisions if you don't want to get overlapping combinations.
Just add another for loop:
void createObstacles(int numObstacles)
{
for(int i = 0; i < numObstacles; i++)
{
if(rand() % 2 == 0)
{
// Create a triangle.
}
else
{
// Create a square.
}
}
}
Call this every time you want to create obstacles, controlling the number of objects released at one time by changing the parameter numObstacles.
You can now do:
if(rand() % 200 == 0)
{
// Create anywhere from 1 to maxToCreate (which is 4) obstacles at a time.
const int maxToCreate = 4;
int numToCreate = (rand() % maxToCreate) + 1;
// Call the function to make some obstacles.
createObstacles(numToCreate);
}
Since your shapes are overlapping, either fix your initialization code to initialize them the way