How do I make an object change direction on tap? - lua

I'm very new to Lua. This is what I tried:
local function tapListener( event )
-- Code executed when the button is tapped
if crate.gravityScale == 1 then crate.gravityScale=-1
if crate.gravityScale == -1 then crate.gravityScale=1
-- "event.target" is the tapped object
return true
end
local myButton = display.newRect( 540, 960, 1080, 1920 )
myButton:setFillColor( 0, 0.01 )
myButton:addEventListener( "tap", tapListener )
-- Add a "tap" listener to the object
What is the correct way to do this? I can't really understand how to do it with just API reference.
.......
Edit 8/19/17:
I didn't like how it moved with gravity so I changed it to setLinearVelocity but now it won't change direction on tap. Here's what I tried:
speed = 400
-- make a crate (off-screen), position it, and rotate slightly
local crate = display.newImageRect( "crate.png", 90, 90 )
crate.x, crate.y = 540, 1750
crate.rotation = 0
physics.addBody( crate, "dyanamic" )
crate:setLinearVelocity(speed, 0)
local function tapListener( event )
speed = speed == 400 and -400 or 400
return true
end
local myButton = display.newRect( 540, 960, 1080, 1920 )
myButton:setFillColor( 0, 0.01 )
myButton:addEventListener( "tap", tapListener )
What did I do wrong?

Related

Trying to make an exit inventory button on coronasdk

I am currently working on a game what requires an inventory system. I cannot work out how to make an exit button for a display object I created.
Here is my code :
local Choose_slot = display.newImage("Images/choose_slot.png")
Choose_slot.x = centerX + 96
Choose_slot.y = 45
function choose_slot:tap ( event )
Inventory_Screen = display.newRect( centerX, centerY, 1500, 1500 )
Inventory_Screen:setFillColor( 0.3, 0.3, 0.3 )
end
local Exit_Button = display.newImageRect( "Images/Exit_Image.png", 32, 32)
Exit_Button.x = centerX + 255
Exit_Button.y = centerY - 135
function Exit_Inventory:tap ( event )
Inventory_Screen:remove()
Exit_Button:remove()
end
Exit_Inventory:addEventListener( "tap", Exit_Button)
Choose_slot:addEventListener( "tap", choose_slot)
Just for your Information, "Choose_slot" is an image that brings up the inventory. I would like to make it so when the "Inventory_Screen" comes up the "Exit_Inventory" button pops up and when you tap it, it removes the "Inventory_Screen" and the "Exit_Button" from the screen and goes back to screen you were on before you clicked inventory!
The picture is what left after I changed your code to this:
function Choose_slot:tap ( event )
Inventory_Screen = display.newRect( centerX, centerY, 1500, 1500 )
Inventory_Screen:setFillColor( 0.3, 0.3, 0.3 )
local function handleExitBEvent( event ) -- ERROR IS BELOW!
if ( "ended" == event.phase ) then
print( "Button was pressed and released" )
print( "Removing Inventory!" )
Choose_slot:removeSelf() -- This is not removing --
ExitB:removeSelf()
Inventory_Screen:removeSelf()
Inventory_Slot1:removeSelf()
end
end
It would be easier to this in a display group so you can remove all objects in a group with a line command.
Add the button and the function to your code as follows:
local function exitFunc(event)
Choose_slot:removeSelf() -- add whatever you want to remove
exitB:removeSelf() -- can use object.isVisible = false if you wanted but they maybe touchable still
end
exitB= widget.newButton
{
width=135,
height=60,
defaultFile = "whatever.png",
overFile = "whateverOver.png",
label = "Exit",
onPress = exitFunc,
}

Attempt to index global 'object' (a nil value)

