Posts Tagged ‘tip’

Dynamic Sound – Part 1

Monday, April 27th, 2009

Eu passei as duas ultimas semanas trabalhando num projeto envolvendo som. Infelizmente não posso mostra-lo ainda, mas meu objetivo era tocar um monte de notas musicais em um intervalo especifico. A primeira coisa que eu tentei fazer foi carregar um monte de samples e toca-los quando precisasse, mas o desempenho ficou muito baixo com isso. Então minha solução foi procurar no Google e no lab do Andre Michelle para entender como trabalhar com sons dinamicos.

Bom, ainda estou aprendendo, mas eu acho que muitas pessoas gostariam de trabalhar com isso e não tem a menor ideia por onde começar, por isso espero que esse post seja util para essas pessoas.

A primeira coisa que precisamos entender é que o som é uma onda, e essa onde pode ter diferentes formatos dependendo do som que você está ouvindo.

sound_wave
(more…)

CustomCursor advanced

Wednesday, April 15th, 2009

OK, let’s begin talking about Design Patterns.

The best thing of OOP, is the capability to create something in way to reuse it in another situation by defining some patterns to follow. Basicly this is Design Patterns. There are several kinds of Patterns and one of them is the Singleton Pattern. It consists in create only one instance of a class and control it by global functions and properties. Unless you are using a multi-touch device, a good example of usage is a CustomCursor class. There is no need to create more than one instance of a custom cursor, because you can point to only one thing at time. However you can change your cursor behavior from anywhere in your application.

The Basics

Let’s create our Singleton class

package {
	import flash.display.Sprite;
 
	public class CustomCursor extends Sprite {
 
		private static var _instance:CustomCursor;
		public function CustomCursor(singleton:SingletonEnforcer):void{
		}
		public static function getInstance():CustomCursor{
			if(CustomCursor._instance == null){
				CustomCursor._instance = new CustomCursor(new SingletonEnforcer());
			}
 
			return CustomCursor._instance;
		}
	}
}
class SingletonEnforcer {
	public function SingletonEnforcer():void{
	}
}

(more…)

Stage.quality vs performance

Friday, April 3rd, 2009

Uma dos piores problemas que um desenvolvedor tem de enfrentar é o desempenhos de suas aplicações. Existem diversos fatores contribuindo para um mau desempenho, um deles é a renderização dos gráficos.

Dependendo de como você está fazendo, existe uma linha de código que resolve esse problema.

stage.quality = StageQuality.LOW

Quando você define a qualidade do stage como low, você diz para o flash renderizar todos os vetores sem suavização. Isso melhora drásticamente a performance. Contudo, isso pode fazer com que sua aplicação fique horrível dependendo da maneira que você a constroi. Existem algumas coisas que você pode fazer para balancear a performance e a qualidade visual.

A primeira delas é definir o alias mode ddo seus textos como ADVANCED ou se for um texto estático como Anti-alias for readability.

This movie requires Flash Player 9

Outra dica é usar bitmaps em vez de vetores. Claro que você precisa escolher direito quais graficos precisam ter uma boa qualidade e o tamanho deles. Você podem também mudar a qualidade da sua imagem através do painel de propriedades para obter um arquivo menor. Entretanto você precisa tomar cuidado com isso, pois os seus bitmaps não vão suavizar caso você rotacione ou mude sua escala.

Eu não pesquisei porque os bitmaps não distorcem quando a qualidade está como low, mas eu acho que o flash não precisa calcular qual cor cada pixel vai ter quando é exibido, todas as cores já estão definidas pelo bitmapData.

Com isso em mente, eu criei uma classe de conteiner com alta qualidade, chamada HQContainer, que renderiza todos os seus filhos com a qualidade que você quiser (low, medium, high, best).
(more…)

Dynamic Custom Event

Tuesday, March 31st, 2009

Custom Events se tornaram muito práticos no desenvolvimento de aplicações mais complexas.
Você pode cria-los para casos específicos e geralmente eles vêm acompanhados de parametros específicos.

Vamos dizer que você cria uma evento customizável para uma classe de vídeo player e você utiliza ele para checar eventos de carregamento e execução do vídeo, como play, pause, progresso da execução e quando ela termina. Então quando você cria esse evento, é precisso passar esses parametros de alguma forma. Diretamente como parametros opcionais, através de um object, array ou da forma que você achar mais adequada.

Entretanto, durante o carregamento de um vídeo, você precisa dos bytesLoaded e bytestotal, mas não precisa da tempo de execução atual. Outro caso é quando você dispara um evento dizendo que o stream foi pausado ou quando a execução termina, você não precisa de nenhum parâmetro além do tipo de evento. O problema (problema não, mais como uma encheção de saco) é que, para cada parâmetro, você precisa criar uma variável na sua classe para armazenar o valor passado, caso contrário você não conseguira passsar nenhum deles atravéz do evento.

Para evitar isso, você pode definir seu evento como dynamic class. Para aqueles que não sabem, classes dinamicas permitem que você crie propriedades nelas em tempo de execução, como movie clips. Assim você consegue passar qualquer parâmetro atravéz de um objeto como parâmetro opcional do evento e armazena-lo na classe, dessa forma:

package app.events {
	import flash.events.Event;
 
	dynamic public class CustomEvent extends Event {
		public function CustomEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false, param:Object = null):void{
			super(type, bubbles, cancelable);
 
			if(param){
				for(var i:String in param){
					this[i] = param[i];
				}
			}
		}
	}
}

