Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Jitter while moving

Credits go to DanielH and Indeterminatus for helping out!
This thread is locked; no one can reply to it. rss feed Print
Jitter while moving
ismqdb
Member #23,641
January 2023

I wrote a very simple Allegro app that spawns a circle (filled with a solid color, no texture), detects if that circle is selected and, if it is, moves it to another spot based on a mouse click.

If I set the moving speed to a low value, moving works pretty nicely. But the more I increase the speed, the more I get this jitter/oscillation of the circle around the destination point. And the program is unable to continue because the circle didn't reach it's destination and it's flag is left unset, therefore clogging the whole program.

Any suggestions on why is this happening? First thoughts that came to mind are screen tearing and/or vector normalization but I'm unsure.

Any advice is highly appreciated as I've started game dev pretty recently.

DanielH
Member #934
January 2001
avatar

Might need to increase checks per move.

Collision on moving objects is not so simple. Most time you divide the distance by n increments. If too jittery,

#SelectExpand
1// change in distance from current position to final position 2int delta_x, delta_y; 3 4// number of increments 5int n; 6 7// amount to move all objects per increment; 8int increment_x = delta_x / n, increment_y = delta_y / n; 9 10for (int i = 0; i < n; ++i) 11{ 12 move_object(increment_x, increment_y); 13 14 if collision() 15 { 16 // move back 17 move_object(-increment_x, -increment_y); 18 } 19}

If multiple moving objects then you need to take each object and increment based on each object's velocity / n. If still too jittery, then increase n.

Indeterminatus
Member #737
November 2000
avatar

The issue of never reaching your destination might also hint a problem with floating point precision (if you're using floating point math, that is).

It's hard to tell without code -- care to share your sample?

_______________________________
Indeterminatus. [Atomic Butcher]
si tacuisses, philosophus mansisses

ismqdb
Member #23,641
January 2023

@DanielH Good idea. I've implemented it and moving works perfectly now. When I increase the speed of the move, it always arrives to its destination.

However, the jitter it still there. For example, if I take the same circle and let it react to key press to move on x or y axis, it moves but it's jittery. When it starts, it travels lets say 20% of the distance, slows down and then passes other 80% consistently, all while I'm holding one arrow key and not doing anything else. Random example but you get the idea, inconsistent.

I'm assuming it could be something related to framerate (I'm using 60 fps rn). For example, I'm thinking I could iterate [0-fps] and move by (axis offset/fps) distance.

@Indeterminatus Nothing special there but sure, here it is, before the adjustments that implement steps.

bool Vec3::translate(double a, double b, double c){
    this->x += a;
    this->y += b;
    this->z += c;
    return true;
}

DanielH
Member #934
January 2001
avatar

Need to see some code (more code than the translate function). Could be many things.

ismqdb
Member #23,641
January 2023

Sure.

Main loop is standard event handling.

#SelectExpand
1switch(primitives.event.type){ 2 case ALLEGRO_EVENT_TIMER: 3 if(primitives.key[ALLEGRO_KEY_UP]){ 4 circle.translate(0, -10, 0); 5 } 6 7 if(primitives.key[ALLEGRO_KEY_DOWN]){ 8 circle.translate(0, +10, 0); 9 } 10 11 if(primitives.key[ALLEGRO_KEY_LEFT]){ 12 circle.translate(-10, 0, 0); 13 } 14 15 if(primitives.key[ALLEGRO_KEY_RIGHT]){ 16 circle.translate(+10, 0, 0); 17 } 18 19 if(primitives.key[ALLEGRO_KEY_ESCAPE]) 20 primitives.done = true; 21 22 for(int i = 0; i < ALLEGRO_KEY_MAX; i++) 23 primitives.key[i] &= KEY_SEEN; 24 25 primitives.redraw = true; 26 break; 27 28 case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: 29 break; 30 31 case ALLEGRO_EVENT_KEY_DOWN: 32 primitives.key[primitives.event.keyboard.keycode] = KEY_SEEN | KEY_RELEASED; 33 break; 34 case ALLEGRO_EVENT_KEY_UP: 35 primitives.key[primitives.event.keyboard.keycode] &= KEY_RELEASED; 36 break; 37 38 case ALLEGRO_EVENT_DISPLAY_CLOSE: 39 primitives.done = true; 40 break; 41 }

Circle.cpp handles instantiation, clipping to screen and rendering.

#SelectExpand
1#include "Circle.hpp" 2 3Circle::Circle(Vec3 pos, double rad){ 4 if(rad <= 0) 5 throw std::invalid_argument("Circle radius can't be negative or zero."); 6 7 this->position = pos; 8 this->radius = rad; 9 10 this->top = Vec3{pos.X(), pos.Y() - rad, 0}; 11 this->bottom = Vec3{pos.X(), pos.Y() + rad, 0}; 12 this->left = Vec3{pos.X() - rad, pos.Y(), 0}; 13 this->right = Vec3{pos.X() + rad, pos.Y(), 0}; 14} 15 16bool Circle::isMoveAllowed(double a, double b, double c){ 17 if((this->left.X() + a) < 0) 18 return false; 19 20 if((this->right.X() + a) > screenWidth) 21 return false; 22 23 if((this->top.Y() + b) < 0) 24 return false; 25 26 if((this->bottom.Y() + b) > screenHeight) 27 return false; 28 29 return true; 30} 31 32bool Circle::translate(double a, double b, double c){ 33 if(this->isMoveAllowed(a, b, c) == true){ 34 this->position.translate(a, b, c); 35 this->top.translate(a, b, c); 36 this->bottom.translate(a, b, c); 37 this->left.translate(a, b, c); 38 this->right.translate(a, b, c); 39 return true; 40 } 41 42 return false; 43} 44 45bool Circle::drawItself(){ 46 al_draw_filled_circle(this->position.X(), this->position.Y(), this->radius, al_map_rgb(255, 0, 0)); 47 return true; 48}

