When doing hittest, circle reacts to invisible part of maze - actionscript-3

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.

Related

Cursor movement too fast for code to read

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.

ActionScript classes reference

I have a class Square and a class Circle.
This my class Circle:
public class Circle extends MovieClip
{
var growthRate:Number = 2;
public function Circle()
{
addEventListener(Event.ENTER_FRAME, grow);
}
function grow(e :Event):void
{
e.target.width +=growthRate;
e.target.height +=growthRate;
}
}
I need to stop growing the circle inside a function from Shape.
public function Square() {
buttonMode = true;
addEventListener(MouseEvent.MOUSE_DOWN, down);
}
protected function down ( event: MouseEvent):void
{
//here i need to stop the circle
}
I don't know how to make a relation with the Circle class in order to stop the circle growing.
Thank you in advance.
I don't know how to make a relation with the Circle class in order to stop the circle growing.
That's because you cannot with the code you have right now. There's nothing in your class that's accessible from outside (public), that stops the growth. But there's not even something private in your class that does this. The functionality simply is not there.
So first of all, create the desired functionality. and make it available to public.
Here's how your Circle class could look like:
public class Circle extends Sprite
{
private var growthRate:Number = 2;
public function Circle()
{
// nothing here
// this is just to create a circle graphic, if you have artwork in your library symbol, you do not need this
graphics.beginFill(0xffffff * Math.random());
graphics.drawCircle(0, 0, 10 + 30 * Math.random());
graphics.endFill();
}
public function startGrowing(rate:Number = 0):void
{
if(rate != 0)
{
growthRate = rate;
}
addEventListener(Event.ENTER_FRAME, grow);
}
public function stopGrowing():void
{
removeEventListener(Event.ENTER_FRAME, grow);
}
private function grow(e:Event):void
{
width += growthRate;
height += growthRate;
}
}
Pay attention to
the constructor: I create a circle graphic there with code. As the comment says, if Circle is a class associated to a library symbol, you do not need this, because you already created the artwork in the symbol.
the super class: It's Sprite. This should be your default superclass. The only real reason to use MovieClip is if you have a timeline animation. It doesn't look like you have any of that from what you posted, so I recommend Sprite.
the two new public methods: startGrowing and stopGrowing, which do exactly what their names imply. startGrowing has an optional parameter to to start growing at a different growth rate.
the lack of e.target: which is unnecessary here.
A simple demo of that code looks like this:
var circle:Circle = new Circle();
circle.x = 200;
circle.y = 200;
addChild(circle);
circle.startGrowing();
//circle.startGrowing(1); // grow slowly
//circle.startGrowing(5); // grow fast
To stop the growth, stop listening for the ENTER_FRAME Event.
So far so good, now to your actual question:
how to make a relation with the Circle class
protected function down ( event: MouseEvent):void
{
//here i need to stop the circle
}
You think that you should make this connection in your Square class, but you are wrong about that. It's very bad practice to connect two classes this way. You want the classes to be as individual as possible.
Think about it like phones. Does your phone have a direct way to a specific other phone? No. It has the ability to connect to any phone, which makes it a lot more universally useful than a phone hard wired to another phone.
You make the connection outside both classes with events. That's like your phone making a call to the network with a number it wants to call. The network then figures out how to find the other phone with that number and how to establish the connection.
As a short interlude and so that we are on the same page about it, here's the Square class that I'm using:
public class Square extends Sprite
{
public function Square()
{
// nothing here
// this is just to create a circle graphic, if you have artwork in your library symbol, you do not need this
graphics.beginFill(0xffffff * Math.random());
graphics.drawRect(0, 0, 100, 100);
graphics.endFill();
}
}
As you can see, it only has a constructor in which I programmatically draw a rectangle. Again, if you have the desired artwork in your library symbol, there's no need for this. In that case, the constructor would be empty and in turn the entire class file would be empty. In this case, you do not even need a class file. Just associate the library symbol with the name. The Square is only a graphic asset without any code attached to it.
Here's a full fledged document class using both classes:
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
public class Main extends Sprite
{
private var circle:Circle;
public function Main()
{
circle = new Circle();
circle.x = 200;
circle.y = 200;
addChild(circle);
circle.startGrowing(1);
var square:Square = new Square();
addChild(square);
square.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
private function onMouseDown(e:MouseEvent):void
{
circle.stopGrowing();
}
}
}
As you can see, the event listener is added in the document class and also the function that is executed when the event occurs is in Main.
Here's a variation of that without the square. This time you have to click on the circle to stop it growing:
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
public class Main extends Sprite
{
private var circle:Circle;
public function Main()
{
circle = new Circle();
circle.x = 200;
circle.y = 200;
addChild(circle);
circle.startGrowing(1);
circle.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
private function onMouseDown(e:MouseEvent):void
{
circle.stopGrowing();
}
}
}
As you can see, making the connection outside both classes with events gives you a lot of flexibility to wire things up in a different way. Just like having a phone that connects to a network instead of another phone directly.

Creating Top Down Shooter in Adobe Flash CS4 using ActionScript 3 but bullets behaving weirdly