Então quando você precisar passar qualquer valor, você adiciona ele em um objeto:

dispatchEvent(new CustomEvent(CustomEvent.LOAD_PROGRESS, false, false, {bytesLoaded:135817, bytesTotal:521387}));
dispatchEvent(new CustomEvent(CustomEvent.VIDEO_PROGRESS, false, false, {currentTime:8.65}));
dispatchEvent(new CustomEvent(CustomEvent.PAUSE));

E recebe ele dessa forma:

function onLoadProgress(event:CustomEvent):void{
	trace(Math.floor(event.bytesLoaded*100/event.bytesTotal)+"% loaded");
}
function onVideoProgress(event:CustomEvent):void{
	trace("Current time:", event.currentTime);
}
function onPause(event:CustomEvent):void{
	trace("Video paused");
}

Papervision3D – Max3DS Parser bug

Friday, March 27th, 2009

Desde que o papervision adicionou o Max3DS parser, eu venho usando ele invés de trabalhar com DAE. Entretanto existe um bug que eu notei quando importei um modelo assimétrico na minha cena. Ele estava espelhado no eixo X. Como estava correndo eu tomei o cmainho mais fácil, espelhei meu modelo antes de exportar o arquivo 3ds.

Depois disso eu tentei mudar o parser para importar o arquivo corretamente mas estava me tomando mais tempo do que eu tinha, então escrevi esse método para concertar o mesh depois do parsionamento.

Aqui está minha cena no 3D Max

objects

Note que o cubo está atrás da chaleira e o cilindro na frente dela.

Aqui está uma imagem da cena no PPV quando eu importo eles usando o Max3DS

objects_fliped

Depois de rodar meu script

objects_normalized

Eu não testei ele para modelos mais complexos, mas ele vai funcionar em 90% dos casos.

Aqui está o script:

normalize(object3ds);
 
function normalize(max3ds:Max3DS):void{
	max3ds.rotationX = 0;
	max3ds.rotationY = 0;
	max3ds.rotationZ = 0;
 
	for each(var mesh:DisplayObject3D in max3ds.children){
		mesh.scaleZ *= -1;
		mesh.rotationX *= -1;
		mesh.rotationY *= -1;
		mesh.rotationZ *= -1;
 
		var m:Matrix3D =  new Matrix3D();
		m.calculateMultiply(m, Matrix3D.rotationX(mesh.rotationX*Math.PI/180));
		m.calculateMultiply(m, Matrix3D.rotationY(mesh.rotationY*Math.PI/180));
		m.calculateMultiply(m, Matrix3D.rotationZ(mesh.rotationZ*Math.PI/180));
 
		m.calculateMultiply(m, Matrix3D.scaleMatrix(mesh.scaleX, mesh.scaleY, mesh.scaleZ));
 
		for(var i:Number = 0; i<mesh.geometry.vertices.length; i++){
			var vertex:* = mesh.geometry.vertices[i];
 
			var vx :Number = vertex.x;
			var vy :Number = vertex.y;
			var vz :Number = vertex.z;
 
			var tx :Number = vx * m.n11 + vy * m.n12 + vz * m.n13 + m.n14;
			var ty :Number = vx * m.n21 + vy * m.n22 + vz * m.n23 + m.n24;
			var tz :Number = vx * m.n31 + vy * m.n32 + vz * m.n33 + m.n34;
 
			vertex.x = tx;
			vertex.y = ty;
			vertex.z = tz;
		}
 
 
		mesh.rotationX = 0;
		mesh.rotationY = 0;
		mesh.rotationZ = 0;
		mesh.scaleZ *= -1;
 
		mesh.geometry.flipFaces();
	}
}

Demo
Source

Loader issue

Monday, March 23rd, 2009

Sexta passada estava olhando o Flash Bookmarks e vi que uma dúvida foi postada em relação ao Loader.
Um tempo atrás eu precisei carregar um arquivo utilizando um Loader e depois adicionar o conteudo carregado no stage. Contudo um erro era gerado ao adicionar o conteúdo.

ArgumentError: Error #2025 : The supplied DisplayObject must be a child of the caller.

Para resolver o problema eu precisei extrair o conteudo em uma variavel e depois executar um loader.unload() antes de adicionar ao stage.

function onLoadComplete(e:Event):void{
	var image:Bitmap = e.currentTarget.content;
	loader.unload();
	addChild(image);
}

É o mesmo caso quando você utiliza o mesmo loader para carregar dois ou mais arquivos.

Exemplo

Soundcard check

Tuesday, September 16th, 2008

Para verificar se a placa de som está disponível, veja se a classe SoundChannel não é nula

var sound:Sound = new Sound();
var channel:SoundChannel = sound.play();
 
if(channel != null){
    trace("Soundcard available");
}else{
    trace("Soundcard not available");
}

numberLoop

Wednesday, September 3rd, 2008

Um método que eu uso bastante quando preciso de um loop em determinado comprimento de elementos

trace(numberLoop(103754, 3));
//2
 
trace(numberLoop(686.9384, 17.53));
//3.268399999999957
 
trace(numberLoop(Math.PI*13/6, Math.PI*2));
//0.5235987755982991 rad - radToDegree == 0.5235987755982991*180/Math.PI -&gt; 30.000000000000014º
 
trace(numberLoop(-2187.4, 2));
//0.599999999999909
 
function numberLoop(n:Number, t:Number):Number {
	if(t<=0){
		throw new Error("Total must be greater thant 0");
	}
 
	return (n%t+t)%t;
}