attempt to call method 'applyForce' - android

I'm making a side scroller and when i start my game i can touch the screen to keep my penguin in the air, but when i fail and collide with an ice block and press play after going to restart.lua i get the error attempt to call method 'applyForce'
heres my code
local function activatePengs(self,event)
self:applyForce(0, -45, self.x, self.y)
print("run")
end
local function touchScreen(event)
print("touch")
if event.phase == "began" then
peng.enterFrame = activatePengs
Runtime:addEventListener("enterFrame", peng)
end
if event.phase == "ended" then
Runtime:removeEventListener("enterFrame", peng)
end
end
local function onCollision(event)
if event.phase == "began" then
print "collide"
composer.gotoScene( "restart",{ time=800, effect="crossFade" } )
end
end
-- now comes four required functions for Composer:
function scene:create( event )
local sceneGroup = self.view
bg1 = display.newImageRect(sceneGroup, "bg.png", 800, 1000)
bg2 = display.newImage(sceneGroup, "ice2.png",140,210)
bg3 = display.newImage(sceneGroup, "ice2.png",540,210)
bg4 = display.newImage(sceneGroup, "ice2.png",940,210)
bg5 = display.newImage(sceneGroup, "ice2.png",1340,210)
bg6 = display.newImage(sceneGroup, "ice2.png",1740,210)
bg7 = display.newImage(sceneGroup, "ice1.png",140,420)
bg8 = display.newImage(sceneGroup, "ice1.png",540,420)
bg9 = display.newImage(sceneGroup, "ice1.png",940,420)
bg10 = display.newImage(sceneGroup, "ice1.png",1340,420)
bg11 = display.newImage(sceneGroup, "ice1.png",1740,420)
peng = display.newImage(sceneGroup, "peng.png", 80, 201)
physics.addBody(peng, "dynamic", {density=.18, bounce=0.1, friction=.5, radius=55})
...
end

Probably the error occurs because penguin is not a physics object when the function is called. I think remove enterFrame listener before go to next scene should solve your problem.
I added some improvements to your code (not tested) :
local applyForceToPenguin = false
local function enterFrame( self, event )
if applyForceToPenguin then
self:applyForce( 0, -45, self.x, self.y )
print("run")
end
end
local function touchScreen(event)
print("touch")
if event.phase == "began" then applyForceToPenguin = true end
if event.phase == "ended" then applyForceToPenguin = false end
end
local function onCollision(event)
if event.phase == "began" then
print "collide"
applyForceToPenguin = false
composer.gotoScene( "restart",{ time=800, effect="crossFade" } )
end
end
-- now comes four required functions for Composer:
function scene:create( event )
local sceneGroup = self.view
bg1 = display.newImageRect( sceneGroup, "bg.png", 800, 1000 )
bg2 = display.newImage( sceneGroup, "ice2.png", 140, 210 )
bg3 = display.newImage( sceneGroup, "ice2.png", 540, 210 )
bg4 = display.newImage( sceneGroup, "ice2.png", 940, 210 )
bg5 = display.newImage( sceneGroup, "ice2.png", 1340, 210 )
bg6 = display.newImage( sceneGroup, "ice2.png", 1740, 210 )
bg7 = display.newImage( sceneGroup, "ice1.png", 140, 420 )
bg8 = display.newImage( sceneGroup, "ice1.png", 540, 420 )
bg9 = display.newImage( sceneGroup, "ice1.png", 940, 420 )
bg10 = display.newImage( sceneGroup, "ice1.png", 1340, 420 )
bg11 = display.newImage( sceneGroup, "ice1.png", 1740, 420 )
peng = display.newImage( sceneGroup, "peng.png", 80, 201)
physics.addBody( peng, "dynamic", { density=.18, bounce=0.1, friction=.5, radius=55 } )
Runtime:addEventListener( "enterFrame", enterFrame )
...
end
function scene:destroy()
Runtime:removeEventListener( "enterFrame", enterFrame )
end
function scene:hide( event )
local sceneGroup = self.view
local phase = event.phase
if phase == "will" then
-- Code here runs when the scene is still off screen (but is about to come on screen)
elseif phase == "did" then
-- Code here runs when the scene is entirely on screen
applyForceToPenguin = false
end
end
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )
Have a nice day:)

