[SOLVED] Creating a circular meter with code?


(azrafe7) #26

Use Draw.setTarget():

Draw.setTarget(myBitmapData);
Draw.linePlus(...);
Draw.resetTarget();

(Mike Evmm) #27

@TTL_Anderson

Those are some way cool effects. Regarding the trig involved, it’s really just a formula: <br

The formula for points on a circle are:

x = xcenter + radius * sin(theta)
y = ycenter + radius * cos(theta)

You simply have to iterate theta from your starting angle to your ending angle in small enough steps, and extract the x and y values for plotting


@azrafe7

That demo looks cool as hell.


(TaylorAnderson) #28

Alright, now that I have this bitmapdata, how do I use it? (forgive me for being so noobish: i’ve never worked with bitmaps before)


(azrafe7) #29

:rainbow: Rainbow bonus :wink:


(azrafe7) #30

Mind to elaborate some more.

What are you trying to do, and what have you tried so far?


(TaylorAnderson) #31

This is my code for the MeterBar (the class that displays the meter).

public function MeterBar(player:Player) 
{

	this.player = player
	this.layer = 0
	graphic = img
	Draw.setTarget(bitmapData)
	
}

override public function update():void
{
	
	this.x = player.x;
	this.y = player.y
	img.render(bitmapData, new Point, new Point)
}

override public function render():void
{
	Draw.arcPlus(x + 10, y + 10, 15, 60, player.meter * 18, player.inner.color, 1, true);
	Draw.arcPlus(x + 10, y + 10, 15, 60, player.meter * 18, player.inner.color, 1, true);

}

basically what i want to do is render the bitmap to an Image, if thats possible, because I want to use it as the entity’s graphic instead of having to redraw it every frame using Draw


(azrafe7) #32

Basically this then right?!

So…:

class MeterBar extends Entity {
  var meterBMD:BitmapData;
  var meterImage:Image;
  var player:Player;

  function MeterBar(...) {
    ...
    meterBMD = new BitmapData(width, height, true, 0); // new transparent BitmapData with correct size
    meterImage = new Image(meterBMD);
    graphic = meterImage;
  }

  override function added() {
    updateMeter(); // update meter graphic when added to world
  }

  function updateMeter() {
    Draw.setTarget(meterBMD); // set target to meterBMD
    Draw.arcPlus(..., player.meter * 18, ...); // draw the meter onto meterBMD
    Draw.resetTarget(); // reset Draw to target the screen instead of meterBMD
    meterImage.updateBuffer(true); // ensure the Image is also updated
  }

  override function update() {
    if (player.meter value has changed) {
      updateMeter();
    }
  }

That’s the general idea (it’s not actually compilable code, but you should get the gist of it).


(Zachary Lewis) #33

Any child of Graphic can take a BitmapData as a construction argument to create a Graphic. Once you have the BitmapData, you would (like @azrafe7 showed) create an Image from it, then use that Image wherever you’d like.


(TaylorAnderson) #34

Alright cool, I did not know that about Images (and other children of Graphic). I will try this out and report back!


(Zachary Lewis) #35

There may be some confusion caused by the terms I’m using.

Whenever someone talks about a texture, they are talking about a raster image where every pixel is defined with a value. Textures are very static: Every pixel has one and only one value, and you can’t break it down past pixels. A texture can be a wide range of things, such as a .png or a BitmapData, but they provide the same functionality — storing an image in an easily accessible format (making them quick to draw on the screen).

In Flash, the base display object is (unsurprisingly) the DisplayObject. Most of the drawing tools Flash provides draws vectors. A vector is a mathematical representation of a shape, so it is infinitely scalable, but every time it is drawn to the screen, the computer has to calculate what color to draw each pixel. So, if you have a vector circle, the edge won’t be fuzzy or pixelated no matter how much you squish or stretch it, but it will take much longer (in computer-time) to draw, since it will have to calculate every pixel using the mathematical representation of the circle.

The technique I was describing uses the pros of both textures and vectors: Creating a variable shape quickly (vector) and the ability to draw to the screen quickly (texture). Hopefully that clears up some confusion you might encounter.


(TaylorAnderson) #36

I got it (mostly) working, but now it doesn’t seem to update the image…the code is calling the updateMeter function appropriately, I checked, but the image isn’t changing…unsure if its just some bug in my own code though, so I’ll keep looking

EDIT:yeah the meter’s updating, everythings in place, but the image isn’t being updated. my implementation of @azrafe7’s code:

public class MeterBar extends Entity 
{
	private var player:Player
	public var redraw:Boolean = false;
	private var bitmapData:BitmapData
	private var img:Image
	public function MeterBar(player:Player) 
	{
		bitmapData = new BitmapData(60, 60, true, 0)
		img = new Image(bitmapData)
		this.player = player
		this.layer = 0
		graphic = img
		img.x = -10
		img.y = -10
		
		
	}
	override public function added():void
	{
		updateMeter();
	}
	override public function update():void
	{
		this.x = player.x;
		this.y = player.y
	}
	
	public function updateMeter():void
	{
		trace(player.meter)
		Draw.setTarget(bitmapData)
		Draw.arcPlus(x + 20, y + 20, 15, 60, player.meter * 18, player.inner.color, 1, true);
		
		Draw.resetTarget()
		img.updateBuffer(true)
		graphic = img
	} 

i call updatemeter from player, right after his meter changes. (i put graphic = img at the end of the function to see if that would work, it didnt)


(TaylorAnderson) #37

I suppose I should probably put this in a new post: the image isn’t updating, for some reason. See code above


(azrafe7) #38

Yes, agree with creating a new topic. Also sharing the project (or even better a simpler case with relevant code) would help.

By the way, can you try this (draw the bitmapDatajust onto the screen directly) and report if the meter is correctly shown:

in MeterBar add this:

  override public function render() {
    super.render();
    var matrix:Matrix = new Matrix();
    matrix.translate(100, 100); // translate this somewhere where it is visible
    FP.buffer.draw(bitmapData, matrix); // this draws bitmapData on screen at 100, 100
  }

(Mike Evmm) #39


(TaylorAnderson) #40

That doesn’t work either, which makes me think my Draw call isn’t working properly. I’ll take a closer look


(azrafe7) #41

Yes, it’s your Draw call. Try changing to:

public function updateMeter():void
{
	trace(player.meter);
	bitmapData.fillRect(bitmapData.rect, 0); // clear bitmapData
	Draw.setTarget(bitmapData);
	// removed x, y from next call as they are relative to bitmapData and not to screen
	Draw.arcPlus(20, 20, 15, 60, player.meter * 18, player.inner.color, 1, true);
	Draw.resetTarget();
	img.updateBuffer();
}

Also, since I tested it, you’ll probably end up with the meter’s position being out of sync in respect to the player. If it does just update its pos in render(), or change it directly from player.update().


(TaylorAnderson) #42

Alright cool, it works now :stuck_out_tongue:

This has perhaps been the most I’ve learned in a single Flashpunk topic, so thanks guys!


(Zachary Lewis) #43

Even that topic where I posted half a season of Coin Duder? Or that topic where I added eleven more episodes of Coin Duder!? :cry:


(TaylorAnderson) #44

I never saw those :stuck_out_tongue: I’m not sure how much I’d learn from it now that I’ve been using FP for like, 2yrs


(Zachary Lewis) #45

You’d be surprised. You’ll learn over ten ways to fuck up what you’re trying to do!


Text effects found in A Thousand Years Of Dreams - there's support in Flash, but is it possible to mix .fla work and .as work in my flashpunk game?