Author Topic: multiple hits  (Read 288231 times)

billybob884

  • Contributor
  • Fanatic
  • **
  • Posts: 355
    • AOL Instant Messenger - billybob884
    • View Profile
multiple hits
« on: 2005-11-11, 03:15:44 PM »
is there a way (other than using an inventory for each sprite) to make an enemy that required multiple hits to kill? Maybe just like 2 or 3, and not so much for the bosses, more for the level enemies.

--edit--
also, does the 'follow floor and slopes' movement option mean flat floor, or does it mean any flat surface (walls/ceiling)?
"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move." :: Hitchhiker's Guide to the Galaxy

durnurd

  • Lead Lemming
  • Expert
  • Fanatic
  • *****
  • Posts: 1234
  • Games completed so far: 0
    • MSN Messenger - durnurd@hotmail.com
    • View Profile
    • Find My Ed
multiple hits
« Reply #1 on: 2005-11-11, 05:19:31 PM »
Floors and slopes means only down (or up if gravity is up).  Follow Left wall follows all walls around.

There are three other ways that I can think of to have "hitpoints" for enemies.  One is through scripting, each sprite having its own value in there, which would be much easier than creating an inventory item for each.

Another is to have three seperate sprite definitions which react differently to collisions with bullets.  The sprite you add to the map would create a different sprite in the same place as the old one and delete the old one upon collision.  So would the second one.  The third one would "kill" the enemy upon collision with a bullet.

The third way is instead to have "replenishable" health.  Basically, you have a counter inventory that has a global function adding one every second.  Have a max of maybe (MAX_FRAME_RATE * 2 or 3) and when it hits the maximum, reset to opposite limit and add 1 to anb "HP" inventory (max 3, initial 3) whenever you hit a sprite and HP is at 0, destroy the sprite and reset to 3.  So basically, you have one Hitpoint counter for all enemies.  The only problem with this is that if you hit one enemy twice, then another once, it will kill the second one in only one hit but the other will still require three more shots.  Overall though, it adds up to six shots total.  The other thing is that their hitpoints are regenerative, so you have a certain amount of time to shoot them three times before they regain a hitpoint.
Edward Dassmesser

billybob884

  • Contributor
  • Fanatic
  • **
  • Posts: 355
    • AOL Instant Messenger - billybob884
    • View Profile
