I'm trying to do something very simple as I'm new to Corona SDK, but I'm having a lot of issues with it.
What I'm trying to accomplish is when a user "swipes", "flings", "flicks" a certain area of the screen (an image set to half the screen) a ball in the middle of the screen moves in that direction at a set speed. No physics or anything special. So basically, if you swipe the image at an angle, the ball will move to that angle and eventually off the screen unless you "swipe" the ball again in a different direction.
What i have so far is:
physics.addBody( ball, "dynamic" )
function flick(event)
if event.phase == "moved" then
ball:applyForce( (ball.x) * 0.5, (ball.y) * 0.5, ball.x, ball.y )
end
end
Currently when you move the ball it just shoots in one direction (the 0.5) how would i get the direction "flung"?
I'm new to corona and still trying to figure out the touch events. Still a little confusing to me.
Any help and advice is appreciated! Thanks everyone!
You need to track where the touch starts and ends: this is the flick. The difference between start and end along x and y will give direction of motion of ball. If ball speed depends on how fast user flicked, you need to track time too. Also, I'm not sure why you are making the force proportional to the object's position: this means that if the object is at 0,0 there is no force, that's probably not what you want. You would just want a force proportional to the flick vector. The amount of time would determine the time. It would look something like this:
local flickStartTime = 0
local function touch(event)
if event.phase == "began" then
flickStartTime = system.timer()
elseif event.phase == "ended" then
local flickDuration = system.timer() - flickStartTime
if flickDuration <= 0 then return end -- ignore flick
local speedX = (event.xStart - event.x)/flickDuration
local speedY = (event.yStart - event.y)/flickDuration
local coef = 0.1 -- adjust this via "trial and error" so moves at "reasonable" speed
-- only react to flick if it was large enough
if math.abs(event.xStart - event.x) > 10 or math.abs(event.yStart - event.y) > 10 then
ball:applyForce( coef * speedX, coef * speedY, ball.x, ball.y )
end
end
end
However you said you don't want any physics, yet you apply force, do you mean you just want to set the velocity? Then instead of applyForce you would call setLinearVelocity(speedX, speedY)
local speedX = (event.xStart - event.x)/flickDuration
local speedY = (event.yStart - event.y)/flickDuration
local coef = 0.1 -- adjust this via "trial and error" so moves at "reasonable" speed
-- only react to flick if it was large enough
if math.abs(event.xStart - event.x) > 10 or math.abs(event.yStart - event.y) > 10 then
ball:setLinearVelocity( coef * speedX, coef * speedY )
end
By the looks of it, flick is a touch listener. You must filter the event that is passed on, and determine which direction the user swiped. Read more about touch listeners here
What you are interested in, is the xStart and yStart properties, and measure how much the user moved, something like this:
local function flick(event)
if event.phase == "moved" then
local diffX = event.xStart - event.x
local diffY = event.yStart - event.y
if math.abs(diffX) > 10 or math.abs(diffY) > 10 then
ball:applyForce( (ball.x) * diffX, (ball.y) * diffY, ball.x, ball.y )
end
end
end
Related
So I am trying to make a ball fall and when it is touched, I need it to bounce in the direction the ball is touched. Right now all I have it doing is going straight up, but if I were to tap on the edge of the ball, it needs to start heading in that direction but also up.
The game is a soccer keep ups game, you tap and the ball goes up, if it hits the ground, the score resets. Simple. But I cannot seem to find any examples on how to have the ball roll side to side as well as upwards.
local ball = display.newImageRect("soccerball.png", 112, 112)
ball.x = display.contentCenterX
ball.y = display.contentCenterY
physics.addBody(ball, "dynamic", {radius=50, bounce=0.3})
local function pushBall(event)
ball:applyLinearImpulse(0, -0.75, ball.x, ball.y)
tapCount = tapCount + 1
tapText.text = tapCount
end
ball:addEventListener("touch", pushBall)
Code above only allows the ball to go straight up. No roll.
Thank you for your help.
Try
function ball:touch( event )
local phase = event.phase
if ( phase == 'ended' ) then
local x, y = ball.x - event.x, ball.y - event.y
self:applyLinearImpulse( x / 30, -math.abs(y) / 30, self.x, self.y )
--tapCount = tapCount + 1
--tapText.text = tapCount
end
return true
end
ball:addEventListener("touch")
local function shoot( event )
local x, y = event.x, event.y
rotateShip(x, y)
local laser = display.newImage("Images/laser.png")
laser.x = player.x
laser.y = player.y
transition.to(laser, {time=300, x=x, y=y, onComplete=shotDone})
end
^ That is my code so far. It shoots the object until it reaches the click position. What I want it to do is continue on past the click until it reaches the edge of the screen. I already have the angle of the shot stored in a variable that for the sake of this we will call "shotAngle"
Any help would be greatly appreciated!
Liv :)
Okey, so first of all: you should not do this movement with transition.to(). As I assume you make a game where you can shoot laser projectiles. Way easier would be moving all of the projectiles you have currently in game by velocity*dt (in their current moving direction) where dt is amount of time passed since last frame. Then you can just check if they are out of playground and delete them if yes. But if you really want to do it this way...
Oh boy, here we go!
local function shoot(event)
local width, height -- Size of playground
local ex, ey = event.x, event.y -- Where player have clicked/tapped/etc
local px, py = player.x, player.y -- Current position of player
local speed -- Projectile speed in [pixels per milisecond]
-- Our laser projectile
local laser = display.newImage("Images/laser.png")
laser.x, laser.y = player.x, player.y
-- Borders: bx, by
local bx, by = width, height
if ex < px then
bx = 0
end
if ey < py then
by = 0
end
-- Let's get our target coordinates
local tx, ty = bx
ty = ((py-ey)/(px-ex))*bx+py-((py-ey)/(px-ex))*px
if ty > height or ty < 0 then
ty = by
tx = (by-py+((py-ey)/(px-ex))*px)/((py-ey)/(px-ex))
end
-- Let's get animation time now!
local distance = math.sqrt((tx-px)*(tx-px)+(ty-py)*(ty-py))
local time = distance/speed
-- Now, just shoot
transition.to(laser, {time=time, x=tx, y=ty, onComplete=shotDone})
end
Hi Everyone,
I would like know one thing :
I want to make this rectangle moving from the left side to the right side with physics and loop, and make it disappear when is out the leftscreen, and make reappear it in the right side,
This is what I've made in my code but I would like know if there is another easiest way to do it.
Is it better to use transition.to ?
Ps : My game is an endless runner game where the player jump from the floor to rectangles in the air
if someone have tutorial for this, I get it ! thank you
thanks every one for all
local physics = require( "physics" )
physics.start()
physics.setDrawMode( "hybrid")
local _x = display.contentCenterX
local _y = display.contentCenterY
local speed = 10
local GroupMur1 = display.newGroup()
local Mur1 = display.newRect(680,25,680,25)
Mur1.x = _x +900
Mur1.y = _y +80
physics.addBody(Mur1, "static")
GroupMur1:insert(Mur1)
local a =1
local function update ()
if(a==1)then updateMur1() end
if(a==2)then updateMur2() end
end
function updateMur1 ()
GroupMur1.x =GroupMur1.x - speed
if(GroupMur1.x < -2000) then
GroupMur1:remove(1)
a=2
end
end
function updateMur2()
GroupMur1:insert(Mur1)
physics.addBody(Mur1, "static")
GroupMur1.x = _x + 900
a=1
end
timer.performWithDelay(1, update, -1)
Well it's true that the transition.to is really useful and easy to use, but if you want to use physics, then use the applyLinearImpulse(), which is going to be easier if you want to use also collision detection. And once the rectangle is off screen, use the if and then function. It would be something like this:
if object.x > 500 then -- for example with a rectangle of 20 by 20
object.x = -20
end
To extend what #Fannick said, which should work by the way, the generic way to trigger this (for any object of any size) would be the code below. For this, I assume you have object.anchorX = 0 or object:setReferencePoint(display.CenterLeftReferencePoint) depending on your SDK version (the former is for v2 and the latter is for v1 - This link should help clear up differences)
--if the object is past the edge (screenOriginX used to scale for bigger devices)
if object.x > (display.contentWidth - display.screenOriginX) then
object.x = 0 + display.screenOriginX - object.contentWidth
end
If you have object.anchorX = 0.5 or object:setReferencePoint(display.CenterReferencePoint) (or haven't set either - both of these are the defaults) it would be:
if object.x > (display.contentWidth + (object.contentWidth/2) - display.screenOriginX) then
object.x = 0 + display.screenOriginX - (object.contentWidth/2)
end
For object.anchorX = 1 or object:setReferencePoint(display.CenterRightReferencePoint) it would be:
if object.x > (display.contentWidth + object.contentWidth - display.screenOriginX) then
object.x = 0 + display.screenOriginX
end
Hope you find the answer if you haven't already!
Cush
thanks both of you guy;
I've used the velocity to make the rectangle start to move and a collision to make 'em disappear
All your answers help me to understand better corona SDK !
Hi I'm new to Corona SDK. I hope someone can help me out.
I have an object (called furry) dropping from the sky, using the physics engine of the Corona SDK.
When this object Furry is half way the screen I would like to play a sound effect (wee.mp3).
I'm trying to update furry.x and furry.y to control for the updated location. But I'm not sure how to do this as the physics engine updates the location based on gravity.
I hope the code below is sufficient to help me.
centerX = display.contentWidth * .5
centerY = display.contentHeight * .5
local furry = display.newImage("flurry.png")
furry.x = centerX-300
furry.y = centerY-1000
physics.addBody(furry, "dynamic", physicsData:get("flurry"))
if furry.x == centerX then
audio.play(wee)
end
So how can I get after the game has started the updated locations (x, y) of my object Furry?
you can use Runtime Listener enterFrame to detect the object location see the code below
physics = require("physics")
physics.start()
centerX = display.contentWidth * .5
centerY = display.contentHeight * .5
local function listener( event )
local furry = display.newCircle(10,10,10)
furry.x = math.random(1, display.contentWidth)
furry.y = 10
physics.addBody(furry, "dynamic")
local function removeObject()
if furry.y > centerY then
furry:removeSelf()
Runtime:removeEventListener("enterFrame", removeObject)
end
end
Runtime:addEventListener("enterFrame", removeObject)
end
timer.performWithDelay( 500, listener ,0)
I am working on a game in corona. I want to fire a bullet when a user swipes their finger on an object. The further he swipes, the further the the bullet should go. I worked on this and on tap event the bullet is fired, there are two functions start projectile and game loop, start projectile is used to fire projectile and game loop is used to translate the weapon, but I can't understand how to aim for the target using finger swipe. Please give me any suggestions, thanks...
Code for what has been achieved so far is below
local function startprojectile(event)
gameIsActive=true
local firetimer
local getobj=event.target
local getxloc=getobj.x
local getyloc=getobj.y
local function firenow()
if gameIsActive=false then
timer.cancel(firetimer)
firetimer=nil
else
local bullet=display.newImageRect("object.png",50,60);
bullet.x=getxloc-50; bullet.y=getyloc-50
bullet.type=bullet1
physics.addBody(bullet,{isSensor=true})
weaponGroup:insert(bullet)
end
gameIsActive=false
end
firetimer.timer.performWithDelay(650,firenow)
end
local function gameloop()
local i
for i=weaponGroup.numChildren,1,-1 do
local weapon=weaponGroup[i]
if weapon ~=nil and weapon.x ~=nil
then
weapon:translate(-20,0)
end
end
You can get the angle that the bullet should be fired by using the built in lua function
startX, startY = player.x, player.y
dir = math.atan2(( swipeY - player.y ), ( swipeX - player.x ))
bulletDx = bullet.speed * math.cos(dir)
bulletDy = bullet.speed * math.sin(dir)
table.insert( bullet, { x = startX, y = startY, dx = bulletDx, dy = bulletDy } )
You can change the variable from swipe Y to whatever Corona uses (I don't code with it).
I'm assuming you know how to move the bullet, but if not,
for i, v in ipairs( bullet ) do
bullet.x = bullet.x + bullet.dx * dt
bullet.y = bullet.y + bullet.dy * dt
end