value not updating when transition is in progress - lua

FuelGaugeArrow:rotate( 75 )
local FuelDecreaseAngle = 150 / FuelLevelMax
local function BurnFuel(event)
--transition.to( FuelGaugeArrow, { rotation = FuelGaugeArrow.rotation - FuelDecreaseAngle } )
FuelGaugeArrow.rotation = FuelGaugeArrow.rotation - FuelDecreaseAngle
FuelLevel = FuelLevel -1
if FuelLevel <=0 then
OutOfFuel()
end
end
local FuelBurn = timer.performWithDelay( 1000, BurnFuel , 0)
The FuelGaugeArrow rotation value is updated by another function (when the rocket picks up a fuel barrel, it increases the value):
local function ScrollExtras(event)
if FuelGaugeArrow.rotation + FuelIncreaseAngle <= 75 then
FuelGaugeArrow.rotation = FuelGaugeArrow.rotation + FuelIncreaseAngle
else
FuelGaugeArrow.rotation = 75
end
end
Runtime:addEventListener( "enterFrame", ScrollExtras )
This works fine in the code above, but when I use the commented-out code, i.e. when I try to use transition to move the arrow, it only works when there is no transition going on at that precise moment. The updated value is not picked up by the BurnFuel function when transition is in progress.
I'm sure there's a better way to do this, so please enlighten me.

You either have to cancel previous transition before starting new, or wait till previous ends before starting new. The transition.to() returns a reference to a transition object which can be paused etc. For example,
local fuelTrans
local function BurnFuel(event)
if fuelTrans ~= nil then
fuelTrans.cancel()
fuelTrans = transition.to( FuelGaugeArrow, ... )
end
...
end
The second method (wait till first complete) is probably not what you want, plus it involves setting onComplete parameter to a listener, but if you prefer that it is explained in transition.to.

Related

while constantly moving character, it skips frames

I am using this code to move the monkey where i touch the screen. it works alright if i touch the screen one at a time but when i try to constantly touch the screen on the left and right side it skips frames and instead transport to the area on the screen where i touched previously
local function moveMonkey(event)
if event.phase == "began" then
speed = 1500 / screenWidth * (mAbs(monkey.x - event.x))
transition.to ( monkey, {time = speed, x = event.x} )
end
end
You should cancel the previous transition before starting a new one (on same parameters). Do this by saving the return value of transition.to and checking, before creating new transition, whether the variable is defined, if yes then call transition.cancel() on it:
local trans = nil
local function moveMonkey(event)
if event.phase == "began" then
speed = 1500 / screenWidth * (mAbs(monkey.x - event.x))
if trans ~= nil then
transition.cancel(trans)
end
trans = transition.to ( monkey, {time = speed, x = event.x} )
end
end
There are other ways of managing transitions, see . For instance you might be able to tag the transition and cancel it, so no need to keep a reference to it (but I can't test right now, don't know if transition.cancel on a non-existent tag will cause problem -- my guess is it will simply be ignored), but the tag name should be rather unique:
local function moveMonkey(event)
if event.phase == "began" then
speed = 1500 / screenWidth * (mAbs(monkey.x - event.x))
transition.cancel("monkey_trans")
transition.to ( monkey, {time = speed, x = event.x, tag="monkey_trans"} )
end
end

Can someone test my Corona project and identify the issue with my jump function?

