Hey i've been trying to input a score text in canvas but gives me this error: Uncaught TypeError: Cannot read property 'Container' of undefined.
Here's the code:
class ScoreBox extends Phaser.GameObjets.Container{
constructor (config){
//invoke constructor of extended class
super (config.scene);
//get scene from parameter and set scene atribute
this.scene = config.scene;
//add a text box to the scene
this.text = this.scene.add.text ( 0, 0, "SCORE: 0");
//set text origin
this.text.setOrigin (0.5, 0.5);
//add the text to the container
this.add (this.text);
//add the container to the scene
this.scene.add.existing (this);
//Enable score update through emitter
emitter.on (messageConstants.SCORE_UPDATED, this.scoreUpdated);
}
scoreUpdated (){
this.text.setText ("SCORE: " + model.score);
}
}
I'm connecting this to the html but I don't know why doesn't recognizes the container class, anyone can help me?
At least in your example code you have a typo. It should be Phaser.GameObjects.Container not Phaser.GameObjets.Container
Related
I have this as3 project, and in frame one of the timeline I tried to load a swf movie named "menu" and in this loaded movie I have an instance of a button named "button1", and I want to add a new EventListener to this "button1". my code is here:
var theLoader:Loader = new Loader();
var address:URLRequest = new URLRequest("menu.swf");
theLoader.load(address);
theLoader.contentLoaderInfo.addEventListener(Event.COMPLETE , swfDidLoad);
function swfDidLoad(evt:Event){
if(theLoader.content){
addChild(theLoader);
var button:SimpleButton = theLoader.content.button1;
button.addEventListener(MouseEvent.CLICK, handler1);
}
}
function handler1 (event:MouseEvent):void
{
removeChild(theLoader);
gotoAndStop(10);
};
but I get this undefind property error. what should I do? Am i doing this right at all?
The reason you are getting that error is because you are trying to access button1 on theLoader.content which is a non-dynamic DisplayObject (this means that only explicitly defined properties/methods are valid). You must first cast it to a MovieClip (which is dynamic).
You should change that line to:
var button:SimpleButton = MovieClip(theLoader.content).button1;
I'm making a game in AS3.
I've got in my code :
public var _classes:Array = new Array(poubelle1, poubelle2, poubelle3);
public var _movieClips:Array = new Array();
public function apparitionDechet(event : TimerEvent):void{
_movieClips.push(new _classes[Math.floor(Math.random() * _classes.length)]());
stageRef.addChild(_movieClips[_movieClips.length-1]);
I'm trying to put an addEventListener on the MovieClips.
The player should be able to click on a MovieClip when it's appearing or he can wait. Few will appears, and he can click on them at any moments.
Each clicks will make the MoviClip disapear..
So I've put :
_movieClips[1].addEventListener(MouseEvent.CLICK, removePoubelle, false, 0, true);
}
public function removePoubelle(e:MouseEvent):void{
if(e.target=="_movieClips[0]"){
trace("ok1");
}
if(e.target=="_movieClips[1]"){
trace("ok2");
}
if(e.target=="_movieClips[2]"){
trace("ok3");
}
but it's not that...
Do you know how I can do that ?
It's my first time that I'm using the randomly apparition of MovieClips...
Thank you very much,
EDIT
So I've followed your tips and did this :
public function apparitionDechet(event : TimerEvent):void{
var mc:DisplayObject = new _classes[Math.floor(Math.random() * _classes.length)]();
_movieClips.push(mc);
stageRef.addChild(mc);
mc.addEventListener(MouseEvent.CLICK, removePoubelle, false, 0, true);
}
public function removePoubelle(e:MouseEvent):void{
var mc:DisplayObject = e.target;
var i:int=_movieClips.indexOf(mc);
if (i>=0){
_movieClips.splice(i,1);
mc.parent.removeChild(mc);
}
}
But I've got the error 1118 Implicit coercion of a value with static type Object to a possibly unrelated type flash.display:DisplayObject
EDIT 2
Quick question though, is it possible to do :
if(stageRef.contains(poubelle1)) {
trace("poubelle1détécté");
}
if(stageRef.contains(poubelle2)) {
trace("poubelle2 détécté");
}
?
movieClips poubelle1 and poubelle 2 are defined like this
public var _classes:Array = new Array(poubelle1, poubelle2, poubelle3);
public var _movieClips:Array = new Array();
it doesn't seem to work if I do that.(error 1027 Contrainte implicite d'une valeur du type Class vers un type sans rapport flash.display:DisplayObject) Any idea why ?
Do you want me to create a new post ?
Thank you
If you are to remove the movieclip that was clicked, you already have it as the event's target. So you get its parent and call removeChild(). Don't forget to remove the event listener off the target.
public function removePoubelle(e:MouseEvent):void {
var mc:DisplayObject = e.target as DisplayObject;
if (!mc) return; // typecast failed
mc.parent.removeChild(mc);
// mc.removeEventListener(MouseEvent.CLICK, removePoubelle, false, 0, true);
// the line above might not be needed as the listener weakly references the mc
}
And you put the listener as soon as you create your new movie clip.
public function apparitionDechet(event : TimerEvent):void {
var mc:DisplayObject = new _classes[Math.floor(Math.random() * _classes.length)]();
_movieClips.push(mc);
stageRef.addChild(mc);
mc.addEventListener(MouseEvent.CLICK, removePoubelle, false, 0, true);
}
See, how you can avoid referencing the newly created movie clip without ugly _movieClips[_movieClips.length-1] construction? You just make a local variable which is then instantiated for your random MC out of _classes, and you then use the variable to do everything else that's needed at the time of creation.
But, this is still not enough - your "poubelle" is still inside your _movieClips array, so it'll grow. You need to clean up the array too. So, add this code to removePoubelle:
var i:int=_movieClips.indexOf(mc);
if (i>=0) _movieClips.splice(i,1);
This gets the position of the clicked movie clip inside your array, and if it's a valid one (zero or more) the array is told to remove that element.
You shouldn't be using just _movieClips[1]. That refers specifically to the SECOND object in your _movieClips Array.
You should add your eventListener as soon as the MovieClip is added to the _movieClips Array. You can add it to the most recently '.push'ed MovieClip, like this:
_movieClips[_movieClips.length-1].addEventListener(MouseEvent.CLICK, removePoubelle);
Do that on the next line after the line where MovieClip is pushed into the _movieClips Array.
Your event handler (the removePoubelle function) will be passed a MouseEvent and you can refer to the .target of this event to isolate WHICH MovieClip has been clicked:
private function removePoubelle(e:MouseEvent):void {
var mcToRemove:DisplayObject = e.target;
removeChild(mcToRemove); // note there is no need to refer to .parent as the MovieClip was added in this Class
// more code to come - see below
}
Also note: Because each MovieClip has an eventListener added WHEN IT IS CREATED, e.target will ALWAYS refer to whichever MovieClip was clicked.
The only other thing you may want to implement is removing the MovieClip from the _movieClips Array. This can be done in the removePoubelle function too:
var removalIndex:int = _movieClips.indexOf(MovieClip(e.target)); // here I am 'casting' the e.target to the type MovieClip. That basically just means I'm changing it's type from DisplayObject to MovieClip (which is a subclass of DisplayObject)
if (removalIndex>-1) {
_movieClips.splice(removalIndex, 1); // this line removes one item at the index returned from the _movieClips.indexOf... line above.
}
Let me know if any of this doesn't make sense.
}
In short, here is what I'd like to accomplish:
Click Movie Clip, add child
Click child movie clip, play sound
Click child again, stop sound
Click child a third time, remove child
Sadly, I've only gotten as far as step 1. I've figured out how to get a sound to play when the parent movie clip is clicked (I'm using linkage), but when I attempt the same after with the child, I get the following error:
TypeError: Error #1010: A term is undefined and has no properties. (I'm no longer getting this error)
Scene 1, Layer 'actions', Frame 1, Line 29 1120: Access of undefined property newBox.
leftBox.addEventListener(MouseEvent.CLICK, addBox);
function addBox(event:MouseEvent):void
{
var newBox:right_box = new right_box();
addChild(newBox);
newBox.x = 0;
newBox.y = 0;
newBox.width = leftBox.width;
newBox.height = leftBox.height /2;
}
newBox.addEventListener(MouseEvent.CLICK, playSound);
function playSound(event:Event)
{
var mySound:testSound = new testSound();
mySound.play();
}
Any help would be much appreciated.
Thanks!
(P.S. I'm a n00b, so please, be nice!)
You are trying to add an event listener to newbox, before it is created.. Try it as follows:
// mySound should be availible in scope
var mySound:testSound = new testSound();
// newBox also
var newBox:right_box;
// here is a channel for you
var channel: SoundChannel;
// ok this adds the first listener...
leftBox.addEventListener(MouseEvent.CLICK, addBox);
function addBox(event:MouseEvent):void {
newBox = new right_box();
addChild(newBox);
newBox.x = 0;
newBox.y = 0;
newBox.width = leftBox.width;
newBox.height = leftBox.height /2;
// you should add listener here...
newBox.addEventListener(MouseEvent.CLICK, playSound);
// you have to avoid multiple newBoxes on each other and
// leaving the older ones under..
// So stop listening to the newBox generating event:
leftBox.removeEventListener(MouseEvent.CLICK, addBox);
}
function playSound(event:Event){
channel = mySound.play();
// On next click you want sound to stop so
// First remove the old listener to avoid play over:
newBox.removeEventListener(MouseEvent.CLICK, playSound);
// and hook listener to stop method
newBox.addEventListener(MouseEvent.CLICK, stopSound);
}
function stopSound(event:Event){
channel.stop();
// On next click you want to remove newBox
// First remove the old listener to avoid play over:
newBox.removeEventListener(MouseEvent.CLICK, stopSound);
newBox.addEventListener(MouseEvent.CLICK, removeNewBox);
}
function removeNewBox(event:Event){
// First remove the listener :
newBox.removeEventListener(MouseEvent.CLICK, removeNewBox );
removeChild(newBox); // now remove from display list
newBox = null; // make contents eligible for garbage collection
}
I am working on an AS3 project and I am struggling with one particularly fragile part which will need a lot of refactoring in the near future. Just unit testing separate classes in isolation does not catch all issues we are running into. For example, we might forget to disable mouse events on a transparent overlay and thereby block all clicks on a button. Therefore, I am trying to write a test that simulates real user input.
I have tried to manually send a MouseEvent to the stage at the correct position:
stage.dispatchEvent(new MouseEvent(MouseEvent.CLICK, true, true, 380, 490, stage));
Since the stage has no click event handler, I expected the event to propagate through the hierarchy to the button that will actually handle it (as it does when I physically click the mouse). However, it doesn't.
I know that I could just dispatch the event on the button, but that will not detect if the object is somehow obstructed. Is there some way to simulate mouse events, such that they will properly propagate through the hierarchy?
Edit:
I managed to do it by re-implementing the propagation behavior of Flash:
Edit 2:
My previous solution didn't work if there was a partly transparent overlay with a click handler, like a Sprite with a few Shapes in it. The problem is that the hitTestPoint method returns true even if the object in question is completely transparent at that point. Therefore, I modified it to check the actual pixel value:
private function clickObject(obj:DisplayObject) : void
{
var relPos:Point = new Point(obj.width / 2, obj.height / 2);
var globalPos:Point = obj.localToGlobal(relPos);
simulateClick(obj.stage, globalPos);
}
private function simulateClick(obj:InteractiveObject, globalPos:Point) : Boolean
{
// first, check if we have any children that would rather handle the event
var container:DisplayObjectContainer = obj as DisplayObjectContainer;
if (container != null)
{
if (container.mouseChildren)
{
for (var i:int = 0; i < container.numChildren; ++i)
{
var child:DisplayObject = container.getChildAt(i);
var interactive:InteractiveObject = child as InteractiveObject;
if (interactive != null)
{
if (simulateClick(interactive, globalPos))
{
// if we have found a handler in the children, we are done
return true;
}
}
}
}
}
if (!obj.mouseEnabled) {
return false;
}
if (obj.hitTestPoint(globalPos.x, globalPos.y))
{
var localPos:Point = obj.globalToLocal(globalPos);
// check if object is visible at the clicked location
var pixel:BitmapData = new BitmapData(1, 1);
pixel.draw(obj, new Matrix(1, 0, 0, 1, -localPos.x, -localPos.y));
var color:uint = pixel.getPixel32(0, 0);
if ((pixel.getPixel32(0, 0) & 0xff000000) != 0)
{
// if yes, dispatch the click event
var e:MouseEvent = new MouseEvent(MouseEvent.CLICK, true, true, localPos.x, localPos.y, obj);
obj.dispatchEvent(e);
return true;
}
}
return false;
}
Unfortunately, there is still at least one case not covered: If the object is a mask for another object. I have no idea how to check for this, since it could be mask anywhere in the display hierarchy. I would have to traverse the whole tree and check every single display object to find this out.
So, my question remains: Isn't there an easier way to do this?
I've had issues with events in AS3 as well. I've found that the best way is to have the eventListeners added to the same object that's dispatching the events. In your case, adding the .addEventListener to the stage and sending the function as a function on a child clip. eg:
stage.addEventListener(MouseEvent.CLICK, object.object.clicked);
I hope this may help. I've used this method with success in the past.
You can use stage.getObjectsUnderPoint(new Point(pointerX , pointerY )); function , that will return You array with objects . Than remove overlay object and last instance in array should be deepest DisplayObject.
note: last instance can be graphic or such thing , so You should loop through parent objects to find nearest InteractiveObject .
Also , dont forget that parent objects can have mouseChildren = false or mouseEnabled = false
Recently I followed and made the 3d carousel in AS2, but I'm looking to use it and make it in AS3. Is there any possible way of converting the code so the carousel can work in AS3?
Below is the code for the AS2 carousel:
import mx.utils.Delegate;
var numOfItems:Number;
var radiusX:Number = 300;
var radiusY:Number = 75;
var centerX:Number = Stage.width / 2;
var centerY:Number = Stage.height / 2;
var speed:Number = 0.05;
var perspective:Number = 130;
var home:MovieClip = this;
var tooltip:MovieClip = this.attachMovie("tooltip","tooltip",10000);
tooltip._alpha = 0;
var xml:XML = new XML();
xml.ignoreWhite = true;
xml.onLoad = function()
{
var nodes = this.firstChild.childNodes;
numOfItems = nodes.length;
for(var i=0;i<numOfItems;i++)
{
var t = home.attachMovie("item","item"+i,i+1);
t.angle = i * ((Math.PI*2)/numOfItems);
t.onEnterFrame = mover;
t.toolText = nodes[i].attributes.tooltip;
t.icon.inner.loadMovie(nodes[i].attributes.image);
t.r.inner.loadMovie(nodes[i].attributes.image);
t.icon.onRollOver = over;
t.icon.onRollOut = out;
t.icon.onRelease = released;
}
}
function over()
{
home.tooltip.tipText.text = this._parent.toolText;
home.tooltip._x = this._parent._x;
home.tooltip._y = this._parent._y - this._parent._height/2;
home.tooltip.onEnterFrame = Delegate.create(this,moveTip);
home.tooltip._alpha = 100;
}
function out()
{
delete home.tooltip.onEnterFrame;
home.tooltip._alpha = 0;
}
function released()
{
trace(this._parent.toolText);
}
function moveTip()
{
home.tooltip._x = this._parent._x;
home.tooltip._y = this._parent._y - this._parent._height/2;
}
xml.load("icons.xml");
function mover()
{
this._x = Math.cos(this.angle) * radiusX + centerX;
this._y = Math.sin(this.angle) * radiusY + centerY;
var s = (this._y - perspective) /(centerY+radiusY-perspective);
this._xscale = this._yscale = s*100;
this.angle += this._parent.speed;
this.swapDepths(Math.round(this._xscale) + 100);
}
this.onMouseMove = function()
{
speed = (this._xmouse-centerX)/2500;
}
When I add this code in AS3 I get the following error:
Scene 1, Layer 'Layer 1', Frame 1, Line 1 1172: Definition mx.utils:Delegate could not be found.
Scene 1, Layer 'Layer 1', Frame 1, Line 1 1172: Definition mx.utils:Delegate could not be found.
Scene 1, Layer 'Layer 1', Frame 1, Line 41 1120: Access of undefined property Delegate.
Scene 1, Layer 'Layer 1', Frame 1, Line 6 1119: Access of possibly undefined property width through a reference with static type Class.
Scene 1, Layer 'Layer 1', Frame 1, Line 7 1119: Access of possibly undefined property height through a reference with static type Class.
I'm quite new to AS2 and AS3 but after some research I understand that import mx.utils.Delegate; is no longer need in AS3 as it already has delegate and they are already built in so in the code so I delete the delegate which are line 1 and line 41 and got two errors:
Scene 1, Layer 'Layer 1', Frame 1, Line 6 1119: Access of possibly undefined property width through a reference with static type Class.
Scene 1, Layer 'Layer 1', Frame 1, Line 7 1119: Access of possibly undefined property height through a reference with static type Class.
Now I cant figure out what to do so can someone help me convert this code from AS2 to AS3?
You have quite a few things to address here:
Your mouse events need to be changed to as3 calls
t.icon.onRollOver = over, in as3 looks more like t.icon.addEventListener(MouseEvent.ROLL_OVER, over);
attachMovie is no longer used in as3.
you need to export for actionscript the movie you want to get from the library with a unique class name, then use new someName(); to create it. Then it must be added to the display list with addChild
onEnterFrame is not used in as3, you need to create an enterframe event more like this: **addEventListener(Event.ENTER_FRAME, someFunction);
delegate is not used in as3.
flags on _x, _y, _parent, _alpha etc have been removed in as3. just use x,y, parent, alpha etc.
swapDepths has been removed from as3, You need to use the display list to add/remove/swap levels.
sounds like you might need to study up a little on as3 before you can properly tackle this one! try checking out this link for comparisons between as2 and as3 functionality.
http://www.actionscriptcheatsheet.com/downloads/as3cs_migration.pdf