Difference between revisions of "Animated Sprite Factory"

From GiderosMobile
m (added assets links)
Line 237: Line 237:
 
* https://opengameart.org/content/space-soldier-resize-64x64
 
* https://opengameart.org/content/space-soldier-resize-64x64
 
* https://opengameart.org/content/pixel-coins-asset
 
* https://opengameart.org/content/pixel-coins-asset
 
<!--
 
=== <translate>A YouTube Video</translate> ===
 
A step by step video on how to use this platformer template. Enjoy!
 
 
https://www.youtube.com/watch?v=WPcbsgOCnLU
 
-->
 

Revision as of 02:47, 5 January 2020

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, ...

--[[
	-- FREE TO USE AND MODIFY

	Sprite_Maker:init(xname, xspritesheet, xcols, xrows, xposx, xposy)

	Where:
	xname (String) = the name of your sprite (default are "player1", "enemy01", "enemy02", "coin01")
	xspritesheet (String) = the path to your spritesheet gfx (png, jpeg, ...)
	xcols (int) = the number of columns of your sprite spritesheet
	xrows (int) = the number of rows of your sprite spritesheet
	xposx (int) = initial x position of your sprite
	xposy (int) = initial y position of your sprite
	
	example:
	local player1 = Sprite_Maker.new("player1", "gfx/hero/HQ_Trooper_all.png", 6, 13, 64, 128)
]]

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) -- you can uncomment this line for debugging
	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

Assets

You can pick the files from opengameart.org: