How to highlight static text background in AS3 dynamically? - actionscript-3

If i can search a word in search box that word will find static text then highlight appear in flash as3. Any suggest please?

You can use .getCharBoundaries(), which returns a Rectangle encompassing a character at a given index in your TextField.
Using that Rectangle, you can create some highlight graphics. Here's a function that will simplify that process:
function highlightChar(textField:TextField, charIndex:int):void
{
var rect:Rectangle = textField.getCharBoundaries(charIndex);
var box:Shape = new Shape();
box.blendMode = BlendMode.MULTIPLY;
box.graphics.beginFill(0xFFCC33);
box.graphics.drawRect(textField.x + rect.x, textField.y + rect.y, rect.width, rect.height);
box.graphics.endFill();
if(textField.parent) textField.parent.addChild(box);
}
From here, you can create another function that will accept a phrase to highlight:
function highlightPhrase(textField:TextField, phrase:String):void
{
var start:int = textField.text.indexOf(phrase);
if(start >= 0)
{
for(var i:int = start; i < phrase.length; i++)
{
highlightChar(textField, i);
}
}
}
Combined, you'll find it easily to highlight a block of text like this:
var t:TextField = new TextField();
t.text = "This text is highlighted";
addChild(t);
highlightPhrase(t, "This text");

Related

Changing color of objects based on the color as3

I have made simple drag-and-drop color buttons where if user drag the specific buttons, it will detects the color based on the what user drag and apply it to the object where user drop the color into. However, I can't figure it out why the color keep changing to black whenever I chose a button and drag and drop it to the single object in the scene, it will turn black even though I already have define the color of buttons.
How can I solve this?
Here is the code that I am using (I am using this on CS6):
var array_objects:Array = new Array(firstRectangle_mc, secondRectangle_mc, thirdRectangle_mc, fourthRectangle_mc);
var hit_object:Array = new Array();
var color_x:int;
var color_y:int;
addListeners(red_btn, black_btn, yellow_btn);
function addListeners(... objects):void
{
var color:Array = new Array("0xFF0000", "0x000000", "0xFFFF00");
for (var i:int = 0; i < objects.length; i++)
{
var input:TextField = new TextField();
input.text = color[i];
input.visible = false;
objects[i].addChild(input);
objects[i].addEventListener(MouseEvent.MOUSE_DOWN, onColorMouseDown);
objects[i].addEventListener(MouseEvent.MOUSE_UP, onColorMouseUp);
}
}
function onColorMouseDown(e:MouseEvent):void
{
hit_object = [];
color_x = e.currentTarget.x;
color_y = e.currentTarget.y;
e.currentTarget.startDrag();
}
function onColorMouseUp(e:MouseEvent):void
{
e.currentTarget.stopDrag();
for (var i:int = 0; i < array_objects.length; i++)
{
if (e.currentTarget.hitTestObject(array_objects[i]))
{
hit_object.push(array_objects[i]);
}
}
e.currentTarget.x = color_x;
e.currentTarget.y = color_y;
var changeColor:ColorTransform = hit_object[hit_object.length - 1].transform.colorTransform;
changeColor.color = e.currentTarget.text;
hit_object[hit_object.length - 1].transform.colorTransform = changeColor;
}
Here is the link of the demo:
Link
Your answer much appreciated!
Thank you very much
Let's see at this line:
changeColor.color = e.currentTarget.text;
e.currentTarget is a circle. What is e.currentTarget.text? Circle doesn't have a text property. It has a child TextField. So, if you want to get text from TextField you must write:
e.currentTarget.getChildAt(1).text;
Circle have two children: Shape and TextField. So getChildAt(1) = TextField.
You can do it without TextField. See:
for (var i:int = 0; i < objects.length; i++)
{
objects[i].color = color[i];
objects[i].addEventListener(MouseEvent.MOUSE_DOWN, onColorMouseDown);
objects[i].addEventListener(MouseEvent.MOUSE_UP, onColorMouseUp);
}
Circle it's a MovieClip. The MC it's a dynamic class, that means that you can add any property to it. In our case, we add a color property.
Next:
changeColor.color = e.currentTarget.color;
Understand?
In your code I have found a bug:
var changeColor:ColorTransform = hit_object[hit_object.length - 1].transform.colorTransform;
If you stop dragging circle and circle doesn't hitTest any boxes the error appears:
TypeError: Error #1010: A term is undefined and has no properties.
To avoid this, add condition:
if (hit_object.length)
{
var changeColor:ColorTransform = hit_object[hit_object.length - 1].transform.colorTransform;
changeColor.color = e.currentTarget.color;
hit_object[hit_object.length - 1].transform.colorTransform = changeColor;
}