I'm all very new to this and everything in this project is just placeholders and scrap work. Some of you may recognize some of the graphics used from other Corona tutorials, but it's to help me get better, so don't be too judgemental. Here's a link to the download for the Corona Simulator: http://www.mediafire.com/download/6a78bsewgwsiyp2/GooMan.rar
Anyways, here's my issue. The jump button seems fine at first. If I hold it down, the character constantly jumps. And if I let go, he stops. If I simultaneously hold down jump while pushing one of the arrow buttons, he'll jump in that direction. However, it seems as though if I jump once, then I hit the jump button again RIGHT as the character is making contact with the ground, that he won't jump. There's a sudden lack of responsiveness. I literally have to pause slightly and wait for the character to fully hit the ground before I can make another successful jump. Why?
And here's all the relevant code for you to look at:
I have this at the beginning to help define my goo character's position:
local spriteInAir = false
local yspeed = 0
local oldypos = 0
local holding = false
I then created the jump button.
local bJump = display.newImage("Images/jumpbutton.png")
bJump.x = 445
bJump.y = 265
bJump.xScale = 0.78
bJump.yScale = 0.78
Followed up by creating an enterFrame Runtime Event which will update my goo character's position in the Y. Running the game at 60fps if that's relevant.
function checkSpeed()
yspeed = sprite.y - oldypos
oldypos = sprite.y
if yspeed == 0 then
spriteInAir = false
else
spriteInAir = true
end
end
Runtime:addEventListener( "enterFrame", checkSpeed )
Then the meat of it all. Created a function called hold which tells the game to not only make my goo character jump, but to keep my goo character constantly jumping as long as the bJump button is held down. Works perfectly. The "jumping" function is a touch event that listens for the hold function, and all of it is executed by the bJump button listening to the jumping function.
local function hold()
if holding and spriteInAir == false then
sprite:applyForce( 0, -8, sprite.x, sprite.y )
sprite:setLinearVelocity(0, -350)
spriteInAir = true
return true
end
end
local function jumping( event )
if event.phase == "began" then
display.getCurrentStage():setFocus( event.target )
event.target.isFocus = true
event.target.alpha = 0.6
Runtime:addEventListener( "enterFrame", hold )
holding = true
elseif event.target.isFocus then
if event.phase == "moved" then
elseif event.phase == "ended" then
holding = false
event.target.alpha = 1
Runtime:removeEventListener( "enterFrame", hold )
display.getCurrentStage():setFocus( nil )
event.target.isFocus = false
spriteInAir = false
return true
end
end
return true
end
bJump:addEventListener("touch",jumping)
Anyone who can help me identify this problem, I'd greatly appreciate it!
You're using a velocity check to detect if the character is on the ground. It can take a short while to set it back to zero after colliding with Box2D, so the better way to do it is to use a collision sensor:
sprite.grounded = 0 -- Use a number to detect if the sprite is on the ground; a Boolean fails if the sprite hits two ground tiles at once
function sprite:collision(event)
if "began" == event.phase then
-- If the other object is a ground object and the character is above it...
if event.other.isGround and self.contentBounds.yMax < event.other.contentBounds.yMin + 5 then
sprite.grounded = sprite.grounded + 1 -- ...register a ground collision
end
elseif "ended" == event.phase then
-- If the other object is a ground object and the character is above it...
if event.other.isGround and self.contentBounds.yMax < event.other.contentBounds.yMin + 5 then
sprite.grounded = sprite.grounded - 1 -- ...unregister a ground collision
end
end
end
sprite:addEventListener("collision")
Then, in your jump function, just check to see if sprite.grounded > 0. If it is, the player is grounded.

LUA/Corona sdk: storyboard.gotoScene() not working

