CleverRaven / Cataclysm-DDA

Cataclysm - Dark Days Ahead. A turn-based survival game set in a post-apocalyptic world.
http://cataclysmdda.org
Other
10.65k stars 4.18k forks source link

Multiple valid positions should be attempted when pulling a vehicle. #19934

Closed Asmageddon closed 5 years ago

Asmageddon commented 7 years ago

Because sometimes it weirds out, and cannot realize that you actually should be able to haul it through a spot.

natsirt721 commented 7 years ago

Vehicle dragging has always been weird, and even more so recently. See #19770

Coolthulhu commented 7 years ago

It's easy for 1-tile vehicles, but anything more than that could act really weird.

Asmageddon commented 7 years ago

Well, there are multiple valid ways to drag a vehicle, e.g. change angle slightly, or the square of the being-dragged part, and to be honest, most wouldn't be much weirder than what happens presently, but attempting them would solve great many "why can't I drag the vehicle here..." issues.

Aivean commented 7 years ago

I was harboring a model of better dragging for some time. Maybe this is a good place and time to share it.

The main idea is quite simple. There are two points of the dragged vehicle:

During the step of the drag:

That's it. This model makes dragged and pushed multitile vehicle turn "realistically" taking wheels into account. And even better it also allows to implement trailers and vehicle towing relatively easy (just by adding vehicle tile that acts as "dragging point" for another vehicle).

I can see several limitations and corner cases:

I can elaborate on the description of the model and/or provide some illustrations if you find the idea worthy.


UPD: Here is the small demo which illustrates the model. Drag the vehicle with the mouse to see how it behaves. I didn't restrict tiles where drag can be applied, but note that in game this point will always lie on the outer tiles.

Also I forgot to mention the biggest restriction of this model: It doesn't account for wheel direction. Wheels behave like static "legs", which means that they have equal resistance when dragged in any direction.

mutability commented 7 years ago

so that the distance between these points remains constant

Distance between which points?

note that we already have "wheel center", it is the vehicle pivot point

Aivean commented 7 years ago

@mutability Distance between drag point and the "center" always remains constant.

Here I created a small demo to illustrate that model: http://codepen.io/aivean/full/ygywQd/

You can edit the car layout (it's at the very top of the source) so see how model behaves in different situations.

Asmageddon commented 7 years ago

That seems a bit odd tbh. And I dunno, it'd probably still have weird cases with dragging and obstacles sometimes.

mutability commented 7 years ago

That demo 404s for me.

From your description it's basically reasonable though, I had been playing with something similar a while back. A couple of notes:

natsirt721 commented 7 years ago

I imagine that rounding floats from the angle/distance calculations into integer coordinates could cause some issues but conceptually this seems pretty solid. Also, how is the pivot point determined? If I have a semi-trailer and I drag it from the front, does it pivot about the rear wheels or the areal center?

mutability commented 7 years ago

If I have a semi-trailer and I drag it from the front, does it pivot about the rear wheels or the areal center?

Rear wheels. It's basically a weighted average of the wheel positions. See https://github.com/CleverRaven/Cataclysm-DDA/blob/aa8c7d4083b9339731c68488f9ee603a8722f75f/src/vehicle.cpp#L4848

Aivean commented 7 years ago

@mutability This link should work (I tried it from different browsers in private mode). Not sure why it's not working for you.

Regarding your notes:

you have to handle the degenerate case where the "new drag point" is coincident with the old pivot center

Nice catch. I believe the simplest way to solve this is following: if the old dragging point is not coincident with "wheel center" then you can perform two-step simulation. First you assume "new dragging point" as the center of the line segment between old and "actual new" dragging points and move vehicle center accordingly. This will ensure that "actual new dragging point" and "new wheel center" are no longer coincident, so you perform the same calculation again.

The more interesting question is what happens if vehicle is being dragged by it's "wheel center". There is not way to avoid it, as you can construct U-shaped vehicle and drag it from "the inside". This looks like a case that requires completely separate treatment.

 

because you grab a vehicle part that is adjacent to the player position, the drag point is not just the player position; how do you find the new drag point? Or do you ignore the grabbed part and transform the player position into vehicle coordinates (there will - usually - not be a vehicle part there)?

I've been thinking about that for a while and I don't see any reason why "dragging point" can't be outside of the vehicle even if there is no actual vehicle tile there (i.e. player's center point). The demo shows that.  

when rotating in the final step, I assume you calculate the change in drag-center line angle and apply that change to the overall vehicle rotation, rather than directly pointing the vehicle along the line

Correct.  

because we don't have continuous coordinates, the rotate-and-translate step needs to be something like: apply the rotation, transform the drag point from vehicle coordinates to world coordinates using the new rotation angle, translate the vehicle so that that the transformed drag point is at the new player position

I was thinking that all points are to be stored and calculations performed in continuous coordinates and then mapped to discrete ones, but I don't see why calculations in discrete coordinates won't work.

 

@Asmageddon

That seems a bit odd tbh. And I dunno, it'd probably still have weird cases with dragging and obstacles sometimes.

I never claimed that this model is accurate simulation. However this model is very simple (that means it has a decent chance of being implemented) and it's clearly better than current drag model.

I'm not sure that dragged vehicle should automatically avoid obstacles. You don't expect player to go around the obstacle if you're commanding to move directly into it, do you? Also, what if you intentionally want to ram obstacle with dragged vehicle?

mutability commented 7 years ago

Ok, it works in incog mode, I guess it is an interaction with my plugins.

It seems to handle things better than the current system: push/pull/rotate all behave much as you'd expect, so long as you're not expecting the vehicle to roll preferentially along the forward/back axis.

Only oddity I notice is that dragging from a point close to the center produces very strong rotations, I wonder if we can damp those.

Aivean commented 7 years ago

Only oddity I notice is that dragging from a point close to the center produces very strong rotations, I wonder if we can damp those.

I think this can be solved by introducing some kind of "feedback". In other words, you first calculate linear and angular shift of the vehicle and then you adjust the angular shift and recalculate vehicle position again.

The simplest way is to just restrict angular shift by some constant number. So if vehicle tries to turn by more than N degrees during the drag step it will instead turn by N degrees and it's "wheel center" will be moved accordingly.

More complex and probably more accurate way is to calculate the work ratio between angular and linear drag. Then, during the drag step, if rotation is required, partially transform rotation into linear shift, so that the total work is minimized.

I'll try different variants in the demo later.

Aivean commented 7 years ago

I revised the model.

Now it accounts for the directional resistance of the wheels. On each step the ratio of angular and linear drag is calculated, so that amount of "work" is minimal ("work" means effort required to overcome the friction).

In practice it means that vehicle prefers to "roll" forward or backward along the direction of the wheels. This also naturally solves the problem of free rotation when drag point is close to vehicle center (but only if vehicle has more than one non-steering axis).

Updated demos:

Asmageddon commented 7 years ago

That really looks nice, but I've got to admit that without a grid, I can't quite tell how well it'd be likely to behave in C:DDA.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. Please do not \'bump\' or comment on this issue unless you are actively working on it. Stale issues, and stale issues that are closed are still considered.

stale[bot] commented 5 years ago

This issue has been automatically closed due to lack of activity. This does not mean that we do not value the issue. Feel free to request that it be re-opened if you are going to actively work on it