Lua / corona sdk physics.addBody() - lua

When my ball hits but 30 targets 30 new returns except I have an error message lua:76: physics.addBody() cannot be called when the world is locked and in the middle of number crunching, such as during a collision event why ?
function CreeNiveau()
print("Crée le Niveau 1 ")
local lig,col ,x,y
local largeurColonne = (display.actualContentWidth/(5+1))
x = display.screenOriginX + largeurColonne
y = display.screenOriginY + 100
-- si une cible et toucher la Remove et donne des point
local function onToucheCible(self, event)
if event.phase == "began" then
audio.play(sonBump)
self:removeSelf()
AjouteScore(25)
nbCible = nbCible - 1
print("Nombre de cible restent", nbCible)
if nbCible == 0 then
Recible()
end
end
end
for lig = 1,6 do
for col = 1, 5 do
local cible = display.newCircle(x,y, 8)
-- couleur des cible
cible:setFillColor(1,math.random(),math.random())
physics.addBody( cible, "static", { density = 1, friction = 0.3, bounce = 0.6, radius = 8})
cible.collision = onToucheCible
cible:addEventListener("collision")
globaleview:insert(cible)
x = x + largeurColonne
end
y = y + 50
x = display.screenOriginX + largeurColonne
end

You probably use physics functions/APIs in collision listener. Use timer.performWithDelay to delay execution of Recible function:
local function onToucheCible( self, event )
if event.phase == "began" then
audio.play( sonBump )
self:removeSelf()
AjouteScore( 25 )
nbCible = nbCible - 1
print("Nombre de cible restent", nbCible)
if nbCible == 0 then
timer.performWithDelay( 50, Recible )
end
end
end
Read more:
physics.addBody() cannot be called
physics.addBody cannot be called when the world is locked and in the middle of number crunching such as during a collision event

Related

Problems with score function in corona sdk (lua)

Good evening,
I have a problem with the score function in my videogame.
I need it for a university exam.
in practice, in the video game the little man has to "save" the animals from the burning forest and jump over the sotacles.
when he goes on an animal the score increases, only that the score doubles and, after he has saved the first animal, the other elements invert the typical direction of travel. it almost seems that the little man pushes him in the opposite direction.
What could be the problem?
here the codes with the score function and the generation of the elements
local function updateScore()
scoreDisplay=display.newText(sceneGroup, "Score:", display.contentCenterX, display.contentCenterY-150, native.systemFont, 30)
scoreDisplay:setFillColor(black)
score = score + 1
scoreDisplay.text="Score:" .. score
end
-- Funzione per la creazione degli ostacoli e animali
local function createElement( event )
-- In base al numero cambia l'elemento caricato
local obstacle = math.random(4)
-- Ostacolo fiamma
if(obstacle == 1) then
element = display.newImageRect(sceneGroup,"img/flame.png", 80, 80);
element.myName = "obstacle"
-- L'elemento generato viene posizionato in modo casuale, ma entro i margini dello schermo
element.x = 1080
element.y = 100;
-- Aggiungiamo un corpo statico alla fiamma
physics.addBody(element, "dynamic", { bounce=0.0 })
-- Ostacolo roccia
elseif(obstacle == 2) then
element = display.newImageRect(sceneGroup,"img/rock.png", 70, 50);
element.myName = "obstacle"
element.x = 1080
element.y = 100;
-- Aggiungiamo un corpo statico alla roccia
physics.addBody(element, "dynamic", { bounce=0.0 })
-- Animale
elseif (obstacle == 3) then
element = display.newImageRect(sceneGroup,"img/rabbit.png", 80, 80);
element.myName = "animal"
element.x = 1080
element.y = 100;
-- Aggiungiamo un corpo statico al coniglio
physics.addBody(element, "dynamic", { bounce=0.0 })
elseif (obstacle==4) then
element = display.newImageRect(sceneGroup,"img/koala.png", 200, 120);
element.myName = "animal"
element.x = 1080
element.y = 100;
-- Aggiungiamo un corpo statico al koala
physics.addBody(element, "dynamic", { bounce=0.0 })
end
table.insert(elements, element)
return element
end
-- funzione che elimina gli ostacoli non attivi e ne crea di nuovi
-- e viene chiamato ogni secondo
and here the collision function
--funzione che implementa le collisioni
local function onCollision(self,event)
if (event.phase=="began") then
-- self rappresenta l'oggetto badGuy
-- event.other rappresenta l'altro ogetto
-- coinvolto nell'urto
if event.other.myName=="ground" and event.contact.isTouching==true then
self.action="run"
end
if ((event.other.myName=="animal" and self.myName=="boy") or (event.other.myName=="animal" and self.myName=="boy")) then
if(event.contact.isTouching==true) then
updateScore()
end
event.contact.isTouching=false
transition.fadeOut( event.other, { time = 30 } )
print("score")
end
end
--se la collisione avviene tra boy, la fiamma e la roccia
if ((event.other.myName=="obstacle" and self.myName=="boy") or (event.other.myName=="boy" and self.myName=="obstacle")) then
physics.pause()
display.remove(boy)
boy = nil
--rimozione suono in sottofondo
audio.stop(playSound)
playSound=nil
--liberazione memoria
audio.dispose(playSound)
--rimozione listener dello sfondo
Runtime:removeEventListener("enterFrame", bosco1)
Runtime:removeEventListener("enterFrame", bosco2)
--rimozione listener terreno
Runtime:removeEventListener("enterFrame", terreno1)
Runtime:removeEventListener("enterFrame", terreno2)
--rimozione listener collisioni
Runtime:removeEventListener("enterFrame", onCollision)
--Rimozione listener per il tap di boy
Runtime:removeEventListener("tap", boyJump)
--stoppamente generazione nuovi elementi
timer.cancel(gameLoopTimer)
composer.gotoScene("restart",{ time=800, effect="crossFade" } )
end
end
who can help me? thanks!

I got an error here in main.lua: 178: attempt to index global 'pausebutton' (a nil value)

