can you make an object fire towards where you touch

I want to make a cannon that will sit in the corner and fire bullets towards wherever you touch on the screen. can someone please help me develop the function that would fire the bullets toward wherever you press.

thanks. [import]uid: 75779 topic_id: 21800 reply_id: 321800[/import]

You’d do something like this;

[lua]local cannon = display.newRect( 0, 420, 40, 60 )

local function shoot (event)
local ball = display.newCircle( cannon.x, cannon.y, 20 )
transition.to(ball, {x=event.x, y=event.y})
end
Runtime:addEventListener(“tap”, shoot)[/lua]

This isn’t perfect but should give you a starting point.

Peach :slight_smile: [import]uid: 52491 topic_id: 21800 reply_id: 86560[/import]

Check out ludicrous software .com there is a great tutorial on the site for a missile defence game with a great pdf writeup to follow with source files at many stages. Everything you need to start is there.

http://www.ludicroussoftware.com/blog/2011/11/21/build-missile-command-with-the-corona-sdk/

One thing to note is this examples engine does not use delta time, which is the difference in the time it takes for each frame to complete, when this is thrown into the equations you get smoother performance. [import]uid: 118379 topic_id: 21800 reply_id: 86576[/import]

Yes that is perfecto gracias! [import]uid: 75779 topic_id: 21800 reply_id: 86655[/import]

local angle = (object.rotation-90)*0.0174532925 --covert to radians
local a, b = math.cos(angle)*500, math.sin(angle)*500 --make sure speed is always the same
bullet:applyLinearImpulse(a,b)

learn trig. Is good. [import]uid: 79135 topic_id: 21800 reply_id: 86667[/import]

@andrewscott

thanks thats some good stuff and I think ultimately what I’m looking for. I want the bullets to go from the cannon to wherever I press, but I dont want the bullet to stop where I pressed I want it to keep going and bounce around the walls for a few seconds at the same velocity until I remove it. I want all the bullets to fire at the same velocity too.

I tried putting your code into Peach’s code but I can’t get it to work. Can you see what is going wrong?
[lua]local cannon = display.newRect( 0, 420, 40, 60 )

local function shoot (event)
local ball = display.newCircle( cannon.x, cannon.y, 20 )
local angle = (ball.rotation-90)*0.0174532925 --covert to radians
local a, b = math.cos(angle)*500, math.sin(angle)*500 --make sure speed is always the same
ball:applyLinearImpulse(event.x,event.y, a,b)
end
Runtime:addEventListener(“tap”, shoot)[/lua] [import]uid: 75779 topic_id: 21800 reply_id: 86807[/import]

Change:
ball:applyLinearImpulse(event.x,event.y, a,b)
TO
ball:applyLinearImpulse( a,b, ball.x ,ball.y )

local angle = (ball.rotation-90)*0.0174532925
I imagine you want the cannons rotation for that. [import]uid: 79135 topic_id: 21800 reply_id: 86833[/import]

[lua]local cannon = display.newRect( 0, 420, 40, 60 )

local function shoot (event)
local ball = display.newCircle( cannon.x, cannon.y, 20 )
local angle = (cannon.rotation-90)*0.0174532925 --covert to radians
local a, b = math.cos(angle)*500, math.sin(angle)*500 --make sure speed is always the same
ball:applyLinearImpulse( a,b, ball.x ,ball.y )
end
Runtime:addEventListener(“tap”, shoot)[/lua]

It is coming back ‘attempt to call method ‘applyLinearImpulse’(a nil value)’.

any ideas what is going wrong?

Also cannon needs to be inserted into local angle yes? [import]uid: 75779 topic_id: 21800 reply_id: 86909[/import]

You need to require the physics class like so, also changed some bits, u can uncomment what you dont like etc:

[code]

physics = require(“physics”)
physics.start()
physics.setScale(50)
physics.setGravity(0,0)

local cannon = display.newRect( 0, 420, 40, 60 )

local function shoot (event)
local ball = display.newCircle( cannon.x, cannon.y, 20 )
physics.addBody( ball, “dynamic”, { density=2, friction=0, bounce=0.2 } )
–local angle = (cannon.rotation-90)*0.0174532925 --covert to radians /// THIS ONLY SHOOT AT THE ANGLE OF THE CANNON
–local a, b = math.cos(angle)*500, math.sin(angle)*500
ball:applyLinearImpulse((ball.x - event.x)*-0.5, (ball.y - event.y)* -0.5, ball.x, ball.y) --CHANGE NEGATIVE NUMBERS TO SUIT

