Difference between revisions of "Tuto tiny-ecs demo Part 10 Conclusion"

From GiderosMobile
(Created page with "__TOC__ In this chapter we will make the player1 able to "shoot" and "hurt" enemies. This will be done in two parts: first enabling the player1 "shoot" action, then hurting...")
 
Line 1: Line 1:
 
__TOC__
 
__TOC__
  
In this chapter we will make the player1 able to "shoot" and "hurt" enemies.
+
So this is the last chapter.
  
This will be done in two parts: first enabling the player1 "shoot" action, then hurting the enemies with some fx and make them "die".
+
== Adding Buildings ==
 +
Let's finish the '''tiny-ecs demo''' by adding some buildings to our level1.
  
== Player1 can Shoot ==
+
In the entities folder "_E", let's add a file called "''eBuilding.lua''" for example.
We implement player1 can shoot in the '''SDynamicBodies''' system.
 
  
Please go to the "''sDynamicBodies.lua''" file to add some code.
+
This is the code for an '''EBuilding''' entity:
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
SDynamicBodies = Core.class()
+
EBuilding = Core.class()
  
function SDynamicBodies:init(xtiny, xnmes) -- tiny function
+
function EBuilding:init(xspritelayer, x, y, w, h)
self.tiny = xtiny -- ref so we can remove entities from tiny system
+
-- sprite
self.tiny.processingSystem(self) -- called once on init and every update
+
self.spritelayer = xspritelayer
self.nmes = xnmes -- a list of nmes we can hurt
+
self.sprite = Pixel.new(math.random(0xffffff), 1, w, h)
 +
self.sprite:setAnchorPoint(0.5, 1)
 +
-- params
 +
self.x = x
 +
self.y = y
 
end
 
end
-- ...
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
In the '''init''' function we add the list of enemies to the function signature and we make that list available to the other functions.
+
The only thing here is to change the anchor point of the '''EBuilding''' entity.
  
Then in the '''process''' function, we check if the player presses the ''action1'' button (the spacebar) and we set a random enemy in the '''nmes''' list to be hurt.
+
Now in the "''LevelX.lua''" file we add some buildings to tiny-ecs world:
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
function SDynamicBodies:process(ent, dt) -- tiny function
 
 
-- ...
 
-- ...
-- actions (player1)
+
-- tiny-ecs
if ent.isplayer1 and ent.isaction1 then
+
if self.tiny == nil then
ent.isaction1 = false
+
self.tiny = require "classes/tiny-ecs"
if #self.nmes > 0 then -- check nmes list is not empty
 
self.nmes[math.random(#self.nmes)].isdirty = true
 
else -- nmes list is empty
 
print("you killed everybody!")
 
end
 
 
end
 
end
-- move
+
self.tiny.tworld = self.tiny.world()
ent.x += ent.body.vx * dt
+
-- some deco (xspritelayer, x, y, w, h)
ent.sprite:setPosition(ent.x, ent.y)
+
for i = 1, 8 do -- 8 random buildings
end
+
self.tiny.tworld:addEntity(
</syntaxhighlight>
+
EBuilding.new(self.camera,
 
+
math.random(myappwidth), 14*16,
I set the ''hurt'' behavior as being the flag ''isdirty'' (some of my Box2D leftovers).
+
math.random(4*16, myappwidth/4), math.random(8, 12)*16
 
+
)
So every time the player presses the spacebar, a random enemy from the nmes list will get hurt.
+
)
 
 
== Enemies can die ==
 
In order to hurt an enemy we need to add a new System. The system will decrease an enemy ''health'' which will eventually "die".
 
 
 
In the systems folder "_S", create a file called "''sNme1.lua''" for example, and copy the following code:
 
<syntaxhighlight lang="lua">
 
SNme1 = Core.class()
 
 
 
function SNme1:init(xtiny, xnmes) -- 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.nmes = xnmes
 
end
 
 
 
function SNme1:filter(ent) -- tiny function
 
return ent.isnme
 
end
 
 
 
function SNme1:onAdd(ent) -- tiny function
 
end
 
 
 
function SNme1:onRemove(ent) -- tiny function
 
print("SNme1:onRemove")
 
end
 
 
 
function SNme1:process(ent, dt) -- tiny function
 
for i = #self.nmes, 1, -1 do -- scan in reverse
 
if self.nmes[i].isdirty then -- hit
 
self.nmes[i].health -= 1
 
self.nmes[i].washurt = 5 -- timer for a flash effect
 
self.nmes[i].sprite:setColorTransform(2, 0, 0, 3) -- the flash effect (a bright red color)
 
self.nmes[i].isdirty = false
 
if self.nmes[i].health <= 0 then -- dead :-(
 
self.tiny.tworld:removeEntity(self.nmes[i]) -- sprite removed from sprite layer in SDrawable
 
self.nmes[i] = nil -- remove from table
 
table.remove(self.nmes, i) -- remove from table
 
end
 
end
 
 
end
 
end
end
+
-- some enemies (xspritelayer, x, y, dx, dy)
 +
local nmes = {}
 +
for i = 1, 10 do -- we create 10 enemies
 +
-- ...
 
</syntaxhighlight>
 
</syntaxhighlight>
  
In this system, when an entity is dirty (hurt), we decrease its health, set a timer for a flashing effect and if it dies, we remove it from tiny-ecs world and the '''nmes''' list.
+
We add 8 randomly positionned and sized EBuilding entities.
  
Please note the sprite is removed from the sprite layer in the '''SDrawable''' system:
+
'''I hope you like the demo'''!
<syntaxhighlight lang="lua">
 
function SDrawable:onRemove(ent) -- tiny function
 
ent.spritelayer:removeChild(ent.sprite)
 
end
 
</syntaxhighlight>
 
  
Let's add the flashing effect to the '''SDynamicBodies''' system like so:
+
== Conclusion ==
<syntaxhighlight lang="lua">
+
This was my take on using '''tiny-ecs'''. To sum up:
function SDynamicBodies:process(ent, dt) -- tiny function
+
* tiny-ecs has a world
-- hurt fx
+
* a world is made of entities and systems
if ent.washurt and ent.washurt > 0 then
+
* entities have ids
ent.washurt -= 1
+
* entities can have components
if ent.washurt <= 0 then
+
* components can serve as ids
ent.sprite:setColorTransform(1, 1, 1, 1)
+
* a system filters the entities to act upon based on entities ids
end
+
* a system can be run once or every update
end
 
-- movement
 
if ent.isleft and not ent.isright then -- LEFT
 
ent.body.vx = -ent.body.speed
 
elseif ent.isright and not ent.isleft then -- RIGHT
 
ent.body.vx = ent.body.speed
 
-- ...
 
</syntaxhighlight>
 
 
 
If an entity counter ''washurt'' is greater than 0, we decrease it. When the counter reaches zero we set the entity sprite color back to normal.
 
 
 
== Action ==
 
To see the result of our work, we need to add the '''SNme1''' system to tiny-ecs world.
 
  
In the "''levelX.lua''" file add the '''SNme1''' system:
+
'''I really enjoy making games using the ECS paradigm, and I hope to have given you the keys to experiment with it'''!
<syntaxhighlight lang="lua">
 
-- ...
 
-- add systems to tiny-ecs
 
self.tiny.tworld:add(
 
SDrawable.new(self.tiny),
 
SDynamicBodies.new(self.tiny, nmes), -- add the nmes list here too!
 
SPlayer1Control.new(self.tiny),
 
SAI.new(self.tiny),
 
SNme1.new(self.tiny, nmes)
 
)
 
-- ...
 
</syntaxhighlight>
 
  
'''Remember we changed the ''SDynamicBodies'' init function signature, so you need to add the new parameter to the System here too'''!
+
'''Thanks for reading'''!
  
That's it!
+
== Gideros Project ==
  
'''You can run the demo and press the spacebar. A random enemy should get hit and eventually die, until you kill everyone'''.
 
  
  

Revision as of 02:30, 22 December 2023

So this is the last chapter.

Adding Buildings

Let's finish the tiny-ecs demo by adding some buildings to our level1.

In the entities folder "_E", let's add a file called "eBuilding.lua" for example.

This is the code for an EBuilding entity:

EBuilding = Core.class()

function EBuilding:init(xspritelayer, x, y, w, h)
	-- sprite
	self.spritelayer = xspritelayer
	self.sprite = Pixel.new(math.random(0xffffff), 1, w, h)
	self.sprite:setAnchorPoint(0.5, 1)
	-- params
	self.x = x
	self.y = y
end

The only thing here is to change the anchor point of the EBuilding entity.

Now in the "LevelX.lua" file we add some buildings to tiny-ecs world:

	-- ...
	-- tiny-ecs
	if self.tiny == nil then
		self.tiny = require "classes/tiny-ecs"
	end
	self.tiny.tworld = self.tiny.world()
	-- some deco (xspritelayer, x, y, w, h)
	for i = 1, 8 do -- 8 random buildings
		self.tiny.tworld:addEntity(
			EBuilding.new(self.camera,
				math.random(myappwidth), 14*16,
				math.random(4*16, myappwidth/4), math.random(8, 12)*16
			)
		)
	end
	-- some enemies (xspritelayer, x, y, dx, dy)
	local nmes = {}
	for i = 1, 10 do -- we create 10 enemies
	-- ...

We add 8 randomly positionned and sized EBuilding entities.

I hope you like the demo!

Conclusion

This was my take on using tiny-ecs. To sum up:

  • tiny-ecs has a world
  • a world is made of entities and systems
  • entities have ids
  • entities can have components
  • components can serve as ids
  • a system filters the entities to act upon based on entities ids
  • a system can be run once or every update

I really enjoy making games using the ECS paradigm, and I hope to have given you the keys to experiment with it!

Thanks for reading!

Gideros Project

Prev.: Tuto tiny-ecs demo Part 9 Player Shoots Enemies Die
END


Tutorial - tiny-ecs demo