Difference between revisions of "Tuto tiny-ecs beatemup Part 11 Systems 3"

From GiderosMobile
(wip)
 
(4 intermediate revisions by the same user not shown)
Line 2: Line 2:
  
 
== The Systems 3 ==
 
== The Systems 3 ==
A couple more systems to add and we are done. Those systems apply on the breakable objects and the collectibles.
+
A couple more systems to add and we are done. We also add the '''Debug Systems''' to help us visualize all the boxes (hitbox, hurtbox, collsion box, ...).
  
 
== sDestructibleObjects.lua ==
 
== sDestructibleObjects.lua ==
Line 187: Line 187:
 
* there are two kind of collectibles: health and jump attacks (updated in the HUD)
 
* there are two kind of collectibles: health and jump attacks (updated in the HUD)
  
== sSpritesSorting.lua.lua ==
+
'''There are quite a bit of commented code you can delete as this Entity is immediately removed'''
"'''sSpritesSorting.lua.lua'''" in the '''"_S"''' folder. The code:
+
 
 +
== sSpritesSorting.lua ==
 +
"'''sSpritesSorting.lua'''" in the '''"_S"''' folder. The code:
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
 
SSpritesSorting = Core.class()
 
SSpritesSorting = Core.class()
Line 245: Line 247:
 
* there is a distinction between the actor being on floor and jumping
 
* there is a distinction between the actor being on floor and jumping
  
== XXX.lua ==
+
== '''DEBUG SYSTEMS''' ==
"'''sCollision.lua'''" in the '''"_S"''' folder. The code:
+
It would be difficult to accurately position the hit and hurt boxes, the collision boxes, ... without visual cues.
 +
 
 +
Debug systems help us with the above. Fortunately they are small and quite simple.
 +
 
 +
=== sDebugCollision.lua ===
 +
"'''sDebugCollision.lua'''" in the '''"_S"''' folder. The code:
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
 +
SDebugCollision = Core.class()
 +
 +
function SDebugCollision:init(xtiny) -- tiny function
 +
xtiny.processingSystem(self) -- called once on init and every update
 +
end
 +
 +
function SDebugCollision:filter(ent) -- tiny function
 +
return ent.collbox
 +
end
 +
 +
function SDebugCollision:onAdd(ent) -- tiny function
 +
local debugcolor = 0xff00ff
 +
if ent.isplayer1 then debugcolor = 0x00ffff end
 +
ent.debug = Pixel.new(debugcolor, 0.25, ent.collbox.w, ent.collbox.h)
 +
ent.spritelayer:addChild(ent.debug)
 +
end
 +
 +
function SDebugCollision:onRemove(ent) -- tiny function
 +
ent.spritelayer:removeChild(ent.debug)
 +
end
 +
 +
function SDebugCollision:process(ent, dt) -- tiny function
 +
-- ent.debug:setPosition(ent.x, ent.y)
 +
ent.debug:setPosition(ent.pos)
 +
end
 
</syntaxhighlight>
 
</syntaxhighlight>
  
This System uses the '''Bump''' plugin to check for collisions between the actors collision boxes:
+
This System displays the actors collision box.
* runs once on init and '''every game loop''' (''process'')
+
 
* in ''init'' we pass the Bump '''world''' the actors live in
+
=== sDebugHitBoxNme.lua ===
* we define Bump collision filter
+
"'''sDebugHitBoxNme.lua'''" in the '''"_S"''' folder. The code:
* we check if player1 collides with a collectible actor and tag the collectible as dirty
+
<syntaxhighlight lang="lua">
* finally we set the actor position and flip its bitmap in the direction it is going
+
SDebugHitBoxNme = Core.class()
* I experimented with '''asyncCall''' to test if we could gain some frames per second ;-)
+
 
 +
function SDebugHitBoxNme:init(xtiny, xshowbox) -- tiny function
 +
xtiny.processingSystem(self) -- called once on init and every update
 +
self.showbox = xshowbox
 +
end
 +
 
 +
function SDebugHitBoxNme:filter(ent) -- tiny function
 +
return (ent.headhitboxattack1 or ent.headhitboxattack2 or ent.spinehitboxattack1 or ent.spinehitboxattack2 or
 +
ent.headhitboxjattack1 or ent.spinehitboxjattack1) and not ent.isplayer1
 +
end
 +
 
 +
function SDebugHitBoxNme:onAdd(ent) -- tiny function
 +
-- debugheadhitboxp1
 +
if ent.headhitboxattack1 then
 +
ent.debugheadhitboxp1 = Pixel.new(0xaa0000, 0.5, ent.headhitboxattack1.w, ent.headhitboxattack1.h)
 +
ent.debugheadhitboxp1:setAnchorPoint(0.5, 0.5)
 +
ent.spritelayer:addChild(ent.debugheadhitboxp1)
 +
ent.debugheadhitboxp1:setVisible(self.showbox[1]) -- granular debugging
 +
end
 +
-- debugheadhitboxp2
 +
if ent.headhitboxattack2 then
 +
ent.debugheadhitboxp2 = Pixel.new(0xaa5500, 0.5, ent.headhitboxattack2.w, ent.headhitboxattack2.h)
 +
ent.debugheadhitboxp2:setAnchorPoint(0.5, 0.5)
 +
ent.spritelayer:addChild(ent.debugheadhitboxp2)
 +
ent.debugheadhitboxp2:setVisible(self.showbox[2]) -- granular debugging
 +
end
 +
-- debugspinehitboxk1
 +
if ent.spinehitboxattack1 then
 +
ent.debugspinehitboxk1 = Pixel.new(0x005500, 0.5, ent.spinehitboxattack1.w, ent.spinehitboxattack1.h)
 +
ent.debugspinehitboxk1:setAnchorPoint(0.5, 0.5)
 +
ent.spritelayer:addChild(ent.debugspinehitboxk1)
 +
ent.debugspinehitboxk1:setVisible(self.showbox[3]) -- granular debugging
 +
end
 +
-- debugspinehitboxk2
 +
if ent.spinehitboxattack2 then
 +
ent.debugspinehitboxk2 = Pixel.new(0x00aa00, 0.5, ent.spinehitboxattack2.w, ent.spinehitboxattack2.h)
 +
ent.debugspinehitboxk2:setAnchorPoint(0.5, 0.5)
 +
ent.spritelayer:addChild(ent.debugspinehitboxk2)
 +
ent.debugspinehitboxk2:setVisible(self.showbox[4]) -- granular debugging
 +
end
 +
-- debugheadhitboxjp1
 +