How to get index of a Bitmap Image from bitmapdata(from an Array)?

I am wondering if i have an Array that push content that is Bitmap, how do i get index of a specific image when clicked. I tried to use indexOf but no luck, my codes are below.
Thanks for your time!
Code:
//First Part is where i add the URLRequest and add the image into contentHolder then onto Stage
function loadImage():void {
for(var i:int = 5; i < somedata.length; i++){
if(somedata[i]){
var loader:Loader = new Loader();
loader.load(new URLRequest("http://www.rentaid.info/rent/"+somedata[i]));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
}
}
}
function onImageLoaded(e:Event):void {
loadedArray.push(e.target.content as Bitmap);
for(var i:int = 0; i < loadedArray.length; i++){
var currentY1:int = 200;
e.currentTarget.loader.content.height =200;
e.currentTarget.loader.content.y += currentY1;
currentY1 += e.currentTarget.loader.content.height +300;
_contentHolder.mouseChildren = false; // ignore children mouseEvents
_contentHolder.mouseEnabled = true; // enable mouse on the object - normally set to true by default
_contentHolder.useHandCursor = true; // add hand cursor on mouse over
_contentHolder.buttonMode = true;
_contentHolder.addChild(loadedArray[i]);
addChild(_contentHolder);
_contentHolder.addEventListener(MouseEvent.CLICK, gotoscene);
}
}
// then the part where i try to get the index
function gotoscene(e:MouseEvent):void {
var index:Number;
index = loadedArray.indexOf(e.target);
trace(index);
}
Edit:
var viewport:Viewport = new Viewport();
viewport.y = 0;
viewport.addChild(_contentHolder);
Your first question has very simple answer:
var image:Bitmap = new Bitmap();
var images:Array = new Array(image);
for (var i:uint = 0; i < images.length; i++) {
// images[i].bitmapData is the original image in your array
// image.bitmapData is searched one
if (images[i].bitmapData == image.bitmapData) {
// found
}
}
But your problem is bigger than this. I see you keep wandering around..
You should add listener to each child, not the content holder as one. I usually don't use Loaders, but get their Bitmaps and wrap them in Sprites or something, that I add into the scene. You should store either this Sprite or your Loader into that array, not the Bitmap. Then add listener to each of them (Sprite or Loader, not Bitmap) and get the target. Depending on what you've stored in the array, you can easily get it as:
function gotoscene(e:MouseEvent):void {
var index:uint = loadedArray(indexOf(e.target));
}
But it's important to store one specific type that will actually be clickable. Don't think about the Bitmap - it's only a graphic representation, and doesn't do much in the code.
**EDIT:
Okay I'm adding the code you need but it's important to understand what you are doing and not just rely on someone else's answer :)
function onImageLoaded(e:Event):void {
var bitmap:Bitmap = e.target.content as Bitmap; // get the Bitmap
var image:Sprite = new Sprite();
image.addChild(bitmap); // wrap it inside new Sprite
// add listener to Sprite!
image.addEventListener(MouseEvent.CLICK, gotoscene);
// gets url of current image (http://website.com/images/image1.jpg)
var url:String = e.target.loaderURL;
// get only the number from that url by replacing or by some other way
// this removes the first part and results in "1.jpg"
var name:String = url.replace("http://website.com/images/image", "");
// this removes the extension and results in number only - 1, 2, 3
// it's important to change this depending on your naming convention
name = name.replace(".jpg", "");
image.name = "button" + name; // results in "button1", "button2", "button3"
// store object, name, or whatever (not really needed in your case, but commonly used)
loadedArray.push(image.name);
image.x = counter * 100; // position so you can see them, at 100, 200, 300, etc.
_contentHolder.addChild(image); // add newly created Sprite to content
}
function gotoscene(e:MouseEvent):void {
var name:String = e.target.name;
// strips down "button" from "button1", and only the number remains,
// which is 1, 2, 3, etc. the number of the scene :)
var scene:uint = name.replace("button", "");
// you're the man now :)
}

Remove randomly generated sprites with Mouse.Event