Related

How do I switch to another scene in the Corona SDK?

I have a main scene in the Corona SDK (main.lua) On this scene there is a button, when you click on which there should be a transition to another scene (home.lua). How do I do this? Preferably using composer
Modified version of example from documentation
local composer = require( "composer" )
local scene = composer.newScene()
...
local object = display.newImage( "ball.png" )
local function onObjectTouch( event )
if ( event.phase == "began" ) then
elseif ( event.phase == "ended" ) then
composer.gotoScene( "home" )
end
return true
end
object:addEventListener( "touch", onObjectTouch )

Properly remove a scrollView in Corona SDK

In my game I have a scrollview widget declared inside a function, and I want to remove that scrollview using another function, something like this:
local function createScrollView(event)
if(event.phase=="ended")then
local function scrollListener( event )
local phase = event.phase
local direction = event.direction
if "began" == phase then
--print( "Began" )
elseif "moved" == phase then
print( "Moved" )
elseif "ended" == phase then
--print( "Ended" )
end
-- If the scrollView has reached it's scroll limit
if event.limitReached then
if "up" == direction then
print( "Reached Top Limit" )
elseif "down" == direction then
print( "Reached Bottom Limit" )
elseif "left" == direction then
print( "Reached Left Limit" )
elseif "right" == direction then
print( "Reached Right Limit" )
end
end
return true
end
-- Create a ScrollView
local scrollView = widget.newScrollView
{
left = display.contentWidth/2-130,
top = display.contentHeight/2-165,
width = 440,
height = 300,
bottomPadding = 10,
id = "onBottom",
backgroundColor = { 0, 0, 0, 0 },
horizontalScrollDisabled = true,
verticalScrollDisabled = false,
listener = scrollListener,
}
end
end
local function removeScrollView(event)
if(event.phase==ended)then
if scrollView then
scrollView:removeSelf()
scrollView = nil
end
end
end
It doesn't return any error, but I can see that the scrollView still exists because the Corona Terminal keeps printing "moved".
Do you know how could I remove it?
local scrollView ------------EDITED
local function createScrollView(event)
if(event.phase=="ended")then
local function scrollListener( event )
local phase = event.phase
local direction = event.direction
if "began" == phase then
--print( "Began" )
elseif "moved" == phase then
print( "Moved" )
elseif "ended" == phase then
--print( "Ended" )
end
-- If the scrollView has reached it's scroll limit
if event.limitReached then
if "up" == direction then
print( "Reached Top Limit" )
elseif "down" == direction then
print( "Reached Bottom Limit" )
elseif "left" == direction then
print( "Reached Left Limit" )
elseif "right" == direction then
print( "Reached Right Limit" )
end
end
return true
end
-- Create a ScrollView
---EDITED---------------------
scrollView = widget.newScrollView
{
left = display.contentWidth/2-130,
top = display.contentHeight/2-165,
width = 440,
height = 300,
bottomPadding = 10,
id = "onBottom",
backgroundColor = { 0, 0, 0, 0 },
horizontalScrollDisabled = true,
verticalScrollDisabled = false,
listener = scrollListener,
}
end
end
local function removeScrollView(event)
if(event.phase==ended)then
if scrollView then
scrollView:removeSelf()
scrollView = nil
end
end
end
So that you can remove the scroll view in the removeScrollView function.

Closing slide menu

