Make an enemy go against hero

Hi, guys.

I have an enemy somewhere on the screen and I want him to go against the hero then shoot an object(“ball” on the code) against that last. I tried using transition.to this way, but it didn’t work well:

[code]local function shoot()
if(enemy.x == 100)then
ball = display.newImage(“images/ball.png”);
ball.x, ball.y = enemy.x, enemy.y;
transition.to(ball, {x = hero.x, y = hero.y});
end
end

local function moveToHero()
transition.to(enemy, {time = 2000, x=100, y=display.contentCenterY + 50, onComplete = shoot});
end
moveToHero();
[/code]

The problem using transition.to is that every enemy created shoots against the hero, even if that last one had already destroyed the enemy. In other words, even if the enemy has already been destroyed, the transition.to keeps working and a ball is always shot.

Can someone help me creating a function that works better than that?
Thanks. :smiley:
[import]uid: 162818 topic_id: 31975 reply_id: 331975[/import]

@wiler_camo,

#1 Maintain a reference to the transition handle in a variable attached to the enemy.

local function moveToHero() enemy.moveToTransition = transition.to(enemy, {time = 2000, x=100, y=display.contentCenterY + 50, onComplete = shoot}); end

Later, you can delete the enemy and at the same time cancel the active transition:

local function destroyEnemy()  
 if( enemy.moveToTransition) then  
 transition.cancel( enemy.moveToTransition )  
 end  
  
 enemy:removeSelf()  
 enemy = nil  
end  

I see some other possible problems with your code, but I’ll post them below…

-Ed
[import]uid: 110228 topic_id: 31975 reply_id: 127458[/import]

I’ll try that then leave a comment.
Tell something: is that “moveToTransition” a variable created like “local moveToTransition”? [import]uid: 162818 topic_id: 31975 reply_id: 127459[/import]

If I understand correct, your destroyed enemies are still firing after death. My solution would be to cancel the transition used in moveToHero(). Here’s my suggestions:

[lua]----Previous Code Here-----

local function moveToHero ( )
enemy.transition = transition.to(enemy, {time = 2000, x=100, y=display.contentCenterY + 50, onComplete = shoot});
end

– Call this when destroying enemies
local function destroyEnemy ( enemy )
if ( enemy.transition ) then
– This prevents onComplete function from performing (your problem I believe)
transition.cancel ( enemy.transition )
enemy.transition = nil
end
enemy:removeSelf ( )
end

moveToHero ( )[/lua]

– EDIT: HAHA, someone already beat me! Good community support here! [import]uid: 7721 topic_id: 31975 reply_id: 127461[/import]

kkkkk Vou tentar desse jeito aí também, @ETdoFresh. [import]uid: 162818 topic_id: 31975 reply_id: 127462[/import]

As I mentioned above, I think there may be some other issues with your game/code.

If you are creating multiple enemies and are not careful about how you use globals, you will get into problems.

However, there is an easy way to be sure your code works (once you understand the syntax).

Here is a suggested change (with some additions; #'d comments explained after code):

  
local function createEnemy() -- #1   
  
 local curEnemy -- #2  
  
 -- Add your own code to make an enemy object here   
 -- Be sure to store a reference to the enemy in curEnemy local created above  
  
 -- Now, attach a set of functions and methods to your enemy like this:  
  
 curEnemy.shoot = function() -- #3  
  
 local thisEnemy = curEnemy -- #4  
  
 if(thisEnemy == 100) then  
  
 ball = display.newImage("images/ball.png");  
  
 ball.x, ball.y = thisEnemy.x, thisEnemy.y;  
  
 transition.to(ball, {x = hero.x, y = hero.y});  
  
 end  
 end  
  
  
 function curEnemy:moveToHero() -- #5  
  
 self.myTransition = transition.to(self, {time = 2000, x=100, y=display.contentCenterY + 50, onComplete = self.shoot});  
  
 end  
  
 function curEnemy:destroy() -- #6  
  
 if( self.myTransition ) then  
  
 transition.cancel( self.myTransition )  
  
 end  
  
 self:removeSelf()   
 end  
 return curEnemy - #7  
end  
  1. It is usually better to have a ‘builder’ function and to call a builder when you need it rather than embed building code in other logic. This makes builder code easy to maintain and supplement.

  2. The first thing to do is to make a local variable to contain your new build object (the enemy). This makes it easy to modify and to attach functions/methods to.

  3. This is a function attached to the current enemy we are making. You call the function like this: var.shoot() , where var is a variable containg a reference to the enemy object. (See more code examples below.)

  4. When the shoot() function is being defined, we store a copy of the curEnemy reference in a local variable within the new function. Every time a new enemy is created, the code to create the shoot() function is executed and every enemy gets its own shoot function with a unique refernce to that enemy inside it. We have to do this, because when you call a function attached to an object, the function doesn’t know what object its parent is. Furthermore, the callback part of transition only takes functions not methods. i.e. We will give the callback reference enemy.shoot(), but it won’t know which one. Storing a refernce inside the function when we write/generate it solves this connundrum. Note: This is a bit redundant in that I could simply have refered to ‘curEnemy’ in all of the shoot() function, but I like to use a local reference for clarity sake.

  5. moveHero() is a method call. Later we can call it like this: var:moveToHero() , where var is a variable containg a reference to the enemy object. When we do this, moveHero is automatically passed a variable ‘self’ containing a reference to the enemy object stored in var.

  6. Here we add a method named destroy(). It contains code to cancel any oustanding transtion and then remove the enemy object from the scene.

  7. Lastly, we return ‘curEnemy’ from our builder function. (See below to understand how this call comes together.)

Now, we can use our builder and its attached methods to do some work:

  
local myEnemy = createEnemy()  
  
myEnemy:moveToHero()  
.... Later, we can destroy this enemy (as long as we have kept track of the object ID in 'myEnemy' somehow.):  
myEnemy:destroy()  
  

I hope this is helpful and not confusing. Please note: In the future I will be putting together tutorials on game making and mechanics. So if you are interested, keep track of my RSS feed or visit my site occasionally.
Cheers,
Ed
Roaming Gamer, LLC.
SSK for Corona SDK (github) (videos)

[import]uid: 110228 topic_id: 31975 reply_id: 127466[/import]

@wiler_camo,

#1 Maintain a reference to the transition handle in a variable attached to the enemy.

local function moveToHero() enemy.moveToTransition = transition.to(enemy, {time = 2000, x=100, y=display.contentCenterY + 50, onComplete = shoot}); end

Later, you can delete the enemy and at the same time cancel the active transition:

local function destroyEnemy()  
 if( enemy.moveToTransition) then  
 transition.cancel( enemy.moveToTransition )  
 end  
  
 enemy:removeSelf()  
 enemy = nil  
end  

I see some other possible problems with your code, but I’ll post them below…

-Ed
[import]uid: 110228 topic_id: 31975 reply_id: 127458[/import]

I’ll try that then leave a comment.
Tell something: is that “moveToTransition” a variable created like “local moveToTransition”? [import]uid: 162818 topic_id: 31975 reply_id: 127459[/import]

If I understand correct, your destroyed enemies are still firing after death. My solution would be to cancel the transition used in moveToHero(). Here’s my suggestions:

[lua]----Previous Code Here-----

local function moveToHero ( )
enemy.transition = transition.to(enemy, {time = 2000, x=100, y=display.contentCenterY + 50, onComplete = shoot});
end

– Call this when destroying enemies
local function destroyEnemy ( enemy )
if ( enemy.transition ) then
– This prevents onComplete function from performing (your problem I believe)
transition.cancel ( enemy.transition )
enemy.transition = nil
end
enemy:removeSelf ( )
end

moveToHero ( )[/lua]

– EDIT: HAHA, someone already beat me! Good community support here! [import]uid: 7721 topic_id: 31975 reply_id: 127461[/import]

kkkkk Vou tentar desse jeito aí também, @ETdoFresh. [import]uid: 162818 topic_id: 31975 reply_id: 127462[/import]

As I mentioned above, I think there may be some other issues with your game/code.

If you are creating multiple enemies and are not careful about how you use globals, you will get into problems.

However, there is an easy way to be sure your code works (once you understand the syntax).

Here is a suggested change (with some additions; #'d comments explained after code):

  
local function createEnemy() -- #1   
  
 local curEnemy -- #2  
  
 -- Add your own code to make an enemy object here   
 -- Be sure to store a reference to the enemy in curEnemy local created above  
  
 -- Now, attach a set of functions and methods to your enemy like this:  
  
 curEnemy.shoot = function() -- #3  
  
 local thisEnemy = curEnemy -- #4  
  
 if(thisEnemy == 100) then  
  
 ball = display.newImage("images/ball.png");  
  
 ball.x, ball.y = thisEnemy.x, thisEnemy.y;  
  
 transition.to(ball, {x = hero.x, y = hero.y});  
  
 end  
 end  
  
  
 function curEnemy:moveToHero() -- #5  
  
 self.myTransition = transition.to(self, {time = 2000, x=100, y=display.contentCenterY + 50, onComplete = self.shoot});  
  
 end  
  
 function curEnemy:destroy() -- #6  
  
 if( self.myTransition ) then  
  
 transition.cancel( self.myTransition )  
  
 end  
  
 self:removeSelf()   
 end  
 return curEnemy - #7  
end  
  1. It is usually better to have a ‘builder’ function and to call a builder when you need it rather than embed building code in other logic. This makes builder code easy to maintain and supplement.

  2. The first thing to do is to make a local variable to contain your new build object (the enemy). This makes it easy to modify and to attach functions/methods to.

  3. This is a function attached to the current enemy we are making. You call the function like this: var.shoot() , where var is a variable containg a reference to the enemy object. (See more code examples below.)

  4. When the shoot() function is being defined, we store a copy of the curEnemy reference in a local variable within the new function. Every time a new enemy is created, the code to create the shoot() function is executed and every enemy gets its own shoot function with a unique refernce to that enemy inside it. We have to do this, because when you call a function attached to an object, the function doesn’t know what object its parent is. Furthermore, the callback part of transition only takes functions not methods. i.e. We will give the callback reference enemy.shoot(), but it won’t know which one. Storing a refernce inside the function when we write/generate it solves this connundrum. Note: This is a bit redundant in that I could simply have refered to ‘curEnemy’ in all of the shoot() function, but I like to use a local reference for clarity sake.

  5. moveHero() is a method call. Later we can call it like this: var:moveToHero() , where var is a variable containg a reference to the enemy object. When we do this, moveHero is automatically passed a variable ‘self’ containing a reference to the enemy object stored in var.

  6. Here we add a method named destroy(). It contains code to cancel any oustanding transtion and then remove the enemy object from the scene.

  7. Lastly, we return ‘curEnemy’ from our builder function. (See below to understand how this call comes together.)

Now, we can use our builder and its attached methods to do some work:

  
local myEnemy = createEnemy()  
  
myEnemy:moveToHero()  
.... Later, we can destroy this enemy (as long as we have kept track of the object ID in 'myEnemy' somehow.):  
myEnemy:destroy()  
  

I hope this is helpful and not confusing. Please note: In the future I will be putting together tutorials on game making and mechanics. So if you are interested, keep track of my RSS feed or visit my site occasionally.
Cheers,
Ed
Roaming Gamer, LLC.
SSK for Corona SDK (github) (videos)

[import]uid: 110228 topic_id: 31975 reply_id: 127466[/import]