I've tried googling this however the tutorials only tell you how to make a projectile transition to a certain target.In my case I want it to travel towards the target but then carry on until the edge of the screen.
This is my current shoot function:
local function shoot()
--Invert coordinates
local x = screenWidth - x
local y = screenHeight - y
--a2+b2=c2
local sqDistance = ((x-centerX)*(x-centerX))+((y-centerY)*(y-centerY))
--Sqaure root it.
local dist = mSqrt(sqDistance);
--speed = d/t
distTime = dist/BULLET_SPEED
--if distTime is negative, this makes it positive
if distTime < 0 then
distTime = distTime -distTime -distTime
end
--Create the bullet
local shot = display.newRect(1,1,6,2)
shot.x = centerX; shot.y = centerY;
shot:setFillColor(240,200,0)
shot.rotation = angleBetween+90;
bulletGroup:insert(shot)
--Remove bullet
local function removeShot()
display.remove(shot)
shot = nil
end
--Move the bullet
transition.to(shot, {time = distTime, x = x, y = y, onComplete = removeShot})
end
Found out how to do this, unfortunately it seems you have to use the physics library.
When creating the bullet add this line:
physics.addBody(shot,"dynamic")
And use this instead of transition.to to move the bullet:
--Move the bullet
local xVelocity = (x-centerX)*BULLET_SPEED
local yVelocity = (y- centerY)*BULLET_SPEED
shot:setLinearVelocity(xVelocity,yVelocity)
Make the body a bullet by setting the object.isBullet = true to act as a bullet.
See reference here http://docs.coronalabs.com/api/type/Body/isBullet.html
Related
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
I have a table full of enemies and simple want them to move across the screen via gameLoop, however for some reason nothing seems to work. Its probably an easy fix but I have tried to fix it but am getting nowhere. Anyone know whats up?
gameLoop Function
local i
for i = 1, #enemies do--.numChildren,1, -1 do
local blocks = enemies[i]
if blocks ~= nil and blocks.x ~= nil then
enemyRate = 2.0 + (0.1 * wave)
transition.to( blocks, { time=1500, x=300} )
end
end
The Spawn Function
function spawnEnemy()
local spawnData = { -- Easily store spawns in a table to make it easier to add new enemies later
{name = "Blue", seq = "blueRect", frame = 3, imgSheet = imageSheetRectangle, seqData = sequenceDataRectangle},
{name = "Red", seq = "blueCross", frame = 1, imgSheet = imageSheetCross, seqData = sequenceDataCross},
{name = "Green", seq = "blueCirc", frame = 2, imgSheet = imageSheetCircle, seqData = sequenceDataCircle}
}
local xPos = display.contentWidth - 150
local r = math.random(1, #spawnData)
local sd = spawnData[r] -- get the spawn data for this enemy
local s = display.newSprite(sd.imgSheet, sd.seqData)
s.name = sd.name
physics.addBody(s, { isSensor = true })
s:setSequence(sd.seq)
s:setFrame(sd.frame)
s.y = display.contentHeight - 400
s.x = xPos
enemies[#enemies+1] = s
enemyGroup:insert(s)
In this related answer: transition.to( ) doesn't work within a function and with a Runtime:addEventListener( "enterFrame", method) listener in Corona / Lua you can see a similar issue as I stated above. You are creating an animation right as one is starting - making it seem as though it is not moving. As I suggested above, if it suits your game, begin the transition when you spawn the object; not every gameloop.
My collision detection works by getting intersection between rectangles and reversing the effect. This is happening during each frame. It works great except in the case where the player is sitting on top of a corner and jumps. every once in a while the vertical intersection is greater than the horizontal intersection which makes my player slide down the side of the platform. Any suggestions?
-- detect initial collision
if mathy.hasCollided(player, platform) then
local playerBoundaries = player:boundaries()
-- list of intersections between platform and player
local bottomBoundary = mathy.bottomBoundary( playerBoundaries, platform )
local topBoundary = mathy.topBoundary( playerBoundaries, platform )
local rightBoundary = mathy.rightBoundary( playerBoundaries, platform )
local leftBoundary = mathy.leftBoundary( playerBoundaries, platform )
local smallestDist = ""
local smallestBoundary
local boundaries = {
bottom = bottomBoundary,
top = topBoundary,
right = rightBoundary,
left = leftBoundary
}
-- get the smallest intersection (thats the side we're probably closest to)
for direction, boundary in pairs(boundaries) do
if not smallestBoundary then
smallestBoundary = boundary
smallestDist = direction
end
if smallestBoundary > boundary then
smallestBoundary = boundary
smallestDist = direction
end
end
-- reverse effects depending on collision location
if smallestDist == "bottom" then
player.desiredPos:add(diffX, -bottomBoundary)
player.velocity.y = 0
player.onGround = true
elseif smallestDist == "top" then
player.velocity.y = 250
player.desiredPos:add(0, topBoundary)
elseif smallestDist == "right" then
player.desiredPos:add(-rightBoundary, 0)
elseif smallestDist == "left" then
player.desiredPos:add(leftBoundary, 0)
end
end
Its hard to tell from the short clip, but I think the issue is a result of checking for the smallest intersection instead of checking for the intersection in the direction of the object's velocity. You could try something like this in place of the smallestBoundary loop:
local boundary = nil
if (player.velocity.y > 0) then
boundary = topBoundary
elseif (player.velocity.y < 0) then
boundary = bottomBoundary
elseif (player.velocity.x > 0) then
boundary = rightBoundary
elseif (player.velocity.x < 0) then
boundary = leftBoundary
end
Of course, this isn't as robust as it can be. You might also try to combine the two approaches and do something like this in place of the smallestBoundary loop:
local yMod = math.abs(player.velocity.y)
local xMod = math.abs(player.velocity.x)
local topMod = player.velocity.y > 0 and yMod or 1
local bottomMod = player.velocity.y < 0 and yMod or 1
local rightMod = player.velocity.x > 0 and xMod or 1
local leftMod = player.velocity.x < 0 and xMod or 1
local boundaries = {
bottom = (bottomMod / MAX_VELOCITY) * bottomBoundary,
top = (topMod / MAX_VELOCITY) * topBoundary,
right = (rightMod / MAX_VELOCITY) * rightBoundary,
left = (leftMod / MAX_VELOCITY) * leftBoundary
}
for direction, boundary in pairs(boundaries) do
if not smallestBoundary then
smallestBoundary = boundary
smallestDist = direction
end
if smallestBoundary > boundary then
smallestBoundary = boundary
smallestDist = direction
end
end
This will do exactly what you're doing now, but will adjust the size of the boundary (in context of the comparison only) by the velocity of the player in that direction. So if you're moving in x with -5 and in y with -10, downward collisions in the y plane will have twice the weight of leftward collisions in the x plane. Of course, there's always the other option of adjusting the player in every plane of collision:
if bottomBoundary > 0 then
player.desiredPos:add(diffX, -bottomBoundary)
player.velocity.y = 0
player.onGround = true
end
if topBoundary > 0 then
player.velocity.y = 250
player.desiredPos:add(0, topBoundary)
end
if rightBoundary > 0 then
player.desiredPos:add(-rightBoundary, 0)
end
if leftBoundary > 0 then
player.desiredPos:add(leftBoundary, 0)
end
This last method would make the most sense, except you don't seem to handle collisions in all directions uniformly, for whatever reason, so it might not fit your architecture.
Keep in mind that I'm not familiar with the framework you're using, so this code might not work out of the box. Also, this post assumes that +y is up, -y is down, +x is right, and -x is left.
I am trying to make a simple platform game, and obviously I need tile collision. The problem with the code I have so far is that it moves the character first, then checks to see if it is colliding with something, but sometimes it thinks its colliding at the wrong times depending on if I check the x-axis for collisions first or the y-axis first. Am I going about this the wrong way? Here's some code.
function checkCollision(val, axis, oldPos)
if axis == "x" and char.tX then
local tileX = math.ceil(val/absoluteTileSize)
local tileY = math.floor(oldPos/absoluteTileSize)
local tl, tr, bl ,br = getTouchingTiles(tileX, tileY)
local isOnFlatSurface = math.abs(oldPos/absoluteTileSize-tileY) <= .00001--might not be a good i
if isOnFlatSurface then
if tr.canCollide then
char.tX = nil
char.x = tileX * absoluteTileSize - absoluteTileSize
end
else
if br.canCollide then
char.tX = nil
char.x = tileX * absoluteTileSize - absoluteTileSize
end
end
elseif axis == "y" then
local tileX = math.ceil(oldPos/absoluteTileSize)
local tileY = math.floor(val/absoluteTileSize)
local tl, tr, bl ,br = getTouchingTiles(tileX, tileY)
if bl.canCollide or br.canCollide then
char.tY = nil
char.y = tileY * absoluteTileSize --// - absoluteTileSize
--/////////////idk why i don't need to subtract that but it works
elseif not char.tY then--start falling if walk off something
char.tY = love.timer.getTime()
char.yi = char.y
char.vyi = 0
end
end
end
local tileX = math.ceil(val/absoluteTileSize)
local tileY = math.floor(oldPos/absoluteTileSize)
It seems strange that you would use math.ceil for the x values and math.floor for the y. This may be why you are getting some strange occurrences. I would recommend this little debugging trick that may help you:
-- Since you are using LÖVE, this is what you would use:
love.graphics.setColor( 255, 0, 0, 255 )
love.graphics.rectangle( 'line', ( tileX - 1 ) * absoluteTileSize, ( tileY - 1 ) * absoluteTileSize, absoluteTileSize, absoluteTileSize )
-- assuming absoluteTileSize represents the width/height of the tiles?
This would go at the end of your drawing function and would draw a red box in the "tile" your player is currently inside.
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