C# XNA Making the object stay within the bounds - c#

I currently have a method that checks to see if I go out of bounds either from either the top/bottom/sides. The object itself is a ball, and I have a question about getting the ball bouncing off the edges correctly? How do I go about this?
// The behavior is not quite what I want.
if ( InsideOfBounds )
{
Vector3 mCenter = Ball.getCenter();
Vector3 normalizeV = tempCenter;
normalizeV.Normalize();
mHeroBall.setVelocity(-testSpeed * normalizeV);
}

I can provide you with an example from a Breakout-clone written in XNA:
Ball.cs
Basically, you flip the right component of velocity to make a 'perfect' rebound. If you want, you can add friction or elasticity by multiplying by a coefficient like 0.95 or 1.1 so your ball speed change.

When you update the position of your object (ball), you want to check if the new value is out of bounds (and which bount Top\Bottom or Left\Right). If the it actually out of bounds, flip the correct element in your speed vector.
example: if the ball has passed the left bound then BallSpeed.X = -BallSpeed.X
don't forget to update the ball's position with the new speed and not the old at this point, or it will fly off the screen for the current frame (unless that isn't an issue).

Related

How do I check if a sprite is at a specific location on Monogame XNA C#

I am making a game and am fairy new to this language and I need to detect if a sprite has reached a certain location for the game to have some sort of response.
something like;
if ( /* position of sprite1 == (100,400) */ )
{
// Do stuff;
}
First, you need to have an Vector2 variable that keeps their position stored.
Then, you can use that Vector2 to compare one position with another.
A possible idea is to use it like this:
Vector2 position = new Vector2(0,0);
if (position == new Vector2(100, 400))
{
//Do stuff
}
and then in the place where you draw your sprite, you replace the sprite's location with the position variable.
Keep in mind though, position checking is very precise, if you miss on one pixel, you won't be triggering the if-statement.
Often, you rather want to do collision checking using Rectangle, so you have a whole 'hitbox' to check positions with. Though that depends on the context of your game.

Unity player collision with horizontal small colliders

I know the title isnt very explanatory, but here's my problem:
I have a player (merely a cube with a rigidbody, a collider and a movement script), and I have a floor made of small 1 by 1 by 1 cubes (cubes with box colliders).
For some reason unknown to me, when my player cube falls and tries to collide horizontally with the floor, he just phases through... But want him to get blocked by the cubes just like it does vertically. Any help would be greatly appreciated ;)
heres how the scene looks like
heres a cube object
heres the player object
Here's a gif of the player going through the floor
Here's my c# player movement script (I know its very bad, but I prefer to put this here just in case its linked to my problem) :
void ApplyMovement()
{
transform.position += new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
}
If you need any more info to help me just tell me, I'll provide it as fast as I can.
The value of
new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"))
is framerate-dependent. This means the faster the framerate the faster your object will move. This is usually not what you want. Instead use Time.deltaTime
// Adjust the speed in the inspector
public float speedMultiplicator = 1;
//...
new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")) * speedMultiplicator * Time.deltaTime
to get a framerate-independent movement. Also see the example in Input.GetAxis.
When dealing with RigidBody never change the transform.position (and rotation) directly!
If you would want to make the RigidBody jump to a certain position rather use
rigidBody.position = transform.position + ...;
However what you want is a smooth movement in order to keep the collision detection intact. So you should use RigidBody.MovePosition instead
rigidBody.MovePosition(transform.position + ...);
You don't have to deal with force etc.
Also add a RigidBody component to the floor objects. Even ifnthe object is not moving this improves the collision detection (at the cost of performance in the Physics engine ofcourse). And since the objects are not supposed to move set
isKinematic -> true
use Gravity -> false
you can also set freeze position and freeze rotation.
On both floor and player objects set Collision Detection -> Continous Dynamic. This improves the collision detection and looks for collisions also between frames.
Be aware, however, that dynamic detection is quite expensive so use it only if there is still trouble with too fast objects.
On the player you might want to also use interpolate as well.
Finally
Note that continuous collision detection is intended as a safety net to catch collisions in cases where objects would otherwise pass through each other, but will not deliver physically accurate collision results, so you might still consider decreasing the fixed Time step value in the TimeManager inspector
to make the simulation more precise, if you run into problems with fast moving objects.
For more information see the RigidBody manual and the Colliders manual
I recreated the scenario you described on my end. I put your "ApplyMovement" code in "Update". I was basically able to reproduce your results.
It seems to me that the issue might be Freezing Position X/Z on the Player. I think since you are doing that, you're telling the Rigidbody component that it is not allowed to modify the X/Z positions of the objects as part of it's collision resolution and physics simulation. When I turn those two off, I get results that are (I think) closer to what you're looking for.
One note: your "ApplyMovement" code is frame-locked, meaning your player will move at different speeds at different frame rates. To solve this, you'd need to multiply your Input.GetAxis values by Time.deltaTime.
Also, if your player moves too fast, it'll still be able to pass through collisions and cause odd behavior, so be sure to limit the max movement rate of the player to some reasonable value.
You should be applying a force to the Rigidbody of the character instead of directly manipulating the transform.position (this is preventing the physics engine from resolving the collisions). You're also freezing the X and Z position on the Rigidbody; you don't want that because it entirely prevents the Rigidbody from manipulating those values.
Instead of transform.postion += ... first get a reference to the Rigidbody somewhere in your script (best done in an Awake() method):
private Rigidbody _body;
private void Awake() {
_body = GetComponent<Rigidbody>();
}
Then make sure the vector built from your inputs is being applied to the object's "movement," not its position:
Vector3 inputVector = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
// You can multiply this vector by a float to adjust "speed"
_body.ApplyForce(inputVector, ForceMode.VelocityChange);
Finally, you should read up on the different ForceMode options and decide which one fits your preferences: https://docs.unity3d.com/ScriptReference/ForceMode.html
Don't forget this should happen in a FixedUpdate(), not an Update() (all physics operations should be done in FixedUpdate())
As a side note, there is also the possibility your rigidbodies still up moving too quickly and passing through each-other. Even when you're using forces and velocities, this is possible so if your run into this case down the line, investigate Collision Detection Modes. TLDR; they're settings for performance vs accuracy trade-offs.

