Difference between revisions of "Tuto tiny-ecs demo Part 8 Enemies"

From GiderosMobile
(Created page with "__TOC__ We continue with our tiny-ecs demo. It is time to add some "enemies". == Entity enemy1 == First we create an entity of type enemy1. In the entites folder "_E", crea...")
 
Line 28: Line 28:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
We start by adding some ids, a sprite layer and a sprite to see our enemy1. The sprite here is a Pixel with a random color.
+
We start by adding some ids, a sprite layer and a sprite. The sprite here is a Pixel with a random color.
  
 
We add some more parameters like position and health.
 
We add some more parameters like position and health.
  
 
Finally we add the body component so the entity can move.
 
Finally we add the body component so the entity can move.
 +
 +
'''Please note in the init parameters, there are two unused yet variables: dx and dy. They will be used when we add an artificial intelligence (AI) component later'''.
  
 
'''With ECS it is easy to build your game, you add/remove parameters and components as you need'''.
 
'''With ECS it is easy to build your game, you add/remove parameters and components as you need'''.
  
 
== World addEntity ==
 
== World addEntity ==
We add a couple of enemy1 entities to tiny-ecs world.
+
We need to add the enemy1 entity to tiny-ecs world. Let's add a couple of them.
  
 
Please go to the "''LevelX.lua''" file and complete the code as follow:
 
Please go to the "''LevelX.lua''" file and complete the code as follow:
Line 57: Line 59:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
'''You can run the demo and you should be able to see ten enemies placed randomly on the x axis'''.
+
When we add an enemy1 entity to tiny-ecs world, we also add it to an '''nmes''' list so we can iterate through them in our game.
 +
 
 +
'''You can run the demo and you should see ten enemies placed randomly on the x axis'''.
 +
 
 +
== Enemy add AI Component ==
 +
Our enemy1 entities don't do anything yet. Let's equip them with an Artificial Intelligence component.
 +
 
 +
In the components folder "_C", create a file called ''cAI.lua'' for example, and copy the following code:
 +
<syntaxhighlight lang="lua">
 +
CAI = Core.class()
 +
 
 +
function CAI:init(x, y, dx, dy)
 +
self.startpositionx = x
 +
self.startpositiony = y
 +
self.dx = dx -- delta x
 +
self.dy = dy -- delta y
 +
end
 +
</syntaxhighlight>
 +
 
 +
Here, in the '''init''' function, we store an entity starting position and a delta x and y to set how far they can travel.
 +
 
 +
We can now attach this AI component to our enemies in "''eNme1.lua''":
 +
<syntaxhighlight lang="lua">
 +
ENme1 = Core.class()
 +
 
 +
function ENme1:init(xspritelayer, x, y, dx, dy)
 +
-- ids
 +
self.isnme = true
 +
self.isactor = true
 +
-- sprite
 +
self.spritelayer = xspritelayer
 +
self.sprite = Pixel.new(math.random(0xffffff), 1, 32, 64)
 +
-- params
 +
self.x = x
 +
self.y = y
 +
self.health = 10
 +
-- BODY COMPONENT: function CBody:init(xspeed, xjumpspeed)
 +
self.body = CBody.new(4*16, 6*16) -- xspeed, xjumpspeed
 +
self.body.defaultmass = 1
 +
self.body.currmass = self.body.defaultmass
 +
-- AI COMPONENT: function CAI:init(x, y, dx, dy)
 +
self.ai = CAI.new(self.x, self.y, dx, dy)
 +
if self.ai.dx then self.isright = true end -- start moving our enemy1
 +
if self.ai.dy then self.isdown = true end -- start moving our enemy1
 +
end
 +
</syntaxhighlight>
 +
 
 +
'''You can run the demo and the enemies should move to the right'''.
  
== And a System to move our actors ==
+
== Enemy AI System ==
Now we add another system which will be responsible for moving the actors (entities).
+
To make our enemies intelligent we need to create an AI system.
  
In the same systems folder "_S", create a file called ''sDynamicBodies.lua'' for example, and copy the following code:
+
In the systems folder "_S", create a file called ''sAI.lua'' for example, and copy the following code:
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
SDynamicBodies = Core.class()
+
SAI = Core.class()
  
