Object vibrating on floor in XNA - c#

I tried creating a simple physics based "game" where you can spawn balls and they then get affected by different natural force, like gravity.
But I have a problem, when the ball reaches the floor, and it keeps getting affected by gravity. It kind of vibrates. Here's a quick example of how it looks.
And here is the code for collision detection and the gravity calculation.
public void CheckBounds(int maxHeight, int maxWidth)
{
if (this.position.Y + (radius + radius) > maxHeight)
this.velocity.Y = -Math.Abs(velocity.Y * 0.65f); // 0.65 is the "bouncyness"
}
Here is the main Update section
for (int i = 0; i < balls.Count; i++ )
{
Ball b = balls[i];
for (int k = 0; k < balls.Count; k++) // check for collision with other balls
{
if (balls[i] == balls[k])
continue;
if (balls[i].Colliding(balls[k]))
balls[i].Collide(balls[k]);
}
b.velocity.Y += gravitationalPull; // a gravity constant
b.CheckBounds();
b.position = Vector2.Add(b.position, b.velocity);
}
Does anyone know how to fix the vibration? I tried setting a minimum value of velocity that the gravity would be calculated (if velocity.y < some value then dont calculate), but then the ball stopped mid air at collisions and even at spawn.

Related

How to move camera thats attached to player

I'm trying to recreate a dolphin dive type of feel, as of right now my character is a cube with no animation so I feel like the best way to do this would be to manually move the camera as if the character had just dolphin dived but every time I try to move the camera the entire player itself moves.
Code:
if (Input.GetKeyDown(KeyCode.C) && isSprinting) {
for (float i = 0; i <= 10; i++) {
var forceForward = 8f;
if (isGrounded == true && moveVertical != 0) {
_rgb.AddForce(fpsCam.transform.forward * forceForward);
for (float j = 0; j <= 10; j++) {
_camera.AddForce(Vector3.up * 3f);
}
}
}
}
if you need any more information let me know!
If you want a shortcut, you can make the camera gameobject a child of the player game object. This way it will move with the player.

C# Enemy doesn't follow player in Windows Form (not XNA)

UPDATE
I managed to figure the answer out myself, what was happening was that my movement function was only registering the players original static position instead of the dynamic coordinates as the player moved around the screen. What I did was create a 'God' class to publicly store the players current X and Y coordinates, and then reference the 'god' class coordinates in my enemy's movement function.
Now, not only does the enemy detect when the player is within it's sights, it will follow the player changing directions accordingly, until it can't 'see' them anymore :D
If anyone wants to see the updated code just ask :)
I'm trying to make a program that contains player and enemy sprites, but I'm having a little trouble with the code for the 'Enemy'. Most of the coding problems on here deal with XNA, which I'm not using, so I was wondering if I could have a little help.
Basically, when the player moves within a certain distance, the movement function for the enemy should activate and it will move towards the players location as long as they're in the 'detection zone'. The enemy's sprite also has a walk animation for each direction, and it should flip through frames depending on whether it's currently moving or not.
The movement function is within a timer, so that it'll update with every tick. I have two separate functions for updating its location, one to physically change it's coordinates in the Form based on the data received from the movement function, and another to update the current frame from my sprite sheet.
The problem is that the enemy doesn't move whatsoever, if I get rid of it's detection and the code to follow the player, and instead just move it across the screen, it works perfectly fine. But unfortunately that's not what I'm trying to achieve.
The code works perfectly fine for my player sprite (albeit, it's controlled by the user and the keyboard keys), so I'm not sure what I'm doing wrong.
I believe the problems lies within the Movement function, but I'm not sure what that problem is exactly.
Here's my code for the relevant functions:
public void Movement() //This function is in a timer, and determines which direction the sprite will move and face
{
//The sprite rectangle is the position of the player sprite, and detection is the area where the enemy would 'see' the player if they entered it
sprite = new Rectangle(charX - 1, charY + 1, charWidth * 2 + 2, charHeight * 2 + 2);
Detection = new Rectangle(curX - 25, curY - 25, Enemy.Width * 6, Enemy.Height * 6);
if (Detection.IntersectsWith(sprite)) //Checks to see if the player is within range
{
//Moves the enemy based on the players position and changes direction accordingly
if (curX > charX)
{
curDirection = RIGHT;
dX = -1;
dY = 0;
numUpdates = 0;
curAnimation = MOVING;
}
else if (curX < charX)
{
curDirection = LEFT;
dX = 1;
dY = 0;
numUpdates = 0;
curAnimation = MOVING;
}
if (curY > charY)
{
curDirection = UP;
dY = -1;
dX = 0;
numUpdates = 0;
curAnimation = MOVING;
}
else if (curY < charY)
{
curDirection = DOWN;
dY = 1;
dX = 0;
numUpdates = 0;
curAnimation = MOVING;
}
}
//If not within range, don't move the sprite
else
{
dY = 0;
dX = 0;
curAnimation = FINISHED;
}
}
These are the updating functions that move the enemy and change the current frame
public void Follow() //Physcially moves the enemy across the form
{
int xMod = 0;
int yMod = 0;
if (dX != 0)
xMod = dX / Math.Abs(dX) * 2;
if (dY != 0)
yMod = dY / Math.Abs(dY) * 2;
//Moves the sprite across the x and y axis
curX += xMod;
dX += -xMod;
curY += yMod;
dY += -yMod;
}
public void UpdateFrame(int direction = DOWN)
{
numUpdates++;
switch (curAnimation)
{
//Stops the animation if the sprite stops moving
case FINISHED:
curFrame = 0;
break;
//Moves to the next frame when movement is found
case MOVING:
curFrame = (curFrame + 1) % 3;
Follow();
//check if done animation
if (dX == 0 && dY == 0) curAnimation = FINISHED;
break;
}
}
If you need more code just ask, any help is appreciated :)

