Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Dynamic Body Stop Moving
Started by philippe.roubert Apr 23 2013 09:29 AM

- - - - -
10 replies to this topic
dynamic object stop move

Best Answer EvilAnton , 28 May 2013 - 12:29 AM

Oh, finally! Problem solved!

Well, let me explain. I have to body - dynamic (hero) and static (wall). When I press a joystic I count an angle, and then dX and dY (proepries of triangle). Then I set linearVelocity to hero, and he is moving. But I need him to be in a center. So I count a distance between the center of the screen and hero Position. These new dX and dY I apply to a hero as hero:translate(dX, dY) and also to a wall - wall:translate(dX, dY). And here we go! Hero only touch a wall and cannot to go through it and so on. Here is a sample code:

 

-- SAMPLE COLLISION FILTERS
local heroCollisionFilter = { categoryBits = 1, maskBits = 2 }
local objectsCollisionFilter = { categoryBits = 2, maskBits = 1 }

-- HELPS TO LOCATE OBJECTS
window_width = display.actualContentHeight
window_height = display.actualContentWidth
-- PHYSICS ENGINE ON
local physics = require ("physics")
physics.start()
physics.setGravity (0, 0) -- because it up view game

-- File with general functions. In this sample only getAngle() and getVector() functions used
require ("function")
-- In project this group consist information about all objects in the game
local world = display.newGroup()
-- Initialize objects for this project
local circleMove, moveArea, hero, topBorder

function move (obj, dX, dY)
    obj:translate(dX, dY)
end

function moveWorld (event)    
    local dX, dY = getVector (hero.direction, hero.speed) -- how far to push
    hero:setLinearVelocity (dX, dY) -- move hero as a physical object
    dX = window_width / 2 - hero.x -- count distance from screen center
    dY = window_height / 2 - hero.y
    move (hero, dX, dY) -- and move hero and border
    move (topBorder, dX, dY)
    --print (hero.x,  window_width / 2 - hero.x)
end

function world:startMove ()
    world.enterFrame = moveWorld
    Runtime:addEventListener ("enterFrame", world)
end

function world:stopMove ()
    hero:setLinearVelocity (0, 0) -- stop a movement
    Runtime:removeEventListener ("enterFrame", world)
end

-- When touch joystick calculate the angle, and give this information to moveWorld() function
function onMoveTouch (event)
    hero.direction = getAngle (moveArea.x, moveArea.y, event.x, event.y)    
    circleMove.x = event.x
    circleMove.y = event.y        
    if event.phase == "began" then
        world:startMove ()
    end    
    if event.phase == "cancelled" then
        print ("CANCELL")
    end    
    if event.phase == "ended" then         
        circleMove.x = moveArea.x
        circleMove.y = moveArea.y    
        world:stopMove ()    
    end
end

-- Visualisation of sample inteface
local background = display.newImage("background.png")
local moveGroup = display.newGroup ()
moveArea = display.newRect (moveGroup, 0,0,10,10)
moveArea:setFillColor (0,0,0,0)
moveArea.height = window_height / 2
moveArea.width = moveArea.height
moveArea.x = moveArea.width / 2
moveArea.y = window_height - (moveArea.height / 2)
local circleMoveBorder = display.newImageRect (moveGroup, "circle.png", moveArea.width, moveArea.height)
circleMoveBorder.x = moveArea.x
circleMoveBorder.y = moveArea.y
circleMove = display.newImageRect (moveGroup, "circle.png", moveArea.width/4, moveArea.height/4)
circleMove.x = moveArea.x
circleMove.y = moveArea.y
moveArea:addEventListener ("touch", onMoveTouch)

hero = display.newCircle (0,0, 10)
hero:setFillColor (120, 44, 220)
hero.x = window_width / 2
hero.y = window_height / 2
hero.speed = 80 -- this variable goes to the getVector() function
hero.direction = 0
topBorder = display.newRect (-100, 100, window_width + 200, 10)
topBorder:setFillColor (0,0,0)

