Crossed physics bodies issue in cocos2dxv3.4 - c++

I am new to Cocos2dx v3.x.I am developing a basic car racing game in which the car can move within the continuous scrolling track which is straight and small curvy like "Road Fighter" game in Google play Store.For moving the car,i am using device accelerometer and adjusts the velocity of the car body acc. to that.For the path body,i am using EdgeChain Shape of 5 points which i have shown below so that it makes the bound area for the car motion and car should not go beyond that.But with setVelocity function,my car body goes outside the boundary.I have also set the CollisionBitmask and ContactTestBitmask,collision is detected,even then the physics body of car crossed over the edge chain body of path.
auto *sprite = Sprite::create("Road.jpg");
sprite->setPosition(Vec2(winSize.width/2,winSize.height/2));
sprite->setScaleX(rX);
sprite->setScaleY(rY);
this->addChild(sprite, 0);
auto edge_body=PhysicsBody::createEdgeChain(vec ,5 ,PHYSICSBODY_MATERIAL_DEFAULT,3);
edge_body->setDynamic(false);
edge_body->addShape(PhysicsShapeEdgeChain::create(vec3, 5));
sprite->setPhysicsBody(edge_body);
edge_body->setCollisionBitmask(1);
edge_body->setContactTestBitmask(true);
//where vec and vec3 are vectors of 5 points acc to track boundary.
auto *mycar=Sprite::create(car_png_name);
mycar->setPosition(Point(winSize.width/2,winSize.height*0.35));
addChild(mycar,2);
mycar_body=PhysicsBody::createBox(mycar->getContentSize(),PhysicsMaterial(0,1,0));
mycar->setPhysicsBody(mycar_body);
mycar_body->setRotationEnable(false);
mycar_body->setCollisionBitmask(2);
mycar_body->setContactTestBitmask(true);
// DEVICE ACCELEROMETER
Device::setAccelerometerEnabled(true);
auto listener= EventListenerAcceleration::create (CC_CALLBACK_2(HelloWorld::OnAcceleration,this));
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
auto contact_listener=EventListenerPhysicsContact::create();
contact_listener->onContactBegin=CC_CALLBACK_1(HelloWorld::onContactBegin, this);
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(contact_listener, this);
void HelloWorld::OnAcceleration(cocos2d::Acceleration *acc, cocos2d::Event *event)
{
#define KFILTERINGFACTOR 0.7
#define KRESTACCELX 0
#define KsquirrelMAXPOINTSPERSEC (winSize.width*0.5)
#define KMAXDIFFX 0.15
double rollingX=0;
acc->y = acc->x;
rollingX = (acc->y * KFILTERINGFACTOR) + (rollingX * (1.0 - KFILTERINGFACTOR));
float accelX = acc->y - rollingX;
float accelDiff = accelX - KRESTACCELX;
float accelFraction = accelDiff / KMAXDIFFX;
carspeed = KsquirrelMAXPOINTSPERSEC * accelFraction*1.5;
if(mycar_body!=NULL)
mycar_body->setVelocity(Vec2(carspeed*1.5,0));
}
I have faced this issue in Cocos2dxv3.4.The same logic works fine in Cocos2dxv2.2.6 with box2d b2body.I am not getting where i am wrong or how in other way,i can move my car with accelerometer within the scrolling boundary.Can anyone Suggest?
Thanks in advance.

Related

Why sprites tremble in cocos2d-x

