Cocos2d bullet movement - cocos2d-iphone

As of now I have the bullet (a sprite) using a CCAction moveTo the players position. I have it set up so that the bullet always travels at a constant rate using t = d/v. But I need help so that the bullet passes through the given point and keeps going for a certain distance.
CCSprite * bullet = [CCSprite spriteWithFile:#"Projectile.png"];
int gunRange = 300;
int velocity = 300;
int t = distanceFromPlayer/velocity;
CCAction *shoot = [CCMoveTo actionWithDuration:t
position:player.position];
bullet.position = enemy.position;
if (distanceFromPlayer <= gunRange) {
[self addChild:bullet];
[bullet runAction:shoot];
}
Need to know how to shoot if in range (I think I have that part), shoot towards the player position and keep going in that direction once there (No idea on how to do this), and for the bullet sprite to be removed after it has traveled a distance equal to the gun range (No idea for this either). Please Help.

This line doesn't make sense to me:
bullet.position = enemy.position;
Use MoveTo to move the bullet to the enemy position not the above line.
Also to move the bullet past the enemy to a certain position just use the old high school trigonometry we'll all learned -- SOH CAH TOA for right triangles. You have the angle of the bullet and the distance to the enemy so using the info and right triangle trig you can have the bullet move past the target a certain distance
Hope this helps!

Related

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!

Ball passing through paddle from certain angles

I'm creating a pong clone for school with C++ and SFML 2.1 and I'm having a little problem when the ball hits the left paddle at sharp angles (It goes through).
The right paddle works fine at all angles, and as far as i can remember they're using the same code.
This is the code I'm using for collision:
for (auto& it : collisionPaddles)
{
if (this->ballShape.getGlobalBounds().intersects(it->getGlobalPaddleBounds()))
{
float deltaDistance = (this->y + this->radius) - (it->y + it->height / 2);
bool fromLeft = true;
if ((ballAngle < (3*myMath::MY_PI/2) && ballAngle > myMath::MY_PI/2))
{
fromLeft = false;
}
else
{
fromLeft = true;
}
ballAngle = static_cast<float>(deltaDistance * (myMath::MY_PI/180));
if (fromLeft)
{
ballAngle = static_cast<float>(myMath::MY_PI - ballAngle);
}
moveBall(2);
}
}
That's not the way a good pong should be implemented. When your model of physics uses some deltas, you get a lot of artefacts. The one of most prominent is objects passing through each other. In such simple cases deltas should be used for animation only.
Here's the way I would solve it. When the ball gets its initial speed and vector of movement, I would calculate the whole path until it hits the player's baseline.
Calculate an initial ray from the current position of the ball, directed the same way it moves.
Intersect that ray with segments that consistute the borders of your field.
Calculate the time that is needed to reach that intersection point.
Calculate the new ray from the intersection point towards the new movement vector.
Repeat steps 2-4 until you hit a player's base line. Sum all the times.
Now you have a relative time of the hit with baseline and the place it will happen. Now on every frame you should
Check if that collision time has been between the previous frame and the current one. If it was,
Calculate the expected position of paddle at that moment.
If the segment of paddle contains that intersection point, it was reflected. Calculate the new path as described before.
This way you'll get true game mechanics that are not limited by most of the aspects of game development, i.e. FPS, sudden lags etc.

C++ DirectX11 2d Game: Stopping enemy sprites moving over each other?

I am using IntersectsWith(this->boundingBox)) method to detect collisions between sprites and player. I want to somehow be able to use this method in detecting my enemy sprites that collide with each other, and when they do to make sure they don't move over one another.
All of the enemy sprites follow the player.
MainGame.cpp
Loops over each enemy in the vector and does the update loop:
for (auto &enemyMobsObj : this->enemyMobs)
{
enemyMobsObj->Update(tickTotal, tickDelta, timeTotal, timeDelta, windowBounds, this->ship, this->firstBoss,
this->enemyMobs, this->bullets, this->missiles, NULL, "NULL", "NULL");
}
Here is what I tried before to stop each sprite moving over each other:
EnemyMobOne::Update:
int nextEnemy;
for (int i = 0; i < enemyMobOne.size(); i++)
{
nextEnemy = i + 1;
if (nextEnemy < enemyMobOne.size())
{
//Deal with mobs collision
if (enemyMobOne[i].boundingBox.IntersectsWith(enemyMobOne[nextEnemy].boundingBox))
{
enemyMobOne[i].position.x = enemyMobOne[nextEnemy].position.x - enemyMobOne[i].boundingBox.Width;
}
}
}
However this makes each enemy sprite obviously stick to each other, which doesn't look right, it also makes them teleport.
Anyone know the correct code to stop them moving over each other? Thanks.
When you detect an intersection between two collision objects, you need to make a decision about how you're going to counteract the overlap (as I'm sure you figured out). However, how one does this is a bit trickier than simply "pushing" them to one side (as you've done in your code). What you likely want to do is to have a counter-force to the applied force, so to speak. Basically, you want to calculate the minimum translation, or the direction by which the least amount of movement would be required, to get at least ONE of the boxes to move OUT of the other one.
This is a bit more complicated than simply "put me on the right (or left, depending on how you set up your coordinates, I suppose) side of the other guy," which is more or less what your code does, now.
For a simple solution, just check if one of the colliders is closer to the left, right, top, or bottom of the other. To do this, you can simply take the collision intersection position and check the relative distance between that point and the minimum and maximum x and y coordinates relative to one of the colliders, then move the one or both of the sprites, accordingly.
Ex:
[Edit] After reviewing my previous answer for this, I realized you would need to calculate the overlap of the boxes, which would make it much easier to accomplish this all like so:
float minX = min(sprite0.boundingBox.maxX, sprite1.boundingBox.maxX);// Minimum of the boxes' right-side points (top right and bottom right) x coordinates
float minY = min(sprite0.boundingBox.maxY, sprite1.boundingBox.maxY);// Minimum of the boxes' top-side points (top left and top right) y coordinates
float maxX = max(sprite0.boundingBox.minX, sprite1.boundingBox.minX);// Maximum of the boxes' left-side points (top left and bottom left) x coordinates
float maxY = max(sprite0.boundingBox.minY, sprite1.boundingBox.minY);// Maximum of the boxes' bottom-side points (bottom left and bottom right) y coordinates
float distHoriz = minX - maxX;// The horizontal intersection distance
float distVert = minY - maxY;// The vertical instersection distance
// If the boxes are overlapping less on the horizontal axis than the vertical axis,
// move one of the sprites (in this case, sprite0) in the opposite direction of the
// x-axis overlap
if(abs(distHoriz) < abs(distVert))
{
sprite0.x -= distHoriz;
}
// Else, move one of the sprites (again, I just decided to use sprite0 here,
// arbitrarily) in the opposite direction of the y-axis overlap
else
{
sprite0.y -= distVert;
}
To further clarify (beyond the comments), what we're basically doing here is checking the distance between the overlapping lines. For example:
Box 0 x-axis xmin0|------------------|xmax0
Box 1 x-axis xmin1|----------------------|xmax1
|----|<-- Overlap (xmax0 - xmin1)
Notice that the minimum from the two bounding boxes that is used for the overlap is the maximum among the two minima (xmin0 and xmin1), and the maximum that is used for the overlap is the minimum among the two maxima (xmax0 and xmax1).
The y-axis calculation works exactly the same way. Once we have both axes, we simply check to see which one has a lower absolute value (which distance is shorter) and move along that distance to counteract the intersection.

Can I make CCFollow follow more naturally?

I want to build a platform game with cocos2d/Box2D. I use CCFollow to follow the player sprite but CCFollow constantly puts it in the center of the screen. I want CCFollow to follow more naturally, like a human turning a camcorder with an acceptable lag, a small overshoot ...etc.
Here is a method of mine that didn't work: I attached (via a distance joint) a small physics body to the player that doesn't collide with anything, represented by a transparent sprite. I CCFollow'ed the transparent sprite. I was hoping this ghost body would act like a balloon attached to the player, hence a smooth shift in view. The problem is distance joint breaks with too heavy - too light objects. The balloon moves around randomly, and of course, it pulls the player back a little no matter how light it is.
What is a better way of following a moving sprite smoothly?
Try add this to CCActions in cocos2d libs.
-(void) step:(ccTime) dt
{
#define CLAMP(x,y,z) MIN(MAX(x,y),z)
CGPoint pos;
if(boundarySet)
{
// whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased
if(boundaryFullyCovered) return;
CGPoint tempPos = ccpSub(halfScreenSize, followedNode_.position);
pos = ccp(CLAMP(tempPos.x,leftBoundary,rightBoundary), CLAMP(tempPos.y,bottomBoundary,topBoundary));
}
else {
// pos = ccpSub( halfScreenSize, followedNode_.position );
CCNode *n = (CCNode*)target_;
float s = n.scale;
pos = ccpSub( halfScreenSize, followedNode_.position );
pos.x *= s;
pos.y *= s;
}
CGPoint moveVect;
CGPoint oldPos = [target_ position];
double dist = ccpDistance(pos, oldPos);
if (dist > 1){
moveVect = ccpMult(ccpSub(pos,oldPos),0.05); //0.05 is the smooth constant.
oldPos = ccpAdd(oldPos, moveVect);
[target_ setPosition:oldPos];
}
#undef CLAMP
}
i get this from cocos2d forums.
Perhaps this http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:actions_ease can help you get an "acceleration" effect with CCFollow.

Shooting bullets with a joystick cocos2d

I have a working joystick in my cocos2d app but I cannot figure out how to make the 'player' shoot bullets out of it in the direction the joystick is pointing. I have the player moving and rotating. Also the bullets need to disappear when they hit the edges of the screen. Any help would be great. Thanks in advance.
You should get the angle from joystick.
For instance, SneakyInput has a degrees property which enables you to rotate your bullets like this :
_bullet.rotation = -joystick.degrees;
And your update method can be like this :
void update:(ccTime) delta
{
float moveAngle = _bullet.rotation;
CGPoint deltaPos = CGPointMake(cos(moveAngle) * velocity, sin(moveAngle) * velocity);
_bullet.position = ccpAdd(self.position, deltaPos);
}