Opinions on platform game actor/background collision resolving - c#

Imagine the following scenario: I have a level whose physical structure is built up from a collection of bounding rectangles, combined with prerendered bitmap backgrounds. My actors, including the player character, all have their own bounding rectangle. If an actor manages to get stuck inside a level block, partially or otherwise, it'll need to be shifted out again, so that it is flush against the block.
The untested technique I thought up during bio break is as follows:
If an actor's box is found to intersect a level box, determine where the centerpoints of each rect are. If the actor's center is higher than the level box's, move the actor so that the bottom of the actor's rect is flush with the top of the level's rect, and vice versa if it's lower. Then do a similar thing horizontally.
Opinions on that? Suggestions on better methods?
Actually, the bounding rects are XNA BoundingBoxes with their Z spanning from -1 to 1, but it's still 2D gameplay.

Have you read the N Tutorials? They're a wonderful introduction, complete with little demos, of Separating Axis Theorem based collision detection and simple projection response. (They're actually used in the N game to great effect.) The tutorials cover more than you need, but they're very general (extensible to many other shapes), and start to touch on issues with fast-moving objects and other response techniques.
Even if you do decide to go with something simpler than a SAT implementation, this may give you a lot of good ideas.
(When you're done with that and if you want your mind blown, try looking into some of the presentations from the Game Developers Conference physics tutorial day, including realtimecollisiondetection.net publications, the essentialmath.com tutorial slides, both of those books, and/or other stuff linked from those sites. I'd highly recommend the GDC session itself, too. While we still don't need or particularly want fancy GJK on swept hulls on the handheld game platforms we work with, some of the simpler concepts such as "configuration spaces" and Minkowski sums and differences have greatly influenced how I think about physics and collision detection and how we implement it.)

What the "real" physics engines do is find the minimum penetration vector. That is - the smallest vector that represents how far inside each other the two objects penetrate.
For an AABB (axis-aligned bounding box) this is really easy to calculate.
(Consider making your own 2D AABB structure, it will be smaller and therefore better for performance.)
Once you have your minimum penetration vector, you can perform collision response. And the easiest response is to simply separate the two objects by that vector (or separate the one object if the other is static).
Here is a good reference, by the makers of N on how to do this for convex polygons and circles. You should be able to simplify this down for AABBs.

A lot depends on the details. A complete solution could take into account velocities or other issues. But treating this simply...
You don't want to always resolve vertically first. Imagine an actor nudges horizontally into a block. If you resolve vertically first then the actor will pop up above that block, when a small horizontal movement would have sufficed.
Find what the vertical and horizontal movements would need to be to "get out of collision", and then apply the one with the smallest absolute value.
Then repeat a few times, in case the movement puts the actor into another block. But don't repeat forever, because the actor could be wedged somewhere that never resolves.
Maybe if your last movement still leaves you in collision, you could just average the last two movements and leave it there.

Another possible approach is, rather than waiting for a collision and then shifting out, check for possible collisions before you move objects and, if there is going to be a collision, move the player only up to the edge of the block.
I.e., contrast how Adventure does collisions with walls: http://www.youtube.com/watch?v=I6-zN_eaRd8
to how most NES games do collisions with walls.

Related

Unity2D: move object along path - unevenly distributed waypoints - constant speed needed

I am currently facing a problem I cannot wrap my head around. In my 2D game which in the end should become some kind of virtual model railway, I can create a path, consisting of different railtypes. Each rail has it's own waypoints. Now the issue is as follows:
Straight rails don't need many waypoints, since they only need two to be defined; The start and the end point. Curves on the other hand need a lot more waypoints, so the objects movement on them is not all jaggy and unsmooth. The problem I am facing is, that the waypoints then are so unevenly distributed on the whole railway, it makes the speed which the object moves along the path very uneven.
I also already know the issue: The points are so cramped in the curve sections that the distribution looks like this:
See this picture for an example with red Gizmo.Spheres as waypoints
Now when I move an object along that said path, I do it like this:
wagon.transform.position = Vector2.MoveTowards(wagon.transform.position, wagon.GetNextPosition(), wagon.GetSpeed());
The third parameter of the method Vector2.MoveTowards() is the maxDistanceDelta, so it can only move that amount into the direction of wagon.GetNextPosition(), which is constantly updated.
The twist is, that the densly packed points result in a way shorter distance than the maxDistanceDelta. So in those parts of the railway, the object moves way slower then wagon.GetSpeed() per frame.
I already have a solution to this, which sadly I cannot use: I took every waypoint and distributed them evenly on the path. I don't want that; I want the path to stay as is, but the speed to the eye to be uniform.
Thanks in advance for your help!
PS: I already looked in similar threads, but none of those solutions seems to work for me :( Namely:
This thread
And this one
I would comment this but unfortunately I don't have enough reputation, so here it is:
The best idea I can think of is to create 2 waypoints for your curve (at the start and finish) and use a parabolic function to define the movement between them. So in other words, your train follows a parabola instead of moving towards waypoints directly.
I found a useful answer on a unity forum about parabolic trajectories which you may find useful for your project (It is the first answer beneath the question at the time of writing).
How are you generating those waypoints?
Could you use bezier curves instead?
If yes, there it's typical to run into exactly this issue and solutions have been found. Not solutions with absolute accuracy, but usually sufficient for games (aka visualizations that in the end only need to be as accurate as the pixels you see).
There is this outstanding video about the topic: https://www.youtube.com/watch?v=aVwxzDHniEw

How do I determine if i just calculated the normal in the correct direction?

To explain the context, I procedurally generate buildings on unity in C#. I create a mesh and fill in the vertices and triangles, then I calculate the normals of the different points. I have several hundreds of buildings that are generated, but some faces are not in the right direction, the normals point inwards instead of outwards.
The normals are good
The normals are bad
To calculate the normals I create a Plane with the different vertex that make up the triangle, and then I retrieve the normal of the Plane. I also tested the cross product that gives the same result.
Plane plane = new Plane(v1, v2, v3);
normals.Add(plane.normal);
How i generate Triangle ?
Ex: I make a for loop on the points at the base of the building.
vectors.Add(v1);
vectors.Add(v2);
vectors.Add(v3); //v3 = v1+height
vectors.Add(v4); //v4 = v2+height
// index values
int idx1, idx2, idx3, idx4;
idx4 = vectors.Count - 1;
idx3 = vectors.Count - 2;
idx2 = vectors.Count - 3;
idx1 = vectors.Count - 4;
// Triangle 1
indices.Add(idx1);
indices.Add(idx3);
indices.Add(idx2);
...
mesh.triangles = indices.ToArray();
So my question is: How to determine if the normal is in the right direction (inside or outside)? If I can determine that, I can then flip the normal and normally it will work.
I do not totally understand your question, but for simple shapes a simple algorithm is ..
just take the "center" of the object (the CG is fine) and make a vector from there to your vertex or triangle. That direction is "outside". If you're pointing over 90° away from that, you're pointing in to the guts of the object
the next more complicated approach ...
move along your normal say "one meter". call that point "test point". you should now be "outside" your building, correct?
now you just need to check if testPoint is inside or outside your 3D shape.
in short, to determine if you are inside or outside a 3D object, you just cast a ray and count how many times you intersect with the walls. if odd, you're inside, if even you're outside.
You can google hundreds of discussions on this on the www, example https://stackoverflow.com/a/63572837/294884
Note that there are many, many variations on this, and many problems too. In some cases you start from "just inside" your normal (ie go backwards a little); sometimes it's better to start from the middle of the object (if such a thing is knowable); sometimes there are issues about how the ray casting system works in edge cases (like "right on" the surface, which is what your vertex is)
the first solution seems to me to be the right one
It may be. Sometimes it is useless. It depends on the nature of your shapes.
I wanted to avoid having to do raycast ..
Can assure you - you will have to constantly raycast during any construction process! If you wish to "avoid" casting, set the idea aside. You will be casting until you are sick of it :)
I wanted to avoid having to do raycast to limit the generation time
The good news is this is totally incorrect. Casting is extremely trivial and a very minor burden compared to everything going on in a 3D scene. When you play any 3D scene, casts are being made 100s and 1000s of times each frame.
but if I have two buildings that are close to each other, the ray will find the wall but from the second building so I couldn't determine the normal is "inside" or "outside", right?
TBC in the simple system I described. You would certainly ONLY cast against that same building that you are working on! So that's the way to go.
But indeed, unrelated to what you're asking about. Say you're in a "city". You can indeed cast through "all walls" and the parity (ie: odd or even) will let you know if you are indoors or out. This has problems though, relating to edges, corners etc. But in some case it is relevant to that problem.
As mentioned on this answer https://stackoverflow.com/a/63593282/294884 ultimately you can investigate convex hulls and more. It's a big topic!
Note that often when you build dynamic buildings/shapes, you havce a data structure of each "wall" and indeed it knows which side is in and which side out. When you do that first, it's then easy to draw the triangles the correct way. It's a big topic!

Simulate depressurization in a discrete room

I am trying to build a top down view spaceship game which has destructible parts. I need to simulate the process of depressurization in case of hull breach.
I have a tiled map which has the room partitioning code setup:
What I am trying to do is build some kind of a vector field which would determine the ways the air leaves depressurized room. So in case you would break the tile connecting the vacuum and the room (adjacent to both purple and green rooms), you'd end up with a vector map like this:
My idea is to implement some kind of scalar field (kind of similar to a potential field) to help determine the airflow (basically fill the grid with euclidean distances (taking obstacles into account) to a known zero-potential point and then calculate the vectors by taking into account all of the adjacent tiles with lower potential value that the current tile has:
However this method has a flaw to where the amount of force applied to a body in a certain point doesn't really take airflow bottlenecks and distance into account, so the force whould be the same in the tile next to vacuum tile as well as on the opposite end of the room.
Is there a better way to simulate such behavior or maybe a change to the algorithm I though of that would more or less realistically take distance and bottlenecks into account?
Algorithm upgrade ideas collected from comments:
(...) you want a realistic feeling of the "force" in this context, then it should be not based just on the distance, but rather, like you said, the airflow. You'd need to estimate it to some degree and note that it behaves similar to Kirchoff rule in electronics. Let's say the hole is small - then amount-of-air-sucked-per-second is small. The first nearest tile(s) must cover it, they lose X air per second. Their surrounding tiles also must conver it - they lose X air per second in total. And their neighbours.. and so on. That it works like Dijkstra distance but counting down.
Example: Assuming no walls, start with 16/sec at point-zero directing to hole in the ground, surrounding 8 tiles will get 2/sec directed to the point-zero tile. next layer of surrounding 12 tiles will get something like 1.33/sec and so on. Now alter that to i.e. (1) account for various initial hole sizes (2) various large no-pass-through obstacles (3) limitations in air flow due to small passages - which behave like new start points.
Another example (from the map in question): The tile that has a value of zero would have a value of, say, 1000 units/s. the ones below it would be 500/s each, the next one would be a 1000/s as well, the three connected to it would have 333/s each.
After that, we could base the coefficient for the vector on the difference of this scalar value and since it takes obstacles and distance into account, it would work more or less realistically.
Regarding point (3) above, imagine that instead of having only sure-100%-pass and nope-0%-wall you also have intermediate options. Instead of just a corridor and a wall you can also have i.e. broken window with 30% air pass. For example, at place on the map with distance [0] you've got the initial hole that generates flux 1000/sec. However at distance [2] there is a small air vent or a broken window with 30% air flow modifier. It means that it will limit the amount from incoming (2x500=1000) to 0.3x(2x500)=300/sec that will now flow further to the next areas. That will allow you to depressurize compartments with different speeds so the first few tiles will lose all air quickly and the rest of the deck will take some more time (unless the 30%-modifier window at point [2] breaks completely, etc).

How to implement Pentago AI algorithm

i'm trying to develop Pentago-game in c#.
right now i'm having 2 players mode which working just fine.
the problem is, that i want One player mode (against computer), but unfortunately, all implements of minimax / negamax are for one thing calculated for each "Move" (placing marble, moving game-piece).
butin Pentago, every player need to do two things (place marble, and rotate one of the inner-boards)
I didn't figure out how to implement both rotate part & placing the marble, and i would love someone to guide me with this.
if you're not familiar with the game, here's a link to the game.
if anyone want's, i can upload my code somewhere if that's relevant.
thank you very much in advance
If a single legal moves consists of two sub-moves, then your "move" for game algorithm purposes is simply a tuple where the first item is the marble placement and the second item is the board rotation e.g.:
var marbleMove = new MarbleMove(fromRow, fromCol, toRow, toCol);
var boardRotation = new BoardRotation(subBoard, rotationDirection);
var move = new Tuple<MarblMove, BoardRotation>(marbleMove, boardRotation);
Typically a game playing algorithm will require you to enumerate all possible moves for a given position. In this case, you must enumerate all possible pairs of sub-moves. With this list in hand you can move on to using standing computer game playing approaches.
Rick suggested tuples above, but you might want to actually just have each player make two independent moves, so it remains their turn twice in a row. This can make move ordering easier, but may complicate your search algorithm, depending on which one you are using.
In an algorithm like UCT (which is likely to outperform minimax for simple implementations) breaking into two moves can be more efficient because the algorithm can first figure out what moves placements are good, and then figure out what rotation is best. (Googling UCT doesn't give much. The original research paper isn't very insightful, but this page might be better: http://senseis.xmp.net/?UCT)

How to effeciently spread objects on a 2D surface in a "natural" way?

i would like to effeciently generate positions for objects on a given surface. As you probably guessed this is for a game. The surface is actually a 3D terrain, but the third dimension does not matter as it is determined by terrain height.
The problem is i would like to do this in the most effecient and easy way, but still get good results. What i mean by "natural" is something like mentoined in this article about Perlin noise. (trees forming forests, large to small groups spread out on the land) The approach is nice, but too complicated. I need to do this quite often and prefferably without any more textures involved, even at the cost of worse performance (so the results won't be as pretty, but still good enough to give a nice natural terrain with vegetation).
The amount of objects placed varies, but generally is around 50. A nice enhancement would be to somehow restrict placement of objects at areas with very high altitude (mountains) but i guess it could be done by placing a bit more objects and deleting those placed above a given altitude.
This might not be the answer you are looking for, but I believe that Perlin Noise is the solution to your problem.
Perlin Noise itself involves no textures; I do believe that you have a misunderstanding about what it is. It's basically, for your purposes, a 2D index of, for each point, a value between 0 and 1. You don't need to generate any textures. See this description of it for more information and an elegant explanation. The basics of Perlin Noise involves making a few random noise maps, starting with one with very few points, and each new one having twice as many points of randomness (and lower amplitude), and adding them together.
Especially, if your map is discretely tiled, you don't even have to generate the noise at a high resolution :)
How "often" are you planning to do this? If you're going to be doing it 10+ times every single frame, then Perlin Noise might not be your answer. However, if you're doing it once every few seconds (or less), then I don't think that you should have any worries about speed impact -- at least, for 2D Perlin Noise.
Establishing that, you could look at this question and my personal answer to it, which is trying to do something very similar to what you are trying to do. The basic steps involve this:
Generate perlin noise; higher turbulence = less clumping and more isolated features.
Set a "threshold" (ie, 0.5) -- anything above this threshold is considered "on" and anything above it is considered "off". Higher threshold = more frequent, lower threshold = less frequent.
Populate "on" tiles with whatever you are making.
Here are some samples of Perlin Noise to generate 50x50 tile based map. Note that the only difference between the nature of the two are the "threshold". Bigger clumps means lower threshold, smaller clumps means a higher one.
A forest, with blue trees and brown undergrowth
A marsh, with deep areas surrounded by shallower areas
Note you'll have to tweak the constants a bit, but you could do something like this
First, pick a random point. (say 24,50).
Next, identify points of interest for this object. If it's a rock, your points might be the two mountains at 15,13 or 50,42. If it was a forest, it would maybe do some metrics to find the "center" of a couple local forests.
Next, calculate the distance vectors between the the point and the points of interest, and scale them by some constant.
Now, add all those vectors to the point.
Next determine if the object is in a legal position. If it is, move to the next object. If it's not, repeat the process.
Adapt as necessary. :-)
One thing: If you want to reject things like trees on mountains you don't add extra tries, you keep trying to place an object until you find a suitable location or you've tried it a bunch of times and you need to bail out because it doesn't look placeable.

Categories

Resources