function SDynamicBodies:init(xtiny) -- tiny function
+
function SAI:init(xtiny) -- tiny function
self.tiny = xtiny -- ref so we can remove entities from tiny system
+
xtiny.processingSystem(self) -- called once on init and every frames
self.tiny.processingSystem(self) -- called once on init and every update
 
 
end
 
end
  
function SDynamicBodies:filter(ent) -- tiny function
+
function SAI:filter(ent) -- tiny function
return ent.isactor and ent.body -- only actors with body component
+
return ent.ai
 
end
 
end
  
function SDynamicBodies:onAdd(ent) -- tiny function
+
function SAI:onAdd(ent) -- tiny function
 
end
 
end
  
function SDynamicBodies:onRemove(ent) -- tiny function
+
function SAI:onRemove(ent) -- tiny function
 
end
 
end
  
function SDynamicBodies:process(ent, dt) -- tiny function
+
function SAI:process(ent, dt) -- tiny function
-- velocity
+
if ent.ai.dx and ent.ai.dy then -- DIAGONAL
if ent.isleft and not ent.isright then -- LEFT
+
if ent.x >= ent.ai.startpositionx + ent.ai.dx then
ent.body.vx = -ent.body.speed
+
ent.isleft, ent.isright = true, false
elseif ent.isright and not ent.isleft then -- RIGHT
+
ent.isup, ent.isdown = true, false
ent.body.vx = ent.body.speed
+
elseif ent.x <= ent.ai.startpositionx then
else
+
ent.isleft, ent.isright = false, true
ent.body.vx = 0
+
ent.isup, ent.isdown = false, true
 +
end
 +
elseif ent.ai.dx then -- HORIZONTAL
 +
if ent.x >= ent.ai.startpositionx + ent.ai.dx then
 +
ent.isleft, ent.isright = true, false
 +
elseif ent.x <= ent.ai.startpositionx then
 +
ent.isleft, ent.isright = false, true
 +
end
 +
elseif ent.ai.dy then -- VERTICAL
 +
if ent.y >= ent.ai.startpositiony + ent.ai.dy then
 +
ent.isup, ent.isdown = true, false
 +
elseif ent.y <= ent.ai.startpositiony then
 +
ent.isup, ent.isdown = false, true
 +
end
 
end
 
end
-- move
 
ent.x += ent.body.vx * dt
 
ent.sprite:setPosition(ent.x, ent.y)
 
 
end
 
end
 
</syntaxhighlight>
 
</syntaxhighlight>
  
All systems follow the same pattern, they are easy to create!
+
This is a simple AI system, which switches an entity direction when it reaches some limits (delta x, delta y).
 
 
Here, in the '''init''' function, we create a reference to the ''xtiny'' parameter, so we can use it later to add or remove actors from tiny-ecs world.
 
  
Then, we tell tiny-ecs that this system needs to be '''updated''' each game loop (cf: [[Tuto_tiny-ecs_demo_Part_3_tiny-ecs_World]], '''self.tiny.world:update(dt)''').
+
Finally we need to add this AI system to tiny-ecs world.
  
In the '''filter''' function, we tell tiny-ecs that this system applies to entities with an '''id''' of ''isactor'' and ''body'' ('''remember that a component can serve as an id''').
 
  
Finally, in the '''process''' function, we check if an actor is going left or right to add velocity to its body. The velocity will change the actor position.
 
  
 
== Next? ==
 
== Next? ==

Revision as of 01:06, 21 December 2023

We continue with our tiny-ecs demo. It is time to add some "enemies".

Entity enemy1

First we create an entity of type enemy1.

In the entites folder "_E", create a file called "eNme1.lua" for example and copy the following code:

ENme1 = Core.class()

function ENme1:init(xspritelayer, x, y, dx, dy)
	-- ids
	self.isnme = true
	self.isactor = true
	-- sprite
	self.spritelayer = xspritelayer
	self.sprite = Pixel.new(math.random(0xffffff), 1, 32, 64)
	-- params
	self.x = x
	self.y = y
	self.health = 10
	-- BODY COMPONENT: function CBody:init(xspeed, xjumpspeed)
	self.body = CBody.new(4*16, 6*16) -- xspeed, xjumpspeed
	self.body.defaultmass = 1
	self.body.currmass = self.body.defaultmass
end

We start by adding some ids, a sprite layer and a sprite. The sprite here is a Pixel with a random color.

We add some more parameters like position and health.

Finally we add the body component so the entity can move.

