Corona - Lua - Dragging object without physics - drag-and-drop

I am relatively new to coding in lua so bear with me.
I'm ultimately trying to setup a drag & drop function for multiple 'tiles' on one scene. But to begin with (and to make sure I understand all of this correctly) I am just trying to get one tile moving around the screen.
So I browsed the interwebs for a while and found the solution below (among other similar solutions) and implemented this myself with my own object names etc.
It works great....but...unfortunatelt when i drag the object into the top right quadrant of the screen (on the simulator and a phone) the object gets stuck. It stops dragging as it hits any part of the top right quadrant of the screen, and I cannot re-select it to drag it back to the rest of the screen.
Any ideas as to why this is happening?? (my code is below)
local _H = display.contentHeight
local _W = display.contentWidth
local notesGroup = display.newGroup()
local tile1 = display.newImage ("graphics/image.PNG")
tile1.x = _W/2
tile1.y = _H/2
function tile1:touch( event )
if event.phase == "began" then
self.markX = self.x -- store x location of object
self.markY = self.y -- store y location of object
elseif event.phase == "moved" then
local x = (event.x - event.xStart) + self.markX
local y = (event.y - event.yStart) + self.markY
self.x, self.y = x, y
end
return true
end
notesGroup:insert(tile1)
tile1:addEventListener("touch", tile1)

You need to set focus on touched object to prevent from loosing it while you drop it outside screen. Your touch event should look like this:
function tile1:touch( event )
if event.phase == "began" then
display.getCurrentStage():setFocus( event.target )
self.markX = self.x -- store x location of object
self.markY = self.y -- store y location of object
elseif event.phase == "moved" then
local x = (event.x - event.xStart) + self.markX
local y = (event.y - event.yStart) + self.markY
self.x, self.y = x, y
elseif event.phase == "ended" or event.phase == "cancelled" then
display.getCurrentStage():setFocus(nil)
end
return true
end

Try
-- create a circle and put it in the center of the screen
local circle = display.newCircle( display.contentWidth*0.5,display.contentHeight*0.5, 75)
circle:setFillColor( 255 )
-- touch listener function
function circle:touch( event )
if event.phase == "began" then
-- first we set the focus on the object
display.getCurrentStage():setFocus( self, event.id )
self.isFocus = true
-- then we store the original x and y position
self.markX = self.x
self.markY = self.y
elseif self.isFocus then
if event.phase == "moved" then
-- then drag our object
self.x = event.x - event.xStart + self.markX
self.y = event.y - event.yStart + self.markY
elseif event.phase == "ended" or event.phase == "cancelled" then
-- we end the movement by removing the focus from the object
display.getCurrentStage():setFocus( self, nil )
self.isFocus = false
end
end
-- return true so Corona knows that the touch event was handled propertly
return true
end
-- finally, add an event listener to our circle to allow it to be dragged
circle:addEventListener( "touch", circle )

A problem with your way of handling movement of the touch is that if the touch moves off the DisplayObject (in this case, tile1) between frames, the object's listener method won't be called before rendering the next frame and its position won't be updated. This may explain the weird "stuck in upper right quadrant" behaviour you're getting.
lduriat and Lukis show that setting the focus for this touch event (note the use of event.id by lduriat to handle the multitouch case) on the object avoids this problem. The use of setFocus() in handling touch events is explained in this section of the Corona Events/Listeners dev guide.

Related

The NPC follows the part but when i go near the NPC they leave the part and start going to random directions

So i'm trying to make an npc move to a part when i click on the npc, when i clicked on it all seemed well until i went near the npc, at that point it left the part and started moving to random directions. Is there something wrong?
Script:
local value = script.Parent.FollowSurvivor
local value2 = workspace.Values.MoveToValue
function findNearestTorso(pos)
local list = game.Workspace:children()
local torso = nil
local dist = 1000
local temp = nil
local human = nil
local temp2 = nil
for x = 1, #list do
temp2 = list[x]
if (temp2.className == "Model") and (temp2 ~= script.Parent) then
temp = temp2:findFirstChild("Torso")
human = temp2:findFirstChild("Humanoid")
if (temp ~= nil) and (human ~= nil) and (human.Health > 0) then
if (temp.Position - pos).magnitude < dist then
torso = temp
dist = (temp.Position - pos).magnitude
end
end
end
end
return torso
end
while true do
wait(0.5)
local target = findNearestTorso(script.Parent.Torso.Position)
if target ~= nil then
if value.Value == true then
script.Parent.Zombie:MoveTo(target.Position, target)
end
if value.Value == false then
script.Parent.Zombie:MoveTo(workspace.MoveToPart.Position)
end
end
end
This script gets the nearest humanoid and goes towards it. When you walked next to it, it found your humanoid and it started following you.

