I'm new to actionscript so this question might be a stupid one.
I'm trying to replace a movieclip with another movieclip, while keeping the instance name of the previous.
I have a menu with a selection of buttons, each leading to the same screen with a movieclip and a scrubber bar. I tried defining the movieclip through a variable, then tried redefining it through an event listener function, but I'm guessing I can't do like this:
var MC: movieclipsymbol1 = new movieclipsymbol1;
private function selectionscreen(): void {
selectionscreenbutton1.addEventListener(MouseEvent.CLICK, screenbutton1);
selectionscreenbutton2.addEventListener(MouseEvent.CLICK, screenbutton2);
private function screenbutton1(event: MouseEvent): void {
var MC: movieclipsymbol1 = new movieclipsymbol1;
movieclipscreen();
}
private function screenbutton2(event: MouseEvent): void {
var MC: movieclipsymbol2 = new movieclipsymbol2;
movieclipscreen();
}
}
public function movieclipscreen(): void {
stage.addChild(MC);
}
Because of the scrubber bar code I did, I need to keep the instance for the movieclips the same. Is the approach I'm using completely off?
You have to remove var MC from both handlers, as you want your new MC to be accessible from outside of the handlers. But also you need to change the type of class variable MC so that it could hold either movieclipsymbol1 or movieclipsymbol2. The most common choice for the type in there is MovieClip. So, you have to change your functions like this:
var MC:MovieClip = new movieclipsymbol1();
private function screenbutton1(event: MouseEvent): void {
clearOldMC();
MC = new movieclipsymbol1();
movieclipscreen();
}
private function screenbutton2(event: MouseEvent): void {
clearOldMC();
MC = new movieclipsymbol2();
movieclipscreen();
}
private function clearOldMC():void {
if (MC.parent) MC.parent.removeChild(MC);
}
The new function removes the previously displayed movie clip, regardless of its type.
Use "name" property of display object to give the instance name to movieclip.
Related
I have a gun child inside of a movieclip called "player" and "player" is inside another movieclip called "level one".
So inside the gun class, the code spawns a bullet. Which has to spawn in the parent's parent. So the bullet can shoot into the level.
private function fire(m: MouseEvent)
{
//when bullet fired
var b = new Bullet;
MovieClip(MovieClip(parent).parent).addChild(b);
}
However, the bullet never appears in the parent's parent. What could be the issue here?
UPDATED CODE:
In gun class:
function fire(e:MouseEvent):void
{
dispatchEvent(new Event('fire!', true));
}
In player class:
protected function fire(e: Event)
{
var b: Bullet = new Bullet();
// bullet must be in same position and angle as player.gun
b.rotation = player.gun.rotation;
b.x = player.gun.x; + player.gun.width * Math.cos(player.gun.rotation / 180 * Math.PI);
b.y = player.gun.y + player.gun.width * Math.sin(player.gun.rotation / 180 * Math.PI);
addChild(b);
}
You missed to strong typing the variable and add parentheses
Try
var b:Bullet = new Bullet();
Why don't you keep a reference to the parent.parent?
var b:Bullet = new Bullet(parent)
...
public function Bullet(spawnTarget:MovieClip)
{
_spawnTarget = spawnTarget;
}
private function fire(m: MouseEvent)
{
//when bullet fired
var b = new Bullet;
_spawnTarget.addChild(b);
}
Using parent.parent is risky because you'd always need to make sure that the gun class is instantiated in a child of the game class. Also, you can't create guns in any other position in the hierarchy which can be a problem if your game grows bigger.
You can solve this with listeners (as the comments state, and this is an example of passing a game reference. Each instance receives a reference to game, so each instance can call public function on game:
Game.as
myPlayer = new Player(this);
public function addBulletToWorld(){
}
Player.as
public function Player(game){
myGun = new Gun(game);
}
Gun.as
public function Gun(game){
game.addBulletToWorld();
}
If you absolutely insist on using the parent.parent thing, just set a break point at that line and see what parent.parent actually is, then adjust as needed to match your actual structure. But aside from the fact that this is just bad practice, it's going to limit you to where you can't use this Class anywhere but at that one depth.
I'd recommend just generating a custom event when you want to fire the bullet, and letting the grandparent handle it.
In Gun:
function fire(e:MoudeEvent):void {
dispatchEvent(new Event('fire!', true));//setting it true lets it bubble up to the parent
}
In Game
protected var bullets:Vector. = new Vector();
public function Game() {
addEventListener('fire!', fire);
}
//note I worked with Flex too long to use private methods very often
protected function fire(e:Event) {
var bullet:Bullet = new Bullet();
bullet.x = MoveClip(e.target).x);
bullet.y = MoveClip(e.target).y);
addChild(bullet);
bullets.push(bullet);//I assume you're going to want to move this or something, so we need to store it to manage it
}
i am newbie to flash.i need to change the below actionscript code to actionscript 3.0 code.
i am currently working on drag and drop. so i want to duplicate the movieclip while dragging i found the code on internet but it is actionscript 2.0 so please convert it to as3. the box is a instance name of a movieclip.
the code blocks are:
var num:Number = 0
box.onPress = function(){
num++
duplicateMovieClip(box ,"box"+num, _root.getNextHighestDepth())
_root["box"+num].startDrag();
}
box.onReleaseOutside = function(){
trace(_root["box"+num])
stopDrag();
}
If you dont want to use seperate .as file, follow this steps:
1- assign AS linkage to box movieClip (in library panel):
2- Select frame 1 on the timeline, and paste this code in the Actions panel:
var boxes:Array=[];
//var box:Box=new Box();
//addChild(box);
box.addEventListener(MouseEvent.MOUSE_DOWN,generateBox);
function generateBox(e:MouseEvent):void{
var newBox:Box=new Box();
newBox.x = e.target.x;
newBox.y = e.target.y;
newBox.startDrag();
newBox.addEventListener(MouseEvent.MOUSE_UP,stopD);
newBox.addEventListener(MouseEvent.MOUSE_DOWN,startD);
boxes.push(newBox);
addChild(newBox);
}
function startD(e:MouseEvent):void{
e.target.startDrag();
}
function stopD(e:MouseEvent):void{
e.target.stopDrag();
}
Unfortunately, there's no duplicateMovieClip analog in AS3, so you'll have to create a Class for your box movieClip template. Let's say it will be called BoxTemplate. (You can google how to create Classes for your library object). Add a Class with this name and add this code (event subscription in the constructor and a private event listener). You'll get something like this:
package
{
public class BoxTemplate
{
public function BoxTemplate()
{
addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
}
private function onMouseUp(e:MouseEvent):void
{
stopDrag();
}
}
Leave your present instance of this symbol on the stage. This is your code in the frame:
import flash.event.MouseEvent
box.addEventListener(MouseEvent.CLICK, onClick);
function onClick(e:MouseEvent):void
{
var newBox:BoxTemplate = new BoxTemplate();
newBox.x = e.target.x;
newBox.y = e.target.y;
addChild(newBox);
newBox.startDrag();
}
It will allow you to infinitely clone your boxes. Of course, you can add all of them in the array to keep the references.
am having problem with using mouse click event inside a class, i am an absolute beginner to Action Script.
what i want is that if i click the btn_MClick button it should run the script, but everytime i click it i get error message that btn_MClick is undefined.
btn_MClick is on stage and with the instance name if btn_MClick
public class gunShip1 extends MovieClip
{
var moveCount = 0;
public function gunShip1()
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveGunShip1);
stage.addEventListener(KeyboardEvent.KEY_DOWN, ShootGunShip1)
btn_MClick.addEventListener(MouseEvent.MOUSE_DOWN.KEY_DOWN, ShootGunShip1);;
}
function ShootGunShip1(evt: MouseEvent)
{
var s_Bullet:survBullet = new survBullet();
var stagePos:Point = this.localToGlobal (new Point(this.width / 2-10, this.height));;
s_Bullet.x = stagePos.x;
s_Bullet.y = stagePos.y;
parent.addChild(s_Bullet);
//play sound
var gun_sound:ricochetshot = new ricochetshot();
gun_sound.play();
}
}
Please, i have absolutely no idea what to do, and somehow it feels like the whole process is wrong.
Your class gunShip1 does not have the property btn_MClick, the root, or document class does.
Basically what's happening is that you've placed your button on the stage, which makes it an instance that belongs to the root container. At the moment, you're trying to refer to the button as a property of gunShip1.
What you should really do here is have the button click managed separately to gunShip1, and have that separate code invoke methods of gunShip1. For example, you could have this in your document class:
public class Game extends MovieClip
{
private var _ship:gunShip1;
public function Game()
{
_ship = new gunShip1();
// The Document Class will have reference to objects on the stage.
btn_MClick.addEventListener(MouseEvent.CLICK, _click);
}
private function _click(e:MouseEvent):void
{
_ship.shoot();
}
}
And then your updated shoot method in gunShip1:
public function shoot():void
{
var s_Bullet:survBullet = new survBullet();
var stagePos:Point = this.localToGlobal (new Point(this.width / 2 - 10, this.height));
s_Bullet.x = stagePos.x;
s_Bullet.y = stagePos.y;
parent.addChild(s_Bullet);
var gun_sound:ricochetshot = new ricochetshot();
gun_sound.play();
}
The idea is that the gunShip1 should not be responsible for dealing with user input (mouse, keyboard, etc). Instead, that should be a separate class which informs gunShip1 that it should do something.
There are two files in my actionscript project named "TestAPP", TestAPP.as and Draggable.as
TestAPP.as:
package {
import flash.display.Sprite;
import flash.display.Stage;
public class TestAPP extends Sprite
{
var _mainStage:Stage;
public function TestAPP()//This is where we test the UI components.
{
var sp:Sprite = new Sprite();
_mainStage = stage;
_mainStage.addChild(sp);
sp.graphics.beginFill(0x00FF00);
sp.graphics.drawCircle(0,0,10);
sp.graphics.endFill();
sp.x = 50;
sp.y = 50;
var draggable1:Draggable = new draggable(sp,_mainStage,limitingfunc);
}
public function limitingfunc(x:Number,y:Number):int{
return 0;
}
}
}
And for the draggable.as:
package
{
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.MouseEvent;
public class Draggable
{
private var _limitingFunc:Function;
private var _which:Sprite;
private var _MouseSavedX:Number;
private var _MouseSavedY:Number;
private var _stage:Stage;
public function Draggable(which:Sprite,stage:Stage,limitingfunc:Function)
{
_limitingFunc = limitingfunc;
_which = which;
_stage = stage;
_which.addEventListener(MouseEvent.MOUSE_DOWN,begin_drag);
}
//limiting func: returns 0 when the object is free to move that place.
//returns -1 when the user wants to block X coordinate changes (but maintain Y free)
//returns -2 when the user wants to block Y ...
//returns -3 or less when the user wants to block both X and Y from changing.
//returns
private function Return_0(x:Number = 0,y:Number = 0):int{
return 0;
}
private function begin_drag(ev:MouseEvent):void{
var xTo:Number = _stage.mouseX - _MouseSavedX + _which.x;
var yTo:Number = _stage.mouseY - _MouseSavedY + _which.y;
var limitingFuncReturnValue:int = _limitingFunc(xTo,yTo);
if(limitingFuncReturnValue == 0){//free to move.
_which.x = xTo;
_which.y = yTo;
}
else if(limitingFuncReturnValue == -1){//free to move Y
_which.y = yTo;
}
else if(limitingFuncReturnValue == -2){
_which.y = yTo;
}
//else:do nothing.
}
}
}
In "my actionscript theory", I'm supposed to see a circle that follows the mouse when I click it. (The draggable is not fully implemented) But the circle doesn't even budge :(
...I've been trying to figure out how to access the main class's stage property. I've googled for it, but still no progress.
Please help this helpless newb!!! I'll really appreciate your help:)
Thank you!
You're implementing your 2nd class as "draggable", when you named it (and it has to be named) "Draggable" with an upper case. Change it and see if that works. You seem to be passing in the parent classes stage correctly though.
If TestAPP is your document class. You can access to the stage thru the stage property (like your are doing in your example).
If TestAPP is not the document class, you should listen first to the ADDED_TO_STAGE event and then access to the stage property.
There is no need to add _mainStage property because you already have the stage property.
In order to move objects around, you need to use the ENTER_FRAME event.
You can access the main class' stage property the same way you do it for any DisplayObject on the stage: Use this.stage.
So just this should be enough:
var sp:Sprite = new Sprite();
stage.addChild(sp);
You could then pass the sprite and the main class' stage as a parameter, the way you did - but I would recommend creating a subclass Draggable extends Sprite and instantiate the whole thing using new Draggable() instead.
The new object will automatically have its own reference to stage as soon as it is added to the display list, and limitingFunc could be a member of Draggable, as well.
Also, you can use the startDrag() and stopDrag() methods, no need to implement your own: You can specify a Rectangle as a parameter to startDrag() to limit the permitted movement.
if you need it so much you may:
private static var _instance: TestAPP;
//...
public function TestAPP(){
_instance = this;
//...
}
public static function get instance():TestAPP{
return _instance;
}
public static function set instance(newVal: TestAPP):void{
_instance = newVal;
}
and you'll be able to reference its stage from any class where your TestAPP will be imported just with TestAPP.instance.stage.
but _instance is a property of the class TestAPP itself, not its instances
There is a mouseUpEvent listener attached to the stage in the main class, while dragging the movieClip the mouseUpEvent doesnot trigger the handler and the movieClip gets sticks to the mouse. While the item is being dragged and the mouse is moved away from the movieClip i.e somewhere not on the item but on the stage the mouseUp is detected.
Edit: Here is the scenario I am using a static (Singleton) class as a movieClip as a "DragManager". Whenever a movieClip has to be dragged it is passed to the DragManager and is added as a child, when a mouseUp from stage is detected another static function of dragManager is called to stop the drag and put the movieClip on the appropriate layer. Here is the static function in the DragManager which is called on MouseDown from variouslayers.
public static function startDragMethod(item:Item):void
{
instance.addChild(item); //This is the instance of the DragManager
var boundArea:Rectangle = new Rectangle(0,0,610,760);
item.startDrag(false,boundArea);
}
In the constructor of the main class I add the eventHandler for the MouseUpEvent
this.addEventListener(MouseEvent.MOUSE_UP,stageMouseUpHandler);
The MouseUpHandler in the main class
private function stageMouseUpHandler(event:MouseEvent):void
{
DragManager.itemMouseUpHandler(event);
}
If there is something wrong with technique please guide me, my goal is to implement drag drop between various layers and with as less coupling as possible.
Well there are many ways to get the task done. Put some condition at your static listener function or when the object is dragged.
like
public static function startDragMethod(item:Item):void
{
instance.addChild(item); //This is the instance of the DragManager
var boundArea:Rectangle = new Rectangle(0,0,610,760);
item.startDrag(false,boundArea);
check = true;
}
private function stageMouseUpHandler(event:MouseEvent):void
{
if(check==true)
{
DragManager.itemMouseUpHandler(event);
check = false;
}
}