1
\$\begingroup\$

Is there a common trick for getting around sprites that are changing directions 'too quickly' and causing their sprite to display erratically?

In this project, the player moves in 8 directions by determining the abs() distance between the mouse's X and Y coordinates and its own obj.rect.center. If the absolute value is less than obj.speed, it simply moves to that point. If it is greater, it moves the distance its speed allows it to move in that direction. When it's time to draw the sprite, PyGame rotates it in accordance to obj.direction by using a dict called SPINNER with stored default values to pass to pygame.transform.rotate.

def draw(obj):
    drawImg = pygame.rotate.transform(obj.img, SPINNER[obj.direction])
    drawCtr = drawImg.get_rect(center=obj.rect.center)
    DISPLAYSURF.blit(drawImg, drawCtr)

This is fine for the foolish AI characters which typically make very few course corrections - however, small movements of the mouse can cause the player's obj.direction to update very quickly, which looks chaotic.

Is there a simple way to curb this behavior? My first guess is to bog down the player object with values that retain its previous state and then determine the amount of rotation to apply, but I have a feeling the better solution is to assign that responsibility to the 'view' and not the 'model'. I'm not sticking to any hard and fast rules regarding MVC, but I am trying to engage in enough separation of concerns that 'view-like methods' don't make 'controller-like' changes to 'model-like' objects, if that makes sense.

\$\endgroup\$
  • \$\begingroup\$ Try adding a dead zone to your calculations. Essentially you would need to move x pixels in a given direction before the character would rotate to the target rotation. \$\endgroup\$ – user39686 Dec 31 '13 at 17:12
1
\$\begingroup\$

I think you want a certain amount of "hysteresis" in your system here; this is commonly used in many kinds of systems to prevent rapid back-and-forth switching.

For example, you might add a 2.5 degree buffer, so when moving from top-right to right, an angle above 70 degrees is needed, but to move from right to top-right, and angle below 65 degrees is needed. This will stop the rapid flicking between the two.

As this is a concern of the display, I would say this probably belongs in View. You only need one additional attribute, to hold which of the 8 directions the object is currently pointing, and one argument, the new angle from the Model. The View layer then decides whether the new angle means a displayed change of direction.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.