I'm new to Corona and Lua, so pleas be patient.
So i have a main screen, that I go to from my main file, and it works fine. Then i want to go back to that sceen from a diffrent sceen, and nothing happens (but the "win" is spaming my consol window).
The win function:
function win()
print("win!");
storyboard.gotoScene( "MSCREEN.mscreen" );
end
Function where i'm calling it:
function scene:enterFrame(inEvent)
--some other stuff
if (ball.x>display.contentWidth and failFlag==false) then
win();
end
end
and my main sceen:
local scene = storyboard.newScene();
local bg;
local text;
function scene:createScene(inEvent)
bg = display.newImage( "MSCREEN/bg.png");
bg.x = display.contentWidth / 2;
bg.y = display.contentHeight / 2;
text=display.newText( "Touch!", 0,0, fontName, 70);
text.x =display.contentWidth / 2 ;
text.y =display.contentHeight / 2 +230;
self.view:insert(bg);
self.view:insert(text);
end
function scene:enterFrame(inEvent)
tekstBujany(text);
end
function scene:touch(inEvent)
if inEvent.phase == "ended" then
storyboard.gotoScene( "JUMP.GJump" );
end
end
function scene:destroyScene(inEvent)
bg:removeSelf();
bg=nil;
text:removeSelf();
text=nil;
end -- End destroyScene().
scene:addEventListener("createScene", scene);
scene:addEventListener("destroyScene", scene);
Runtime:addEventListener("enterFrame", scene);
Runtime:addEventListener("touch",scene);
return scene;
SOLVED
so adding
storyboard.purgeOnSceneChange = true;
did the trick, not sure why.
Be careful with the win() function, it looks like it gets called a lot of times. Set another variable and change it in the method.
function win()
isNotWin = false -- so this method doesn't get called a lot of times.
print("win!")
storyboard.gotoScene( "MSCREEN.mscreen" )
end
function scene:enterFrame(inEvent)
--some other stuff
if (ball.x>display.contentWidth and failFlag==false and isNotWin == true) then
win();
end
end
The "enterFrame" event gets generated at every frame for the Runtime object, so about 30 to 60 times / sec. So win() will be called at every frame if possible. Since win() causes a transition to a new scene, if storyboard.purgeOnSceneChange = false then enterFrame gets called for each scene, leading to constant stream of win() calls and constant stream of transitions to the same scene "MSCREEN.mscreen" (this can't be good). OTOH if you set storyboard.purgeOnSceneChange = true then the previous scene, here the one with enterFrame that calls win(), is purged so win() will only get called once.
In conclusion, setting storyboard.purgeOnSceneChange = true may work but I think there is a problem with the logic you have there: a scene transition should not be called at every frame! If you are monitoring for some condition to declare a win, you should either remove the enterFrame callback in win() or ensure the condition is false after win() called once:
function scene:enterFrame(inEvent)
if (ball.x > display.contentWidth and failFlag == false) then
win();
Runtime:removeEventListener("enterFrame", scene);
end
end
With the guard variable it looks like this:
local winCalled = false
function win()
winCalled = true
...
end
function scene:enterFrame(inEvent)
if (ball.x > display.contentWidth and failFlag == false) then
win();
end
end

Corona SDK adding physics bodies/ not accepting collisions

I am attempting to add/remove objects from the physics engine (addBody() and removeBody()) in an app I am working on. The app I am working on is modular so the issue is in one of two files.
The objects file (TransmitterObject) or the main file (main):
This is the relevant code for both:
main.lua
local physics = require("physics")
physics.start()
physics.setGravity(0,0)
physics.setDrawMode( "debug" )
local TransmitterObject = require("TransmitterObject")
function updateGame(event)
if(ITERATIONS % 100 == 0) then
tran1:activate() --create new physics object here
end
ITERATIONS = ITERATIONS + 1
--print(ITERATIONS)
end
Runtime:addEventListener("enterFrame", updateGame)
TransmitterObject.lua
function transmitter.new(props) --constructor
Transmitter =
{
x = props.x,
y = props.y,
receivers = props.receivers
}
return setmetatable( Transmitter, transmitter_mt )
end
function transmitter:activate()
local group = math.random(1, #self.receivers)
local receiver = math.random(1,#self.receivers[group])
local x , y = self.receivers[group][receiver][1], self.receivers[group][receiver][2]
local d = math.sqrt(math.pow((self.x-x),2) + math.pow((self.y-y),2))
local dx = math.abs(self.x - x)
local angle = math.deg(math.acos(dx/d))
local beam = display.newRect(self.x,self.y, d, 10)
beam:setReferencePoint(display.TopLeftReferencePoint)
beam.rotation = 180 + angle
beam:setFillColor(0,255,0)
beam.alpha = 0
local function add(event)
physics.addBody(beam, "static")
end
local function delete(event)
physics.removeBody(beam)
end
transition.to( beam, { time=1000, alpha=1.0, onComplete=add } )
transition.to( beam, { time=1000, delay=2500, alpha=0, onComplete=delete})
end
Now let me try to describe the issue a little better. basically every 100th time that 'enterFrame' fires I tell the transmitter object (tran1) to call its function 'activate'
which then preforms some basic math to get coordinates. Then it creates a rectangle (beam) using the calculated information and sets some properties. That is all basic stuff. Next I tell it to transition from not visible (alpha = 0) to visible over the span of 1 second. When does it is to call the function 'add' which adds the object to the physics engine. Likewise with the next line where it removes the objects.
That being said, when i set physics.setDrawMode( "debug" ) the beam object appears as a static body, but does not accept collisions. Does anyone know why the above code would not accept collisions for the beam object?
Keep in mind I have other objects that do work properly within the physics engine.
Wow, I'm answering super late!
On collisions, modifying bodies aren't supported.
What I propose you is to create a new function,
local function addBody ( event )
physics.addBody(ball, "static")
end
and in your collision event you have to add this,
timer.performWithDelay(500, addBody)
The only thing that may cause some problems it's the delay, but as the collision doesn't take too much time it should be ok.
Sorry for this necroposting,
It's just to help other people that may have that problem,
Fannick

iPad-style inertial scrolling in Corona

I'm trying to imitate an iPad-style inertia scroll in Corona, using the touch event and the enterFrame event. In short, I should be able to drag and "throw" an object to a certain extent, similar to scrolling on the iPad. I'm fairly new to Corona, but I've used other languages before. (This is my second day.)
This is the code I've got so far:
local bg = display.newImage("cloud.jpg");
bg:setReferencePoint(bg.TopLeftReferencePoint);
bg.x = 0;
bg.y = 0;
function bg:touch (event)
print("event", event)
for i,v in pairs(event) do
print("**: ",i,v)
end
bg.x = event.x;
bg.y = event.y;
bg.xStart = event.xStart;
bg.yStart = event.yStart;
if (event.phase == "ended")
then
bg.xdelta = bg.xStart + bg.x;
bg.ydelta = bg.yStart + bg.y;
Runtime.addEventListener("enterFrame", bg);
end
end
function bg:enterFrame(event)
bg.x = bg.x + bg.xdelta;
bg.y = bg.y + bg.ydelta;
// TODO: Add code to decrease delta so that object gradually stops.
end
bg:addEventListener("touch");
This is throwing an error in the compiler. What am I doing wrong? I tried making the enterFrame function a local function instead of a table function, but I ran into the same issue. I'm sure that the answer is VERY simple, but I'm not familiar enough with Corona to see it immediately.
Edit: I've done some reading and I've realized that this is closer to what I want:
local bg = display.newImage("cloud.jpg");
bg:setReferencePoint(bg.TopLeftReferencePoint);
bg.x = 0;
bg.y = 0;
bg.xdelta = 0;
bg.ydelta = 0;
local function onEveryFrame(event)
bg.x = bg.x + (bg.oldx - bg.x);
bg.y = bg.y + (bg.oldy - bg.y);
end
function bg:touch (event)
if (event.phase == "ended")
then
print("ended")
bg.oldx = bg.x;
bg.oldy = bg.y;
bg.x = event.x;
bg.y = event.y;
Runtime.addEventListener("enterFrame", onEveryFrame)
end
print("event", event)
for i,v in pairs(event) do
print("**: ",i,v)
end
bg.oldx = bg.x;
bg.oldy = bg.y;
bg.x = event.x;
bg.y = event.y;
print("bg.x:", bg.x)
print("bg.oldx:", bg.oldx)
print("bg.y:", bg.y)
print("bg.oldy:", bg.oldy)
end
bg:addEventListener("touch");
This is no longer erroring out, but I'm not getting the desired result either...
I have not attempted to solve this problem in Corona, but encountered it a lot in Director when implementing smooth scrolling.
While dragging, capture a velocity that measures speed over several touch events, comparing position differences to timestamp differences. Use a table or a linked list for the individual measuring points, and average the velocity over the stored values.
Then the "ended" event in the same position as the last "moved" event will only slightly decrease speed, preserving inertia. In absence of dragging events, subtract a value from the velocity for friction.
Actually, you have a syntax error.
It is Runtime:AddEventListener (pay attention to the : instead of .)
EDIT:
Now about your math:
Your logic do: during a moved event, it sets the bg.p (p for position, both x and y) to event.p
During the ended event you set bg.olp to bg.p and then bg.p to event.p and then you try to every frame do bg.p+=(bg.oldp-bg.p)
This maybe would work IF you did the olp logic on "moved" because the result is this:
Users move finger: moved event triggers, and bg.p changed (thus you see it moving).
Users attempt to remove finger: This trigger a "ended" event, that has a very high change that it will trigger in the same place as the last "moved" event (you would need to move the finger VERY, VERY, VERY fast to trigger a "ended" far from the last "moved"). This will make your bg.oldp be the same as bg.p and thus you do bg.p+=(bg.olp-bg.p) the result is bg.p+=0

Resources