multiple hits
« Reply #2 on: 2005-11-13, 07:51:20 PM »
...Ok, it sounds to me like scripting ( shivers ) is the easiest way to go about this. ok, there are 4 different enemies in my 5th level: 2 are going to be '1-hitters', the sprite names are SC1-4,6-15; and NB1-8,10-20; and their templates are just SC and NB respectively, (I
"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move." :: Hitchhiker's Guide to the Galaxy

durnurd

  • Lead Lemming
  • Expert
  • Fanatic
  • *****
  • Posts: 1234
  • Games completed so far: 0
    • MSN Messenger - durnurd@hotmail.com
    • View Profile
    • Find My Ed
multiple hits
« Reply #3 on: 2005-11-13, 10:42:27 PM »
Well, I started the script.  See if you can finish it....okay, just kidding.  But I can't think right now, and I have to go to bed, so here's the beginning anyway, if somebody wants to pick up where I left off or completely scrap it and start over.  Anybody who takes a look will notice that I created a class defined for multi-hitpoint sprites, so that this could be expanded and easily used for anybody who wants to have multi-hitpoint sprites.

Code: [Select]

Option Explicit

Class Hit
   Private hMap
   Private hSpriteName
   Private hHPs
   Public Default Sub Hit(Map, SpriteName, HPs)
      hMap = Map
      hSpriteName = SpriteName
      hHPs = HPs
   End Sub

   public function getMap()
      getMap = hMap
   End Sub
   public function getSprite()
      getSprite = hSpriteName
   End Sub
   public function getHPs()
      getHPs = hHPs
   end Sub
End Class

Sub Player_OnSpritesCollide(Name, ClsASprIdx, ClsBSprIdx, CollDefIdx)
   '-----Insert Juicy Stuff Here(?)-----
End Sub

'-----Initialize Sprites-----

Dim Hits(1)
set Hits(0) = new Hit("5-0TheMoon","MJW1-4",2)
set Hits(1) = new Hit("5-0TheMoon","MS1-13",3)

'-----End initialization-----

HostObj.SinkObjectEvents ProjectObj.GamePlayer, "Player"
HostObj.ConnectEventsNow()
ProjectObj.GamePlayer.Play 16
Edward Dassmesser

billybob884

  • Contributor
  • Fanatic
  • **
  • Posts: 355
    • AOL Instant Messenger - billybob884
    • View Profile
multiple hits
« Reply #4 on: 2005-11-14, 04:57:10 AM »
set Hits(0) = new Hit("5-0TheMoon","MJW1-4",2)
i know this is just the beginning, and you probably just put this there to start it off, but jus so u know, i meant 'MJW1, MJW2, MJW3, MJW4' when i said 'MJW1-4', and the same respectively for the others
"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move." :: Hitchhiker's Guide to the Galaxy

bluemonkmn

  • SGDK Author
  • Administrator
  • Fanatic
  • *****
  • Posts: 2761
    • ICQ Messenger - 2678251
    • MSN Messenger - BlueMonkMN@gmail.com
    • View Profile
    • http://sgdk2.sf.net/
    • Email
multiple hits
« Reply #5 on: 2005-11-14, 07:07:58 AM »
I would pick it up from there, but I have to go to work.  One trick remaining that hasn't been addressed in that implementation is how to keep the Hit objects connected to the sprite objects.  Right now it looks like the Hit object just has a sprite definition name in it.  This might work if you only use the sprite definition to create one sprite instance, but it wouldn't work in a general case where you might have multiple sprite instances based on the same definition.

(That gives me an idea for 2.0 -- since sprite definitions rarely need multiple instances, maybe I'll make a kind of sprite definition that inherently supports only having 1 instance of the sprite, and then you don't have to go looking for it every time you want to access it -- just use the name of the sprite like a global variable.  Then you can deal with the confusion of multiple sprites per definition only when you really need it).

billybob884-no-login

  • Guest
multiple hits
« Reply #6 on: 2005-11-14, 09:17:32 AM »
well, then couldn't i just adda aline for each sprite? like having maybe 30 lines like

set Hits(0) = new Hit("5-0TheMoon","MJW1-4",2)

with each one having a different name in it?

durnurd

  • Lead Lemming
  • Expert
  • Fanatic
  • *****
  • Posts: 1234
  • Games completed so far: 0
    • MSN Messenger - durnurd@hotmail.com
    • View Profile
    • Find My Ed
multiple hits
« Reply #7 on: 2005-11-14, 12:43:18 PM »
Unfortunately, the onSpritesCollide only give you the sprite class rather than the sprite definition or sprite template.  I don't know what the name is used for.  But the problem is how to figure out exactly which sprites collided so you can access those sprites' User Data (and change their current HP).
Edward Dassmesser

billybob884

  • Contributor
  • Fanatic
  • **
  • Posts: 355
    • AOL Instant Messenger - billybob884
    • View Profile
multiple hits
« Reply #8 on: 2005-11-14, 12:59:53 PM »
is there a way to maybe make the game tell the script when a certain colision occurs? heh, i'm probably not helping, am i
"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move." :: Hitchhiker's Guide to the Galaxy

durnurd

  • Lead Lemming
  • Expert
  • Fanatic
  • *****
  • Posts: 1234
  • Games completed so far: 0
    • MSN Messenger - durnurd@hotmail.com
    • View Profile
    • Find My Ed
multiple hits
« Reply #9 on: 2005-11-14, 03:10:01 PM »
If you created a Special Function for each sprite collision, then yes, it would be possible.  For example, COL_MJW1Bullet would activate, then run through a loop like

Code: [Select]

for i = 0 to UBound(Hits)
   spr = Hits(i).getSprite
   if left(Special.Name,4 + len(spr)) = "COL_" & spr then
      '---Subtract Hitpoints
   end if
next


But then the problem would be finding the sprite to subtract the hitpoints from and also you would have to create the special function for each sprite (which could be done in the script during runtime, I suppose).
Edward Dassmesser

durnurd

  • Lead Lemming
  • Expert
  • Fanatic
  • *****
  • Posts: 1234
  • Games completed so far: 0
    • MSN Messenger - durnurd@hotmail.com
    • View Profile
    • Find My Ed
multiple hits
« Reply #10 on: 2005-11-14, 03:33:12 PM »
Okay, so I came up with this.  Note that I haven't tested it so I don't know if it will work (due to minor bugs).  However, it should work, in theory, to actually keep track of how many hitpoints each sprite has, and remove the sprite when their hitpoints run out (no explosion or anything;  This could be done though).  All you need is one collision definition between an enemy class and, for lack of a better term, an "attacking" class (i.e. a bullet or sword) (doesn't matter what they're called) that upon collision activates the COL_<ADef>* function
Code: [Select]

Option Explicit

Class Hit
   Private hMap
   Private hSpriteName
   Private hHPs
   Public Default Sub Hit(Map, SpriteName, HPs)
      hMap = Map
      hSpriteName = SpriteName
      hHPs = HPs
   End Sub

   public function getMap()
      getMap = hMap
   End function
   public function getSprite()
      getSprite = hSpriteName
   End function
   public function getHPs()
      getHPs = hHPs
   end function
End Class

Sub Player_OnPlayInit()
   Dim i
   Dim oNewSpecial
   Set oNewSpecial = NewSpecialFunction
   for i = 0 to ubound(Hits)
      oMap = ProjectObj.Maps(Hits(i).getMap())
      oNewSpecial.FuncType = 7 ' SPECIAL_EVENT
      oNewSpecial.Name = "COL_" & Hits(i).getSprite()
      oMap.AddSpecial(hostObj.AsObject(oNewSpecial))
   Next
End Sub

Sub Player_OnSpecialFunction(SpecialObj)
   dim i, layer, idx
   for i = 0 to UBound(Hits)
   spr = Hits(i).getSprite()
   if left(Special.Name,4 + len(spr)) = "COL_" & spr then
      spr = FindSpriteByDef(spr,layer,idx)
      if spr.UserData > Hits(i).getHPs() or spr.UserData < 0 then spr.UserData = 0
      spr.UserData = spr.UserData + 1
      if spr.UserData = Hits(i).getHPs() then
         layer.RemoveSprite(idx)
      end if
   end if
next
End Sub

Function FindSpriteByDef(SpriteName, byref oLayer, byref oSprIndex)
   dim i, j
   oMap = ProjectObj.GamePlayer.rMap
   for i = 0 to rMap.LayerCount
      for j = 0 to rMap.MapLayer(i).SpriteCount()
         if rMap.MapLayer(i).Sprite(j).SpriteDef.Name = SpriteName then
            set oLayer = rMap.MapLayer(i)
            oSprIndex = j
            set FindSpriteByDef = oLayer.Sprite(j)
         end if
      next
   next
End Function

'-----Initialize Sprites-----

Dim Hits(16)
Dim i
for i = 0 to 3
   set Hits(i) = new Hit
   Hits(i) "5-0TheMoon","MJW" & i + 1,2
next
for i = 4 to 16
   set Hits(i) = new Hit
   Hits(i) "5-0TheMoon","MS" & i - 3,3
next

'-----End initialization-----

HostObj.SinkObjectEvents ProjectObj.GamePlayer, "Player"
HostObj.ConnectEventsNow()
ProjectObj.GamePlayer.Play 16
Edward Dassmesser

billybob884

  • Contributor
  • Fanatic
  • **
  • Posts: 355
    • AOL Instant Messenger - billybob884
    • View Profile
multiple hits
« Reply #11 on: 2005-11-15, 05:01:30 AM »
ok, ill give it a shot this afternoon. one question i have is this: right now i have the colision of 'Attack' (ADef) and 'Enemy' (BDef), it activates COL_<ADef><BTemplate>, i did this so i would only need 1 class for enemy, so do i need to give each enemy with multiple hit points a seperate class? and does the enemy need to be the ADef in the colision?
"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move." :: Hitchhiker's Guide to the Galaxy

bluemonkmn

  • SGDK Author
  • Administrator
  • Fanatic
  • *****
  • Posts: 2761
    • ICQ Messenger - 2678251
    • MSN Messenger - BlueMonkMN@gmail.com
    • View Profile
    • http://sgdk2.sf.net/
    • Email
multiple hits
« Reply #12 on: 2005-11-15, 05:54:19 AM »
Quote from: "durnurd"
Unfortunately, the onSpritesCollide only give you the sprite class rather than the sprite definition or sprite template.  I don't know what the name is used for.  But the problem is how to figure out exactly which sprites collided so you can access those sprites' User Data (and change their current HP).


Actually it doesn't just give you the class.  It gives you the index of the sprite associated with the "Class A" sprite and the index of the sprite associated with the "Class B" sprite.  From this you can get the sprite instance (using Layer.Sprite()) and from that you can get the sprite definition and the sprite template using Sprite.rDef and Sprite.rDef.Template.  The "Name" parameter is the name of the layer on which the collision occurred (so you know which layer's sprite array to reference with Layer.Sprite()).