Please note in the init parameters, there are two unused yet variables: dx and dy. They will be used when we add an artificial intelligence (AI) component later.

With ECS it is easy to build your game, you add/remove parameters and components as you need.

World addEntity

We need to add the enemy1 entity to tiny-ecs world. Let's add a couple of them.

Please go to the "LevelX.lua" file and complete the code as follow:

	...
	-- tiny-ecs
	self.tiny = require "classes/tiny-ecs"
	self.tiny.world = self.tiny.world()
	-- some enemies (xspritelayer, x, y, dx, dy)
	local nmes = {}
	for i = 1, 10 do -- we create 10 enemies
		nmes[i] = ENme1.new(self.camera, math.random(24)*16, 10*16, math.random(12)*16, 0)
		self.tiny.world:addEntity(nmes[i])
	end
	-- the player (xspritelayer, x, y)
	self.player1 = EPlayer1.new(self.camera, 12*16, 10*16)
	self.tiny.world:addEntity(self.player1)
	...

When we add an enemy1 entity to tiny-ecs world, we also add it to an nmes list so we can iterate through them in our game.

You can run the demo and you should see ten enemies placed randomly on the x axis.

Enemy add AI Component

Our enemy1 entities don't do anything yet. Let's equip them with an Artificial Intelligence component.

In the components folder "_C", create a file called cAI.lua for example, and copy the following code:

CAI = Core.class()

function CAI:init(x, y, dx, dy)
	self.startpositionx = x
	self.startpositiony = y
	self.dx = dx -- delta x
	self.dy = dy -- delta y
end

Here, in the init function, we store an entity starting position and a delta x and y to set how far they can travel.

We can now attach this AI component to our enemies in "eNme1.lua":

ENme1 = Core.class()

function ENme1:init(xspritelayer, x, y, dx, dy)
	-- ids
	self.isnme = true
	self.isactor = true
	-- sprite
	self.spritelayer = xspritelayer
	self.sprite = Pixel.new(math.random(0xffffff), 1, 32, 64)
	-- params
	self.x = x
	self.y = y
	self.health = 10
	-- BODY COMPONENT: function CBody:init(xspeed, xjumpspeed)
	self.body = CBody.new(4*16, 6*16) -- xspeed, xjumpspeed
	self.body.defaultmass = 1
	self.body.currmass = self.body.defaultmass
	-- AI COMPONENT: function CAI:init(x, y, dx, dy)
	self.ai = CAI.new(self.x, self.y, dx, dy)
	if self.ai.dx then self.isright = true end -- start moving our enemy1
	if self.ai.dy then self.isdown = true end -- start moving our enemy1
end

You can run the demo and the enemies should move to the right.

Enemy AI System

To make our enemies intelligent we need to create an AI system.

In the systems folder "_S", create a file called sAI.lua for example, and copy the following code:

SAI = Core.class()

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

function SAI:filter(ent) -- tiny function
	return ent.ai
end

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

function SAI:onRemove(ent) -- tiny function
end

function SAI:process(ent, dt) -- tiny function
	if ent.ai.dx and ent.ai.dy then -- DIAGONAL
		if ent.x >= ent.ai.startpositionx + ent.ai.dx then
			ent.isleft, ent.isright = true, false
			ent.isup, ent.isdown = true, false
		elseif ent.x <= ent.ai.startpositionx then
			ent.isleft, ent.isright = false, true
			ent.isup, ent.isdown = false, true
		end
	elseif ent.ai.dx then -- HORIZONTAL
		if ent.x >= ent.ai.startpositionx + ent.ai.dx then
			ent.isleft, ent.isright = true, false
		elseif ent.x <= ent.ai.startpositionx then
			ent.isleft, ent.isright = false, true
		end
	elseif ent.ai.dy then -- VERTICAL
		if ent.y >= ent.ai.startpositiony + ent.ai.dy then
			ent.isup, ent.isdown = true, false
		elseif ent.y <= ent.ai.startpositiony then
			ent.isup, ent.isdown = false, true
		end
	end
end

This is a simple AI system, which switches an entity direction when it reaches some limits (delta x, delta y).

Finally we need to add this AI system to tiny-ecs world.


Next?

In the next part, we ...


Prev.: Tuto tiny-ecs demo Part 7 Systems to move actors
Next: xxx


Tutorial - tiny-ecs demo