trying to use slide menu from function https://coronalabs.com/blog/2014/04/08/widgets-creating-a-sliding-panel/
I followed exactly the suggested code and I created a panel with 3 texts and one button. Then I added an event to the button to close the panel, but it does not work. Cannot understand why..:(. Here is the code:
local panel = widget.newPanel
{
location = "left",
--onComplete = panelTransDone,
width = display.contentWidth * 0.8,
height = display.contentHeight * 0.8,
speed = 500,
--inEasing = easing.outBack,
outEasing = easing.outCubic
}
panel.background = display.newRect( 100, -50, 900, 730 )
panel.background:setFillColor( 0.1, 0.1, 0.1, 0.9 )
panel:insert( panel.background )
panel.item1 = display.newText( "GAME DESCRIPTION", 0, 0, native.systemFontBold, 40 )
panel.item1:setFillColor( 1, 1, 0 )
panel.item1.x = -95
panel.item1.y = -350
panel:insert( panel.item1 )
panel.item2 = display.newText( "SET SOUNDS", 0, 0, native.systemFontBold, 40 )
panel.item2:setFillColor( 1, 1, 0 )
panel.item2.x = -170
panel.item2.y = -250
panel:insert( panel.item2 )
panel.item3 = display.newText( "CHECK SCORE", 0, 0, native.systemFontBold, 40 )
panel.item3:setFillColor( 1, 1, 0 )
panel.item3.x = -150
panel.item3.y = -150
panel:insert( panel.item3 )
panel.item4 = display.newText( "CLOSE", 0, 0, native.systemFontBold, 40 )
panel.item4:setFillColor( 1, 1, 0 )
panel.item4.x = -230
panel.item4.y = -50
panel:insert( panel.item4 )
local bottoneex = widget.newButton
{
--defaultFile = "play.png",
label="ESCI",
labelColor =
{
default = { 1, 1, 0, 255 },
},
font = native.systemFont,
fontSize = 40,
emboss = false,
textonly = true,
onEvent = provap
}
bottoneex.x = -250
bottoneex.y = 50
panel:insert( bottoneex )
function apripanel()
panel:show()
panel:toFront()
end
function provap()
panel:hide()
end
My target is to build a slide menu by adding to this panel several menu items. How can I achieve that? I tried putting a button ( textonly = true ) but I am not sure...what if I add displaytext (as I did)? How can I add listeners to texts?
Sorry for silly questions but I am quit new to this language! :)
Thanks a lot for your help! Ubaldo
Hiding the menu works for me, maybe you use an old version of newPanel.lua, this should work for you.
main.lua
widget = require("widget")
require("newPanel")
BG = display.newRect(160,240,300,460)
BG:setFillColor( 0.1, 0.1, 0.1, 1.0 )
local panel = widget.newPanel
{
location = "left",
onComplete = panelTransDone,
width = display.contentWidth*0.8,
height = display.contentHeight,
speed = 500,
inEasing = easing.outBack,
outEasing = easing.outCubic
}
panel.background = display.newRect( 0, 0, 320, 480 )
panel.background:setFillColor( 0.3, 0.3, 0.3, 0.9 )
panel:insert( panel.background )
panel.item1 = display.newText( "Item1", 0, 0, native.systemFontBold, 10 )
panel.item1:setFillColor( 1, 1, 0 )
panel:insert( panel.item1 )
local function ButtonEvent1(e)
if ( "ended" == e.phase ) then
print( "Button 1" )
panel:show()
panel:toFront()
end
end
local function ButtonEvent2(e)
if ( "ended" == e.phase ) then
print( "Button 1" )
panel:hide()
end
end
local B1 = widget.newButton({left = 100,top = 200,id = "button1",label = "Show",onEvent = ButtonEvent1})
local B2 = widget.newButton({left = 100,top = 300,id = "button2",label = "Hide",onEvent = ButtonEvent2})
newPanel.lua
function widget.newPanel( options )
local customOptions = options or {}
local opt = {}
opt.location = customOptions.location or "top"
local default_width, default_height
if ( opt.location == "top" or opt.location == "bottom" ) then
default_width = display.contentWidth
default_height = display.contentHeight * 0.33
else
default_width = display.contentWidth * 0.33
default_height = display.contentHeight
end
opt.width = customOptions.width or default_width
opt.height = customOptions.height or default_height
opt.speed = customOptions.speed or 500
opt.inEasing = customOptions.inEasing or easing.linear
opt.outEasing = customOptions.outEasing or easing.linear
if ( customOptions.onComplete and type(customOptions.onComplete) == "function" ) then
opt.listener = customOptions.onComplete
else
opt.listener = nil
end
local container = display.newContainer( opt.width, opt.height )
if ( opt.location == "left" ) then
container.anchorX = 1.0
container.x = display.screenOriginX
container.anchorY = 0.5
container.y = display.contentCenterY
elseif ( opt.location == "right" ) then
container.anchorX = 0.0
container.x = display.actualContentWidth
container.anchorY = 0.5
container.y = display.contentCenterY
elseif ( opt.location == "top" ) then
container.anchorX = 0.5
container.x = display.contentCenterX
container.anchorY = 1.0
container.y = display.screenOriginY
else
container.anchorX = 0.5
container.x = display.contentCenterX
container.anchorY = 0.0
container.y = display.actualContentHeight
end
function container:show()
local options = {
time = opt.speed,
transition = opt.inEasing
}
if ( opt.listener ) then
options.onComplete = opt.listener
self.completeState = "shown"
end
if ( opt.location == "top" ) then
options.y = display.screenOriginY + opt.height
elseif ( opt.location == "bottom" ) then
options.y = display.actualContentHeight - opt.height
elseif ( opt.location == "left" ) then
options.x = display.screenOriginX + opt.width
else
options.x = display.actualContentWidth - opt.width
end
transition.to( self, options )
end
function container:hide()
local options = {
time = opt.speed,
transition = opt.outEasing
}
if ( opt.listener ) then
options.onComplete = opt.listener
self.completeState = "hidden"
end
if ( opt.location == "top" ) then
options.y = display.screenOriginY
elseif ( opt.location == "bottom" ) then
options.y = display.actualContentHeight
elseif ( opt.location == "left" ) then
options.x = display.screenOriginX
else
options.x = display.actualContentWidth
end
transition.to( self, options )
end
return container
end