I am making a game for my class where different chemical elements are generated as sprites at the top of the screen and then fall down. Different types are made and I want students to mouse over specific types depending on where they are in the game.
My question is how to write the function to remove them when they are correctly selected? I've tried a lot of different ways but am having a lot of trouble. An example of the code that I wrote to make each element is below and then I have a separate function to move down all of the sprites created.
var spriteArray:Array = new Array();
var halogenArray:Array = new Array("F", "Cl", "Br", "I");
var rndnum:Number = Math.random();
//Halogens
if (rndnum < 0.05)
{
var halo:Sprite = new Sprite();
halo.graphics.beginFill(0x00FF00, 1);
halo.graphics.drawCircle(7.5, 7.5, 15);
halo.graphics.endFill();
halo.addEventListener(MouseEvent.MOUSE_OVER, removeElement);
halo.x = Math.random()*500 + 50;
halo.y = -18;
var textField = new TextField();
textField.text = halogenArray[int(Math.random()*4)];
textField.width = 30;
textField.height = 30;
textField.x = (15 - textField.textWidth)/2; // center it horizontally
textField.y = (15 - textField.textHeight)/2; // center it vertically
halo.addChild(textField);
spriteArray.push(halo);
addChild(halo);
}
At what point are you struggling?
I am assuming it is in determining the types of the halogens.
In your remove function I assume you have the desired type already figured out, you would then compare it to
element.getChildAt(0).text
and you would get the element by either looping across every element in the spriteArray, or using the mouseEvent's target
My suggestion is to use a halogen Class to contain the grapics & textfield, and a vector to hold the objects. It would then be easier to get the type rather than searching the anonymous children of the sprite.
I believe you are looking for something like this:
//give your textfields a name, it isn't totally necessary as we can do getChildAt(0)
//but it's more readable, and if you decide to add more children before you
//add the text field, then this will still work
var textField = new TextField();
textField.text = halogenArray[int(Math.random()*4)];
textField.width = 30;
...
textField.name = "haloTx"; //for tracking later
//assuming you have some variable set to the correct answer
var correctAnswer:String = "F";
function removeElement( e:MouseEvent ):void {
var element:TextField = ( e.target as Sprite ).getChildByName( "haloTx" );
//if we have the correct element, remove from parent and list
if ( element && element.text == correctAnswer ) {
var index:int = spriteArray.indexOf( e.target as Sprite );
removeChild( spriteArray.splice( index, 1 )[0] );
}
}
Although #VBCPP is right, doing that in a separate class is definitely the best way organizationally. Which might look something like:
class ElementSprite extends Sprite {
public var textField:TextField;
//pass shapeArgs as string, so say a circle at x=7.5, y=7.5, and radius=15 -- shapeArgs = "7.5, 7.5, 15"
public function ElementSprite( element:String, drawShape:String="Circle", shapeArgs:String="7.5, 7.5, 15", fillColor:uint=0x00FF00 ) {
//set textfield properties etc. or textFormat
textField = new TextField();
textField.text = element;
addChild( textField );
//if you passed some arguments to draw our shape
if ( shapeArgs != "" ) {
graphics.beginFill( fillColor );
graphics[ "draw" + drawShape ].apply( this, shapeArgs.split( "," ) );
}
}
public function get currentElement():String { return textField.text }
}
Then you would use it like so in your if statement if (rndnum < 0.05):
var elementSprite:ElementSprite = new ElementSprite( "A" );
//elementSprite.x = set your x;
//elementSprite.y = set your y;
addChild(elementSprite);
That would be replacing all your current code in that if statement. This is all a working example, if you have an questions feel free to comment.

Remove sprite from stage in as3

I have this code for a message to appear on stage when player finishes drag and drop. I would like this sprite to be removed when a button is clicked for the next frame. Can someone help me with the code?
stage.addEventListener(Event.ENTER_FRAME, EntFrame);
function EntFrame (e:Event):void
{
if (CntP1+CntP2+CntP3+CntP4+CntP5+CntP6+CntP7+CntP8 == 40)
{
var w:int = 400, h:int = 200;
var win:Sprite = new Sprite();
win.name = "Mywin";
addChild(win);
// draw rounded rect with subtle vertical linear gradient fill and blue stroke
win.graphics.lineStyle(4,0x0077ff);
var mat:Matrix = new Matrix();
mat.createGradientBox(w, h, 90 * (Math.PI / 180));
win.graphics.beginGradientFill(GradientType.LINEAR,[0xffffff,0xeeeeee],[1.00,1.00],[0,255],mat);
win.graphics.drawRoundRect(0,0,w,h,15,15);
// show center "YOU WIN!" text
var tf:TextField = new TextField();
tf.autoSize = TextFieldAutoSize.LEFT;
tf.antiAliasType = AntiAliasType.ADVANCED;
tf.defaultTextFormat = new TextFormat("Arial, Verdana",36,0x454545,true);
tf.text = "Κέρδισες!";
tf.selectable = false;
win.addChild(tf);
tf.x = w/2 - tf.width/2;
tf.y = h/2 - tf.height/2;
// add a drop shadow
var dropShadow:DropShadowFilter = new DropShadowFilter(3,45,0,.35,8,8,1,3);
win.filters = [dropShadow];
// center the graphic
win.x = stage.stageWidth/2 - win.width/2;
win.y = stage.stageHeight/2 - win.height/2;
}
}
Your code isn't written well and needs rewriting to ensure reuse or scalability of your project, but here's a quick way out.
make a holder Sprite, something like
var messageHolder:Sprite = new Sprite();
addChild(messageHolder);
add all the messages to that holder in any fashion you like. When you need to erase the contents of that holder, call following method:
function clearHolderContents(holder:DisplayObjectContainer):void
{
if (holder.numChildren < 1)
return; // no need to continue this method if the target is empty
for (var i:int = holder.numChildren - 1; i >= 0; i--)
removeChild(holder.getChildAt(i));
}
This method can clear contents of any DisplayObjectContainer => use it for your messageHolder:
clearHolderContents(messageHolder);
Hope that helps!

as3 getting object coordinates

Hello everyone so i have a piece of code witch creates some circles, and after i move them with another function i want to get their center coordinates so i can draw lines from center to center of circles, but i don`t have any idea how to do it ... if you can suggest me 1 , here is the code witch creates the circle :
function new_sond(event:MouseEvent):void
{
if (i<9)
{
i++;
q=i;
var btn:Sprite = new Sprite();
btn.graphics.beginFill(0x0099FF, 1);
btn.graphics.drawCircle(400, 300, 15);
btn.graphics.endFill();
var s:String = String(q);
btn.name=s;
var textField = new TextField();
textField.mouseEnabled=false;
textField.text = i;
textField.width = 10;
textField.height = 17;
textField.x = 395; // center it horizontally
textField.y = 292; // center it vertically
btn.addChild(textField);
this.addChild(btn);
}
}
the code with is mooving them is :
this.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownH);
this.addEventListener(MouseEvent.MOUSE_UP, mouseUpH);
function mouseDownH(evt:MouseEvent):void {
var object = evt.target;
object.startDrag();
}
function mouseUpH(evt:MouseEvent):void {
var obj = evt.target;
obj.stopDrag();
}
And the code where i draw the lines between them :
function click1(e:MouseEvent):void{
e.currentTarget.removeEventListener(MouseEvent.CLICK, click1);
var i:int;
i=1;
if (e.target.name!=null){
trace(e.target.name);
sx=mouseX;
sy=mouseY;
stage.addEventListener(MouseEvent.CLICK,click2);
}
}
function click2(e:MouseEvent):void{
e.currentTarget.removeEventListener(MouseEvent.CLICK, click2);
fx=mouseX;
fy=mouseY;
var i:int;
i=2;
trace(e.target.name);
var line:Shape = new Shape();
line.graphics.lineStyle(1,0x0066FF,1);
line.graphics.moveTo(sx,sy);
line.graphics.lineTo(fx,fy);
this.addChild(line);
var inputField:TextField = new TextField();
inputField.border = true;
inputField.type = TextFieldType.INPUT;
str=inputField.text;
trace(str);
inputField.width = 23;
inputField.height = 18;
inputField.x = (sx+fx)/2;
inputField.y = (sy+fy)/2;
addChild(inputField);
}
The thing is i want to draw the line from center to center, but i get the mouseX and mouseY coordinates to draw, because i don`t know how to take the center coordinates of an object.... what i get is : http://gyazo.com/6003630d549209ec5e16ccfffe0ee689
But i want the lines to be drawn from center, if someone has any suggestions please help
Sorry for the long post, i just don`t know where i need to put the piece with will center them so i wanted to give the hole code where it can be placed.... I will appreciate very much any idea .
Well, if you drew the circle at 0,0 and moved the btn object .x and .y to 400,300 like this:
btn.graphics.drawCircle(0,0,15);
btn.x = 400;
btn.y = 300;
Then as you drag btn around the screen, btn.x , btn.x (or in the click handler, e.target.x and e.target.y) would always be the center of the circle.
Alternately, if you can't or don't want to do it that way, you can get the bounds of btn (with respect to this coordinate system, since that's where line is being drawn), and since it's a circle, then center of the bounds will be the center of the circle:
var btn:Sprite = e.target;
var bounds:Rectangle = btn.getBounds(this);
var center_x:Number = bounds.x + bounds.width/2;
var center_y:Number = bounds.y + bounds.height/2;