I've added my object ( a ball) and when it collide with an object the ball start changing it x an y position even if I apply force just on it y position (up and down)
local physics = require "physics"
physics.start()
--physics.setContinuous( false )
ball = display.newImage("ball.png") --MAIN OBJECT
ball.x = 100; ball.y = 100
physics.addBody(ball, "dynamic", {density=.05, bounce=0.1, friction=.2, radius=12})
screenGroup:insert(ball)
ball.myName = "ball"
function activateBall(self, event) --APPLY FORCE FUNCTION
self:applyForce(0, -1.5, self.x, self.y)
end
function onCollision (event) --BALL COLLIDES WITH JUST THIS OBSTACLES
if (event.object1.myName == "obst1") or (event.object1.myName == "obst2") then
storyboard.gotoScene("restart", "fade", 400)
audio.stop()
end
I want the ball to keep it position without starting to move randomly .
A quick solution would be to simply reset the balls x position in every frame.
local ballListener = function( event )
ball.x = 100
end
Runtime:addEventListener( "enterFrame", ballListener )
Maybe before applyForce() you can setLinearVelocity() for x value to 0, for y to the value you getLinearVelocity() for y value, and then applyForce() you want to. Probably that resets the x velocity you could have after collision.
Related
In my application i have pitch zoom.There i have followed the example from google search and did it.but while i am zooming in the image went to inside the boundaries.its perfect when zooming out.But while i zooming in at left or right corner,image is not set with that boundaries.Please help any one.
if "moved" == phase then
if ( tempGroup.distance ) then
local dx,dy
if previousTouches and ( numTotalTouches ) >= 2 then
dx,dy,midX,midY,offX,offY = calculateDelta( previousTouches, event )
end
if ( dx and dy ) then
local newDistance = math.sqrt( dx*dx + dy*dy )
modScale = newDistance / tempGroup.distance
if ( modScale > 0 ) then
----MODIFIED BY CON
local newScale=tempGroup.xScaleOriginal * modScale
-- uncomment below to set max and min scales
maxScale,minScale=3,1
if (newScale>maxScale) then
newScale=maxScale
end
if (newScale<minScale) then
newScale=minScale
end
tempGroup.xScale = newScale
tempGroup.yScale = newScale
end
This is a working example. Copy this into your main.lua
-- one more thing
-- turn on multitouch
system.activate("multitouch")
-- which environment are we running on?
local isDevice = (system.getInfo("environment") == "device")
-- returns the distance between points a and b
function lengthOf( a, b )
local width, height = b.x-a.x, b.y-a.y
return (width*width + height*height)^0.5
end
-- returns the degrees between (0,0) and pt
-- note: 0 degrees is 'east'
function angleOfPoint( pt )
local x, y = pt.x, pt.y
local radian = math.atan2(y,x)
local angle = radian*180/math.pi
if angle < 0 then angle = 360 + angle end
return angle
end
-- returns the degrees between two points
-- note: 0 degrees is 'east'
function angleBetweenPoints( a, b )
local x, y = b.x - a.x, b.y - a.y
return angleOfPoint( { x=x, y=y } )
end
-- returns the smallest angle between the two angles
-- ie: the difference between the two angles via the shortest distance
function smallestAngleDiff( target, source )
local a = target - source
if (a > 180) then
a = a - 360
elseif (a < -180) then
a = a + 360
end
return a
end
-- rotates a point around the (0,0) point by degrees
-- returns new point object
function rotatePoint( point, degrees )
local x, y = point.x, point.y
local theta = math.rad( degrees )
local pt = {
x = x * math.cos(theta) - y * math.sin(theta),
y = x * math.sin(theta) + y * math.cos(theta)
}
return pt
end
-- rotates point around the centre by degrees
-- rounds the returned coordinates using math.round() if round == true
-- returns new coordinates object
function rotateAboutPoint( point, centre, degrees, round )
local pt = { x=point.x - centre.x, y=point.y - centre.y }
pt = rotatePoint( pt, degrees )
pt.x, pt.y = pt.x + centre.x, pt.y + centre.y
if (round) then
pt.x = math.round(pt.x)
pt.y = math.round(pt.y)
end
return pt
end
-- calculates the average centre of a list of points
local function calcAvgCentre( points )
local x, y = 0, 0
for i=1, #points do
local pt = points[i]
x = x + pt.x
y = y + pt.y
end
return { x = x / #points, y = y / #points }
end
-- calculate each tracking dot's distance and angle from the midpoint
local function updateTracking( centre, points )
for i=1, #points do
local point = points[i]
point.prevAngle = point.angle
point.prevDistance = point.distance
point.angle = angleBetweenPoints( centre, point )
point.distance = lengthOf( centre, point )
end
end
-- calculates rotation amount based on the average change in tracking point rotation
local function calcAverageRotation( points )
local total = 0
for i=1, #points do
local point = points[i]
total = total + smallestAngleDiff( point.angle, point.prevAngle )
end
return total / #points
end
-- calculates scaling amount based on the average change in tracking point distances
local function calcAverageScaling( points )
local total = 0
for i=1, #points do
local point = points[i]
total = total + point.distance / point.prevDistance
end
return total / #points
end
-- creates an object to be moved
function newTrackDot(e)
-- create a user interface object
local circle = display.newCircle( e.x, e.y, 50 )
-- make it less imposing
circle.alpha = .5
-- keep reference to the rectangle
local rect = e.target
-- standard multi-touch event listener
function circle:touch(e)
-- get the object which received the touch event
local target = circle
-- store the parent object in the event
e.parent = rect
-- handle each phase of the touch event life cycle...
if (e.phase == "began") then
-- tell corona that following touches come to this display object
display.getCurrentStage():setFocus(target, e.id)
-- remember that this object has the focus
target.hasFocus = true
-- indicate the event was handled
return true
elseif (target.hasFocus) then
-- this object is handling touches
if (e.phase == "moved") then
-- move the display object with the touch (or whatever)
target.x, target.y = e.x, e.y
else -- "ended" and "cancelled" phases
-- stop being responsible for touches
display.getCurrentStage():setFocus(target, nil)
-- remember this object no longer has the focus
target.hasFocus = false
end
-- send the event parameter to the rect object
rect:touch(e)
-- indicate that we handled the touch and not to propagate it
return true
end
-- if the target is not responsible for this touch event return false
return false
end
-- listen for touches starting on the touch layer
circle:addEventListener("touch")
-- listen for a tap when running in the simulator
function circle:tap(e)
if (e.numTaps == 2) then
-- set the parent
e.parent = rect
-- call touch to remove the tracking dot
rect:touch(e)
end
return true
end
-- only attach tap listener in the simulator
if (not isDevice) then
circle:addEventListener("tap")
end
-- pass the began phase to the tracking dot
circle:touch(e)
-- return the object for use
return circle
end
-- spawning tracking dots
-- create display group to listen for new touches
local group = display.newGroup()
-- populate display group with objects
local rect = display.newRect( group, 200, 200, 200, 100 )
rect:setFillColor(0,0,255)
rect = display.newRect( group, 300, 300, 200, 100 )
rect:setFillColor(0,255,0)
rect = display.newRect( group, 100, 400, 200, 100 )
rect:setFillColor(255,0,0)
-- keep a list of the tracking dots
group.dots = {}
-- advanced multi-touch event listener
function touch(self, e)
-- get the object which received the touch event
local target = e.target
-- get reference to self object
local rect = self
-- handle began phase of the touch event life cycle...
if (e.phase == "began") then
print( e.phase, e.x, e.y )
-- create a tracking dot
local dot = newTrackDot(e)
-- add the new dot to the list
rect.dots[ #rect.dots+1 ] = dot
-- pre-store the average centre position of all touch points
rect.prevCentre = calcAvgCentre( rect.dots )
-- pre-store the tracking dot scale and rotation values
updateTracking( rect.prevCentre, rect.dots )
-- we handled the began phase
return true
elseif (e.parent == rect) then
if (e.phase == "moved") then
print( e.phase, e.x, e.y )
-- declare working variables
local centre, scale, rotate = {}, 1, 0
-- calculate the average centre position of all touch points
centre = calcAvgCentre( rect.dots )
-- refresh tracking dot scale and rotation values
updateTracking( rect.prevCentre, rect.dots )
-- if there is more than one tracking dot, calculate the rotation and scaling
if (#rect.dots > 1) then
-- calculate the average rotation of the tracking dots
rotate = calcAverageRotation( rect.dots )
-- calculate the average scaling of the tracking dots
scale = calcAverageScaling( rect.dots )
-- apply rotation to rect
rect.rotation = rect.rotation + rotate
-- apply scaling to rect
rect.xScale, rect.yScale = rect.xScale * scale, rect.yScale * scale
end
-- declare working point for the rect location
local pt = {}
-- translation relative to centre point move
pt.x = rect.x + (centre.x - rect.prevCentre.x)
pt.y = rect.y + (centre.y - rect.prevCentre.y)
-- scale around the average centre of the pinch
-- (centre of the tracking dots, not the rect centre)
pt.x = centre.x + ((pt.x - centre.x) * scale)
pt.y = centre.y + ((pt.y - centre.y) * scale)
-- rotate the rect centre around the pinch centre
-- (same rotation as the rect is rotated!)
pt = rotateAboutPoint( pt, centre, rotate, false )
-- apply pinch translation, scaling and rotation to the rect centre
rect.x, rect.y = pt.x, pt.y
-- store the centre of all touch points
rect.prevCentre = centre
else -- "ended" and "cancelled" phases
print( e.phase, e.x, e.y )
-- remove the tracking dot from the list
if (isDevice or e.numTaps == 2) then
-- get index of dot to be removed
local index = table.indexOf( rect.dots, e.target )
-- remove dot from list
table.remove( rect.dots, index )
-- remove tracking dot from the screen
e.target:removeSelf()
-- store the new centre of all touch points
rect.prevCentre = calcAvgCentre( rect.dots )
-- refresh tracking dot scale and rotation values
updateTracking( rect.prevCentre, rect.dots )
end
end
return true
end
-- if the target is not responsible for this touch event return false
return false
end
-- attach pinch zoom touch listener
group.touch = touch
-- listen for touches starting on the touch object
group:addEventListener("touch")
I have an image (ground) with transparent pixels on top of it since the ground has hills like ups and downs ... the problem is that the ball isn't moving down and up according to the hills ... the ball is just floating over the image. what can I do ??
local bg2 = display.newImage("images/ground.png",true)
bg2:setReferencePoint(display.CenterLeftReferencePoint)
bg2.x = 0; bg2.y = _H/1.25;
local physics = require("physics")
physics.start()
local redOrb = display.newCircle( 0, 0, 25)
redOrb:setFillColor(255,0, 0)
physics.setGravity(0,9.8)
redOrb.x = 180; redOrb.y = 190; redOrb.rotation = 5
physics.addBody( bg2, "static", { friction=0.5, bounce=0.3 } )
physics.addBody( redOrb, { density=3.0, friction=0.5, bounce=0.3 } )
When you add a body to an image that has a transparency , it will not automatically make the body the as the image itself.
You can use this tool for the physics body
http://www.codeandweb.com/physicseditor
http://www.codeandweb.com/blog/2012/05/24/getting-started-with-coronasdk-and-physicseditor-tutorial
To view the actual physics body you can add this code
physics.setDrawMode("hybrid")
I want to make a moon rotating around a planet, or something along that analogy. So is there something I can call for physics.setGravity(0,0) that changes the position that the gravity pulls towards, particularly assigning that to be a physics body? If not, simply a specific x-y coordinate will be fine.
local moon = display.newImage ("moon.png")
physics.addBody(moon, {bounce=0, density=1.0})
local earth = display.newImage ("earth.png")
physics.addBody(earth, {bounce=0, density=1.0})
Thanks
Instead of playing around with the setGravity option, I think you should just rotate the images using something like this:
local physics = require("physics")
physics.start()
physics.setGravity(0, 0)
display.setStatusBar( display.HiddenStatusBar )
local background = display.newImage( "space.png", true )
background.x = display.contentWidth / 2
background.y = display.contentHeight / 2
local earth = display.newImage( "earth.png" )
earth.x = 100; earth.y = 200
earth.xScale = 0.7
earth.yScale = 0.7
physics.addBody( earth, {radius=40 } )
earth.bodyType = "static"
local moon = display.newImage( "moon.png", 40, 40)
moon.x = earth.x + 80
moon.y = earth.y
moon.xScale = 0.3
moon.yScale = 0.3
moon.rotation = 100
physics.addBody( moon, {radius=10 } )
moon.bodyType = "dynamic"
myJoint = physics.newJoint( "pivot", moon, earth, earth.x, earth.y )
local orbit = function( event )
moon.rotation = moon.rotation + 1.5
end
Notice that I am not really mucking about with setGravity, but the speed of the rotation is defined in the orbit function.
The above code assumes you just have image files to represent your planetary bodies. If so, you will have to play around with the constants above (earth.x and earth.y, scaling values, etc) to make the whole system LOOK right for the images you choose.
Good luck!
No - you can change gravity but it will pull/push only in the direction you have it set to, never to any point. You'd likely use a sensor (invisible) around your earth and apply force to draw things towards it when the collision event between the moon/other and sensor began.
I have a joystick graphic placed in the corner of the screen in my Corona game.
When the user touches the joystick and drags it from side-to-side, it moves the character. However, if the user drags from the middle of the joystick all the way off to the side, then removes his/her finger, the character keeps on moving. I'd like the character to stop on touch-up, even if the touch up is no longer on the joystick graphic.
The joystick image subscribes to the "touch" listener with control:addEventListener( "touch", onTouch ).
Joystick code below:
-- Constants
local playerSpeed = 300
local playerDamping = 15
-- Player controls
local onTouch = function( event )
-- Player rotation
local deltaX = event.x - control.x
local deltaY = event.y - control.y
local magnitude = math.sqrt( deltaX * deltaX + deltaY * deltaY )
player.rotation = math.deg( math.atan2 ( deltaY, deltaX ) )
-- Player speed
if event.phase == "ended" then
player.linearDamping = playerDamping
else
player.linearDamping = 0
player:setLinearVelocity( deltaX / magnitude * playerSpeed, deltaY / magnitude * playerSpeed )
end
end
Any ideas? Thanks!
Add:
if event.phase == "began" then
display.getCurrentStage():setFocus( control, event.id )
end
to the body of the onTouch function, to subscribe to the 'touch ended' event, even when the user's finger isn't on the joystick.
Hey guys, I just finished my app with Corona SDK and thought I'd try to make my first game.
As my first app was learning about the accelerometer I thought my game should be with that too.
So I placed a little doodle on the screen and got him controlled by the accelerometer in both X and Y direction, the game is in landscape but if I have the device on an angle towards me the doodle slides off the screen in Y direction.
If I would be laying in bed or slouching on the couch then the game won't be playable.
How do I write a function that compensate this angle?
Here is the code I have for the accelerometer at the moment;
display.setStatusBar(display.HiddenStatusBar)
system.setAccelerometerInterval( 50 )
_W = display.contentWidth
_H = display.contentHeight
local player = display.newImageRect("doodle.png", 64, 64)
player:setReferencePoint(display.CenterReferencePoint)
player.x = _W/2
player.y = _H/2
-- Set up the Accelerometer values in Landscape
local motionX = 0
local motionY = 0
local function onAccelerate( event )
motionX = 10 * event.yGravity;
motionY = 10 * event.xGravity;
end
Runtime:addEventListener ("accelerometer", onAccelerate);
-- Make the player move on tilt.
local function movePlayer (event)
player.x = player.x + motionX;
player.y = player.y - motionY;
end
Runtime:addEventListener("enterFrame", movePlayer))
We faced a similar challenge for ArdentHD.
Basically what you need to do is calibrate for the "still" X, Y and Z values.
Once you launch your game, keep reading the accelerometer for a few seconds.
During that time you can display a count down or something else to comfort the user.
Calculate the average value for X, Y and Z respectively.
These are the values that represent a "still" device.
So when the user holds the device upright, you'll have X = 0, Y = -1 and Z = 0.
(With the device on it's back, it would be X = 0, Y = 0, Z = -1)
Save those somewhere.
e.g:
xOffset = event.xGravity
yOffset = event.yGravity
zOffset = event.zGravity
Now, instead of executing
motionX = 10 * event.yGravity;
motionY = 10 * event.xGravity;
in your movement calculation function, instead execute
motionX = 10 * (event.yGravity - xOffset);
motionY = 10 * (event.xGravity - yOffset);
This cleans out the original position.
Also, be aware that of you want to really turn the device 360°, you will to calculate both your motionX and motionY as a cotangent of xGravity and zGravity as well as yGravity and zGravity. Otherwise the movement will only feel "real" when the device is horizontal (zGravity constant at -1).