So this is the error I have been getting:
Game.lua:66: attempt to index global 'Spears' (a nil value)
stack traceback:
Game.lua:66: in function '_listener'
and this is some of the code, showing where the error happens:
local Spears = {}
local SpearsTimer
local SpearsCounter = 1
local delayTimer
local removeListeners
end
end
local field = display.newCircle( 0, 0, 0 ) ; field.alpha = 0.3
field.name = "field"
field.x = display.contentCenterX ; field.y = display.contentCenterY
physics.addBody( field, "static", { isSensor=true, radius=320 } )
local spawnSpears = function()
local Fall = math.random(display.contentWidth * -0.2, display.contentWidth * 1.2)
Spears[SpearsCounter] = display.newImageRect( "Spear.png", 15, 50 )
Spears[SpearsCounter].x = Fall
Spears[SpearsCounter].y = -200
physics.addBody( Spears[SpearsCounter], "dynamic", {bounce = 0} )
--Spears[SpearsCounter].collision = onCollision
--Spears[SpearsCounter]:addEventListener( "collision", Spears[SpearsCounter] )
transition.to( Spears[SpearsCounter], { rotation = Spears[SpearsCounter].rotation+720, time=15000, onComplete=spinImage } )
Spears[SpearsCounter].gravityScale = 0.5
sceneGroup:insert(Spears[SpearsCounter])
group:insert(Spears[SpearsCounter])
SpearsCounter = SpearsCounter + 1
end
SpearsTimer = timer.performWithDelay( 5000, spawnSpears, -1 )
The Error points to line 66, which is this line of code:
Spears[SpearsCounter] = display.newImageRect( "Spear.png", 15, 50 )
So what am I doing wrong?
Oh, and keep in mind that I am trying to make objects spawn randomly throughout the screen and fall/go to the center of the screen. I put Radial Gravity.
The problem is you have declared the
local Spears = {}
in side a function which is not accessible outside that function. Try declaring it outside the function and access. Learn about the scope of the variables.
This is most likely a scope problem. This tutorial will guide you into understanding scope:
https://coronalabs.com/blog/2015/06/16/tutorial-scope-for-beginners/

Placing one object in front of another in Corona SDK

I am building a platform jumper, and when the ball passes through the platform, I would like it to appear in front, not behind, the platform. I've tried putting both objects into a new dispaly group in the proper order and sending the ball to the front using toFront(), but I just can't get it to work. Any thoughts?
local ball = display.newCircle( 100, 100, 30 )
ball.id = "ball"
ball.x, ball.y = 160, 350
ball.rotation = 15
local gradient = {
type="gradient",
color1={ 1, 4, 7 }, color2={ .1, 1, 1.5}, direction="down"
}
ball:setFillColor( gradient )
-- add physics to the ball
physics.addBody( ball, "dynamic", { density=1.0,
friction=0.9, bounce=0 } )
-- create a platform w/ physics
local bottom = display.newRect( 0, 0, 320, 100 )
bottom.anchorX = 0
bottom.anchorY = 1
bottom.x, bottom.y = 0, display.contentHeight
physics.addBody( bottom, "static", { friction=0.3 } )
-- put plat in middle
local platform = display.newRect( 0, 0, screenW-100, screenH-450 )
platform.x, platform.y = 160, 200
platform.collType = "passthru"
physics.addBody( platform, "static", { bounce=0.0, friction=0.3 } )
-- place ball in front
local group = display.newGroup( )
group:insert( ball )
group:insert( platform )
ball:toFront( )
your putting the ball in the wrong order, it should be
local group = display.newGroup( )
group:insert( platform )
group:insert( ball )
Take a look at Group Hierarchy

physics doesn't work in lua

