Corona SDK: black screen on Composer transition - android

-- hide device status bar
display.setStatusBar( display.HiddenStatusBar )
-- require controller module
local composer = require( "composer" )
-- load first scene
local scrOptions =
{
effect = "fromRight",
time = 2000
}
composer.gotoScene( "game", scrOptions )
--
-- Display objects added below will not respond to storyboard transitions
local MemUsageDisplay = display.newText( "0", 400, 25, native.systemFont, 20 )
MemUsageDisplay:setFillColor( gray )
local monitorMem = function()
local textMem = system.getInfo( "textureMemoryUsed" ) / 1000000
collectgarbage()
local date = os.date( "*t" )
MemUsageDisplay.text = date.hour .. ":" .. date.min .. ":" .. date.sec .. " / Lua: " .. math.round(collectgarbage("count")) .. "K " .. "Tex: " .. math.round(textMem*10) * 0.1 .. "MB"
end
timer.performWithDelay( 500, monitorMem, 0 )
In the simulator everything is fine.
On the device however the splashscreen flashes for less than a second, then the screen goes black for about 5 seconds, and then the game starts.
There is no transition.
I have to add that my game.lua contains a lot of code, but if I understand the docs correctly, all of that should be processed while the splashscreen is visible? I also ran the app while watching it in debugging mode (catlog...) and put some markers in it to see how fast the code executes. The whole game.lua is processed in less than a second.
Is this normal behavior?

What is the parameter required for composer.gotoScene( "game", scrOptions )?
You need to figure it out in composer library.
have you decrease the time and change the effect in your scrOptions array?
Just try this and let me know what are you getting.
So i can do the further investigation.

It sounds like to me that you are not creating your scene in the scene:create() event function but in the scene:show() event function. Your transition is set for 2 seconds and if you are not creating anything in scene:create() then there won't be anything to transition, but the transition will still take place, ergo going black for a couple of seconds.
Rob

Add this code
local scene = composer.newScene()
If everything is working fine in simulator, that means please check in your code whether your using the proper file name (i.e image name and scene names are correct) since simulator will take Image.png and image.png as same, but in device it will show error.

Related

FFmpeg : How to create dynamic volume changes in an audio file?

I am working on a project in which I need to change the volume of an audio file dynamically.
Let's say, I have an audio file with name xyz.mp3 (20 - seconds audio file).
I need to set the volume in it like :
Time Range (in Seconds) || Volume Percentage (in %)
-------------------------------------------------------------------
0 - 4 || 100
||
4 - 8 || change from 100 - 20 (dynamically)
||
8 - 12 || 20
||
12 - 16 || change from 20 - 100 (dynalically)
||
16 - 20 || 100
Now, I know that to change the volume for a particular time in audio, I can use the following command :
ffmpeg -i in.mp3 -af volume=20:enable='between(t,8,12)' out.mp3
but when I use volume effect, it does not change the volume dynamically. It just straightly change volume from 100 to 20 and not change it like fading.
and When I use afade command like :
ffmpeg -i in.mp3 -af afade=t=in:ss=4:d=8,afade=t=out:st=12:d=16 out.mp3
or
ffmpeg -i in.mp3 -af afade=enable='between(t,4,8)':t=in:ss=4:d=4,afade=enable='between(t,12,16)':t=out:st=12:d=4 out.mp3
but it looks that afade does not work multiple times even when I am using ffmpeg 3.0.1 version.
As afade only works single time, I had also split my audio into parts of 4 second and add fade effects to it and then combine them again, but there is some milliseconds gap comes between each clip. Does anyone know a better way to do it? Please help me...
Update 1 :
Here is that code I used :
"volume='" +
"between(t,0,8)+(1-0.8*(t-8)/4)*" + // full
"between(t,8.01,11.99)+0.1*" + // change from HIGH -> LOW
"between(t,12,16)+(0.1+0.8*(t-16)/4)*" + // low
"between(t,16.01,19.99)+1*" + // change from LOW -> HIGH -
"between(t,20,24)+(1-0.8*(t-24)/4)*" + // full
"between(t,24.01,27.99)+0.1*"+ // change from HIGH -> LOW -
"between(t,28,32)+(0.1+0.8*(t-32)/4)*" + // low
"between(t,32.01,35.99)+1*" + // change from LOW -> HIGH -
"between(t,36,40)+(1-0.8*(t-40)/4)*" + // full
"between(t,40.01,43.99)+0.1*"+ // change from HIGH -> LOW -
"between(t,44,48)+(0.1+0.8*(t-48)/4)*" + // low
"between(t,48.01,51.99)+" + // change from LOW -> HIGH -
"between(t,52,56)" + // high
"':eval=frame";
In this code, I got a small (some milliseconds gap) at those places where I initialize the audio to change the volume
Update 2
Ok I got it, I just need to change the time values like 19.99 to 19.9999 and 16.01 to 16.0001 and it solve the problem. Thank You Gyaan Sir.
Use
volume='between(t,0,4)+(1-0.8*(t-4)/4)*between(t,4.01,7.99)+0.2*between(t,8,12)+(0.2+0.8*(t-12)/4)*between(t,12.01,15.99)+between(t,16,20)':eval=frame

