Change Alpha on Rollover; Not Changing Back on Mouse Out? - actionscript-3

So I have a Tile class, with a sprite variable that holds the graphic for the tile. On mouse over, I ColorTransform the graphic. Seems to work fine. On mouse out, I try to change it back. Nada. And in fact, rolling over the same tile twice will increase the alpha until eventually it fades totally. Not sure how to fix it. Here's my code.
In the Tile class:
this.addEventListener(MouseEvent.MOUSE_OVER, thisMouseOver);
this.addEventListener(MouseEvent.MOUSE_OUT, thisMouseOut );
public function thisMouseOver( e:Event ):void {
tileGraphic.bitmapData = setAlpha(tileGraphic.bitmapData);
}
public function thisMouseOut( e:Event ):void {
tileGraphic.bitmapData = resetAlpha(tileGraphic.bitmapData);
}
private function setAlpha( bmd:BitmapData ):BitmapData {
var rec:Rectangle = new Rectangle( 0, 0, bmd.width, bmd.height );
var ct:ColorTransform = new ColorTransform();
ct.alphaMultiplier = .65;
bmd.colorTransform( rec, ct );
return bmd;
} //end function setAlpha
private function resetAlpha( bmd:BitmapData ):BitmapData {
var rec:Rectangle = new Rectangle( 0, 0, bmd.width, bmd.height );
var ct:ColorTransform = new ColorTransform();
ct.alphaMultiplier = 1;
bmd.colorTransform( rec, ct );
return bmd;
} //end function resetAlpha
Can anyone point me in the right direction? Thanks!

Replace the resetAlpha with
private function resetAlpha( bmd:BitmapData ):BitmapData {
var rec:Rectangle = new Rectangle( 0, 0, bmd.width, bmd.height );
var ct:ColorTransform = new ColorTransform();
ct.alphaOffset = 255
bmd.colorTransform( rec, ct );
return bmd;
} //end function resetAlpha

You should better change alpha of the container instead of playing with the BitmapData pixels. For example, in your case if your tile bitmap will initially have transparent pixels (fill it with 0x00ff0000 prior to drawing a thing and check if so), they will become opaque with codingbuddha's answer. So, change the listeners to the following:
public function thisMouseOver( e:Event ):void {
tileGraphic.alpha=0.65;
}
public function thisMouseOut( e:Event ):void {
tileGraphic.alpha=1;
}

Related

As3 hittesting doesn't really work (nested)

I got a tank.
I got a hero (controllable character).
The tank has a nested movieclip which has a very thin surface area.
Yet, the thing detects a collision when it's not even touching the hero.
public class tank_sight extends MovieClip
{
private var _root:MovieClip;
public function tank_sight()
{
addEventListener(Event.ADDED, beginClass);
}
private function beginClass(event:Event):void
{
_root = MovieClip(root);
addEventListener(Event.ENTER_FRAME, loop);
}
private function loop(event:Event):void
{
if(this.hitTestObject(_root.hero.hitbox))
{
this.gotoAndStop(2);
trace("HIT");
fire();
}
else
{
this.gotoAndStop(1);
}
}
private function fire():void
{
var shell:Shell = new Shell(x, y, rotation - 180);
_root.addChild(shell);
}
}
What's wrong? I don't get it.
EDIT: Sight is rotating, so that's probably why. I tried using this code on the player class:
point = _root.tanks.barrel.sight.localToGlobal(new Point());
if(this.hitTestPoint(point.x, point.y, false))
{
trace("HIT");
}
But it doesn't work.. It never traces "HIT", unless I stand in some weird location at certain times.
hitTestObject works with nested objects also (display objects that have different parents), you should check logic of your game, and do some tests.
Simple example:
var squareHolder:Sprite = new Sprite();
var squareInner:Shape = new Shape();
var hitHolder:Sprite = new Sprite();
var hitCircle:Shape = new Shape();
hitCircle.graphics.beginFill(0x990000);
hitCircle.graphics.drawCircle(0, 0, 20);
squareInner.graphics.beginFill(0x009900);
squareInner.graphics.drawRect(0, 0, 40, 40);
addChild(squareHolder);
squareHolder.addChild(squareInner);
squareHolder.x = 200;
squareHolder.y = 100;
squareInner.x = 50;
squareInner.y = 50;
stage.addChild(hitHolder);
hitHolder.addChild(hitCircle);
hitCircle.transform.matrix = new Matrix(1, 0.5, 0.5, 1, 30, 30);
stage.addEventListener(MouseEvent.MOUSE_MOVE, function (e:MouseEvent):void {
hitHolder.x = e.stageX;
hitHolder.y = e.stageY;
if (hitCircle.hitTestObject(squareInner)) {
trace("Ding!");
}
});
Whatever you do with hitCircle (visible=false, trasparent fill, transformations) it will still work.

as3 draw line with LineStyle and then edit with transparent (invisible) pixels

