Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

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
physics.addBody(newMine2, "dynamic", {isSensor = true, radius=35})
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
Runtime:addEventListener( "collision", onCollision2 )

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 :unsure:

 



[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
physics.addBody(newMine2, "dynamic", {isSensor = true, radius=35})
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
Runtime:addEventListener( "collision", onCollision2 )

 



[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
physics.addBody(newMine2, "dynamic", {isSensor = true, radius=35})
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
Runtime:addEventListener( "collision", onCollision2 )

 



[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]