getGravity not working? - c++

I am new to c++ as well as game development. I coded a function using bullet physics which returns the gravity of the world and it seems to be not working. It always returns 0. Though, I've initialized the world, solver, dispatcher, broadphase and collision configuration.
Here's the code:
void _setGravity(btScalar gravity) //sets the gravity of the world
{
if(gravity > 0.f)
gravity = -gravity;
_dynamicsWorld->setGravity(btVector3(0, gravity, 0));
}
btScalar _getGravity(void) //returns the gravity of the world
{
return ((btScalar*)_dynamicsWorld->getGravity());
}
Is there something that I am doing wrong ?
Thank you.

The getGravity function returns a btVector3 by value, so you need to use resulting vectors getY to get the gravity:
return _dynamicsWorld->getGravity().getY();

Related

Deflection issue in platformer game programmed with Unreal Engine 4

I'm trying to program a simple platformer game with very accurate movement using Unreal Engine 4 (4.22 release). It took some inspiration from games like Super Meat Boy or Celeste.
I'm using the APaperCharacter that uses UCharacterMovementComponent, but I'm not very satisfied of it.
Particularly I would like to avoid the deflection that is used in UCharacterMovementComponent::PhysFalling() method:
const FVector OldHitNormal = Hit.Normal;
const FVector OldHitImpactNormal = Hit.ImpactNormal;
FVector Delta = ComputeSlideVector(Adjusted, 1.f - Hit.Time, OldHitNormal, Hit);
// Compute velocity after deflection (only gravity component for RootMotion)
if (subTimeTickRemaining > KINDA_SMALL_NUMBER && !bJustTeleported)
{
const FVector NewVelocity = (Delta / subTimeTickRemaining);
Velocity = HasAnimRootMotion() && !CurrentRootMotion.HasOverrideVelocity() ? FVector(Velocity.X, Velocity.Y, NewVelocity.Z) : NewVelocity;
}
I recorded a video to show you the behavior I would like to prevent:
https://www.youtube.com/watch?v=fko1aPl-Vdo
I'm thinking to create my personal movement component that derives UCharacterMovementComponent in order to override the ComputeSlideVector() method, but I don't know if it is the best idea to resolve this issue.
I would like to have your opionion and I would like to know if I can simply solve the problem changing some parameters by editor.
I eventually decided to create my own class derived from UCharacterMovementComponent.
I solved the issue I described in my question overriding the UCharacterMovementComponent ::ComputeSlideVector() method:
FVector UMyMovementComponent::ComputeSlideVector(const FVector& Delta, const float Time, const FVector& Normal, const FHitResult& Hit) const
{
FVector Result = Super::ComputeSlideVector(Delta, Time, Normal, Hit);
if (Hit.bBlockingHit)
{
float Angle = FVector::DotProduct(Hit.Normal, FVector::DownVector);
if (Angle > KINDA_SMALL_NUMBER) // if the collision normal points downwards
{
Result.X = 0.0f;
}
}
return Result;
}

Getting the world position/orientation of a VR headset using Unreal C++

I need to find the world position/orientation of a VR headset (both Oculus and HTC) and then set an actor to be at the same location. Getting the camera's position seems to not work well in VR, so I thought this code was the proper way to do this:
FQuat DeviceRotation;
FVector DevicePosition;
GEngine->XRSystem->GetCurrentPose(0, OUT DeviceRotation, OUT DevicePosition);
myActor->SetActorLocation(DevicePosition);
myActor->SetActorRotation(DeviceRotation);
However, the resulting coordinates are too low on the Z axis and the orientation doesn't properly match.
So what is the proper way to do this in C++? Do I need to factor in the player controller somehow?
UPDATE:
Looking more into this, it seems you have to add the HMD position rotated by the player pawn rotation:
FQuat DeviceRotation;
FVector DevicePosition;
FVector FinalPosition;
GEngine->XRSystem->GetCurrentPose(IXRTrackingSystem::HMDDeviceId, DeviceRotation, DevicePosition);
APlayerController *PlayerController = UGameplayStatics::GetPlayerController(GetWorld(), 0);
FinalPosition = PlayerController->GetPawn()->GetActorRotation().RotateVector(DevicePosition) + PlayerController->PlayerCameraManager->GetCameraLocation();
myActor->SetActorLocation(FinalPosition);
myActor->SetActorRotation(DeviceRotation);
However, the results are still not correct, as there seems to be a rotation offset. I have the camera set to lock on to the HMD, so I'm not sure what else I'm missing here.
Figured it out. GetCurrentPose only gives an offset position for the HMD, so it needs to be added to the player pawn's transform like so:
FQuat hmdRotation;
FVector hmdLocationOffset;
GEngine->XRSystem->GetCurrentPose(IXRTrackingSystem::HMDDeviceId, hmdRotation, hmdLocationOffset);
APawn * playerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
myActor->SetActorLocation(playerPawn->GetTransform().TransformPosition(hmdLocationOffset));
myActor->SetActorRotation(hmdRotation);

