How to stop a character if the character in front of him is still - coronasdk

I don't know why my code doesn't work. I just want to stop the next character if the character in front of him is still. My thought was to setLinearVelocity(0,0) when their linear velocity is 0 so the next character know that he has to stop when the linear velocity of the character in front of him is 0.
local function loopPg()
local runningPG = display.newSprite(pg[math.random(5)], sequences_runningPG)
runningPG.x = display.contentCenterX
runningPG.y = display.contentCenterY-730
runningPG:scale(0.75, 0.75)
runningPG:play()
physics.addBody(runningPG, "dynamic", {radius = 55})
local function pathPg()
if(runningPG.y >= -190 and runningPG.y < 160) then
runningPG:setLinearVelocity(0,250)
elseif (runningPG.y >= 160 and runningPG.x >= 220) then
runningPG:setLinearVelocity(-250,0)
elseif (runningPG.x <= 220 and runningPG.y <= 635) then
runningPG:setLinearVelocity(0,250)
elseif ( runningPG.y >= 635) then
runningPG:setLinearVelocity(0,0)
end
end
local vx,vy = runningPG:getLinearVelocity()
if(vx == 0 and vy == 0) then
runningPG:setLinearVelocity(0,0)
end
Runtime:addEventListener( "enterFrame", pathPg )
end
timer.performWithDelay(600, loopPg, 3)

Here is something that could help you:
characters velocity function has to be involved in the enterFrame
then you have to take the character's velocity from the character in front
This is not a solution, but it could help you
local function pathPg()
local vx,vy = 0,0 -- this has to be the velocity of the character in front
if(runningPG.y >= -190 and runningPG.y < 160) then
vx,vy = 0,250
runningPG:setLinearVelocity(vx,vy)
elseif (runningPG.y >= 160 and runningPG.x >= 220) then
vx,vy = -250, 0
runningPG:setLinearVelocity(vx,vy)
elseif (runningPG.x <= 220 and runningPG.y <= 635) then
vx,vy = 0,250
runningPG:setLinearVelocity(vx,vy)
elseif ( runningPG.y >= 635) then
vx,vy = 0,0
runningPG:setLinearVelocity(vx,vy)
end
end
Runtime:addEventListener( "enterFrame", pathPg )
end

Related

How to stop an object from moving past a point

I was wondering if there was a way to stop an object from moving off the screen. In my code, I have a controllable character (player) and I want to prevent it from moving to the left when it's x coordinate is < 1
I have tried to do this in the code below, however, the player will not be stopped if you hold down the left arrow key.
Is there a way to fix this? If I had a guess, I would somehow need my program to continuously check for the case where player.x < 1
motionx = 0; -- Variable used to move character along x axis
speed = 10; -- Set Walking Speed
local function moveplayer (event)
player.x = player.x + motionx;
end
Runtime:addEventListener("enterFrame", moveplayer)
local function onKeyEvent( event )
if ( event.phase == "down" ) then
if ( event.keyName == "left" ) and player.x > 1 then
motionx = -speed
return true
elseif ( event.keyName == "right" ) then
motionx = speed
return true
end
end
end
Runtime:addEventListener( "key", onKeyEvent )
You need to check the boundaries and set the motionx to zero:
local player = display.newCircle(display.contentCenterX, display.contentCenterY, 10)
local motionx = 0; -- Variable used to move character along x axis
local speed = 10; -- Set Walking Speed
local function moveplayer( event )
player.x = player.x + motionx;
if player.x < 0 then
player.x = 0
motionx = 0
elseif player.x > display.contentWidth then
player.x = display.contentWidth
motionx = 0
end
end
Runtime:addEventListener( "enterFrame", moveplayer )
local function onKeyEvent( event )
if event.phase == "down" then
if event.keyName == "left" then
motionx = -speed
return true
elseif event.keyName == "right" then
motionx = speed
return true
end
end
end
Runtime:addEventListener( "key", onKeyEvent )
Simply implement a function that checks your objects position vs your screen boundaries. Whenever it reaches the border of your screen you stop it.
To check your objects position for every frame add your function as an event listener for the event "enterFrame".
Read this for details:
https://docs.coronalabs.com/guide/events/detectEvents/index.html
Of course you can also use the collision engine by placing invisible walls around your screen so your object will bounce back whenever it hits the border.
You were fairly close but may need your whole code to test it. I only changed this player.x < 1 and moved )
motionx = 0; -- Variable used to move character along x axis
speed = 10; -- Set Walking Speed
local function moveplayer (event)
player.x = player.x + motionx;
end
Runtime:addEventListener("enterFrame", moveplayer)
local function onKeyEvent( event )
if ( event.phase == "down" ) then
if ( event.keyName == "left" and player.x < 1) then
motionx = -speed
return true
elseif ( event.keyName == "right" ) then
motionx = speed
return true
end
end
end
Runtime:addEventListener( "key", onKeyEvent )

corona sdk pinch to zoom