ball reflection angles Xna c#

I'm trying to find a way to handle reflections for a breakout clone.
I would upload an image to the post instead of the following paragraph, however i have not yet gained the privilege of that yet.
If the ball intersects the left hand side i want it to bounce off to the left.
if the ball intersects the right hand side i want it to bounce off to the right. if the ball intersects the middle section i want it to bounce up the way. i want to learn how to make it bounce in a varying direction dependant on what side of the left, right, or middle section was intersected
I would like to not use three separate rectangles for this, i want to learn how to do it with one.
I use a Vector2 for ball velocity, projVel.
It's position is projPos.
A rectangle for the paddle lightRect.
The reason I use proj.collRect for the beginning of the if is because I cannot use the intersect method with Vector2.
This is my makeshift collision handler at present, which does work but the speed changes to an extent which renders the game unplayable. The speed clamp i have only slightly slows it down i think. i have a variable for projSpeed i cannot clamp that or it will never be able to stop.
if (proj.collRect.Intersects(lightSaber.lightRect))
{
proj.projPos.Y = lightSaber.lightRect.Y - proj.projTxr.Height;
proj.projVel.Y *= -1;
proj.projVel.X = 10 * (proj.projPos.X - lightSaber.lightRect.Center.X) / (lightSaber.lightRect.Center.X);
}
proj.projVel.X = Math.Max(-4, Math.Min(proj.projVel.X, 4));
proj.projVel.Y = Math.Max(-4, Math.Min(proj.projVel.Y, 4));
Help me by showing me how I could do this, maybe in the Math. method, or even an alternative to .Intersects so I can use projPos instead of collRect.
I really am not sure where to start, if there is another way I could do it an example would be great.
Instead of manipulating X and Y velocities independently, I recommend that you calculate a reflection angle based on the position and then derive the velocity from the angle and the speed prior to impact.
Example:
// NOTE: this code assumes that positive Y is down
if (proj.collRect.Intersects(lightSaber.lightRect) && projPos.projVel.Y > 0.0f) // only bounce if projectile is moving downward
{
// remember current speed for when we calculate new velocity
var projSpeed = projVel.Length();
// make sure the projectile no longer intersects the bar
proj.projPos = lightRect.Y - proj.projTxr.Height;
// interpolate reflection angle
var t = (proj.projPos.X - lightSaber.lightRect.X) / lightSaber.lightRect.Width;
var reflectDegrees = 150.0f - t * 120f; // straight up +/- 60 degrees
var reflectRadians = reflectDegrees * (float)Math.PI / 180.0f;
// final velocity determined by angle and original projectile speed
proj.projVel = new Vector2((float)Math.Cos(reflectRadians) * projSpeed, -(float)Math.Sin(reflectRadians) * projSpeed);
}

