As coroutines são funções úteis para implementar tarefas que devem ocorrer ao longo de várias frames.
Neste posto vamos ver como animar a camera de um ponto inicial para outro ponto final com uma determinada duração em segundos. A duração da animação é armazenada numa variável para que possa ser facilmente ajustada.
A função é executada quando o utilizador premir a barrar de espaços.
void Update () {
if (Input.GetKeyDown(KeyCode.Space))
{
if(func!=null)
StopCoroutine(func);
func = StartCoroutine(smoothMoveCamera());
}
}
Precisamos de algumas variáveis:
public float duration = 2.0f;
public float xStart = -5.0f;
public float xFinish = 5.0f;
Coroutine func;
A primeira define a duração em segundas da animação. A segunda o ponto inicial e a terceira o ponto final, ao longo do eixo dos x.
Por temos uma referência para a coroutina para que seja possível parar a sua execução, se necessário.
O código da coroutina:
IEnumerator smoothMoveCamera()
{
float speed = 1 / duration;
float percent = 0;
while (true)
{
percent += speed*Time.deltaTime;
transform.position = new Vector3(Mathf.Lerp(xStart, xFinish, percent),1,-10);
yield return null;
if (percent >= 1) break;
}
}
Começamos por calcular a velocidade da animação, por segundo, dividindo 1 pela duração da animação. Esta velocidade é, dentro do ciclo, multiplicada pelo deltaTime para ajustar em função do tempo que demorou a desenhar a última frame.
Depois calculamos a nova posição usando a função Lerp com base na percentagem do tempo da animação que já está concluída e interpolando entre o ponto inicial e final.
Depois da nova posição ser definida devolvemos a execução ao Unity, com o método yield, para que possa fazer o render da frame. Depois testamos se a animação já terminou e nesse caso saímos do ciclo.
domingo, 28 de outubro de 2018
quarta-feira, 12 de setembro de 2018
Coroutines em Unity3d
Coroutines são funções que mantém o estado enquanto devolvem a execução do código ao método que as chamou.
São úteis para o desenvolvimento de jogos para permitir a execução de determinado código ao longo de várias frames.
Por exemplo para animar a câmara do jogo podíamos executar o seguinte código:
for(int i=0;i<100;i++){
transform.position += new Vector3(1, 0,0);
}
Se este código estiver dentro de uma função que é executada normalmente não é possível ver a câmara a mover-se ao longo do eixo dos X uma vez que a atualização do cenário do jogo só ocorre no final do ciclo e não ao longo da execução deste.
Para que seja possível ver o movimento da câmara é necessário executar um iteração do ciclo e depois atualizar a cena (fazer o render) e depois continuar a execução do ciclo com mais uma iteração e volta a atualizar a cena, neste caso o que se pretende é interromper a execução e retomar sem que se perca o estado, para isso pode-se implementar uma coroutine.
Uma coroutine não é mais do que um IEnumerator em C#, a seguinte função executa um ciclo com 100 iterações e em cada iteração a câmara move-se um valor ao longo do eixo dos X e depois interrompe a execução por 0,1 segundos. A execução continua com a atualização da variável do ciclo e mais uma iteração.
IEnumerator animaCameraPrincipal()
{
for(int i = 0; i < 100; i++) {
transform.position += new Vector3(1, 0,0);
yield return new WaitForSecondsRealtime(0.1f);
}
}
Esta função é executada assim:
StartCoroutine(animaCameraPrincipal());
É muito importante não esquecer que como esta função é executada ao longo do tempo não deve ser chamada antes da sua execução estar concluída. Neste caso a execução total do código da função dura 10 segundos (0,1 x 100 = 10).
A coroutine pode ser parada de duas formas:
- parando todas as coroutines: StopAllCoroutines();
- parando só esta e para isso tempos de guardar uma referência para a coroutine, assim, Coroutine funcao=StartCoroutine(animaCameraPrincipal()); e depois parando assim, StopCoroutine(funcao);
São úteis para o desenvolvimento de jogos para permitir a execução de determinado código ao longo de várias frames.
Por exemplo para animar a câmara do jogo podíamos executar o seguinte código:
for(int i=0;i<100;i++){
transform.position += new Vector3(1, 0,0);
}
Se este código estiver dentro de uma função que é executada normalmente não é possível ver a câmara a mover-se ao longo do eixo dos X uma vez que a atualização do cenário do jogo só ocorre no final do ciclo e não ao longo da execução deste.
Para que seja possível ver o movimento da câmara é necessário executar um iteração do ciclo e depois atualizar a cena (fazer o render) e depois continuar a execução do ciclo com mais uma iteração e volta a atualizar a cena, neste caso o que se pretende é interromper a execução e retomar sem que se perca o estado, para isso pode-se implementar uma coroutine.
Uma coroutine não é mais do que um IEnumerator em C#, a seguinte função executa um ciclo com 100 iterações e em cada iteração a câmara move-se um valor ao longo do eixo dos X e depois interrompe a execução por 0,1 segundos. A execução continua com a atualização da variável do ciclo e mais uma iteração.
IEnumerator animaCameraPrincipal()
{
for(int i = 0; i < 100; i++) {
transform.position += new Vector3(1, 0,0);
yield return new WaitForSecondsRealtime(0.1f);
}
}
Esta função é executada assim:
StartCoroutine(animaCameraPrincipal());
É muito importante não esquecer que como esta função é executada ao longo do tempo não deve ser chamada antes da sua execução estar concluída. Neste caso a execução total do código da função dura 10 segundos (0,1 x 100 = 10).
A coroutine pode ser parada de duas formas:
- parando todas as coroutines: StopAllCoroutines();
- parando só esta e para isso tempos de guardar uma referência para a coroutine, assim, Coroutine funcao=StartCoroutine(animaCameraPrincipal()); e depois parando assim, StopCoroutine(funcao);
terça-feira, 20 de fevereiro de 2018
ASP.NET MVC com Entity, Identity e Migrações Parte 3 - Upload de ficheiros
Na terceira parte deste tutorial vamos adicionar dois controllers e dois models com a possibilidade de fazer o upload de ficheiros para o nosso site.
O model Room é muito simples:
public class Room {
[Key]
public int nr { get; set; }
[Required(ErrorMessage = "Deve indicar o piso do quarto")]
public int piso { get; set; }
[Required(ErrorMessage = "Deve indicar a lotação")]
public int lotacao { get; set; }
[Required(ErrorMessage = "Deve indicar o estado do quarto")]
public bool estado { get; set; }
[DataType(DataType.Currency)]
[Required(ErrorMessage = "Deve indicar o preço por dia do quarto")]
public decimal custo_dia { get; set; }
}
Agora basta adicionar o controller com a Entity framework.
O Client model:
public class Client {
[Key]
public int ClientId { get; set; }
[Required(ErrorMessage = "Tem de indicar o nome do cliente")]
[StringLength(50)]
[MinLength(5, ErrorMessage = "O nome é muito pequeno")]
public string nome { get; set; }
[Required(ErrorMessage = "Tem de indicar a morada do cliente")]
[StringLength(50)]
[MinLength(5, ErrorMessage = "Morada muito pequena")]
public string morada { get; set; }
[Required(ErrorMessage = "Tem de indicar o código postal do cliente")]
[StringLength(8)]
[MinLength(7, ErrorMessage = "O código postal é muito pequeno")]
[Display(Name = "Código Postal")]
public string cp { get; set; }
[DataType(DataType.EmailAddress)]
public string email { get; set; }
public string telefone { get; set; }
[DataType(DataType.Date)]
[Display(Name = "Data de Nascimento")]
[Required(ErrorMessage = "Tem de indicar a data de nascimento do cliente")]
public DateTime data_nascimento { get; set; }
}
Mais uma vez utilizamos a Entity framework para adicionar o controller:
Para fazer o upload dos ficheiros precisamos de alterar a view create dos clientes assim:
<div class="form-group">
<input type="file" name="fotografia" id="fotografia" class="form-control" /><br />
</div>
O web form também tem de ser alterado:
@using (Html.BeginForm("Create", "Clients", FormMethod.Post, new { enctype = "multipart/form-data" }))
O model Room é muito simples:
public class Room {
[Key]
public int nr { get; set; }
[Required(ErrorMessage = "Deve indicar o piso do quarto")]
public int piso { get; set; }
[Required(ErrorMessage = "Deve indicar a lotação")]
public int lotacao { get; set; }
[Required(ErrorMessage = "Deve indicar o estado do quarto")]
public bool estado { get; set; }
[DataType(DataType.Currency)]
[Required(ErrorMessage = "Deve indicar o preço por dia do quarto")]
public decimal custo_dia { get; set; }
}
Agora basta adicionar o controller com a Entity framework.
O Client model:
public class Client {
[Key]
public int ClientId { get; set; }
[Required(ErrorMessage = "Tem de indicar o nome do cliente")]
[StringLength(50)]
[MinLength(5, ErrorMessage = "O nome é muito pequeno")]
public string nome { get; set; }
[Required(ErrorMessage = "Tem de indicar a morada do cliente")]
[StringLength(50)]
[MinLength(5, ErrorMessage = "Morada muito pequena")]
public string morada { get; set; }
[Required(ErrorMessage = "Tem de indicar o código postal do cliente")]
[StringLength(8)]
[MinLength(7, ErrorMessage = "O código postal é muito pequeno")]
[Display(Name = "Código Postal")]
public string cp { get; set; }
[DataType(DataType.EmailAddress)]
public string email { get; set; }
public string telefone { get; set; }
[DataType(DataType.Date)]
[Display(Name = "Data de Nascimento")]
[Required(ErrorMessage = "Tem de indicar a data de nascimento do cliente")]
public DateTime data_nascimento { get; set; }
}
Mais uma vez utilizamos a Entity framework para adicionar o controller:
Para fazer o upload dos ficheiros precisamos de alterar a view create dos clientes assim:
<div class="form-group">
<input type="file" name="fotografia" id="fotografia" class="form-control" /><br />
</div>
O web form também tem de ser alterado:
@using (Html.BeginForm("Create", "Clients", FormMethod.Post, new { enctype = "multipart/form-data" }))
Precisamos do multipart encoding para fazer o upload do ficheiro.
Para terminar temos de alterar a função que recebe o formulário quando é submetido:
public ActionResult Create([Bind(Include = "ClientId,nome,morada,cp,email,telefone,data_nascimento")] Client client)
{
if (ModelState.IsValid)
{
db.Clients.Add(client);
db.SaveChanges();
//save the file
HttpPostedFileBase fotografia = Request.Files["fotografia"];
if (fotografia != null) {
string imagem = Server.MapPath("~/Images/") + client.ClientId.ToString() + ".jpg";
fotografia.SaveAs(imagem);
}
return RedirectToAction("Index");
}
return View(client);
}
Não podemos nos esquecer de criar a pasta Images.
Para podermos ver as imagens enviadas temos de alterar a view index, adicionando uma coluna assim:
<td>
<img src="@Url.Content(String.Format("~/Images/{0}.jpg",item.ClientId))" width="100" />
</td>
Isto tudo está disponível no Youtube
E GitHub
domingo, 18 de fevereiro de 2018
TensorFlow Variáveis e placeholders
Neste tutorial vamos introduzir dois novos tipos de nós: variáveis e placeholders.
Depois de importarmos o tensorflow:
import tensorflow as tf
Depois de importarmos o tensorflow:
import tensorflow as tf
Iniciamos a sessão, mas antes fazemos o reset ao estado interno:
tf.reset_default_graph()
sess=tf.Session()
Agora podemos criar duas variáveis:
x = tf.Variable(2.0,tf.float32)
y = tf.Variable(3.0,tf.float32)
Sempre que se utilizam variáveis numa sessão tensorflow é necessário inicializa-las:
init = tf.global_variables_initializer()
sess.run(init)
Agora podemos definir a expressão matemática a utilizar:
sumnodes = x + y
Agora podemos calcular o resultado da expressão:
print(sess.run(sumnodes))
Para alterarmos os valores das variáveis devemos utilizar a função assign:
sess.run(x.assign(5.0))
Como sempre temos de executar dentro da sessão. Podemos associar esta operação a uma referência o que permite executar várias operações em simultâneo:
NewX = x.assign(5.0)
NewY = y.assign(10.0)
sess.run([NewX,NewY])
Agora, se avaliarmos a expressão o resultado é diferente:
print(sess.run(sumnodes))
Os placeholders têm um comportamento diferente, pois permite mudar o valor quando a expressão é avaliada, podendo ser definido um conjunto de valores (array) que fazem com que o TensorFlow avalie a expressão para cada um de eles.
Assim, criamos um placeholder:
a = tf.placeholder(tf.float32)
Como se pode ver não tem nenhum valor atribuído. De seguida alteramos a nossa expressão para:
sumnodes = x*a + y
Para avaliar a expressão fazemos:
print(sess.run(sumnodes,{a: 10}))
O parâmetro que é passado define o valor do placeholder. Também podemos fazer assim:
print(sess.run(sumnodes,{a: range(10)}))
ou assim:
print(sess.run(sumnodes,{a: [2,5,8,11]}))
Ao trabalharmos com variáveis e placeholders é muito importante não esquecer de fechar a sessão:
sess.close()
O vídeo no youtube
O codigo no Github
segunda-feira, 12 de fevereiro de 2018
Introdução ao TensorFlow - Parte 1
Segundo a Google o TensorFlow é uma framework the software aberto que permite para a computação numérica.
No TensorFlow cada nó pode ser uma constante, uma variável ou uma expressão matemática que utiliza variáveis e/ou constantes.
Estes nós pode ser executados no CPU ou no GPU tirando partido de dispositivos multicore.
Começamos por importar a framework:
import tensorflow as tf
Para criar uma constante fazemos:
node1 = tf.constant(3.0)
ou
node2 = tf.constant(4.0, dtype=tf.float32)
A primeira linha permite ao TensorFlow decidir qual o tipo de dados a aplicar à variável.
Depois temos de iniciar uma sessão TensorFlow assim:
sess = tf.Session()
Para ver o tipo de nó podemos utilizar:
print(node1,node2)
Para avaliar o nó, recebendo o valor que ele contém:
print(sess.run([node1,node2]))
Podemos criar uma função matemática que calcular a soma das duas constantes:
sumnodes = tf.add(node1,node2)
Para obter o resultado:
print(sess.run(sumnodes))
Vídeo no Youtube:
Código no GitHub
Como instalar o TensorFlow no Windows com Anaconda:
No TensorFlow cada nó pode ser uma constante, uma variável ou uma expressão matemática que utiliza variáveis e/ou constantes.
Estes nós pode ser executados no CPU ou no GPU tirando partido de dispositivos multicore.
Começamos por importar a framework:
import tensorflow as tf
Para criar uma constante fazemos:
node1 = tf.constant(3.0)
ou
node2 = tf.constant(4.0, dtype=tf.float32)
A primeira linha permite ao TensorFlow decidir qual o tipo de dados a aplicar à variável.
Depois temos de iniciar uma sessão TensorFlow assim:
sess = tf.Session()
Para ver o tipo de nó podemos utilizar:
print(node1,node2)
Para avaliar o nó, recebendo o valor que ele contém:
print(sess.run([node1,node2]))
Podemos criar uma função matemática que calcular a soma das duas constantes:
sumnodes = tf.add(node1,node2)
Para obter o resultado:
print(sess.run(sumnodes))
Vídeo no Youtube:
Código no GitHub
Como instalar o TensorFlow no Windows com Anaconda:
ASP.NET MVC com Entity, Identity e Migrações Parte 2 - Dropdown list
Na segunda parte do tutorial sobre MVC vamos adicionar uma dropdown list que permitirá escolher o perfil do utilizador.
No User model temos de adicionar um campo do tipo interface que servirá para passar à view a lista de opções:
public IEnumerable<System.Web.Mvc.SelectListItem> perfis { get; set; }
No User model temos de adicionar um campo do tipo interface que servirá para passar à view a lista de opções:
public IEnumerable<System.Web.Mvc.SelectListItem> perfis { get; set; }
No controlador temos de editar as funções Create e Edit para preencher a interface com um vetor com as opções de perfis. O código é qualquer coisa assim:
// GET: Users/Create
public ActionResult Create()
{
//perfis options for the dropdownlist
var user = new User();
user.perfis = new[] {
new SelectListItem{Value="0",Text="Admin"},
new SelectListItem{Value="1",Text="User"},
};
return View(user);
}
Agora as Views. Apagamos a linha que cria a text box e adicionamos uma linha para gerar a drop down list:
@Html.DropDownListFor( model=>model.perfil,new SelectList(Model.perfis,"Value","Text"))
Vídeo no youtube
Código no GitHub
// GET: Users/Create
public ActionResult Create()
{
//perfis options for the dropdownlist
var user = new User();
user.perfis = new[] {
new SelectListItem{Value="0",Text="Admin"},
new SelectListItem{Value="1",Text="User"},
};
return View(user);
}
Agora as Views. Apagamos a linha que cria a text box e adicionamos uma linha para gerar a drop down list:
@Html.DropDownListFor( model=>model.perfil,new SelectList(Model.perfis,"Value","Text"))
Vídeo no youtube
Código no GitHub
terça-feira, 6 de fevereiro de 2018
ASP.NET MVC com Entity, Identity e Migrations
Este tutorial explora o MVC da Microsoft com as frameworks Entity, Identity e migrações para a manipulação da base de dados.
A framework Entity é o que normalmente se apelida de um ORM (Object-Relational Mapping) basicamente é uma forma de armazenar dados de um objecto numa base de dados relacional sem utilizar SQL.
A framework Identity é responsável por gerir as credenciais do utilizador e as permissões de acesso, permitindo que cada utilizar tenha diferentes perfis.
A base de dados é criada com recurso às migrações (método code first), começando por criar uma classe que representa os dados em memória as migrações geram a correspondente tabela na base de dados.
O vídeo com o tutorial
O código no GitHub
A framework Entity é o que normalmente se apelida de um ORM (Object-Relational Mapping) basicamente é uma forma de armazenar dados de um objecto numa base de dados relacional sem utilizar SQL.
A framework Identity é responsável por gerir as credenciais do utilizador e as permissões de acesso, permitindo que cada utilizar tenha diferentes perfis.
A base de dados é criada com recurso às migrações (método code first), começando por criar uma classe que representa os dados em memória as migrações geram a correspondente tabela na base de dados.
O vídeo com o tutorial
O código no GitHub
sexta-feira, 26 de janeiro de 2018
Decision Trees
Neste artigo criamos uma árvore de decisão para classificar o género de pessoas com base na sua altura, peso e tamanho do calçado.
Para começar importamos da framework sklearn a class tree.
from sklearn import tree
De seguida criamos um vetor X com os valores que permitem criar uma tendência.
X=[[181,80,44],[177,70,43],[160,60,38],[154,54,37],[166,65,40],[190,90,47],[175,64,39],[177,70,40],[159,55,37],
[171,75,42],[181,85,43]]
Para começar importamos da framework sklearn a class tree.
from sklearn import tree
De seguida criamos um vetor X com os valores que permitem criar uma tendência.
X=[[181,80,44],[177,70,43],[160,60,38],[154,54,37],[166,65,40],[190,90,47],[175,64,39],[177,70,40],[159,55,37],
[171,75,42],[181,85,43]]
A estes valores temos de juntar a classificação de cada elemento, por isso criamos o vetor Y.
Y=['male','female','female','female','male','male','male','female','male',
'female','male']
Agora podemos criar um objeto do tipo DecisionTreeClassifier.
clf=tree.DecisionTreeClassifier()
Inserimos os valores e as classificações.
clf=clf.fit(X,Y)
Por fim podemos fazer uma previsão com base num exemplo novo.
prediction=clf.predict([[160,50,33]])
print(prediction)
Basta alterar os valores para obter uma classificação diferente.
Vídeo no YouTube
quinta-feira, 4 de janeiro de 2018
Instalar TensorFlow no Windows 10 com Anaconda
Este vídeo mostra como instalar o TensorFlow no Windows utilizando o Anaconda sem utilizar a linha de comandos.
Começa por abrir a ferramenta Anaconda Navigator e criar um Environment (Ambiente).
Agora, com o ambiente criado selecionado, pesquise pelo TensorFlow e clique em install.
De seguida instalamos o editor de código Spyder.
Por fim podemos atualizar a versão do TensorFlow com o comando:
conda install -c conda-forge tensorflow
Muito importante, devemos sempre executar o spyder através da linha de comandos deste ambiente, de outro modo o package do TensorFlow não está disponível.
Começa por abrir a ferramenta Anaconda Navigator e criar um Environment (Ambiente).
Agora, com o ambiente criado selecionado, pesquise pelo TensorFlow e clique em install.
De seguida instalamos o editor de código Spyder.
Por fim podemos atualizar a versão do TensorFlow com o comando:
conda install -c conda-forge tensorflow
Muito importante, devemos sempre executar o spyder através da linha de comandos deste ambiente, de outro modo o package do TensorFlow não está disponível.
Subscrever:
Mensagens (Atom)