Stop physics for single object in Corona SDK?

I'm having a problem when I try to restart my game. I pause the physics, then when the user clicks the button, the physics are supposed to restart. When I put in physics.start(), though the game crashes. So, I was wondering if it's possible to pause one physical object and then change it's position on the screen. I'm kind of a newb so any answer will be helpful.
local physics = require( "physics")
physics.start( )
local crate1 = display.newRect( display.contentWidth/2,display.contentHeight/2, 40,40)
physics.addBody( crate1, { density=4.0, friction=0.3, bounce=.4} )
crate1.bodyType = "dynamic"
crate1.isBodyActive = true
crate1:setFillColor( 1,0,.3)
sky = display.newRect( display.contentWidth/2, .5, display.contentWidth, 0.000000000000000000001)
physics.addBody( sky, {density=4.0, friction=0.3, bounce=1.5} )
sky.bodyType = "static"
ground = display.newRect( display.contentWidth/2, display.contentHeight, display.contentWidth, .00000000001 )
physics.addBody( ground, {density=4.0, friction=0.3, bounce=1.5 } )
ground.bodyType = "static"
rightWall = display.newRect( display.contentWidth, display.contentHeight/2, 1, display.contentHeight )
physics.addBody( rightWall, {density=4.0, friction=0.3, bounce=1.5} )
rightWall.bodyType = "static"
leftWall = display.newRect(1, display.contentHeight/2, .0000000001, display.contentHeight )
physics.addBody( leftWall, {density=4.0, friction=0.3, bounce=1.5} )
leftWall.bodyType = "static"
physics.setGravity( 0, 3 )
local function handleCollisionOnDelay( event )
local obj = event.source.object
obj.isBodyActive = false
end
local function onLocalCollision( self, event )
if ( event.phase == "began" ) then
local dr = timer.performWithDelay( 10, handleCollisionOnDelay )
dr.object = self
crate1.x = display.contentWidth/2
crate1.y = display.contentHeight/2
end
end
crate1.collision = onLocalCollision
crate1:addEventListener( "collision", crate1 )
use isBodyActive property
http://docs.coronalabs.com/api/type/Body/isBodyActive.html
good luck

Multitouch detection with holding event Corona SDK

