Difference between revisions of "Tuto tiny-ecs 2d platformer Part 8 more entities"

From GiderosMobile
(wip)
 
(wip)
Line 2: Line 2:
  
 
== Some more Entities ==
 
== Some more Entities ==
A game is made of many "''actors''" besides the player and the enemies. Here we will add more "actors" aka entities (collectibles, doors, keys, ...).
+
A game is made of many "''actors''" besides the players and the enemies. Here we will add more "actors" aka entities (collectibles, doors, keys, ...).
  
 
  '''As I have mentioned before, components are shared amongst entities and this is exactly the case here too'''
 
  '''As I have mentioned before, components are shared amongst entities and this is exactly the case here too'''
  
 
== ECollectibles.lua ==
 
== ECollectibles.lua ==
Let's add some collectibles, shall we? Please create a file "'''eCollectibles.lua'''" in the '''"_E"''' folder. The code:
+
Let's add some collectibles, shall we? Please create a file called "'''eCollectibles.lua'''" in the '''"_E"''' folder. The code:
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
 
ECollectibles = Core.class()
 
ECollectibles = Core.class()
Line 67: Line 67:
 
When we create a '''collectible''', we assign it an entity id (eid). Depending on the ''eid'' we will either spawn a '''coin''', a '''life''' (to heal the player) or a '''key''' (to open doors).
 
When we create a '''collectible''', we assign it an entity id (eid). Depending on the ''eid'' we will either spawn a '''coin''', a '''life''' (to heal the player) or a '''key''' (to open doors).
  
The code is quite small and follows the same principle as the previous entities (player1 and enemies). The only thing we add here is an oscillation '''Component''' to give our collectibles some juice. Please create a file called "'''cOscillation.lua'''" in the '''"_C"''' folder. The code:
+
The code is quite small and follows the same principle as the previous entities (player1 and enemies). The only thing we add here is an '''oscillation Component''' to give our collectibles some juice. Please create a file called "'''cOscillation.lua'''" in the '''"_C"''' folder. The code:
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
 
COscillation = Core.class()
 
COscillation = Core.class()
Line 80: Line 80:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
An oscillation System will look for it and act accordingly. '''Easy as E C S ;-)'''
+
An '''oscillation System''' will look for it and act accordingly. '''Easy as E C S ;-)'''
  
 
+
== eDoor.lua ==
 
+
We need some doors keys can open. Please create a file "'''eDoor.lua'''" in the '''"_E"''' folder. The code:
 
 
 
 
== eCollectible.lua ==
 
"'''eCollectible.lua'''" in the '''"_E"''' folder. The code:
 
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
ECollectible = Core.class()
+
EDoor = Core.class()
  
function ECollectible:init(xspritelayer, xpos)
+
function EDoor:init(xid, xspritelayer, xpos, xtexpath, xcolor, w, h, dx, dy, xdir, xspeed, xbgfxlayer)
 +
local function hexToRgb(hex)
 +
return (hex >> 16 & 0xff), (hex >> 8 & 0xff), (hex & 0xff)
 +
end
 
-- ids
 
-- ids
self.iscollectible = true
+
self.isdoor = true
-- sprite layer
+
self.eid = xid -- player1 needs key matching eid
 +
-- sprite layers
 
self.spritelayer = xspritelayer
 
self.spritelayer = xspritelayer
 +
self.bgfxlayer = xbgfxlayer
 
-- params
 
-- params
 
self.pos = xpos
 
self.pos = xpos
self.positionystart = self.pos.y -- for sprite sorting
 
 
self.sx = 1
 
self.sx = 1
 
self.sy = self.sx
 
self.sy = self.sx
self.flip = math.random(100)
+
self.flip = 1
if self.flip > 80 then self.flip = 1
+
if xtexpath then -- texture + color modulate?
else self.flip = -1
+
local tex = Texture.new(xtexpath)
 +
local texsx, texsy = tex:getWidth()/w, tex:getHeight()/h
 +
self.sprite = Pixel.new(tex, w, h, texsx, texsy)
 +
if xcolor then -- color modulate
 +
local r, g, b = hexToRgb(xcolor)
 +
self.sprite:setColorTransform(r/255, g/255, b/255, 1)
 +
end
 +
else -- color only
 +
self.sprite = Pixel.new(xcolor or 0xffffff, 1, w, h)
 
end
 
end
self.totallives = 1
+
self.sprite:setAnchorPoint(0.5, 0.5)
self.currlives = self.totallives
+
self.sprite:setScale(self.sx, self.sy)
 +
self.w, self.h = self.sprite:getWidth(), self.sprite:getHeight()
 
-- COMPONENTS
 
-- COMPONENTS
-- ANIMATION: CAnimation:init(xspritesheetpath, xcols, xrows, xanimspeed, xoffx, xoffy, sx, sy)
+
-- BODY: CBody:init(xmass, xspeed, xupspeed)
local texpath = "gfx/collectible/Dragon Eggs 1.png"
+
self.body = CBody.new(1, xspeed.x, xspeed.y)
local framerate = 1
 
self.animation = CAnimation.new(texpath, 1, 1, framerate, 0, 0, self.sx, self.sy)
 
self.sprite = self.animation.sprite
 
self.sprite:setScale(self.sx*self.flip, self.sy)
 
self.animation.sprite = nil -- free some memory
 
self.w, self.h = self.sprite:getWidth(), self.sprite:getHeight()
 
-- create animations: CAnimation:createAnim(xanimname, xstart, xfinish)
 
self.animation:createAnim(g_ANIM_DEFAULT, 1, 1)
 
self.animation:createAnim(g_ANIM_IDLE_R, 1, 1)
 
-- clean up
 
self.animation.myanimsimgs = nil
 
-- BODY: CBody:init(xspeed, xjumpspeed)
 
self.body = CBody.new(0, 0) -- xspeed, xjumpspeed
 
self.body.defaultmass = 1
 
self.body.currmass = self.body.defaultmass
 
 
-- COLLISION BOX: CCollisionBox:init(xcollwidth, xcollheight)
 
-- COLLISION BOX: CCollisionBox:init(xcollwidth, xcollheight)
local collw, collh = self.w*0.6, self.h*0.6
+
local collw, collh = self.w//1, self.h//1 -- must be round numbers for cbump physics!
 
self.collbox = CCollisionBox.new(collw, collh)
 
self.collbox = CCollisionBox.new(collw, collh)
-- SHADOW: CShadow:init(xparentw, xshadowsx, xshadowsy)
+
-- motion AI: CDistance:init(xstartpos, dx, dy)
self.shadow = CShadow.new(self.w*0.75)
+
self.distance = CDistance.new(self.pos, dx, dy)
-- IDEA: CREATE AN OSCILLATION COMPONENT using body xspeed, xjumpspeed!
+
self.dir = xdir
 +
end
 +
</syntaxhighlight>
 +
 
 +
What's in there? When we create this door Entity we can texture or color it so the doors are not all the same, plus it has a '''distance Component''' to control how far a door can open. Please create a file called "'''cDistance.lua'''" in the '''"_C"''' folder. The code:
 +
<syntaxhighlight lang="lua">
 +
CDistance = Core.class()
 +
 
 +
function CDistance:init(xstartpos, dx, dy)
 +
self.startpos = xstartpos
 +
self.dx = dx -- delta x
 +
self.dy = dy -- delta y
 
end
 
end
 
</syntaxhighlight>
 
</syntaxhighlight>
  
You get the idea ;-)
+
A '''System''' will look for it and act accordingly.
 +
 
 +
 
 +
 
 +
 
  
 
  '''We are done making all our entities!!!'''
 
  '''We are done making all our entities!!!'''

Revision as of 21:47, 25 October 2025

Some more Entities

A game is made of many "actors" besides the players and the enemies. Here we will add more "actors" aka entities (collectibles, doors, keys, ...).

As I have mentioned before, components are shared amongst entities and this is exactly the case here too

ECollectibles.lua

Let's add some collectibles, shall we? Please create a file called "eCollectibles.lua" in the "_E" folder. The code:

ECollectibles = Core.class()

function ECollectibles:init(xid, xspritelayer, xpos, xspeed, xdx, xdy)
	-- ids
	self.iscollectible = true
	self.eid = xid
	self.doanimate = true -- to save some cpu
	-- sprite layer
	self.spritelayer = xspritelayer
	-- params
	self.pos = xpos
	self.sx = 1
	self.sy = self.sx
	self.flip = 1
	self.totallives = 1
	self.currlives = self.totallives
	-- default to coin
	local framerate = 1/10 -- magik XXX
	local texpath = "gfx/collectibles/Coin_A_0_0001.png"
	local cols, rows = 4, 3
	self.sx = 0.7
	if self.eid == "lives" then -- heart
		texpath = "gfx/collectibles/Heart_2_0001.png"
		cols, rows = 4, 3
		self.sx = 0.8
	elseif self.eid:find("door") then -- key
		texpath = "gfx/collectibles/Key_3_0001.png"
		cols, rows = 4, 3
		self.sx = 0.8
	end
	self.sy = self.sx
	-- COMPONENTS
	-- ANIMATION
	local anims = {} -- table to hold actor animations
	local animsimgs = {} -- table to hold actor animations images
	-- CAnimation:init(xanimspeed)
	self.animation = CAnimation.new(framerate)
	-- CAnimation:cutSpritesheet(xspritesheetpath, xcols, xrows, xanimsimgs, xoffx, xoffy, sx, sy)
	self.animation:cutSpritesheet(texpath, cols, rows, animsimgs, 0, 0, self.sx, self.sy)
	-- 1st set of animations: CAnimation:createAnim(xanims, xanimname, xanimsimgs, xtable, xstart, xfinish)
	self.animation:createAnim(anims, g_ANIM_DEFAULT, animsimgs, nil, 1, cols*rows)
	self.animation:createAnim(anims, g_ANIM_IDLE_R, animsimgs, nil, 1, cols*rows)
	-- end animations
	self.animation.anims = anims
	self.sprite = self.animation.sprite
	self.sprite:setScale(self.sx*self.flip, self.sy)
	self.animation.sprite = nil -- free some memory
	self.w, self.h = self.sprite:getWidth(), self.sprite:getHeight() -- with applied scale
	-- COLLISION BOX: CCollisionBox:init(xcollwidth, xcollheight)
	local collw, collh = self.w//1, self.h//1 -- must be round numbers for cbump physics!
	self.collbox = CCollisionBox.new(collw, collh)
	-- COscillation:init(xspeed, xamplitudex, xamplitudey)
	self.oscillation = COscillation.new(xspeed, xdx, xdy)
end

When we create a collectible, we assign it an entity id (eid). Depending on the eid we will either spawn a coin, a life (to heal the player) or a key (to open doors).

The code is quite small and follows the same principle as the previous entities (player1 and enemies). The only thing we add here is an oscillation Component to give our collectibles some juice. Please create a file called "cOscillation.lua" in the "_C" folder. The code:

COscillation = Core.class()

function COscillation:init(xspeed, xamplitudex, xamplitudey)
	self.vx = 0
	self.vy = 0
	self.speed = xspeed
	self.amplitudex = xamplitudex
	self.amplitudey = xamplitudey
end

An oscillation System will look for it and act accordingly. Easy as E C S ;-)

eDoor.lua

We need some doors keys can open. Please create a file "eDoor.lua" in the "_E" folder. The code:

EDoor = Core.class()

function EDoor:init(xid, xspritelayer, xpos, xtexpath, xcolor, w, h, dx, dy, xdir, xspeed, xbgfxlayer)
	local function hexToRgb(hex)
		return (hex >> 16 & 0xff), (hex >> 8 & 0xff), (hex & 0xff)
	end
	-- ids
	self.isdoor = true
	self.eid = xid -- player1 needs key matching eid
	-- sprite layers
	self.spritelayer = xspritelayer
	self.bgfxlayer = xbgfxlayer
	-- params
	self.pos = xpos
	self.sx = 1
	self.sy = self.sx
	self.flip = 1
	if xtexpath then -- texture + color modulate?
		local tex = Texture.new(xtexpath)
		local texsx, texsy = tex:getWidth()/w, tex:getHeight()/h
		self.sprite = Pixel.new(tex, w, h, texsx, texsy)
		if xcolor then -- color modulate
			local r, g, b = hexToRgb(xcolor)
			self.sprite:setColorTransform(r/255, g/255, b/255, 1)
		end
	else -- color only
		self.sprite = Pixel.new(xcolor or 0xffffff, 1, w, h)
	end
	self.sprite:setAnchorPoint(0.5, 0.5)
	self.sprite:setScale(self.sx, self.sy)
	self.w, self.h = self.sprite:getWidth(), self.sprite:getHeight()
	-- COMPONENTS
	-- BODY: CBody:init(xmass, xspeed, xupspeed)
	self.body = CBody.new(1, xspeed.x, xspeed.y)
	-- COLLISION BOX: CCollisionBox:init(xcollwidth, xcollheight)
	local collw, collh = self.w//1, self.h//1 -- must be round numbers for cbump physics!
	self.collbox = CCollisionBox.new(collw, collh)
	-- motion AI: CDistance:init(xstartpos, dx, dy)
	self.distance = CDistance.new(self.pos, dx, dy)
	self.dir = xdir
end

What's in there? When we create this door Entity we can texture or color it so the doors are not all the same, plus it has a distance Component to control how far a door can open. Please create a file called "cDistance.lua" in the "_C" folder. The code:

CDistance = Core.class()

function CDistance:init(xstartpos, dx, dy)
	self.startpos = xstartpos
	self.dx = dx -- delta x
	self.dy = dy -- delta y
end

A System will look for it and act accordingly.



We are done making all our entities!!!

Next?

The time has come to tackle the systems. I will try to make it easy :-)


Prev.: Tuto tiny-ecs 2d platformer Part 7 Enemies
Next: Tuto tiny-ecs 2d platformer Part 9 Systems


Tutorial - tiny-ecs 2d platformer