This code creates a cannon and 3 balloons, the cannon should shoot out a bullet that'll destroy balloons, along with the words. DUring the process the cannon should rotate and when i release my finger from the screen it shoots. For some reason it doesn't respond, cannon not rotating nor any bullet is shot.
local score = 0
local scoreText
local scoreForLevelComplete
local background
local infoBar
local restartBtn
local cannon
local levelNum
local cannonCharge = {}
local shot = {}
local cannonBall
local impulse = 0
local balloons = {}
local cannonCharge = {}
local shot = {}
function scene:createScene(event)
local group = self.view
background = display.newImage( "bkg_clouds.png")
group:insert(background)
background.x = 230
background.y = 195
scoreText = display.newText( "0", 0, 0, native.systemFont, 32 )
scoreText:setFillColor( 0,0, 0 )
scoreText.x = 87
scoreText.y = 28
group:insert( scoreText )
questionText = display.newText('a', display.contentCenterX, display.contentWidth/4, native.systemFont, 40)
group:insert(questionText)
infoBar = display.newImage ("infoBar.png")
group:insert(infoBar)
infoBar.x = 10
infoBar.y = 25
restartBtn = display.newImage ("restartBtn.png")
group:insert(restartBtn)
restartBtn.x = 470
restartBtn.y = 300
cannon = display.newImage ("cannon.png")
group:insert(cannon)
cannon.x = 10
cannon.y = 270
cannon.anchorX = 0.5
cannon.anchorY = 0.5
restartBtn.isVisible = true
local balloon = display.newImage ('balloon_fat_red.png', 495, 125)
group:insert(balloon)
balloon = display.newImage ('balloon_fat_red.png', 495, 175)
group:insert(balloon)
balloon = display.newImage ('balloon_fat_red.png', 495, 225)
group:insert(balloon)
local balloonText1 = display.newText('\227\129\130', 495, 125)
balloonText1:setFillColor( 1,1, 0 )
local balloonText2 = display.newText('\227\129\132', 495, 170)
balloonText2:setFillColor( 1,1, 0 )
local balloonText3 = display.newText('\227\129\134', 495, 225)
balloonText3:setFillColor( 1,1, 0 )
balloon.name = 'balloon'
physics.addBody(balloon)
balloon.bodyType = 'static'
table.insert(balloons, balloon)
group:insert(balloonText1)
group:insert(balloonText2)
group:insert(balloonText3)
function ballCollision(e)
if (e.other.name == 'balloon') then
scene.updateScore()
e.target:removeSelf()
print ('remove balloon text')
e.other:removeSelf()
audio.play(pop)
end
end
function cannonCharge:touch(e)
if(e.phase == 'began') then
impulse = 0
cannon.isVisible = true
Runtime:addEventListener('enterFrame', charge)
end
end
function charge()
local degreesPerFrame = 0.5
cannon.rotation = cannon.rotation - degreesPerFrame
impulse=impulse-0.2
if(cannon.rotation < -46) then
cannon.rotation = -46
impulse = -3.2
end
end
function shot:touch(e)
if(e.phase == 'ended') then
Runtime:removeEventListener('enterFrame', charge)
cannon.isVisible = true
cannon.rotation = 0
cannonBall = display.newImage('cannon ball.png', 84, 220)
physics.addBody(cannonBall, {density = 1, friction = 0, bounce = 0})
group:insert(cannonBall)
-- Shoot cannon ball
cannonBall:applyLinearImpulse(3, impulse, cannonBall.x, cannonBall.y )
--Collision listener
cannonBall:addEventListener ('collision', ballCollision)
end
end
end
This is my enterscene function
function scene:enterScene( event )
local group = self.view
background:addEventListener('touch', cannonCharge)
background:addEventListener('touch', shot)
end
I know the Corona docs say that listener can be a table object when call addEventListener('event', listener) but I have never seen or used that. There is no advantage in posted code to have functions defined inside the createScene since they are global and you already have a bunch or module-local variables. Try pulling the listeners out and making them regular functions:
local canon
...
local cannonCharge = function(event)
if event.phase == 'began' then
impulse = 0
cannon.isVisible = true
Runtime:addEventListener('enterFrame', charge)
end
end
local shot = function(event)
...
end
local function charge()
...
end
... other local functions ...
function scene:createScene(event)
...
end
Also, confirm that your touch listeners are being called by printing something inside each one.
Finally, and most importantly, you only added the last balloon to the physics so the bullet can only collide with that one balloon. The same way that you had to add group:insert(balloon) after each balloon created, you should have physics.addBody(balloon, ...) after each group insert. So do this:
local balloon1 = display.newImage ('balloon_fat_red.png', 495, 125)
local balloon2 = display.newImage ('balloon_fat_red.png', 495, 175)
local balloon3 = display.newImage ('balloon_fat_red.png', 495, 225)
group:insert(balloon1)
group:insert(balloon2)
group:insert(balloon3)
physics.addBody(balloon1)
physics.addBody(balloon2)
physics.addBody(balloon3)
balloon1.bodyType = 'static'
balloon2.bodyType = 'static'
balloon3.bodyType = 'static'
table.insert(balloons, balloon1)
table.insert(balloons, balloon2)
table.insert(balloons, balloon3)
There is a lot of code duplication there, and adding more balloons requires many lines to change, so you might as well factor out the duplicate code into a function:
local function createBalloon(x, y)
local balloon = display.newImage ('balloon_fat_red.png', x, y)
group:insert(balloon)
physics.addBody(balloon)
balloon.bodyType = 'static'
table.insert(balloons, balloon)
end
createBalloon(495, 125)
createBalloon(495, 175)
createBalloon(495, 225)
which has the advantage that if you need more balloon you won't forget any settings, and any new settings put in createBallon so all balloons have same config (except for function parameters like x,y etc).
Update: Determine which balloon in collision handler
Depends why you need to know which of the balloons. For example if it's because balloon 1 gives 10 pts while 3 gives 30, then there are better ways: you can add your fields to objects, like you could have balloon1.points = 10, balloon2.points = 30 etc (you would make that a function argument of createBalloon) and in collision handler just use score = score + e.other.points. You should only need to use Local Collision Handling because only need to know when the cannon ball collides with balloons. To figure out if e.other is a balloon, easiest is to add a property when you create balloon:
local function createBalloon(x, y, balloonText)
local balloon = ...
...
balloon.isBalloon = true -- only balloon objects will have this
balloon.label = balloonText
end
Couple notes on the above: another custom property is label since you want to remove the balloon text in the collision handler, easiest is to have a property for it. But do not remove objects involved in collision in the collision handler, as explained in that document, use delayed removal. So your handler becomes
function ballCollision(e)
if e.other.isBalloon then
scene.updateScore(e.other.points)
timer.performWithDelay(1, e.target.removeSelf, e.target)
timer.performWithDelay(1, e.other.removeSelf, e.target)
e.other.label:removeSelf() -- this is ok: not involved in collision
audio.play(pop)
end
end
You have declared balloons as a array and using the balloon
as a variable while assigning images to them. So you need to declare 3 separate balloon object like balloon text or if you are using array then you need to declare like this.
for i=1,3 do
balloon[i] = display.newImage ('balloon_fat_red.png', 495, 225)
group:insert(balloon[i])
end
So it will identify which balloon you want to shoot.