Why is my flight script not functioning correctly?

I'm making a flight script to use for ProtoSmasher and it's not working as intended. I want it to have a toggle button (G) and then be able to fly with a button (W). Instead of that, to get it to work I have to hold W and then press G; but if I try to let go of w to stop in the air I have to press G again.
local plr = game:GetService("Players").LocalPlayer
local char = plr.Character
local hum = char.Humanoid
local Torso = char.HumanoidRootPart
local Mouse = plr:GetMouse()
local toggle = false
local wToggle = false
Mouse.KeyDown:Connect(function(key)
if key == "w" then
wToggle = true
end
if key == "g" then
if toggle == false then
toggle = true
local BV = Instance.new("BodyVelocity",Torso)
BV.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
while wToggle == true do
BV.Velocity = Mouse.Hit.lookVector*200
wait()
end
end
if toggle == true then
toggle = false
Torso:FindFirstChildOfClass("BodyVelocity"):remove()
end
end
end)
Mouse.KeyUp:Connect(function(key)
if key == "w" then
wToggle = false
end
end)
It looks like you are trying to connect to keyboard key presses, but you are doing so in the event listener for mouse button presses.
Try something like this :
local isFlying = false
local function onKeyPress(actionName, userInputState, inputObject)
local isKeyDown = userInputState == Enum.UserInputState.Begin
local isKeyUp = userInputState == Enum.UserInputState.End
if actionName == "toggleFlight" then
if isKeyUp then
isFlying = not isFlying
end
elseif actionName == "fly" then
if isKeyDown then
-- start flying forward
elseif isKeyUp then
-- stop flying
end
end
end
-- listen for keyboard input
game.ContextActionService:BindAction("toggleFlight", onKeyPress, false, Enum.KeyCode.G)
game.ContextActionService:BindAction("fly", onKeyPress, false, Enum.KeyCode.W)

is there a touch and hold event in Corona sdk, If not then how to do that

