applyForce Speed going faster - lua

Hey I have this problem where If I tap and hold the screen, the player gains speed going up on Y.
What I would prefer is that the player taps the screen (and holds to float up) and he goes up at steady speed (without getting quicker).
Here is the function for float speed and touch event:
function activateJets(ship,event)
ship:applyForce(0, -1.0, ship.x, ship.y)
print("run")
end
function touchScreen(event)
print("touch")
if event.phase == "began" then
ship.enterFrame = activateJets
Runtime:addEventListener("enterFrame", ship)
end
if event.phase == "ended" then
Runtime:removeEventListener("enterFrame", ship)
end
end
Runtime:addEventListener("touch", touchScreen)
Sorry if this doesn't make sense. Here is a general idea of what I want:
player touches screen (and holds)
object then floats up at consistent speed (no speed gain)
player releases touch
object drops normally

The physics involved prevents you from doing that: you are applying a constant force to your ship. According to Newton's laws (simulated by the physics library), this means a constant acceleration, thus a linear increase in speed.
The behavior you want (which is not coherent with real physics) is an instant acceleration to your target speed and then no speed variation. Thus it should be enough to set the speed of your ship to a constant value using shipSetLinearVelocity() inside your activateJets function. Of course you should reset the speed to zero when the touch has ended.

Related

SpriteKit Jumping and moving issues

