Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Drag and drop — Gideros Forum

Drag and drop

oggychristieoggychristie Member
edited April 2013 in General questions
I am trying to learn by starting with a drag and drop game. I want to do this using classes. I have objects dragging using info from others in these forums but as you'll see I get errors - attempt to perform arithmetic on field 'x0' (a nil value) - but I am having enough success to be hopeful this can work.

Eventually I want to detect collisions between sprites and labels as per a matching game.

------------
-- main.lua
------------

-- Create multiple blocks.

scene = gideros.class(Sprite)

--on scene initialization
function scene:init()
--create world instance
self.actors = {}
local actors = {}
for i = 0, 5 do
-- The block image.
local blockSprite = Bitmap.new(Texture.new("_tanker.png"))

-- Create new block.
local block = Block.new(blockSprite)

-- Place blocks in the bottom screen side by side.
block:setPosition((i * 50) + 32, 240)
stage:addChild(block)
self.actors[block] = block
end

end
--Input (sprite2): another sprite to check for collision detection
--Return: return true if the rectangles overlap otherwise return false
function Sprite:collision(sprite2)

-- self bottom < other sprite top
if self:getY() + self:getHeight() < sprite2:getY() then
return false
end
-- self top > other sprite bottom
if self:getY() > sprite2:getY() + sprite2:getHeight() then
return false
end
-- self left > other sprite right
if self:getX() > sprite2:getX() + sprite2:getWidth() then
return false
end
-- self right < other sprite left
if self:getX() + self:getWidth() < sprite2:getX() then
return false
end

return true
end
--running the world
function scene:onEnterFrame()

for sprite in pairs(self.actors) do
--get specific sprite
--sprite:setPosition(body:getPosition())
--sprite:setRotation(body:getAngle() * 180 / math.pi)

--sprite:setPosition(body:getPosition())
--sprite:setRotation(body:getAngle() * 180 / math.pi)
end
end


--removing event on exiting scene
--just in case you're using SceneManager
function scene:onExitBegin()
self:removeEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
end

--add created scene to stage or sceneManager
local mainScene = scene.new()
stage:addChild(mainScene)

----------

Block = Core.class(Sprite)
local sprite



function Block:init(sprite)

self:addChild(sprite)


-- Register touch events.
sprite:addEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self)
sprite:addEventListener(Event.TOUCHES_MOVE, self.onTouchesMove, self)
sprite:addEventListener(Event.TOUCHES_END, self.onTouchesEnd, self)
sprite:addEventListener(Event.TOUCHES_CANCEL, self.onTouchesCancel, self)
local dragging=false
--sprit.
end

-- If block is on focus, stop propagation of touch events
function Block:onTouchesBegin(event)
if self.id == nil then
self.id = event.touch.id

print("BEGIN")
if self:hitTestPoint(event.touch.x, event.touch.y) then
dragging = true
-- Get start postion.
self.x0 = event.touch.x
self.y0 = event.touch.y
else
--self.x0 = 1
--self.y0 = 1
end
end
end

-- If block is on focus, stop propagation of touch events.
function Block:onTouchesMove(event)
if self.id == event.touch.id then


if self:hitTestPoint(event.touch.x, event.touch.y) then
if event.touch.x == nil then
event:stopPropagation()

end
print( self.x0)
local dx = event.touch.x - self.x0--get the diff of initial pos and current touch pos
print("MOVE2")
local dy = event.touch.y - self.y0
print("MOVE3")
self:setX(self:getX() + dx) -- add this diff to img's x and y pos
self:setY(self:getY() + dy)
print("MOVE4")

self.x0 = event.touch.x -- change the initial pos with new one
self.y0 = event.touch.y


event:stopPropagation()
end

end
end

-- If block is on focus, stop propagation of touch events.
function Block:onTouchesEnd(event)
if self.id - event.touch.id then

print("END")

self.id = nil
end
end

-- If touches are cancelled, reset the state of the button.
function Block:onTouchesCancel(event)
if self.focus then
self.focus = false;
self:updateVisualState(false)
event:stopPropagation()
end
end

Comments

  • The first problem is this:

    main.lua:19: attempt to index global 'Block' (a nil value)

    This means that at line 19 it doesn't know what "Block" is. Why doesn't it know that? Because you put this at line 77:

    Block = Core.class(Sprite)

    You may be thinking: "By the time it gets to scene:init(), it will know what Block is, because line 77 is actually executed before line 19!"

    But Lua doesn't work that way. It reads the file from top to bottom and so when it gets to line 17 it goes: "Block? WTF is Block? No one told me about Block!" (As you can probably tell, Lua is very dramatic.) :)

    So you need to put this:

    Block = Core.class(Sprite)

    BEFORE any function that uses "Block".

    I would like to help you more, but this will have to do for now as I'm at work. :)
  • One more quick comment:

    The next problems you'll run into also have to do with the order of things.

    If "function Block:init(sprite)" isn't declared before you create your Block, it won't be called. So you need to move this function so it's above your "function scene:init()".

    And the next problem:

    Block:init(sprite) calls:

    sprite:addEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self)
    sprite:addEventListener(Event.TOUCHES_MOVE, self.onTouchesMove, self)
    sprite:addEventListener(Event.TOUCHES_END, self.onTouchesEnd, self)
    sprite:addEventListener(Event.TOUCHES_CANCEL, self.onTouchesCancel, self)

    So again, move these four functions (onTouchesBegin, onTouchesMove, onTouchesEnd, onTouchesCancel) up so they come before the function that uses them.
  • Thank you so much for taking the time to comment on this. I have just arrived back from overseas and plan to sit down and try your suggestions. I am learning this and hope to push for gideros to be taught at my school. This is a great community that's for certain.
Sign In or Register to comment.