I create a little game on cocos2d-x and have some problem in mobile version. Game have layer with terrain and character and layer with ui/info objects. Layer with terrain does not move. And layer with ui/info move with character (so it static on screen).
In mobile version all sprites from ui layer are trembling, but only sprites, labels are static. In PC version sprites and labels are also static.
Create label and sprite. Label static on PC (Win and Mac) and mobile (Android), sprite static on PC and tremble on mobile:
auto infoLayer = m_params->getGameInfoDelegate(); // class GameInfo
auto size = Director::getInstance()->getVisibleSize();
TTFConfig ttfconfig("fonts/Marker Felt.ttf", 100);
auto label = Label::createWithTTF(ttfconfig, "0");
label->setPosition(Vec2(size.width / 2, size.height / 2 + 40));
label->setString("Hello");
infoLayer->getLayer()->addChild(label, 10);
auto spr = Sprite::create();
spr->setColor(Color3B(200, 100, 100));
spr->setTextureRect(Rect(0, 0, 150, 150));
spr->setPosition(Vec2(size.width / 2, size.height / 2 - 40));
infoLayer->getLayer()->addChild(spr, 9);
Update position layer and camera:
update(float t)
{
...
m_cameraFollow->update();
...
}
void CameraFollow::update()
{
float moveX;
float moveY;
...
m_camera->move(Vec2(moveX, moveY)); // class GameCamera
}
void GameCamera::move(const cocos2d::Vec2& m)
{
float x;
float y;
...
m_position.x = x;
m_position.y = y;
m_camera->setPosition(m_position); // class cocos2d::Camera
auto infoPanel = m_params->getGameInfoDelegate(); // class GameInfo
if(infoPanel)
{
infoPanel->setMoving(m_position - m_startPosition);
}
}
class GameInfo : public cocos2d::Layer, public GameInfoDelegate
void GameInfo::setMoving(const cocos2d::Vec2 &position)
{
this->setPosition(position);
}
So, how i can fix it?
The answer to your question is complicated. The main reason is that your phone does not have the same processing power as your computer, and Cocos2d-x uses some clever optimizations to try and hide that. With moving sprites, it has to redraw them every frame (usually 30-60 fps), and slight inconsistencies can lead to this effect.
To remedy this, I would double check that your fps is 60, because 30 fps will lead to trembling. Also, if you're updating the sprite's position in update(float dt), I would try and use the physics engine instead, with velocities. If that isn't an option, maybe try to have less layers, because the more sprites you draw ontop of one another, the more it will look like it is jittering. Let me know if any of these solutions work.
The issue may be related to how you are moving the camera. Setting new X,Y coordinates through your update method without factoring in the delta time on each update call will result in jerky movement on screen.
You need to smooth out the movement from one location to another.
Try this:
update(float dt)
{
...
m_cameraFollow->update(dt);
...
}
void CameraFollow::update(float dt)
{
float moveX;
float moveY;
float speed = 1.0f;
...
Vec2 cameraPosition = m_camera->getPosition();
Vec2 targetPosition = Vec2(moveX, moveY);
Vec2 newPosition = cameraPosition.lerp(targetPosition, dt * speed);
m_camera->move(newPosition);
}

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 rotate an object so it faces another?

I am making a game in opengl, and i can't figure out how to make my enemy characters turn to face my player. I only need the enemy to rotate on the y axis towards the player. Then I want them to move towards him.I have tried a bunch of different methods but haven't been able to get anything to work.
There are a few things you need to decide on yourself at the beginning of the project to be used throughout the project, like the representation of positions and the orientation (as well as the setup of the screen/clip planes etc.) However, you haven't mentioned any of this. So you may have to adapt the code below to suit your game, but it should be easily adaptable and applicable.
For the following example, I'll assume that -y axis is the top of your screen.
#include <math.h> // atan2
// you need to way to represent position and directions
struct vector2{
float x;
float y;
} playerPosition, enemyPosition;
float playerRotation;
// setup the instances and values
void setup() {
// Set some default values for the positions
playerPosition.x = 100;
playerPosition.y = 100;
enemyPosition.x = 200;
enemyPosition.y = 300;
}
// called every frame
void update(float delta){
// get the direction vector between the player and the enemy. We can then use this to both calculate the rotation angle between the two as well as move the player towards the enemy.
vector2 dirToEnemy;
dirToEnemy.x = playerPosition.x - enemyPosition.x;
dirToEnemy.y = playerPosition.y - enemyPosition.y;
// move the player towards the enemy
playerPosition.x += dirToEnemy.x * delta * MOVEMENT_SPEED;
playerPosition.y += dirToEnemy.y * delta * MOVEMENT_SPEED;
// get the player angle on the y axis
playerRotation = atan2(-dirToEnemy.y, dirToEnemy.x);
}
void draw(){
// use the playerPosition and playerAngle to render the player
}
Using the above code, you should be able to move your player object around and set the angle of rotation (you need to watch out for radians/degrees of the returned and expected angle values).

