0

O que os investidores estão buscando? - Parte 3

by Luiz Jr 10. novembro 2013 16:19

No ano passado, quando finalmente decidi me aventurar e abrir minha própria startup, passei a estudar profundamente as características que envolvem este "mercado", se é que podemos chamá-lo assim. Desde cursos, eventos, livros e blogs, devorei tudo o que podia sobre o tema, para me certificar que teria os subsídios intelectuais necessários para fazê-lo. O time eu tinha, meus amigos e atuais sócios Adriano Costa e Lucas Pfeiffer e a ideia também, seria o Busca Acelerada, um motor de pesquisa especializado em classificados automotivos. Faltava um terceiro item, que era o dinheiro, e ainda um quarto, que era a experiência em ter uma empresa, assuntos deste post.

Este post é uma continuação, embora eu nunca tivesse tido a intenção de criar uma série de posts. Para conferir a parte anterior, veja este post.

Smart Money

Dentro do mundo das startups existe um conceito chamado smart money. Que todo mundo precisa de dinheiro isso não é novidade, mas nem sempre o dinheiro por si só resolve o problema, se não souber onde aplicá-lo. Histórias de ganhadores da Mega Sena falidos são o que há de mais comum, assim como de startups com investimentos milionários que fracassaram (Shoes4You recentemente passou por isso, e até mesmo o Peixe Urbano não está muito bem das pernas atualmente). O smart money é o casamento entre capital intelectual e financeiro, onde o investidor também se torna parte da equipe, talvez não no dia-a-dia, mas como um mentor mais experiente para ajudar a tomar as decisões mais difíceis, abrir portas para alguns mercados e/ou clientes, entre outras coisas.

Dentro da ideia de smart money temos alguns Investidores Anjo, que passam a atuar de maneira bem próxima à startup, e as Aceleradoras, que são entidades que funcionam de forma análoga às incubadoras tecnológicas, mas com aporte de capital e participação societárias nas startups que serão aceleradas. Independente da opção o intuito é o mesmo: ajudar a startup a ter uma tração inicial para seguir seu caminho rumo a consolidação de um modelo de negócios rentável e escalável.

Quando notei que não conseguiríamos fazer o Busca Acelerada crescer apenas com nossas economias pessoais e principalmente com nossos conhecimentos, decidi que era hora de ir atrás de Smart Money de verdade. Já havia feito pitches e outros tipos de apresentações, mas nunca com 100% de intuito em levantar fundos e mentoria para a startup, o que muda bastante a situação. Abaixo segue o vídeo do pitch que fiz durante a Demo Brasil 2013, maior evento de startups da América Latina, do qual estivemos entre os finalistas.

http://www.youtube.com/watch?v=whVHjrkGZ-4

Aceleradoras de Startups

Como não havíamos arranjado ainda um escritório para a startup (usávamos apenas meu home-office) e tínhamos quase nenhuma experiência com práticas comerciais e operacionais de uma empresa, achei que recorrer a uma aceleradora era uma boa alternativa. Existem diversas pelo Brasil, embora a concentração maior seja em São Paulo e Rio. As primeiras aceleradoras surgiram tem poucos anos, e diz-se que foram moldadas pelo padrão proposto pela Y Combinator, que até hoje é a aceleradora que detém o maior percentual de startups bem sucedidas mundialmente. Aqui no Brasil elas tem começado a aparecer tem uns 3 anos e mais recentemente ganharam força através do programa Startup Brasil do governo federal, que em parceria com as mesmas levanta investimentos a fundo perdido para ajudar negócios de base tecnológica com grande potencial de crescimento a se tornarem "empresas de verdade".

Basicamente o que uma aceleradora faz é selecionar os melhores projetos que puder encontrar, para então investir tempo, dinheiro e infraestrutura neles, visando torná-los maiores e mais rentáveis a ponto de fazer com que valham muito dinheiro. Obviamente elas não fazem isso apenas pelo bem-estar dos empreendedores e existe a necessidade de incluir a aceleradora no quadro de sócios da empresa, o que garante à elas a possibilidade futura de venda dessa participação para outros fundos maiores, reavendo o investimento inicial com uma margem de lucro (obviamente muito superior ao investimento realizado). As quantias investidas costumam ser baixas, entre R$20 mil e R$150 mil, em troca de participações que variam entre 5% a 50%, embora o mais comum praticado seja investimentos de R$40-50 mil em troca de 25-30%, para empresas em estágio inicial (repito: o mais comum).

Geralmente as aceleradoras funcionam em ciclos semestrais. A cada ciclo a aceleradora seleciona um grupo de startups, geralmente 5, e durante os 6 meses seguintes oferece a possibilidade de incubação em suas dependências. Durante este período também oferece acesso a mentoria especializada sobre os temas necessários ao crescimento da startup, acompanha o mesmo através de reuniões, busca novos investimentos para a startup se necessário e abre tantas portas quanto possível através do seu networking. É um modelo que funciona muito bem, uma vez que o sucesso da aceleradora depende do sucesso das startups aceleradas, pois o investimento realizado não é um empréstimo, ou seja, se a startup falir, o dinheiro terá sido perdido.