How to add random x, 0, z movement to GameObjects on Terrain?

I'm inexperienced with UnityScript and C#, and a solution I can study would be greatly appreciated.
The behavior I want is for Pickups to move in random directions on a terrain, changing direction if they encounter a rigid body or static object.
I tried the script "Wander.cs" available here:
http://wiki.unity3d.com/index.php/Wander
However, when played, the script turns the game object on end, and I cannot correct this. Also, objects tend to pool in corners instead of heading away.
There are two possibilities as far as I can understand your query.
I didn't try but hope it helps.
1- With help of parametric equation of circle i.e.
x=v.t.cos(theta)
y=v.t.sin(theta)
In you case:
x=v.t.cos(theta) + xDistance
z=v.t.sin(theta) + zDistance
where xDistance and zDistance are simple initial position value of your body. These value will not be changed after starting movement (during movement until collision occur).
In Update() apply these equations to your body with constant v and theta and increase t (t++ or t+= 0.1f) by time. When body collides, just retain the current translate (position) value. And start movement again, this time change the value of xDistance and zDistance with current value but only once.
2- With help of iTween. Its a free animation script available at Asset Store
You can use iTween.MoveTo to move body to any given direction (You can assign a random direction as well.). And stop and restart movement upon collision.

Mouse movement: Click the sprite "walks" to point clicked