So for example, to get the sprite definition name of the first sprite in the collision, you'd use:
Code: [Select]
ProjectObj.GamePlayer.rMap.MapLayer(Name).Sprite(ClsASprIdx).rDef.Name

bluemonkmn

  • SGDK Author
  • Administrator
  • Fanatic
  • *****
  • Posts: 2761
    • ICQ Messenger - 2678251
    • MSN Messenger - BlueMonkMN@gmail.com
    • View Profile
    • http://sgdk2.sf.net/
    • Email
multiple hits
« Reply #13 on: 2005-11-15, 06:10:48 AM »
Quote from: "billybob884"
ok, ill give it a shot this afternoon. one question i have is this: right now i have the colision of 'Attack' (ADef) and 'Enemy' (BDef), it activates COL_<ADef><BTemplate>, i did this so i would only need 1 class for enemy, so do i need to give each enemy with multiple hit points a seperate class? and does the enemy need to be the ADef in the colision?


COL_<ADef><BTemplate> will activate the same function for all enemies that use the same enemy template and all attackers that use the same attacker sprite definition.  In other words, it activates a unique function for each attacker sprite and enemy template combination.  So take, for example, these three attacker sprites:
SpriteDef: Sword1 Template: Sword Class: Attacker
SpriteDef: Bullet Template: Projectile Class: Attacker
SpriteDef: Missile1 Template: Projectile Class: Attacker