How do I accomplish proper trajectory with a Cocos2d-x node using Chipmunk 2D impulses and rotation?

I'm building a game with Cocos2d-x version 3.13.1 and I've decided to go with the built-in physics engine (Chipmunk 2D) to accomplish animations and collision detection. I have a simple projectile called BulletUnit that inherits from cocos2d::Node. It has a child sprite that displays artwork, and a rectangular physics body with the same dimensions as the artwork.
The BulletUnit has a method called fireAtPoint, which determines the angle between itself and the point specified, then sets the initial velocity based on the angle. On each update cycle, acceleration is applied to the projectile. This is done by applying impulses to the body based on an acceleration variable and the angle calculated in fireAtPoint. Here's the code:
bool BulletUnit::init() {
if (!Unit::init()) return false;
displaySprite_ = Sprite::createWithSpriteFrameName(frameName_);
this->addChild(displaySprite_);
auto physicsBody = PhysicsBody::createBox(displaySprite_->getContentSize());
physicsBody->setCollisionBitmask(0);
this->setPhysicsBody(physicsBody);
return true;
}
void BulletUnit::update(float dt) {
auto mass = this->getPhysicsBody()->getMass();
this->getPhysicsBody()->applyImpulse({
acceleration_ * mass * cosf(angle_),
acceleration_ * mass * sinf(angle_)
});
}
void BulletUnit::fireAtPoint(const Point &point) {
angle_ = Trig::angleBetweenPoints(this->getPosition(), point);
auto physicsBody = this->getPhysicsBody();
physicsBody->setVelocityLimit(maxSpeed_);
physicsBody->setVelocity({
startingSpeed_ * cosf(angle_),
startingSpeed_ * sinf(angle_)
});
}
This works exactly as I want it to. You can see in the image below, my bullets are accelerating as planned and traveling directly towards my mouse clicks.
But, there's one obvious flaw: the bullet is remaining flat instead of rotating to "point" towards the target. So, I adjust fireAtPoint to apply a rotation to the node. Here's the updated method:
void BulletUnit::fireAtPoint(const Point &point) {
angle_ = Trig::angleBetweenPoints(this->getPosition(), point);
// This rotates the node to make it point towards the target
this->setRotation(angle_ * -180.0f/M_PI);
auto physicsBody = this->getPhysicsBody();
physicsBody->setVelocityLimit(maxSpeed_);
physicsBody->setVelocity({
startingSpeed_ * cosf(angle_),
startingSpeed_ * sinf(angle_)
});
}
This almost works. The bullet is pointing in the right direction, but the trajectory is now way off and seems to be arcing away from the target as a result of the rotation: the more drastic the rotation, the more drastic the arcing. The following image illustrates what's happening:
So, it seems that setting the rotation is causing the physics engine to behave in a way I hadn't originally expected. I've been racking my brain on ways to correct the flight path, but so far, no luck! Any suggestions would be greatly apprecitated. Thanks!

How to move a sprite with dynamic physics body with constant speed

Until lately I've been just changing the x coordinate of my sprite on each update and I was happy with it. But yesterday when being in the debugDraw mode, I found out that after certain speed physics body wouldn't align correctly with the sprite ,like this:
Later I got told that, (by Birkemose in cocos2d forum) the preferred way to move a physics body from A to B is to apply impulse to it. But I have no idea how to achieve constant speed this way. This is the code I used to move it without applying any impulse:
-(void)update:(CCTime)delta{
rollingHero.position=ccp(rollingHero.position.x+scrollSpeed*delta,
rollingHero.position.y);
physicsNode.position=ccp(physicsNode.position.x-scrollSpeed*delta,
physicsNode.position.y);
}
So to create a feeling of moving I scroll the physics node and the hero in opposite directions with the same scrolling speed.
I tried lots of different variants of applying impulse, but I never got it moving with constant speed. The speed accelerates and the hero gets offscreen. I would appreciate it very much if someone would post a sample code.
The reason impulse isn't working to keep your character at a constant speed is because impulse translates directly into a change in momentum (and thus a change in velocity). So if you were to try to maintain a constant velocity through impulse, you would have to check your sprite's velocity first, and although you could get pretty close to a constant velocity, it wouldn't be truly constant.
static const float kRollingHeroMoveSpeed = 10.f;
static const float kRollingHeroAccelConstant = 10.f;
-(void)update:(CCTime)delta {
// check velocity of sprite
if(_rollingHero.physicsBody.velocity.x < kRollingHeroMoveSpeed) {
// if velocity is under limit, push character
[_rollingHero.physicsBody applyImpulse:ccp(kRollingHeroAccelConstant, 0)];
}
}
The better way to do this is to step into the C level of the Chipmunk2D physics engine that powers Cocos2D physics.
-(void)onEnter {
[super onEnter];
// tell physics engine to use our C function to update physics body
_rollingHero.physicsBody.body.body->velocity_func = playerUpdateVelocity;
}
static void playerUpdateVelocity(cpBody *body,
cpVect gravity,
cpFloat damping,
cpFloat dt) {
// check validity of cpBody
cpAssertSoft(body->m > 0.0f && body->i > 0.0f, "Body's mass and moment must be positive to simulate. (Mass: %f Moment: %f)", body->m, body->i);
// update velocity and angular velocity
body->v = cpvadd(cpvmult(body->v, damping), cpvmult(cpvadd(gravity, cpvmult(body->f, body->m_inv)), dt));
body->w = body->w*damping + body->t*body->i_inv*dt;
// reset force vector
body->f = cpvzero;
// reset torque
body->t = 0.0f;
// set body's velocity to desired velocity
body->v.x = kRollingHeroMoveSpeed;
}
Here's cpBody.h on Github.

