Showing main menu over objects / movieclips? - actionscript-3

I am creating a game in Flash and I am creating a main menu for the game (With buttons like 'Play', 'How to Play', 'Hiscores' etc.) and was wondering what is the best way to go about it?
All of my Actionscript code is in external .as files and I've used classes throughout but I was having trouble figuring out how to get it so that the menu will be shown as soon as the game is ran. The main problem is that there are timers in my game that have event handlers attached to them and I was trying to think of the best way to essentially stop these timers until the user actually clicks 'Play', otherwise the objects spawn over the top of the menu and the timer ticks down.
Would stopping the timers but then adding an event handler to the play button to start the timers be a good idea? I am trying to figure out the best way to do this for future reference.
Thank you for any assistance.
Edit: Tried Cherniv's advice, getting some errors.
Main.as:
package {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.DisplayObject;
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;
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 var crosshair:crosshair_mc;
static var score:Number;
var enemyShipTimer:Timer;
var enemyShipTimerMed:Timer;
var enemyShipTimerSmall:Timer;
static var scoreHeader:TextField = new TextField();
static var scoreText:TextField = new TextField();
static var timeHeader:TextField = new TextField();
static var timeText:TextField = new TextField();
public function Main()
{
var mainMenu:myMenu = new myMenu;
addChild(gameLayer);
addChild(endGameLayer);
addChild(menuLayer);
playBtn.addEventListener(MouseEvent.CLICK, startButtonPressed);
}
function startButtonPressed(e:Event)
{
levelDuration = 30;
gameTime = levelDuration;
var gameTimer:Timer = new Timer(1000,levelDuration);
gameTimer.addEventListener(TimerEvent.TIMER, updateTime);
gameTimer.addEventListener(TimerEvent.TIMER_COMPLETE, timeExpired)
gameTimer.start();
scoreHeader = new TextField();
scoreHeader.x = 5;
scoreHeader.text = String("Score: ");
gameLayer.addChild(scoreHeader);
scoreText = new TextField();
scoreText.x = 75;
scoreText.y = 0;
scoreText.text = String(0);
gameLayer.addChild(scoreText);
timeHeader = new TextField();
timeHeader.x = 490;
timeHeader.y = 0;
timeHeader.text = String("Time: ");
gameLayer.addChild(timeHeader);
timeText = new TextField();
timeText.x = 550;
timeText.y = 0;
timeText.text = gameTime.toString();
gameLayer.addChild(timeText);
var scoreFormat = new TextFormat("Arial Rounded MT Bold", 20, 0xFFFFFF);
scoreHeader.setTextFormat(scoreFormat);
scoreText.setTextFormat(scoreFormat);
timeHeader.setTextFormat(scoreFormat);
timeText.setTextFormat(scoreFormat);
enemyShipTimer = new Timer(2000);
enemyShipTimer.addEventListener("timer", sendEnemy);
enemyShipTimer.start();
enemyShipTimerMed = new Timer(2500);
enemyShipTimerMed.addEventListener("timer", sendEnemyMed);
enemyShipTimerMed.start();
enemyShipTimerSmall = new Timer(2750);
enemyShipTimerSmall.addEventListener("timer", sendEnemySmall);
enemyShipTimerSmall.start();
crosshair = new crosshair_mc();
gameLayer.addChild(crosshair);
crosshair.mouseEnabled = crosshair.mouseChildren = false;
Mouse.hide();
gameLayer.addEventListener(Event.ENTER_FRAME, moveCursor);
resetScore();
}
function sendEnemy(e:Event)
{
var enemy = new EnemyShip();
gameLayer.addChild(enemy);
gameLayer.addChild(crosshair);
}
function sendEnemyMed(e:Event)
{
var enemymed = new EnemyShipMed();
gameLayer.addChild(enemymed);
gameLayer.addChild(crosshair);
}
function sendEnemySmall(e:Event)
{
var enemysmall = new EnemyShipSmall();
gameLayer.addChild(enemysmall);
gameLayer.addChild(crosshair);
}
static function updateScore(points)
{
score += points;
scoreText.text = String(score);
var scoreFormat = new TextFormat("Arial Rounded MT Bold", 20, 0xFFFFFF);
scoreHeader.setTextFormat(scoreFormat);
scoreText.setTextFormat(scoreFormat);
}
static function resetScore()
{
score = 0;
scoreText.text = String(score);
}
function updateTime(e:TimerEvent):void
{
trace(gameTime);
// your class variable tracking each second,
gameTime--;
//update your user interface as needed
var scoreFormat = new TextFormat("Arial Rounded MT Bold", 20, 0xFFFFFF);
timeText.defaultTextFormat = scoreFormat;
timeText.text = String(gameTime);
}
function timeExpired(e:TimerEvent):void
{
var gameTimer:Timer = e.target as Timer;
gameTimer.removeEventListener(TimerEvent.TIMER, updateTime)
gameTimer.removeEventListener(TimerEvent.TIMER, timeExpired)
// do whatever you need to do for game over
}
function moveCursor(event:Event)
{
crosshair.x=mouseX;
crosshair.y=mouseY;
}
}
}
Menu.as:
package {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.DisplayObject;
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;
public class Menu extends MovieClip
{
var mainMenu:Menu = new Menu();
Main.menuLayer.addChild(myMenu);
playBtn.addEventListener(MouseEvent.CLICK, playBtnPressed);
function playBtnPressed()
{
Main.menuLayer.removeChild(myMenu);
dispatchEvent(new Event("playButtonPressed"))
}
}
My menu is a movieclip named myMenu and the class is set as Menu but I get errors such as:
Main.as, Line 50 1120: Access of undefined property playBtn
I gave the button an instance name of playBtn before I converted the menu to a movieclip so not sure what's going on there. I'm probably missing something really easy but it's a bit confusing for me after typing all day.

If you have all of your initialization stuff (including timers initializations) in Main constructor function , so you need to split it to two functions , Main constructor will show the menu , and "start" button will fire the second function , that will include all the initialization stuff

Related

My AS3 game won't go to full screen

I'm making an AS3 platform game. I don't know why but it won't go to full screen...
Here's my code :
package {
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.utils.getTimer;
import flash.display.StageScaleMode;
import flash.events.MouseEvent;
public class PlatformGame extends MovieClip {
// movement constants
static const gravity:Number = .004;
// screen constants
static const edgeDistance:Number = 100;
// object arrays
private var fixedObjects:Array;
private var otherObjects:Array;
// hero and enemies
private var hero:Object;
private var enemies:Array;
// game state
private var playerObjects:Array;
private var gameScore:int;
private var gameMode:String = "start";
private var playerLives:int;
private var lastTime:Number = 0;
// start game
public function startPlatformGame() {
addEventListener(Event.ADDED_TO_STAGE, startGame);
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
playerObjects = new Array();
gameScore = 0;
gameMode = "play";
playerLives = 3;
}
Do you know what could be the problem ? (I've just put the begining if my code, if you think it's necessary that I put all my code, don't hesitate to tell me)
Read this Adobe documentation:
http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS2E9C7F3B-6A7C-4c5d-8ADD-5B23446FBEEB.html

Text doesn't appear in MovieClip after added as child. What's wrong with my ActionScript 3?

I'm pulling data from external XML. i created a sprite to serve as container for my pages. Those pages are movieclips which i then add each of them to stage as child to container using a for loop. For each movieclip i will add text & images which i will then animate using greensock. but the problem now is a simple text wont appear when i export swf movie. i have no problems loading external xml files and what not. i dont believe this to be a xml or loader problem. where did i go wrong? :~( .I believe i imported all the necessary package too.
import flash.events.*;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.text.*;
import flash.text.TextFieldAutoSize;
import flash.media.Sound;
import flash.media.SoundTransform;
import flash.media.SoundChannel;
import flash.net.navigateToURL;
import flash.display.*;
import flash.text.TextFormat;
import flash.display.StageScaleMode;
import flash.display.Stage;
public class menu extends Sprite {
protected var container:Sprite = new Sprite();
public function buildPages(e:Event):void {
var menu:XML=new XML(e.target.data);
menu.ignoreWhitespace=true;
container.x = menu.config.frxpos;
container.y = menu.config.frypos;
addChild(container);
var i:Number;
totalPages = menu.pages.page.length();
for(i=0; i<totalPages; i++) {
var pageMc:MovieClip = new MovieClip();
pageMc.name = menu.pages.page[i].#name;
pageMc.id = menu.pages.layoutNum.layNum[i];
container.addChild(pageMc);
pageMc.x = 100;
pageMc.y = 100;
pageMc.width = 200;
pageMc.height = 200;
pageNames[i] = pageMc.name;
pageLayoutNo[i] = pageMc.id;
if(pageMc.name == "registration") {
var myTxt:TextField = new TextField();
myTxt.text = menu.pages.intro.htext;
myTxt.textColor = 0xff0000;
myTxt.x = 150;
myTxt.y = 150;
myTxt.border = true;
myTxt.borderColor = 0x747474;
pageMc.addChild(myTxt);
}
}
}
}

Problems with STAGE

I am pretty new to as3 programming. This forum helped me already a lot, but now I have a problem where I don't know how to get on. So this is my first Post on stack overflow.com.
I need StageWebView for displaying a PDF-document. After several hours, I was successful. I created the code in a new blank document and tested it step by step.
This is my code:
import flash.display.MovieClip;
import flash.media.StageWebView;
import flash.geom.Rectangle;
import flash.filesystem.File;
import flash.display.Sprite;
import flash.display.Stage;
public function StageWebViewExample(pdfdoc:String, xpos:Number, ypos:Number, breite:Number, hoehe:Number)
{
var webView:StageWebView = new StageWebView();
webView.stage = this.stage; //PROBLEM LINE
webView.viewPort = new Rectangle (xpos, ypos, breite, hoehe);
var file:String = pdfdoc;
var pdf:File = File.applicationDirectory.resolvePath(file);
webView.loadURL(pdf.nativePath);
}
StageWebViewExample("test.pdf", 200, 200, 600, 1200);
After testing, I copied the code in my existing flash-document. (The code in a several as-File and the "calling" (StageWebViewExample("....) in the existing flash-document...)
But now the code does't work anymore and there are the following Errors:
- 1119 Access of possibly undefined property stage...
- 1059 Property is read-only.
--> Both Errors referring to the same line I marked in the Code.
Has anyone an idea why it don't work?
I would really appreciate a good hint!
Answer for question is your actions ;) You moved code from the Document Class, in another one, that don't have access to the stage as instance property. I mean this.stage.
Pass Stage also to the method StageWebViewExample, function signature will look like:
public function stageWebViewExample(stage: Stage, pdfdoc:String, xpos:Number, ypos:Number, breite:Number, hoehe:Number):void {
var webView:StageWebView = new StageWebView();
webView.stage = stage;
webView.viewPort = new Rectangle (xpos, ypos, breite, hoehe);
var file:String = pdfdoc;
var pdf:File = File.applicationDirectory.resolvePath(file);
webView.loadURL(pdf.nativePath);
}
Working AIR example:
package {
import flash.display.Sprite;
import flash.display.Stage;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Rectangle;
import flash.media.StageWebView;
public class StackOverflow extends Sprite {
public function StackOverflow() {
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
private function onAdded(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, onAdded);
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
start();
}
private function start():void {
showWebViewAt(this.stage, "http://www.iab.net/media/file/VASTv3.0.pdf", new Rectangle(0, 0, stage.stageWidth * 0.5, stage.stageHeight));
}
private function showWebViewAt(stage:Stage, path:String, frame:Rectangle):void {
var webView:StageWebView = new StageWebView();
webView.stage = stage;
webView.viewPort = frame;
webView.loadURL(path);
}
}
}

ActionScript 3: Zoom functions - drag does not show

I've included a zoom functionality similar to the one explained at this website: http://www.flashandmath.com/howtos/zoom/
Even though it does indeed work in terms of the possibility of moving the image on my stage, the drag-animation is not present, meaning there will be no "movement" of my image, just a sudden change in position.
The problem followed my attempt to change the concept from timeline-based to class-based.
Here is my Main class:
package
{
import flash.display.MovieClip;
import flash.utils.Dictionary;
import flash.display.Shape;
import fl.transitions.Fly;
import fl.motion.MatrixTransformer;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.ui.Mouse;
public class Main extends Sprite
{
public static var scale:Number = 1;
private var _rootMC:MovieClip;
// ------------------------------
public var bg_image:Sprite;
public var spImage:Sprite;
public var mat:Matrix;
public var mcIn:MovieClip;
public var mcOut:MovieClip;
public var boardWidth:int = 980;
public var boardHeight:int = 661;
public var boardMask:Shape;
public var externalCenter:Point;
public var internalCenter:Point;
public static var scaleFactor:Number = 0.8;
public static var minScale:Number = 0.25;
public static var maxScale:Number = 10.0;
//-------------------------------
public function Main(rootMC:MovieClip)
{
_rootMC = rootMC;
bg_image = new image();
this.graphics.beginFill(0xB6DCF4);
this.graphics.drawRect(0,0,boardWidth,boardHeight);
this.graphics.endFill();
spImage = new Sprite();
this.addChild(spImage);
boardMask = new Shape();
boardMask.graphics.beginFill(0xDDDDDD);
boardMask.graphics.drawRect(0,0,boardWidth,boardHeight);
boardMask.graphics.endFill();
boardMask.x = 0;
boardMask.y = 0;
this.addChild(boardMask);
spImage.mask = boardMask;
minScale = boardWidth / bg_image.width;
mcIn = new InCursorClip();
mcOut = new OutCursorClip();
bg_image.addChild(mcIn);
bg_image.addChild(mcOut);
bg_image.scaleX = minScale;
bg_image.scaleY = minScale;
spImage.addChild(bg_image);
spImage.addChild(mcIn);
spImage.addChild(mcOut);
spImage.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
_rootMC.stage.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
spImage.addEventListener(MouseEvent.CLICK, zoom);
_rootMC.stage.addEventListener(KeyboardEvent.KEY_DOWN, keyHandler);
_rootMC.stage.addEventListener(KeyboardEvent.KEY_UP, keyHandler);
}
private function startDragging(mev:MouseEvent):void
{
spImage.startDrag();
}
private function stopDragging(mev:MouseEvent):void
{
spImage.stopDrag();
}
private function zoom(mev:MouseEvent):void
{
if ((!mev.shiftKey)&&(!mev.ctrlKey))
{
return;
}
if ((mev.shiftKey)&&(mev.ctrlKey))
{
return;
}
externalCenter = new Point(spImage.mouseX,spImage.mouseY);
internalCenter = new Point(bg_image.mouseX,bg_image.mouseY);
if (mev.shiftKey)
{
bg_image.scaleX = Math.max(scaleFactor*bg_image.scaleX, minScale);
bg_image.scaleY = Math.max(scaleFactor*bg_image.scaleY, minScale);
}
if (mev.ctrlKey)
{
bg_image.scaleX = Math.min(1/scaleFactor*bg_image.scaleX, maxScale);
bg_image.scaleY = Math.min(1/scaleFactor*bg_image.scaleY, maxScale);
}
mat = this.transform.matrix.clone();
MatrixTransformer.matchInternalPointWithExternal(mat,internalCenter,externalCenter);
bg_image.transform.matrix = mat;
}
private function keyHandler(ke:KeyboardEvent):void
{
mcIn.x = spImage.mouseX;
mcIn.y = spImage.mouseY;
mcOut.x = spImage.mouseX;
mcOut.y = spImage.mouseY;
mcIn.visible = ke.ctrlKey;
mcOut.visible = ke.shiftKey;
if (ke.ctrlKey || ke.shiftKey)
{
Mouse.hide();
}
else
{
Mouse.show();
}
}
}
}
Here is my image class:
package {
import fl.motion.MatrixTransformer;
import flash.display.MovieClip;
import flash.utils.Dictionary;
import flash.display.Shape;
import fl.transitions.Fly;
import fl.motion.MatrixTransformer;
import flash.events.MouseEvent;
public class image extends MovieClip
{
public function image()
{
this.width = 980
this.height = 500
this.y = 0
this.x = 0
}
}
I know this is a lot of code, but I am really stuck :(
On your MOUSE_DOWN handler, you need to start listening to the MOUSE_MOVE event.
On your MOUSE_UP handler, you need to stop listening to the MOUSE_MOVE event.
Not sure if you are already doing this.
In your MOUSE_MOVE event handler, you need to update the x / y positions of the image, in a similar way to what you are probably doing on the MOUSE_UP handler.

Alternative way to rearrange objects on a stage?

I want my menu to appear above everything else when my game opens but at the minute, the menu is on top at first until my timer starts then all of the other objects appear over the top of the menu. How can I change it so that the menu is on top and the game only starts playing and the timer only starts once the user clicks the 'Play' button and it takes them to the game?
Here is the code I have in my Main.as file. I have been experimenting to no avail as I have tried to figure out the easiest or most efficient way to do this, but I am so frustrated with it at the minute:
package {
import flash.display.MovieClip;
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;
public class Main extends MovieClip {
public var gameTime:int;
public var levelDuration:int;
public var crosshair:crosshair_mc;
static var score:Number;
var enemyShipTimer:Timer;
var enemyShipTimerMed:Timer;
var enemyShipTimerSmall:Timer;
var menu:menuMain = new menuMain;
static var scoreHeader:TextField = new TextField();
static var scoreText:TextField = new TextField();
static var timeHeader:TextField = new TextField();
static var timeText:TextField = new TextField();
public function Main()
{
levelDuration = 30;
gameTime = levelDuration;
var gameTimer:Timer = new Timer(1000,levelDuration);
gameTimer.addEventListener(TimerEvent.TIMER, updateTime);
gameTimer.addEventListener(TimerEvent.TIMER_COMPLETE, timeExpired)
gameTimer.start();
scoreHeader = new TextField();
scoreHeader.x = 5;
scoreHeader.text = String("Score: ");
addChild(scoreHeader);
scoreText = new TextField();
scoreText.x = 75;
scoreText.y = 0;
scoreText.text = String(0);
addChild(scoreText);
timeHeader = new TextField();
timeHeader.x = 490;
timeHeader.y = 0;
timeHeader.text = String("Time: ");
addChild(timeHeader);
timeText = new TextField();
timeText.x = 550;
timeText.y = 0;
timeText.text = gameTime.toString();
addChild(timeText);
var scoreFormat = new TextFormat("Arial Rounded MT Bold", 20, 0xFFFFFF);
scoreHeader.setTextFormat(scoreFormat);
scoreText.setTextFormat(scoreFormat);
timeHeader.setTextFormat(scoreFormat);
timeText.setTextFormat(scoreFormat);
enemyShipTimer = new Timer(2000);
enemyShipTimer.addEventListener("timer", sendEnemy);
enemyShipTimer.start();
enemyShipTimerMed = new Timer(2500);
enemyShipTimerMed.addEventListener("timer", sendEnemyMed);
enemyShipTimerMed.start();
enemyShipTimerSmall = new Timer(2750);
enemyShipTimerSmall.addEventListener("timer", sendEnemySmall);
enemyShipTimerSmall.start();
crosshair = new crosshair_mc();
addChild(crosshair);
crosshair.mouseEnabled = crosshair.mouseChildren = false;
Mouse.hide();
stage.addEventListener(Event.ENTER_FRAME, moveCursor);
resetScore();
showMenu();
}
function showMenu()
{
stage.addChild(menu);
Mouse.show();
enemyShipTimer.stop();
enemyShipTimerMed.stop();
enemyShipTimerSmall.stop();
}
function sendEnemy(e:Event)
{
var enemy = new EnemyShip();
stage.addChild(enemy);
stage.addChild(crosshair);
}
function sendEnemyMed(e:Event)
{
var enemymed = new EnemyShipMed();
stage.addChild(enemymed);
stage.addChild(crosshair);
}
function sendEnemySmall(e:Event)
{
var enemysmall = new EnemyShipSmall();
stage.addChild(enemysmall);
stage.addChild(crosshair);
}
static function updateScore(points)
{
score += points;
scoreText.text = String(score);
var scoreFormat = new TextFormat("Arial Rounded MT Bold", 20, 0xFFFFFF);
scoreHeader.setTextFormat(scoreFormat);
scoreText.setTextFormat(scoreFormat);
}
static function resetScore()
{
score = 0;
scoreText.text = String(score);
}
function updateTime(e:TimerEvent):void
{
trace(gameTime);
// your class variable tracking each second,
gameTime--;
//update your user interface as needed
var scoreFormat = new TextFormat("Arial Rounded MT Bold", 20, 0xFFFFFF);
timeText.defaultTextFormat = scoreFormat;
timeText.text = String(gameTime);
}
function timeExpired(e:TimerEvent):void
{
var gameTimer:Timer = e.target as Timer;
gameTimer.removeEventListener(TimerEvent.TIMER, updateTime)
gameTimer.removeEventListener(TimerEvent.TIMER, timeExpired)
// do whatever you need to do for game over
}
function moveCursor(event:Event)
{
crosshair.x=mouseX;
crosshair.y=mouseY;
}
}
}
I have been trying to figure it out most of the day but I don't have a lot of experience with Actionscript.
Create two containers (Sprites or MovieClips), add the one that you want to be in the back first, and the one you want to be in the front second. Now, add the menu to the front one and evrything else to the back one.