-- The main trouble right here. What to do with collisions, should I use sensor or what?
hero.bodyType = "dynamic"
hero.physicsOptions = {
    density = 1,
    radius = 10,
    isSensor = false,
    filter = heroCollisionFilter,
}
physics.addBody (hero, hero.bodyType, hero.physicsOptions)

topBorder.bodyType = "static"
topBorder.physicsOptions = {
    density = 30,
    friction = 1.0,
    bounce = 0,
    isSensor = false,
    filter =  objectsCollisionFilter
}
physics.addBody (topBorder, topBorder.bodyType, topBorder.physicsOptions)


local function onCollision (self, event)    
    -- MEET A HERO
    if (event.other.physicsOptions.filter.categoryBits == 1) then    
        print (event.phase) -- to see is it over or not.
    end
end

topBorder.collision = onCollision
topBorder:addEventListener ("collision", topBorder)

 

[TOPIC CONTROLS]
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

philippe.roubert

[GLOBAL: userInfoPane.html]
philippe.roubert
  • Enthusiast

  • 36 posts
  • Corona SDK

Hello everyone,


So, I have a question, I'm creating a joystick based game, and I need some dynamic bodies for collisions, (kinda walls).


My player is static (/dynamic, doesn't change here). And when my
player collides with a wall, the wall moves with the action. How can I
stop dynamic objects moving and still have the wall stopping my player?


Thank you


Philippe


P.S.: Maybe I didn't understood well some physics actions :P I'm a newbie in lua



[TOPIC: post.html]
#2

hatethinkingofnames

[GLOBAL: userInfoPane.html]
hatethinkingofnames
  • Contributor

  • 186 posts
  • Corona SDK

Pretty sure your played is supposed to be dynamic and the wall static?

 

I believe the isSensor = true is what you are looking for either way to stop your walls from moving

 

http://docs.coronalabs.com/api/type/Body/isSensor.html

 

Edit: oh wow just saw the thread date, sorry for the late reply, you've probably figured it out already



[TOPIC: post.html]
#3

EvilAnton

[GLOBAL: userInfoPane.html]
EvilAnton
  • Observer

  • 29 posts
  • Corona SDK

I have the same problem. My game is joystick type and I move the world instead of player, which is stay in the center of the screen. Could you explain how excactly isSensor can help with this problem?



[TOPIC: post.html]
#4

torbenratzlaff

[GLOBAL: userInfoPane.html]
torbenratzlaff
  • Contributor

  • 404 posts
  • Corona SDK

I don't know if that's what the author of this topic wanted to know, but I will answer anton2111 at first.

 

I use the following method for letting my character stay in the center and the world moving around him.

 

The chracter is an dynamic object, the walls and all unmovable objects are static objects. The character and all objects are inside of a display group. Now you use your joystick and move the charater around. You have a function with a runtime listener, which moves the whole group in the opposite direction then the character does.

 

You have to do some annoying calculations here, but it's not that hard.

 

Hope that helps.



[TOPIC: post.html]
#5

EvilAnton

[GLOBAL: userInfoPane.html]
EvilAnton
  • Observer

  • 29 posts
  • Corona SDK

Thank you, torbenratzlaff! I used exactly the same method you described. But I have a problem with interaction with walls. What do you do, when character collides with any wall? What the logic of it? Do you use sensor and then implement other world-movement? Please explain, I brake my mind already :)

 

[TOPIC: post.html]
#6

hatethinkingofnames

[GLOBAL: userInfoPane.html]
hatethinkingofnames
  • Contributor

  • 186 posts
  • Corona SDK

Hmm that's weird. Not sure why I said isSensor would help in this case. I must have been tired or something since isSensor would make the player go through the wall I believe.

 

If your player is dynamic and walls are static, no isSensor involved at all, it should be false by default, then your player should be moving around the wall, depending on other physics properties. What do you want it to do exactly when it touches the wall?



[TOPIC: post.html]
#7

EvilAnton

