Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
How to make objects move in circular motion from (startX,startY) to (destinationX, destinationY) with some aberration using TweenLite [actionscript 3 library]?
You should be able to set a circular motion using the CirclePath2D plugin and maybe offset the location a bit with an onUpdate function.
The bit that sounds confusing is
from (startX,startY) to (destinationX, destinationY)
because if you move in a circular motion, at some point you end where you started from.
if you start from one position and end in another, you might move on a curve, in which case you want to have a look at the BezierThroughPlugin.
Still, it's fairly straight forward to animate on a circle path with an onEnterFrame loop and you can easily change the circle into an oval for example or randomly offset the path a bit. Normally you'd need to convert from polar to cartesian coordinates:
x = cos(angle) * radius
y = sin(angle) * radius
but Point's polar() method already does that for you:
var speed:Number = 0;//how fast to move around the circle
var spread:Number = 20;//how far away from the centre
var b:Sprite = addChild(new Sprite()) as Sprite;
b.graphics.beginFill(0);
b.graphics.drawCircle(-3,-3,3);
b.graphics.endFill();
graphics.lineStyle(1,0xDEDEDE);
this.addEventListener(Event.ENTER_FRAME,update);
function update(event:Event):void{
speed += .1;//update the 'angle' , .1 is the increment/speed at which b spins
var distance:Number = spread + (Math.random() * 10 - 5);//spread + random 'aberration'
var offset:Point = Point.polar(distance,speed);//convert from angle/radius to x,y
b.x = mouseX + offset.x;
b.y = mouseX + offset.y;
graphics.lineTo(b.x,b.y);
}
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I want to create a bounding box for a geolocation in Swift which returns to me (minY maxY minX maxX) Is there a function to do this in Swift?
iOS doesn't have the idea of a bounding box, but it does have a region struct called MKCoordinateRegion.
MKCoordinateRegion contains two things:
CLLocationCoordinate2D center;
MKCoordinateSpan span;
Both are structs. The span contains the height and width of the region. Using those you can make a bounding box (from here)
CLLocationCoordinate2D centerCoord = CLLocationCoordinate2DMake(41.145495, −73.994901);
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(centerCoord, 2000, 2000);
double latMin = region.center.latitude - .5 * startRegion.span.latitudeDelta;
double latMax = region.center.latitude + .5 * startRegion.span.latitudeDelta;
double lonMin = region.center.longitude - .5 * startRegion.span.longitudeDelta;
double lonMax = region.center.longitude + .5 * startRegion.span.longitudeDelta;
Edit: I just realised the request was for Swift. I'll leave translation as an exercise for bonus points.
I'm currently trying to make a top-down based game using Corona SDK.
Basically what I wanna do is, make enemies move straight to the center of the map. It is easy to do it with transition.to() but when I do that, the objects lose their physics until they reach their destination.
I was wondering, is there anyway to make the objects move like transition.to() but without using it? Because I really want my objects to hit obstacles on their way when they're trying to get to the center of the map.
About the game scenario:
Its like a tower defense game, there is a object in the middle(Castle) there is need to be hitted by other objects(enemies) that respawn randomly from the sides.
Here is some code:
function spawnEnemy()
for i=1,numberEnemies do
enemy = display.newImage("enemy.png")
physics.addBody(enemy,"dynamic")
enemy:addEventListener("tap",enemyKill)
enemy.gravityScale = -0
if math.random(2) == 1 then
enemy.x = math.random(-100, -10)
enemy:setLinearVelocity(50,0)
else
enemy.x = math.random (display.contentWidth + 10, display.contentWidth + 100)
enemy:setLinearVelocity(-40,0)
end
enemy.y = math.random(display.contentHeight)
--enemy.trans = transition.to(enemy, {x=centerX, y=centerY, time=5000,onComplete=hitCastle})
end
timer.performWithDelay( 10000, spawnEnemy, 0 )
end
You should set the linear velocity of the enemy so that the enemy heads towards the center. Once the enemy collides with the castle, you can remove the enemy object from the scene. In order to do this, you must calculate the vector between two points (the enemy and the center) and then multiply both the X and Y values of the vector by the speed you would like the enemy to move.
Enemy position = (EnemyXPos, EnemyYPos)
Center Position = (CenterXPos, CenterYPos)
Velocity Vector = (CenterXPos - EnemyXPos, CenterYPos - EnemyYPos)
You then need to normalize the Velocity Vector (Not covered in this answer) which will give you the x and y values of a vector that points from the enemy to the center with a length of 1.
To adjust speed:
Adjusted Velocity Vector = (NormalizedVelXVal * Speed, NormalizedVelYVal * Speed)
At this point, you just set the enemies linear velocity equal to the Adjusted Velocity Vector calculated above.
You should look at the API for body.
These two links should help you to solve the problem :
https://docs.coronalabs.com/api/type/Body/applyLinearImpulse.html
and
https://docs.coronalabs.com/api/type/Body/applyForce.html
Well Hello,
I'm making a 2d platformer for iOS using spritekit. I have moving platforms to allow my characters to move with the platform.
I can't just use skactions to move my platforms because the character will not move with the platform.
question:
How would I add an ease in and out function in order to have the platforms??? simulate: SKactionTimeMode.easeInEaseOut
Current Solution:
I don't have the code in front of me, but for a left/right moving platform this is pretty much what I'm doing. This would be running within the platforms update() method.
If platform.position.x < xPositionIWantNodeToStopGoingLeft {
velAmount = -velAmount
}
else if platform.position.x > xPositionIWantNodeToStopGoingRight {
velAmount = -velAmount
}
platform.physicsBody?.velocity = SKVector(dx: velAmount, dy: velAmount
platform.position.y = staticYPosition
Just to clarify, this works great. If there is a better way to do this I'm all ears. But this creates a jagged stop and turn kind of feel. I want that ease in and out feel so that the platform feels more natural.
Thanks for any help!!!
Ease in out function
If we consider the time for the platform to move from one side to the other as one unit ( it might be 10 seconds, or 17 frames, it does not matter, we work in units for now).
We do the same with the distance. The platform must move one unit distance in one unit of time.
For this answer time is t and the position is a function of time written as f(t) is the platform position at time t.
For simple linear movement then the function is simply f(t)=t. So at time t=0 the distance moved is 0, at time 0.5 (half way) the distance is 0.5 (half way), and so on.
So lets put that into something a little more practical.
Please excuse my swift I have never used it befor (I am sure you can correct any syntax I get wrong).
// First normalise the distance and time (make them one unit long)
// get the distance
let distance = Double(xPositionStopGoingLeft - xPositionStopGoingRight);
// use that and the velocity to get the time to travel
let timeToTravel = distance / Double(velAmountX);
// first we have a frame ticker
gameTick += 1; // that ticks for every frame
// We can assume that the platform is always moving back and forth
// Now is the unit time where at now = 2 the platform has move there and back
// at 3 it has move across again and at 4 back again.
let now = Double(gameTick) / timeToTravel; // normalize time.
// get the remainder of 2 as from 0-1 is moving forward and 1-2 is back
let phase = now % 2.0;
// We also need the unit time for the function f(t)=t
let t = abs(phase - 1);
if phase >= 1 { t = 1 - t } // reverse for return
// implement the function f(t) = t where f(t) is dist
let dist = t
// and convert back to pixel distance
platform.position.x = Int(dist * distance + Double(xPositionStopGoingLeft));
So that is the linear platform. To make the movement change all we need to do is change the function f(t)=?, in the above its the line let dist = t
For a ease in out there is a handy function that is used in most ease applications f(t) = t * t / ((t * t) + (1 - t) * ( 1 - t))
There are some t*t which are powers, t to the power of 2 or t^2 . In swift its pow(t,2) so rewriting the above as code
let dist = pow(t,2) / (pow(t,2) + pow((1-t),2);
This gives a nice ease at the start and end As the distance and time traveled is constant the speed at the middle point t = 0.5 must be greater to catch up with the slow start and end. (Side note, Get the derivative of the above function lets you workout the speed at every point in time f'(t) = speed(t) = 2(-(t-1)t)^(2-1) /(t^2+(1-t)^2)^2)
This function is so nice, the speed at time 0.5 is 2, the same as the power (for the linear journey it would be 1). A handy property of the function is that the speed at the mid way point is always the same as the power. If you want it to move really fast at the midpoint say 4 times as fast then you use the power of 4
let dist = pow(t,4) / (pow(t,4) + pow((1-t),4);
If you want it only to speed up a little say 1.2 times the speed at the center then the power is 1.2
let dist = pow(t,1.2) / (pow(t,1.2) + pow((1-t),1.2);
So now we can introduce another term, maxSpeed which is the normalised maxSpeed (Side note more precisely it is the speed at t=0.5 as it can be the slower than 1, but for our need max speed will do)
let maxSpeed = Double(velAmountX + 3) / Double(velAmountX); // 3 pixels per frame faster
and the function f(t) = t^m / (t^m + (1-t)^m) where m is maxSpeed.
and as code
let dist = pow(t,maxSpeed ) / (pow(t,maxSpeed ) + pow((1-t),maxSpeed);
So put that all together
// the next 3 lines can be constats
let distance = Double(xPositionStopGoingLeft - xPositionStopGoingRight);
let timeToTravel = distance / Double(velAmountX);
let maxSpeed = Double(velAmountX + 3) / Double(velAmountX);
gameTick += 1; // that ticks for every frame
let now = Double(gameTick) / timeToTravel; // normalize time.
let phase = now % 2.0;
let t = abs(phase - 1);
if phase >= 1 { t = 1 - t } // reverse for return
// the next line is the ease function
let dist = pow(t, maxSpeed) / (pow(t, maxSpeed) + pow((1-t) ,maxSpeed);
// position the platform
platform.position.x = Int(dist * distance + Double(xPositionStopGoingLeft));
Now you can at any tick calculate the position of the platform. If you want to slow the whole game down and step frames at half ticks it still will work. if you speed the game up gameTick += 2 it still works.
Also the max speed can be lower than the linear speed. If you want the platform to be half the normal speed at the center t=0.5 the set maxSpeed = 0.5 and at the halfway point the speed will be half. To keep everything working the ease at the start and end will be quicker a rush in and rush out. (and works for reverse as well)
To help maybe a visual representation
Image shows the movement of the platform back and forth over time. The distance is about 60 pixels and the time can be 1 minute. So at 1 min it will be one the right 2min on the left, and so on.
Then we normalise the movement and time by looking only at one section of movement.
The graph represents the movement from left to right side, the distance is 1, and the time is 1. It has just been scaled to fit the unit box (1 by 1 box).
The red line represent the linear movement f(t)=t (constant speed). At any point of time you move across hit the line move down and you can find the distance traveled.
The green line represents the ease function f(t)=t*t/(t*t+(1-t)*(1-t)) and it works the same. At any point of time scan across to find the green line and move down to get the distance. the function f(t) does that for you.
With the maxSpeed the steepness of the line at dist 0.5 is changed, with steeper slope representing faster travel.
For physic, play with friction and linear damping of the body. You can even use an SKAction run block to reduce or add friction.
you could do something like:
physicsBody.friction = (10 - physicsBody.velocity.dx) > 0 ? (10 - physicsBody.velocity.dx) / 10 : 0
Basically it gives friction when velocity.dx is < 10, you may want to tweak the 10 to the number of your liking
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am doing on sliding puzzle game i need to help for how to slice image and make the more sprite images this images are arranging to descending order the player will arrange to correct position.
Know idea how to slice the image in cocos2d-x 3.2 anybody please help to me solve this.
Thanks dude.
You can slice sprite in cocos2d-x using setTextureRect(). For example, here's the code for the 16 segments, you can change it for your number:
Size visibleSize = Director::getInstance()->getVisibleSize();
vector<Sprite*> vecSprites;
for (int i = 0; i <= 15; i++)
{
Sprite* segment = Sprite::create("example.png");
float segmentWidth = segment->getBoundingBox().size.width / 4;
float segmentHeight = segment->getBoundingBox().size.height / 4;
float originX = (i % 4) * segmentWidth;
float originY = ((int)i/4) * segmentHeight;
segment->setTextureRect(Rect(originX, originY, segmentWidth, segmentHeight));
vecSprites.push_back(segment);
}
Display segments of the sprite on the screen in the reverse order:
for (int i = 15; i >= 0; i--)
{
vecSprites[i]->setPosition((i%4) * visibleSize.width / 4, (((int)i/4) + 1) * visibleSize.height / 4);
vecSprites[i]->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT);
this->addChild(vecSprites[i]);
}
Result:
Of course, you can display them in random order. I hope this will help you.
I don't know wether it works in cocos2d or not, but its perfect solution in iOS.
Please follow the given link:
How to programmatically slice an image in 4 , 9 , 16 and 25 slices
You can also download application from Github:
https://github.com/bpolat/Image-Slicer
This is a problem I hit when trying to implement a game using the LÖVE engine, which covers box2d with Lua scripting.
The objective is simple: A turret-like object (seen from the top, on a 2D environment) needs to orientate itself so it points to a target.
The turret is on the x,y coordinates, and the target is on tx, ty. We can consider that x,y are fixed, but tx, ty tend to vary from one instant to the other (i.e. they would be the mouse cursor).
The turret has a rotor that can apply a rotational force (torque) on any given moment, clockwise or counter-clockwise. The magnitude of that force has an upper limit called maxTorque.
The turret also has certain rotational inertia, which acts for angular movement the same way mass acts for linear movement. There's no friction of any kind, so the turret will keep spinning if it has an angular velocity.
The turret has a small AI function that re-evaluates its orientation to verify that it points to the right direction, and activates the rotator. This happens every dt (~60 times per second). It looks like this right now:
function Turret:update(dt)
local x,y = self:getPositon()
local tx,ty = self:getTarget()
local maxTorque = self:getMaxTorque() -- max force of the turret rotor
local inertia = self:getInertia() -- the rotational inertia
local w = self:getAngularVelocity() -- current angular velocity of the turret
local angle = self:getAngle() -- the angle the turret is facing currently
-- the angle of the like that links the turret center with the target
local targetAngle = math.atan2(oy-y,ox-x)
local differenceAngle = _normalizeAngle(targetAngle - angle)
if(differenceAngle <= math.pi) then -- counter-clockwise is the shortest path
self:applyTorque(maxTorque)
else -- clockwise is the shortest path
self:applyTorque(-maxTorque)
end
end
... it fails. Let me explain with two illustrative situations:
The turret "oscillates" around the targetAngle.
If the target is "right behind the turret, just a little clock-wise", the turret will start applying clockwise torques, and keep applying them until the instant in which it surpasses the target angle. At that moment it will start applying torques on the opposite direction. But it will have gained a significant angular velocity, so it will keep going clockwise for some time... until the target will be "just behind, but a bit counter-clockwise". And it will start again. So the turret will oscillate or even go in round circles.
I think that my turret should start applying torques in the "opposite direction of the shortest path" before it reaches the target angle (like a car braking before stopping).
Intuitively, I think the turret should "start applying torques on the opposite direction of the shortest path when it is about half-way to the target objective". My intuition tells me that it has something to do with the angular velocity. And then there's the fact that the target is mobile - I don't know if I should take that into account somehow or just ignore it.
How do I calculate when the turret must "start braking"?
Think backwards. The turret must "start braking" when it has just enough room to decelerate from its current angular velocity to a dead stop, which is the same as the room it would need to accelerate from a dead stop to its current angular velocity, which is
|differenceAngle| = w^2*Inertia/2*MaxTorque.
You may also have some trouble with small oscillations around the target if your step time is too large; that'll require a little more finesse, you'll have to brake a little sooner, and more gently. Don't worry about that until you see it.
That should be good enough for now, but there's another catch that may trip you up later: deciding which way to go. Sometimes going the long way around is quicker, if you're going that way already. In that case you have to decide which way takes less time, which is not difficult, but again, cross that bridge when you come to it.
EDIT:
My equation was wrong, it should be Inertia/2*maxTorque, not 2*maxTorque/Inertia (that's what I get for trying to do algebra at the keyboard). I've fixed it.
Try this:
local torque = maxTorque;
if(differenceAngle > math.pi) then -- clockwise is the shortest path
torque = -torque;
end
if(differenceAngle < w*w*Inertia/(2*MaxTorque)) then -- brake
torque = -torque;
end
self:applyTorque(torque)
This seems like a problem that can be solved with a PID controller. I use them in my work to control a heater output to set a temperature.
For the 'P' component, you apply a torque that is proportional to the difference between the turret angle and the target angle i.e.
P = P0 * differenceAngle
If this still oscillates too much (it will a bit) then add an 'I' component,
integAngle = integAngle + differenceAngle * dt
I = I0 * integAngle
If this overshoots too much then add a 'D' term
derivAngle = (prevDifferenceAngle - differenceAngle) / dt
prevDifferenceAngle = differenceAngle
D = D0 * derivAngle
P0, I0 and D0 are constants that you can tune to get the behaviour that you want (i.e. how fast the turrets respond etc.)
Just as a tip, normally P0 > I0 > D0
Use these terms to determine how much torque is applied i.e.
magnitudeAngMomentum = P + I + D
EDIT:
Here is an application written using Processing that uses PID. It actually works fine without I or D. See it working here
// Demonstration of the use of PID algorithm to
// simulate a turret finding a target. The mouse pointer is the target
float dt = 1e-2;
float turretAngle = 0.0;
float turretMass = 1;
// Tune these to get different turret behaviour
float P0 = 5.0;
float I0 = 0.0;
float D0 = 0.0;
float maxAngMomentum = 1.0;
void setup() {
size(500, 500);
frameRate(1/dt);
}
void draw() {
background(0);
translate(width/2, height/2);
float angVel, angMomentum, P, I, D, diffAngle, derivDiffAngle;
float prevDiffAngle = 0.0;
float integDiffAngle = 0.0;
// Find the target
float targetX = mouseX;
float targetY = mouseY;
float targetAngle = atan2(targetY - 250, targetX - 250);
diffAngle = targetAngle - turretAngle;
integDiffAngle = integDiffAngle + diffAngle * dt;
derivDiffAngle = (prevDiffAngle - diffAngle) / dt;
P = P0 * diffAngle;
I = I0 * integDiffAngle;
D = D0 * derivDiffAngle;
angMomentum = P + I + D;
// This is the 'maxTorque' equivelant
angMomentum = constrain(angMomentum, -maxAngMomentum, maxAngMomentum);
// Ang. Momentum = mass * ang. velocity
// ang. velocity = ang. momentum / mass
angVel = angMomentum / turretMass;
turretAngle = turretAngle + angVel * dt;
// Draw the 'turret'
rotate(turretAngle);
triangle(-20, 10, -20, -10, 20, 0);
prevDiffAngle = diffAngle;
}
Ok I believe I got the solution.
This is based on Beta's idea, but with some necessary tweaks. Here it goes:
local twoPi = 2.0 * math.pi -- small optimisation
-- returns -1, 1 or 0 depending on whether x>0, x<0 or x=0
function _sign(x)
return x>0 and 1 or x<0 and -1 or 0
end
-- transforms any angle so it is on the 0-2Pi range
local _normalizeAngle = function(angle)
angle = angle % twoPi
return (angle < 0 and (angle + twoPi) or angle)
end
function Turret:update(dt)
local tx, ty = self:getTargetPosition()
local x, y = self:getPosition()
local angle = self:getAngle()
local maxTorque = self:getMaxTorque()
local inertia = self:getInertia()
local w = self:getAngularVelocity()
local targetAngle = math.atan2(ty-y,tx-x)
-- distance I have to cover
local differenceAngle = _normalizeAngle(targetAngle - angle)
-- distance it will take me to stop
local brakingAngle = _normalizeAngle(_sign(w)*2.0*w*w*inertia/maxTorque)
local torque = maxTorque
-- two of these 3 conditions must be true
local a,b,c = differenceAngle > math.pi, brakingAngle > differenceAngle, w > 0
if( (a and b) or (a and c) or (b and c) ) then
torque = -torque
end
self:applyTorque(torque)
end
The concept behind this is simple: I need to calculate how much "space" (angle) the turret needs in order to stop completely. That depends on how fast the turret moves and how much torque can it apply to itself. In a nutshell, that's what I calculate with brakingAngle.
My formula for calculating this angle is slightly different from Beta's. A friend of mine helped me out with the physics, and well, they seem to be working. Adding the sign of w was my idea.
I had to implement a "normalizing" function, which puts any angle back to the 0-2Pi zone.
Initially this was an entangled if-else-if-else. Since the conditions where very repetitive, I used some boolean logic in order to simplify the algorithm. The downside is that, even if it works ok and it is not complicated, it doesn't transpire why it works.
Once the code is a little bit more depurated I'll post a link to a demo here.
Thanks a lot.
EDIT: Working LÖVE sample is now available here. The important stuff is inside actors/AI.lua (the .love file can be opened with a zip uncompressor)
You could find an equation for angular velocity vs angular distance for the rotor when accelerating torque is applied, and find the same equation for when the braking torque is applied.
Then modify the breaking equation such that it intesects the angular distance axis at the required angle. With these two equations you can calculate the angular distance at which they intersect which would give you the breaking point.
Could be totally wrong though, not done any like this for a long time. Probably a simpler solution. I'm assuming that acceleration is not linear.
A simplified version of this problem is pretty simple to solve. Assume the motor has infinite torque, ie it can change velocity instantaneously. This is obviously not physically accurate but makes the problem much simpler to solve and in the end isn't a problem.
Focus on a target angular velocity not a target angle.
current_angle = "the turrets current angle";
target_angle = "the angle the turret should be pointing";
dt = "the timestep used for Box2D, usually 1/60";
max_omega = "the maximum speed a turret can rotate";
theta_delta = target_angle - current_angle;
normalized_delta = normalize theta_delta between -pi and pi;
delta_omega = normalized_deta / dt;
normalized_delta_omega = min( delta_omega, max_omega );
turret.SetAngularVelocity( normalized_delta_omega );
The reason this works is the turret automatically tries to move slower as it reaches its target angle.
The infinite torque is masked by the fact that the turret doesn't try to close the distance instantaneously. Instead it tries to close the distance in one timestep. Also since the range of -pi to pi is pretty small the possibly insane accelerations never show themselves. The maximum angular velocity keep the turret's rotations looking realistic.
I've never worked out the real equation for solving with torque instead of angular velocity, but I imagine it will look a lot like the PID equations.