Calculate a circular wrapper?

Sorry guys but i have some serious brain freeze.

I found a code sample on Peach Pellens site how to wrap the screen so the object wont go outside the screen edges. This sample works great but how do you make a wrapper around a circular object?

here’s a version for a creating a wrapper around a square that is 200x200px based on her code, how do you make one that is a circle with the same dimensions?

local function wrapper()  
  
 -----  
 if ball.x \< (\_W/2 - square.width/2 + ball.width/2) then   
 ball.x = (\_W/2 - square.width/2 + ball.width/2)  
 end  
  
 -----  
 if ball.x \> (\_W/2 + square.width/2 - ball.width/2) then  
 ball.x = (\_W/2 + square.width/2 - ball.width/2)  
 end  
  
 -----  
 if ball.y \< (\_H/2 - square.height/2 + ball.height/2) then   
 ball.y = (\_H/2 - square.height/2 + ball.height/2)  
 end  
  
 -----  
 if ball.y \> (\_H/2 + square.height/2 - ball.height/2) then  
 ball.y = (\_H/2 + square.height/2 - ball.height/2)  
 end  
end  

[import]uid: 34126 topic_id: 9781 reply_id: 309781[/import]

may be this will help

http://developer.anscamobile.com/code/joystick [import]uid: 12482 topic_id: 9781 reply_id: 35661[/import]

I’m not that good at analyzing code or math for that fact, but hey I’m learning so I’ll give it a shot.

So basically what needs to be done is to find the center of the circle and calculate the distance to where ever the ball might go towards the circles outer bounds?

I wont have access to my own computer running corona simulator for another week so I’m just writing this from the top of my head, feel free to try it and/or correct any typos or errors or improve it etc…

Help out if you can.

main.lua

function main()  
  
 local centerX = display.contentWidth/2;  
 local centerY = display.contentHeight/2;  
  
 local wrapperRadius = 100;  
 local max = this.ballMax;  
  
 local acc = {}  
  
 local mainGroup = display.newGroup()   
 -- I used a circle   
 local ball = display.newCircle(centerX, centerY, 16)  
 ball:setFillColor(128,199,200)  
  
 mainGroup:insert(ball)  
  
 function acc:accelerometer(event)  
 -- I have landscapeLeft defined as orientation in build.settings.  
 ball.x = centerX - (centerX \* event.yGravity);  
 ball.x = centerX + (centerX \* event.yGravity);  
 ball.y = centerY - (centerY \* event.xGravity);  
 ball.y = centerY + (centerY \* event.xGravity);  
 end  
 Runtime:addEventListener("accelerometer", acc)  
  
 function circleWrapper (ball)  
 -- this pretty much defines a "pie slice" of the circleWrapper.  
 local xDistance = ball.x - wrapperRadius;  
 local yDistance = ball.y - wrapperRadius;  
  
 -- what this does I'm not really sure since I know the radius already, does it calculate the diameter of the wrapper perhaps?  
 local distance = math.sqrt (( xDistance\*xDistance) + (yDistance + yDistance));  
  
 -- if the above calculates the diameter then this defines how far it can go left/right or up/down?  
 if distance \> max then distance = max  
 end  
  
 -- This part then calculate the angle of the "pie slice" then, sort of cutting out a section of the pie?  
 local angle = (math.atan2(xDistance, xDistance) \*(yDistance, yDistance)) + 90   
 if angle \<0 then  
 angle = 360 + angle   
 end  
  
 -- Now to getting the outer bounds of the circleWrapper  
 local xFinal = (math.sin (angle\*math.pi/180) \*distance);  
 local yFinal = (math.cos (angle\*math,pi/180) \*distance);   
  
 -- Now Normalize, I don't really know what that does  
 distance = distance/max;  
 xFinal = xFinal/max;  
 yFinal = yFinal/max  
  
  
 end   
  
 return mainGroup;  
end  
  
main()  
  

[import]uid: 34126 topic_id: 9781 reply_id: 35799[/import]

I noticed I did a type error here.

local angle = (math.atan2(xDistance, xDistance) \*(180 / math.pi)) + 90   
 if angle \<0 then  
 angle = 360 + angle   
 end  

Also after reading up a little on accelerometer and looking at samples I noticed I don’t need to write the accelerometer code like I did in my previous post instead this should be enough.

function acc:accelerometer(event)  
 -- I have landscapeLeft defined as orientation in build.settings.  
 ball.x = centerX - (centerX \* event.yGravity);   
 ball.y = centerY - (centerY \* event.xGravity);  
  
 end  
 Runtime:addEventListener("accelerometer", acc)  

This should be enough to get the ball rolling in any direction.

Then I think the circleWrapper function should be renamed to something like circleBounds as it does not set up the wrapper but calculates the bounds?