[GLOBAL: userInfoPane.html]
EvilAnton
  • Observer

  • 29 posts
  • Corona SDK

Well, I just want the walls and buildings to be a solid objects - when character touch a wall he will not allowed to move further. But because I move world instead of hero, walls begin to push and character shift to the opposite side. And by the way, there some bug also - when dynamic - static interaction between them, collision event.phase become "began", in some cases it return to "ended", in other not. And then  it is possible to go through the wall without any collision. I will load a YouTube video to show it in 2-3 hours



[TOPIC: post.html]
#8

EvilAnton

[GLOBAL: userInfoPane.html]
EvilAnton
  • Observer

  • 29 posts
  • Corona SDK

  Best Answer

Oh, finally! Problem solved!

Well, let me explain. I have to body - dynamic (hero) and static (wall). When I press a joystic I count an angle, and then dX and dY (proepries of triangle). Then I set linearVelocity to hero, and he is moving. But I need him to be in a center. So I count a distance between the center of the screen and hero Position. These new dX and dY I apply to a hero as hero:translate(dX, dY) and also to a wall - wall:translate(dX, dY). And here we go! Hero only touch a wall and cannot to go through it and so on. Here is a sample code:

 

-- SAMPLE COLLISION FILTERS
local heroCollisionFilter = { categoryBits = 1, maskBits = 2 }
local objectsCollisionFilter = { categoryBits = 2, maskBits = 1 }

-- HELPS TO LOCATE OBJECTS
window_width = display.actualContentHeight
window_height = display.actualContentWidth
-- PHYSICS ENGINE ON
local physics = require ("physics")
physics.start()
physics.setGravity (0, 0) -- because it up view game

-- File with general functions. In this sample only getAngle() and getVector() functions used
require ("function")
-- In project this group consist information about all objects in the game
local world = display.newGroup()
-- Initialize objects for this project
local circleMove, moveArea, hero, topBorder

function move (obj, dX, dY)
    obj:translate(dX, dY)
end

function moveWorld (event)    
    local dX, dY = getVector (hero.direction, hero.speed) -- how far to push
    hero:setLinearVelocity (dX, dY) -- move hero as a physical object
    dX = window_width / 2 - hero.x -- count distance from screen center
    dY = window_height / 2 - hero.y
    move (hero, dX, dY) -- and move hero and border
    move (topBorder, dX, dY)
    --print (hero.x,  window_width / 2 - hero.x)
end

function world:startMove ()
    world.enterFrame = moveWorld
    Runtime:addEventListener ("enterFrame", world)
end

function world:stopMove ()
    hero:setLinearVelocity (0, 0) -- stop a movement
    Runtime:removeEventListener ("enterFrame", world)
end

-- When touch joystick calculate the angle, and give this information to moveWorld() function
function onMoveTouch (event)
    hero.direction = getAngle (moveArea.x, moveArea.y, event.x, event.y)    
    circleMove.x = event.x
    circleMove.y = event.y        
    if event.phase == "began" then
        world:startMove ()
    end    
    if event.phase == "cancelled" then
        print ("CANCELL")
    end    
    if event.phase == "ended" then         
        circleMove.x = moveArea.x
        circleMove.y = moveArea.y    
        world:stopMove ()    
    end
end

-- Visualisation of sample inteface
local background = display.newImage("background.png")
local moveGroup = display.newGroup ()
moveArea = display.newRect (moveGroup, 0,0,10,10)
moveArea:setFillColor (0,0,0,0)
moveArea.height = window_height / 2
moveArea.width = moveArea.height
moveArea.x = moveArea.width / 2
moveArea.y = window_height - (moveArea.height / 2)
local circleMoveBorder = display.newImageRect (moveGroup, "circle.png", moveArea.width, moveArea.height)
circleMoveBorder.x = moveArea.x
circleMoveBorder.y = moveArea.y
circleMove = display.newImageRect (moveGroup, "circle.png", moveArea.width/4, moveArea.height/4)
circleMove.x = moveArea.x
circleMove.y = moveArea.y
moveArea:addEventListener ("touch", onMoveTouch)