Corona: Can't get instance to "jump" on screen touch

Trying to get a sprite (instance1) to jump on touch, but it won't work.
Here is my code:
physics.addBody( instance1, { density=1.0, friction=0.3, bounce=0.3} )
local function jump( event )
if(event.numTaps == 2) then
instance1:applyForce( 350, -2000, instance1.x, instance1.y )
end
end
instance1:addEventListener("tap", jump)
I will add, that if I do this, the sprite instance will jump once, but never again:
local function jump( event )
if(event.numTaps == 2) then
physics.addBody( instance1, { density=1.0, friction=0.3, bounce=0.3} )
instance1:applyForce( 350, -2000, instance1.x, instance1.y )
end
end
instance1:addEventListener("tap", jump)
Instance info:
local sheet1 = sprite.newSpriteSheet( "character.png", 75, 105 )
local spriteSet1 = sprite.newSpriteSet(sheet1, 1, 16)
sprite.add( spriteSet1, "character", 1, 12, 700, 1 ) -- play 12 frames every 700 ms
local instance1 = sprite.newSprite( spriteSet1 )
instance1.x = display.contentWidth/2
instance1.y = 240
still cant reproduce your error,
i answered your question to paste the code i tested:
--main.lua
local sprite=require("sprite")
local physics=require("physics")
local sheet1 = sprite.newSpriteSheet( "character.png", 75, 105 )
local spriteSet1 = sprite.newSpriteSet(sheet1, 1, 16)
sprite.add( spriteSet1, "character", 1, 12, 700, 1 ) -- play 12 frames every 700 ms
local instance1 = sprite.newSprite( spriteSet1 )
instance1.x = display.contentWidth/2
instance1.y = 240
physics.start()
physics.setGravity(0,1)
physics.addBody( instance1, { density=1.0, friction=0.3, bounce=0.3} )
local function jump( event )
if(event.numTaps == 2) then
instance1:applyForce( 35, -200, instance1.x, instance1.y )
end
end
instance1:addEventListener("tap", jump)

Resources