A busca por Smart Money em Aceleradoras

Tendo entendido estes pontos, fica mais fácil compreender o porque de termos ido atrás de smart money em aceleradoras. Somos três profissionais técnicos que precisavam (e ainda precisamos) muito de capital intelectual nas áreas que não dominamos, além é claro de algum investimento financeiro. Aqui em Porto Alegre surgiram recentemente 3 aceleradoras, que independente das origens gaúchas aceleram empresas de todo o Brasil. Apesar da juventude das mesmas, os empreendedores por trás delas são conhecidos da cena regional e até mesmo internacional em alguns casos.

Estarte.me: a Estarte.me foi fundada por Maurício Centeno, ex-RBS e tem um pequeno portfólio de startups em processo de aceleração. A aceleradora faz aportes menores, cerca de R$20 mil e detém participações obviamente menores nos negócios que investe. Essencialmente digital, investe em startups web e mobile, incluindo games. Ela possui sede própria onde são incubadas as startups e não possui ciclo de aceleração bem definidos, podendo acelerar novas startups a qualquer momento.

Ventiur.net: a Ventiur foi fundada pelos mesmos criadores da Venti, empresa de projetos que ajuda outras empresas a tirarem suas ideias do papel e levarem para o mercado. Com esse know-how e um fundo de investidores por trás, surgiu a Ventiur, uma aceleradora em rede que busca projetos diversos que possuam inovação tecnológica, potencial de escala e mercado comprovado. Principalmente este último requisito que é avaliado através de um processo de pré-aceleração, onde os candidatos a receberem investimento recebem mentoria e auxílio em seus negócios para ver quais tem maior capacidade de execução e/ou possibilidade de retorno, o que por si só já vale como uma mini-aceleração.

Wow.ac: a Wow foi fundada por grandes empresários como André Ghignatti (Neogrid), Jaime Wagner (Digitel, Plugin, Powerself, Vakinha) e Cassio Bobsin (Zenvia, Mobigroup) que juntos formaram um grupo de 57 investidores que planejam investir em 20 startups até 2014. Além do investimento que varia de R$50 a R$150 mil dependendo do estágio da startup, eles investem também todo o capital intelectual de dezenas de mentores que atuam nos mais diversos mercados, de fundadores a executivos temos membros de empresas como W3haus, ECS, CWI, Google, entre outros nomes conhecidos. Os ciclos de aceleração são semestrais, em turmas de 5 startups.

Acabamos optando por esta última aceleradora devido à sinergia e afinidade que tivemos com os membros da mesma, aplicamos nossa proposta e após algumas entrevistas e uma apresentação ao vivo ao grupo de investidores fomos selecionados.

Mas o que as aceleradoras estão buscando?

Conversando com os investidores antes e depois da seleção, pude finalmente compreender porque fomos selecionados. O Busca Acelerada é um bom projeto, mas existem opções mais seguras de investimento nas quais eles poderiam estar colocando o dinheiro deles. O que não se encontra fácil por aí são pessoas comprometidas com uma ideia e que possuem capacidade para executá-la. Já estávamos rodando o projeto tinha um ano, dois de nós já havíamos largado a segurança dos nossos empregos e trabalhávamos full-time nele. Somos três apaixonados pelo que fazemos. Temos inovação em nosso DNA e a ambição de criar algo global. Somos inexperientes em criação de negócios, em gestão de empresas, em vendas. É verdade. Mas somos muito bons em tirar ideias do papel e enfrentar de frente as adversidades do empreendedorismo. Isso tudo pode soar muito clichê e de fato é, mas pergunte-se quantas pessoas você conhece que tem boas ideias, e destas, quantas executam ou executaram essas boas ideias? É exatamente neste ponto que fomos selecionados.

Se vamos ter sucesso em nossa empreitada, só o tempo dirá. Mas uma coisa posso afirmar: o que tem nos diferenciado é a execução, pois morrer abraçado com as ideias, sem jamais pô-las em prática, não está com nada.

Tags: , , ,

Dica | Mercado | Projetos | Startup

34

Criando Aplicações Móveis com Corona - O Livro

by Luiz Jr 19. outubro 2012 21:06

Criando Aplicações Móveis com Corona

Comprem com o botão na barra lateral do blog! O site de compras é o PagSeguro do UOL, e minha empresa é a Busca Acelerada Ltda.

Depois de algum tempo sem postar nada sobre meu framework multiplataforma favorito: Corona SDK, eis que volto com uma grande notícia pro pessoal que curte fazer apps e games pra smartphones e tablets: acaba de sair do forno a versão em Português do livro "Criando Aplicações Móveis com Corona" de meu amigo o Dr. Brian G. Burton, que é professor do curso de games mobile na faculdade de Abilene, no Texas. O livro é gigantesco, com cerca de 400 páginas e cobre praticamente todas as APIs do Corona, com muitas ilustrações e exemplos de projetos, incluindo várias aplicações e dois games completos, um scrolling shooter (os clássicos jogos de navezinha, tipo G-Darius) e um tower defense (tipo Plants vs Zombies).