– ball:applyLinearImpulse( a,b, ball.x ,ball.y )

ball.linearDamping = 10; – use this to damp e.g. apply opposite force (decelerate)
end
Runtime:addEventListener(“tap”, shoot)

[/code] [import]uid: 118379 topic_id: 21800 reply_id: 86916[/import]

@Beloudest

thankyou that works absolutely perfectly!!! [import]uid: 75779 topic_id: 21800 reply_id: 86919[/import]

Excellent. Just looking for something like this! Glad others figured it out for me. :wink: [import]uid: 11636 topic_id: 21800 reply_id: 88190[/import]

This is awesome no doubt. I am trying my arse off to figure out how to clean up all the bullets once they are shot…they are everywhere!! I have tried and tried but I alwys get the unable to index because it doesn’t see the bullet as global because the bullet is called out as local inside the function…HEEEEEEELLLLLP 8) [import]uid: 7346 topic_id: 21800 reply_id: 108205[/import]

also I have read the events and other docs, I guess I just dont get it??? [import]uid: 7346 topic_id: 21800 reply_id: 108206[/import]

My mathlib will likely help you here…

http://developer.anscamobile.com/code/maths-library

Also, here’s a snippet to do it - but provide your own ‘ship’ object and initialise the physics yourself…

[lua]require(“mathlib”)
local screenCenter = {x=display.contentCenterX,y=display.contentCenterY}
local degrees = angleOf( ship, screenCenter )
local rotated = rotateTo( {x=100,y=0}, degrees )
ship:setLinearVelocity( rotated.x, rotated.y )[/lua] [import]uid: 8271 topic_id: 21800 reply_id: 108208[/import]

@Horace:

Thats really awesome stuff. How does that help me to remove the bullets after they are shot and still on the screen? Or does it?
8)

here’s my rub:

local function shoot (event)
local ball = display.newCircle( killer1.x, killer1.y, 20 )
ball.myName = “ball”
physics.addBody( ball, “dynamic”, { density=2, friction=0, bounce=0.2 } )
–local angle = (cannon.rotation-90)*0.0174532925 --covert to radians /// THIS ONLY SHOOT AT THE ANGLE OF THE CANNON
–local a, b = math.cos(angle)*500, math.sin(angle)*500
ball:applyLinearImpulse((ball.x - event.x)*-0.5, (ball.y - event.y)* -0.5, ball.x, ball.y) --CHANGE NEGATIVE NUMBERS TO SUIT

– ball:applyLinearImpulse( a,b, ball.x ,ball.y )

ball.linearDamping = 0; – use this to damp e.g. apply opposite force (decelerate)

end
Runtime:addEventListener(“tap”, shoot)

—collision reporting for force or other events

function onLocalPreCollision( event, self)
– This new event type fires shortly before a collision occurs, so you can use this if you want
– to override some collisions in your game logic. For example, you might have a platform game
– where the character should jump “through” a platform on the way up, but land on the platform
– as they fall down again.

– Note that this event is very “noisy”, since it fires whenever any objects are somewhat close!

print( "preCollision: " … self.myName … " is about to collide with " … event.other.myName )

end

function onLocalPostCollision( event, self)
– This new event type fires only after a collision has been completely resolved. You can use
– this to obtain the calculated forces from the collision. For example, you might want to
– destroy objects on collision, but only if the collision force is greater than some amount.

if ( event.force > .000001) then
print( "postCollision force: " … event.force … ", friction: " … event.friction )
ball.parent:remove( ball )

local currentScore = getScore()
currentScore = currentScore + 300
setScore( currentScore )

– After ignore further collisions
self:removeEventListener( “postCollision”, self )
end

end

ball.preCollision = onLocalPreCollision
ball:addEventListener( “preCollision”, ball )

ball.postCollision = onLocalPostCollision
ball:addEventListener( “postCollision”, ball )

-----end collision reporting------ [import]uid: 7346 topic_id: 21800 reply_id: 108209[/import]