I have MC with external loaded image (jpg).
Next layer is masked Sprite where I am drawing lines in different colors, opacity ,etc with graphics.lineStyle . Everything works fine, so I can see image and drawings over. Now I want eraser to make, and trying to make some kind of (transparent) line which will "erase" exising line.
If I for example draw (with mouse) red line, and then switch color to yellow and intersect on some point with previous line, it is ok, I see yellow color. Now I don't have idea how to make "transparent" color? So when mouse move over existing drawing, just see again part of background image. If I set one color background everything is OK, but I have image, end eraser leaves some color, and I need to be transparent. Tried blend modes, cached as bmp, everything I found but still no solution.
Seemingly you use Graphics objects that overlay the image. In order to erase something, you should give your sprite a topmost shape that will have BlendMode.ERASE as blend mode, and draw on it with alpha component of color being 0xFF. The sprite should have its blendMode to be BlendMode.LAYER. Here's a test to play with:
public class TestErase extends Sprite
{
public function TestErase() {
var b:Sprite = new Sprite();
var c:Shape = new Shape();
b.blendMode = BlendMode.LAYER;
c.blendMode = flash.display.BlendMode.ERASE;
c.graphics.beginFill(0, 1);
c.graphics.drawRect(50, 50, 50, 50);
c.graphics.endFill();
b.graphics.beginFill(0xff0000, 1);
b.graphics.drawRect(0, 0, 150, 150);
b.graphics.endFill();
b.addChild(c);
addChild(b);
this.graphics.beginFill(0x00c000, 1);
graphics.drawRect(75, 75, 100, 100);
graphics.endFill();
}
}
This makes a 50x50 hole, defined by "c" sprite in "b" sprite, that does not affect "this" sprite.
Okay you asked for an example. Here.
public class Main extends Sprite
{
public var sh:Shape;
public var drawing:Boolean;
public var sp:Sprite;
public var bd:BitmapData;
public var erasing:Boolean;
[Embed(source = '../lib/093.jpg')]
public static const Background:Class;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
var ba:Bitmap = new Background();
ba.scaleX = 0.5;
ba.scaleY = 0.5;
addChild(ba);
bd = new BitmapData(640, 400, true, 0);
var bm:Bitmap = new Bitmap(bd);
sp = new Sprite();
sp.addChild(bm);
sp.blendMode = BlendMode.LAYER;
var tf:TextField = new TextField();
tf.y = 401;
tf.background = true;
tf.backgroundColor = 0x0;
tf.defaultTextFormat = new TextFormat('Arial', 12, 0xe00000, true, false, false);
tf.selectable = false;
tf.text = 'Erase';
addChild(tf);
addChild(sp);
tf.addEventListener(MouseEvent.CLICK, toggleErasing);
sp.addEventListener(MouseEvent.MOUSE_DOWN, startDrawing);
sp.addEventListener(MouseEvent.ROLL_OUT, endDrawing);
sp.addEventListener(MouseEvent.MOUSE_UP, endDrawing);
}
private function toggleErasing(e:MouseEvent):void {
erasing = !erasing;
if (erasing) (e.currentTarget as TextField).text = 'Erasing...'; else (e.currentTarget as TextField).text = 'Erase';
e.stopPropagation();
}
private function startDrawing(e:MouseEvent):void {
if (drawing) return;
sh = new Shape();
sh.graphics.lineStyle(3, Math.floor(Math.random() * 0x100000), 1,true);
if (erasing) sh.blendMode = BlendMode.ERASE;
sh.graphics.moveTo(e.localX, e.localY);
addEventListener(MouseEvent.MOUSE_MOVE, trackMouse);
sp.addChild(sh);
drawing = true;
}
private function endDrawing(e:MouseEvent):void {
if (!drawing) return;
removeEventListener(MouseEvent.MOUSE_MOVE, trackMouse);
if (erasing) bd.draw(sh, null, null, BlendMode.ERASE);
else bd.draw(sh);
sp.removeChild(sh);
sh = null;
drawing = false;
}
private function trackMouse(e:MouseEvent):void {
sh.graphics.lineTo(e.localX, e.localY);
}
}
Tested by me, and should work as is, just change the background :)

Actionscript 3, flash: Erasing area dynamically?

