[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]

## Hitpoints Started by Ceterge Dec 19 2019 04:51 AM

7 replies to this topic
hitpoints
[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

### Ceterge

[GLOBAL: userInfoPane.html]
Ceterge
• Observer

• 15 posts
• Corona SDK

Hello everyone! Could someone help me with adding lives for the "enemy"? I want the enemy to lose 1 hp after a collision.  I have many ideas but everyone doesn't work.

This is code for enemy :

local function enemy2()
local function miny2()
local newMine2 = display.newImageRect("mina2.png", 35, 35)
miny2HP = 3
newMine2.myName = "mina2"
local whereFrom2 = math.random(5)

if     ( whereFrom2 == 1 ) then
newMine2.x = 550
newMine2.y = 80
newMine2:setLinearVelocity(-150, 0)
elseif ( whereFrom2 == 2 ) then
newMine2.x = 550
newMine2.y = 148
newMine2:setLinearVelocity(-150, 0)
elseif ( whereFrom2 == 3 ) then
newMine2.x = 550
newMine2.y = 124
newMine2:setLinearVelocity(-150, 0)
elseif ( whereFrom2 == 4 ) then
newMine2.x = 550
newMine2.y = 176
newMine2:setLinearVelocity(-150, 0)
elseif ( whereFrom2 == 5 ) then
newMine2.x = 550
newMine2.y = 284
newMine2:setLinearVelocity(-150, 0)
end
end
timer.performWithDelay( 1000, miny2, 20 )
end
timer.performWithDelay( 10000, enemy2, 1 )

and this is my code for collision (bullet-enemy) :

local function onCollision2( event )

if ( event.phase == "began" ) then

local obj1 = event.object1
local obj2 = event.object2

if ( ( obj1.myName == "bullet" and obj2.myName == "mina2" ) or
( obj1.myName == "mina2" and obj2.myName == "bullet" ) )
then
display.remove( obj1 )
display.remove( obj2 )

end
end
end

I tried to separate obj1 and obj2 and add new functions, unfortunately my knowledge is too small, and I can't find anywhere to explain for beginners how to do it.

If someone could take a moment to explain me and I would be very grateful

Sorry for the mistakes, my english is not perfect

[TOPIC: post.html]
#2

### Alan PlantPot

[GLOBAL: userInfoPane.html]
Alan PlantPot
• Contributor

• 928 posts
• Corona SDK

You English is fine  , but you haven't explained exactly what is going wrong.

My best guess is that the enemy is disappearing after 1 hit, instead of losing 1hp? If that's the case, it's because you are removing the enemy every time it collides with a bullet:

if ( ( obj1.myName == "bullet" and obj2.myName == "mina2" ) or
( obj1.myName == "mina2" and obj2.myName == "bullet" ) )
then
display.remove( obj1 )
display.remove( obj2 )

end

What you want to do instead is delete only the bullet, and reduce the HP of the enemy by 1. If the HP reaches 0, then you remove the enemy as well.

Your enemy objects don't have any HP value assigned in the code you have posted, instead you have "miny2HP = 3" and miny2HP is never used again.

You can add an HP property to each enemy as they are created just as you do with the myName property:

local newMine2 = display.newImageRect("mina2.png", 35, 35)
newMine2.HP = 3

Then use that property in the collision:

if ( ( obj1.myName == "bullet" and obj2.myName == "mina2" ) or ( obj1.myName == "mina2" and obj2.myName == "bullet" ) ) then

local theEnemy
local theBullet
if obj1.myName == "mina2" then
theEnemy = obj1
theBullet = obj2
elseif obj2.myName == "mina2" then
theEnemy = obj2
theBullet = obj1
end

if theBullet then
--always remove the bullet
display.remove( theBullet )
end

if theEnemy then
--reduce HP by 1
theEnemy.HP = theEnemy.HP - 1

--and only remove enemy if health is 0 (or less)
if theEnemy.HP <= 0 then
display.remove( theEnemy )
end
end
end

The code could be written in a more concise way, but hopefully this makes it clearer what is happening.

Edit: you may also need to put the object removal inside a 1 millisecond timer.performWithDelay call - if I remember correctly removing an object immediately inside a collision can cause problems.

[TOPIC: post.html]
#3

### Ceterge

[GLOBAL: userInfoPane.html]
Ceterge
• Observer

• 15 posts
• Corona SDK

Thank you very much for your answer. I did as you wrote, thanks to you I understand how it works But I still have a problem with assigning HP, the first enemy has 3 HP, and after 3 collisions disappears, but the next ones sometimes can disappear after 1 collision. Did I put the given HP correctly? And could you explain to me what you meant to use timer.performWithDelay. What should it look like?
I ask a lot because thanks to the answers of experienced people I can learn the most

local function miny2()
local newMine2 = display.newImageRect("mina2.png", 35, 35)
theEnemyHP = 3
newMine2.myName = "mina2"
.
.
.
local function onCollision2( event )

if ( event.phase == "began" ) then

local obj1 = event.object1
local obj2 = event.object2

if ( ( obj1.myName == "bullet" and obj2.myName == "mina2" ) or
( obj1.myName == "mina2" and obj2.myName == "bullet" ) )
then
local theEnemy
local theBullet

if obj1.myName == "mina2" then
theEnemy  = obj1
theBullet = obj2
elseif obj2.myName == "mina2" then
theEnemy = obj2
theBullet = obj1
end

if theBullet then
display.remove(theBullet)
end

if theEnemy then
theEnemyHP = theEnemyHP - 1
if theEnemyHP <= 0 then
display.remove(theEnemy)
end
end
end
end
end

[TOPIC: post.html]
#4

### Alan PlantPot

[GLOBAL: userInfoPane.html]
Alan PlantPot
• Contributor

• 928 posts
• Corona SDK

It's behaving that way because you haven't correctly implemented the health.

What you have done is created one single variable called "theEnemyHP", which is being shared across ALL enemies. What you need to do is "attach" a health property to each instance of an enemy that you create, using the "." symbol. This is something you are already doing when you set a "myName" property on each object.

Notice the difference between my example:

local newMine2 = display.newImageRect("mina2.png", 35, 35)
newMine2.HP = 3

and yours:

local newMine2 = display.newImageRect("mina2.png", 35, 35)
theEnemyHP = 3

Do you see how I have attached something called "HP" to the instance of "newMine2"? In your code you simply have a variable called theEnemyHP which does not belong to any object.

Regarding my comment about timer.performWithDelay, this is a function that you are already using in your first post but I will explain further. When a collision occurs, if you try to immediately remove one of the colliding objects using display.remove() you may experience runtime errors. A safe workaround is to say "don't remove the object now, remove it on the next frame".

To do this, we use the timer.performWithDelay function which allows us to call a function after a delay as you are doing here:

timer.performWithDelay( 1000, miny2, 20 )

As you probably know, the arguments to this function are

timer.performWithDelay(theTimeDelayInMilliseconds, theFunctionToCall, howManyTimesToCallTheFunction)

So to delay the removal of an object until the next frame you could change the collision function to do something like this:

if theBullet then
local function removeBullet()
display.remove( theBullet )
end
timer.performWithDelay(1, removeBullet, 1)
end

if theEnemy then
--reduce HP by 1
theEnemy.HP = theEnemy.HP - 1

--and only remove enemy if health is 0 (or less)
if theEnemy.HP <= 0 then
local function removeEnemy()
display.remove( theEnemy )
end
timer.performWithDelay(1, removeEnemy, 1)
end
end

Setting the time delay to 1 milliseconds forces Corona to execute the code on the next frame.

[TOPIC: post.html]
#5

### Ceterge

[GLOBAL: userInfoPane.html]
Ceterge
• Observer

• 15 posts
• Corona SDK

Thank you for the answer , but I still have a problem with theEnemy.HP = 3. After using "." I get the error "attempt to index global 'theEnemy'" (a nil value), I tried to move theEnemy.HP = 3 to different places, but corona still has nothing to refer to. Could you still advise me what to do in this situation? Below I insert the code after entering ".HP" and without changing places

local function enemy2()
local function miny2()
local newMine2 = display.newImageRect("mina2.png", 35, 35)
theEnemy.HP = 3
newMine2.myName = "mina2"
local whereFrom2 = math.random(5)
...

...
end
timer.performWithDelay( 1500, miny2, 25 )
end
timer.performWithDelay( 1500, enemy2, 1 )

--ZNIKANIE MIN LVL2

local function onCollision2( event )

if ( event.phase == "began" ) then

local obj1 = event.object1
local obj2 = event.object2

if ( ( obj1.myName == "bullet" and obj2.myName == "mina2" ) or
( obj1.myName == "mina2" and obj2.myName == "bullet" ) )
then
local theEnemy
local theBullet

if obj1.myName == "mina2" then
theEnemy  = obj1
theBullet = obj2
elseif obj2.myName == "mina2" then
theEnemy = obj2
theBullet = obj1
end

if theBullet then
display.remove(theBullet)
end

if theEnemy then
theEnemy.HP = theEnemy.HP - 1
if theEnemy.HP <= 0 then
display.remove(theEnemy)
end
end
end
end
end

[TOPIC: post.html]
#6

### Alan PlantPot

[GLOBAL: userInfoPane.html]
Alan PlantPot
• Contributor

• 928 posts
• Corona SDK

Sorry for taking so long to respond, you may have already worked out the problem. If you haven't, I think you might benefit from working through some Lua/Corona tutorials as the error you're describing is something very fundamental to how Lua works.

In your last post you have this at the top:

local newMine2 = display.newImageRect("mina2.png", 35, 35)
theEnemy.HP = 3

That second line is saying "add a property called 'HP' to an object called 'theEnemy'". Do you see the problem here? There is no object called theEnemy at this point. What you needed to do is:

local newMine2 = display.newImageRect("mina2.png", 35, 35)
newMine2.HP = 3

This adds a property called HP to your object called newMine2. The reason that the collision code refers to something called 'theEnemy' is because inside the collision function I made a variable called theEnemy to make it easier to read whether obj1 or obj2 is the bullet or the enemy. Outside of the function those names have no meaning, think of them as shortcuts. I could have also done this:

local function onCollision2( event )

if ( event.phase == "began" ) then

local obj1 = event.object1
local obj2 = event.object2

if ( ( obj1.myName == "bullet" and obj2.myName == "mina2" ) or
( obj1.myName == "mina2" and obj2.myName == "bullet" ) )
then

if obj1.myName == "bullet" then
display.remove(obj1)
elseif obj2.myName == "bullet" then
display.remove(obj2)
end

if obj1.myName == "mina2" then
obj1.HP = obj1.HP - 1
if obj1.HP <= 0 then
display.remove(obj1)
end
elseif obj2.myName == "mina2" then
obj2.HP = obj2.HP - 1
if obj2.HP <= 0 then
display.remove(obj2)
end
end
end
end
end

[TOPIC: post.html]
#7

### Ceterge

[GLOBAL: userInfoPane.html]
Ceterge
• Observer

• 15 posts
• Corona SDK

Thank you for your response. I am ashamed to admit it, but after several attempts I stopped and started reading the book "Corona SDK Mobile Game Development Beginners Guide" to learn from the beginning. Trying my hand at other types of games, but thanks to your answer I'm smarter about how to add properties and how to use them Your code works perfectly, of course

[TOPIC: post.html]
#8

### pixec

[GLOBAL: userInfoPane.html]
pixec
• Contributor

• 102 posts
• Corona SDK

Based on your code, you should prolly look at Corona’s own getting started tutorials

[topic_controls]

[/topic_controls]