[SOLVED] Creating a circular meter with code?


(TaylorAnderson) #1

Hey y’all.

I’m thinking of implementing a life meter (sorta) into my game, but my players are just circles. So I wanted a lifebar that sorta wraps around them and fills up or goes down as they get damaged.

Because I’m not very good at explaining things, here is what I mean:

I have an idea how this might work–involving some trigonometry and line segments–but is there an easy way to do this / some tutorial on how to do it?


(Zachary Lewis) #2

The easiest solution would be to create a spritesheet with a fixed number of frames, then set the frame based on the percentage of life left. This method would also look best if you’re using a low-resolution art style.

You could also achieve this effect with two half-circle masks, but it would be more code-intensive and would probably be harder to achieve the same visual style.


(TaylorAnderson) #3

I don’t have a particular need for it to be lowres (the meter would likely be 40x40, since the players are 20x20 squares).

My initial conclusion was to do the spritesheet thing, and I’ve done it before to mimic a weirdly shaped ‘meter’, its just tedious and I thought I could perhaps do it w/ code to save time. But if you don’t think itd save time perhaps I’ll just do that.


(Mike Evmm) #4

For the sake of it I googled a bit: here’s something you might (from the way you worded your question) have seen.
I suppose this could be done with Draw somewhat like this (and bear with me please, I’ve never used the curve() function and have no compiler at hand to check for errors, or even if it works!):

public var life:Number //Out of 100
override public function render():void{
    if (life<100) {´
         var radius:Number = 20;
        var startPoint:Point = new Point(-radius, 0);
        var theta:Number = (life*Math.PI*2) / 100;
        var controlPoint:Point = new Point(radius* Math.sin(theta/2), radius* Math.cos(theta/2) );
        var endPoint:Point = new Point(radius* Math.sin(theta), radius * Math.cos(theta));
        Draw.curve(startPoint.x, startPoint.y, controlPoint.x, controlPoint.y, endPoint.x, endPoint.y);
    }else{
        Draw.circle(0, 0, radius);
    }
    super.render();
}

Haha, that was insane :smile: Can somebody confirm that this doesn’t work at all? Also, @zachwlewis, I’m curious, how would half-circle masks work?


P.S. I realize that becuase it is a curve it will look weird, but more control points could be used for a hackish solution.


(TaylorAnderson) #5

I’m not at my computer right now, but if that ends up working you are a god :stuck_out_tongue:


(Mike Evmm) #6

III don’t think so :stuck_out_tongue:


Edit: Most likely because of this: (quadratic curves)


(Zachary Lewis) #7

First, you need to know what your health circle will look like. You’ll want to be able to mask out a circle.

This doesn’t allow any rotation, so you’ll need to split it up. (Black is the mask area and red is the background color. It doesn’t really matter what masks what as long as you use the same principle.)

Now, you can’t just show the entire thing all the time. To begin filling, hide the left side of the region.

You’ll need to rotate your mask so when the masking is applied, none of the health bar is shown. This will be your zero-health state.

Now, as you rotate the mask, it’ll show the red area it is masking. This mask will handle health from 0–50%.

At this point, you’ll do the exact same thing for the left side of the meter, and it’ll handle health from 50–100%. Not too tricky, but you’ve gotta’ manage states here. If you really need fine-grained health display for all percentages, you can use this method to some success.


(Zachary Lewis) #8

Perhaps a better solution would be to draw to a MovieClip and then render it to a BitmapData. I’ve used this arc drawing process in the past to great success. I’d also set the line line caps style to CapsStyle.NONE to get rid of those weird round ends.


(Mike Evmm) #9

That last solution sounds the best to me (for this case).


Well, if I understood correctly, his solution is pretty much the same discussed above, he just draws a series of small line segments from “control point” to “control point” o get a round effect.


(TaylorAnderson) #10

I’m gonna take a look at that link. I’m not a big fan of mixing regular old Flash with Flashpunk stuff, though :confused:


(Mike Evmm) #11

Its not that far away from regular FP; you only need to use this process to obtain the BMD (which usually isnt generated by flashpunk anyway) and then you can use an image.


(TaylorAnderson) #12

Alright I’ll start diggin into it soon. I don’t need this meter thing right away (and I’ll probably just test the mechanic with an ordinary rectangular one, and then switch if it works).


(TaylorAnderson) #13

So I tried to ‘port’ Emanuele Feronato’s code to Flashpunk and…it didnt really work. I think its more to do with my lack of understanding of how the code worked rather than an actual deficiency in Flashpunk though, so I’m gonna keep trying.

I can’t even be mad, because my first result was beautifully horrifying in its own right:

(I just plopped the class right on the title screen for quick testing :P)


(TaylorAnderson) #14

Aaannd second experiment:

I’m really just kind of enjoying this in its own right.


(TaylorAnderson) #15

Alright last one I swear.

I’m really bad at trigonometry :stuck_out_tongue:


(TaylorAnderson) #16

Final note: I got it working with just Flashpunk stuff, but the performance is HORRENDOUS. Four circles (which is the max of what I need) and the fps is 20 on average, even with a low number of points. I’m assuming this is cuz I’m using Draw statements, but I’m totally inexperienced with using Bitmaps :frowning:


(TaylorAnderson) #17

It doesn’t help that its also really pixellated, even with linePlus. So I think my solution here is just gonna be to draw it by hand…


(azrafe7) #18

Here’s an implementation of Draw.arc().

Probably the best solution would be to generate a meter spritemap procedurally by using arc drawing to mask the actual underlying meter graphic. Mmmh… I might turn this idea into something…


(TaylorAnderson) #19

If you can make something fast and efficient and nice to use thatd be super awesome, for now I’m just using handmade spritesheets :stuck_out_tongue:


(azrafe7) #20

Don’t know if I’ll get to make it, we’ll see.

By the way just using some calls to Draw.arcPlus() (from the code linked previously) you can get interesting results.

I have this in render():

Draw.arcPlus(FP.halfWidth, FP.halfHeight, 40, 180, 360, 0xFFFFFF, 1, false, 9);
Draw.arcPlus(FP.halfWidth, FP.halfHeight, 40, 180, spanAngle, 0xFF0000, 1, false, 10);
Draw.arcPlus(FP.halfWidth, FP.halfHeight, 35, 180, 360, 0, 1, false, 2);
Draw.arcPlus(FP.halfWidth, FP.halfHeight, 45, 180, 360, 0, 1, false, 2);

and tween the spanAngle to get this swf