I am a begginer. I am using Monogame and Farseer Physics Library in C#. (latest versions)
In my game, whenever my ball (circle) hits the corner of a rectangle, (or even another circle), it is supposed to only change direction on the Y-Axis.
However, it does not only change direction on the Y-Axis, (as intended), but it also moves a small amount to the right as well (or the left accordingly), depending on how you hit the corner (or another circle). It is as if some force is being put on the ball, making it move on X-Axis as well.
This movement is cool and all, and it makes a lot of sense, but in my game, it does not, therefore i want to get rid of it.
How is this possible ? I am guessing i have to change some default values.
This what my coding looks like:
BallBody.BodyType = BodyType.Dynamic;
BlockBody.BodyType = BodyType.Static;
Ball.LinearVelocity = new Vector(0,-1); // ball going up
BallBody.OnCollision += Ball_OnCollision;
public bool Ball_OnCollision(Fixture f1, Fixture f2, Contact contact)
{
// if the Ball (f1), collides with the Block (f2)
if (f2.Body == BlockBody)
// change the direction of the Ball on Y-Axis
Ball.LinearVelocity = new Vector(0,-1);
return true;
}
Also with high speeds, this occurs:
Even though the ball is never able to pass through the Block (tunneling), I want to know how could i possible fix that so that the ball never enters the Block area ?
Unfortunately, this is surprisingly difficult to do with Box2D. The best I could manage when I tried, was to record the velocity of the ball when the contact started, and then when the contact ends, manually set the velocity to what I wanted. That works fine when the ball only begins and end contact with one block at a time, but in some cases the ball can begin touching two blocks in the same time step. You would have to look at the arrangement of the blocks it touched, and calculate for yourself what angle you would expect it to bounce away at. Eventually I just gave up and did not bother to cover that case.
Related
I have started to make Pacman and would like to know how can i write in my code the direction where the Ghost is going ? So if the transform.position.y is growing, its obvious Up Direction and so on....
This is for the Direction Change if they're hit the Wall.
Any suggestions?
It depends on how you've got your game set-up. One manual way you could go about it is by saving the position in a frame, and in the next frame you calculate the difference between the two positions (the previous frame and the actual frame), and divide that by the time that has passed (Time.deltaTime).
Another way you could go about it (and I would recommend if possible) is simply getting the Rigidbody component and checking the velocity attribute: https://docs.unity3d.com/ScriptReference/Rigidbody-velocity.html
Keep in mind, since this is a beginner's question, that the fact that an object is moving in a certain direction may not come from a ribidbody. As I said, this depends on your exact set-up.
I'm doing a AI using the NavMesh pathfinding solutions, and I don't to want to use a NavMeshAgent because of some limitations (like teleporting when a carved object comes close, etc.),
Thus I made a sort of fusion, moving a Rigidbody on the path of NavMesh.CalculatePath(), this is working quite good so far, but I have trouble detecting the OffMeshLinks on my path (because it's just an array of Vector3).
I can "trick" a bit using NavMesh.Raycast() like above, but it's not working all the time and sometimes detecting OffMeshLinks that aren't one
NavMeshHit hit;
//Raycast between two corners of a path, because OffMeshLink are most of the time over a hole
if (NavMesh.Raycast(_pathCorners[0], _pathCorners[1], out hit, NavMesh.AllAreas))
{
//If the hit position is really close to the corner, it's surely a offmeshlink generate from the NavMesh
//Or if the second corner is higher than the first one, it's surely a offmeshlink I generate myself
if ((hit.position - _pathCorners[0]).sqrMagnitude < 1
|| _pathCorners[0].y < _pathCorners[1].y)
{
ActivateJump(_pathCorners[0], _pathCorners[1]);
}
}
Thanks in advance :)
My Problem can be seen through this video..
You will be able to see in the link above that until I move rod down every thing works well but as soon as I move down the burger gets stuck in the rod. Help me I want it to just deflect off the surface. Something like ping pong game....
For deflection I used the following snippet of code.
foreach (Bar rod in bar)
{
if(rod.CollisionRectangle.Intersects(GameBall.CollisionRectangle))
{
GameBall.speed *= -1;
Console.WriteLine("game" + GameBall.speed);
}
}
Here gameball refers to the burger and rod refers to the images at the top and the bottom.
What seems to be happening is that the rod is overlapping the ball more than the ball is moving in one frame. In other words, if the ball is moving 3 pixels per frame but the objects are overlapping by 5 pixels they won't be able to come out of collision by simply changing direction. You'll need to actually move the ball out of collision first.
That said, collision detection and response is always tricky code to write. The key is to separate the detection code from the response code.
In other words. For every frame:
Detect all collisions
Move all objects
What you're doing now is moving things during the detection phase. That's going to lead to trouble when 2 objects are moving towards each other.
There's way more material on this subject than I can fit into an answer. I suggest looking around for tutorials on AABB collision detection.
Is your CollisionRectangle the built in Rectangle class in MonoGame/XNA?
Assuming it is and the loop is in Update, maybe you could try inserting a break so that it'll stop updating the gameball speed immediately after the first change. This is because the game is updated 60 times per second, there condition might be true for a few miliseconds or so when the game is updating.
foreach (Bar rod in bar)
{
if(rod.CollisionRectangle.Intersects(GameBall.CollisionRectangle))
{
GameBall.speed *= -1;
Console.WriteLine("game" + GameBall.speed);
break;
}
}
Let me know if it doesn't work and maybe i can try it in a new project when i'm free.
When the ball intersect with the bar, you change the direction but the collision is still here so maybe you can try this:
foreach (Bar rod in bar)
{
if(rod.CollisionRectangle.Intersects(GameBall.CollisionRectangle))
{
GameBall.speed *= -1;
// Reset position of the ball
// Something like :
// For the top bar
Gameball.y = rod.y + rod.height;
// For the bottom bar
// Gameball.y = rod.y - Gameball.height
Console.WriteLine("game" + GameBall.speed);
}
}
Sorry if this question is a bit open ended, but I'm pretty new to C# and XNA... and this forum in fact!
I'm creating a game and require a beam of light to emit from a fixed point (bottom left in attached screen capture, belonging to class named PowerStation) and reflect from mirrors which can be moved and rotated by the user. I've added a per-pixel collision detection method, as can be seen working in the attached capture (Mirror turns red).
Currently I've been trying to test for obstacles to the beam's path by creating a Point and moving it along the path of the light until a collision is detected; from there recording the distance travelled and then stretching the Beam sprite in a non-uniform way by the required amount. This is proving difficult already and I think there's still a long way to go with this method.
I was just wondering if anyone has any advice as to the best method to go about detecting obstacles, their rotation, and determining the direction to reflect the Beam (by which side of Mirror is hit), before I fully commit to something that might get really complicated or never even work?
Here is what my Beam class looks like currently... all but one classes inherit from one base class called Object and Objects are all declared in a static objectList belonging to a separate class Items. Apologies if this is bad, messy coding!
class Beam : Object
{
private Vector2 start;
private double length;
private Vector2 POC;
public Beam(Vector2 pos)
: base(pos)
{
spriteName = "beam";
depth = 0.2f;
solid = true;
foreach (Object o in Items.objectList)
{
if (o.GetType() == typeof(PowerStation))
{
start = o.Origin;
}
}
}
public override void Update()
{
Point newPoint = new Point((int)Origin.X, (int)Origin.Y);
while ((!(collision(new Mirror(new Vector2(0, 0))))) && (newPoint.X > 0) && (newPoint.Y > 0)) // && boundaries of window
{
newPoint.Y--; //will be changed to a Vector
}
POC = PointOfCollision(new Mirror(new Vector2(0, 0))); // Need to make it do POC of newPoint, not just the Beam Object!
length = FindLength(start, new Vector2(50, 50));
//Scale = new Vector2( , ); //amount to scale sprite
base.Update();
}
private double FindLength(Vector2 pos1, Vector2 pos2)
{
return (Math.Sqrt(Math.Pow(Math.Abs(pos2.X - pos1.X), 2.0f) + Math.Pow(Math.Abs(pos2.Y - pos1.Y), 2.0f)));
}
}
Any help would be greatly appreciated! Thanks in advance
Forget pixels--since the mirrors apparently can be at any angle you'll certainly have places where you intersect a mirror not on an even pixel. While you could simply count the impact point as the even pixel this will produce a slightly wrong path for the beam.
Instead, take your beam and iterate over all the mirrors, compute the intersection of the beam and the plane of the mirror (handle the case where there is no intersection), then check the intersection to make sure it's within the physical mirror. Record the match that occurs within the shortest distance.
You can almost certainly speed this calculation by figuring bounding boxes for all the mirrors in advance and when checking a beam note what quadrant it's heading towards from the current point--you can reject at least half (and usually 3/4) of all the mirrors with two integer comparisons each.
Repeat until there is either no intersection (the beam escapes) or it hits something that stops it rather than reflects it.
If there are a LOT of mirrors you could take this even farther and chop the screen up into sectors, each of which has a list of mirrors in it. Check only the mirrors in the current sector, if you don't get a hit figure out what sector it enters next and repeat. This is a bit more math casting the ray of the beam in exchange for excluding most of the mirrors without a single instruction. If you are dealing with user-placed mirrors I doubt there would be enough of them to be worth doing it.
Represent everything as vectors: your light beams and the sides of the shapes they bounce upon. Then it's very simple algebra to detect intersections and reflection angles. It'll also be infinitely faster than any pixel-based detection.
I am using Farseer Physics Engine to build a "Monster Dash" like game targeted for the PC using C# and XNA,
I am trying to move a body with it's texture, the texture is built from parts so they all should move together, basically it looks like this:
public void Update()
{
tilingFloorPosition.X += (floorMoveSpeed / MeterInPixels);
_tilingFloorBody.Position = tilingFloorPosition;
// Update the textures position
for (int i = 0; i < texturePositions.Length; i++)
{
texturePositions[i].X += floorMoveSpeed;
}
}
But whenever my player lands on top of the floor he just goes through it like there is nothing there, what am I doing wrong?
If the player is falling through the floor then I can only assume that either the floor's body isn't actually in position, or the two bodies are not colliding. Can you confirm that the floor is indeed positioned correctly? If you're able, turn on the Farseer Debug View. If so, then the collision must not be occurring.
Check:
That both the player and the floor are not sensors.
That they are not within the same CollisionCategory and at least one of them is included within the others CollidesWithCategory.
That you have not added one of the bodies to the others IgnoreBody list.
That the body types will collide. See: Farseeer Body Types.
Also, it may be worth noting that it is possible that manually setting the position could skip the collision. Try instead setting the LinearVelocity.