Add a movieclip on a 3d cube and have interaction with it - actionscript-3

I created a rotating cube using the below code and add bitmaps as sides of the cube.
I was wondering if it's possibly to assign movie clips as sides of the cube so I can have some interaction with them.
import flash.events.Event;
import flash.display.Bitmap;
import flash.display.BitmapData;
import org.papervision3d.cameras.CameraType;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.view.BasicView;
var cube : Cube;
var basicview : BasicView = new BasicView(640, 480, true, false, CameraType.FREE);
addChild(basicview);
var logo : Logo = new Logo( 0,0); //Bitmapdata (jpeg) exported as class Logo from library
var matFront : BitmapMaterial = new BitmapMaterial(logo);
var matBack : BitmapMaterial = new BitmapMaterial(logo);
var ml : MaterialsList = new MaterialsList();
ml.addMaterial(matFront, "front");
ml.addMaterial(matBack, "back");
ml.addMaterial(new ColorMaterial(0x551F92),"right");
ml.addMaterial(new ColorMaterial(0x431872),"bottom");
ml.addMaterial(new ColorMaterial(0x341359),"top");
ml.addMaterial(new ColorMaterial(0x7429C7),"left");
cube = new Cube(ml,200,200,200,5,5,5);
basicview.scene.addChild(cube);
basicview.camera.fov = 20;
addEventListener(Event.ENTER_FRAME, enterFrame);
function enterFrame(e:Event) : void
{
cube.yaw((320-mouseX)*0.01);
cube.pitch((240-mouseY)*0.01);
}
basicview.singleRender();
}
UPDATE
I add this
var matFront : MovieMaterial = new MovieMaterial(new MV(),false,true);
matFront.interactive = true ;
MV is just a square with this code
package Scripts {
import flash.display.MovieClip;
import flash.events.*;
public class MV extends MovieClip
{
public function MV( )
{
buttonMode = true;
addEventListener(MouseEvent.CLICK,traceFunction);
}
private function traceFunction(ev:MouseEvent) {
trace("clicked");
}
}
}
Why I have not any interaction when I click the side with the movie clip?
UPDATE 2
Ok I find it
I had to add this line
basicview.viewport.interactive = true;
But why I have interaction even when the side of the movieclip isn't visible.
How can I avoid it?

Yes it is possible, you have to create Materials from the MovieClips you want to use, to do just that take a look at the classes MovieMaterial and MovieAssetMaterial inside the papervision3d materials Package.

Related

How to save and load the latest movie clips in a Flash Game with as3?

I have many movieclips that i add or remove with "addChild / removeChild" as player navigate through the game views. I want to save these movie clips (propably using shared objects) so load function show the last status of view. I have to say that always are more than one movie clip in each view. I have no a specific code for this yet.
I do not advise you to store objects entirely in SO. Save only object config data. Adobe Flash Professional CS6 (v. 12).
Main - SharedObjectSaver.as
package {
import flash.display.MovieClip;
import flash.net.SharedObject;
import flash.utils.ByteArray;
import flash.net.registerClassAlias;
public class SharedObjectSaver extends MovieClip
{
public function SharedObjectSaver()
{
//Step 1. Check object
//this.addChild(new SomeObject(20,100));
//Step 2. Save object to SharedObject file.
registerClassAlias("SomeObject", SomeObject);
var mySo2:SharedObject = SharedObject.getLocal("SaveData");
mySo2.data.someObject = new ByteArray();
mySo2.data.someObject.writeObject( new SomeObject() );
mySo2.flush();
//Step 3. Try to read object from SharedObject file.
registerClassAlias("SomeObject", SomeObject);
var mySo3:SharedObject = SharedObject.getLocal("SaveData");
mySo3.data.someObject.position = 0;
var someObjectFromSO:* = mySo3.data.someObject.readObject() as SomeObject;
trace(someObjectFromSO is SomeObject); // true
this.addChild(someObjectFromSO);
trace(someObjectFromSO.s);
}
}
}
Being serialized SomeObject class - SomeObject.as
package {
import flash.display.Sprite;
import flash.display.Shape;
import flash.display.Loader;
import flash.net.URLRequest;
public class SomeObject extends Sprite
{
public var s:String;
// You can not require passing arguments to the constructor
// because ByteArray in readObject() method tries to read class and
// create an instance of serialized object.
public function SomeObject()
{
var loader:Loader = new Loader();
loader.load(new URLRequest('https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png'));
s = "Hi";
trace("I'm called");
var rectangle:Shape = new Shape;
rectangle.graphics.beginFill(0xFF0000);
rectangle.graphics.drawRect(0, 0, 10,20);
rectangle.graphics.endFill();
this.addChild(rectangle);
this.addChild(loader);
}
}
}