is there a touch and hold event in Corona sdk, If not then how to do that. for example. i want to increase the radius of a circle while holding anywhere on the screen, and without moving. how to do that.
'
thanx
Try (as I know you can't change radius so I use xScale and yScale to increase circle)
local circle = display.newCircle( display.contentCenterX, display.contentCenterY, 50 )
step = 0.02
local holding = false
local function enterFrameListener()
if holding then
-- Holding button
circle.xScale = circle.xScale + step
circle.yScale = circle.yScale + step
else
-- Not holding
-- Code here
end
end
local function touchHandler( event )
if event.phase == "began" then
Runtime:addEventListener( "enterFrame", enterFrameListener )
holding = true
elseif event.phase == "ended" or event.phase == "moved" then
holding = false
Runtime:removeEventListener( "enterFrame", enterFrameListener )
end
return true
end
Runtime:addEventListener( "touch", touchHandler )
The code borrow from post from stackoverflow.com.

How to animate (moving by default) and inanimate (make stationary on tap) colliding objects

Hey tired this new code to animate objects (here bubbles) and make them stationary using sprites. The code is as below,
local ui = require("ui")
local gameUI = require("gameUI")
local easingx = require("easingx")
require "sprite"
display.setStatusBar( display.HiddenStatusBar )
local physics = require("physics")
physics.start()
physics.setScale( 60 )
local backgroundPortrait = display.newImage( "sky.png", 0, 0 )
local backgroundLandscape = display.newImage( "sky.png", 80, 80 )
backgroundLandscape.isVisible = false
local disp = backgroundLandscape
local function selectBubble( event )
local tapped = event.target --event.target is how Corona points to the tapped bubble
if ( tapped.bubbleSelected == false ) then
local vx,vy = tapped:getLinearVelocity()
tapped.xVel = vx --stores the current velocity into bubble's "xVel" variable
tapped.yVel = vy --likewise for yVel
tapped:setLinearVelocity( 0,0 ) --set bubble's velocity to 0!
tapped.currentFrame = (3)
tapped.bubbleSelected = true
elseif ( tapped.bubbleSelected == true ) then
tapped:setLinearVelocity( tapped.xVel, tapped.yVel ) --read previous velocity and set
tapped.bubbleSelected = false
end
end
--BUBBLE1
local bubble1 = sprite.newSprite( spriteSet1 )
bubble1.x = 100
bubble1.y = 100
physics.addBody(bubble1, {bounce=0.04, filter = bubbleCollisionFilter})
bubble1:setLinearVelocity( 2, 4 )
bubble1:addEventListener( "tap", selectBubble )
bubble1.bubbleSelected = false
bubble1:prepare("bubble")
bubble1:play()
--BUBBLE2
local bubble2 = sprite.newSprite( spriteSet1 )
bubble2.x = 210
bubble2.y = 20
physics.addBody(bubble2, {bounce=0.05, filter = bubbleCollisionFilter})
bubble2:setLinearVelocity( 2, 4 )
bubble2:prepare("bubble")
bubble2:play()
--BUBBLE3
local bubble3 = sprite.newSprite( spriteSet1 )
bubble3.x = 100
bubble3.y = 17
physics.addBody(bubble3, {bounce=0.02, filter = bubbleCollisionFilter})
bubble1:setLinearVelocity( 1, 2 )
bubble3:prepare("bubble")
bubble3:play()
--BUBBLE4
local bubble4 = sprite.newSprite( spriteSet1 )
bubble4.x = 310
bubble4.y = 20
physics.addBody(bubble4, {bounce=0.4, filter = bubbleCollisionFilter})
bubble4:setLinearVelocity( 2, 4 )
bubble4:prepare("bubble")
bubble4:play()
The problem is firstly the code doesn't seem to work. Secondly though the bubble changes color on tap (this color is same for most). Yet, each bubble has a unique letter on it. How to get this to work. Please help.
It's hard to know what exactly you're asking because your question is pretty vague (what does "animate" mean? And what do you mean by "doesn't seem to work"? explain these terms because they can mean multiple things) but I think you want to set the physics bodies to "static" in the tap event listener. Refer here for what I'm talking about:
http://developer.anscamobile.com/reference/index/bodybodytype
So inside the selectBubble() function you would type something like tapped.bodyType="static"

COCOS2D - Animation Stops During Move

I am trying to run a "Walk" style animation on my main game sprite. The animations work fine, and my sprite is hooked up to my joystick all fine and dandy.
However, I think where I setup the call for my walk animations are wrong. Because everytime the sprite is moving, the animation stops.
I know putting the animation in such a weak if statement is probably bad, but please tell me how I could get my sprite to animate properly while it is being moved by the joystick.
The sprite faces the right direction, so I can tell the action's first frame is being called, however, it doesn't animate until I stop touching my joystick.
Here is How I call the action:
//WALK LEFT
if (joypadCap.position.x <= 69 /*&& joypadCap.position.y < && joypadCap.position.y > >40 */ )
{
[tjSprite runAction:walkLeft];
};
//WALK RIGHT
if ( joypadCap.position.x >= 71 /* && joypadCap.position.y < 100 && >joypadCap.position.y > 40 */)
{
[tjSprite runAction:walkRight];
};
THIS: is the how the joystick controls the character:
CGPoint newLocation = ccp(tjSprite.position.x - distance/8 * cosf(touchAngle),
tjSprite.position.y - distance/8 * sinf(touchAngle));
tjSprite.position = newLocation;
Please help. Any alternative ways to call the characters walk animation would be greatly appreciated!
int current_state;
if (current_state != 1 && joypadCap.position.x <= 69)
{
current_state = 1;
[tjSprite runAction:walkLeft];
}
else if (current_state != 1 && joypadCap.position.x >= 71)
{
current_state = 1;
[tjSprite runAction:walkRight];
}
else
{
current_state = 0;
//[tjSprite stopAllActions];
};
The sprite faces the right direction,
so I can tell the action's first frame
is being called, however, it doesn't
animate until I stop touching my
joystick.
Based on the code you have supplied this actually makes sense. What your if statement is saying is anytime the joypadCap position is greater than 71 or less than 69 play an animation. This means your animations will try to play over and over again from the beginning everytime joypadCap's position falls in these ranges. I assume joypadCap is a measure of how much the joystick is being pressed?
Looks like you could use some additional state logic to determine what your character should be doing. Here is some pseudocode...
state current_state;
if (current_state != walking and joypadCap.position.x <= 69)
{
current_state = walking;
[tjSprite runAction:walkLeft];
}
else if (current_state != walking and joypadCap.position.x >= 71)
{
current_state = walking;
[tjSprite runAction:walkRight];
}
else
{
current_state = idle;
[tjSprite stopAllActions];
}
Keep in mind that is loose pseudocode. Not everything is syntactically correct but logically the idea is that you have a state variable to keep track of the characters current state which allows you so have your animations play one time only. Let me know if this helps and if you have any questions about my answer.