I am trying to draw a line from x1, y1 to x2,y2 and i want it to be a line that repeats a pattern from an image. All I can see is that you can only draw lines and change their color or thickness but I would like it to repeat an image. Is that possible or do i have to use a really long and thin rectangle with a bitmap fill?
The problem is I am making a game where the user will be able to actually draw the line so i have to make it be created dynamically.
The game fantastic contraption (www.fantasticcontraption.com) has in the game a feature where you draw lines of any length and position that are filed with a picture.
Any help is appreciated. Thanks!!
Thanks , I will look into it but I don't think that is exactly what I need. I am more looking to for something like being able to draw a dashed line of any length and have each dash have some texture.
I am thinking that perhap the people at fantasticcontaption did something like draw a rectangle and rotate it using a matrix. What is strange that no one ever had to do anything similar becuase i can not find any examples of a similar thing and it seems like it should be pretty common.
Actually you can do this natively in the drawing API, but only from flash player 10.
There are two ways to do it.
The old API style in fp10, with the new bitmap stroke:
http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/display/Graphics.h tml#lineBitmapStyle()
or
using the IGraphicsData object approach:
create a GraphicsStroke
and assign its fill to be a new GraphicsBitmapFill
A dashed line is more complicated and requires the data for the drawing path which is iterated along its length to draw shorter segments, switching the stroke on and off for each one. Easy for straight lines, a bit more complicated for curves etc.
Here's an example (in Flex, using Degrafa - just for illustrative purposes, I know you are doing this in flash, not flex, so its not directly applicable) with a dashed line.The stroke style here is a gradient style, we haven't implemented the fp10 bitmap stroke in degrafa yet:
http://degrafa.org/source/HappyHolidays/HappyHolidays.html
The underlying Degrafa code for the dashed line is basically doing what I described above.
This code handles curves and arbitrary dash on and off patterns, as well as being specific to work with the Degrafa rendering flow...so it's probably a lot more complex than you'd be looking for, but the general idea is to measure each segment making up your drawing line, (pythagoras if its only linetos) and then break up into pieces the length of your dash on and dash off requirements. You may need to combine the end of one segment with the start of the next one, for example. You switch the lineStyle off with graphics.lineStyle() (i.e. no arguments) and then switch it back on with regular arguments. You can also use moveTo to make gaps in the line but only if you don't need to use a fill, otherwise you must draw the null stroked segments with lineTos for the fill to work correctly.
@kglad you're right, thanks for pointing it out - that is different, I had just interpreted the questions in the text here. I did check out the link earlier but I tend to be impatient with links if I can't see the thing I'm supposed to see straight away. I took another look now and I see (I think) what is meant....the animated blue line with the white 'stroke' and the wooden branch 'stroke'.
I would still be inclined to do something like this with the drawing api.
The same type of approach as the dashline could be used for any type of line decoration along a drawing path if you treat the path as data. It just needs to be drawn slightly differently and redrawn on a frame loop if its animated. If they're doing it that way too, I don't know from looking at it whether the animated blue line is a filled shape or whether the white outline is a filter and the blue part is just a the (frame animated) drawn line.
i think i could create that blue line (water rod) using a movieclip (of an animated horizontal long blue line) that contains a child mask movieclip that masks the blue animated line. by rotating the main movieclip and than sizing the mask i could create that effect.
the wood rod could be easily done using the lineBitmapStyle() method.
yes both those ways could work. I often find myself veering towards code and thinking less about the timeline when I should be.
I think on both counts you could also actually do what the OP suggested in the first post:
Draw a shape that represents a rotated rectangle that runs along the line segment with no stroke and a bitmapFill with a repeat = true and the fill's matrix rotated to orient in the correct direction
use the same bitmapData for all the fills, with matching edges for continuity when repeated
one for the branch
one for the blue stroke
for the animated blue line, just animate the single instance of the blue stroke bitmapdata by scrolling its pixels.
I think that would also work and be pretty lightweight.
I just threw together a quick proof of concept for the last technique I described...using some similar to the branch image from that earlier link. The swf is attached. Just click around the stage.
I didn't get too sophisticated here.... so no mouse dragging of the circles etc although that would be easy to add in.
Once its drawn via the drawing API its basically just the native renderer that get's sluggish with the animation updates if you add too much. All the bitmapdata transformations are being done at the native level for the updates, but it can get quite cumbersome/cpu intensive if you put too much on stage. I suspect it might be faster under these conditions if the drawn content was vector data, because you can loop through thousands of drawing commands very quickly.
BranchBitmap is a library bitmap set to export on frame 1 with BranchBitmap as the class name.
The code for this is :
var segments:Sprite=new Sprite()
addChild(segments)
var connectors:Sprite = new Sprite();
addChild(connectors);
var points:Array=[];
stage.addEventListener(MouseEvent.CLICK, clickhandler)
stage.addEventListener(Event.ENTER_FRAME,frameupdater);
function clickhandler(e:MouseEvent):void{
points.push(new Point(e.stageX,e.stageY));
connectors.graphics.beginFill(0xff0000,.8);
connectors.graphics.drawCircle(e.stageX,e.stageY,15);
drawNewSegment()
}
var lastPoint:Point;
var scrollwidth:uint=2;
var branchBitmapData:BitmapData = new BranchBitmap(247,52);
var scrollpixels:BitmapData = new BitmapData(scrollwidth,branchBitmapData.height)
function frameupdater(e:Event):void{
branchBitmapData.lock();
var rect:Rectangle = branchBitmapData.rect;
rect.x=branchBitmapData.width-scrollwidth;
rect.width=scrollwidth;
scrollpixels.copyPixels(branchBitmapData,rect,new Point(0,0))
branchBitmapData.scroll(1,0)
branchBitmapData.copyPixels(scrollpixels,scrollpixels.rect,new Point(0,0))
branchBitmapData.unlock();
}
function drawNewSegment():void{
if (points.length>1){
if (!lastPoint) lastPoint= points[0];
var latestPoint:Point = points[points.length-1];
var diff:Point = latestPoint.subtract(lastPoint);
var angle:Number = Math.atan2(diff.y,diff.x);
var baseRectangle:Rectangle = new Rectangle (lastPoint.x, lastPoint.y-branchBitmapData.height/2,Point.distance(lastPoint,latestPoint),branchBitmapData.height);
var drawingPoints:Array=[];
var drawingMatrix:Matrix = new Matrix();
var bitmapMatrix:Matrix=new Matrix();
bitmapMatrix.translate(0,-branchBitmapData.height/2)
drawingMatrix.translate(-lastPoint.x,-lastPoint.y);
drawingMatrix.rotate(angle);
bitmapMatrix.rotate(angle);
drawingMatrix.translate(lastPoint.x,lastPoint.y);
bitmapMatrix.translate(lastPoint.x,lastPoint.y);
//DEBUG: segments.graphics.lineStyle(0,0,1);
segments.graphics.beginBitmapFill(branchBitmapData,bitmapMatrix,true,true)
var p:Point = drawingMatrix.transformPoint(baseRectangle.topLeft);
var sp:Point =p;
segments.graphics.moveTo(p.x,p.y);
p=drawingMatrix.transformPoint(new Point(baseRectangle.bottomRight.x,baseRectangle.y));
segments.graphics.lineTo(p.x,p.y);
p=drawingMatrix.transformPoint(baseRectangle.bottomRight);
segments.graphics.lineTo(p.x,p.y);
p=drawingMatrix.transformPoint(new Point(baseRectangle.x,baseRectangle.bottomRight.y));
segments.graphics.lineTo(p.x,p.y);
segments.graphics.lineTo(sp.x,sp.y);
lastPoint= latestPoint
}
}
It looks like the uploads take ages in a 'QUEUED' state, here is the swf and fla as download links, if you want to take a look:
Demo (click around)
http://www.interactionscript.com/adhoc/drawingAPI.swf
Download fla (CS3):
Thank you for your replies. I have tried the demo you posted and it worked and I think I will use this method with a bit of tweaking ( the biggest issue is that the line does not show up while drawing ).
Unfortunately I only have Flash CS3 so I can't (as far as I know) use the flash 10 features.
I appreciate all you help.
You're welcome.
That last part is the easy part
- you just need to redraw the segment between the last point and the current point on mouse move. For performance reasons it's probably best to split the segments out into individual Shape instances inside the segments Sprite , so you're only updating the drawing commands in the last added Shape object.
I don't have cs4 yet either. But if you need to code for fp10 and you're using windows you can do code-only projects (no timeline) with FlashDevelop.
North America
Europe, Middle East and Africa
Asia Pacific
Copyright © 2012 Adobe Systems Incorporated. All rights reserved.
Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy (updated 07-14-2009).