I dont need to rotate a cannon or anything, just trying to remove the bullets"balls" off the screen after either a timed process or after collission, but the local ball is inside the function and the listeners give me an index global error in the terminal…I am pulling my hair out trying to fins out how to do this. 8( [import]uid: 7346 topic_id: 21800 reply_id: 108210[/import]

Yeah, I’m afraid it doesn’t.

To remove the bullets you need some sort of reference. In this case, if you’re not deliberately maintaining a reference to the bullet objects, which is fine, you can find them in the display group by looping through it. Lets say you add bullet images to the ‘bullets’ display group:

[lua]local bullets = display.newGroup()
– do some work here to fire bullets etc

– now loop through the bullets, removing those off screen
function removeBullets()
for i=bullets.numChildren, 1, -1 do
local bullet = bullets[i]
if (bullet.x<0 or bullet.x>display.contentWidth or bullet.y<0 or bullet.y>display.contentHeight) then
bullet:removeSelf()
end
end
end[/lua]

The other thing you can do is put a timer on the bullet itself to have it remove itself, but you need to be careful that you’re not starting too many timers and that other events are removed before you remove the bullets. The code above should be called maybe once every 250 milliseconds:

[lua]local removebullettimer = timer.performWithDelay(250,removeBullets,0)[/lua]

One tip: Whenever I create a display object I always attach a value ‘.class’ to it and give it a name. eg:

[lua]bullet.class = “bullet”[/lua]

That way, if the disp obj gets mixed up with others, or I need to identify it in a collision listener, I can. [import]uid: 8271 topic_id: 21800 reply_id: 108213[/import]

I have this as you suggested, but still the bullets remain:

local function shoot (event)
local bullets = display.newGroup()
local bullet = display.newCircle( killer1.x, killer1.y, 20 )
bullet.class = “bullet”
physics.addBody( bullet, “dynamic”, { density=2, friction=0, bounce=0.2 } )
bullet:applyLinearImpulse((bullet.x - event.x)*-0.5, (bullet.y - event.y)* -0.5, bullet.x, bullet.y)
bullet.linearDamping = 0; – use this to damp e.g. apply opposite force (decelerate)

– now loop through the bullets, removing those off screen
function removeBullets()
for i=bullets.numChildren, 1, -1 do
local bullet = bullets[i]
if (bullet.x<0 or bullet.x>display.contentWidth or bullet.y<0 or bullet.y>display.contentHeight) then
bullet:removeSelf()
end
end
end

end
Runtime:addEventListener(“tap”, shoot) [import]uid: 7346 topic_id: 21800 reply_id: 108215[/import]

BTW Horace, thank you so much for your help, you rock! 8) [import]uid: 7346 topic_id: 21800 reply_id: 108217[/import]

You’re not calling the remove bullets function. Also, you’re declaring the group for them locally - that group needs to be global otherwise you’ll just have lots and lots of groups with no reference to them. Try this:

[lua]local bullets = display.newGroup() – declared locally but that makes it local to this file

– create a bullet in the group and send it off
local function shoot (event)
local bullet = display.newCircle( bullets, killer1.x, killer1.y, 20 ) – create bullet display object in the bullets display group (i don’t know what killer is)
bullet.class = “bullet” – just a useful reference for later
physics.addBody( bullet, “dynamic”, { density=2, friction=0, bounce=0.2 } )
bullet:applyLinearImpulse((bullet.x - event.x)*-0.5, (bullet.y - event.y)* -0.5, bullet.x, bullet.y) – I would use setLinearVelocity, but that’s me
bullet.linearDamping = 0; – use this to damp e.g. apply opposite force (decelerate)
end

Runtime:addEventListener(“tap”, shoot) – do the shooty stuff

– now loop through the bullets, removing those off screen
function removeBullets()
for i=bullets.numChildren, 1, -1 do – check the disp objs in the group
local bullet = bullets[i] – performance: getting a local ref to an obj in a table is quicker than referencing table indices all the time
if (bullet.x<0 or bullet.x>display.contentWidth or bullet.y<0 or bullet.y>display.contentHeight) then
– yeah, it’s off screen - as long as there are no timers or event handlers tied to the disp obj, this is fine
bullet:removeSelf()
end
end
end

– call the remover function once every 1/4 second, done for the whole group instead of each bullet, for performance
local removetimer = timer.performWithDelay(250,removeBullets,0)[/lua]

You NEED to read the tutorials about scope and the basics doc on the Corona site.

Btw, you weren’t adding the bullet objects to the ‘bullets’ display group either. Without being in that group there would be no objects to loop through. [import]uid: 8271 topic_id: 21800 reply_id: 108219[/import]