C++11 std::chrono::steady_clock issue on Android

I have been using std::chrono::steady_clock for interval calculation in an application i am making for Android platform.
Code:
// On application start
auto timeSinceEpoch = std::chrono::steady_clock::now().time_since_epoch();
auto timeInSec = std::chrono::duration_cast<seconds>(timeSinceEpoch).count();
log("On Enter Start Time Point - %lld", timeInSec);
Output:
On Enter Start Time Point - 521
Now i switch off the phone and restart the phone. I run my application and this time Output is:
On Enter Start Time Point - 114
As per definition at cppreference.com
"Class std::chrono::steady_clock represents a monotonic clock. The time points of this clock cannot decrease as physical time moves forward."
How is the output when i restart the phone giving lesser value?
If anyone has faced this issue please help me out here. Thanks!!
The formal requirement for a steady clock is that the result of a call to now() that happens before another call to now() is always less than or equal to the result of the second call. The happens before relationship only applies to actions within a program run. A steady clock is not required to be steady across different invocations of a program.
On Android, AFAICT steady_clock is the same as (from Java) System.Clock.elapsedRealtime, which resets to zero on boot -- https://developer.android.com/reference/android/os/SystemClock.html
I'm totally failing to dig up the source code for clock_gettime, though. https://android.googlesource.com/platform/ndk.git/+/43255f3d58b03cd931d29d1ee4e5144e86e875ce/sources/cxx-stl/llvm-libc++/libcxx/src/chrono.cpp#124 shows it calling clock_gettime(CLOCK_MONOTONIC), but I'm not sure how to penetrate the veil from there.

Corona, creating an item in a loop using a timer, that needs an internal timer