i am using the function contained in corona sample codes for the pinch to zoom. But since i am developing an app, i need to make every single place of interest zoommable. Do i have to copy and paste the horribly long function for every single image or can i redirect every image on just one function? I am new to lua, here is the pinch to zoom function included in the sample code:
function background:touch( event )
local result = true
local phase = event.phase
local previousTouches = self.previousTouches
local numTotalTouches = 1
if ( previousTouches ) then
-- add in total from previousTouches, subtract one if event is already in the array
numTotalTouches = numTotalTouches + self.numPreviousTouches
if previousTouches[event.id] then
numTotalTouches = numTotalTouches - 1
end
end
if "began" == phase then
-- Very first "began" event
if ( not self.isFocus ) then
-- Subsequent touch events will target button even if they are outside the contentBounds of button
display.getCurrentStage():setFocus( self )
self.isFocus = true
previousTouches = {}
self.previousTouches = previousTouches
self.numPreviousTouches = 0
elseif ( not self.distance ) then
local dx,dy
if previousTouches and ( numTotalTouches ) >= 2 then
dx,dy = calculateDelta( previousTouches, event )
end
-- initialize to distance between two touches
if ( dx and dy ) then
local d = math.sqrt( dx*dx + dy*dy )
if ( d > 0 ) then
self.distance = d
self.xScaleOriginal = self.xScale
self.yScaleOriginal = self.yScale
print( "distance = " .. self.distance )
end
end
end
if not previousTouches[event.id] then
self.numPreviousTouches = self.numPreviousTouches + 1
end
previousTouches[event.id] = event
elseif self.isFocus then
if "moved" == phase then
if ( self.distance ) then
local dx,dy
if previousTouches and ( numTotalTouches ) >= 2 then
dx,dy = calculateDelta( previousTouches, event )
end
if ( dx and dy ) then
local newDistance = math.sqrt( dx*dx + dy*dy )
local scale = newDistance / self.distance
print( "newDistance(" ..newDistance .. ") / distance(" .. self.distance .. ") = scale(".. scale ..")" )
if ( scale > 0 ) then
self.xScale = self.xScaleOriginal * scale
self.yScale = self.yScaleOriginal * scale
end
end
end
if not previousTouches[event.id] then
self.numPreviousTouches = self.numPreviousTouches + 1
end
previousTouches[event.id] = event
elseif "ended" == phase or "cancelled" == phase then
if previousTouches[event.id] then
self.numPreviousTouches = self.numPreviousTouches - 1
previousTouches[event.id] = nil
end
if ( #previousTouches > 0 ) then
-- must be at least 2 touches remaining to pinch/zoom
self.distance = nil
else
-- previousTouches is empty so no more fingers are touching the screen
-- Allow touch events to be sent normally to the objects they "hit"
display.getCurrentStage():setFocus( nil )
self.isFocus = false
self.distance = nil
self.xScaleOriginal = nil
self.yScaleOriginal = nil
-- reset array
self.previousTouches = nil
self.numPreviousTouches = nil
end
end
end
return result
end
You could probably use a closure to accomplish this, assuming all of your points of interest are alike.
Example:
local function createPOI(properties)
local pointOfInterest = createPointOfInterest() -- code to create your object
--set properties based on argument
function pointOfInterest:touch(e)
--do stuff
end
pointOfInterest:addEventListner("touch")
return pointOfInterest
end
Corona has some code here that might be useful. Check the 'Multiple Touches' section.

Move a object by flicking

I can move the box by touching it and dragging it along the x-axis, but i like to be able to flick it from one side to the other. is there a simple solution to do this?
local box = display.newRect( 0, 0, 50, 50)
box:setFillColor( math.random(0,255), math.random(0,255), math.random(0,255) )
physics.addBody( box, { density=3.0, friction=0.5 } )
box.gravityScale = 0.0
function box:touch( event )
if event.phase == "began" then
self.markX = self.x
elseif event.phase == "moved" then
local x = (event.x - event.xStart) + self.markX
self.x = x
end
return true
end
box:addEventListener( "touch", box )
You could use transition.to, but you'll have to decide by how much to move. I'll assume you want to move it all the way to other side:
function box:touch( event )
if event.phase == "began" then
self.markX = self.x
elseif event.phase == "end" then
local targetX = 0 -- if flick left
if event.x > self.markX then -- flick right
targetX = display.contentWidth - self.width
end
local duration = 1000 -- 1 second
transition.to(self, {duration, x=targetX})
end
return true
end
Have not tested, could be syntax or other errors, but this should give you a good idea of how to proceed (if not put a comment).

Corona SDK Lua- Collision with coin

I want to make a sprite image have a collision with the coin.
The coin is a image and it is always moving because of this code:
local tPrevious = system.getTimer();
local function move(event)
local tDelta = event.time - tPrevious;
tPrevious = event.time;
local xOffset = (0.3 * tDelta );
grass.x = grass.x - xOffset;
grass2.x = grass2.x - xOffset;
coin.x = coin.x - xOffset;
if (grass.x + grass.contentWidth) < 0 then
grass:translate( 480 * 2, 0);
end
if (grass2.x + grass2.contentWidth) < 0 then
grass2:translate( 480 * 2, 0);
end
if (coin.x + coin.contentWidth) < 0 then
coin:translate( 480 * 2, 0);
coinRect.x = coin.x
end
local i;
end
Does anyone know how I can have a collision with the coin image?
Thanks in advance.
Add collision event listener to the coin like this,
local function onLocalCollision( self, event )
if ( event.phase == "began" ) then
print("on collision began")
elseif ( event.phase == "ended" ) then
print( "on collision ended")
end
end
coin:addEventListener( "collision", onLocalCollision)
if you wants the specific collision with the coin and sprite object,you should use collision filter.

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