Can I build an AI that is more human beatable than this?

I've been building an AI and currently I'm to the point where it mostly works as it should. I hit a few hitches at first, and had something that.. spazzed out. Now that is fixed, but there's a problem - this AI catches the ball 90% of the time and returns it, although somewhat slowly at times. I have yet to build the Attract mode of the game, but I can imagine... when that is in, the two AI will almost never score on eachother.
The game takes place on a 2D plane. The AI moves purely on X, locked into Z and Y while the ball moves on X and Y.
The playing field is set up like tennis, a 'net' in the center - 0,0,0, denotes the middle and the ball moves like a tennis ball does.
The AI (and player) uses two controls - 'Direction' to go either left or right, 1 for left, -1 for right, and a bool to trigger the ball return.
At the moment I just want it to 'miss' the ball every so often, not nearly perfectly every time. I'm programming in C#, with the game engine being Unity3D - here's my code for the AI engine thus far:
void AIHandle()
{
DetectBalls();
if (GameController.Instance.Balls.Count < 1) {
GetFlipperButton = false;
}
if (BallPosition) {
BallPosit = BallPosition.position;
BallX = BallPosit.x;
//BallVelPosit = BallPosition.gameObject.rigidbody.velocity;
//BallPosit.x += BallVelPosit.x;
//BallPosit.y += BallVelPosit.y;
//BallVelPosit.y -= Physics.gravity.y;
//BallHitPredictor = new Vector3 (BallPosit.x, 0, 0);
transformPoint = transform.InverseTransformPoint(BallPosit);
//////////////////
Vector3 Heading = BallPosit - transform.position;
if (BallX > 0) {
Debug.Log(Heading.sqrMagnitude);
// THe ball is to the left //
if (transformPoint.z < 0f)
{
Direction = 1;
}
// The ball is to the right //
if (transformPoint.z > 0f)
{
Direction = -1;
}
if (Heading.sqrMagnitude < 30.0f)
{
Direction = 0;
}
} else {
Retreat();
}
} else {
Retreat();
}
MovementDirection = Mathf.Lerp(MovementDirection, Direction, 2.0f);
}
private void Retreat()
{
float DistanceToCenter = Vector3.Distance(transform.position, PlayerStartPosition);
Vector3 CenterPointOrient = transform.InverseTransformPoint(PlayerStartPosition);
if (DistanceToCenter >= 1f) {
if (CenterPointOrient.z > 0) {
Direction = -1;
} else {
Direction = 1;
}
} else {
Direction = 0;
}
}

applying direction to npc XNA

