carenalgas / popochiu

Godot plugin to make point-and-click adventure games, inspired by tools like Adventure Game Studio and PowerQuest.
https://carenalgas.github.io/popochiu/
MIT License
205 stars 19 forks source link

Better direction checking #334

Closed balloonpopper closed 1 week ago

balloonpopper commented 1 week ago

What's the expected benefit of the feature you are requesting?

From my testing the animation direction checking when you don't have 8 direction animation isn't ideal. Eg A facing direction angle that is anywhere from 22.5 to 67.5 degrees means you're facing down and right.

Lets say

The code will look for a down-right animation, and if it can't find one, it will try for a right facing animation. It will never use the down facing animation.

func _get_valid_oriented_animation(animation_label):
    match _looking_dir:
                <...>
        Looking.DOWN_RIGHT: suffixes = ['_dr', '_r', '_dl', '_l']

In my example it should return the down facing animation as the correct one to use, not the right facing animation.

Though it's unlikely, the solution should also factor in that it's possible that the programmer might not have U/D/L/R animations. e.g. if my game only had animations for UR/UL/DR/DL directions, and the facing direction was "right", the code wouldn't evaluate the correct animation either.

Describe the solution you'd like

Missing animations should choose the nearest animation rather than assuming certain directions should get preference.

Describe alternatives you've considered

None

Additional context

None

stickgrinder commented 1 week ago

This is interesting. The current logic is a "fallback" one, but in fact the number of available animations should inform the angles set against which the direction is calculated.

This may require the dev to explicitely specify which directions are available for the character (or maybe in the game, provided they are consistent), because guessing them may be suboptimal - although feasible.

@balloonpopper should you describe the best use-case, do you want to have full control over the available directions, or having the behavior automatically managed by the engine with a bit of a smarter logic?

stickgrinder commented 1 week ago

I just pushed a change that address the main problem. Now the diagonal slices are checked against the actual angle and the up and down directions are chosen accordingly.

Getting to something more convoluted requires a bit of design, but for now this should improve the experience.

stickgrinder commented 1 week ago

@balloonpopper we merged the improvement in the direction checking in develop, so you can test it if you feel like downloading the branch from github.

About the "diagonal-based" games support (Disco Elysium and Sanitarium comes to my mind), we are going to split this into another issue for later, so we can prioritize it depending on actual demand. Thanks for pointing that out.

Let us know.

stickgrinder commented 1 week ago

Reopening this because it needs more work: probably the explicit facing functions are not working as expected.

I'll take this over.

balloonpopper commented 1 week ago

1) I need to test further, but I don't think the animation directions are being chosen correctly. I have a 4 direction character and it seems to be preferencing down when I believe it should be preferencing right. I'll update this post if I can confirm it's actually wrong rather than it "feels" wrong. 2) I have this code in my room's script

    C.player.position = R.current.get_marker("StartLocation").position
    C.player.face_right()
    if state.Officer1LeftRoom == false:
        C.get_OfficerBlonde().position = R.current.get_marker("BlondeOfficerStart").position
        C.get_OfficerBlonde().face_left()
<...>

None of this logic now works - the character and my 3 NPCs all face downwards now.

Also, to answer your question above :

should you describe the best use-case, do you want to have full control over the available directions, or having the behavior automatically managed by the engine with a bit of a smarter logic?

I would suggest smarter logic. The code will already know which of the animations I have defined (l/r/u/d/ul/ur/dl/dr) for the character. It should be able to find whichever is mathematically nearest the way my character needs to move.

e.g. Theoretically I could have a character with only _L and _U animations defined - if I try and move at 44 degrees, it should use the up animation, and if I try to move at 46 degrees, it should use the left animation. It shouldn't need a default.

balloonpopper commented 1 week ago

The solution I propose here https://github.com/carenalgas/popochiu/pull/339 I believe addresses the preference issue mentioned above.

The logic behind the implementation is:

As shown in the attached example diagram, the first picture shows the way the player wants to walk (orange - approx 50 degrees). The first preference is the 8 direction check. If they have 8 directions, preference DR. The next preference is the 4 direction check. If they have 4 directions, it's closer to down then right, so preference down. The next preference is the 2 direction check. If they have only 2 directions defined, preference right. (If the 2 directions they had were _u and _d instead of _l and _r, down would've been selected at the 4 direction check so it's not needed to preference this at the end.)

This code makes the assumption that: 1) The designer made symmetrical directions for their character (e.g a 2 direction character has _u and _d, and not _u and _r) 2) I followed the original example and preference opposite directions after checking the original (e.g if _r doesn't exist, try _l). It would likely be better if the code had awareness of whether (in this example) "-l" had mirroring selected before preferencing that selection.

image

balloonpopper commented 1 week ago

Also, added a fix for the fault where in the example above, this line wasn't working in the room's script

C.get_OfficerBlonde().face_left()

The cause was that this is in the initialisation code of popochiu_character.gd

var _animation_suffixes: Array = ['_d', '_l', '_r', '']

When the room code sets the facing direction, the NPC runs their idle animation. The request to run the idle animation doesn't reset the animation_suffixes, so the "idle_d" animation will always play. Changing the face_left (etc) code so that it uses the same direction checking code (which sets the facing direction and the animation suffixes) fixes the problem.

stickgrinder commented 1 week ago

Wonderful job @balloonpopper

Closing this now :)