Can I add friction in air?

I have issue regarding speed in air.
When I jump and move simultaneously that time speed of player increase. I use impuls for jump and I use force for movement .I want to know how to slow down it when player is in air.
This is my code of movement left and right
-(void)update:(ccTime)dt :(b2Body *)ballBody :(CCSprite *)player1 :(b2World *)world
{
if (moveRight.active==YES)
{
// maxSpeed=10.0f;
ballBody->SetActive(true);
// b2Vec2 locationworld=b2Vec2(maxSpeed,0);
double mass=ballBody->GetMass();
ballBody->ApplyForce(mass*locationworld, ballBody->GetWorldCenter());
ballBody->SetLinearDamping(1.2f);
}
else if(moveLeft.active==YES)
{
ballBody->SetActive(true);
b2Vec2 locationworld=b2Vec2(-10,0);
double mass=ballBody->GetMass();
ballBody->ApplyForce(mass*locationworld, ballBody->GetWorldCenter());
// ballBody->SetLinearDamping(1.2f);
}
}
And following is for jumping player
-(void)jump:(b2Body*)ballBody:(ccTime)dt:(BOOL)touch
{
if (touch)
{
if (jumpSprte.active==YES)
{
ballBody->SetActive(true);
b2Vec2 locationWorld;
locationWorld=b2Vec2(0,25);
ballBody->ApplyLinearImpulse(locationWorld, ballBody->GetWorldCenter());
}
}
}
So where i used logic??
Thanks in advance
You need to model air resistance to slow the player down in the air. There are several ways to do this depending on how realistic you want the simulation to be. For a simple model linearDampening would slow it down.
True air resistance is not linear. To model this in a more realistic way you'd need to use something like this:
F = - C * v * |v|
F is the total force of the air drag
C is a drag constant that depends on the shape of the object
v is the velocity vector ( |v| is the magnitude of the velocity, or length if you so wish)
It also sounds like your players are able to increase their speed while in the air using move. This is because you allow the player to apply force while his legs aren't touching the ground. In order to disallow this if this is your goal make sure that when the character is touching the ground is the only time when more force can be applied to make him move.
Note that this all very much depends on what sort of game you want this to be. If it looks and feels good when making physics for games it is good. Do not stress out if you don't manage to make a wholly accurate simulation of reality as long as the end result plays well.
This is my code of movement left and right
-(void)update:(ccTime)dt :(b2Body *)ballBody :(CCSprite *)player1 :(b2World *)world
{
if (moveRight.active==YES)
{
// maxSpeed=10.0f;
ballBody->SetActive(true);
// b2Vec2 locationworld=b2Vec2(maxSpeed,0);
double mass=ballBody->GetMass();
ballBody->ApplyForce(mass*locationworld, ballBody->GetWorldCenter());
ballBody->SetLinearDamping(1.2f);
}
else if(moveLeft.active==YES)
{
ballBody->SetActive(true);
b2Vec2 locationworld=b2Vec2(-10,0);
double mass=ballBody->GetMass();
ballBody->ApplyForce(mass*locationworld, ballBody->GetWorldCenter());
// ballBody->SetLinearDamping(1.2f);
}
}
And following is for jumping player
-(void)jump:(b2Body*)ballBody:(ccTime)dt:(BOOL)touch
{
if (touch)
{
if (jumpSprte.active==YES)
{
ballBody->SetActive(true);
b2Vec2 locationWorld;
locationWorld=b2Vec2(0,25);
ballBody->ApplyLinearImpulse(locationWorld, ballBody->GetWorldCenter());
}
}
}
So where i used logic??