I have NPC's in my game that follow a script where they move randomly around the game. I would like them to face the direction they are moving in though.
for (int i = 0; i < GameConstants.NumDaleks; i++)
{
if (dalekList[i].isActive)
{
Vector3 line = dalekList[i].direction;
float rotationDal = (float)(Math.Atan2(dalekList[i].position.Y, dalekList[i].position.X) / (2 * Math.PI));
Matrix dalekTransform = Matrix.CreateScale(GameConstants.DalekScalar) * Matrix.CreateRotationY(rotationDal) * Matrix.CreateTranslation(dalekList[i].position);
DrawModel(mdlDalek, dalekTransform, mdDalekTransforms);
}
}
I'm sure it must be something to do with rotationDal, I have tried changing the calculation and the characters do seem to rotate differently, just not in their current direction
Xna has a built in function that you might find handy here.
Matrix.CreateWorld(positionVector, DirectionVector, UpVector);
here's the doc: http://msdn.microsoft.com/en-us/library/bb975261(v=xnagamestudio.40).aspx
In your case:
for (int i = 0; i < GameConstants.NumDaleks; i++)
{
if (dalekList[i].isActive)
{
Matrix dalekTransform = Matrix.CreateScale(GameConstants.DalekScalar) * Matrix.CreateWorld(dalekList[i].position, dalekList[i].direction, Vector3.Up);
DrawModel(mdlDalek, dalekTransform, mdDalekTransforms);
}
}

XNA - Hold longer to jump higher

I'm looking for a simple method for my game, so that when you hold down the space bar, you jump higher. When you 'tap' you don't jump to maximum height. There would need to be a max, but yeah, I don't know how to go about programming this.
Anyhelp, very appreciated. Feedback will be given. Thanks.
In your update function that handles jumping, you could have it keep track of how long the character has been off the ground and have it's upward velocity stop increasing after an amount of time.
For instance, something like the following should work
class Player
{
private const int gravity = 2; //force of gravity on the object
private const int maxHeight = 5; //change as needed
private const int msecsToMax = 1500; //change as needed
private int yPos = 0;
private int timeOffGround = 0;
private yVel = 0;
//other functions and stuff
void update(GameTime gt)
{
//check if the player is on the ground and update as necessary
if(isOnGround())
timeOffGround = 0;
else
timeOffGround += gt.ElapsedGameTime.TotalMilliseconds;
//update the player's velocity
yVel -= isOnGround() ? 0 : gravity; //no velocity when on the ground
if(Keyboard.GetState().IsKeyDown(Keys.SPACE) && timeOffGround < msecsToMax))
yVel += (maxHeight / msecToMax);
yPos += yVel;
}
}
During the accent of a jump, the Y velocity is completely
overridden by a power curve. During the decent, gravity takes
over. The jump velocity is controlled by the jumpTime field
which measures time into the accent of the current jump.
First off you will need some simple global variables,
public bool isJumping; //Is the player in a jump?
private bool wasJumping; //Did the player just exit a jump?
private float jumpTime; //Time the player has been in a jump (Useful for adding a power curve or to max out on jump height)
MaxJumpTime = .8f; //If you want to max out a jump, otherwise remove the relevant parts of the code
JumpLaunchVelocity = -3000.0f; //How much velocity to "jump" with, this may depend on your speed of your player, so it will need some ajustment
Here is the function that does most of the work:
private float DoJump(float velocityY, GameTime gameTime)
{
// If the player wants to jump
if (isJumping)
{
// Begin or continue a jump
if ((!wasJumping && IsOnGround) || jumpTime > 0.0f)
{
//Do things like animate, or play a sound here
jumpTime += (float)gameTime.ElapsedGameTime.TotalSeconds;
}
// If we are in the ascent of the jump
if (0.0f < jumpTime && jumpTime <= MaxJumpTime)
{
// Fully override the vertical velocity with a power curve that gives players more control over the top of the jump (If you dont want this you can remove the Math.Pow)
velocityY = JumpLaunchVelocity * (1.0f - (float)Math.Pow(jumpTime / MaxJumpTime, JumpControlPower));
}
else
jumpTime = 0.0f; // Reached the apex of the jump
}
else
{
// Continues not jumping or cancels a jump in progress
jumpTime = 0.0f;
}
wasJumping = isJumping;
return velocityY;
}
In your update when you calculate position and stuff:
velocity.Y = DoJump(velocity.Y, gameTime);
Take a look at the Platformer Starter Kit if you run into any problems!

Categories

Resources