if ent.headhitboxjattack1 then
 +
ent.debugheadhitboxjp1 = Pixel.new(0xaaaa00, 0.5, ent.headhitboxjattack1.w, ent.headhitboxjattack1.h)
 +
ent.debugheadhitboxjp1:setAnchorPoint(0.5, 0.5)
 +
ent.spritelayer:addChild(ent.debugheadhitboxjp1)
 +
ent.debugheadhitboxjp1:setVisible(self.showbox[5]) -- granular debugging
 +
end
 +
-- debugspinehitboxjk1
 +
if ent.spinehitboxjattack1 then
 +
ent.debugspinehitboxjk1 = Pixel.new(0x00ff00, 0.5, ent.spinehitboxjattack1.w, ent.spinehitboxjattack1.h)
 +
ent.debugspinehitboxjk1:setAnchorPoint(0.5, 0.5)
 +
ent.spritelayer:addChild(ent.debugspinehitboxjk1)
 +
ent.debugspinehitboxjk1:setVisible(self.showbox[6]) -- granular debugging
 +
end
 +
end
 +
 
 +
function SDebugHitBoxNme:onRemove(ent) -- tiny function
 +
if ent.headhitboxattack1 then ent.spritelayer:removeChild(ent.debugheadhitboxp1) end
 +
if ent.headhitboxattack2 then ent.spritelayer:removeChild(ent.debugheadhitboxp2) end
 +
if ent.spinehitboxattack1 then ent.spritelayer:removeChild(ent.debugspinehitboxk1) end
 +
if ent.spinehitboxattack2 then ent.spritelayer:removeChild(ent.debugspinehitboxk2) end
 +
if ent.headhitboxjattack1 then ent.spritelayer:removeChild(ent.debugheadhitboxjp1) end
 +
if ent.spinehitboxjattack1 then ent.spritelayer:removeChild(ent.debugspinehitboxjk1) end
 +
end
 +
 
 +
function SDebugHitBoxNme:process(ent, dt) -- tiny function
 +
local function fun()
 +
if ent.headhitboxattack1 then
 +
ent.debugheadhitboxp1:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.headhitboxattack1.x*ent.flip), ent.headhitboxattack1.y))
 +
end
 +
if ent.headhitboxattack2 then
 +
ent.debugheadhitboxp2:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.headhitboxattack2.x*ent.flip), ent.headhitboxattack2.y))
 +
end
 +
if ent.spinehitboxattack1 then
 +
ent.debugspinehitboxk1:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.spinehitboxattack1.x*ent.flip), ent.spinehitboxattack1.y))
 +
end
 +
if ent.spinehitboxattack2 then
 +
ent.debugspinehitboxk2:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.spinehitboxattack2.x*ent.flip), ent.spinehitboxattack2.y))
 +
end
 +
if ent.headhitboxjattack1 then
 +
ent.debugheadhitboxjp1:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.headhitboxjattack1.x*ent.flip), ent.headhitboxjattack1.y))
 +
end
 +
if ent.spinehitboxjattack1 then
 +
ent.debugspinehitboxjk1:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.spinehitboxjattack1.x*ent.flip), ent.spinehitboxjattack1.y))
 +
end
 +
Core.yield(1)
 +
end
 +
Core.asyncCall(fun)
 +
end
 +
</syntaxhighlight>
 +
 
 +
This System displays the enemies hit boxes when available.
 +
 
 +
=== sDebugHitBoxPlayer.lua ===
 +
"'''sDebugHitBoxPlayer.lua'''" in the '''"_S"''' folder. The code:
 +
<syntaxhighlight lang="lua">
 +
SDebugHitBoxPlayer = Core.class()
 +
 
 +
function SDebugHitBoxPlayer:init(xtiny, xshowbox) -- tiny function
 +
xtiny.processingSystem(self) -- called once on init and every update
 +
self.showbox = xshowbox
 +
end
 +
 
 +
function SDebugHitBoxPlayer:filter(ent) -- tiny function
 +
return (ent.headhitboxattack1 or ent.headhitboxattack2 or ent.spinehitboxattack1 or ent.spinehitboxattack2 or
 +
ent.headhitboxjattack1 or ent.spinehitboxjattack1) and not ent.isnme
 +
end
 +
 
 +
function SDebugHitBoxPlayer:onAdd(ent) -- tiny function
 +
-- debugheadhitboxp1
 +
if ent.headhitboxattack1 then
 +
ent.debugheadhitboxp1 = Pixel.new(0xaa0000, 0.5, ent.headhitboxattack1.w, ent.headhitboxattack1.h)
 +
ent.debugheadhitboxp1:setAnchorPoint(0.5, 0.5)
 +
ent.spritelayer:addChild(ent.debugheadhitboxp1)
 +
ent.debugheadhitboxp1:setVisible(self.showbox[1]) -- granular debugging
 +
end
 +
-- debugheadhitboxp2
 +
if ent.headhitboxattack2 then
 +
ent.debugheadhitboxp2 = Pixel.new(0xaa5500, 0.5, ent.headhitboxattack2.w, ent.headhitboxattack2.h)
 +
ent.debugheadhitboxp2:setAnchorPoint(0.5, 0.5)
 +
ent.spritelayer:addChild(ent.debugheadhitboxp2)
 +
ent.debugheadhitboxp2:setVisible(self.showbox[2]) -- granular debugging
 +
end
 +
-- debugspinehitboxk1
 +
if ent.spinehitboxattack1 then
 +
ent.debugspinehitboxk1 = Pixel.new(0x005500, 0.5, ent.spinehitboxattack1.w, ent.spinehitboxattack1.h)
 +
ent.debugspinehitboxk1:setAnchorPoint(0.5, 0.5)
 +
ent.spritelayer:addChild(ent.debugspinehitboxk1)
 +
ent.debugspinehitboxk1:setVisible(self.showbox[3]) -- granular debugging
 +
end
 +
-- debugspinehitboxk2
 +
if ent.spinehitboxattack2 then
 +
ent.debugspinehitboxk2 = Pixel.new(0x00aa00, 0.5, ent.spinehitboxattack2.w, ent.spinehitboxattack2.h)
 +
ent.debugspinehitboxk2:setAnchorPoint(0.5, 0.5)
 +
ent.spritelayer:addChild(ent.debugspinehitboxk2)
 +
ent.debugspinehitboxk2:setVisible(self.showbox[4]) -- granular debugging
 +
end
 +
-- debugheadhitboxjp1
 +
if ent.headhitboxjattack1 then
 +