I’ve been looking at some other accelerometer post and I think the wrapper could be written a little prettier I guess so maybe this would do the same?

function wrapper()  
 if ball.x \< (centerX - xFinal + ball.width/2) then   
 ball.x = (centerX - xFinal + ball.width/2)  
  
 elseif ball.x \> (centerX + xFinal - ball.width/2) then   
 ball.x = (centerX + xFinal - ball.width/2)  
  
 elseif ball.y \< (centerY - yFinal + ball.width/2) then   
 ball.x = (centerY - yFinal + ball.width/2)  
  
 elseif ball.y \> (centerY + yFinal - ball.width/2) then   
 ball.x = (centerY + yFinal - ball.width/2)  
  
 end  
end  

Can anyone give me some input on this subject if it works or not as I am dying to find out.

thanks everyone.
/David [import]uid: 34126 topic_id: 9781 reply_id: 36074[/import]

Have anyone had any luck with this, I figured this could be useful since I believe most accelerometer games use a wrapper of some kind right?

I’m starting to believe this is a bit overkill for circular wrapper, maybe it could have been done in a simpler way like the one I found on Peach Pellens site.

Peach, that ain’t your real name right?

Cheers/ David [import]uid: 34126 topic_id: 9781 reply_id: 36157[/import]

I’m finally back to test this, let’s see how it goes.
David [import]uid: 34126 topic_id: 9781 reply_id: 37046[/import]

Ok, this is clearly not working, it seems like I’m just complicating things here…

So here’s what I want to do;

I’ve made a simple game where a ball is inside a circle and the player has to create a centrifugal motion by tilting in a rotation fashion. Make the ball gain momentum inside the wrapper, then when I want to release the ball and “throw” it away I tap the display so a piece of the circle remove it self so the ball can fly out and hit some boxes.

It’s like the Bullet sample but instead of fire the bullet on Touch, the ball has to gain momentum inside the circle and then release it.

I just have the square wrapper working and that doesn’t work with my idea, can someone please help me with the circleWrapper?

Thanks
David

[import]uid: 34126 topic_id: 9781 reply_id: 37048[/import]

[lua]
local physics = require “physics”
physics.start()
–physics.setDrawMode(“hybrid”)

local bg = display.newRect(0,0,480,320)
bg:setFillColor(0)

local circlePart = {}