And these three enemy sprites:
SpriteDef: Ghoul1 Template: Ghostie Class: Enemy
SpriteDef: Phantom1 Template: Ghostie Class: Enemy
SpriteDef: Wolf1 Template: Wolf Class: Enemy

Using this data and a single collision definition, you end up with a number of functions that can be activated:
Collision Definition: When Attacker hits Enemy, Activate COL_<ADef><BTemplate>
Can activate:
COL_Sword1Ghostie
COL_BulletGhostie
COL_Missile1Ghostie
COL_Sword1Wolf
COL_BulletWolf
COL_MissileWolf

If you define your collision definition slightly differently, you could end up with different results:
Collision Definition: When Attacker hits Enemy, Activate COL_<ATemplate><BDef>
Can activate:
COL_SwordGhoul1
COL_SwordPhantom1
COL_SwordWolf1
COL_ProjectileGhoul1
COL_ProjectilePhantom1
COL_ProjectileWolf1

If you don't care what kind of weapon you use, you might do something like this:
Collision Definition: When Attacker hits Enemy, Activate COL_<BTemplate>
Can activate:
COL_Ghostie
COL_Wolf

One thing to keep in mind is that I think you need to have functions by those names in order for anything to happen.  I don't think you can just have a script to handle the collision.  You'll have to actually create functions for the names that you care about, and set them to a type of "Raise an Event" (or whatever) and then if you want to script them you can add script like durnurd provided.

billybob884-nologin

  • Guest
multiple hits
« Reply #14 on: 2005-11-15, 06:50:38 AM »
Quote from: "durnurd"
no explosion or anything;


The explosions aren't that bad, I can just set up a second colision definition to create the explosion