ent.debugheadhitboxjp1 = Pixel.new(0xaaaa00, 0.5, ent.headhitboxjattack1.w, ent.headhitboxjattack1.h)
 +
ent.debugheadhitboxjp1:setAnchorPoint(0.5, 0.5)
 +
ent.spritelayer:addChild(ent.debugheadhitboxjp1)
 +
ent.debugheadhitboxjp1:setVisible(self.showbox[5]) -- granular debugging
 +
end
 +
-- debugspinehitboxjk1
 +
if ent.spinehitboxjattack1 then
 +
ent.debugspinehitboxjk1 = Pixel.new(0x00ff00, 0.5, ent.spinehitboxjattack1.w, ent.spinehitboxjattack1.h)
 +
ent.debugspinehitboxjk1:setAnchorPoint(0.5, 0.5)
 +
ent.spritelayer:addChild(ent.debugspinehitboxjk1)
 +
ent.debugspinehitboxjk1:setVisible(self.showbox[6]) -- granular debugging
 +
end
 +
end
 +
 
 +
function SDebugHitBoxPlayer:onRemove(ent) -- tiny function
 +
if ent.headhitboxattack1 then ent.spritelayer:removeChild(ent.debugheadhitboxp1) end
 +
if ent.headhitboxattack2 then ent.spritelayer:removeChild(ent.debugheadhitboxp2) end
 +
if ent.spinehitboxattack1 then ent.spritelayer:removeChild(ent.debugspinehitboxk1) end
 +
if ent.spinehitboxattack2 then ent.spritelayer:removeChild(ent.debugspinehitboxk2) end
 +
if ent.headhitboxjattack1 then ent.spritelayer:removeChild(ent.debugheadhitboxjp1) end
 +
if ent.spinehitboxjattack1 then ent.spritelayer:removeChild(ent.debugspinehitboxjk1) end
 +
end
 +
 
 +
function SDebugHitBoxPlayer:process(ent, dt) -- tiny function
 +
local function fun()
 +
if ent.headhitboxattack1 then
 +
ent.debugheadhitboxp1:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.headhitboxattack1.x*ent.flip), ent.headhitboxattack1.y))
 +
end
 +
if ent.headhitboxattack2 then
 +
ent.debugheadhitboxp2:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.headhitboxattack2.x*ent.flip), ent.headhitboxattack2.y))
 +
end
 +
if ent.spinehitboxattack1 then
 +
ent.debugspinehitboxk1:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.spinehitboxattack1.x*ent.flip), ent.spinehitboxattack1.y))
 +
end
 +
if ent.spinehitboxattack2 then
 +
ent.debugspinehitboxk2:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.spinehitboxattack2.x*ent.flip), ent.spinehitboxattack2.y))
 +
end
 +
if ent.headhitboxjattack1 then
 +
ent.debugheadhitboxjp1:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.headhitboxjattack1.x*ent.flip), ent.headhitboxjattack1.y))
 +
end
 +
if ent.spinehitboxjattack1 then
 +
ent.debugspinehitboxjk1:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.spinehitboxjattack1.x*ent.flip), ent.spinehitboxjattack1.y))
 +
end
 +
Core.yield(1)
 +
end
 +
Core.asyncCall(fun)
 +
end
 +
</syntaxhighlight>
 +
 
 +
This System displays the player hit boxes when available.
 +
 
 +
=== sDebugHurtBoxNme.lua ===
 +
"'''sDebugHurtBoxNme.lua'''" in the '''"_S"''' folder. The code:
 +
<syntaxhighlight lang="lua">
 +
SDebugHurtBoxNme = Core.class()
 +
 
 +
function SDebugHurtBoxNme:init(xtiny) -- tiny function
 +
xtiny.processingSystem(self) -- called once on init and every update
 +
end
 +
 
 +
function SDebugHurtBoxNme:filter(ent) -- tiny function
 +
return (ent.headhurtbox or ent.spinehurtbox) and not ent.isplayer1
 +
end
 +
 
 +
function SDebugHurtBoxNme:onAdd(ent) -- tiny function
 +
-- debugheadhurtbox
 +
ent.debugheadhurtbox = Pixel.new(0x5500ff, 0.5, ent.headhurtbox.w, ent.headhurtbox.h)
 +
ent.debugheadhurtbox:setAnchorPoint(0.5, 0.5)
 +
ent.spritelayer:addChild(ent.debugheadhurtbox)
 +
-- debugspinehurtbox
 +
ent.debugspinehurtbox = Pixel.new(0xff00ff, 0.5, ent.spinehurtbox.w, ent.spinehurtbox.h)
 +
ent.debugspinehurtbox:setAnchorPoint(0.5, 0.5)
 +
ent.spritelayer:addChild(ent.debugspinehurtbox)
 +
end
 +
 
 +
function SDebugHurtBoxNme:onRemove(ent) -- tiny function
 +
if not ent.isdestructibleobject then -- isdestructibleobject is somehow already removed!
 +
ent.spritelayer:removeChild(ent.debugheadhurtbox)
 +
ent.spritelayer:removeChild(ent.debugspinehurtbox)
 +
end
 +
end
 +
 
 +
function SDebugHurtBoxNme:process(ent, dt) -- tiny function
 +
local function fun()
 +
ent.debugheadhurtbox:setPosition(ent.pos+vector(ent.collbox.w/2+(ent.headhurtbox.x*ent.flip), ent.headhurtbox.y))
 +
ent.debugspinehurtbox:setPosition(ent.pos+vector(ent.collbox.w/2+(ent.spinehurtbox.x*ent.flip), ent.spinehurtbox.y))
 +
Core.yield(1)
 +
end
 +
Core.asyncCall(fun)
 +
end
 +
</syntaxhighlight>
 +
 
 +
This System displays the enemies and breakable objects hurt boxes.
 +
 
 +
=== sDebugHurtBoxPlayer.lua ===
 +
"'''sDebugHurtBoxPlayer.lua'''" in the '''"_S"''' folder. The code:
 +
<syntaxhighlight lang="lua">
 +
SDebugHurtBoxPlayer = Core.class()
 +
 
 +
function SDebugHurtBoxPlayer:init(xtiny) -- tiny function
 +
xtiny.processingSystem(self) -- called once on init and every update
 +
end
 +
 
 +
function SDebugHurtBoxPlayer:filter(ent) -- tiny function
 +
return (ent.headhurtbox or ent.spinehurtbox) and not ent.isnme
 +
end
 +
 
 +
function SDebugHurtBoxPlayer:onAdd(ent) -- tiny function
 +