so im currently giving app development a shot. Ive been programming in corona for nearly 2 weeks and have hit my first proper road block. My problem is that ive created an item ( called a pointball ( its a little circle ball that you need to tap )). the pointball is called every 2 seconds and is given random coords and an event loop for handling a tap event. My problem, is that i would like to make it so that after 4 seconds each pointball disappears, which i currently cannot do because if i do the timer inside the item it gets called once and the timer isn't called for long enough. If its outside it throws up an error as it cannot see the contents inside the class. Here is the code ( i know its messy, and i know its inefficient, please focus on the problem and not my horrible code style )
function spawnball()
local pointball = display.newImage("pointball.png")
pointball.x, pointball.y = math.random(30,spawnrange2),math.random(30,spawnrange)
pointball.type = "standard"
pointball.id = ("point")
physics.addBody(pointball, "dynamic", {friction=0, bounce = 0})
pointball.myName = ("destructible")
pointball.num = 0
pointball.plus = pointball.num + 1
pointball.touch = function( self,event )
if event.phase == "ended" then
self:removeSelf()
score1 = score1 + 1
typenum = typenum + 1
if typenum == 25 then
level = level + 1
typenum = 0
end
end
return true
end
pointball:addEventListener("touch", pointball)
end
end
function starter()
tutorial2 = false
timer.performWithDelay( 2000, spawnball, -1)
end
after the intro starter gets called and it spawns a ball every 2 seconds ( as seen with the ( 2000, spawnball, -1 ). Now i need a way to add a timer inside the actual class!! if you can help, i will be so grateful.
You can create a timer inside your spawning function:
timer.performWithDelay(4000, function() pointball:removeSelf() end, 1)
I don't know Corna, but assuming the 3rd arg for the timer is the number of repeats, this should execute 4000ms after it's created, and destroy the ball.

How do you make a game to replenish its lives over time?

I'm using Action Script3 Flash pro cc. I have tried to write codes to my game so that it replenishes the player's lives over time. But I have had no success. For example, in Candy Crush, it's called 'lives'. You can have maximum of 5 lives. And once you start a level, it takes off 1 life from the 5 lives. And then the timer next to the lives label starts counting down from 20 minutes to 0. once it reaches 0, it gives you 1 life back so that you can start a level again. I tried to do this like this: Frame EventListener to count down from 20 minutes to 0 whenever the number of lives is under 5, and once it reaches 5, stop counting down numbers. It sounds simple and it is simple. But what if the player quits the game while the timer is counting down?? Let's say the player left the game at 3:10pm with 3 lives and 10 min left for a life replenish. And the player starts the game again at 3:30pm. Then the player would have 4 lives and 10 min left for a life replenish. I tried to accomplish this by using date class. But the remaining time gets messed up whenever I quit the game and restart the game.
Basically you need to keep track of the last time you gave a free life, then just compare the current time with the last time to see how many lives to give.
You'll need to store the lastFreeLifeTS timestamp somewhere, so you have 2 options:
Locally - Either a SharedObject or an XML file, depending on if you're on, say, the web, or using AIR for a mobile app. As #DodgerThud pointed out, this is easy enough to cheat, either by finding the file and modifying the value, or changing the system time. Candy Crush does this though, so you have to decide if this is an important enough issue for you
Online - Ideally, you would store this timestamp on a server, in which case, it's best to move this logic there as well, so it's the server that decides when you get a free live (either by telling the client, or the client can poll the server when it thinks it should have one)
Getting your timestamp is as simple as:
this.lastFreeLifeTS = ( new Date() ).time;
Call this when you either a) give a new free life, or b) use a life when you were at maximum (as then you want your next free life to come at the maximum time from that point).
Then you need to deal with 2 issues:
When the player should get a life in the game
When the player comes back after X amount of time
The first one is easy - just have a timer counting down (NOTE: you don't need to go once every frame - that's higher fidelity than's needed. Once every second or so is all you need). When your time is up, give the life:
var currTime:Number = ( new Date() ).time;
var diff:Number = ( currTime - this.lastFreeLifeTime );
var lifeTime:Number = 1000 * 60 * 20; // give a life every 20 minutes
if( diff > lifeTime )
{
giveFreeLife();
this.lastFreeLifeTime += lifeTime;
}
Seeing as you know when you're going to give a new life, you could almost replace it with a getTimer(), which would mean you don't need to keep creating new Date objects all the time.
// starting off
var lifeTime:Number = 1000 * 60 * 20; // 20 minutes
var msUntilNextLife:Number = ( ( new Date() ).time - this.lastFreeLifeTime ) + lifeTime;
this.nextFreeLifeTime = getTimer() + msUntilNextLife;
...
// check if we need to give a new life
if( getTimer() > this.nextFreeLifeTime )
{
giveFreeLife();
this.lastFreeLifeTime += lifeTime;
this.nextFreeLifeTime += lifeTime;
}
For the second one, you just need to check the timestamp when you start your game, and give any free lives necessary, then you're back to the first type of logic, above.
// load our SharedObject/XML and set our lastFreeLifeTime
...
// check how much time has passed and give any lives necessary
var currTime:Number = ( new Date() ).time;
var diff:Number = currTime - this.lastFreeLifeTime;
var lifeTime:Number = 1000 * 60 * 20; // 20 minutes
var numLives:int = int( diff / lifeTime );
if( numLives > 5 )
numLives = 5; // only give a maximum number of lives
if( numLives > 0 )
{
giveFreeLives( numLives );
// update our lastFreeLifeTime only if we didn't give the max number of lives
// (as otherwise we don't need it)
// NOTE: because we're adding (lifeTime * numLives), it handles the time between
// lives nicely. E.g. If we get a life every 20m and we come back after 30m, then
// our lastFreeLifeTime will be (20 * i), meaning a 10m difference between the
// current time, meaning we only have to wait 10m to get our next one
if( numLives < 5 )
this.lastFreeLifeTime += lifeTime * numLives;
}
Update - getting time from the internet
The easiest way to get timestamp from the net it to control the source yourself; i.e. you own the server/webpage that you're asking the timestamp from.
A simple solution is to host the following php code in a file somewhere:
<?php
echo round( microtime( true ) * 1000 );
?>
All this does is print the current timestamp to the page. You should be able then read the time using a URLLoader:
// NOTE: add all the other listeners, like IOErrorEvent, and SecurityErrorEvent
var urlLoader:URLLoader = new URLLoader( new URLRequest( "http://myserver.com/timestamp.php" ) );
urlLoader.addEventListener( Event.COMPLETE, onGetTime );
function onGetTime( e:Event ):void
{
// remove our event listener so we can clean up
var urlLoader:URLLoader = ( e.target as URLLoader );
urlLoader.removeEventListener( Event.COMPLETE, onGetTime );
// the data is the timestamp returned by php, as a string, so convert it
var timestamp:Number = Number( urlLoader.data );
if ( isNaN( timestamp ) )
{
trace( "Couldn't get the timestamp from the server! Returned details: " + urlLoader.data );
timestamp = ( new Date() ).time; // fallback to client
}
// do something with the time
}
Problems with this approach
It's slow; you're making a web request every time you need to know the current time. The time you get won't be the actual current time, due to latency. For most cases, this isn't a problem, though
You need internet connection; if the user's turned theirs off, this won't work
You may run into security problems and need to host a crossdomain.xml (maybe)
It's a lot of hassle; it's a lot more awkward than a simple (new Date()).time; you now need to host this file somewhere; if your game is successful, your server can get slammed pretty quickly depending on how many players you have and how many times you're calling this
It's up to you to decide whether or not it's worth it. If your game already has a server component, then this generally isn't a problem. I'd advise you to get it working just on the client first, and come back to it if necessary (i.e. you have a ton of players cheating)

Audio is also be cancelled which overlap with acoustic echo when using WebRtc_Aecm on Android

As an example:
PCM captured by microphone:
1, {2,3} {4,5} {6,7}, 8, 9,
{A,B} means A is the audio data I really want to capture, B is the echo at the same time.
A and B both captured by mic at the same time.
The issue I encounter: the audio 2, 4 and 6 are also cancelled while cancelling 3, 5 and 7.
This is my code:
WebRtcAecm_Init( &aecm , 8000 );
While ( aecProcessing )
{
WebRtcAecm_BufferFarend( speakerBuffer );
WebRtcAecm_Process( aecm , micBuffer , NULL , aecBuffer , 160 , 200 );
}
if you run a loopback testing, the normal voice can be cancelled partially.
don't use constant delay like 200ms, cus' this delay is always changes, you should estimate it every 1 second or shorter.
EDIT
please make clear what is echo and what is normal voice.

Categories

Resources