O quê? Você não sabe o que é Corona SDK? Criado pela CoronaLabs (antiga Ansca Mobile), ele é um framework de desenvolvimento para smartphones e tablets que lhe permite desenvolver para iOS e Android (entre outras plataformas) de uma vez só, sem ter de transcrever código. Ou seja, você cria seu game ou app usando a linguagem Lua, nativa da plataforma, e gera os arquivos para publicação na Google Play Store e Apple App Store de uma vez só! Imagina o tempo que isto não vai te poupar em sua jornada rumo ao próximo Angry Birds...

A Tradução

A tradução e adaptação do livro, que originalmente se chamava "Beginning Mobile App Development With Corona", foi feita por mim durante o ano de 2012 e gostaria de ficar sabendo de quaisquer erros de Português ou de digitação que vocês encontrarem durante a leitura. Por enquanto o livro encontra-se à venda somente em formato digital, uma vez que custa uma grana preta fazer a versão impressa do mesmo sob o risco de não conseguirmos vender tudo. Para saber tudo o que tem no livro e principalmente para comprá-lo, acessem o blog oficial do livro em http://www.burtonsmediagroup.com/books/criando-aplicacoes-moveis-com-corona

Suporte e Dicas

Continuarei criando posts sobre Corona aqui no blog esporadicamente (como sempre fiz), mas com certeza o conteúdo do livro não será divulgado nos posts (afinal deu muito trabalho traduzir tudo e tenho respeito pelo meu trabalho e do autor). Além disso, todos os desenvolvedores que adquirirem o livro pelo referido site (ou seja, que comprem ele) terão suporte meu e do Dr. Burton por e-mail, ganharão sem custo as versões mais atualizadas do livro que saem esporadicamente e terão acesso a mais alguns materiais traduzidos que devem sair em breve. Mas somente para quem comprá-lo.

Tags: , , , , , , ,

Android | Corona SDK | Dica | iOS | Livros | Lua | Mobile | Projetos | Treinamentos

4

Relançamento do Busca Acelerada

by Luiz Jr 9. agosto 2012 20:50

Busca Acelerada