long story short, I made image for it.
I am beginner in actionscripting, found out that only animating is not enough.
What I try to accomplish:
You can use a simple mask to achieve this. Here's a working example (using LEFT mouse button, though. I don't think RIGHT one would be suitable for this):
package examples
{
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.MouseEvent;
import flash.ui.Mouse;
public class MaskTest extends Example
{
private var _toBeErased:Sprite;
private var _discoverable:Sprite;
private var _holesContainer:Sprite;
private var _mouseIsPressed:Boolean = false;
public function MaskTest()
{
}
// Call this method once this Class instance has been added to stage
public function init():void
{
// Create sprites
_toBeErased = new Sprite();
addChild( _toBeErased );
_discoverable = new Sprite();
addChild( _discoverable );
_holesContainer = new Sprite();
addChild( _holesContainer );
// Draw sprites
_toBeErased.graphics.beginFill( 0xFFFF00 );
_toBeErased.graphics.drawRect( 0, 0, 900, 600 );
_toBeErased.graphics.endFill();
_discoverable.graphics.beginFill( 0xFFAAAA );
_discoverable.graphics.drawRect( 0, 0, 900, 600 );
_discoverable.graphics.endFill();
// Set mask
_discoverable.mask = _holesContainer;
// Add mouse listeners
stage.addEventListener( MouseEvent.MOUSE_MOVE, onMouseMove );
stage.addEventListener( MouseEvent.MOUSE_DOWN, onMouseDown );
stage.addEventListener( MouseEvent.MOUSE_UP, onMouseUp );
}
// Mouse listeners callbacks...
private function onMouseDown( e:MouseEvent ):void{
_mouseIsPressed = true;
}
private function onMouseUp( e:MouseEvent ):void{
_mouseIsPressed = false;
}
private function onMouseMove( e:MouseEvent ):void
{
if( !_mouseIsPressed )
return;
// Get a random size for circle
var radius:Number = 5 + (Math.random()*10-5);
// Create new circle and paint it
var circle:Sprite = new Sprite();
circle.graphics.beginFill( 0x000000 );
circle.graphics.drawCircle( 0, 0, radius );
circle.graphics.endFill();
// Move it randomly, just a bit
circle.x = _holesContainer.mouseX + (Math.random()*20-10);
circle.y = _holesContainer.mouseY + (Math.random()*20-10);
_holesContainer.addChild( circle );
}
}
}
Check out http://f6design.com/journal/2009/05/24/erase-an-image-using-your-mouse-in-as3/
Basically, you have to make use of the erase Blend Mode: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/BlendMode.html

AS3 Tweening a tint change

I have this movieclip loaded on runtime called cHolder. I apply a tint at first, and when it is mouseOver there will be no tint. How do i apply a tween to make the change in tint appear more gradually? THanks!
var imageLoader = new Loader();
imageLoader.load(new URLRequest(projectDP));
var origColor: Color = new Color();
origColor.setTint( 0x000000, 0.8 );
cv.cHolder.transform.colorTransform = origColor;
cv.cHolder.addChild(imageLoader);
this.addChild(cv);
cv.cHolder.addEventListener(MouseEvent.MOUSE_OVER, onRoll);
cv.cHolder.addEventListener(MouseEvent.MOUSE_OUT, onOut);
function onRoll(e:Event):void
{
origColor.setTint( 0, 0 );
e.currentTarget.transform.colorTransform = origColor;
}
function onOut(e:Event):void
{
origColor.setTint( 0x000000, 0.8 );
e.currentTarget.transform.colorTransform = origColor;
}
I recommend using a tween engine. You can use flash Tween, but I prefer to work with any of the many available engines out there, such as TweenMax.
to tween a tint you would do something like this:
import com.greensock.*;
import com.greensock.plugins.*;
TweenPlugin.activate([TintPlugin]);
var color:uint = 0x0;
var imageLoader = new Loader();
imageLoader.load(new URLRequest(projectDP));
var origColor: Color = new Color();
origColor.setTint( 0x000000, 0.8 );
cv.cHolder.transform.colorTransform = origColor;
cv.cHolder.addChild(imageLoader);
this.addChild(cv);
cv.cHolder.addEventListener(MouseEvent.MOUSE_OVER, onRoll);
cv.cHolder.addEventListener(MouseEvent.MOUSE_OUT, onOut);
function onRoll(e:Event):void
{
//origColor.setTint( 0, 0 );
//e.currentTarget.transform.colorTransform = origColor;
TweenLite.to(e.currentTarget, 1, {tint:null});
}
function onOut(e:Event):void
{
//origColor.setTint( 0x000000, 0.8 );
//e.currentTarget.transform.colorTransform = origColor;
TweenLite.to(e.currentTarget, 1, {tint:0x000000});
}

Drawing point in flash

I try to draw some points by coding. But the 1px width point seems has feature at the edge.
Even I try to draw some position ten times.
This is my code:
private function createPoint(radio:Number, rep:int):Shape{
var s:Shape = new Shape();
var i:int = rep;
while( i-- > 0 ){
s.graphics.beginFill(0, 1);
s.graphics.drawRect(0,0, radio, radio);
s.graphics.endFill();
}
return s;
}
private function drawPoint():void
{
this.addChild( createPoint(10) );
}
// param must be >= 1
private function createPoint(radio:uint):Shape
{
var s:Shape = new Shape();
s.graphics.beginFill(0x00ff00, 1);
s.graphics.drawRect(0,0, radio, radio);
s.graphics.endFill();
return s;
}
Will certainly work. You may not of been adding the returned shape into the display list.