I just got started with Corona yesterday and love what I have seen thus far. I have run into a few issues with which I would like some help
It looks like a Corona app is set up to shut down as soon as the Home button on the phone is clicked. I have come across hints that this can be chanaged from build.settings but nothing more specific. What needs to be specified there?#
I imagine there are pause and resume events associated with when the app gets back/fore grounded?
I'd much appreciate any help with this
For iOS devices, add these in build.setting.
iphone =
{
plist =
{
UIApplicationExitsOnSuspend = false
}
}
Android will automatically suspend when home button is pressed.
See here.
For application suspend/resume handling, you can try:
function onSystemEvent( event )
if ( event.type == "applicationSuspend" ) then
--do stuff
elseif ( event.type == "applicationResume" ) then
--do stuff
end
end
Runtime:addEventListener( "system", onSystemEvent )
See here.
Related
I last created Mods back before Cataclysm. It's been a long time. Just now getting back into it. I'm just trying to write a very basic mod that cancels attacking with the right mouse button.
WorldFrame:HookScript("OnMouseUp", function(self, button)
if button == "RightButton" then
local mouseoverName = UnitName("mouseover") or "Unknown";
local reaction = UnitReaction("mouseover", "player") or 10;
if reaction < 5 then
DEFAULT_CHAT_FRAME:AddMessage("Stopped Attack on: "..mouseoverName);
MouselookStop();
else
DEFAULT_CHAT_FRAME:AddMessage(mouseoverName.." is friendly! "..reaction);
end
end
end)
The code I have should be working (from what I can tell) - but it's not. The code always returns Unknown & 10. If I swap out mouseover for player it works fine (but doesn't actually give me the data I need).
Also, if I swap out and hook-into OnMouseDown it also works, but then I can't actually interrupt the attack.
Any insight on why it's not working or how to fix it would be appreciated... Also if there is just a better way to do things I'm all ears.
UnitName("mouseover") indeed returns nil while any mouse button is pressed.
This is quite a smart idea to prevent attacking hostile units with mouse click. It probably doesn't work because Blizard really made sure to protect any possible thing to do with the WorldFrame that could be abused.
https://wow.gamepedia.com/API_GetCursorInfo sadly also doesn't return if the cursor is currently the sword icon, only if it's holding something.
I am programming my app in corona sdks and am attempting to implement IAP into the app. I am using the sample code from http://coronalabs.com/blog/2013/09/03/tutorial-understanding-in-app-purchases/
What I don't get is how:
local function removeAds( event )
if event.phase == "began" then
event.target:setFillColor(224)
elseif event.phase == "ended" then
event.target:setFillColor(255)
if system.getInfo("targetAppStore") == "amazon" or system.getInfo("targetAppStore") == "google" then
store.purchase( "com.acme.superrunner.upgrade" )
else
store.purchase( { "com.acme.superrunner.upgrade" } )
end
end
return true
end
local buyBtn = display.newImageRect("images/buy_button.png", 614, 65)
group:insert( buyBtn )
buyBtn.x = display.contentCenterX - 465
buyBtn.y = 430
buyBtn:addEventListener( "touch", removeAds )
com.acme.superrunner.upgrade is never mention in the main.lua or utilities.lua files. Am I missing something, how does store.purchase( { "com.acme.superrunner.upgrade" } ) equate to something actually being unlocked in game. Thanks so much for any help! Is there another IAP file I need or something?
com.acme.superrunnerupgrade represents the ID of the store item for which you want the purchase to get initiated. This is usually configured in the Store's (Google play, Apple, Amazon) configuration.
After you configure your item / reward in the store, initiating a purchase to that item would take your user to the respective store item and carry out the payment process.
If the payment is completed, iTunes on the phone will get your app/game active and the callback function will be called.
In App Purchase for IOS are setup using iTunes connect. You can read about the process on the folliwing link: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnectInAppPurchase_Guide/Chapters/Introduction.html
I have a really weird issue with cocos2d-x v3, the first 15 touches or so are not registered on my iOS device (tried iPad 2 and iPad air). As soon as a touch is finally registered, everything works fine (aka all touches after that trigger the onTouch functions).
The touch events work perfectly fine in the simulator.
Also, the same code works perfectly fin in my Windows and Android builds.
Has anyone had this happen, or maybe know what could be causing it?
I'm using the listener, and I debugged up to the spot where touchesBegan forwards the input events to the listener, but even there the events don't come in until after the 15th tap or so.
It's really weird... And I figured I'd give it a shot here, as someone might have encountered this as well, before I start stripping code to as clean as possible, and then try to work my way back from there...
Kind regards,
Michaël
EDIT: As requested, here is some code. The desired behaviour is that it works in iOS devices like it should: First touch triggers the onTouchBegan.
I didn't add it as it didn't think it would matter, since the code works fine for Android.
But I appreciate that you'd like to see it, just in case I might have missed something
GameLayer is a Cocos2d::Layer.
void GameLayer::onEnter()
{
cocos2d::CCLayer::onEnter();
// Register Touch Event
auto pEventDispatcher = cocos2d::Director::getInstance()->getEventDispatcher();
if (pEventDispatcher)
{
// Touch listener
auto pTouchListener = cocos2d::EventListenerTouchOneByOne::create();
if (pTouchListener)
{
pTouchListener->setSwallowTouches( true );
pTouchListener->onTouchBegan = CC_CALLBACK_2( GameLayer::onTouchBegan, this );
pTouchListener->onTouchMoved = CC_CALLBACK_2( GameLayer::onTouchMoved, this );
pTouchListener->onTouchEnded = CC_CALLBACK_2( GameLayer::onTouchEnded, this );
pTouchListener->onTouchCancelled = CC_CALLBACK_2( GameLayer::onTouchCancelled, this );
pEventDispatcher->addEventListenerWithSceneGraphPriority( pTouchListener, this );
}
}
}
bool GameLayer::onTouchBegan( cocos2d::Touch* pTouch, cocos2d::Event* /*pEvent*/ )
{
// Breakpoint here triggers fine on first touch for Android/Windows/iOS Simulator,
// but not on iOS device (iPad/iPhone)
bool breakHere = true;
<<snip actual code>>
}
EDIT:
The problem was an std::ofstream trying to open() on the iOS device (most likely in a folder it didn't have access to).
I have lots of layers in my game and I don't do it like you do. In your code the need to get the EventDispatcher locally and create the touch listener like how you are seems odd to me. I've never seen it down that way in so many steps.
I do:
auto listener = cocos2d::EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true);
listener->onTouchBegan = [&](cocos2d::Touch* touch, cocos2d::Event* event)
{
return true;
};
listener->onTouchEnded = [=](cocos2d::Touch* touch, cocos2d::Event* event)
{
// ... do something
};
cocos2d::Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(listener, 31);
I got it fixed.
The problem was seemingly totally unrelated, I was trying to open an std::ofstream file (my log file), most likely in a folder it didn't have (any and/or write) access to.
Which is not required, nor wanted on the iOS device.
Once I added IOS to the exclusion list (just like Android and some more targets) everything started to work perfect.
I do not know what goes wrong exactly, and why it does start working after a few touch inputs, but I'm guess it was waiting or retrying something in the background.
I found the issue while debugging another one :)
Hopefully this helps anyone else who might stumble onto the same or a related issue.
Kind regards,
Michaël
I'm having a strange error developing with Corona SDK relating to collision-detection and the storyboard lib.
Here is my onCollision listener:
local function onBottomBorderCollision( event )
if (event.other.isBall) then
local index = table.indexOf( ballArray, other )
table.remove( ballArray, index )
event.other:removeSelf( )
event.other = nil
updateLife(false)
updateScore(false)
end
end
This works fine at first launch, but after getting back to the menu screen (using storyboard.goToScene("menu")) and replaying the game, now this listener will trigger the following error every time one of my ball hits the bottom border:
attempt to index field "other"(a nil value)
I do create the proper listeners in scene:onEnterScene(scene) so it's not something to do with them, moreover this other listener never generate the error:
local function onPlayerCollision( event )
if(event.other.isBall) then
xVel, yVel = event.other:getLinearVelocity( )
event.other:setLinearVelocity( event.other.XLinearVelocity, yVel )
end
end
I am stuck right now... please help!
Actually, this type of error is caused mainly due to to some active function call/timers/transitions, which is not yet cancelled before changing the scene.
attempt to index field "other"(a nil value)
The above error mentions that any object/ it's property is being called/fetched, but it is not in the current occurrence or the scene. So, check whether you are cancelling your timers, transitions and runtime event listeners.
In your case, it may be due to the failure in cancellation of collision detection function onBottomBorderCollision in runtime. If you are calling it in enterFrame, then you have to cancel it before scene change. YOu can do it as below:
Runtime:removeEventListener("enterFrame",onBottomBorderCollision)
Update: You can't stop the physics engine while collision check is running. So do as follows:
function actualSceneChange()
physics.stop() -- stop physics here
-- call scene chage
director:changeScene("menuPageName") -- call your scene change method
end
function initiatingSceneChange()
physics.pause() -- pause physics here
-- stop unwanted event listeners
Runtime:removeEventListener("enterFrame",onBottomBorderCollision)
if(timer_1)then timer.cancel(timer_1) end -- stop all your timers like this.
if(trans_1)then transition.cancel(trans) end -- stop all your transitions like this.
timer.performWithDelay(1000,actualSceneChange,1)
end
I believe the issue is because storyboard saves some variables in memory when you switch scenes. The display objects gets destroyed but the reference remains. You are probably initializing your display objects in CreateScene function which gets called only once if you do not remove your scene.
Destroying the scene in the enter scene function of menu would probably fix the issue.
This is done by the Storyboard.removeScene function.
On the "EnterScene" Function of menu.lua, add in a line to remove the scene. eg. if your scene name is game:
storyboard.removeScene("game")
You can know more about difference between destroyScene and purgeScene here
I've scoured the web, upgraded the player, rewritten it 5 times, and now completing my 5th day of failing, and still cannot accomplish what the folks at Longtail tell me will work. (Don't get me wrong, I love 'em there, but this has me ready to jump off a bridge).
I'm simply trying to load a video that will play with Flash or iOS, and upon loading it, immediately go to a specific point in the video useing the .seek() method. Longtail tells me to use the onBeforePlay() function because iOS apparently doesn't respect the start value of the playlist. This code works like smoke with Flash, but ignores the seek in iOS.
Can ANYone assist me with this - it has become the most expensive script I've ever worked on and I have made zero progress at all. :( :( :( Also, I removed all the console functions and tried that, but with the same result.
Full code/player can be seen at http://www.tempurl.us/jw6e.html. You can see that with Flash, the video starts at 60 seconds, but on iOS, it starts at 0.
jwp = jwplayer('jwp').setup({
title: 'Single File Player', width: '720', height:'240', autostart: 'false', listbar: {position: "right",size: 400},
sources:[
{ file: 'http://media3.scctv.net/insight/mp4:nursing_4_clips_400.mp4/playlist.m3u8'},
{ file: 'rtmp://fms.scctv.net/insight/nursing_4_clips_400.mp4'}
]
}
);
jwp.onReady(function() {
// Create a playlist item of the video to play
var newItem = [
{ title: 'Title4 ACUTE_ABDO_PAIN_400',
image: 'playlistitem.png',
sources:[
{ file: 'http://media3.scctv.net/insight/mp4:ACUTE_ABDO_PAIN_400.mp4/playlist.m3u8'},
{ file: 'rtmp://fms.scctv.net/insight/ACUTE_ABDO_PAIN_400.mp4'}
]
}
];
jwp.load(newItem);
});
jwp.onBeforePlay(function() {
// This Works on PC/Mac with Flash, but does nothing on iPad/iPhone
jwp.seek(60);
});
Simply to close the question, the bottom line on this problem was that iOS will not allow autostart - period. Knowing that, all the expected events that were not behaving as expected made sense. Once the user initiates the stream with Play, everything works as expected. In our case, this is still a problem because we want to start later in the stream, but knowing that made dealing with it more manageable.
If the problem is iOS will not allow autostart - period. Knowing that,
all the expected events that were not behaving as expected made sense.
Once the user initiates the stream with Play, everything works as
expected
then you can have a play button only for tablet and ios device and on Clicking the play button,
call jwplayer().play(), this could be a work around for your problem, and after you have invoked jwplayer.play, which is only possible with the touch event, after play is triggeredother events will work.
otherwise even if you try jwplayer().play() onReady(), or autostart nothing will work because of iOs will not allow autostart as you said
I've solved this problem on iOS using onBeforePlay with seek() and play(). This work on desktop flash and IOS. Doesn't work on Android using the parameter androidhls:true
jwplayer().onBeforePlay(function() { jwplayer().seek(60); });
jwplayer().play();
As Ethan JWPlayer mentioned in comment use onPlay event. To prevent "loop buffering" as you said just use flag variable:
var isFirstStart = true,
seekValue = 60;
jwplayer().onPlay(function(){
//exit if it's no first playback start
if( !isFirstStart ) {
return;
}
jwplayer().seek(seekValue);
isFirstStart = false;
});