-- debugheadhurtbox
 +
ent.debugheadhurtbox = Pixel.new(0x5500ff, 0.5, ent.headhurtbox.w, ent.headhurtbox.h)
 +
ent.debugheadhurtbox:setAnchorPoint(0.5, 0.5)
 +
ent.spritelayer:addChild(ent.debugheadhurtbox)
 +
-- debugspinehurtbox
 +
ent.debugspinehurtbox = Pixel.new(0xff00ff, 0.5, ent.spinehurtbox.w, ent.spinehurtbox.h)
 +
ent.debugspinehurtbox:setAnchorPoint(0.5, 0.5)
 +
ent.spritelayer:addChild(ent.debugspinehurtbox)
 +
end
 +
 
 +
function SDebugHurtBoxPlayer:onRemove(ent) -- tiny function
 +
ent.spritelayer:removeChild(ent.debugheadhurtbox)
 +
ent.spritelayer:removeChild(ent.debugspinehurtbox)
 +
end
 +
 
 +
function SDebugHurtBoxPlayer:process(ent, dt) -- tiny function
 +
ent.debugheadhurtbox:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.headhurtbox.x*ent.flip), ent.headhurtbox.y))
 +
ent.debugspinehurtbox:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.spinehurtbox.x*ent.flip), ent.spinehurtbox.y))
 +
end
 +
</syntaxhighlight>
 +
 
 +
This System displays the player hurt boxes.
 +
 
 +
=== sDebugSpriteSorting.lua ===
 +
"'''sDebugSpriteSorting.lua'''" in the '''"_S"''' folder. The code:
 +
<syntaxhighlight lang="lua">
 +
SDebugSpriteSorting = Core.class()
 +
 
 +
function SDebugSpriteSorting:init(xtiny) -- tiny function
 +
xtiny.processingSystem(self) -- called once on init and every update
 +
end
 +
 
 +
function SDebugSpriteSorting:filter(ent) -- tiny function
 +
return ent.sprite
 +
end
 +
 
 +
function SDebugSpriteSorting:onAdd(ent) -- tiny function
 +
-- debugposition
 +
ent.debugposition = Pixel.new(0xaa5500, 1, 16, 16)
 +
ent.debugposition:setAnchorPoint(0.5, 0.5)
 +
if ent.isplayer1 then ent.debugposition:setColor(0xaa5500, 1) end
 +
ent.spritelayer:addChild(ent.debugposition)
 +
-- debugstartyposition
 +
ent.debugstartyposition = Pixel.new(0xaa557f, 1, 16, 16)
 +
ent.debugstartyposition:setAnchorPoint(0.5, 0.5)
 +
if ent.isplayer1 then ent.debugstartyposition:setColor(0xaa557f, 1) end
 +
ent.spritelayer:addChild(ent.debugstartyposition)
 +
end
 +
 
 +
function SDebugSpriteSorting:onRemove(ent) -- tiny function
 +
ent.spritelayer:removeChild(ent.debugposition)
 +
ent.spritelayer:removeChild(ent.debugstartyposition)
 +
end
 +
 
 +
function SDebugSpriteSorting:process(ent, dt) -- tiny function
 +
ent.debugposition:setPosition(ent.pos)
 +
ent.debugstartyposition:setPosition(ent.pos.x, ent.positionystart)
 +
end
 +
</syntaxhighlight>
 +
 
 +
This System displays the actors y position.
  
 
== Next? ==
 
== Next? ==
Next we add the systems for the breakable objects and the collectibles and we are almost done with the game!
+
'''Congratulations'''! We have finished our game.
 +
 
 +