I'm fairly new to swift, and have been working on a game for fun, and i'm running into something I can't quite get my head around.
When the run button is pressed, the character moves forward with the following function
func move(dt: CGFloat) {
position.x += moveRate * dt
}
And when the jump button is pressed, the character jumps with the following function
func jump() {
physicsBody?.applyImpulse(CGVector(dx: 0, dy: jumpRate))
run(jumpAnimation!)
}
both work fine, but consider this senario. The player is running, and then they jump while still moving. While in the air, the player releases the move button and the player's x position stops dead. This obviously feels very unnatural, and i would like the player's x position to ease out.
Now i have also played with moving the character with physicsBody?.applyForce(CGVector(dx: 1000, dy: 0)) which would give that effect, but he seems to just gain more and more speed and you don't get a constant rate or "max speed" so to speak.
Could anybody share some insight with me? I'd love to learn anything I can about spritekit and game development in general. Thanks!
You should try to set the velocity instead of setting the X position. When setting the position you bypass all the physics behaviors.
You should also try to set it only when you actually press a button.
func move(dt: CGFloat) {
if Math.abs(moveRate) > 0.1 { // If player initiates movement. You can increase the value 0.1 if you want to filter move values
velocity = CGVector(dx: moveRate, dy: veloxity.dy)
}
}
It your character moves indefinitely like in space, linearDamping will be useful. it's used to simulate air friction, so values closer to 1 means more friction and values closer to 0 means less friction.
linearDamping = 0.85
Also, this way, moveRate isn't dt dependent but it should be lowered.
Try it, I haven't tested it yet, but that's basically how I would do it.
There are two schools of thought on platformer game "physics".
Don't use physics, do everything with positional incrementation.
Do everything with physics, since positional changes mess up physics
Since you're using physics for jumping, and physics jumping is fun:
There are three ways to create movement in a physics system:
Set the velocity as and when required. This is what Crazyrems is suggesting
Apply impulses as needed to increase and decrease rates of movement
Apply forces over time that increase or decrease rates of movement
Use fields to induce motion (too complex for this, and messy, but fun)
What you're attempting, with your physicsBody?.applyForce(CGVector(dx: 1000, dy: 0)) is the application of force over time. Number 3 in the list above. The longer you continue applying this force the faster the character moves.
Each of these techniques can be made to work, but they all need compensation for their various limitations and methodologies of simulation.
In the case of your approach, you need monitor speed and to set a maximum speed. Having reached maximum speed, if the player is still holding the button, only provide enough force to maintain speed (assuming you're using some form of constant resistance to slow the character).
Monitoring speed combined with force-over-time creates interesting acceleration trait possibilities - like very strong initial acceleration and then taper off acceleration as the player nears their maximum speed.
Slowing down when the player releases the button is the next focus. In all these approaches you need something that slows the player. This can be the application of opposing forces, or the use of friction or damping, as provided by the physics engine.

Transition.to during "moved" event issue on device

So basically, I have a paddle that rotates around the screen based around where the user is touching. In the corona simulator, my code works flawlessly... on my test device... that's another story.
--All pseudocode for now but this is the gist of it
local function movePaddle(event)
local phase = phase
if phase == "began" then
--get angle of touch based on centerX/centerY
--get angle of paddle's current location
--get deltaAngle between the two using ((((touchAngle- paddleAngle)%360)+540)%360)-180
transition.to(paddle,{rotation = deltaAngle, time = 200, delta = true, transition = easing.outElastic})
elseif phase == "moved" then
--get angle of touch based on centerX/centerY
--get angle of paddle's current location
--get deltaAngle between the two using ((((touchAngle-paddleAngle)%360)+540)%360)-180
transition.to(paddle,{rotation = deltaAngle, time = 200, delta = true, transition = easing.outElastic})
end
end
On the simulator I have zero issues... When I run this on the device, the "began" phase works flawlessly but if a user drags his/her finger the paddle lags behind significantly. I've tried other easing functions to include not having one(which it defaults to linear iirc). My guess, is that when in the "moved" phase, the time in the transition.to is compounded.
Please help me out :( Is this a known issue with transition.to? I can provide exact code if needed.
Without seeing more of your code, it's possible that you're generating quite a few touch events which are creating quite a few transitions. I'm not sure I would transition the paddle, but just simply move it with the finger.

Corona SDK completely destroy physics joint

I am making a game in Corona sdk where different balls bounce and stick to each other with a weld joint. When I reset the gameplay, all joints are destroyed, then all the balls are repositioned. Here is some of my code:
--stickJoints and balls are tables that contain all the weld joints and ball objects
resetTotal = function()
for i=1,#stickJoints do
stickJoints[i]:removeSelf()
stickJoints[i]=nil
end
for i=1,20 do
--this resets all balls and sets linear and angular velocity to 0
resetP(balls[i],1000+(i-1)*400,5000,0)
end
end
The problem is that as soon as I tap the reset button, the balls that were connected temporarily interact with each other. Any thoughts are helpful. Thanks!
I think your best bet is either
to use timer.performWithDelay to call a function that will reposition the balls after the physics has had a chance to break the constraint.
Remove each ball from physics, and use a delayed function cal (see item 1) to re-add them after having been repositioned.

Corona SDK, flappy bird bounce effect

I'm developing a game where the character bounces much like the "Flappy Bird" character.
I have it working well, but I'm handing the bouncing effect with a touch event and when the user double touches really quick it basically doubles the force behind the player.
Also, take for example if the player is dropping from a higher height then the gravity seems to be too much and I have to touch many more times to bring the player back up, and I just can't seem to figure out how to make every touch consistent with the amount the character bounces.
Here is my function for the bounce effect:
function flyUp(event)
if event.phase == "began" then
if gameStarted == false then
player.bodyType = "dynamic"
instructions.alpha = 0
tb.alpha = 1
addColumnTimer = timer.performWithDelay(1000, addColumns, -1)
moveColumnTimer = timer.performWithDelay(2, moveColumns, -1)
gameStarted = true
player:applyForce(0, -300, player.x, player.y)
else
player:applyForce(0, -460, player.x, player.y)
end
end
end
...and here is where my player is defined as a physics body:
physics.addBody(player, "static",
{ density=.106, bounce=.1, friction=1, radius = 30 })
any help would be extremely appreciated, i just want the player to always move up the same amount no matter how many taps and how much he has dropped.
Thanks
You're probably forgetting that force determines acceleration, not velocity. So if you have an object moving downwards at speed V (V is positive value, since downward is positive in Corona) then applyForce() applies a momentary upward force (duration: one time frame) to the object, so the object's downward velocity will decrease a little bit (decelerate as a result of the upward force), but gravity is constant so you'll have to press multiple times to get enough deceleration.
What you probably want is to directly setLinearVelocity() to a negative value, thus making it look as though the object "bounced" upwards upon touch; gravity will then give it a parabolic trajectory. Also, if the object is always given the same linear velocity, it doesn't matter how many taps occur, although each tap will counter the effect of gravity with same upwards velocity.
Two ideas:
To avoid the double-touch/double-bounce, apply a cooling off period. When the user touches, ignore additional touches for some given amount of time.
Strictly speaking, you are getting the same amount of bounce (or upward force) per touch. It sounds like you want a variable bounce depending on the current velocity toward the ground. This shouldn't be too hard. Try applying more upward force in player:applyForce depending on the velocity on the y axis. If the player isn't falling, a smaller amount of force is needed. If they are falling at terminal velocity, a much larger force is needed.
It sounds like you recognize that "perfect" physics are less fun in your game. That's often the case. You'll likely need to experiment until something feels right.

event.x seems to not work

I have this scene, I want when the earth collide with the blackhole an explosion sprite to be played.
So I wrote this:
local function onCollision( event )
if ( event.phase == "began" ) then
if(event.object1.name =="blackholeSprite" or event.object2.name =="blackholeSprite") then
explosionSprite.x=event.x
explosionSprite.y=event.y
explosionSprite:play()
timer.performWithDelay( 1500, gameOver )
end
end
end
The problem is that the explosion does not occur where the ball and the blackhole collide event.x and event.y . As you can see from the screenshot the explosion take place in the top-left corner. Any idea why this happens?
Maybe it is because of what is reported in the docs under "gotchas" for collision events.
Gotchas
The x and y position can be influenced by physics.getAverageCollisionPositions() and physics.setReportCollisionsInContentCoordinates().
Event position
During the "ended" phase (See the Collision Detection Guide), the X and Y positions are always zero. This is a Box2D limitation.
Also, when a collision involves a circle, and if the collision result is returned in local-space (see physics.setReportCollisionsInContentCoordinates(), then the local-space position of the collision is always 0,0. This is a Box2D limitation.
To solve your issue you could try to get the coordinates from (one of) the objects themselves, instead of getting them from the event.

Resources