Boa noite pessoal. Hoje o post na verdade é um jabá descarado de um antigo projeto que só agora foi voltar ao ar: o Busca Acelerada (http://www.buscaacelerada.com.br).

Se eu tivesse que resumir do que se trata o site eu diria que é "O Google dos carros.". Ok, é uma analogia meio pretensiosa mas é basicamente isso mesmo. A ideia é que as pessoas não tenham mais que entrar em diversos sites de anúncios de carros para encontrar o veículo que procuram. Você entra no Busca Acelerada, digita os termos que definem o carro que busca (marca, modelo, etc) e o Busca Acelerada lhe traz o resultado de dezenas de sites de classificados, em milésimos de segundo e com possibilidades de filtrar os resultados, ordenar, etc.

Por enquanto o projeto está em testes (beta) e somente está englobando os cerca de 5700 anúncios de veículos da cidade de Gravataí-RS (a minha). Ainda assim, eu gostaria que acessassem e dessem um feedback, seja aqui pelo blog, pela página do facebook (http://www.facebook.com/BuscaAcelerada). Em breve estarei, em conjunto de meus sócios Lucas Pfeiffer e Adriano Costa, expandindo o sistema para todo RS e posteriormente para todo Brasil. Então mesmo que não seja Gravataiense como eu, me ajude a construir a melhor ferramenta de busca de veículos do país.

Valeu!

Tags: , ,

ASP.NET | Projetos | Web

19

Sunset Riders Lite com Corona SDK - First Step

by Luiz Jr 21. junho 2012 23:08

Depois de muito tempo sem postar sobre Corona SDK, o nosso framework favorito para desenvolvimento de jogos móveis multi-plataforma, eis que eu volto à ativa no desenvolvimento mobile de games com um clássico dos clássicos: Sunset Riders. Ok, eu já vinha desenvolvendo ele em posts anteriores, mas agora é pra valer. Atendendo a inúmeros pedidos o post de hoje inclui uma série de conceitos importantíssimos: botões, splash screen, tela de seleção de personagens, multimídia, sprites e por aí vai. Como o código é um pouco extenso, me aterei em comentar as etapas mais importantes. Use o link no final do post para baixar o projeto completo e até mesmo o executável para Android caso queira testar em um dispositivo de verdade.

Splash Screen do Sunset Riders Lite

Splash Screen

As splash screens são as clássicas telas de abertura do jogo, onde geralmente temos uma imagem e um menu opcional. No nosso caso, será apenas uma imagem estática do jogo original que achei na Internet, que quando tocada, se fecha, exibindo a tela anterior da pilha de execução. Para esta tela criei um arquivo chamado splashscreen.lua que eu apenas invoco usando require no main.lua.

 

module(..., package.seeall);

local tela = display.newImageRect( "image/splash-screen.jpg",display.contentWidth,display.contentHeight);
 tela:translate(240,160);

 function dismiss(event)
	tela:removeSelf();
 end

 tela:addEventListener("tap", dismiss);

Note que a imagem foi colocada dentro de uma pasta image dentro da pasta do projeto. Encontrará todas as imagens utilizadas neste post nos fontes do projeto.

Seleção de Personagem

Seleção de Personagens

Embora nos exemplos anteriores tenhamos apenas oferecido o Cormano como única opção de cowboy, sabemos que ele não é unanimidade entre os gamers mundo afora. Eu particularmente gostava de jogar com o Bob e suas espingardas, enquanto meus amigos curtiam o xerife Billy. Como segundo passo, criaremos uma tela de seleção de personagem. Seguindo as boas práticas de programação Lua criaremos um arquivo Lua para cada tela, assim como fizemos com a Splash Screen, então, crie um playerselect.lua e coloque lá o código abaixo:

module(..., package.seeall);

local selected = "steve";
local player;

function getSelected()
	return selected;
end

function isVisible()
	return player.isVisible;
end

local callbackFunction;
function callback(listener)
	callbackFunction = listener;
end

function configuraTela()
	player = display.newImageRect( "image/select-"..selected..".png", display.contentWidth, display.contentHeight);
	player:translate(240,180);
	player:addEventListener("tap", selectPlayer);
end

function selectPlayer( event )
   if(selected == "steve") then
	   if(event.x >= 1 and event.x <= 114) then--steve
			player.isVisible = false;
		elseif (event.x >= 151 and event.x <= 207) then--billy
			selected = "billy";
		elseif (event.x >= 271 and event.x <= 327) then--bob
			selected = "bob";
		elseif (event.x >= 391 and event.x <= 448) then--cormano
			selected = "cormano";
	   end
	elseif (selected == "billy") then
		if(event.x >= 30 and event.x <= 87) then--steve
			selected = "steve";
		elseif (event.x >= 119 and event.x <= 234) then--billy
			player.isVisible = false;
		elseif (event.x >= 271 and event.x <= 327) then--bob
			selected = "bob";
		elseif (event.x >= 391 and event.x <= 448) then--cormano
			selected = "cormano";
	   end
	elseif (selected == "bob") then
		if(event.x >= 30 and event.x <= 87) then--steve
			selected = "steve";
		elseif (event.x >= 150 and event.x <= 207) then--billy
			selected = "billy";
		elseif (event.x >= 240 and event.x <= 355) then--bob
			player.isVisible = false;
		elseif (event.x >= 391 and event.x <= 448) then--cormano
			selected = "cormano";
	   end
	elseif (selected == "cormano") then
		if(event.x >= 30 and event.x <= 87) then--steve
			selected = "steve";
		elseif (event.x >= 150 and event.x <= 207) then--billy
			selected = "billy";
		elseif (event.x >= 269 and event.x <= 328) then--bob
			selected = "bob";
		elseif (event.x >= 358 and event.x <= 476) then--cormano
			player.isVisible = false;
	   end
	end

	player:removeSelf();
	if(player.isVisible == true) then
		configuraTela();
	else callbackFunction();
	end
end

Uma breve explicação quanto a este código pode ser resumida no seguinte: para cada estado possível da tela, e são 4 (um para cada personagem) temos uma imagem diferente com o personagem realçado, ou seja, removemos a imagem anterior e carregamos a nova imagem na tela, dando a impressão de seleção de personagem, assim como no jogo original. Ao ser tocada a primeira vez, a tela realça o personagem e guarda seu nome na variável selected, no segundo toque no mesmo personagem, a tela é dispensada para que exiba o item anterior na pilha gráfica do Corona. As funções deste arquivo servem para expor alguns valores para os demais arquivos do projeto (principalmente o main.lua), como por exemplo, para o main.lua saber quem foi o personagem escolhido.

Estrutura de pastas do projeto

Orientação à Objetos

Lua não é orientado à objetos. É uma linguagem simples de scripting que é perfeita para criação de lógica de jogos. Entretanto, quando se programa a anos como eu e sabe-se que bons projetos não vão longe sem um mínimo de arquitetura e por isso você já deve ter notado que estou estruturando melhor os arquivos deste projeto em pastas, arquivos, etc. Desta forma, um conceito importantíssimo para criação de bons projetos são os conceitos de orientação à objetos que entre uma de suas premissas está o fato de que não se deve repetir código. Mas se todos personagens pulam, correm e param, como que não repetiremos esse código? A idéia é simples, vamos criar um arquivo chamado character.lua e nele vamos colocar tudo o que é comum aos personagens, como segue:

-- Arquivo contendo toda a lógica comum a todos os personagens
module(..., package.seeall);

local velocidade = 500;
local started = false;

function getVelocidade()
	return velocidade;
end

function start()
	started = true;
end

--carregando as variáveis e constantes
local relincho = audio.loadSound("audio/relincho.wav");
local trote = audio.loadSound("audio/galope.wav");
local canalTrote;
local cavaloY = 225;
local cavaloX = display.contentWidth / 4;
local escala = 1.2;

local galopandoSheet;
local galopandoSpriteSet;
local galopandoStance;

local jumpingSheet;
local jumpingSpriteSet;
local jumpingStance;

local parado;

function parar()
	audio.pause(canalTrote);

	parado.x = galopandoStance.x;
	parado.y = galopandoStance.y;

	parado.isVisible = true;
	galopandoStance.isVisible = false;
	jumpingStance.isVisible = false;
end

function galopandoConfig(nomeChar,spriteWidth,spriteHeight,spritesNumber)
	galopandoSheet = sprite.newSpriteSheet( "image/"..nomeChar..".png", spriteWidth,spriteHeight );

	galopandoSpriteSet = sprite.newSpriteSet(galopandoSheet, 1, spritesNumber);
	sprite.add( galopandoSpriteSet, nomeChar, 1, spritesNumber, velocidade, 0 );-- roda 5 frames/velocidade

	galopandoStance = sprite.newSprite( galopandoSpriteSet );
	galopandoStance.x = cavaloX + 40;
	galopandoStance.y = cavaloY;
	galopandoStance.xScale = escala;
	galopandoStance.yScale = escala;
	galopandoStance.isVisible = false;

	galopandoStance:addEventListener("tap", parar);
end

function jumpingConfig(nomeChar,spriteWidth, spriteHeight, spritesNumber)
	jumpingSheet = sprite.newSpriteSheet( "image/"..nomeChar.."-jump.png", spriteWidth, spriteHeight )

	jumpingSpriteSet = sprite.newSpriteSet(jumpingSheet, 1, spritesNumber)
	sprite.add( jumpingSpriteSet, nomeChar.."-jumping", 1, spritesNumber, 500, 1 ) -- play 3 frames every 500 ms

	jumpingStance = sprite.newSprite( jumpingSpriteSet )
	jumpingStance.x = cavaloX + 40
	jumpingStance.y = cavaloY;
	jumpingStance.xScale = escala;
	jumpingStance.yScale = escala;
	jumpingStance.isVisible = false;

	jumpingStance:addEventListener("sprite", fimPulo);
end

function paradoConfig(nomeChar)
	parado = display.newImage( "image/"..nomeChar.."-parado.png" )
	parado:setReferencePoint( display.CenterLeftReferencePoint )
	parado.x = cavaloX;
	parado.y = cavaloY;
	parado.xScale = escala;
	parado.yScale = escala;
	parado.isVisible = true;

	parado:addEventListener("tap", galopar);
end

function isParado()
	return parado.isVisible;
end

function galopar(nomeChar)
	if(started == true) then
		audio.play(relincho);
		canalTrote = audio.play(trote, {loops=-1});
		parado.isVisible = false;
		jumpingStance.isVisible = false;
		galopandoStance.isVisible = true;
		galopandoStance:prepare(nomeChar);
		galopandoStance:play();
	end
end

function pulo(nomeChar)
	if (parado.isVisible == false) then
		audio.play(relincho);
		galopandoStance.isVisible = false;

		jumpingStance.x = galopandoStance.x;
		jumpingStance.y = galopandoStance.y;

		jumpingStance.isVisible = true;
		jumpingStance:prepare(nomeChar.."-jumping")
		jumpingStance:play()
	end
end

function fimPulo(event)
	if (event.phase == "end") then
		parado.isVisible = false;
		galopandoStance.isVisible = true;
		jumpingStance:pause();
		jumpingStance.isVisible = false;
	end
end

function onMove(event)

	if (parado.isVisible == false) then
		local joyX = event.joyX
		local joyY = event.joyY

		if(joyX ~= false and joyY ~= false) then
			if(joyX > 0) then
				if(galopandoStance.x < display.contentWidth - 55) then
					galopandoStance.x = galopandoStance.x + 5;
				end
			else
				if(galopandoStance.x > 30) then
					galopandoStance.x = galopandoStance.x - 5;
				end
			end

			if(joyY > 0) then
				if(galopandoStance.y < 250) then
					galopandoStance.y = galopandoStance.y + 5;
				end
			else
				if(galopandoStance.y > 180) then
					galopandoStance.y = galopandoStance.y - 5;
				end
			end
		end
	end
end

Note que este arquivo carrega os sprites de maneira dinâmica, conforme o nome que for passado por parâmetro. Isso porque cada personagem terá suas próprias sprites, ou seja, só o que muda entre os personagens é seu nome (as spritesheets possuem os nomes dos personagens) e a largura e altura das sprites. O resto é exatamente igual. A função onMove será usada para manipularmos o personagem através do joystick que adicionaremos mais para frente na aplicação. Por ora, deixem-na quieta.Note também a forma como estamos carregando os áudios, de dentro de uma pasta audio, com a API audio (pois a API media foi descontinuada) e que não usamos mais os MIDs que usamos nos exemplos anteriores. A nova APi de áudio usa OpenAL e não suporta mais MID. Uma boa alternativa é WAV e incluí nos fontes do projeto os arquivos de áudio para que possa tê-los em seu projeto também.

A ideia é que todos os personagens vão carregar esta biblioteca em uma variável e chamar suas funções para carregar as sprites e poder correr, pular, etc, como veremos a seguir para o personagem Billy:

Billy Galopando

-- Arquivo contendo toda a lógica do personagem Billy
module(..., package.seeall);
local char = require("character");
local nomeChar = "billy";

function getVelocidade()
	return char.getVelocidade();
end

function start()
	char.start();
end

char.galopandoConfig(nomeChar, 96,80,5)
char.jumpingConfig(nomeChar,80,97,3);
char.paradoConfig(nomeChar);

function isParado()
	return char.isParado();
end

function galopar()
	char.galopar(nomeChar);
end

function parar()
	char.parar();
end

function pulo()
	char.pulo(nomeChar);
end

function onMove(event)
	char.onMove(event);
end

Note a simplicidade de criar um novo personagem usando esta arquitetura de software simplíssima baseada em Orientação à Objetos, ao criarmos o personagen Steve:

Steve galopando

-- Arquivo contendo toda a lógica do personagem Steve
module(..., package.seeall);
local char = require("character");
local nomeChar = "steve";

function getVelocidade()
	return char.getVelocidade();
end

function start()
	char.start();
end

char.galopandoConfig(nomeChar, 96,79,5)
char.jumpingConfig(nomeChar,80,95,3);
char.paradoConfig(nomeChar);

function isParado()
	return char.isParado();
end

function galopar()
	char.galopar(nomeChar);
end

function parar()
	char.parar();
end

function pulo()
	char.pulo(nomeChar);
end

function onMove(event)
	char.onMove(event);
end

Não postarei o código dos demais personagens pois acredito que sejam capazes de deduzir por vocês mesmos. Note que o que fizemos foi criar uma espécie de herança da orientação à objetos de uma forma tosca mas que funciona.

Agora que temos todos os personagens criados, vamos criar novamente o plano de fundo de nossa aplicação que conta com trilha sonora, trilhos de trem e uma bela paisagem do oeste selvagem!

Sunset Riders Lite com Cenário, Joystick e Botões

Cenário, Joystick e Botões

Já havíamos criado o cenário em posts anteriores e mesmo com essa nova abordagem mais arquitetural, o código ainda se parece com o código antigo. As imagens ainda são as mesmas de antes, mas agora temos algumas adicionais que nos levam a estudar duas bibliotecas antes: ui.lua e joystick.lua.

A biblioteca ui.lua lhe permite criar botões de forma muito mais fácil e é largamente utilizado em projetos Lua. O projeto inclui uma versão desta biblioteca, a última na época deste tutorial (1.6) e seu uso neste game é para criar dois botões, o de pular (que dispara a função de salto do personagem) e o de atirar, que ainda não tem utilidade mas que no futuro irá disparar projéteis com as armas dos personagens.

 

local ui = require("ui");
function jumpButtonEvent(event) personagem.pulo(); end function shotButtonEvent(event) print("shot"); end function configuraButtons() jumpButton = ui.newButton{ default = "image/jump-button.png", over = "image/jump-button-over.png", onRelease = jumpButtonEvent, x = display.contentWidth - 50, y = display.contentHeight - 75 }; shotButton = ui.newButton{ default = "image/shot-button.png", over = "image/shot-button-over.png", onRelease = shotButtonEvent, x = display.contentWidth - 50, y = display.contentHeight - 150 }; end

Este código deve ir no main.lua, que é um arquivo tão extenso que não incluirei aqui. Apenas pegue os fontes deste projeto e busque este trecho de código para saber onde colocar o seu. Note que as imagens para os botões são duas: a normal e a de botão pressionado. Além disso, os botões disparam uma função quando selecionados, funções estas definidas nas linhas anteriores ao carregamento dos mesmos. Note também que na função de pulo mandamos uma variável personagem pular, sem nem mesmo saber qual personagem que estamos jogando, o que é indiferente para nós. Em orientação à objetos poderíamos dizer que emulamos uma interface.

 

Outra biblioteca importante que usaremos hoje é a biblioteca joystick.lua (a versão 1 se encontra no projeto), que cria um direcional analógico assim como o visto em controles de Nintendo 64 e Playstation. Esse joystick usa duas imagens existentes em nossa pasta de imagens e dispara o evento onMove presente na biblioteca character.lua. Isso porque independente de personagem, ele se moverá da mesma forma, não é mesmo? Para usar o joystick.lua, use o seguinte código:

 

local joystickClass = require( "joystick" );
function configuraJoystick() joystick = joystickClass.newJoystick{ outerImage = "", outerRadius = 60, outerAlpha = 0, innerImage = "image/joystickInner.png", innerRadius = "", innerAlpha = 1, backgroundImage = "image/joystickDial.png", background_x = 0, background_y = 0, backgroundAlpha = 1, position_x = 0, position_y = baseline - 100, ghost = 0, joystickAlpha = 0.4, joystickFade = true, joystickFadeDelay = 2000, onMove = personagem.onMove } end

 

Olhando este código não é muito difícil de imaginar para que servem as propriedades que configuramos, sendo que as principais delas são as imagens que formam o joystick e a função que vai ser executada toda vez que o joystick for utilizado (neste caso, a onMove do personagem).

Mas voltando a ponto que havíamos parado no último tutorial, o plano de fundo é extremamente simples de implementar novamente, bastando carregar os trilhos duas vezes, adicionar música e os demais elementos, incluindo o próprio personagem. Muita atenção à ordem dos elementos no main.lua pois eles são colocados no display na ordem em que são instanciados. Ou seja, o que você quiser que sua aplicação exiba primeiro deve estar no final do arquivo (como a splashscreen e a selectplayer, por exemplo). Tendo isso em mente, o código para o cenário do jogo com os elementos juntos fica assim:

 

-- Arquivo contendo toda a lógica da aplicação Sunset Riders Lite
display.setStatusBar(display.HiddenStatusBar);
system.activate( "multitouch" );

local playerSelect = require("playerselect");
local joystickClass = require( "joystick" );
local ui = require("ui");
require "sprite";

 

Primeiro escondemos a barra de status, carregamos a tela de seleção d epersonagem 9que ainda não é exibida pois exige a chamada de uma função para tanto. Ativamos multitouch em nossa aplicação pois possuímos um joystick e botões, esperando que os usuários jogarão com as duas mãos sobre o dispositivo (impossível de testar no simulador), carregamos as bibliotecas ui e sprite, necessárias mais para frente. Continuando:

 

--variáveis e constantes
local started = false;
local baseline = 280;
local escalaTrilhos = 1.3;
local trilhosY = baseline - 115;
local textoX = 150;
local textoY = baseline - 175;
local velocidadeFundo = 0.2;--quanto maior mais rápido
local milhas = 0;--número de milhas percorridas pelo cowboy
local percurso = 10;--milhas até a cidade
local victoryMusic = audio.loadSound("audio/victory.wav");
local backMusic = audio.loadSound("audio/sunset-riders-bonus-stage.wav");
local backChannel;
local jumpButton, shotButton;
local tPrevious = system.getTimer()

 

Algumas variáveis e constantes para definir a linha base de onde o personagem inicia o jogo, a escala dos trilhos, a posição XY dos textos, trilhos, a velocidade do fundo, o número de milhas percorridas pelo cowboy (sim, um dia a fase irá acabar) o tamanho do percurso em milhas, a música de vitória, a música de fundo, o canal da música de fundo (para poder desligá-la depois), os dois botões e o tempo atual do sistema, para sincronizar as atualizações dos trilhos. Mais código:

 

-- Trilhos
-- O dobro de trilhos para fazer a animação
-- Quando um dos trilhos termina, aparece o outro
function montaTrilhos(x)
	local rails = display.newImage( "image/trilhos.jpg" )
	rails:setReferencePoint( display.CenterLeftReferencePoint )
	rails.y = trilhosY;
	rails.x = x;
	rails.xScale = escalaTrilhos;
	rails.yScale = escalaTrilhos;
	return rails;
end

local trilhos = montaTrilhos(0);
local trilhos2 = montaTrilhos(trilhos.contentWidth);

 

Aqui montamos os trilhos d emaneira bem simples, assim como havíamos construído antes. A diferença é a função que evita repetição de código.

 

--função para configurar um novo texto a ser exibido
function montaTexto(texto)
	local rotulo = display.newImage( "image/"..texto..".png" );
	rotulo:setReferencePoint( display.CenterLeftReferencePoint )
	rotulo.x = textoX;
	rotulo.y = textoY;
	rotulo.isVisible = false;
	return rotulo;
end

local textoStart = montaTexto("start");
textoStart.isVisible = true;
local textoHurry = montaTexto("hurry");
local textoVictory = montaTexto("victory");

 

Aqui temos uma função para montar os textos que usaremos na aplicação. Use esta função para exibir quaisquer textos no formato padrão do nosso jogo, basta ter as imagens corretas n pata de imagens do projeto. Agora vamos mover os elementos:

 

local personagem;

-- movendo os elementos
local function move(event)
	if(started == true and personagem.isParado() == false) then
		local tDelta = event.time - tPrevious;
		tPrevious = event.time;

		local xOffset = ( velocidadeFundo * tDelta )

		trilhos.x = trilhos.x - xOffset;
		trilhos2.x = trilhos2.x - xOffset;

		if (trilhos.x + trilhos.contentWidth) < 0 then
			milhas = milhas + 1;
			trilhos:translate(trilhos.contentWidth * 2, 0)
		end

		if (trilhos2.x + trilhos2.contentWidth) < 0 then
			milhas = milhas + 1;
			trilhos2:translate( trilhos2.contentWidth * 2, 0)
		end

		if(milhas >= percurso) then
			started = false;
			--jogo terminou
			personagem.parar();
			milhas = 0;
			textoVictory.isVisible = true;
			audio.pause();
			audio.play(victoryMusic);
		end
	end
end

--joystick
--botões

 

Este código é chamado a cada atualização de tela do dispositivo e redesenha o cenário conforme o tempo do sistema. Além disso, conta quantas vezes o cenário já foi desenhado por completo para contar as milhas do projeto e dizer se o cowboy já chegou no final do projeto ou não, neste caso tocando uma música de vitória. No último comentário é onde deve ser colocado o código do joystick, sem o comando require que já foi chamado antes no início do arquivo. Onde diz botões, deve ser colocado o código dos botões sem o comando require. Vamos ao último trecho de código do main.lua:

 

--função de início
local function start()
	if(playerSelect.isVisible() == false) then

		personagem = require (playerSelect.getSelected());
		configuraJoystick();
		configuraButtons();

		backChannel = audio.play(backMusic, { loops=-1 });
		started = true;
		textoStart.isVisible = false;
		personagem.start();
	end
end

playerSelect.callback(start);
Runtime:addEventListener( "enterFrame", move );
playerSelect.configuraTela();
local splashScreen = require("splashscreen");

Este trecho define a função de início de jogo, define a função de callback da tela de seleção de personagem (uma função de callback é uma função que será executada quando a tela de seleção de personagem for fechada) e o gatilho para o evento enterFrame, que é chamado uma vez para cada refresh da tela (o que depende do framerate do dispositivo, que pode variar de 30 a 60fps). E por fim, configura a tela de seleção de personagem (desenha) e carrega a splash screen (desenha-a também). Note que as primeiras telas do jogo são as últimas a serem desenhadas.

Os arquivos build.settings e config.lua ainda são os mesmos do último projeto de exemplo e não serão repetidos. Pronto, nosso jogo está pronto para ser executado e até mesmo ter uma versão compilada para ser instalado em um dispositivo de verdade. Incluí no final deste post os arquivos do projeto completo e o arquivo APK para instalação no Android.

Sunset Riders Lite 0.1 lançado!

Conclusões e Futuro

Espero que tenham gostado deste post que ficou muito extenso pois acabei me empolgando no desenvolvimento do game ao longo da semana e me esqueci de ir fazendo este post aos poucos ou até mesmo em pedaços, explicando cada uma das etapas em detalhes. De qualquer forma acredito que servirá para saciar a vontade do pessoal que queria ver coisas como botões, joysticks e a continuidade do jogo, que na verdade meio que começou a ser desenvolvido de verdade agora.

Para o futuro penso em adicionarmos uma barra de progresso enquanto o jogo está sendo inicializado, uma animaçãozinha de abertura, alguns efeitos sonoros adicionais, tiros e alguns obstáculos a serem saltados pelos personagens para dar algum sentido à fase. Então até o próximo post!

Quer saber tudo sobre Corona SDK? Compre já o meu livro!

Sunset Riders Lite 0.1.apk.zip (8,12 mb)

SunsetRiders-4.zip (6,13 mb)

Tags: , , , , ,

Android | Corona SDK | Lua | Mobile | Projetos

0

Ciclo de palestras na FAQI e demais projetos

by Luiz Jr 23. novembro 2011 19:55

Nesta segunda e terça-feira tive a oportunidade de conhecer a FAQI de Porto Alegre, graças ao contato do Prof. João Moreira, coordenador do curso de Análise e Desenvolvimento de Sistemas da instituição. Nos conhecemos na minha última visita à FAQI Gravataí, onde palestrei sobre Cloud Computing, palestra esta que eu e meu colega da RedeHost, Cristiano, temos ministrado em mais de uma dezena de instituições pelo Rio Grande do Sul afora. Desta vez não foi diferente, nossa presença na instituição foi para estreitar ainda mais os laços entre RedeHost e FAQI, enquanto empregadores e educadores.

Eu apresentando a RedeHost pro pessoal

Com esta palestra, provavelmente terá encerrado minha participação em eventos acadêmicos este ano, uma vez que estamos chegando em dezembro, e com ele, o recesso das instituições de ensino. Não que isto signifique o encerramento de minhas atividades relacionadas à ensino, já estão engatilhados novos cursos de desenvolvimento, em cima de plataformas mais tradicionais, como o curso recém organizado de C# Nível 2 que deve estreiar na Facensa no verão e principalmente, minhas estréia como ministrante de cursos em cima de mobilidade, com plataformas como Android, Windows Phone 7 e iOS (bom, quem acompanha o blog sabe do que estou falando!). Embora oficialmente eu não tenha fechado com nenhuma instituição (estou no aguardo de algumas confirmações), considero que 2012 será um grande ano para meus estudos nestas plataformas e que conseguirei alguns bons contratos enquanto instrutor.

2ª dia de palestra na FAQI

E por fim, hoje estive conversando com o Prof. Heitor Boeira, coordenador do curso de Análise e Desenvolvimento de Sistemas da FAQI Gravataí, para montarmos a agenda de cursos de extensão de 2012, desta vez focados em Linux e Virtualização, com os instrutores e colegas Diego Voltz e Cristiano Diedrich. Em contrapartida, a FAQI finalmente fechou conosco o tão aguardado convênio educacional, onde colaboradores da RedeHost terão desconto nos cursos de gradução e pós-graduação na instituição. Com isso, nossos profissionais terão mais um benefício oferecido pela empresa e mais uma motivação para estudarem. Outras parcerias estão em vias de serem fechadas, mas é cedo para comentar ainda...

Hoje o post foi curto, nada de tutorial ou algo do gênero, apenas o uso deste espaço para divulgar meu trabalho. Tenha uma boa semana!

Tags: ,

Blog | Cloud | Eventos | Experiências | Me | Projetos

Powered by BlogEngine.NET 1.6.1.0
Design por Laptop Geek, adaptado por onesoft e personalizado por mim.