I've come across an undesirable effect of using JointStyle.MITER when clearing/redrawing graphics.
My project involves managing custom line graphics with both round and sharp edges, which is why I would like to use a miter joint style.
When the line thickness is greatly increased, even the round areas of the line are affected by the miter style. While I find this unfortunate, it's understandable and not the bug I'm referring to. the bug(?) occurs when decreasing the line thickness doesn't completely clear the graphics, as instructed to do so by the code each time the thickness changes, leaving artifacts of the line graphics where the line once was. Artifacts are also left by sharp edges, not just rounded corners.
I'm using Flash Player version 10.1.53.64 on Mac OS X Snow Leopard (10.6.4).
You can test this by running my sample code below. use the left and right keyboard arrows change the thickness of the stroke of a round rect.
Update: The graphics artifacts are superficial. Dragging the shape over their location after they appear will remove them. Code updated with dragging functionality.
package
{
import flash.display.CapsStyle;
import flash.display.JointStyle;
import flash.display.LineScaleMode;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.ui.Keyboard;
public class StrokeWidth extends Sprite
{
private var roundRect:Sprite = new Sprite();
private var strokeThickness:Number = 6;
public function StrokeWidth()
{
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(evt:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownEventListener);
roundRect.addEventListener(MouseEvent.MOUSE_DOWN, mouseEventListener);
roundRect.addEventListener(MouseEvent.MOUSE_UP, mouseEventListener);
drawRoundRect();
roundRect.x = roundRect.y = 100;
addChild(roundRect);
}
private function drawRoundRect():void
{
roundRect.graphics.clear();
roundRect.graphics.lineStyle(strokeThickness, 0x000000, 1.0, true, LineScaleMode.NONE, CapsStyle.NONE, JointStyle.MITER);
roundRect.graphics.beginFill(0xFF0000);
roundRect.graphics.drawRoundRect(0, 0, 400, 200, 100);
}
private function mouseEventListener(evt:MouseEvent):void
{
switch (evt.type)
{
case MouseEvent.MOUSE_DOWN: roundRect.startDrag(); break;
case MouseEvent.MOUSE_UP: roundRect.stopDrag();
}
}
private function keyDownEventListener(evt:KeyboardEvent):void
{
switch (evt.keyCode)
{
case Keyboard.LEFT: strokeThickness -= 1; break;
case Keyboard.RIGHT: strokeThickness += 1;
}
drawRoundRect();
}
}
}
interesting. the problem was caused because the lineStyle's scale mode was set to none:
LineScaleMode.NONE
changing it to normal fixes the problem:
LineScaleMode.NORMAL
what about re-creating the shape?
Related
This may be a long shot, but hopefully someone can help me with this.
I'm running Windows 10 64-bit on a Dell Inspiron laptop with a 10-touch-point touchscreen. I can get touch events to fire but they're not working the way I'd like in all cases.
A little preliminary info first. On a touchscreen Windows 10 PC, try touching and holding on the background. A transparent white square should tween from small to large, indicating that a right-click will occur if you release that touch. Instead of releasing, add a second touch somewhere else. The square should tween from large to small and disappear. This is normal behavior, and should happen anywhere that has right-click functionality.
Now open Google Chrome (I just updated to the new version 58 but I presume any version will do). Follow the steps from before and watch the square disappear. Now, while still holding a finger down, touch again somewhere else, and keep tapping. Notice the square tweening out over and over again in the same spot despite already having disappeared. If you release your original touch it remembers the point where that touch was released and continues to tween out the square in that spot. In Chrome you can use a two-finger tap to bring up the right-click menu, and I suspect this problem occurs anywhere that has two-finger tap right-click functionality. I suspect this is a Windows bug rather than a Chrome bug.
When I test my program in FlashDevelop this same problem occurs. The program responds pretty quickly when it's just one touch, but the events can lag considerably when there are multiple touches. I've tested in four environments with the following results:
FlashDevelop: White square bug and lag
Standalone Flash Player (projector): White square bug and no lag
Google Chrome: No touch events firing at all
Internet Explorer: No white square bug and no lag
So the ideal behavior seems to be what's happening in Internet Explorer, and I'd like that to happen everywhere. I'd like to know if there's a way to suppress the two-finger touch functionality or if there's some other way to fix this (I've already tried intercepting MouseEvent.RIGHT_CLICK events and it didn't work). Here's my code:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TouchEvent;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
/**
* ...
* #author Kyle Delaney
*/
[Frame(factoryClass="Preloader")]
public class Main extends Sprite
{
private static var _output_txt:TextField = new TextField();
public function Main()
{
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
graphics.beginFill(0);
graphics.drawRect( -5, -5, stage.stageWidth + 5, stage.stageHeight + 5);
var tf:TextFormat = new TextFormat();
tf.font = "Courier New";
tf.size = "14";
_output_txt.defaultTextFormat = tf;
_output_txt.wordWrap = true;
_output_txt.width = stage.stageWidth /2;
_output_txt.height = stage.stageHeight;
_output_txt.selectable = false;
_output_txt.mouseEnabled = false;
_output_txt.background = true;
_output_txt.alpha = 0.5;
addChild(_output_txt);
print("init()");
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
addEventListener(TouchEvent.TOUCH_BEGIN, touchBegin);
addEventListener(TouchEvent.TOUCH_END, touchEnd);
//addEventListener(TouchEvent.TOUCH_MOVE, touchMove);
addEventListener(TouchEvent.TOUCH_TAP, touchTap);
}
private function touchTap(e:TouchEvent):void
{
print("touchTap() " + e.touchPointID);
}
private function touchMove(e:TouchEvent):void
{
print("touchMove() " + e.touchPointID);
}
private function touchEnd(e:TouchEvent):void
{
print("touchEnd() " + e.touchPointID);
}
private function touchBegin(e:TouchEvent):void
{
print("touchBegin() " + e.touchPointID);
}
private function mouseDown(e:MouseEvent):void
{
print("mouseDown");
}
public static function print(str:String):void
{
if (_output_txt)
{
_output_txt.appendText(str + '\n');
if (_output_txt.length > 10000) _output_txt.replaceText(0, 5000, "");
_output_txt.scrollV = _output_txt.maxScrollV;
}
}
}
}
And here's an upload of the swf: http://www.newgrounds.com/dump/item/8eb8b87e551f48db7e0e50c66d3178ff
I have created a MOUSE_MOVE MouseEvent and a code to draw circles while I move the mouse cursor. The problem is, it doesn't draw out every single circle if I move the mouse too fast.
Here are the codes I have for the MOUSE_MOVE event.
stage.addEventListener(MouseEvent.MOUSE_MOVE, mCursor);
public function mCursor(e:MouseEvent):void
{
var cursor:Shape = new Shape();
cursor.graphics.beginFill(1, 1);
cursor.graphics.drawCircle(e.stageX, e.stageY, 10);
cursor.graphics.endFill();
addChild(cursor);
}
Would there be an arithmetic equation or physics formula to have it add every single circle such that it can draw a straight line without the blanks in between?
Just use
cursor.graphics.lineTo(…);
To draw a continuous line between points instead of adding discrete individual circles.
I erased the above codes and just added this one line of code cursor.graphics.lineTo(e.localX, e.localY); I tested it and there were blanks in between
You have to set the line width first by calling lineStyle() method of the graphics object. Otherwise the line width is zero (its default value).
Here's a full working document class:
package
{
import flash.display.Sprite;
import flash.display.Shape;
import flash.events.MouseEvent;
public class Main extends Sprite
{
private var cursor:Shape;
public function Main()
{
cursor = new Shape();
cursor.graphics.lineStyle(2);
addChild(cursor);
stage.addEventListener(MouseEvent.MOUSE_MOVE, mCursor);
}
private function mCursor(e:MouseEvent):void
{
cursor.graphics.lineTo(e.stageX, e.stageY);
}
}
}
You likely have to fiddle around with moveTo in order to set an appropriate starting position. As the code is now, it starts at 0/0.
I'm making a maze-game. I have two objects that need to react to a hittest, my little circle (called "brikke") and the maze itself (called "form"). (I'm Norwegian)
I drew a part of the maze in flash (as one big object, connected) and converted it in to a symbol (movieclip), as for the circle.
My problem is that when I'm doing the hittest, the circle seems to react to the invisible parts of the maze, like a PNG. It reacts to the invisible "pixels" in my drawing of the maze, even tho I drew it inside flash, its not a png. But the shape of the maze is rectangular.
I also use the keypads to control the circle around the maze.
Any ideas on how I can make this work? Make the circle hittest with the shape of the maze, and only that, using the keypads to navigate the circle.
So when the circle hits the maze "walls" it will bounce back to the start again.
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.ui.Keyboard;
import flash.events.KeyboardEvent;
public class Dokument extends MovieClip {
var startskjerm: Startskjerm=new Startskjerm();
var startknapp: Startknapp=new Startknapp();
var bakgrunnbane: Bakgrunnbane=new Bakgrunnbane();
var brikke: Brikke=new Brikke();
var bane: Bane=new Bane();
var form: Form=new Form();
var regler: Regler=new Regler();
var spilleregler: Spilleregler=new Spilleregler();
var tilbake: Tilbake=new Tilbake();
public function Dokument() {
addChild(startskjerm);
addChild(startknapp);
addChild(regler);
startknapp.x= 1020;
startknapp.y= 350;
regler.x= 920;
regler.y= 450;
startknapp.addEventListener(MouseEvent.CLICK, trykket);
regler.addEventListener(MouseEvent.CLICK, klikket);
stage.addEventListener(KeyboardEvent.KEY_DOWN, tastetrykk);
}
public function trykket (evt:MouseEvent) {
removeChild(startknapp);
removeChild(startskjerm);
addChild(bakgrunnbane);
addChild(bane);
addChild(form);
addChild(brikke);
brikke.x= 200;
brikke.y= 95;
bane.x= 630;
bane.y= 485;
form.x= 628;
form.y= 449;
}
public function klikket (evt:MouseEvent) {
removeChild(regler);
removeChild(startskjerm);
addChild(spilleregler);
addChild(tilbake);
tilbake.x= 1100;
tilbake.y= 850;
tilbake.addEventListener(MouseEvent.CLICK, tilbakeklikk);
}
public function tilbakeklikk (evt:MouseEvent) {
removeChild(spilleregler);
removeChild(tilbake);
addChild(startskjerm);
addChild(startknapp);
addChild(regler);
tilbake.x= 1100;
tilbake.y= 850;
startknapp.x= 1020;
startknapp.y= 350;
regler.x= 920;
regler.y= 450;
tilbake.addEventListener(MouseEvent.CLICK, tilbakeklikk);
}
public function tastetrykk(evt:KeyboardEvent) {
if(evt.keyCode==Keyboard.LEFT){
brikke.x= brikke.x-8;
}
if(evt.keyCode==Keyboard.RIGHT){
brikke.x= brikke.x+8;
}
if(evt.keyCode==Keyboard.UP){
brikke.y= brikke.y-8;
}
if(evt.keyCode==Keyboard.DOWN){
brikke.y= brikke.y+8;
}
if(brikke.hitTestObject(form)== true) {
trace('truffet');
}
}
}
}
Try to use hitTestPoint instead of hitTestObject.
If your 'brikke' is bigger shape you can create more points in it and then check hitTestPoint for each point. Remeber to use localToGlobal or globalToLocal to be shure that you work in the same coordinates.
Essentially, I'm making a game in Flash CS6 where a light source is projected onto the screen. You get a mirror that you can drag around. When the mirror touches the light, however, it should bounce off it and end up 90 degrees offset after it hit the mirror.
I don't have enough reputation to post pictures, but here's a link to an explanation of the problem: http://raphaelhennessy.com/misc/explanation.png
If you can help me solve this I would be really happy.
Thanks in advance,
-Raph
This is an extremely quick and dirty example to get the ball rolling. There are many issues with this code, so I suggest you use it only as a jumping off point. Details are commented within the code.
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class MirrorTest extends Sprite
{
private var _mirror:Sprite;
private var _line:Sprite;
public function MirrorTest()
{
super();
// create the line clip
_line = addChild(new Sprite()) as Sprite;
_line.graphics.clear();
_line.graphics.lineStyle(3, 0xFF0000);
_line.graphics.moveTo(0, 0);
_line.graphics.lineTo(500, 0); // starting it off at an arbitrary width
_line.y = 100; // positioning line so that we can see when it bends upwards
// create the mirror clip
_mirror = addChild(new Sprite()) as Sprite;
// draw a square and rotate it so we have a diamond shape
_mirror.graphics.beginFill(0);
_mirror.graphics.drawRect(-20, -20, 40, 40);
_mirror.graphics.endFill();
_mirror.rotation = 45;
_mirror.x = _mirror.y = 200; // position the mirror away from the line
// add even listeners to trigger dragging/dropping
_mirror.addEventListener(MouseEvent.MOUSE_DOWN, dragMirror);
_mirror.addEventListener(MouseEvent.MOUSE_UP, dropMirror);
}
private function dragMirror($event:MouseEvent):void
{
// start dragging the mirror.
_mirror.startDrag(true);
// add the ENTER_FRAME listener so that we can check for colision as the mirror is being moved around
addEventListener(Event.ENTER_FRAME, onTick);
}
private function dropMirror($event:MouseEvent):void
{
// stop dragging the mirror
_mirror.stopDrag();
// remove the ENTER_FRAME listener so we don't waste cycles checking for collision when the mirror is not being moved around
removeEventListener(Event.ENTER_FRAME, onTick);
}
private function onTick($event:Event):void
{
// check to see if the mirror has collided with the line
if (_mirror.hitTestObject(_line))
{
// if so, redraw the line as a right-angle, using the mirror's position as the "collision point"
_line.graphics.clear();
_line.graphics.lineStyle(3, 0xFF0000);
_line.graphics.moveTo(0, 0);
_line.graphics.lineTo(_mirror.x - _mirror.width * .5, 0);
_line.graphics.lineTo(_mirror.x - _mirror.width * .5, -100);
}
else
{
// if not, redraw the original line
_line.graphics.clear();
_line.graphics.lineStyle(3, 0xFF0000);
_line.graphics.moveTo(0, 0);
_line.graphics.lineTo(500, 0);
}
}
}
}
Here's a very simple AS3 project consisting of one class which draws a rectangle. When I run it, the rectangle is clearly larger than 100x100 pixels. After pulling out my hair for a few hours I thought I'd ask: why?
Edit: I know that it isn't correct because, though I have my screen resolution set to 1280x800, if I set the width to 500 it takes up almost all of my screen.
package
{
import flash.display.Sprite;
import flash.events.Event;
public class Draw extends Sprite
{
private var screen:Sprite;
public function Draw():void
{
this.addEventListener(Event.ADDED_TO_STAGE, stageHandler);
}
private function stageHandler(e:Event):void{
screen = new Sprite();
screen.graphics.clear();
screen.graphics.beginFill(0x333333,.9);
screen.graphics.drawRect(0,0,100, 100);
screen.graphics.endFill();
addChild(screen);
trace(stage.width + "," + stage.height);
}
}
}
:
Somehow your scalemode settigns for your flash player are set in a strange mode from FlashBuilder.
Try setting
stage.scaleMode = StageScaleMode.NO_SCALE;
in your stageHandler function. You code has no errors. The problem is in your publish preview settings somewhere.