I have this big issue, and im so pissed off because of this. I have no idea anymore how to make a function that handles touching more than one object. To introduce what i have and what should it do.
I have 3 objects, two buttons: LEFT and RIGHT. and SHOOTING button. I need to be able to shoot while holding the rotating button. I have this (code below) and it does work but if i touch shooting button it stops rotating.
local isShooting = false
function resetShooting()
isShooting = false
end
function holdingLeft()
if isPressed == true then
if rotationOfship > 0 then
if touchedXTimes < 10 then
rotationOfship = rotationOfship-2
touchedXTimes = touchedXTimes + 1
ship.rotation = rotationOfship
elseif touchedXTimes > 9 then
rotationOfship = rotationOfship-5
touchedXTimes = touchedXTimes + 1
ship.rotation = rotationOfship
elseif touchedXTimes > 29 then
rotationOfship = rotationOfship-8
touchedXTimes = touchedXTimes + 1
ship.rotation = rotationOfship
end
else
rotationOfship = 360
end
elseif isPressed == false then
timer.cancel(tmr_hold)
end
end
function holdingRight()
if isPressed == true then
if rotationOfship < 360 then
if touchedXTimes < 10 then
rotationOfship = rotationOfship+2
touchedXTimes = touchedXTimes + 1
ship.rotation = rotationOfship
elseif touchedXTimes > 9 then
rotationOfship = rotationOfship+5
touchedXTimes = touchedXTimes + 1
ship.rotation = rotationOfship
elseif touchedXTimes > 29 then
rotationOfship = rotationOfship+8
touchedXTimes = touchedXTimes + 1
ship.rotation = rotationOfship
end
print(touchedXTimes)
else
rotationOfship = 0
end
elseif isPressed == false then
timer.cancel(tmr_hold)
end
end
function onTouch(event)
if event.target.name == "left" then
if event.phase == "began" then
isPressed = true
display.getCurrentStage():setFocus( event.target )
event.target.isFocus = true
if tmr_hold ~= nil then timer.cancel(tmr_hold) end
tmr_hold = timer.performWithDelay( 8, holdingLeft, 0)
elseif event.target.isFocus then
if event.phase == "ended" or event.phase == "cancelled" then
isPressed = false
timer.cancel(tmr_hold)
touchedXTimes = 0
display.getCurrentStage():setFocus( nil )
event.target.isFocus = false
end
end
end
if event.target.name == "right" then
if event.phase == "began" then
isPressed = true
display.getCurrentStage():setFocus( event.target )
event.target.isFocus = true
if tmr_hold ~= nil then timer.cancel(tmr_hold) end
tmr_hold = timer.performWithDelay( 8, holdingRight, 0)
elseif event.target.isFocus then
if event.phase == "ended" or event.phase == "cancelled" then
isPressed = false
timer.cancel(tmr_hold)
touchedXTimes = 0
display.getCurrentStage():setFocus( nil )
event.target.isFocus = false
end
end
end
if event.target.name == "laser" then
if event.phase == "began" and isShooting == false then
isShooting = true
display.getCurrentStage():setFocus( event.target )
event.target.isFocus = true
bullet = display.newImageRect("images/laser.png",math.random(5,20),5/2)
bullet.x = halfW
bullet.y = halfH
bullet.name = "bullet"
bullet.rotation = rotationOfship-90
physics.addBody( bullet, "dynamic", { isSensor=true, radius=10} )
group:insert(bullet)
ship:toFront()
audio.play( laserSound, { channel=2, loops=0} )
local newX, newY = pointAtDistance(rotationOfship-90, 400)
bullet:setLinearVelocity( newX/2, newY/2 )
tmr_shoot = timer.performWithDelay( math.random(300,400), resetShooting, 1)
elseif event.target.isFocus then
if event.phase == "ended" or event.phase == "cancelled" then
isShooting = false
timer.cancel(tmr_shoot)
display.getCurrentStage():setFocus( nil )
event.target.isFocus = false
end
end
end
return true
end
dpad_left_circle:addEventListener( "touch", onTouch )
dpad_right_circle:addEventListener( "touch", onTouch )
laser_button_circle:addEventListener( "touch", onTouch )
I would recommend to split it to three methods instead of one:
dpad_left_circle:addEventListener( "touch", onTouchLeft )
dpad_right_circle:addEventListener( "touch", onTouchRight )
laser_button_circle:addEventListener( "touch", onTouchLaser )
Code will be much more clear and you'll be able to touch different buttons at the same time.

Categories

Resources