DanielH
Member #934
January 2001
avatar

Your code doesn't match what you first said.

Is it only jittering when it reaches destination or always?

If only destination, I would suspect simple rounding issues. You have to account for that.

If distance from circle to destination is < amount I move in one step then set circle to destination. Other wise you overshoot and then have to rebound and overshoot and rebound .....

ismqdb
Member #23,641
January 2023

Yeah, well, I guess this isn't really for me. I'll probably go back and do embedded in C.

Thank you for your help though. All the best. :)

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Don't give up just yet. You have to understand the nature of graphics, screens, and pixels.

If you're moving something by 10 every time a timer fires say at 60 times per second, that's 600 pixels per second. That's pretty fast. If you move an object more than a pixel at a time, it will appear to jump or teleport.

Jitter could also be caused by vsync, but more often it is tearing that is caused.

You can try drawing a trail behind the circle and attempt to 'smear' or 'wipe' the image along it's path, but that might not look so good.

If your circle is moving back and forth between two adjacent pixels (jittering?) then it is indeed a floating point issue. I can't tell in your code if those are floating point xyz positions or not.

ismqdb
Member #23,641
January 2023

Hello Edgar, 

I'm not giving up because I can't solve some issue, be it a graphics problem or not. I have solved many complex issues before. The thing is, I got fed up with C++ and with OOP in general. This is something I wanted to ask either on Reddit or StackOverflow. Ask for some advice, and I'll probably do it at some point.

I really like C's simplicity. C++ has much more functionality, but I dislike it. I don't like its complexity; it's gotchas and 300 different ways of doing things. 

I like simple functions and simple structures, i.e., C. The only things I used in C++ that are not in C are private struct/class members and class member functions. 

I genuinely wanted to learn C++ and OOP. I devoted 1–1.5 years to learning it every day. Yet, when I was learning templates, STL, and (god forbid) design patterns, I had the urge to vomit because of their convoluted nature and attitude of "do this, is good" and, after a year or two, don't do that, it's bad; do this instead (e.g., malloc -> new -> smart pointers).

I then lost a job because of this. I did 80% of the project myself in the OOP language, using light abstractions and mostly simple functions. Simple, straightforward, and easy to test and change. It works. Yet, a person comes to the project after 2 months and wants to rewrite everything so it fits into that nice, round OOP bullshit. When I objected, they kicked me out.

That's the reason I want to call it a day. I'm just fed up with all that OOP crap. At least, if I go and do development in C, I won't have to deal with it. That Linus quote about C++ is always hovering above my head. And I don't think I can find a job with C in game development; it is mostly C++ and, to some degree, C#.

Sorry for the long post.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Good sir, I'm sorry you lost your job over OOP garbage. Simpler design always wins in my opinion. And C++ isn't about doing everything the C++ way. You're perfectly free to keep programming C++ in "C". Inheritance is really the best part of C++, STL is useful so you don't have to keep writing your own data types, and design patterns are about writing reusable effective code. If you want to give it another go, try reading Scott Meyer's Effective C++ book. It will help you see some of the more obscure gotchas of the language and how to easily deal with them. It's not nearly as dense as anything by Byarne Stroustrup himself.

ismqdb
Member #23,641
January 2023

Well, to be honest, it looks like you're reading my mind. I did learn C++ from Bjarne's books.

Me losing a job was a bit rough, but the way I see it, it might be a blessing in disguise.

I understand the rationale behind STL, design patterns, and similar, but I don't think it's a good language (or not for me, at least). It's a cacophony of different techniques and approaches; it's gargantuan, and it will probably be replaced by some other language since it refuses to break compatibility. I try not to reinvent the wheel, but if I'm learning some algorithm, I want to focus on its functionality and not be anxious about something exploding into my face.

At this point, I'm more interested in learning assembly and (maybe) Rust. At least, when I'm working in assembly (or C), my mind is at peace.

DanielH
Member #934
January 2001
avatar

Assembly!!! It's a challenge and I like challenges. Which machine would you want to learn? Just curious.

I took a whole semester at college where we programmed for the Motorola 68HC11 microprocessor. That was one of my more enjoyable classes.

As opposed to my current "fun" project. I'm working on writing an instruction decoder/processer for the TMS9900 microprocessor. This one is more challenging. It's one step in the larger project: a emulator/disassembler for the TI994a computer.

ismqdb
Member #23,641
January 2023

Damn, that sounds interesting. I'd love to hear more about that. 

The first time I got in contact with assembly was when I saw a guy writing a game using a Motorola 68K on Computerphile. I found some kind of sandbox for it (easy 68k) and wrote a couple of programs for it. 

After that, I left it and focused more on C/C++. As the time passed, I wondered how certain C/C++ constructs translated to assembly. I started disassembling code at first, and after that, I dived in fully to learn it.

Architecture is x86-64; first I did it in nasm, but I didn't like the syntax of it and switched to GAS.

Go to: