Adding enemy knockback

NOTE: I am avoiding the physics plugin for “unexplained reasons” (not going into specifics).

So I have a transition where an enemy is following the play:

transition.to(enemy, {time=math.random(2000,5000),x=player.x-50,y=player.y-50,transition=easing.inOutBounce, tag="goingtoPlayer"})

To make this example simpler I have also a knockback button:

local knockback\_button = display.newCircle(display.contentCenterX+125,display.contentCenterY+150, 30)

When the user clicks on the button, I want the enemy to be knockbacked (in other words have its x and y cordinates to go back) and continue to follow player after the knockback.

I have managed to get the enemy knockbacked but cannot get it to resume following the player.

Anyone know how to do this?

The player by the way doesn’t move.

You need to cancel the ongoing transition, apply the knockback, and start a new transition after a moment (to allow knockback effect to occur and be seen).

If you don’t cancel the old one, it will simply keep updating the position of the enemy.

This is why I don’t use transitions to move enemies in action games.  Too complicated, not the best way to move, and not realistic.

I use physics movement instead.

Put this code in a function:

transition.to(enemy, {time=math.random(2000,5000),x=player.x-50,y=player.y-50,transition=easing.inOutBounce, tag="goingtoPlayer"})

sort of like this:

function enemy.moveToPlayer( self ) transition.to( self, { time = math.random(2000,5000), x = player.x-50,y = player.y-50, transition = easing.inOutBounce, tag = "goingtoPlayer" } ) end

Tip: Your time calculation is not great. Better to measure distance and make time a distance/speed value.

Now, to start it:

enemy:moveToPlayer()

Later if you apply kickback the code would look something like this:

transition.cancel( enemy ) -- apply kickback timer.peformWithDelay( 500, function() enemy:moveToPlayer() end )

You could also pause the transition. 

https://docs.coronalabs.com/api/library/transition/pause.html

( Tip: If you’re just finding out transition.* has a pause feature I think you should have read up on transition.* first.  Keep a link to the APIs in your browser menu bar: https://docs.coronalabs.com/api/)  %C2%A0%C2%A0)

This would simplify the issue to this code:

transition.pause( enemy ) -- apply kickback timer.peformWithDelay( 500, function() transition.resume( enemy ) end )

So I added what you put but the enemy doesnt get knockedback anymore

Here is my knockback code

local function knockdown() transition.cancel( enemy ) transition.to(enemy, {time=500,x=enemy.x-math.random(1,100),y=enemy.y-math.random(1,100),transition=easing.inOutBounce}) timer.performWithDelay(500,enemy:moveToPlayer()) end

I also changed all the transition times to 500.

EDIT: Sorry I meant that after adding the code, the enemy doesnt get knocked back.

Is my knockback code correct?

UPDATE

Perhaps I should use the physics plugin for this.

Anyway to add knockback while the enemy is moving(transitions) using the Physics plugin?

In this case, the knockback is caused by a bullet.

Define correct. 

There is code correctness and there is behavior correctness.

Behavior Correctness

This is subjective. i.e. If it doesn’t look or behave the way you want it to, then it isn’t correct.

Also, you haven’t described the whole sequence (bullet list would be good) of what a knockback should behave like.

Code Correctness

As far as the code… well it has a lot of assumptions so I don’t think it is great.

It assumes either there is only one enemy, or enemy is in scope, neither of which I think is guaranteed.

Better to make a function attached to the enemy itself when you make the enemy:

function enemy.knockback( self ) transition.cancel( self ) transition.to( self, {time=500,x=self.x-math.random(1,100),y=self.y-math.random(1,100),transition=easing.inOutBounce}) timer.performWithDelay(500, function() self:moveToPlayer() end ) end

Later called like this

enemy:knockback() 

Your code also assumes the player is  in scope.  I can’t help on this.  It totally depends on the structure of your game code.

Your timer.performDelay() call was wrong.  You didn’t use a closure.

Request

I find one detail of your code posts really hard to deal with.  You don’t use enough spaces.

Can you please start using spaces?

This makes double-click selecting code a pain in the butt and reading it a pain in the butt too.

This is bad:

 transition.to(self,{time=500,x=self.x-math.random(1,100),y=self.y-math.random(1,100),transition=easing.inOutBounce})

This is better  (more editable, and more legible):

 transition.to( self, { time = 500, x = self.x - math.random( 1, 100 ), y = self.y - math.random(1,100), transition = easing.inOutBounce } )

Thanks @roaminggamer.

I dont think this way of doing knockbacks is going to work.

I think I have use the physics plugin for this.

Thanks alot for your help!

and sorry for the lack of spaces.

You need to cancel the ongoing transition, apply the knockback, and start a new transition after a moment (to allow knockback effect to occur and be seen).

If you don’t cancel the old one, it will simply keep updating the position of the enemy.

This is why I don’t use transitions to move enemies in action games.  Too complicated, not the best way to move, and not realistic.

I use physics movement instead.

Put this code in a function:

transition.to(enemy, {time=math.random(2000,5000),x=player.x-50,y=player.y-50,transition=easing.inOutBounce, tag="goingtoPlayer"})

sort of like this:

function enemy.moveToPlayer( self ) transition.to( self, { time = math.random(2000,5000), x = player.x-50,y = player.y-50, transition = easing.inOutBounce, tag = "goingtoPlayer" } ) end

Tip: Your time calculation is not great. Better to measure distance and make time a distance/speed value.

Now, to start it:

enemy:moveToPlayer()

Later if you apply kickback the code would look something like this:

transition.cancel( enemy ) -- apply kickback timer.peformWithDelay( 500, function() enemy:moveToPlayer() end )

You could also pause the transition. 

https://docs.coronalabs.com/api/library/transition/pause.html

( Tip: If you’re just finding out transition.* has a pause feature I think you should have read up on transition.* first.  Keep a link to the APIs in your browser menu bar: https://docs.coronalabs.com/api/)  %C2%A0%C2%A0)

This would simplify the issue to this code:

transition.pause( enemy ) -- apply kickback timer.peformWithDelay( 500, function() transition.resume( enemy ) end )

So I added what you put but the enemy doesnt get knockedback anymore

Here is my knockback code

local function knockdown() transition.cancel( enemy ) transition.to(enemy, {time=500,x=enemy.x-math.random(1,100),y=enemy.y-math.random(1,100),transition=easing.inOutBounce}) timer.performWithDelay(500,enemy:moveToPlayer()) end

I also changed all the transition times to 500.

EDIT: Sorry I meant that after adding the code, the enemy doesnt get knocked back.

Is my knockback code correct?

UPDATE

Perhaps I should use the physics plugin for this.

Anyway to add knockback while the enemy is moving(transitions) using the Physics plugin?

In this case, the knockback is caused by a bullet.

Define correct. 

There is code correctness and there is behavior correctness.

Behavior Correctness

This is subjective. i.e. If it doesn’t look or behave the way you want it to, then it isn’t correct.

Also, you haven’t described the whole sequence (bullet list would be good) of what a knockback should behave like.

Code Correctness

As far as the code… well it has a lot of assumptions so I don’t think it is great.

It assumes either there is only one enemy, or enemy is in scope, neither of which I think is guaranteed.

Better to make a function attached to the enemy itself when you make the enemy:

function enemy.knockback( self ) transition.cancel( self ) transition.to( self, {time=500,x=self.x-math.random(1,100),y=self.y-math.random(1,100),transition=easing.inOutBounce}) timer.performWithDelay(500, function() self:moveToPlayer() end ) end

Later called like this

enemy:knockback() 

Your code also assumes the player is  in scope.  I can’t help on this.  It totally depends on the structure of your game code.

Your timer.performDelay() call was wrong.  You didn’t use a closure.

Request

I find one detail of your code posts really hard to deal with.  You don’t use enough spaces.

Can you please start using spaces?

This makes double-click selecting code a pain in the butt and reading it a pain in the butt too.

This is bad:

 transition.to(self,{time=500,x=self.x-math.random(1,100),y=self.y-math.random(1,100),transition=easing.inOutBounce})

This is better  (more editable, and more legible):

 transition.to( self, { time = 500, x = self.x - math.random( 1, 100 ), y = self.y - math.random(1,100), transition = easing.inOutBounce } )

Thanks @roaminggamer.

I dont think this way of doing knockbacks is going to work.

I think I have use the physics plugin for this.

Thanks alot for your help!

and sorry for the lack of spaces.