c++ Qt QGraphicsItemAnimation model of thrown ball

I have problem with the animation of a ball, which flies according to the equations of motion
x = speed*cos(angle) * time;
y = speed*sin(angle) * time - (g*pow(time,2)) / 2;
I create a QGraphicsScene with QGraphicsEllipseItem
QGraphicsScenescene = new QGraphicsScene;
QGraphicsEllipseItemball = new QGraphicsEllipseItem(0,scene);
then I try to animate ball
scene->setSceneRect( 0.0, 0.0, 640.0, 480.0 );
ball->setRect(15,450,2*RADIUS,2*RADIUS);
setScene(scene);
QTimeLine *timer = new QTimeLine(5000);
timer->setFrameRange(0, 100);
QGraphicsItemAnimation *animation = new QGraphicsItemAnimation;
animation->setItem(ball);
animation->setTimeLine(timer);
animation->setPosAt(0.1, QPointF(10, -10));
timer->start();
But I can't understand how setPosAt works and how I can use my calculated x,y in this case.
The official Qt documentation for setPosAt is very short and incomprehensible.
You need to call setPosAt() multiple times with various values of (step) between 0.0 and 1.0. Then when you play the animation, Qt will use linear interpolation to animate smoothly between the points you set, as Qt increases its "current step" value from 0.0 to 1.0.
For example, to make the ball move in a straight line you could do something like:
animation->setPosAt(0.0, QPointF(0,0));
animation->setPosAt(1.0, QPointF(10,0));
... or to make the ball go up, and then down, you could do:
animation->setPosAt(0.0, QPointF(0,0));
animation->setPosAt(0.5, QPointF(0,10));
animation->setPosAt(1.0, QPointF(0,0));
... so to get the arc you want you could do something like:
for (qreal step=0.0; step<1.0; step += 0.1)
{
qreal time = step*10.0; // or whatever the relationship should be between step and time
animation->setPosAt(step, QPointF(speed*cos(angle) * time, speed*sin(angle) * time - (g*pow(time,2)) / 2);
}

How to move a sprite at a certain angle with a joystick

Hi I have finally made a working joystick in cocos2d. I am able to rotate a sprite to the exact angle that the joystick thumb, or cap, is 'pointing'. However, I am unable to move the sprite in that same direction. Is there an easy way to move the sprite with the way I have the rotating code set up? Also is there a way to keep it moving if your thumb is still pressed, but not moving the joystick?. PS this code is all within the TouchesMoved method. PPS. the cap is the thumb, the pad is the joystick background, and the Sprite2 is the sprite that I want to move. (95, 95) is the center of the pad sprite.
if(capSprite.position.x>=padSprite.position.x){
id a3 = [CCFlipX actionWithFlipX:NO];
[sprite2 runAction:a3];
}
if(capSprite.position.x<=padSprite.position.x){
id a4 = [CCFlipX actionWithFlipX:YES];
[sprite2 runAction:a4];
}
CGPoint pos1 = ccp(95, 95);
CGPoint pos2 = ccp(capSprite.position.x, capSprite.position.y);
int offX = pos2.x-pos1.x;
int offY = pos2.y-pos1.y;
float angleRadians = atanf((float)offY/(float)offX);
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
float theAngle = -1 * angleDegrees;
sprite2.rotation = theAngle;
I'm not familiar with cocos2d but I had a quick look at the documentation and this sample might be of use to you:
if keys[key.UP]:
self.target.acceleration = (200 * rotation_x, 200 * rotation_y)
I had written a long explanation answering your second question but I believe this "self.target.acceleration" solves that too. You can read more at the cocos2d API documentation.
What I generally do is get the angle, convert it to a CGPoint with ccpForAngle(float) and then multiply the CGPoint by a value:
float angle = whatever;
CGPoint anglePoint = ccpForAngle(angle);
// You will need to play with the mult value
angle = ccpMult(angle, 2.5);
// This also works with box2D or probably Chipmunk.
sprite.position = angle;