I got an error in Corona's simulator console in main.lua
attempt to index global pausebutton (a nil value)
How to solve my problem with Corona error?
The most revelant code from main.lua file I put below
-- Display the pause button
function pauseAndResume ()
local pausebutton = display.newImage ("pause.png")
pausebutton : translate(100, 100)
pausebutton:addEventListener ("touch" , pauseGame)
local resumebutton = display.newImage ("resumed.png")
resumebutton: translate(100, 100)
resumebutton.isVisible = false
resumebutton:addEventListener ("touch", resumeGame)
end
function pauseGame (event)
if (event.phase == "ended") then
physics.pause ()
pausebutton.isVisible = false
resumebutton.isVisible = true
timer.pause(fruitTimer)
timer.pause(bombTimer)
sampleVar = false
return true
end
end
function resumeGame (event)
if (event.phase == "ended") then
physics.start()
pausebutton.isVisible = true
resumebutton.isVisible = false
timer.resume(fruitTimer)
timer.resume(bombTimer)
sampleVar = true
return true
end
end
I think you got error because local variables pausebutton and resumebutton exist only during executing of pauseAndResume function. After that they gone. So you need declare them in the block in which they will be available for pauseAndResume and pauseGame functions, for example on begining of the main.lua file.
Try
local pausebutton
local resumebutton
...
-- Display the pause button
function pauseAndResume ()
pausebutton = display.newImage ("pause.png")
pausebutton : translate(100, 100)
pausebutton:addEventListener ("touch" , pauseGame)
resumebutton = display.newImage ("resumed.png")
resumebutton: translate(100, 100)
resumebutton.isVisible = false
resumebutton:addEventListener ("touch", resumeGame)
end
function pauseGame (event)
if (event.phase == "ended") then
physics.pause ()
pausebutton.isVisible = false
resumebutton.isVisible = true
timer.pause(fruitTimer)
timer.pause(bombTimer)
sampleVar = false
return true
end
end
function resumeGame (event)
if (event.phase == "ended") then
physics.start()
pausebutton.isVisible = true
resumebutton.isVisible = false
timer.resume(fruitTimer)
timer.resume(bombTimer)
sampleVar = true
return true
end
end
From Lua documentation
We create local variables with the local statement:
j = 10 -- global variable
local i = 1 -- local variable
Unlike global variables, local variables have their scope limited to
the block where they are declared. A block is the body of a control
structure, the body of a function, or a chunk (the file or string with
the code where the variable is declared).
-- Samurai Fruit
require ("physics")
local ui = require("ui")
physics.start()
-- physics.setDrawMode ( "hybrid" ) -- Uncomment in order to show in hybrid mode
physics.setGravity( 0, 9.8 * 2)
physics.start()
-- Audio for slash sound (sound you hear when user swipes his/her finger across the screen)
local slashSounds = {slash1 = audio.loadSound("slash1.wav"), slash2 = audio.loadSound("slash2.wav"), slash3 = audio.loadSound("slash3.wav")}
local slashSoundEnabled = true -- sound should be enabled by default on startup
local minTimeBetweenSlashes = 150 -- Minimum amount of time in between each slash sound
local minDistanceForSlashSound = 50 -- Amount of pixels the users finger needs to travel in one frame in order to play a slash sound
-- Audio for chopped fruit
local choppedSound = {chopped1 = audio.loadSound("chopped1.wav"), chopped2 = audio.loadSound("chopped2.wav")}
-- Audio for bomb
local preExplosion = audio.loadSound("preExplosion.wav")
local explosion = audio.loadSound("explosion.wav")
-- Adding a collision filter so the fruits do not collide with each other, they only collide with the catch platform
local fruitProp = {density = 1.0, friction = 0.3, bounce = 0.2, filter = {categoryBits = 2, maskBits = 1}}
local catchPlatformProp = {density = 1.0, friction = 0.3, bounce = 0.2, filter = {categoryBits = 1, maskBits = 2}}
-- Gush filter should not interact with other fruit or the catch platform
local gushProp = {density = 1.0, friction = 0.3, bounce = 0.2, filter = {categoryBits = 4, maskBits = 8} }
-- Will contain all fruits available in the game
local avalFruit = {}
-- Slash line properties (line that shows up when you move finger across the screen)
local maxPoints = 5
local lineThickness = 20
local lineFadeTime = 250
local endPoints = {}
-- Whole Fruit physics properties
local minVelocityY = 850
local maxVelocityY = 1100
local minVelocityX = -200
local maxVelocityX = 200
local minAngularVelocity = 100
local maxAngularVelocity = 200
-- Chopped fruit physics properties
local minAngularVelocityChopped = 100
local maxAngularVelocityChopped = 200
-- Splash properties
local splashFadeTime = 2500
local splashFadeDelayTime = 5000
local splashInitAlpha = .5
local splashSlideDistance = 50 -- The amoutn of of distance the splash slides down the background
-- Contains all the available splash images
local splashImgs = {}
-- Gush properties
local minGushRadius = 10
local maxGushRadius = 25
local numOfGushParticles = 15
local gushFadeTime = 500
local gushFadeDelay = 500
local minGushVelocityX = -350
local maxGushVelocityX = 350
local minGushVelocityY = -350
local maxGushVelocityY = 350
-- Timer references
local bombTimer
local fruitTimer
-- Game properties
local fruitShootingInterval = 1000
local bombShootingInterval = 5000
-- Groups for holding the fruit and splash objects
local splashGroup
local fruitGroup
local sampleVar = true
local score = 0
local scoreText
function main()
score = 0
display.setStatusBar( display.HiddenStatusBar )
setUpBackground()
scoreText = display.newText("Score: 0", 415, 100, native.systemFont, 50)
scoreText:setTextColor(255, 255, 255)
scoreText.text = ("Score: " )..score
pauseAndResume ()
setUpCatchPlatform()
initGroups()
initFruitAndSplash()
Runtime:addEventListener("touch", drawSlashLine)
timer.performWithDelay( 1000, displayScore)
startGame()
end
function displayScore()
scoreText.text = ("Score: " )..score
score = score + 2
end
function startGame()
shootObject("fruit")
bombTimer = timer.performWithDelay(bombShootingInterval, function(event) shootObject("bomb") end, 0)
fruitTimer = timer.performWithDelay(fruitShootingInterval, function(event) shootObject("fruit") end, 0)
end
-- Display the pause button
function pauseAndResume ()
local pausebutton = display.newImage ("pause.png")
pausebutton : translate(100, 100)
pausebutton:addEventListener ("touch" , pauseGame)
local resumebutton = display.newImage ("resumed.png")
resumebutton: translate(100, 100)
resumebutton.isVisible = false
resumebutton:addEventListener ("touch", resumeGame)
end
function pauseGame (event)
if (event.phase == "ended") then
physics.pause ()
pausebutton.isVisible = false
resumebutton.isVisible = true
timer.pause(fruitTimer)
timer.pause(bombTimer)
sampleVar = false
return true
end
end
function resumeGame (event)
if (event.phase == "ended") then
physics.start()
pausebutton.isVisible = true
resumebutton.isVisible = false
timer.resume(fruitTimer)
timer.resume(bombTimer)
sampleVar = true
return true
end
end
function initGroups()
splashGroup = display.newGroup()
fruitGroup = display.newGroup()
end
function setUpBackground()
local background = display.newImage("bg.png", true)
background.x = display.contentWidth / 2
background.y = display.contentHeight / 2
end
-- Populates avalFruit with all the fruit images and thier widths and heights
function initFruitAndSplash()
local watermelon = {}
watermelon.whole = "watermelonWhole.png"
watermelon.top = "watermelonTop.png"
watermelon.bottom = "watermelonBottom.png"
watermelon.splash = "redSplash.png"
table.insert(avalFruit, watermelon)
local strawberry = {}
strawberry.whole = "strawberryWhole.png"
strawberry.top = "strawberryTop.png"
strawberry.bottom = "strawberryBottom.png"
strawberry.splash = "redSplash.png"
table.insert(avalFruit, strawberry)
-- Initialize splash images
table.insert(splashImgs, "splash1.png")
table.insert(splashImgs, "splash2.png")
table.insert(splashImgs, "splash3.png")
end
function getRandomFruit()
local fruitProp = avalFruit[math.random(1, #avalFruit)]
local fruit = display.newImage(fruitProp.whole)
fruit.whole = fruitProp.whole
fruit.top = fruitProp.top
fruit.bottom = fruitProp.bottom
fruit.splash = fruitProp.splash
return fruit
end
function getBomb()
local bomb = display.newImage( "bomb.png")
return bomb
end
function shootObject(type)
local object = type == "fruit" and getRandomFruit() or getBomb()
fruitGroup:insert(object)
object.x = display.contentWidth / 2
object.y = display.contentHeight + object.height * 2
fruitProp.radius = object.height / 2
physics.addBody(object, "dynamic", fruitProp)
if (type == "fruit") then
object:addEventListener("touch", function(event) chopFruit(object) end)
else
local bombTouchFunction
bombTouchFunction = function(event) explodeBomb(object, bombTouchFunction); end
object:addEventListener("touch", bombTouchFunction)
end
-- Apply linear velocity
local yVelocity = getRandomValue(minVelocityY, maxVelocityY) * -1 -- Need to multiply by -1 so the fruit shoots up
local xVelocity = getRandomValue(minVelocityX, maxVelocityX)
object:setLinearVelocity(xVelocity, yVelocity)
-- Apply angular velocity (the speed and direction the fruit rotates)
local minAngularVelocity = getRandomValue(minAngularVelocity, maxAngularVelocity)
local direction = (math.random() < .5) and -1 or 1
minAngularVelocity = minAngularVelocity * direction
object.angularVelocity = minAngularVelocity
end
function explodeBomb(bomb, listener)
bomb:removeEventListener("touch", listener)
-- The bomb should not move while exploding
bomb.bodyType = "kinematic"
bomb:setLinearVelocity(0, 0)
bomb.angularVelocity = 0
-- Shake the stage
local stage = display.getCurrentStage()
local moveRightFunction
local moveLeftFunction
local rightTrans
local leftTrans
local shakeTime = 50
local shakeRange = {min = 1, max = 25}
moveRightFunction = function(event) rightTrans = transition.to(stage, {x = math.random(shakeRange.min,shakeRange.max), y = math.random(shakeRange.min, shakeRange.max), time = shakeTime, onComplete=moveLeftFunction}); end
moveLeftFunction = function(event) leftTrans = transition.to(stage, {x = math.random(shakeRange.min,shakeRange.max) * -1, y = math.random(shakeRange.min,shakeRange.max) * -1, time = shakeTime, onComplete=moveRightFunction}); end
moveRightFunction()
local linesGroup = display.newGroup()
-- Generate a bunch of lines to simulate an explosion
local drawLine = function(event)
local line = display.newLine(bomb.x, bomb.y, display.contentWidth * 2, display.contentHeight * 2)
line.rotation = math.random(1,360)
line.strokeWidth = math.random(15, 25)
linesGroup:insert(line)
end
local lineTimer = timer.performWithDelay(100, drawLine, 0)
-- Function that is called after the pre explosion
local explode = function(event)
audio.play(explosion)
blankOutScreen(bomb, linesGroup);
timer.cancel(lineTimer)
stage.x = 0
stage.y = 0
transition.cancel(leftTrans)
transition.cancel(rightTrans)
end
-- Play the preExplosion sound first followed by the end explosion
audio.play(preExplosion, {onComplete = explode})
timer.cancel(fruitTimer)
timer.cancel(bombTimer)
end
function blankOutScreen(bomb, linesGroup)
local gameOver = displayGameOver()
gameOver.alpha = 0 -- Will reveal the game over screen after the explosion
-- Create an explosion animation
local circle = display.newCircle( bomb.x, bomb.y, 5 )
local circleGrowthTime = 300
local dissolveDuration = 1000
local dissolve = function(event) transition.to(circle, {alpha = 0, time = dissolveDuration, delay = 0, onComplete=function(event) gameOver.alpha = 1 end}); gameOver.alpha = 1 end
circle.alpha = 0
transition.to(circle, {time=circleGrowthTime, alpha = 1, strokeWidth = display.contentWidth * 3, height = display.contentWidth * 3, onComplete = dissolve})
end
function displayGameOver()
-- Will return a group so that we can set the alpha of the entier menu
local group = display.newGroup()
-- Dim the background with a transperent square
-- local back = display.newRect( 0,0, display.contentWidth, display.contentHeight )
--back:setFillColor(0,0,0, 255 * .1)
--group:insert(back)
local gameOver = display.newImage( "gameover.png")
gameOver.x = display.contentWidth / 2
gameOver.y = display.contentHeight / 2
group:insert(gameOver)
local replayButton = ui.newButton{
default = "replayButton.png",
over = "replayButton.png",
onRelease = function(event) group:removeSelf(); main() ; end
}
group:insert(replayButton)
replayButton.x = display.contentWidth / 2
replayButton.y = gameOver.y + gameOver.height / 2 + replayButton.height / 2
return group
end
-- Return a random value between 'min' and 'max'
function getRandomValue(min, max)
return min + math.abs(((max - min) * math.random()))
end
function playRandomSlashSound()
audio.play(slashSounds["slash" .. math.random(1, 3)])
end
function playRandomChoppedSound()
audio.play(choppedSound["chopped" .. math.random(1, 2)])
end
function getRandomSplash()
return display.newImage(splashImgs[math.random(1, #splashImgs)])
end
function chopFruit(fruit)
if (sampleVar == true) then
displayScore()
playRandomChoppedSound()
createFruitPiece(fruit, "top")
createFruitPiece(fruit, "bottom")
createSplash(fruit)
createGush(fruit)
fruit:removeSelf()
end
end
-- Creates a gushing effect that makes it look like juice is flying out of the fruit
function createGush(fruit)
local i
for i = 0, numOfGushParticles do
local gush = display.newCircle( fruit.x, fruit.y, math.random(minGushRadius, maxGushRadius) )
gush:setFillColor(255, 0, 0, 255)
gushProp.radius = gush.width / 2
physics.addBody(gush, "dynamic", gushProp)
local xVelocity = math.random(minGushVelocityX, maxGushVelocityX)
local yVelocity = math.random(minGushVelocityY, maxGushVelocityY)
gush:setLinearVelocity(xVelocity, yVelocity)
transition.to(gush, {time = gushFadeTime, delay = gushFadeDelay, strokeWidth = 0, height = 0, alpha = 0, onComplete = function(event) gush:removeSelf() end})
end
end
function createSplash(fruit)
local splash = getRandomSplash()
splash.x = fruit.x
splash.y = fruit.y
splash.rotation = math.random(-90,90)
splash.alpha = splashInitAlpha
splashGroup:insert(splash)
transition.to(splash, {time = splashFadeTime, alpha = 0, y = splash.y + splashSlideDistance, delay = splashFadeDelayTime, onComplete = function(event) splash:removeSelf() end})
end
-- Chops the fruit in half
-- Uses some trig to calculate the position
-- of the top and bottom part of the chopped fruit (http://en.wikipedia.org/wiki/Rotation_matrix#Rotations_in_two_dimensions)
function createFruitPiece(fruit, section)
local fruitVelX, fruitVelY = fruit:getLinearVelocity()
-- Calculate the position of the chopped piece
local half = display.newImage(fruit[section])
half.x = fruit.x - fruit.x -- Need to have the fruit's position relative to the origin in order to use the rotation matrix
local yOffSet = section == "top" and -half.height / 2 or half.height / 2
half.y = fruit.y + yOffSet - fruit.y
local newPoint = {}
newPoint.x = half.x * math.cos(fruit.rotation * (math.pi / 180)) - half.y * math.sin(fruit.rotation * (math.pi / 180))
newPoint.y = half.x * math.sin(fruit.rotation * (math.pi / 180)) + half.y * math.cos(fruit.rotation * (math.pi / 180))
half.x = newPoint.x + fruit.x -- Put the fruit back in its original position after applying the rotation matrix
half.y = newPoint.y + fruit.y
fruitGroup:insert(half)
-- Set the rotation
half.rotation = fruit.rotation
fruitProp.radius = half.width / 2 -- We won't use a custom shape since the chopped up fruit doesn't interact with the player
physics.addBody(half, "dynamic", fruitProp)
-- Set the linear velocity
local velocity = math.sqrt(math.pow(fruitVelX, 2) + math.pow(fruitVelY, 2))
local xDirection = section == "top" and -1 or 1
local velocityX = math.cos((fruit.rotation + 90) * (math.pi / 180)) * velocity * xDirection
local velocityY = math.sin((fruit.rotation + 90) * (math.pi / 180)) * velocity
half:setLinearVelocity(velocityX, velocityY)
-- Calculate its angular velocity
local minAngularVelocity = getRandomValue(minAngularVelocityChopped, maxAngularVelocityChopped)
local direction = (math.random() < .5) and -1 or 1
half.angularVelocity = minAngularVelocity * direction
end
-- Creates a platform at the bottom of the game "catch" the fruit and remove it
function setUpCatchPlatform()
local platform = display.newRect( 0, 0, display.contentWidth * 4, 50)
platform.x = (display.contentWidth / 2)
platform.y = display.contentHeight + display.contentHeight
physics.addBody(platform, "static", catchPlatformProp)
platform.collision = onCatchPlatformCollision
platform:addEventListener( "collision", platform )
end
function onCatchPlatformCollision(self, event)
-- Remove the fruit that collided with the platform
event.other:removeSelf()
end
-- Draws the slash line that appears when the user swipes his/her finger across the screen
function drawSlashLine(event)
-- Play a slash sound
if(endPoints ~= nil and endPoints[1] ~= nil) then
local distance = math.sqrt(math.pow(event.x - endPoints[1].x, 2) + math.pow(event.y - endPoints[1].y, 2))
if(distance > minDistanceForSlashSound and slashSoundEnabled == true) then
playRandomSlashSound();
slashSoundEnabled = false
timer.performWithDelay(minTimeBetweenSlashes, function(event) slashSoundEnabled = true end)
end
end
-- Insert a new point into the front of the array
table.insert(endPoints, 1, {x = event.x, y = event.y, line= nil})
-- Remove any excessed points
if(#endPoints > maxPoints) then
table.remove(endPoints)
end
for i,v in ipairs(endPoints) do
local line = display.newLine(v.x, v.y, event.x, event.y)
line.strokeWidth = lineThickness
transition.to(line, {time = lineFadeTime, alpha = 0, strokeWidth = 0, onComplete = function(event) line:removeSelf() end})
end
if(event.phase == "ended") then
while(#endPoints > 0) do
table.remove(endPoints)
end
end
end
main()

Receiving "Attempt to index global 'sprite' (a nil value)" in Lua

Im attempting to make a simple game app and keep running into this problem. I stopped programming in Lua for a few years so I don't exactly remember how to fix this. Anyway, my code is as follows:
EDIT: Here is the entire file. Still trying to figure out the formatting of Stack Overflow. Error occurs at line 76.
module(..., package.seeall)
-- Main function - MUST return a display.newGroup()
function new()
local localGroup = display.newGroup()
---------
local Rad = math.rad
local Sin = math.sin
local Cos = math.cos
local Pi = math.pi
local Atan2 = math.atan2
local radD = 180 / Pi
local DegR = Pi / 180
local touchPoint = display.newCircle(localGroup, -50, -50, 20)
touchPoint.isFocus = false
touchPoint.alpha = 0
function GetDistanceFromObjects(obj1, obj2)
local xDist = obj1.x - obj2.x
local yDist = obj1.y - obj2.y
local dist = Sqrt((xDist * xDist) + (yDist * yDist))
return dist
end
function getAngleDeg(inX1, inY1, inX2, inY2)
local xDist = inX2 - inX1
local yDist = inY2 - inY1
local angRad = Atan2(yDist, xDist)
return angRad * radD + 90
end
require "sprite"
function VectorFromAngle(inAngle, inVelocity)
local vx = Cos(Rad(inAngle-90))
local vy = Sin(Rad(inAngle-90))
if(inVelocity ~= nil)then
vx = vx * inVelocity
vy = vy * inVelocity
end
return vx,vy
end
require ( "physics" )
physics.start()
physics.setGravity( 1, 1 )
--( x, y )
--physics.setDrawMode ( "hybrid" )
math.randomseed(os.time())
local background = display.newImage("yazd.jpeg")
localGroup:insert(background)
--width of image divided by # of pics lined up from left to right (in the sprite) = the first #
--height of image divided by # of pics lined up from top to bottom (in the sprite) = the second #
local birdSheet = sprite.newSpriteSheet( "enemy.jpg", 59, 50 )
local birdSet = sprite.newSpriteSet(birdSheet, 1, 1)
-- images 1-14
sprite.add( birdSet, "bird", 1, 1, 200, 0 )
-- play 1-14, each image every 200 ms, 0 = loop count, which is infinite
local bird1 = sprite.newSprite( birdSet )
bird1.x = 40 -- starting point
bird1.y = 40 -- starting point
bird1.xScale = 0.5 --scale down x
bird1.yScale = 0.5 --scale down y
bird1:prepare("bird") --prepare sprite sequence
bird1:play() --play sprite
localGroup:insert(bird1)
--only local to this group
local killSheet = sprite.newSpriteSheet("explosion.png", 100, 100)
local killSet = sprite.newSpriteSet(killSheet, 1, 9)
sprite.add(killSet, "kill", 1, 9, 200, 1)
local birdCount = 1
local transDirection12
local function transDirection1()
bird1.xScale = 0.5
transition.to(bird1, {time=math.random(200,500), x = math.random(200,490), y = math.random(10,310), alpha = (math.random(9,100))/100, onComplete = transDirection12})
end
transDirection12 = function()
bird1.xScale = 0.5
transition.to(bird1, {time= math.random(200,500), x = math.random(200,490), y = math.random(10,310), alpha = (math.random(9,100))/100, onComplete = transDirection1})
end
transDirection1()
-- local transDirection1 declares what will be used (local function)
-- transDirection1 = function
-- following it are the function qualities
-- declares it will use object/image called bird1 and scales it to .5
-- time = ____ means it will take a certain time, between ____ and ____ to complete the transition
-- x=____ means that is where it will move to on the x axis
-- y=____ means that is where it will move to on the y axis
-- alpha = ___ means the is how transparent it will be
-- onComplete = ________ means that when the action is complete, it will call another function
-- The next function has the same qualities as transDirection1, but the onComplete part calls transDirection1 and they continue to loop
-- transDirection1() declares transDirection1 so the app knows about it and can use it
-- the other trans do not need to be declared because they are part of transDirection1, which is already declared
--(x, y, size.x, size.y)
local player = display.newImage( "mk11.png" )
player.x = 240
player.y = 260
player.xScale = .5
player.yScale = .5
localGroup:insert( player )
-- add physics to all the objects wanted: (object wanted, "static" or "dynamic")
physics.addBody(player, "static", {radius=30, isSensor = true})
physics.addBody(bird1, "static", {radius=23})
local function shoot(inPointX, inPointY)
-- (start at the x of the player + 10, also start at the y of the player, the radius of the circle is 5)
local bullet = display.newImage( "bullet2.png" )
bullet.x = player.x
bullet.y = player.y
-- add physics to the object, which is the bullet.
-- Make the bullet "dynamic" or moving
physics.addBody(bullet, "dynamic")
bullet.isFixedRotation = true
localGroup:insert( bullet )
local velocity = 300
local vx, vy = VectorFromAngle(player.rotation, velocity)
bullet.rotation = player.rotation
bullet:setLinearVelocity(vx, vy)
end
function RotateToTouchPoint(inPointX, inPointY)
local ang = getAngleDeg(player.x, player.y, inPointX, inPointY)
player.rotation = ang
end
local function ScreenTouchListener(event)
local phase = event.phase
if(phase == "began")then
if(touchPoint.isFocus == false)then
touchPoint.alpha = 1
touchPoint.x = event.x
touchPoint.y = event.y
display.getCurrentStage():setFocus(touchPoint, event.id)
touchPoint.isFocus = true
RotateToTouchPoint(event.x, event.y)
shoot(event.x, event.y)
end
elseif(touchPoint.isFocus)then
if(phase == "moved")then
touchPoint.x = event.x
touchPoint.y = event.y
RotateToTouchPoint(event.x, event.y)
elseif(phase == "ended" or phase == "cancelled")then
display.getCurrentStage():setFocus(touchPoint, nil)
touchPoint.isFocus = false
touchPoint.alpha = 0
end
end
return true
end
local function gotShot (event)
event.target:removeSelf()
event.other:removeSelf()
local explosion = sprite.newSprite(killSet)
explosion.x, explosion.y = event.target.x, event.target.y
explosion:prepare("kill")
explosion:play()
localGroup:insert( explosion )
birdCount = birdCount - 1
-- when there are no more birds, remove the runtime event listener and perform the
-- function with a delay of 500 m.s. The function changes the scene to test.lua
if "ended" then
if birdCount == 0 then
Runtime:removeEventListener("touch", ScreenTouchListener)
timer.performWithDelay(500, function()
director:changeScene("mainPage") end, 1)
end
end
end
bird1:addEventListener("collision", gotShot)
Runtime:addEventListener("touch", ScreenTouchListener)
---------
-- MUST return a display.newGroup()
return localGroup
end
Any help is appreciated!
The error message is perfectly clear -- the variable sprite used at this line:
local bird1 = sprite.birdSheet( birdSet )
has a nil value, meaning it has not been initialized or was set to nil. You need to show the earlier code where you should have set it up.
(After OP updates)
I think this line
require "sprite"
should actually be
sprite = require "sprite"
You can read more in modules tutorial here:
http://lua-users.org/wiki/ModulesTutorial

How to utilize combo scoring in Corona?

i just have a quick question. Im playing around with Corona to try and get the look and feel of it and im currently editing some one else's sample code. I have added a scoring mechanism, and now i want to add a combo scoring mechanism so that when the user chops more than one fruit, i can add an extra 5 points. Its just that i have no idea how to start. If some one would point me in the right direction that would be great thank you. :)
Or if this would be much clearer: How about a function that will help me detect how many objects the user touches/slices in one touch/move?
require ("physics")
local ui = require("ui")
physics.start()
-- physics.setDrawMode ( "hybrid" ) -- Uncomment in order to show in hybrid mode
physics.setGravity( 0, 9.8 * 2)
physics.start()
-- Audio for slash sound (sound you hear when user swipes his/her finger across the screen)
local slashSounds = {slash1 = audio.loadSound("slash1.wav"), slash2 = audio.loadSound("slash2.wav"), slash3 = audio.loadSound("slash3.wav")}
local slashSoundEnabled = true -- sound should be enabled by default on startup
local minTimeBetweenSlashes = 150 -- Minimum amount of time in between each slash sound
local minDistanceForSlashSound = 50 -- Amount of pixels the users finger needs to travel in one frame in order to play a slash sound
-- Audio for chopped fruit
local choppedSound = {chopped1 = audio.loadSound("chopped1.wav"), chopped2 = audio.loadSound("chopped2.wav")}
-- Audio for bomb
local preExplosion = audio.loadSound("preExplosion.wav")
local explosion = audio.loadSound("explosion.wav")
-- Adding a collision filter so the fruits do not collide with each other, they only collide with the catch platform
local fruitProp = {density = 1.0, friction = 0.3, bounce = 0.2, filter = {categoryBits = 2, maskBits = 1}}
local catchPlatformProp = {density = 1.0, friction = 0.3, bounce = 0.2, filter = {categoryBits = 1, maskBits = 2}}
-- Gush filter should not interact with other fruit or the catch platform
local gushProp = {density = 1.0, friction = 0.3, bounce = 0.2, filter = {categoryBits = 4, maskBits = 8} }
-- Will contain all fruits available in the game
local avalFruit = {}
-- Slash line properties (line that shows up when you move finger across the screen)
local maxPoints = 5
local lineThickness = 20
local lineFadeTime = 250
local endPoints = {}
-- Whole Fruit physics properties
local minVelocityY = 850
local maxVelocityY = 1100
local minVelocityX = -200
local maxVelocityX = 200
local minAngularVelocity = 100
local maxAngularVelocity = 200
-- Chopped fruit physics properties
local minAngularVelocityChopped = 100
local maxAngularVelocityChopped = 200
-- Splash properties
local splashFadeTime = 2500
local splashFadeDelayTime = 5000
local splashInitAlpha = .5
local splashSlideDistance = 50 -- The amoutn of of distance the splash slides down the background
-- Contains all the available splash images
local splashImgs = {}
-- Gush properties
local minGushRadius = 10
local maxGushRadius = 25
local numOfGushParticles = 15
local gushFadeTime = 500
local gushFadeDelay = 500
local minGushVelocityX = -350
local maxGushVelocityX = 350
local minGushVelocityY = -350
local maxGushVelocityY = 350
-- Timer references
local bombTimer
local fruitTimer
-- Game properties
local fruitShootingInterval = 1000
local bombShootingInterval = 5000
-- Groups for holding the fruit and splash objects
local splashGroup
local fruitGroup
local sampleVar = true
local score = 0
local scoreText
function main()
score = 0
display.setStatusBar( display.HiddenStatusBar )
setUpBackground()
scoreText = display.newText("Score: 0", 415, 100, native.systemFont, 50)
scoreText:setTextColor(255, 255, 255)
scoreText.text = ("Score: " )..score
pauseAndResume ()
setUpCatchPlatform()
initGroups()
initFruitAndSplash()
Runtime:addEventListener("touch", drawSlashLine)
timer.performWithDelay( 1000, displayScore)
startGame()
end
function displayScore()
scoreText.text = ("Score: " )..score
score = score + 2
end
function startGame()
shootObject("fruit")
bombTimer = timer.performWithDelay(bombShootingInterval, function(event) shootObject("bomb") end, 0)
fruitTimer = timer.performWithDelay(fruitShootingInterval, function(event) shootObject("fruit") end, 0)
end
-- Display the pause button
function pauseAndResume ()
pausebutton = display.newImage ("paused2.png", 10, 100)
pausebutton:addEventListener ("touch" , pauseGame)
resumebutton = display.newImage ("resume.png", 10, 100)
resumebutton.isVisible = false
resumebutton:addEventListener ("touch", resumeGame)
end
function pauseGame (event)
if (event.phase == "ended") then
physics.pause ()
pausebutton.isVisible = false
resumebutton.isVisible = true
timer.pause(fruitTimer)
timer.pause(bombTimer)
sampleVar = false
return true
end
end
function resumeGame (event)
if (event.phase == "ended") then
physics.start()
pausebutton.isVisible = true
resumebutton.isVisible = false
timer.resume(fruitTimer)
timer.resume(bombTimer)
sampleVar = true
return true
end
end
function initGroups()
splashGroup = display.newGroup()
fruitGroup = display.newGroup()
end
function setUpBackground()
local background = display.newImage("bg.png", true)
background.x = display.contentWidth / 2
background.y = display.contentHeight / 2
end
-- Populates avalFruit with all the fruit images and thier widths and heights
function initFruitAndSplash()
local watermelon = {}
watermelon.whole = "watermelonWhole.png"
watermelon.top = "watermelonTop.png"
watermelon.bottom = "watermelonBottom.png"
watermelon.splash = "redSplash.png"
table.insert(avalFruit, watermelon)
local strawberry = {}
strawberry.whole = "strawberryWhole.png"
strawberry.top = "strawberryTop.png"
strawberry.bottom = "strawberryBottom.png"
strawberry.splash = "redSplash.png"
table.insert(avalFruit, strawberry)
-- Initialize splash images
table.insert(splashImgs, "splash1.png")
table.insert(splashImgs, "splash2.png")
table.insert(splashImgs, "splash3.png")
end
function getRandomFruit()
local fruitProp = avalFruit[math.random(1, #avalFruit)]
local fruit = display.newImage(fruitProp.whole)
fruit.whole = fruitProp.whole
fruit.top = fruitProp.top
fruit.bottom = fruitProp.bottom
fruit.splash = fruitProp.splash
return fruit
end
function getBomb()
local bomb = display.newImage( "bomb.png")
return bomb
end
function shootObject(type)
local object = type == "fruit" and getRandomFruit() or getBomb()
fruitGroup:insert(object)
object.x = display.contentWidth / 2
object.y = display.contentHeight + object.height * 2
fruitProp.radius = object.height / 2
physics.addBody(object, "dynamic", fruitProp)
if(type == "fruit") then
object:addEventListener("touch", function(event) chopFruit(object) end)
else
local bombTouchFunction
bombTouchFunction = function(event) explodeBomb(object, bombTouchFunction); end
object:addEventListener("touch", bombTouchFunction)
end
-- Apply linear velocity
local yVelocity = getRandomValue(minVelocityY, maxVelocityY) * -1 -- Need to multiply by -1 so the fruit shoots up
local xVelocity = getRandomValue(minVelocityX, maxVelocityX)
object:setLinearVelocity(xVelocity, yVelocity)
-- Apply angular velocity (the speed and direction the fruit rotates)
local minAngularVelocity = getRandomValue(minAngularVelocity, maxAngularVelocity)
local direction = (math.random() < .5) and -1 or 1
minAngularVelocity = minAngularVelocity * direction
object.angularVelocity = minAngularVelocity
end
function explodeBomb(bomb, listener)
bomb:removeEventListener("touch", listener)
-- The bomb should not move while exploding
bomb.bodyType = "kinematic"
bomb:setLinearVelocity(0, 0)
bomb.angularVelocity = 0
-- Shake the stage
local stage = display.getCurrentStage()
local moveRightFunction
local moveLeftFunction
local rightTrans
local leftTrans
local shakeTime = 50
local shakeRange = {min = 1, max = 25}
moveRightFunction = function(event) rightTrans = transition.to(stage, {x = math.random(shakeRange.min,shakeRange.max), y = math.random(shakeRange.min, shakeRange.max), time = shakeTime, onComplete=moveLeftFunction}); end
moveLeftFunction = function(event) leftTrans = transition.to(stage, {x = math.random(shakeRange.min,shakeRange.max) * -1, y = math.random(shakeRange.min,shakeRange.max) * -1, time = shakeTime, onComplete=moveRightFunction}); end
moveRightFunction()
local linesGroup = display.newGroup()
-- Generate a bunch of lines to simulate an explosion
local drawLine = function(event)
local line = display.newLine(bomb.x, bomb.y, display.contentWidth * 2, display.contentHeight * 2)
line.rotation = math.random(1,360)
line.width = math.random(15, 25)
linesGroup:insert(line)
end
local lineTimer = timer.performWithDelay(100, drawLine, 0)
-- Function that is called after the pre explosion
local explode = function(event)
audio.play(explosion)
blankOutScreen(bomb, linesGroup);
timer.cancel(lineTimer)
stage.x = 0
stage.y = 0
transition.cancel(leftTrans)
transition.cancel(rightTrans)
end
-- Play the preExplosion sound first followed by the end explosion
audio.play(preExplosion, {onComplete = explode})
timer.cancel(fruitTimer)
timer.cancel(bombTimer)
end
function blankOutScreen(bomb, linesGroup)
local gameOver = displayGameOver()
gameOver.alpha = 0 -- Will reveal the game over screen after the explosion
-- Create an explosion animation
local circle = display.newCircle( bomb.x, bomb.y, 5 )
local circleGrowthTime = 300
local dissolveDuration = 1000
local dissolve = function(event) transition.to(circle, {alpha = 0, time = dissolveDuration, delay = 0, onComplete=function(event) gameOver.alpha = 1 end}); gameOver.alpha = 1 end
circle.alpha = 0
transition.to(circle, {time=circleGrowthTime, alpha = 1, width = display.contentWidth * 3, height = display.contentWidth * 3, onComplete = dissolve})
end
function displayGameOver()
-- Will return a group so that we can set the alpha of the entier menu
local group = display.newGroup()
-- Dim the background with a transperent square
local back = display.newRect( 0,0, display.contentWidth, display.contentHeight )
back:setFillColor(0,0,0, 255 * .1)
group:insert(back)
local gameOver = display.newImage( "gameover.png")
gameOver.x = display.contentWidth / 2
gameOver.y = display.contentHeight / 2
group:insert(gameOver)
local replayButton = ui.newButton{
default = "replayButton.png",
over = "replayButton.png",
onRelease = function(event) group:removeSelf(); main() ; end
}
group:insert(replayButton)
replayButton.x = display.contentWidth / 2
replayButton.y = gameOver.y + gameOver.height / 2 + replayButton.height / 2
return group
end
-- Return a random value between 'min' and 'max'
function getRandomValue(min, max)
return min + math.abs(((max - min) * math.random()))
end
function playRandomSlashSound()
audio.play(slashSounds["slash" .. math.random(1, 3)])
end
function playRandomChoppedSound()
audio.play(choppedSound["chopped" .. math.random(1, 2)])
end
function getRandomSplash()
return display.newImage(splashImgs[math.random(1, #splashImgs)])
end
function chopFruit(fruit)
if (sampleVar == true) then
displayScore()
playRandomChoppedSound()
createFruitPiece(fruit, "top")
createFruitPiece(fruit, "bottom")
createSplash(fruit)
createGush(fruit)
fruit:removeSelf()
end
end
-- Creates a gushing effect that makes it look like juice is flying out of the fruit
function createGush(fruit)
local i
for i = 0, numOfGushParticles do
local gush = display.newCircle( fruit.x, fruit.y, math.random(minGushRadius, maxGushRadius) )
gush:setFillColor(255, 0, 0, 255)
gushProp.radius = gush.width / 2
physics.addBody(gush, "dynamic", gushProp)
local xVelocity = math.random(minGushVelocityX, maxGushVelocityX)
local yVelocity = math.random(minGushVelocityY, maxGushVelocityY)
gush:setLinearVelocity(xVelocity, yVelocity)
transition.to(gush, {time = gushFadeTime, delay = gushFadeDelay, width = 0, height = 0, alpha = 0, onComplete = function(event) gush:removeSelf() end})
end
end
function createSplash(fruit)
local splash = getRandomSplash()
splash.x = fruit.x
splash.y = fruit.y
splash.rotation = math.random(-90,90)
splash.alpha = splashInitAlpha
splashGroup:insert(splash)
transition.to(splash, {time = splashFadeTime, alpha = 0, y = splash.y + splashSlideDistance, delay = splashFadeDelayTime, onComplete = function(event) splash:removeSelf() end})
end
-- Chops the fruit in half
-- Uses some trig to calculate the position
-- of the top and bottom part of the chopped fruit (http://en.wikipedia.org/wiki/Rotation_matrix#Rotations_in_two_dimensions)
function createFruitPiece(fruit, section)
local fruitVelX, fruitVelY = fruit:getLinearVelocity()
-- Calculate the position of the chopped piece
local half = display.newImage(fruit[section])
half.x = fruit.x - fruit.x -- Need to have the fruit's position relative to the origin in order to use the rotation matrix
local yOffSet = section == "top" and -half.height / 2 or half.height / 2
half.y = fruit.y + yOffSet - fruit.y
local newPoint = {}
newPoint.x = half.x * math.cos(fruit.rotation * (math.pi / 180)) - half.y * math.sin(fruit.rotation * (math.pi / 180))
newPoint.y = half.x * math.sin(fruit.rotation * (math.pi / 180)) + half.y * math.cos(fruit.rotation * (math.pi / 180))
half.x = newPoint.x + fruit.x -- Put the fruit back in its original position after applying the rotation matrix
half.y = newPoint.y + fruit.y
fruitGroup:insert(half)
-- Set the rotation
half.rotation = fruit.rotation
fruitProp.radius = half.width / 2 -- We won't use a custom shape since the chopped up fruit doesn't interact with the player
physics.addBody(half, "dynamic", fruitProp)
-- Set the linear velocity
local velocity = math.sqrt(math.pow(fruitVelX, 2) + math.pow(fruitVelY, 2))
local xDirection = section == "top" and -1 or 1
local velocityX = math.cos((fruit.rotation + 90) * (math.pi / 180)) * velocity * xDirection
local velocityY = math.sin((fruit.rotation + 90) * (math.pi / 180)) * velocity
half:setLinearVelocity(velocityX, velocityY)
-- Calculate its angular velocity
local minAngularVelocity = getRandomValue(minAngularVelocityChopped, maxAngularVelocityChopped)
local direction = (math.random() < .5) and -1 or 1
half.angularVelocity = minAngularVelocity * direction
end
-- Creates a platform at the bottom of the game "catch" the fruit and remove it
function setUpCatchPlatform()
local platform = display.newRect( 0, 0, display.contentWidth * 4, 50)
platform.x = (display.contentWidth / 2)
platform.y = display.contentHeight + display.contentHeight
physics.addBody(platform, "static", catchPlatformProp)
platform.collision = onCatchPlatformCollision
platform:addEventListener( "collision", platform )
end
function onCatchPlatformCollision(self, event)
-- Remove the fruit that collided with the platform
event.other:removeSelf()
end
-- Draws the slash line that appears when the user swipes his/her finger across the screen
function drawSlashLine(event)
-- Play a slash sound
if(endPoints ~= nil and endPoints[1] ~= nil) then
local distance = math.sqrt(math.pow(event.x - endPoints[1].x, 2) + math.pow(event.y - endPoints[1].y, 2))
if(distance > minDistanceForSlashSound and slashSoundEnabled == true) then
playRandomSlashSound();
slashSoundEnabled = false
timer.performWithDelay(minTimeBetweenSlashes, function(event) slashSoundEnabled = true end)
end
end
-- Insert a new point into the front of the array
table.insert(endPoints, 1, {x = event.x, y = event.y, line= nil})
-- Remove any excessed points
if(#endPoints > maxPoints) then
table.remove(endPoints)
end
for i,v in ipairs(endPoints) do
local line = display.newLine(v.x, v.y, event.x, event.y)
line.width = lineThickness
transition.to(line, {time = lineFadeTime, alpha = 0, width = 0, onComplete = function(event) line:removeSelf() end})
end
if(event.phase == "ended") then
while(#endPoints > 0) do
table.remove(endPoints)
end
end
end
main()
Try Runtime touch listener ...in that listener event.phase == "move" you can do like above.In event.phase=="ended" reset the value.
Initial set some temp value.
Tempvalue=0
function displayScore()
if Tempvalue == 0 then
Tempvalue=Tempvalue+1
score = score + 2
scoreText.text = ("Score: " )..score
else
score = score + 5
scoreText.text = ("Score: " )..score
end
I just put the sample how to do.
temp=0
local newLine = function(event)
if event.phase=="began" then
elseif event.phase=="moved" then
for i=1,3 do
if event.target.name==i then
temp=temp+1
--here you can do your action to the object(like remove or score)
print("touch"..temp)
end
end
elseif event.phase=="ended" then
end
return true
end
for i=1,3 do
local myCircle = display.newCircle( 100*i, 100, 9 )
myCircle:setFillColor(128,128,128)
myCircle.name=i
myCircle:addEventListener("touch",newLine)
end

Corona SDK: Remove display object from table

I have been working on a tower defense game. So basically I have a loop that makes a table of display objects that are tanks and adds physics bodies to them. Then it "gives the tanks" to a function called moveTank to actually move them.
However to conserve memory I want to remove the physics body and display obejct itself once it is offscreen. The code for that stars at line 234. In the simulator, if you test just removing the physics body everything works fine. However, if I remove the display object (maybe I'm doing it wrong?) it removes the image, but some other functions that use it give an error saying that I'm trying to compare a number with a nil value# line 229. The nil value is the object is removed and I set its property isMoving and isAlive to false so why is it even trying to perform the operation??
Can anyone help me finish this part of trying to remove the display object with no errors?
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
local physics = require "physics"
physics.start()
physics.setGravity( 0, 0)
physics.setDrawMode("hybrid")
local screenW, screenH, halfW, halfH = display.contentWidth, display.contentHeight, display.contentWidth*0.5, display.contentHeight*0.5
local tanks = {}
local tickCnt = 0
local TOTAL_TANKS = 2
local tankCnt = 1
function AddCommas( number, maxPos )
local s = tostring( number )
local len = string.len( s )
if len > maxPos then
-- Add comma to the string
local s2 = string.sub( s, -maxPos )
local s1 = string.sub( s, 1, len - maxPos )
s = (s1 .. "," .. s2)
end
maxPos = maxPos - 3 -- next comma position
if maxPos > 0 then
return AddCommas( s, maxPos )
else
return s
end
end
function tickCntFunct()
if tickCnt <= 2000 then
tickCnt = tickCnt + 25
print("tick count", tickCnt)
else
tickCnt = 0
end
end
timer.performWithDelay(10, tickCntFunct, 0)
function moveTank(aTank)
local mSpeed = 150
rSpeed = 6
if aTank.isAlive == true and aTank.isKilled == false then
print("aTank.x = ", aTank.x)
print("aTank.y = ", aTank.y)
print("tank rotation = ", aTank.rotation)
local disP1 = math.sqrt((math.abs(aTank.x - pointer1.x))^2 + (math.abs(aTank.y - pointer1.y))^2)
local disP2 = math.sqrt((math.abs(aTank.x - pointer2.x))^2 + (math.abs(aTank.y - pointer2.y))^2)
local disP3 = math.sqrt((math.abs(aTank.x - pointer3.x))^2 + (math.abs(aTank.y - pointer3.y))^2)
local disP4 = math.sqrt((math.abs(aTank.x - pointer4.x))^2 + (math.abs(aTank.y - pointer4.y))^2)
removeTanknumber = 0
if aTank.x < 0 then
aTank.rotation = 90
aTank:setLinearVelocity( mSpeed, 0)
end
if aTank.rotation < 180 and disP1 < 1 then
aTank:setLinearVelocity( 0, 0)
aTank.rotation = aTank.rotation + rSpeed
end
if aTank.rotation >= 180 and disP1 < 1 then
aTank.rotation = 180
aTank:setLinearVelocity( 0, mSpeed)
end
if aTank.rotation > 90 and disP2 < 1 then
aTank:setLinearVelocity( 0, 0)
aTank.rotation = aTank.rotation - rSpeed
end
if aTank.rotation <= 90 and disP2 < 1 then
aTank.rotation = 90
aTank:setLinearVelocity( mSpeed, 0)
end
if aTank.rotation > 0 and disP3 < 1 then
aTank:setLinearVelocity( 0, 0)
aTank.rotation = aTank.rotation - rSpeed
end
if aTank.rotation <= 0 and disP3 < 1 then
aTank.rotation = 0
aTank:setLinearVelocity( 0, -1*mSpeed)
end
if aTank.rotation < 90 and disP4 < 1 then
aTank:setLinearVelocity( 0, 0)
aTank.rotation = aTank.rotation + rSpeed
end
if aTank.rotation >= 90 and disP4 < 1 then
aTank.rotation = 90
aTank:setLinearVelocity( mSpeed, 0)
end
end
end
timer.performWithDelay(1, moveTank, 0)
function scene:createScene( event )
local group = self.view
pointersGroup = display.newGroup()
mapGroup = display.newGroup()
-- create a grey rectangle as the backdrop
map = display.newImage( "map1.png" )
map:setReferencePoint(display.TopLeftReferencePoint)
map.x = 0
map.y = 0
spawner = display.newImage("pointer.png")
spawner:setReferencePoint(display.CenterReferencePoint)
spawner.y = 210
spawner.x = -40
pointer1 = display.newImage("pointer.png")
pointer1:setReferencePoint(display.CenterReferencePoint)
pointer1.x = 210
pointer1.y = 210
pointer2 = display.newImage("pointer.png")
pointer2:setReferencePoint(display.CenterReferencePoint)
pointer2.x = 210
pointer2.y = 390
pointer3 = display.newImage("pointer.png")
pointer3:setReferencePoint(display.CenterReferencePoint)
pointer3.x = 510
pointer3.y = 390
pointer4 = display.newImage("pointer.png")
pointer4:setReferencePoint(display.CenterReferencePoint)
pointer4.x = 510
pointer4.y = 90
sideBlock = display.newImage("side_block.png")
physics.addBody( sideBlock, "static", { friction=0.5, bounce=0.3 } )
sideBlock:setReferencePoint(display.CenterReferencePoint)
sideBlock.x = screenW - 100
sideBlock.y = screenH/2
-- all display objects must be inserted into group
pointersGroup:insert( spawner )
pointersGroup:insert( pointer1 )
pointersGroup:insert( pointer2 )
pointersGroup:insert( pointer3 )
pointersGroup:insert( pointer4 )
pointersGroup:insert( sideBlock )
mapGroup:insert( map )
group:insert( pointersGroup )
group:insert( mapGroup )
end
function scene:enterScene( event )
local group = self.view
for i = 1, TOTAL_TANKS do
-- create 5 tanks, place them off screen, set their status to isAlive and not isMoving
table.insert(tanks, display.newImage("tank.png"))
print("memory (all spawned): ", AddCommas( system.getInfo("textureMemoryUsed"), 9 ) .. " bytes" )
tanks[i]:setReferencePoint(display.CenterReferencePoint)
tanks[i]:scale(0.75, 0.75)
tanks[i].x = spawner.x
tanks[i].y = spawner.y
tanks[i].isAlive = true
tanks[i].isMoving = false
tanks[i].isKilled = false
end
local function gameLoop(event)
-- normally should not have loops inside the game loop, because
-- if there is too much going on during each frame call it can cause issues
-- but for moving only 5 tanks, this is how you can do it.
-- each tank will call the same function above (moveTank)
-- have a variable that you would check here, to see if 'so many ticks or seconds'
-- has passed, and if so, set the isMoving to true for the next tank .. will just use
-- a simple incremented variable 'tickCnt'
if tickCnt > 2000 and tankCnt <= TOTAL_TANKS then
physics.addBody( tanks[tankCnt], { density=3.0, friction=0.5, bounce=0.3 } )
tanks[tankCnt].isMoving = true
print("tankCnt= ", tankCnt)
tankCnt = tankCnt + 1
print("memory (moving): ", AddCommas( system.getInfo("textureMemoryUsed"), 9 ) .. " bytes" )
end
for i=1, TOTAL_TANKS do
if tanks[i].isMoving == true and tanks[i].isAlive == true and tanks[i].isKilled == false then
moveTank(tanks[i])
end
end
for i = 1, TOTAL_TANKS do
if tanks[i].x >= 40 and tanks[i].isKilled == false then
tanks[i].isKilled = true
tanks[i].isMoving = false
tanks[i].isAlive = false
physics.removeBody( tanks[i] )
display.remove(tanks[i])
tanks[i] = nil
end
end
end
Runtime:addEventListener("enterFrame", gameLoop)
physics.start()
end
function scene:exitScene( event )
local group = self.view
physics.stop()
end
function scene:destroyScene( event )
local group = self.view
package.loaded[physics] = nil
physics = nil
end
--------------------------------------------------------------------------------------- --
-- END OF YOUR IMPLEMENTATION
-----------------------------------------------------------------------------------------
-- "createScene" event is dispatched if scene's view does not exist
scene:addEventListener( "createScene", scene )
-- "enterScene" event is dispatched whenever scene transition has finished
scene:addEventListener( "enterScene", scene )
-- "exitScene" event is dispatched whenever before next scene's transition begins
scene:addEventListener( "exitScene", scene )
-- "destroyScene" event is dispatched before view is unloaded, which can be
-- automatically unloaded in low memory situations, or explicitly via a call to
-- storyboard.purgeScene() or storyboard.removeScene().
scene:addEventListener( "destroyScene", scene )
-----------------------------------------------------------------------------------------
return scene
Try to loop from last tank to first.

Resources