hero = display.newCircle (0,0, 10)
hero:setFillColor (120, 44, 220)
hero.x = window_width / 2
hero.y = window_height / 2
hero.speed = 80 -- this variable goes to the getVector() function
hero.direction = 0
topBorder = display.newRect (-100, 100, window_width + 200, 10)
topBorder:setFillColor (0,0,0)

-- The main trouble right here. What to do with collisions, should I use sensor or what?
hero.bodyType = "dynamic"
hero.physicsOptions = {
    density = 1,
    radius = 10,
    isSensor = false,
    filter = heroCollisionFilter,
}
physics.addBody (hero, hero.bodyType, hero.physicsOptions)

topBorder.bodyType = "static"
topBorder.physicsOptions = {
    density = 30,
    friction = 1.0,
    bounce = 0,
    isSensor = false,
    filter =  objectsCollisionFilter
}
physics.addBody (topBorder, topBorder.bodyType, topBorder.physicsOptions)


local function onCollision (self, event)    
    -- MEET A HERO
    if (event.other.physicsOptions.filter.categoryBits == 1) then    
        print (event.phase) -- to see is it over or not.
    end
end

topBorder.collision = onCollision
topBorder:addEventListener ("collision", topBorder)

 



[TOPIC: post.html]
#9

EvilAnton

[GLOBAL: userInfoPane.html]
EvilAnton
  • Observer

  • 29 posts
  • Corona SDK

function.lua

------------------

function getAngle (startX, startY, targetX, targetY)
    local quarter, cath_opp, cath_adj, hypotenuse, sin, cos, tan, newAngle
    if (targetX == startX and targetY == startY) then
        -- zero event to predict disappearence of the arrow
    else
        if targetX > startX then --> I and II quarters
            if targetY > startY then --> II quarter
                quarter = 2            
                 cath_opp = targetY - startY
                 cath_adj = targetX - startX
            else --> I quarter
                 quarter = 1
                 cath_opp = targetX - startX
                 cath_adj = startY - targetY
            end
        else --> III and IV quarters
            if targetY > startY then --> III quarter
                 quarter = 3    
                 cath_opp = startX - targetX
                 cath_adj = targetY - startY        
            else --> IV quarter
                 quarter = 4        
                 cath_opp = startY - targetY
                 cath_adj = startX - targetX
            end    
        end
        hypotenuse = math.sqrt ((cath_opp^2) + (cath_adj^2))
        --sin = cath_opp / hypotenuse    
        cos = cath_adj / hypotenuse
        --tan = cath_opp / cath_adj
        newAngle = (90 * (quarter-1)) + math.acos (cos) * 180 / math.pi
    end
    return newAngle
end

function getVector (angle, speed)
    local dX, dY
    if angle >= 0 and angle <= 90 then
        dX = speed * (angle / 90)
        dY = -speed * ((90 - angle) / 90)
    else if angle > 90 and angle <= 180 then
        dX = speed * ((180 - angle) / 90)
        dY = speed * ((angle - 90) / 90)
    else if angle > 180 and angle <= 270 then
        dX = -speed * ((angle - 180) / 90)
        dY = speed * ((270 - angle) / 90)
    else if angle > 270 and angle <= 360 then
        dX = -speed * ((360 - angle) / 90)
        dY = -speed * ((angle - 270) / 90)
    end    end    end    end
    return dX, dY
end 

 



[TOPIC: post.html]
#10

torbenratzlaff

[GLOBAL: userInfoPane.html]
torbenratzlaff
  • Contributor

  • 404 posts
  • Corona SDK

Great, you got it.

That was what I originally meant by moving the group containing the character in and the walls in the opposite direction.

Should have written it clearer I think ;)



[TOPIC: post.html]
#11

philippe.roubert

[GLOBAL: userInfoPane.html]
philippe.roubert
  • Enthusiast

  • 36 posts
  • Corona SDK

Well done guys




[topic_controls]
[/topic_controls]