local function myFF(x,y,w,h,angle1,angle2,r,g,b)
local xStart,yStart = x,y
local startAngle = math.rad(angle1) or math.rad(0)
local endAngle = math.rad(angle2) or math.rad(360)
local r = r or 255
local g = g or 255
local b = b or 255
for i=startAngle,endAngle,0.009 do
circlePart[#circlePart + 1] = display.newLine(xStart + w * math.cos(i),yStart - h*math.sin(i),xStart + w * math.cos(i) - 1,yStart - h*math.sin(i) -1)
circlePart[#circlePart]:setColor(r,g,b)
physics.addBody(circlePart[#circlePart],“static”,{bounce = 0,density = 1000})
end
end

myCircle = myFF(240,160,100,100,0,360,255,255,0)

local myBall = display.newCircle(0,0,20,20)
myBall.x = 240
myBall.y = 160
physics.addBody(myBall,{radius = 20,bounce = 0.1})

local function onTilt( event )
physics.setGravity( 10 * event.xGravity, -10 * event.yGravity )
end

Runtime:addEventListener( “accelerometer”, onTilt )

local function removeCircle()
for i=1,#circlePart do
circlePart[i]:removeSelf()
circlePart[i] = nil
end
end
bg:addEventListener(“tap”,removeCircle)[/lua]

:slight_smile: cheers [import]uid: 12482 topic_id: 9781 reply_id: 37096[/import]

Thanks for the reply, I made some changes and added a few images. I’ve tried to modify this code to work with just the accelerometer but I can’t get the wrapper to work without the physics.

How do I write a circle wrapper for a non physics game, like the wrapper at the top of the thread for a square?

I want to learn how to write the wrapper based on what radius I define.
Thanks for the code, it helped a lot.

[code]

local physics = require “physics”
physics.start()
physics.setGravity(0.0, 0,0)
–physics.setDrawMode(“hybrid”)

display.setStatusBar(display.HiddenStatusBar)
system.setAccelerometerInterval( 100 )

local centerX = display.contentWidth/2;
local centerY = display.contentHeight/2;
local _W = display.contentWidth;
local _H = display.contentHeight;

local bg = display.newImageRect(“bg.png”, 480,320)
bg:setReferencePoint(display.CenterReferencePoint);
bg.x = centerX;
bg.y = centerY;

local circlePart = {}
– This is the radius of the my image (myBase) which is like a wheel but I subtracted
local halfWidth = 102;
local halfHeight = 102;

local function myFF(x,y,w,h,angle1,angle2,r,g,b)
local xStart,yStart = x,y
local startAngle = math.rad(angle1) or math.rad(0)
local endAngle = math.rad(angle2) or math.rad(360)
local r = r or 255
local g = g or 255
local b = b or 255
for i=startAngle,endAngle,0.009 do
circlePart[#circlePart + 1] = display.newLine(xStart + w * math.cos(i),yStart - h*math.sin(i),xStart + w * math.cos(i) - 1, yStart - h*math.sin(i) -1)
circlePart[#circlePart]:setColor(r,g,b)
physics.addBody(circlePart[#circlePart],“static”,{bounce = 0,density = 1000})
end
end

myCircle = myFF(display.contentWidth/2, display.contentHeight/2, halfWidth, halfHeight,0,360,255,255,0)
–myCircle:setReferencePoint(display.CenterReferencePoint)

local myBase = display.newImageRect(“myBase.png”, 228, 228)
myBase:setReferencePoint(display.CenterReferencePoint);
myBase.x = centerX;
myBase.y = centerY;

local myBall = display.newImageRect(“bubbleSmall.png”, 32, 32)
myBall:setReferencePoint(display.CenterReferencePoint);
myBall.x = centerX;
myBall.y = centerY
physics.addBody(myBall,{radius = 16, bounce = 0.1})

local function onTilt( event )
physics.setGravity( ( 9.8 * event.xGravity ), ( -9.8 * event.yGravity ) )
end

Runtime:addEventListener( “accelerometer”, onTilt )

local function removeCircle()
for i=1,#circlePart do
circlePart[i]:removeSelf()
circlePart[i] = nil
end
end
bg:addEventListener(“tap”,removeCircle)
[/code] [import]uid: 34126 topic_id: 9781 reply_id: 37161[/import]

I tried to break the code apart so I could make a circleWrapper that works without physics but when I tried to do it like the screen wrapper the code does not work.

Can someone please help me make the wrapper so myBall stays inside the circle when I tilt the device.

[code]
display.setStatusBar(display.HiddenStatusBar)
system.setAccelerometerInterval( 100 )

local centerX = display.contentWidth/2;
local centerY = display.contentHeight/2;
local _W = display.contentWidth;
local _H = display.contentHeight;

local halfWidth = 114;
local halfHeight = 114;

local acc = {}
– The ring the ball can not go outside.
local circle = display.newCircle(centerX, centerY, halfWidth, halfHeight)
circle:setReferencePoint(display.CenterReferencePoint);
circle:setFillColor( 123, 123, 123, 0)
circle:setStrokeColor(211, 199, 1 )
circle.strokeWidth = 2

local myBall = display.newCircle(centerX, centerY, 16, 16)
myBall:setReferencePoint(display.CenterReferencePoint);
myBall:setFillColor( 232, 111, 255)

function acc:accelerometer(event)
myBall.x = centerX + (centerX * event.xGravity);
myBall.y = centerY - (centerY * event.yGravity);
end

Runtime:addEventListener( “accelerometer”, acc )
–[[
function circleWrapper(x,y,w,h,angle1,angle2)

local xStart,yStart = x,y
local startAngle = math.rad(angle1) or math.rad(0)
local endAngle = math.rad(angle2) or math.rad(360)
i = startAngle,endAngle

if myBall.x < (xStart + w * math.cos(i),yStart - h*math.sin(i),xStart + w * math.cos(i) - 1, yStart - h*math.sin(i) -1) then
myBall.x = (xStart + w * math.cos(i),yStart - h*math.sin(i),xStart + w * math.cos(i) - 1, yStart - h*math.sin(i) -1)
end

if myBall.x > (xStart - w * math.cos(i),yStart + h*math.sin(i),xStart - w * math.cos(i) + 1, yStart + h*math.sin(i) 1) then
myBall.x = (xStart - w * math.cos(i),yStart + h*math.sin(i),xStart - w * math.cos(i) + 1, yStart + h*math.sin(i) 1)
end

if myBall.y < (xStart + w * math.cos(i),yStart - h*math.sin(i),xStart + w * math.cos(i) - 1, yStart - h*math.sin(i) -1) then
myBall.y = (xStart + w * math.cos(i),yStart - h*math.sin(i),xStart + w * math.cos(i) - 1, yStart - h*math.sin(i) -1)
end

if myBall.y > (xStart - w * math.cos(i),yStart + h*math.sin(i),xStart - w * math.cos(i) + 1, yStart + h*math.sin(i) 1) then
myBall.y = (xStart - w * math.cos(i),yStart + h*math.sin(i),xStart - w * math.cos(i) + 1, yStart + h*math.sin(i) 1)
end

end
myBall = circleWrapper(display.contentWidth/2, display.contentHeight/2, halfWidth, halfHeight,0,360)
–]]

[/code] [import]uid: 34126 topic_id: 9781 reply_id: 37365[/import]