I'm pretty new to C# and XNA and well programing (like I can follow a tutorial but most of the creating it on my own is still really really hard). Right now I'm going round and round trying to figure out how to do this one "simple" thing.
Here's the idea, its going to be a tower defense game; right now I'm working on bare bone basics. I've got my little sprite guy who will move around with Keyboard input, now I want to click somewhere on the screen and have him "walk" to that point. Only I'm lost on the logic. I can click and he'll jump there with
if (aMouse.LeftButton == ButtonState.Pressed)
{
Position.X = aMouse.X;
Position.Y = aMouse.Y;
}
From what I've read for other mousing input, I'm thinking I'll need some kind of loop (bool maybe?) that will move the sprite in a direction and will have to run a check to see if he's got to that point yet. But getting that point after the mouse click and creating that loop, running the check...I'm clueless.
You need to add some instance variables:
Point2D targetPos;
And some constants:
const Point2D speed;
When you run through your Update() loop, update the current position by adding the speed vector to it (in the correct direction of course) until you are within a predefined threshold from the target position (usually the thresholds are calculated from the speed vector - if the distance from the current position to the target position is less than the length of the speed vector, then you're at your position). Using a bool in this case would work well. When you click your mouse set another instance variable (moving) to true, and once you've reached your target position, set moving to false.
People are answering your question at a very low level. Sometimes it help to think of the problem at a higher level.
What you need is a type of state management. The fancy Computer Science term for that is a Finite State Machine. But don't bother looking that up right now. It's fairly dry and confusing at first :)
Your character currently has one state - "standing around". You need to add and process the "walking to destination" state.
From what I've read for other mousing input, I'm thinking I'll need some kind of loop
You need one loop, called the game loop. If you're using XNA, you've already got one. But you're on the right track.
Every time through the game loop, you should process the current state, and check for what are called State Transitions. That's when you change something in your world from one state to another state. For example, when you click the mouse, you want the guy to start moving.
In your game loop you check to see if a mouse click just happened. If it did, then set up some data (where to move to), and tell him to start walking by setting his state to "walking to destination". Next update, you'll process that state instead.
When your character is in the "walking to desintation" state, you need to update their position, based on the amount of time that passed since the last game update. In XNA, this is calculated for you. If you're not using XNA, then you'll have to check yourself. You might be able to use something like the Stopwatch class, and check the Elapsed field.
If the character is at the destination, you need to switch them back to the "standing around" state.
If you receive another mouse click, it is up to you if you want the "walking to destination" state to pay attention to it or not. If you do pay attention to it, you set up the same sort of data as when you transitioned from the "standing around" state.
So, you'll need these variables:
A timer, to find out the elapsed time since the last game loop (XNA gives it to you)
The current player state (maybe an enum)
The current player position (a vector)
The walking speed of the player (a float, probably), measured in units per second (or millisecond)
Data for the "walking to destination" state - target position (another vector)
Data related to user input (mouse events that occurred since the last update, the position of those clicks, etc)
The character specific data will be different for each character in your game, so you want a new copy of it for each. You'll probably want to put it in a class. The rest of it is more global, so you can keep it separate, or make it part of your game, game loop, input classes, etc (however you choose to organize it).
I won't cover the vector math for how to actually calculate the partial movement stuff, since other people have covered that. No sense in duplicating those answers. It basically boils down to making a vector between your current position and the target position, and multiplying/dividing it by your walking speed (to chop it up to the distance moved in a single update).
I'm assuming you have three things:
Current position
Desired position
Speed to move each 'game tick' // don't know what a game tick is? find out!
You're looking at doing this
// dx, dy are delta x and delta y. It's how far in each direction
// the player must travel
// note, I fixed a typo where they were desired - desired... should be
// desired - current, as they are now
float dx = desiredX - currentX;
float dy = desiredY - currentY;
// d uses the pythagorean theorum to find the distance between current and desired
float d = sqrt(dx*dx + dy*dy);
// fac is how far along that line between desired and current will you move
float fac = d / speed;
// mx is the component of the dx line proportional to the size of fac : d
// which means it's how far in the x direction you'll move
float mx = dx * fac;
float my = dy * fac;
// the new postition is the old position plus the move value
float newPositionX = dx + mx;
float newPositionY = dy + my;
I have found this code to be most useful... additionally I have added an extra couple lines to prevent certain situations from occuring. For instance there will be times where direction is 0.83 and speed may have been modified by game factors like terrain/wheather/etc.... if speed is below 1, the sprite may not move at all or even move in the wrong direction!
if (Vector2.Distance(Position, TargetPosition) > 2.0f)
{
velocity = Vector2.Subtract(TargetPosition, Position);
velocity.Normalize();
/// Now no matter which direction we are going we are always moving # sprite.Speed
/// at velocity or speed below 1 - problems occur where the unit may not move at all!!
if(current_Speed < 1)
{
Vector2 temp = (velocity * 10) * (current_Speed * 10);
Position += temp / 10;
}
else
{
Vector2 temp = velocity * current_Speed;
Position += temp;
}
//convert to int to render sprite to pixel perfect..
Position = new Vector2((int)Position.X, (int)Position.Y);
}

Categories