Add your Stage in a ScrollWindow ActionScript 3.0

I'm gonna try explaining my situation with images, to make sure that everyone will understand what i want to succeed.
First of all i have 3 files:
GenImage.fla which is linked to class GeneralImage.as
and it only contains the following picture (I tried to make the image Movie Clip but again it's not working):
Pic1
and a file named ScrollUI.as which contains the class ScrollUI.
What i want to succeed is from my GeneralImage class to create a ScrollUi item, pass the stage, and there create a ScrollPane which makes the picture look like this:
Pic2
The center part of the second image is the ScrollPane Component, which i need to make it Scrollable through the whole image. I managed to get it in my screen but i can't put the Stage in it and make it scrollable.
These are my codes :
GeneralImage.as
package {
import flash.display.*;
import flash.events.*;
import flash.display.Stage;
import ScrollUI;
public class GeneralImage extends MovieClip
{
public function GeneralImage()
{
var k = new ScrollUI();
k.ScrollConstructor(this);
}
}
}
ScrollUI.as
package
{
import flash.display.*;
import flash.events.*;
import fl.containers.ScrollPane;
import fl.events.ScrollEvent;
import fl.controls.ScrollPolicy;
public class ScrollUI extends MovieClip
{
private var _mainStage:Stage;
var aBox:MovieClip = new MovieClip();
var aSp:ScrollPane = new ScrollPane();
public function ScrollUI()
{
}
function ScrollConstructor(stage:Object):void
{
_mainStage = (stage as MovieClip).stage;
aBox == stage as MovieClip;
aSp.source == aBox ;
_mainStage.addChild(aBox);
aSp.setSize(300,300);
aSp.move(150, 75);
aSp.scrollDrag = true;
aSp.horizontalScrollPolicy=ScrollPolicy.OFF;
_mainStage.addChild(aSp);
}
}
}
So what i want it to set the Source of the Scroll Pane ( which is named aSp ) to be the _mainStage which is the stage i get from GeneralImage
Your issues is likely these two lines:
aBox == stage as MovieClip;
aSp.source == aBox ;
You're doing a comparison by using two ==, which effectively does nothing in your case. Use a single = to assign a value.
This is how I would suggest you approach this:
In the FlashPro library, find your image asset (I'm going to assume you have it wrapped in a MovieClip), right-click (or command click) and go to it's properties. Check the "export for actionscript" box, and give it a meaningful class name (for my example, I'll assume you called it MyImage)
Then you could do the following:
ScrollUI Class
package
{
import flash.display.Sprite;
import fl.containers.ScrollPane;
import fl.events.ScrollEvent;
import fl.controls.ScrollPolicy;
public class ScrollUI extends Sprite
{
//just declare the variables here, don't assign them new values
private var aBox:MovieClip;
private var aSp:ScrollPane;
public function ScrollUI()
{
//use the actual constructor...
aSp = new ScrollPane(); //instantiate a new scroll pane
addChild(aSp); //add the scroll pane to the display
aBox = new MyImage(); //instantiate an new MyImage from the library
//set the scroll pane properties
aSp.source = aBox; //you had two = signs here before, which doesn't actually assign anything it compares
aSp.setSize(300,300);
aSp.move(150, 75);
aSp.scrollDrag = true;
aSp.horizontalScrollPolicy=ScrollPolicy.OFF;
}
}
}
Document Class
package {
import ScrollUI;
public class GeneralImage extends MovieClip
{
public function GeneralImage()
{
var k:ScrollUI = new ScrollUI(); //create a new instance of the ScrollUI class
addChild(k); //add the scrollUI object to the display;
//OR, you just do this:
//addChild(new ScrollUI());
}
}
}
You could also just set the .source property of the scroll pane to the physical path of your image.
I found the solution, Thanks Batman for his help, I changes some things into my code and the program is working.
First of all as Batman said , In my GenImage.fla i made the logo a MovieClip and i named it "wholemap"
Here are my codes :
GeneralImage.as
package {
import flash.display.*;
import flash.events.*;
import flash.display.Stage;
import ScrollUI;
public class GeneralImage extends MovieClip
{
//as Batman indicated, I should have used the ScrollUI constructor, but
//except for the Stage, i also send the wholemap that is in my GenImage.fla
//<< this.getChildByName("wholemap") as MovieClip) >>
public function GeneralImage()
{
var k = new ScrollUI(this, this.getChildByName("wholemap") as MovieClip);
}
}
}
ScrollUI.as
package
{
import flash.display.*;
import flash.events.*;
import fl.containers.ScrollPane;
import fl.events.ScrollEvent;
import fl.controls.ScrollPolicy;
public class ScrollUI extends MovieClip
{
private var _mainStage:Stage;
var aBox:MovieClip = new MovieClip();
//So our constructor gets 2 items, a Stage, and a MovieClip
public function ScrollUI(stage:Object, pic:MovieClip)
{
//We set the Stage at the variable _mainStage with that way:
_mainStage = (stage as MovieClip).stage;
//We set the Image that we will take at our clip variable :
var clip:MovieClip = pic;
//And we send the Movieclip (clip) in our ScrollConstructor function
ScrollConstructor(clip);
}
function ScrollConstructor(Clip:MovieClip):void
{
var aSp:ScrollPane = new ScrollPane();
aBox = Clip;
_mainStage.addChild(aBox);
aSp.source = aBox ;
aSp.setSize(300,300);
aSp.move(150, 75);
aSp.scrollDrag = true;
aSp.horizontalScrollPolicy=ScrollPolicy.OFF;
aSp.verticalScrollPolicy=ScrollPolicy.OFF;
_mainStage.addChild(aSp);
}
}
}
Thank you very much for your assistance, I hope if someone else come across with this problem to be able to solve it with this Answer

Why am I Gettign this Error ?: TypeError: Error #1010: A term is undefined and has no properties. at Main()

I am trying to make a small fanmade Zelda game. I am currently working on the menus, and have a small intro video that leads to the logo and start button being faded in. For some reason however my button is not removing the startPage and adding the filePage. My buttons name and ActionScript link in my library are "StartButton" and it is located in my StartPage movieclip. The filePage is also named "FilePage" aswell as it's AS3 link.
This is my code,
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.events.Event;
import flash.media.Sound;
import flash.media.SoundChannel;
public class Main extends MovieClip
{
var startPage:StartPage;
var filePage:FilePage;
var introMusic:Sound = new IntroMusic;
var introMusicChannel:SoundChannel = new SoundChannel();
public function Main()
{
introMusicChannel = introMusic.play();
startPage = new StartPage;
filePage = new FilePage;
addChild(startPage);
startPage.x = 275;
startPage.y = -12.50;
startPage.width = 795.95;
startPage.height = 498.40;
/*ADD EVENT LISTENERS
***********************/
startPage.addEventListener(MouseEvent.CLICK, onStartPageClick);
startPage.StartButton.addEventListener(MouseEvent.CLICK,
onStartButtonClick);
}
/*EVENT HANDLERS
***********************/
function onStartPageClick(event:MouseEvent):void
{
startPage.gotoAndPlay(599);
}
function onStartButtonClick(event:MouseEvent):void
{
addChild(filePage);
filePage.x = 275.00;
filePage.y = 200.00;
filePage.width = 599.90;
filePage.height = 399.90;
removeChild(startPage);
introMusicChannel.stop();
}
}
}
I believe it is this line.
startPage.StartButton.addEventListener(MouseEvent.CLICK, onStartButtonClick);
Goto StartPage MovieClip, select the StartButton and look into properties panel. Make sure your StartButton has "instance name" as StartButton in properties panel

Event listener on button not working

So, my menu for my game is in a separate .fla file and I have used a loader like so to load the menu into my game:
package {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.DisplayObject;
import flash.display.Stage;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.ui.Mouse;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.text.TextFormat;
import flash.text.TextField;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.system.LoaderContext;
import flash.display.Sprite;
import flash.net.Socket;
import caurina.transitions.Tweener;
public class Main extends MovieClip {
public static var gameLayer:Sprite = new Sprite;
public static var endGameLayer:Sprite = new Sprite;
public static var menuLayer:Sprite = new Sprite;
public var gameTime:int;
public var levelDuration:int;
public function Main()
{
addChild(gameLayer);
addChild(endGameLayer);
addChild(menuLayer);
var myMenu:Loader = new Loader();
var url:URLRequest = new URLRequest("Menu.swf");
myMenu.load(url);
myMenu.contentLoaderInfo.addEventListener(Event.COMPLETE, menuLoaded);
function menuLoaded(event:Event):void
{
menuLayer.addChild(myMenu.content);
}
playBtn.addEventListener(MouseEvent.CLICK, startGame);
}
public function startGame(e:Event)
{
// Code to remove the menu (menuLayer.removeChild?)
// Code here to start timers etc
}
I set instance names for my buttons but when I try to do something like menuLayer.playBtn.addEventListener(MouseEvent.CLICK, startGame);, I get messages saying Access of undefined property playBtn.
Now, I double checked on my Menu.fla and I definitely gave the button an instance name of playBtn but it's not working. Any help please? Might be something really obvious I've missed but I'm not sure what.
EDIT: Trying it another way (Converting the menu to a movieclip) but not 100% sure how to do it exactly. The code I have is:
public class Main extends MovieClip {
var mainMenu:menuMain = new menuMain;
// Other variables
public function Main()
{
addChild(gameLayer);
addChild(endGameLayer);
addChild(menuLayer);
menuLayer.addChild(mainMenu);
mainMenu.addEventListener(Event.COMPLETE, menuLoaded);
}
function menuLoaded(event:Event):void
{
//var mainMenu:LoaderInfo = event.currentTarget as LoaderInfo;
//var menuInstance:MovieClip = menuLayer.getChildAt(0) as MovieClip;
// now you can actually add the listener, because the content is actually loaded
mainMenu.playBtn.addEventListener(MouseEvent.CLICK, startGame);
}
public function startGame(e:Event)
{
// Code to execute timers etc.
}
My guess is that you think that when you go menuLayer.addChild(myMenu.content) that menuLayer suddenly becomes an instance of menu.swf That is not the case. It becomes a child of menuLayer.
Try this :
menuLayer.addChild(myMenu.content);
var menuInstance:MovieClip = menuLayer.getChildAt(0) as MovieClip;
trace (menuInstance.playBtn);
This code assumes that you have nothing else added to menuLayer and in that case your menu.swf content would be the only child on the display list of menuLayer.
I am also assuming that menu.swf's contents are a MovieClip.
If my assumptions are wrong, this may not work.
I also noticed that you have your menuLoaded method inside your constructor. Not a good idea. Especially since the next line is expecting playBtn to exist and the menu hasn't even been loaded.
Try something like this :
public function Main()
{
addChild(gameLayer);
addChild(endGameLayer);
addChild(menuLayer);
var myMenu:Loader = new Loader();
var url:URLRequest = new URLRequest("Menu.swf");
myMenu.load(url);
myMenu.contentLoaderInfo.addEventListener(Event.COMPLETE, menuLoaded);
}
function menuLoaded(event:Event):void
{
var myMenu:LoaderInfo = event.currentTarget as LoaderInfo;
menuLayer.addChild(myMenu.content);
var menuInstance:MovieClip = menuLayer.getChildAt(0) as MovieClip;
// now you can actually add the listener, because the content is actually loaded
menuInstance.playBtn.addEventListener(MouseEvent.CLICK, startGame);
}
public function startGame(e:Event)
{
// Code to remove the menu (menuLayer.removeChild?)
// Code here to start timers etc
}

How to update children in actionscript?

For starters let me just say that I am very new to action script and also that I'm not using adobe creative suite, I am using notepad with flex as a compiler. I have two classes, a main class and a class called OBJECT_square.
Here is the MAIN class:
package
{
import flash.display.*; import mx.core.*;
import flash.events.*; import mx.collections.*;
import flash.geom.*; import mx.controls.*;
import flash.text.*; import mx.events.*;
import mx.styles.*;
import mx.containers.*;
public class MAIN extends Sprite
{
public var APPLICATION:Application = Application(Application.application);
public var keyDownText:TextField = new TextField();
public function MAIN()
{
stage.addEventListener(KeyboardEvent.KEY_DOWN,KEY_DOWN);
addEventListener(Event.ENTER_FRAME,STEP);
this.addChild(new OBJECT_square().CREATE(10,100,1));
this.addChild(new OBJECT_square().CREATE(10,200,1));
}
public function STEP():void {}
public function DRAW():void {}
public function KEY_DOWN(event:KeyboardEvent):void
{
keyDownText.text = "Key code: " + event.keyCode;
this.addChild(keyDownText);
}
}
}
Here is the OBJECT_square class:
package
{
import flash.display.*;
import flash.events.*;
public class OBJECT_square extends Sprite
{
public var X:int = 0;
public var Y:int = 0;
public var DEPTH:int = 0;
public var SPRITE:Sprite = new Sprite();
public function CREATE(X:int,Y:int,DEPTH:int):Sprite
{
addEventListener(KeyboardEvent.KEY_DOWN,KEY_DOWN);
this.DEPTH = DEPTH;
this.X = X;
this.Y = Y;
DRAW();
return SPRITE;
}
public function KEY_DOWN(event:KeyboardEvent):void
{
if (event.keyCode == 39) {X += 1; DRAW();}
}
public function DRAW():void
{
SPRITE.graphics.beginFill(0xFF0000,1);
SPRITE.graphics.drawRect(X - 10,Y - 10,20,20);
SPRITE.graphics.endFill();
}
}
}
Now my problem is this. Simply put I would like the square that OBJECT_square draws to move right when I press the right arrow key. Right now I can only get it to be drawn once (though I am actually creating two separate squares in two different spots). Now the thing I need to know is if I have used the keyboard event correctly in OBJECT_square. I used keyboard event in the main class as well to display the last key I pressed but I'm not sure how to use it in a class other than the main one. Also I'm not sure how to 'update' the square so that it is redrawn when it moves, that is remove its old self from the display list and reinsert its new self. The whole kinda point to the code is that the square be 'self-sufficient', ie contains all the code needed to draw it and move it rather than relying on any other class. I basically want it so that once another class has made a square the square is capable of doing everything else on its own.
You don't need to keep manually redrawing the square. Sprites have x and y properties that you can change and will automatically be moved. There is also no reason to be creating a sprite inside a class that is already extending sprite. There are a couple of other weird things you are doing so a fixed up version of your class would look something like:
package
{
import flash.display.*;
import flash.events.*;
public class ObjectSquare extends Sprite
{
public function ObjectSquare (x:int,y:int):void
{
graphics.beginFill(0xFF0000,1);
graphics.drawRect(x,y,30,30);
graphics.endFill();
addEventListener(KeyboardEvent.KEY_DOWN,KEY_DOWN);
}
public function KEY_DOWN(event:KeyboardEvent):void
{
if (event.keyCode == 39)
{
x += 1;
}
}
}
}
package
{
import flash.display.*; import mx.core.*;
import flash.events.*; import mx.collections.*;
import flash.geom.*; import mx.controls.*;
import flash.text.*; import mx.events.*;
import mx.styles.*;
import mx.containers.*;
//rename your class to Main. Should not be all caps
public class Main extends Sprite
{
public var APPLICATION:Application = Application(Application.application);
public var keyDownText:TextField = new TextField();
public function Main()
{
stage.addEventListener(KeyboardEvent.KEY_DOWN,onKeyPress);
addChild(new ObjectSquare(10,100));
addChild(new ObjectSquare(10,200));
}
public function onKeyPress(event:KeyboardEvent):void
{
keyDownText.text = "Key code: " + event.keyCode;
this.addChild(keyDownText);
}
}
}
You would probably be better off creating a class to handle all your keyboard inputs and then change the relevant objects.