Primeiro vou explicar o princípio, depois a parte do desenho:
No meu exemplo, suponho que você tenha um valor de progresso de 0 a 100 (%), mesmo que qualquer outra coisa faça.
Em uma linha reta, a posição atual da barra de progresso seria simplesmente esse valor de progresso.
Em um círculo, você obtém essa posição com trigonometria. Qualquer ponto em um círculo é dado como:
point.x = r * cos(angle);
point.y = r * sin(angle);
onde r é o raio do círculo. Como você vê, o ângulo é a única variável nessas equações. Isso significa que você de alguma forma precisa integrar seu progresso ao ângulo.
A solução é simples: uma "corrida" ao redor do círculo é igual a 2 * Pi (ou 360 graus). Você precisa dividir essa distância em 100 partes menores, para que, quando o valor do progresso for 100, o valor dentro de cos () e sin () seja 2 * pi (ou 360 graus).
Você consegue isso simplesmente dividindo 2 * pi (ou 360 graus) por 100 e multiplicando-o pelo progresso:
float step = 2*pi/100;
point.x = r * cos(progress * step);
point.y = r * sin(progress * step);
Agora para a parte do desenho.
Não sei nada sobre o Actionscript3 (ou o Flash, por sinal), por isso não posso lhe dizer os procedimentos exatos, mas em geral haveria duas maneiras de fazer isso:
Primeiro, e (na minha opinião, mais fácil dos dois): desenhe o círculo parcial manualmente como simplesmente uma conexão de linhas coloridas com uma certa espessura (se você não precisar de uma textura e bastar uma cor simples) ou desenhe o circule como uma conexão de quadriláteros texturizados (se você precisar de texturas).
Segundo: você desenha uma imagem que representa seu círculo totalmente carregado e o carrega como textura, coloca-o em um quadrilátero e o renderiza. Em seguida, desenhe manualmente um círculo parcial sobre esse quadrilátero e renderize apenas a parte do quadrilátero texturizado onde o círculo é renderizado à sua frente. No OpenGL, por exemplo, você pode fazer isso facilmente usando o buffer de estêncil.
Se você deseja saber como calcular os diferentes pontos do seu círculo para usá-los na montagem dos polígonos / linhas necessários, observe as equações acima novamente:
point.x = r * cos(angle);
point.y = r * sin(angle);
Você pode executar aqueles dentro de um loop for que vai de 0 ao seu progresso atual, por exemplo, se fosse um círculo que consistia em uma série de pontos conectados (na sintaxe c ++):
float granularity = 2*PI/required_granularity; //determines how smooth your circle will look
float step = 2*PI/100.0f;
list<Vector2> points; //list of all the calculated points
for(float angle=0; angle < progress*step; angle += granularity)
{
Vector2 point(radius*cos(angle), radius*sin(angle));
points.push_back(point); //adds the point to the list
}
Agora, todos esses pontos serão centralizados na origem do seu sistema de coordenadas, portanto, é necessário movê-los para qualquer posição em que você queira que seu círculo esteja. Mas acho que você pode descobrir isso sozinho: P
Não tentei o seguinte, mas parece que deve funcionar.
Você precisa de duas imagens:
O seguinte pressupõe que sua marca de 0% (e 100%) está na posição de 9 horas.
Se o seu progresso for 50% ou menos:
Se o seu progresso for> 50%:
Não sei como fazer isso especificamente (ou se é possível) no AS3. Espero que isso faça sentido (ah, e realmente funcione!).
fonte
Outro método que vi foi usar shaders.
Você só precisa de uma imagem, a imagem inteira do HUD, com a área de progresso em uma escala de cinza degradê. Comece na posição 0% (9 horas, por exemplo) com branco puro e progrida gradualmente para preto na posição 100%.
Você não pode ter nenhum cinza na parte do HUD, incluindo branco ou preto. Se você precisar usar essas cores, escolha outra cor pura para sua escala de gradiente (uma cor que não é usada em nenhum outro lugar).
Faça com que seu programa passe ao sombreador o valor do progresso no intervalo de '0,0' a '1,0' (ou qualquer escala que o idioma do seu sombreamento use para os intervalos de cores). Você também pode passar ao shader uma cor da barra de progresso (e a cor 'off', se desejar), se quiser que a cor mude dinamicamente, como quando estiver vazia (ou cheia) para avisar o jogador.
No seu sombreador, você avalia cada pixel de origem e, se for cinza puro (cada R, G, B tem o mesmo valor), esse pixel faz parte do medidor de progresso. Se não for apenas passar a cor original. Se for um pixel do medidor de progresso, é necessário determinar se deve ser a cor 'ativada' ou a 'desativada'. Basta verificar a cor do pixel (é cinza puro, então você só precisa dizer o componente 'vermelho') para ver se está acima ou abaixo do valor do progresso passado. O efeito é que qualquer cor cinza abaixo do valor do progresso será ativada, as outras serão desativadas.
fonte