I am making a TDS in Flash CS4 using AS3 but there seems to be a problem. It's hard to explain so I'm gonna link the flash file. Click this.
This is the first time uploading a file for sharing so for those who can't or are unable to download the file, this is what happens:
Player has mouse rotation that is, Player looks at where the mouse is. On Mouse down I've put the script for creating bullets. The bullets are being created alright. But when the bullets move that's when the problem arises. Say that at position and rotation X, I shot 5 bullets and they are moving in X direction. Now if I shoot a bullet in Y position and rotation, the bullet that was created there goes in Y direction but so do all the other bullets that were created in the X position and direction. They change their course.
Here is the code for the game.
package {
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.MouseEvent;
import flash.ui.Keyboard;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Mouse;
import flash.events.TimerEvent;
public class Main extends MovieClip {
var player : Player = new Player();
//Customizable Weapon Settings
var bulletNumber:Number;//number of bullets per shot
var bulletOffset:Number;//bigger number = less acurate
var bulletSpeed:Number;//pixels per frame
var bulletMaxAge:Number;//1000 = 1 second
var reloadSpeed:Number;//1000 = 1 second
var randomNum:Number;
public static var xSpeed:Number;
public static var ySpeed:Number;
var bulletAngle:Number;
var timer:Number=0;
var flag:Boolean;
//other variables (do not edit)
var mouseClicked:Boolean=false;
var radians:Number=Math.PI/180;
public function Main() {
player.x=stage.stageWidth/2;
player.y=stage.stageHeight/2;
stage.addChild(player);
player.gotoAndStop(5);
loadWeapon("Machine Gun");
addEventListener(Event.ENTER_FRAME,on_enter_frame);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUpHandler);
}
public function onMouseDownHandler(event:MouseEvent) {
//trace("Mouse Down");
mouseClicked=true;
flag=true;
}
public function onMouseUpHandler(event:MouseEvent) {
//trace("Mouse Up");
mouseClicked=false;
flag=false;
timer=0;
}
public function loadWeapon(weaponType:String) {
switch (weaponType) {
case "Machine Gun" :
//bulletNumber = 100;
bulletOffset=10;
bulletSpeed=10;
bulletMaxAge=1000;
break;
}
}
function on_enter_frame(e:Event) {
trace("Click: "+ mouseClicked);
fireWeapon();
}
function fireWeapon() {
//check if mouse is clicked
//if true, create bullet
if (mouseClicked) {
createBullet();
player.gotoAndStop(10);
} else {
player.gotoAndStop(1);
}
}
public function createBullet() {
var bullet : Bullet2= new Bullet2();
bullet.x=player.x;
bullet.y=player.y;
if (flag) {
timer++;
if (timer==10) {
trace("lol");
//calculate random bullet offset.
randomNum = Math.random() * (bulletOffset);
//set bullet firing angle
bulletAngle = (player.rotation + randomNum) * radians;
//set bullet speed based on angle
xSpeed=Math.cos(bulletAngle)*bulletSpeed;
ySpeed=Math.sin(bulletAngle)*bulletSpeed;
//trace (bulletAngle);
stage.addChild(bullet);
bullet.addEventListener(Event.ENTER_FRAME, runForest);
//mouseClicked = false;
timer=0;
}
}
function runForest(e:Event) {
bullet.x+=xSpeed;
bullet.y+=ySpeed;
}
}
}
}
Things that I've tried:
1) I put the "runForest()" funtion outside of "createbullet()" function which give me a "1120: Access of undefined property bullet." Error. (Which doesn't make sense since I am giving it a enter frame event listener.)
2) For solving this, I made the bullet variable global and declared it inside the "createbullet()" function like this- "var bullet : Bullet2;" And inside createbullet()- "bullet = new Bullet2();" That gives me a completely different output.
3) I put the "runForest()" function in its own class file. But the same thing is happening.
I was referring to a Tutorial that used AS2. This is the link.
Help me solve this please.
Thanks!
Review this code:
//set bullet speed based on angle
xSpeed=Math.cos(bulletAngle)*bulletSpeed;
ySpeed=Math.sin(bulletAngle)*bulletSpeed;
then take a look at how these variables for speed are created:
public static var xSpeed:Number;
public static var ySpeed:Number;
You have 1 variable for the x direction of the speed. If there is only one variable, there can only be 1 value for speed.
that's why all your bullets are moving in the same direction, because they all share that one single value for speed, which causes them to go into the same direction.
Your Main class is doing everything at the moment and you should really refactor some of that code into several other classes.
Even your own understanding of the code you are writing is not reflected by the code, your comment says:
//set bullet speed based on angle
Now why is that bullet speed a variable of Main? Object oriented programming is made exactly for that. You can literally turn your plain English description of the desired behaviour into code.
When you say that you "want to have Bullets", then create a Bullet class.
When you say "each Bullet object should have its own speed", then add a property to that class that is the speed.
You will encounter the same problem with your weapons and the same solution applies.

bend line 90 degrees at a point where another movieclip intersects with it in actionscript 3

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);
}
}
}
}

ActionScript - Clearing Graphics With JointStyle.MITER Bug?

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?