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.
Related
My main loop is working fine, but the problem I'm encountering is when I click the "esc" button on my keyboard, the shape that I have should move to the right every 1 second for five times then terminate. I did a loop on it, but it doesn't work. I call this function with
case 27:
glutTimerFunc(25, move, 1);
Here's the portion of that code I did:
void move(int value)
{
int i = value;
while (i <= 5)
{
pX += 0.5; //pX is the position of the object in x-axis
i++;
}
glutPostRedisplay();
exit(0);
}
Can you help me point out my mistakes? I'm still confused on how glutTimerFunc works so any tips/explanation would be nice. Thanks.
For some reason when I run the code below... The character only moves diagonally down. Lets say line I"m drawing is character:
\
\
\
\
\
That's the only direction it moves if I press up, right, down or left key!
Please help, I want to go right if right, up if up, down if down, and left if left.
My Code is:
#include<iostream>
#include<string>
#include<SFML\Graphics.hpp>
using std::cout;
using std::endl;
enum Direction
{
DOWN,
LEFT,
RIGHT,
UP
};
int main()
{
sf::RenderWindow _Win(sf::VideoMode(600, 600), "Hello World");
sf::Texture _texture;
if (!(_texture.loadFromFile("Resources/SPRITE.png")))
{
cout << "Could not load iamge" << endl;
}
//Source, tell us our starting position.
//Vector2i = Vector of 2 in SFML
sf::Vector2i source(1, DOWN/*or 0*/);
sf::Sprite _sprite(_texture);
float x = _sprite.getPosition().x;
float y = _sprite.getPosition().y;
while (true)
{
sf::Event _event;
while (_Win.pollEvent(_event))
{
switch (_event.type)
{
case sf::Event::Closed:
_Win.close();
exit(1);
break;
case sf::Event::KeyPressed:
switch (_event.key.code)
{
case sf::Keyboard::Up:
source.y = UP;
_sprite.move(sf::Vector2f(x,y--));
y = 3, x=3;
break;
case sf::Keyboard::Down:
source.y = DOWN;
_sprite.move(sf::Vector2f(x, y++));
y = 3, x = 3;
break;
case sf::Keyboard::Right:
source.y = RIGHT;
_sprite.move(sf::Vector2f(x++, y));
y = 3, x = 3;
break;
case sf::Keyboard::Left:
source.y = LEFT;
_sprite.move(sf::Vector2f(x--, y));
y = 3, x = 3;
break;
}
break;
}
}
//Cropping Out Image
//Please Look at sprite in resources/Sprite.png
//When we run this :
//_sprite.setTextureRect(sf::IntRect( source.x*32 , source.y*32 , 32 , 32 ));
//Its going to give us the top left corner sprite image. Thats so because
//we are cropping source.x*32 , which of 32 is the width of the sprite.. So it
//starts from 1 * 32. 32 is the width of one sprite so it goes to the end of it.
//Same Applies to the y. source.y * 32. It just goes to the end of the down sprite.
//As you go down the y increases, 1 * 32 = 32. And 32 is the width of one sprite
//so it shows body of one full sprite.
_sprite.setTextureRect(sf::IntRect( source.x*32 , source.y*32 , 32 , 32 ));
//Clears Window(Flickering..)
_Win.clear();
//Draw Sprite
_Win.draw(_sprite);
//And Finally Display the Window.
_Win.display();
}
}
In every case of your switch statement, you move the sprite by (x,y), and then either increment or decrement x or y, depending upon the direction. However, this is fruitless, since on the very next line, you reset them both to 3. So in effect, whatever direction key is pressed, you are doing this:
_sprite.move(sf::Vector2f(3, 3));
That is, 3 units to the right and 3 units down, which seems to fit your description of the movement you are seeing. I'm not sure what kind of movement you're going for, but here's an example that could work:
switch (_event.key.code) {
case sf::Keyboard::Up:
_sprite.move(sf::Vector2f(0, -3));
break;
case sf::Keyboard::Down:
_sprite.move(sf::Vector2f(0, 3));
break;
case sf::Keyboard::Right:
_sprite.move(sf::Vector2f(3, 0));
break;
case sf::Keyboard::Left:
_sprite.move(sf::Vector2f(-3, 0));
break;
}
This would move the sprite 3 units each time a direction key was pressed, in that direction.
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
I am making an ncurses game which has a spaceship fire bullets at other enemies.
I've got the ship firing bullets how ever when I fire more than one bullet, only the latest bullet will move and the rest will stay still.
int i=0 , j=-1;
switch(key){
case KEY_UP: playership.row=changeRow(playership.row,-1,playership.col); /* move up */
break;
case KEY_DOWN: playership.row=changeRow(playership.row,+1,playership.col); /* move down */
break;
case KEY_LEFT:playership.col=changeColumn(playership.col,-1,playership.row); /* move left */
break;
case KEY_RIGHT:playership.col=changeColumn(playership.col,+1,playership.row); /* move right */
break;
case ' ': {j++; bullets[0].col=playership.col+5; bullets[j].row=playership.row-2 ;break;}
default: break; /* do nothing if other keys */
}
if (j!=-1){
attrset(COLOR_PAIR(2));
mvprintw(bullets[j].row,bullets[0].col,"%c",bullet);
mvprintw(bullets[j].row+1,bullets[0].col," ");
bullets[j].row=bullets[j].row-1;
refresh();
}
I tried to implement the suggestion from the comments in this answer to my earlier question, but I don't think I've done it right:
If you can have 5 bullets at once, you need to store their positions.
If you have int bullet_pos[5] that would be fine. You could use -1 in
each position to say that no bullets are active. Then when you want to
fire one you search the array to find the first position that is -1
and change it to 0. When you draw the bullets, you go through the
array and draw a bullet for any position that is not -1, and update
its position.
If you don't already, try adding a flag to your bullet structure. Something like alive.
When you want to fire, you check through your array and find an unused bullet position (if any):
for( int i = 0; i < MAX_BULLETS; i++ ) {
if( !bullets[i].alive ) {
bullets[i].alive = true;
bullets[i].row = playership.row;
bullets[i].col = playership.col+5;
break;
}
}
Then when you update or draw:
for( int i = 0; i < MAX_BULLETS; i++ ) {
if( bullets[i].alive ) {
attrset(COLOR_PAIR(2));
mvprintw(bullets[i].row, bullets[i].col, "%c", bullet);
mvprintw(bullets[i].row+1, bullets[i].col, " " );
bullets[i].col++;
// TODO check for bullet death. If bullet is done, set `alive` to false.
}
}
refresh();
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.