Let's add the final scene: '''YOU WIN'''!
  
  
 
Prev.: [[Tuto tiny-ecs beatemup Part 10 Systems 2]]</br>
 
Prev.: [[Tuto tiny-ecs beatemup Part 10 Systems 2]]</br>
'''Next: [[Tuto tiny-ecs beatemup Part 12 XXX]]'''
+
'''Next: [[Tuto tiny-ecs beatemup Part 12 You Win]]'''
  
  
 
'''[[Tutorial - tiny-ecs beatemup]]'''
 
'''[[Tutorial - tiny-ecs beatemup]]'''
 
{{GIDEROS IMPORTANT LINKS}}
 
{{GIDEROS IMPORTANT LINKS}}

Latest revision as of 02:32, 25 November 2024

The Systems 3

A couple more systems to add and we are done. We also add the Debug Systems to help us visualize all the boxes (hitbox, hurtbox, collsion box, ...).

sDestructibleObjects.lua

Please create a file "sDestructibleObjects.lua" in the "_S" folder and the code:

SDestructibleObjects = Core.class()

local random, cos, sin = math.random, math.cos, math.sin
local insert = table.insert

function SDestructibleObjects:init(xtiny, xbworld) -- tiny function
	self.tiny = xtiny -- ref so we can remove entities from tiny system
	self.tiny.processingSystem(self) -- called once on init and every update
	self.bworld = xbworld
	-- sfx
	self.snd = Sound.new("audio/sfx/footstep/Forest02.wav")
	self.channel = self.snd:play(0, false, true)
end

function SDestructibleObjects:filter(ent) -- tiny function
	return ent.isdestructibleobject
end

function SDestructibleObjects:onAdd(ent) -- tiny function
end

function SDestructibleObjects:onRemove(ent) -- tiny function
	-- spawn a random collectible: ECollectible:init(xspritelayer, xpos)
	local function fun()
		local el = ECollectible.new(ent.spritelayer, ent.pos+vector(ent.collbox.w/4, -1*ent.collbox.h))
		self.tiny.tworld:addEntity(el)
		self.bworld:add(el, el.pos.x, el.pos.y, el.collbox.w, el.collbox.h)
		Core.yield(1)
	end
	Core.asyncCall(fun)
	self.bworld:remove(ent) -- remove collision box from cbump world here!
end

function SDestructibleObjects:process(ent, dt) -- tiny function
	local function EffectExplode(s, scale, pos, r, speed, texture)
		local p = Particles.new()
		p:setPosition(pos)
		p:setTexture(texture)
		p:setScale(scale)
		s:addChild(p)
		local parts = {}
		for i = 1, 6 do -- 8
			local a = random()*6.3
			local dx, dy = cos(a), sin(a)
			local sr = random()*r
			local px, py = dx*sr, dy*sr
			local ss = (random()+0.5) * (speed or 1)
			insert(parts,
				{
					x = px, y = py,
					speedX = dx * ss,
					speedY = dy * ss,
					speedAngular = random()*4 - 2,
					decayAlpha = random()*0.04 + 0.95,
					ttl = 32, -- 500
					size = random()*10 + 20,
				}
			)
		end
		p:addParticles(parts)
		Core.yield(1)
		p:removeFromParent()
	end
	-- hurt fx
	if ent.washurt and ent.washurt > 0 then
		ent.washurt -= 1
		if ent.washurt < ent.recovertimer/2 then
			if ent.hitfx then ent.hitfx:setVisible(false) end
		end
		if ent.washurt <= 0 then
			ent.sprite:setColorTransform(1, 1, 1, 1)
		end
	end
	if ent.isdirty then -- hit
		self.channel = self.snd:play()
		if self.channel then self.channel:setVolume(g_sfxvolume*0.01) end
		ent.hitfx:setVisible(true)
		ent.hitfx:setPosition(ent.pos + vector(ent.headhurtbox.x+4, ent.headhurtbox.y))
		ent.spritelayer:addChild(ent.hitfx)
		ent.currhealth -= ent.damage
		ent.washurt = ent.recovertimer -- timer for a flash effect
		ent.sprite:setColorTransform(1, 1, 1, 3) -- a flash effect
		ent.isdirty = false
		if ent.currhealth <= 0 then
			--EffectExplode(s, scale, pos, r, speed, texture)
			Core.asyncCall(EffectExplode, ent.spritelayer, 2,
				ent.pos+vector(ent.collbox.w/2, -ent.h/2), 4, 2,
				Texture.new("gfx/fx/fxBarrel_02_0011.png"))
			ent.spritelayer:removeChild(ent.hitfx)
			self.tiny.tworld:removeEntity(ent) -- sprite is removed in SDrawable
			self.tiny.numberofdestructibleobjects -= 1
		end
	end
end

The System removes a breakable object when destroyed and spawn a collectible in the onRemove function:

  • it runs every frame
  • it affects only entities with an isdestructibleobject id
  • on hurt adds an hit fx
  • on destroyed adds particles
  • onRemove spawns a collectible

sCollectible.lua

"sCollectible.lua" in the "_S" folder. The code:

SCollectible = Core.class()

local random = math.random

function SCollectible:init(xtiny, xbump, xplayer1) -- tiny function
	self.tiny = xtiny -- make a class ref
	self.tiny.processingSystem(self) -- called once on init and every update
	self.bworld = xbump
	self.player1 = xplayer1
	-- sfx
	self.snd = Sound.new("audio/sfx/sfx_coin_double1.wav")
	self.channel = self.snd:play(0, false, true)
end

function SCollectible:filter(ent) -- tiny function
	return ent.iscollectible
end

function SCollectible:onAdd(ent) -- tiny function
end

function SCollectible:onRemove(ent) -- tiny function
	self.bworld:remove(ent) -- remove collision box from cbump world here!
end

function SCollectible:process(ent, dt) -- tiny function
	if ent.isdirty then -- hit
		local function map(v, minSrc, maxSrc, minDst, maxDst, clampValue)
			local newV = (v - minSrc) / (maxSrc - minSrc) * (maxDst - minDst) + minDst
			return not clampValue and newV or clamp(newV, minDst >< maxDst, minDst <> maxDst)
		end
		self.channel = self.snd:play()
		if self.channel then self.channel:setVolume(g_sfxvolume*0.01) end
--		ent.hitfx:setVisible(true)
--		ent.hitfx:setPosition(ent.pos.x+ent.headhurtbox.x, ent.y+ent.headhurtbox.y)
--		ent.spritelayer:addChild(ent.hitfx)
--		ent.currhealth -= ent.damage
--		ent.washurt = ent.recovertimer -- timer for a flash effect
		if random(100) > 50 then
			if self.player1.currjumps < 0 then self.player1.currjumps = 0 end
			self.player1.currjumps += 3
			self.tiny.hudcurrjumps:setText("JUMPS: "..self.player1.currjumps)
		else
			self.player1.currhealth += 1
			-- hud
			local hudhealthwidth = map(self.player1.currhealth, 0, self.player1.totalhealth, 0, 100)
			self.tiny.hudhealth:setWidth(hudhealthwidth)
			if self.player1.currhealth < self.player1.totalhealth/3 then self.tiny.hudhealth:setColor(0xff0000)
			elseif self.player1.currhealth < self.player1.totalhealth/2 then self.tiny.hudhealth:setColor(0xff5500)
			else self.tiny.hudhealth:setColor(0x00ff00)
			end
		end
		ent.sprite:setColorTransform(0, 2, 0, 3) -- the flash effect (a bright color)
		ent.isdirty = false
--[[
		if ent.currhealth <= 0 then
			ent.hitfx:setColorTransform(3, 0, 0, random(1, 3)/10)
			ent.hitfx:setY(ent.hitfx:getY()+ent.h/1.1) -- magik XXX
			ent.hitfx:setRotation(random(360))
			ent.hitfx:setScale(random(5, 10)/10)
			ent.bgfxlayer:addChild(ent.hitfx)
			self.tiny.tworld:removeEntity(ent) -- sprite is removed in SDrawable
--			self.tiny.numberofnmes -= 1
		end
]]
		self.tiny.tworld:removeEntity(ent) -- sprite is removed in SDrawable
	end
end

This System spawns a collectible:

  • runs once on init and every game loop (process)
  • there are two kind of collectibles: health and jump attacks (updated in the HUD)
There are quite a bit of commented code you can delete as this Entity is immediately removed

sSpritesSorting.lua

"sSpritesSorting.lua" in the "_S" folder. The code:

SSpritesSorting = Core.class()

function SSpritesSorting:init(xtiny) -- tiny function
	xtiny.processingSystem(self) -- called once on init and every update
	self.spriteslist = xtiny.spriteslist
end

function SSpritesSorting:filter(ent) -- tiny function
	return ent.sprite
end

function SSpritesSorting:onAdd(ent) -- tiny function
--	print("SSpritesSorting added", ent)
	self.spriteslist[ent] = true
end

function SSpritesSorting:onRemove(ent) -- tiny function
--	print("SSpritesSorting removed", ent)
	self.spriteslist[ent] = nil
end

local p1rangetoofar = myappwidth*0.5 -- save some CPU
function SSpritesSorting:process(ent, dt) -- tiny function
	local function fun()
		for k, _ in pairs(self.spriteslist) do
			if ent.currlives <= 0 or k.currlives <= 0 then -- don't sort if dead
				return
			end
			if k.isplayer1 then -- don't sort out of range actors to save frames
				if -(k.pos.x-ent.pos.x)<>(k.pos.x-ent.pos.x) > p1rangetoofar then
					return
				end
			end
			if not ent.body.isonfloor then
				if ent.positionystart < k.positionystart and -- ent is behind
					ent.spritelayer:getChildIndex(ent.sprite) > k.spritelayer:getChildIndex(k.sprite) then -- sprite is in front
					ent.spritelayer:swapChildren(ent.sprite, k.sprite)
				end
			else
				if ent.pos.y < k.pos.y and -- ent is behind
					ent.spritelayer:getChildIndex(ent.sprite) > k.spritelayer:getChildIndex(k.sprite) then -- sprite is in front
					ent.spritelayer:swapChildren(ent.sprite, k.sprite)
				end
			end
		end
		Core.yield(0.5)
	end
	Core.asyncCall(fun) -- profiler seems to be faster without asyncCall (because of pairs traversing?)
end

Finally this System sorts the actors on the y axis:

  • runs once on init and every game loop (process)
  • there is a distinction between the actor being on floor and jumping

DEBUG SYSTEMS

It would be difficult to accurately position the hit and hurt boxes, the collision boxes, ... without visual cues.

Debug systems help us with the above. Fortunately they are small and quite simple.

sDebugCollision.lua

"sDebugCollision.lua" in the "_S" folder. The code:

SDebugCollision = Core.class()

function SDebugCollision:init(xtiny) -- tiny function
	xtiny.processingSystem(self) -- called once on init and every update
end

function SDebugCollision:filter(ent) -- tiny function
	return ent.collbox
end

function SDebugCollision:onAdd(ent) -- tiny function
	local debugcolor = 0xff00ff
	if ent.isplayer1 then debugcolor = 0x00ffff end
	ent.debug = Pixel.new(debugcolor, 0.25, ent.collbox.w, ent.collbox.h)
	ent.spritelayer:addChild(ent.debug)
end

function SDebugCollision:onRemove(ent) -- tiny function
	ent.spritelayer:removeChild(ent.debug)
end

function SDebugCollision:process(ent, dt) -- tiny function
--	ent.debug:setPosition(ent.x, ent.y)
	ent.debug:setPosition(ent.pos)
end

This System displays the actors collision box.

sDebugHitBoxNme.lua

"sDebugHitBoxNme.lua" in the "_S" folder. The code:

SDebugHitBoxNme = Core.class()

function SDebugHitBoxNme:init(xtiny, xshowbox) -- tiny function
	xtiny.processingSystem(self) -- called once on init and every update
	self.showbox = xshowbox
end

function SDebugHitBoxNme:filter(ent) -- tiny function
	return (ent.headhitboxattack1 or ent.headhitboxattack2 or ent.spinehitboxattack1 or ent.spinehitboxattack2 or
		ent.headhitboxjattack1 or ent.spinehitboxjattack1) and not ent.isplayer1
end

function SDebugHitBoxNme:onAdd(ent) -- tiny function
	-- debugheadhitboxp1
	if ent.headhitboxattack1 then
		ent.debugheadhitboxp1 = Pixel.new(0xaa0000, 0.5, ent.headhitboxattack1.w, ent.headhitboxattack1.h)
		ent.debugheadhitboxp1:setAnchorPoint(0.5, 0.5)
		ent.spritelayer:addChild(ent.debugheadhitboxp1)
		ent.debugheadhitboxp1:setVisible(self.showbox[1]) -- granular debugging
	end
	-- debugheadhitboxp2
	if ent.headhitboxattack2 then
		ent.debugheadhitboxp2 = Pixel.new(0xaa5500, 0.5, ent.headhitboxattack2.w, ent.headhitboxattack2.h)
		ent.debugheadhitboxp2:setAnchorPoint(0.5, 0.5)
		ent.spritelayer:addChild(ent.debugheadhitboxp2)
		ent.debugheadhitboxp2:setVisible(self.showbox[2]) -- granular debugging
	end
	-- debugspinehitboxk1
	if ent.spinehitboxattack1 then
		ent.debugspinehitboxk1 = Pixel.new(0x005500, 0.5, ent.spinehitboxattack1.w, ent.spinehitboxattack1.h)
		ent.debugspinehitboxk1:setAnchorPoint(0.5, 0.5)
		ent.spritelayer:addChild(ent.debugspinehitboxk1)
		ent.debugspinehitboxk1:setVisible(self.showbox[3]) -- granular debugging
	end
	-- debugspinehitboxk2
	if ent.spinehitboxattack2 then
		ent.debugspinehitboxk2 = Pixel.new(0x00aa00, 0.5, ent.spinehitboxattack2.w, ent.spinehitboxattack2.h)
		ent.debugspinehitboxk2:setAnchorPoint(0.5, 0.5)
		ent.spritelayer:addChild(ent.debugspinehitboxk2)
		ent.debugspinehitboxk2:setVisible(self.showbox[4]) -- granular debugging
	end
	-- debugheadhitboxjp1
	if ent.headhitboxjattack1 then
		ent.debugheadhitboxjp1 = Pixel.new(0xaaaa00, 0.5, ent.headhitboxjattack1.w, ent.headhitboxjattack1.h)
		ent.debugheadhitboxjp1:setAnchorPoint(0.5, 0.5)
		ent.spritelayer:addChild(ent.debugheadhitboxjp1)
		ent.debugheadhitboxjp1:setVisible(self.showbox[5]) -- granular debugging
	end
	-- debugspinehitboxjk1
	if ent.spinehitboxjattack1 then
		ent.debugspinehitboxjk1 = Pixel.new(0x00ff00, 0.5, ent.spinehitboxjattack1.w, ent.spinehitboxjattack1.h)
		ent.debugspinehitboxjk1:setAnchorPoint(0.5, 0.5)
		ent.spritelayer:addChild(ent.debugspinehitboxjk1)
		ent.debugspinehitboxjk1:setVisible(self.showbox[6]) -- granular debugging
	end
end

function SDebugHitBoxNme:onRemove(ent) -- tiny function
	if ent.headhitboxattack1 then ent.spritelayer:removeChild(ent.debugheadhitboxp1) end
	if ent.headhitboxattack2 then ent.spritelayer:removeChild(ent.debugheadhitboxp2) end
	if ent.spinehitboxattack1 then ent.spritelayer:removeChild(ent.debugspinehitboxk1) end
	if ent.spinehitboxattack2 then ent.spritelayer:removeChild(ent.debugspinehitboxk2) end
	if ent.headhitboxjattack1 then ent.spritelayer:removeChild(ent.debugheadhitboxjp1) end
	if ent.spinehitboxjattack1 then ent.spritelayer:removeChild(ent.debugspinehitboxjk1) end
end

function SDebugHitBoxNme:process(ent, dt) -- tiny function
	local function fun()
		if ent.headhitboxattack1 then
			ent.debugheadhitboxp1:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.headhitboxattack1.x*ent.flip), ent.headhitboxattack1.y))
		end
		if ent.headhitboxattack2 then
			ent.debugheadhitboxp2:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.headhitboxattack2.x*ent.flip), ent.headhitboxattack2.y))
		end
		if ent.spinehitboxattack1 then
			ent.debugspinehitboxk1:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.spinehitboxattack1.x*ent.flip), ent.spinehitboxattack1.y))
		end
		if ent.spinehitboxattack2 then
			ent.debugspinehitboxk2:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.spinehitboxattack2.x*ent.flip), ent.spinehitboxattack2.y))
		end
		if ent.headhitboxjattack1 then
			ent.debugheadhitboxjp1:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.headhitboxjattack1.x*ent.flip), ent.headhitboxjattack1.y))
		end
		if ent.spinehitboxjattack1 then
			ent.debugspinehitboxjk1:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.spinehitboxjattack1.x*ent.flip), ent.spinehitboxjattack1.y))
		end
		Core.yield(1)
	end
	Core.asyncCall(fun)
end

This System displays the enemies hit boxes when available.

sDebugHitBoxPlayer.lua

"sDebugHitBoxPlayer.lua" in the "_S" folder. The code:

SDebugHitBoxPlayer = Core.class()

function SDebugHitBoxPlayer:init(xtiny, xshowbox) -- tiny function
	xtiny.processingSystem(self) -- called once on init and every update
	self.showbox = xshowbox
end

function SDebugHitBoxPlayer:filter(ent) -- tiny function
	return (ent.headhitboxattack1 or ent.headhitboxattack2 or ent.spinehitboxattack1 or ent.spinehitboxattack2 or
		ent.headhitboxjattack1 or ent.spinehitboxjattack1) and not ent.isnme
end

function SDebugHitBoxPlayer:onAdd(ent) -- tiny function
	-- debugheadhitboxp1
	if ent.headhitboxattack1 then
		ent.debugheadhitboxp1 = Pixel.new(0xaa0000, 0.5, ent.headhitboxattack1.w, ent.headhitboxattack1.h)
		ent.debugheadhitboxp1:setAnchorPoint(0.5, 0.5)
		ent.spritelayer:addChild(ent.debugheadhitboxp1)
		ent.debugheadhitboxp1:setVisible(self.showbox[1]) -- granular debugging
	end
	-- debugheadhitboxp2
	if ent.headhitboxattack2 then
		ent.debugheadhitboxp2 = Pixel.new(0xaa5500, 0.5, ent.headhitboxattack2.w, ent.headhitboxattack2.h)
		ent.debugheadhitboxp2:setAnchorPoint(0.5, 0.5)
		ent.spritelayer:addChild(ent.debugheadhitboxp2)
		ent.debugheadhitboxp2:setVisible(self.showbox[2]) -- granular debugging
	end
	-- debugspinehitboxk1
	if ent.spinehitboxattack1 then
		ent.debugspinehitboxk1 = Pixel.new(0x005500, 0.5, ent.spinehitboxattack1.w, ent.spinehitboxattack1.h)
		ent.debugspinehitboxk1:setAnchorPoint(0.5, 0.5)
		ent.spritelayer:addChild(ent.debugspinehitboxk1)
		ent.debugspinehitboxk1:setVisible(self.showbox[3]) -- granular debugging
	end
	-- debugspinehitboxk2
	if ent.spinehitboxattack2 then
		ent.debugspinehitboxk2 = Pixel.new(0x00aa00, 0.5, ent.spinehitboxattack2.w, ent.spinehitboxattack2.h)
		ent.debugspinehitboxk2:setAnchorPoint(0.5, 0.5)
		ent.spritelayer:addChild(ent.debugspinehitboxk2)
		ent.debugspinehitboxk2:setVisible(self.showbox[4]) -- granular debugging
	end
	-- debugheadhitboxjp1
	if ent.headhitboxjattack1 then
		ent.debugheadhitboxjp1 = Pixel.new(0xaaaa00, 0.5, ent.headhitboxjattack1.w, ent.headhitboxjattack1.h)
		ent.debugheadhitboxjp1:setAnchorPoint(0.5, 0.5)
		ent.spritelayer:addChild(ent.debugheadhitboxjp1)
		ent.debugheadhitboxjp1:setVisible(self.showbox[5]) -- granular debugging
	end
	-- debugspinehitboxjk1
	if ent.spinehitboxjattack1 then
		ent.debugspinehitboxjk1 = Pixel.new(0x00ff00, 0.5, ent.spinehitboxjattack1.w, ent.spinehitboxjattack1.h)
		ent.debugspinehitboxjk1:setAnchorPoint(0.5, 0.5)
		ent.spritelayer:addChild(ent.debugspinehitboxjk1)
		ent.debugspinehitboxjk1:setVisible(self.showbox[6]) -- granular debugging
	end
end

function SDebugHitBoxPlayer:onRemove(ent) -- tiny function
	if ent.headhitboxattack1 then ent.spritelayer:removeChild(ent.debugheadhitboxp1) end
	if ent.headhitboxattack2 then ent.spritelayer:removeChild(ent.debugheadhitboxp2) end
	if ent.spinehitboxattack1 then ent.spritelayer:removeChild(ent.debugspinehitboxk1) end
	if ent.spinehitboxattack2 then ent.spritelayer:removeChild(ent.debugspinehitboxk2) end
	if ent.headhitboxjattack1 then ent.spritelayer:removeChild(ent.debugheadhitboxjp1) end
	if ent.spinehitboxjattack1 then ent.spritelayer:removeChild(ent.debugspinehitboxjk1) end
end

function SDebugHitBoxPlayer:process(ent, dt) -- tiny function
	local function fun()
		if ent.headhitboxattack1 then
			ent.debugheadhitboxp1:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.headhitboxattack1.x*ent.flip), ent.headhitboxattack1.y))
		end
		if ent.headhitboxattack2 then
			ent.debugheadhitboxp2:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.headhitboxattack2.x*ent.flip), ent.headhitboxattack2.y))
		end
		if ent.spinehitboxattack1 then
			ent.debugspinehitboxk1:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.spinehitboxattack1.x*ent.flip), ent.spinehitboxattack1.y))
		end
		if ent.spinehitboxattack2 then
			ent.debugspinehitboxk2:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.spinehitboxattack2.x*ent.flip), ent.spinehitboxattack2.y))
		end
		if ent.headhitboxjattack1 then
			ent.debugheadhitboxjp1:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.headhitboxjattack1.x*ent.flip), ent.headhitboxjattack1.y))
		end
		if ent.spinehitboxjattack1 then
			ent.debugspinehitboxjk1:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.spinehitboxjattack1.x*ent.flip), ent.spinehitboxjattack1.y))
		end
		Core.yield(1)
	end
	Core.asyncCall(fun)
end

This System displays the player hit boxes when available.

sDebugHurtBoxNme.lua

"sDebugHurtBoxNme.lua" in the "_S" folder. The code:

SDebugHurtBoxNme = Core.class()

function SDebugHurtBoxNme:init(xtiny) -- tiny function
	xtiny.processingSystem(self) -- called once on init and every update
end

function SDebugHurtBoxNme:filter(ent) -- tiny function
	return (ent.headhurtbox or ent.spinehurtbox) and not ent.isplayer1
end

function SDebugHurtBoxNme:onAdd(ent) -- tiny function
	-- debugheadhurtbox
	ent.debugheadhurtbox = Pixel.new(0x5500ff, 0.5, ent.headhurtbox.w, ent.headhurtbox.h)
	ent.debugheadhurtbox:setAnchorPoint(0.5, 0.5)
	ent.spritelayer:addChild(ent.debugheadhurtbox)
	-- debugspinehurtbox
	ent.debugspinehurtbox = Pixel.new(0xff00ff, 0.5, ent.spinehurtbox.w, ent.spinehurtbox.h)
	ent.debugspinehurtbox:setAnchorPoint(0.5, 0.5)
	ent.spritelayer:addChild(ent.debugspinehurtbox)
end

function SDebugHurtBoxNme:onRemove(ent) -- tiny function
	if not ent.isdestructibleobject then -- isdestructibleobject is somehow already removed!
		ent.spritelayer:removeChild(ent.debugheadhurtbox)
		ent.spritelayer:removeChild(ent.debugspinehurtbox)
	end
end

function SDebugHurtBoxNme:process(ent, dt) -- tiny function
	local function fun()
		ent.debugheadhurtbox:setPosition(ent.pos+vector(ent.collbox.w/2+(ent.headhurtbox.x*ent.flip), ent.headhurtbox.y))
		ent.debugspinehurtbox:setPosition(ent.pos+vector(ent.collbox.w/2+(ent.spinehurtbox.x*ent.flip), ent.spinehurtbox.y))
		Core.yield(1)
	end
	Core.asyncCall(fun)
end

This System displays the enemies and breakable objects hurt boxes.

sDebugHurtBoxPlayer.lua

"sDebugHurtBoxPlayer.lua" in the "_S" folder. The code:

SDebugHurtBoxPlayer = Core.class()

function SDebugHurtBoxPlayer:init(xtiny) -- tiny function
	xtiny.processingSystem(self) -- called once on init and every update
end

function SDebugHurtBoxPlayer:filter(ent) -- tiny function
	return (ent.headhurtbox or ent.spinehurtbox) and not ent.isnme
end

function SDebugHurtBoxPlayer:onAdd(ent) -- tiny function
	-- debugheadhurtbox
	ent.debugheadhurtbox = Pixel.new(0x5500ff, 0.5, ent.headhurtbox.w, ent.headhurtbox.h)
	ent.debugheadhurtbox:setAnchorPoint(0.5, 0.5)
	ent.spritelayer:addChild(ent.debugheadhurtbox)
	-- debugspinehurtbox
	ent.debugspinehurtbox = Pixel.new(0xff00ff, 0.5, ent.spinehurtbox.w, ent.spinehurtbox.h)
	ent.debugspinehurtbox:setAnchorPoint(0.5, 0.5)
	ent.spritelayer:addChild(ent.debugspinehurtbox)
end

function SDebugHurtBoxPlayer:onRemove(ent) -- tiny function
	ent.spritelayer:removeChild(ent.debugheadhurtbox)
	ent.spritelayer:removeChild(ent.debugspinehurtbox)
end

function SDebugHurtBoxPlayer:process(ent, dt) -- tiny function
	ent.debugheadhurtbox:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.headhurtbox.x*ent.flip), ent.headhurtbox.y))
	ent.debugspinehurtbox:setPosition(ent.pos + vector(ent.collbox.w/2+(ent.spinehurtbox.x*ent.flip), ent.spinehurtbox.y))
end

This System displays the player hurt boxes.

sDebugSpriteSorting.lua

"sDebugSpriteSorting.lua" in the "_S" folder. The code:

SDebugSpriteSorting = Core.class()

function SDebugSpriteSorting:init(xtiny) -- tiny function
	xtiny.processingSystem(self) -- called once on init and every update
end

function SDebugSpriteSorting:filter(ent) -- tiny function
	return ent.sprite
end

function SDebugSpriteSorting:onAdd(ent) -- tiny function
	-- debugposition
	ent.debugposition = Pixel.new(0xaa5500, 1, 16, 16)
	ent.debugposition:setAnchorPoint(0.5, 0.5)
	if ent.isplayer1 then ent.debugposition:setColor(0xaa5500, 1) end
	ent.spritelayer:addChild(ent.debugposition)
	-- debugstartyposition
	ent.debugstartyposition = Pixel.new(0xaa557f, 1, 16, 16)
	ent.debugstartyposition:setAnchorPoint(0.5, 0.5)
	if ent.isplayer1 then ent.debugstartyposition:setColor(0xaa557f, 1) end
	ent.spritelayer:addChild(ent.debugstartyposition)
end

function SDebugSpriteSorting:onRemove(ent) -- tiny function
	ent.spritelayer:removeChild(ent.debugposition)
	ent.spritelayer:removeChild(ent.debugstartyposition)
end

function SDebugSpriteSorting:process(ent, dt) -- tiny function
	ent.debugposition:setPosition(ent.pos)
	ent.debugstartyposition:setPosition(ent.pos.x, ent.positionystart)
end

This System displays the actors y position.

Next?

Congratulations! We have finished our game.

Let's add the final scene: YOU WIN!


Prev.: Tuto tiny-ecs beatemup Part 10 Systems 2
Next: Tuto tiny-ecs beatemup Part 12 You Win


Tutorial - tiny-ecs beatemup