Animated Sprite Factory

From GiderosMobile
Revision as of 18:33, 8 December 2019 by MoKaLux (talk | contribs) (→‎Example)

Here you will find various resources to help you create games and apps in Gideros Studio.
note: You may have to provide your own assets (fonts, gfx, …).

Description

This section deals with animating any of your sprites (player, enemies, collectibles, ...). It can be used either in conjunction with cbump, liquidfun or as a standalone class.

Animation Sprite Factory (player, enemies, collectibles, npcs, ...)

This animation sprite factory class allows you to control all your characters parameters like speed, animations, ...

Sprite_Maker = Core.class(Sprite)

function Sprite_Maker:init(xname, xspritesheet, xcols, xrows, xposx, xposy)
	-- settings
	self.name = xname
	self.x = xposx
	self.y = xposy
	self.vx = 0
	self.vy = 0
	self.flip = 1
	self.isonfloor = false
	self.isattacking = false
	self.lives = 1
	self.accel = 500
	self.maxspeed = 200
	self.jumpspeed = 980

	-- animations
	self.currentanim = ""
	self.frame = 0
	self.animspeed = 1 / 8
	self.animtimer = self.animspeed

	-- retrieve all anims in texture
	local myanimstex = Texture.new(xspritesheet)
	local cellw = myanimstex:getWidth() / xcols
	local cellh = myanimstex:getHeight() / xrows
	local myanims_list = {}
	for r = 1, xrows do
		for c = 1, xcols do
			local myanimstexregion = TextureRegion.new(
					myanimstex, (c - 1) * cellw, (r - 1) * cellh, cellw, cellh)
			myanims_list[#myanims_list + 1] = myanimstexregion
		end
	end

	-- create anims
	self.anims = {}
	if self.name == "player1" then -- you can adapt your name here!
		self:createAnim("idle", 1, 2, myanims_list)
		self:createAnim("jump_up", 38, 38, myanims_list)
		self:createAnim("jump_down", 39, 39, myanims_list)
		self:createAnim("walk", 13, 16, myanims_list)
		self:createAnim("shoot", 67, 70, myanims_list)
	elseif self.name == "enemy01" then -- you can adapt your name here!
		self:createAnim("walk", 1, 7, myanims_list)
	elseif self.name == "enemy02" then -- you can adapt your name here!
		self:createAnim("walk", 1, 5, myanims_list)
	elseif self.name == "coin01" then -- you can adapt your name here!
		self:createAnim("walk", 1, 6, myanims_list)
	end

	-- the bitmap
	self.bmp = Bitmap.new(myanims_list[1]) -- starting bmp texture
	self.bmp:setAnchorPoint(0.5, 0.5)
	if self.name == "player1" then -- adapt name here
		self.w = self.bmp:getWidth() / 2
		self.h = self.bmp:getHeight() - 0
		-- set position inside sprite
		self.bmp:setPosition(self.w / 2, self.h / 2 - 0 / 2)
	elseif self.name == "enemy01" then -- adapt name here
		self.w = self.bmp:getWidth() / 2
		self.h = self.bmp:getHeight() - 0
		-- set position inside sprite
		self.bmp:setPosition(self.w / 2, self.h / 2 - 0 / 2)
	elseif self.name == "enemy02" then -- adapt name here
		self.w = self.bmp:getWidth() / 8
		self.h = self.bmp:getHeight() - 0
		-- set position inside sprite
		self.bmp:setPosition(self.w / 2, self.h / 2 - 0 / 2)
	else
		self.w = self.bmp:getWidth()
		self.h = self.bmp:getHeight()
		-- set position inside sprite
		self.bmp:setPosition(self.w / 2, self.h / 2)
	end

	-- collisions debugging
	local mypixel = Pixel.new(0xff0000, 0.5, self.w, self.h)

	-- our sprite is ready
	local mysprite = Sprite.new()
	mysprite:addChild(self.bmp)
	mysprite:addChild(mypixel) -- debug. you can comment this line when you are done
	self:addChild(mysprite)

	-- hero controls
	if self.name == "player1" then
		self.iskeyleft = false
		self.iskeyright = false
		self.iskeyup = false
		self.iskeydown = false
		self.iskeyspace = false

		self:addEventListener(Event.KEY_DOWN, self.onKeyDown, self)
		self:addEventListener(Event.KEY_UP, self.onKeyUp, self)
	end
end

-- FUNCTIONS
function Sprite_Maker:createAnim(xanimname, xstart, xfinish, xanimslist)
	self.anims[xanimname] = {}
	for i = xstart, xfinish do
		self.anims[xanimname][#self.anims[xanimname] + 1] = xanimslist[i]
	end
end

-- KEYS HANDLER
function Sprite_Maker:onKeyDown(e)
	-- keys pressed
	if e.keyCode == KeyCode.LEFT then self.iskeyleft = true end
	if e.keyCode == KeyCode.RIGHT then self.iskeyright = true end
	if e.keyCode == KeyCode.UP then self.iskeyup = true end
	if e.keyCode == KeyCode.DOWN then self.iskeydown = true end
	if e.keyCode == KeyCode.SPACE then self.iskeyspace = true end
end

function Sprite_Maker:onKeyUp(e)
	-- keys released
	if e.keyCode == KeyCode.LEFT then self.iskeyleft = false end
	if e.keyCode == KeyCode.RIGHT then self.iskeyright = false end
	if e.keyCode == KeyCode.UP then self.iskeyup = false end
	if e.keyCode == KeyCode.DOWN then self.iskeydown = false end
	if e.keyCode == KeyCode.SPACE then self.iskeyspace = false end
end

Example

-- stage
local player1 = Sprite_Maker.new("player1", "gfx/hero/HQ_Trooper_all.png", 6, 13, 64, 128)
player1.lives = 3 -- you can change parameters on the fly
stage:addChild(player1)
local coin = Sprite_Maker.new("coin01", "gfx/coins/coin_20_x01.png", 6, 1, 128, 128)
coin:setScale(3)
coin.animspeed = 1 / 3
stage:addChild(coin)

-- GAME LOOP
stage:addEventListener(Event.ENTER_FRAME, function(e)
	updatePlayer(player1, e.deltaTime)
	updateCollectibles(coin, e.deltaTime)
end)

-- FUNCTIONS
function updatePlayer(xsprite, dt)
	-- anim state
	if xsprite.vx == 0 then
		xsprite.currentanim = "idle"
	elseif xsprite.vx ~= 0 then
		xsprite.currentanim = "walk"
	end
	-- keyboard handling
	if xsprite.iskeyright then
		xsprite.vx += xsprite.accel * dt
		if xsprite.vx > xsprite.maxspeed then xsprite.vx = xsprite.maxspeed end
		xsprite.flip = 1
	elseif xsprite.iskeyleft then
		xsprite.vx -= xsprite.accel * dt
		if xsprite.vx < -xsprite.maxspeed then xsprite.vx = -xsprite.maxspeed end
		xsprite.flip = -1
	else
		xsprite.vx = 0
	end
	-- anim loop
	if xsprite.currentanim ~= "" then
		xsprite.animtimer = xsprite.animtimer - dt
		if xsprite.animtimer <= 0 then
			xsprite.frame += 1
			xsprite.animtimer = xsprite.animspeed
			if xsprite.frame > #xsprite.anims[xsprite.currentanim] then
				xsprite.frame = 1
			end
			xsprite.bmp:setTextureRegion(xsprite.anims[xsprite.currentanim][xsprite.frame])
		end
	end
	-- move & flip
	xsprite.x += xsprite.vx * dt
	xsprite.y += xsprite.vy * dt
	xsprite:setPosition(xsprite.x, xsprite.y)
	xsprite.bmp:setScale(xsprite.flip, 1)
end

function updateCollectibles(xsprite, dt)
	-- anim state
	xsprite.currentanim = "walk"
	-- anim loop
	if xsprite.currentanim ~= "" then
		xsprite.animtimer = xsprite.animtimer - dt
		if xsprite.animtimer <= 0 then
			xsprite.frame += 1
			xsprite.animtimer = xsprite.animspeed
			if xsprite.frame > #xsprite.anims[xsprite.currentanim] then
				xsprite.frame = 1
			end
			xsprite.bmp:setTextureRegion(xsprite.anims[xsprite.currentanim][xsprite.frame])
		end
	end
	-- show
	xsprite:setPosition(xsprite.x, xsprite.y)
	xsprite.bmp:setScale(xsprite.flip, 1)
end