While sitting, watching and reading about framework, I tried it and cant get my program going.
So when I programmed I had 3 frames. One for pre loader, one for Game (no menu, just straight to game), and one last one for me to keep notes and patch note etc in.
I coded in the frame. I didnt have any extra .as files or nothing, and it all works.
Then I tried converting to having a GameControler.as and a C.as (for constant values etc), and that didn't work.
So I started over, and ended up just trying it out and ended with this code:
package {
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.text.*;
import flash.utils.*;
import flash.ui.*;
import Game.*;
public class GameController extends MovieClip {
private var score: Number;
public function GameController() {
// constructor code
}
public function startGame() {
score = C.score;
stage.addEventListener(Event.ENTER_FRAME, update);
}
public function scoreF(e: MouseEvent):void {
score = score + 1;
}
hitBtn.addEventListener(MouseEvent.CLICK, scoreF)
private function update(e: Event) {
score_n.text = String(score);
}
}
}
I end up with these two errors.
Line 30, Column 3 1120: Access of undefined property hitBtn.
Line 30, Column 45 1120: Access of undefined property scoreF.
What am I not understanding?
I just wanna click the button, witch is on stage, add up the score and update the on stage score.
Even though your question was answered, here is a pattern you might want to follow:
package {
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.text.*;
import flash.utils.*;
import flash.ui.*;
import Game.*;
public class GameController extends MovieClip {
private var hitBtn:MovieClip;
private var score: Number;
public function GameController() {
// constructor code
createChildren();
}
protected function createChildren():void {
// when it was not read from the display list
// or created in a subclass via inheritence
if (!hitBtn) {
hitBtn = getChildByName('hitBtn') as MovieClip;
if (hitBtn) {
hitBtn.addEventListener(MouseEvent.CLICK, scoreF);
} else {
trace('Child #hitBtn is not found or not a MovieClip.').
}
}
}
public function startGame() {
score = C.score;
if (stage) {
stage.addEventListener(Event.ENTER_FRAME, update);
} else {
trace("Attempt to start the game, although the controller is not added to stage.");
}
}
public function scoreF(e: MouseEvent):void {
score = score + 1;
}
private function update(e: Event) {
score_n.text = String(score);
}
}
}
When using Flash to add children, those are added to the MovieClip when it is created, so you can access them right away. Following the pattern will give you more safety when working on larger projects, which sometimes change ... this way you can get very fast an idea of what's wrong.
Related
I have a weird problem in a game which I want to create. At first I have created a project without external classes.
On the root I have three Characters and one Level. Also there is a script for the key listeners and I have eventListeners to register the level, levelElements, coins and the characters. Then I have a CharacterControl MovieClip in the library. This MovieClip contains the character behaviour. As example walk, jump, idle, gravity if not colliding to the ground. There are also different events and eventListeners.
The scripts are on the timeline. If I call in both timelines a trace-function, the root was called before the CharacterController.
After that in my next exercise I created a document class Main. Now there are all root scripts. And for the CharacterController I also copied the timeline code and put it into an external class.
Now my problem is that the CharacterController class is called before the main class gets called. This leads to the problem that the eventListener and events can't get called in right order. There are happening a few errors. No Coin and no Character collides on the ground or a plattform. Everything is falling down.
How can I achieve that the Main gets called at first? Should I remove the characters and create them by script?
EDIT:
Ok, I give a short example which shows the basic problem without the complex code of my game.
package {
import flash.display.MovieClip;
public class Main extends MovieClip {
public function Main() {
trace("main was called");
}
}
}
package {
import flash.display.MovieClip;
public class My_Circle extends MovieClip {
public function My_Circle() {
// constructor code
trace("circle was called");
}
}
}
Here are some pictures of the configuration and structure of my project:
I need Main called as first. I think it's a basic problem in as3.
You'd make the class file of your stage Main.as in the properties pane.
Edit: Interesting. Just replicated this. I believe then that flash/air constructs elements so they're ready to be put on the stage instead of constructing the stage first and elements after. You should put the code you want to execute for your circle in some sort of init function and execute it in.
package
{
import flash.display.MovieClip;
public class Main extends MovieClip
{
public function Main()
{
super();
trace("Hello");
(circle_mc as Circle).init();
}
}
}
Circle:
package
{
import flash.display.MovieClip;
public class Circle extends MovieClip
{
public function Circle()
{
super();
}
public function init():void
{
trace("World");
}
}
}
ok, I figured out a simple solution how you can make it by code. At first I think it's a better solution to create the object (circle, character, whatever) by code.
The timeline code:
import flash.events.Event;
Main.setStageRef(this.stage); //Super-important
stop();
The Main class code:
package {
import flash.display.MovieClip;
import flash.display.Stage;
import flash.display.DisplayObject;
import flash.events.Event;
public class Main extends MovieClip {
public static var stageRef : Object = null;
var movieClipExample : My_Circle;
public function Main() {
this.addEventListener(Event.ENTER_FRAME,this.afterMainTimeLine);
stage.addEventListener("myEvent", myEventFunction);
}
public function afterMainTimeLine(e:Event) {
trace("Hello");
movieClipExample = new My_Circle;
movieClipExample.init();
stageRef.addChild(movieClipExample);
removeEventListener(Event.ENTER_FRAME, this.afterMainTimeLine);
this.addEventListener(Event.ENTER_FRAME,this.updateFunction);
}
public function updateFunction(e:Event){
movieClipExample.moveFunction();
}
public function myEventFunction(_event: Event) {
trace("myEvent was triggered");
}
//Getter/setter for stage
public static function setStageRef(_stage : Object) : void
{
stageRef = _stage;
}
public static function getStageRef() : Object
{
return stageRef;
}
}
}
The Object code (as example My_Circle):
package {
import flash.display.MovieClip;
import flash.display.Stage;
import flash.display.DisplayObject;
public class My_Circle extends MovieClip {
public function My_Circle()
{
stageRef = Main.getStageRef();
trace("World");
this.x = x;
this.y = y;
var evt = new Event("myEvent", true);
stageRef.dispatchEvent(evt);
}
public function init():void
{
trace("Created Circle");
this.x = 300;
this.y = 100;
}
function moveFunction(){
this.y += 1;
}
}
}
The output is following:
Hello
World
myEvent was triggered
Created Circle
Maybe this could be helpful for others.
Just one thing. For different objects from the same class it's better to use an array. The position (maybe) should be random.
This is extremely basic, but to help me understand could someone please explain why this doesn't work. Trying to call a function from one as file to another, and get the following error.
Error: Error #2136: The SWF file file:///test/Main.swf contains invalid data.
at code::Main()[C:\Users\Luke\Desktop\test\code\Main.as:12]
Error opening URL 'file:///test/Main.swf'
Main.as
package code {
import flash.display.MovieClip;
import flash.events.*;
import code.Enemy;
public class Main extends MovieClip
{
public function Main()
{
var enemy:Enemy = new Enemy();
}
public function test():void
{
trace("Test");
}
}
}
Enemy.as
package code {
import flash.display.MovieClip;
import flash.events.*;
import code.Main;
public class Enemy extends Main {
public function Enemy() {
var main:Main = new Main();
main.test();
}
}
}
Assuming Main is your document class, you can't instantiate it. That might explain the SWF invalid data error.
What it looks like you are trying to do is access a function on Main from your Enemy. To do that you just need a reference to Main from inside your Enemy class. If you add the Enemy instance to the display list you can probably use root or parent to get a reference to Main. You could also pass a reference to Main through the constructor of your Enemy class:
public class Main {
public function Main() {
new Enemy(this);
}
public function test():void {
trace("test");
}
}
public class Enemy {
public function Enemy(main:Main) {
main.test();
}
}
From the constructor of the class Main you are creating the Object of Enemy. In the constructor of Enemy you are creating the Object of Main. Hence it continues to create those two objects until there is Stack overflow. It never reaches to the line where you have main.test();
if you wana get data frome main.as you can use the static var.
package {
import flash.display.MovieClip;
public class Main extends MovieClip {
// i well get this var in my Enemy as.
public var i:uint=1021;
public function txtuto() {
// constructor code
}
}
}`
// the Enemy.as
`package {
import flash.display.MovieClip;
public class Enemy extends MovieClip {
public static var tx:Main = new Main;
public function Enemy() {
trace(tx.i);
}
}
}
good luck.
I a document class (Main) and a class connected to a symbol (MainMenu), and I get an error I just can't figure how to solve.. I get this error:
1136: Incorrect number of arguments. Expected 1.
it is reffering to "public var mainMenu = new MainMenu();" in my document class.
Anyways, here are my classes:
Main(document class):
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.display.Stage;
public class Main extends MovieClip {
public var mainMenu = new MainMenu();
public function Main() {
// constructor code
startGame();
}
public function startGame(){
addChild(mainMenu);
}
public function initGame(event){
//Adding player and such..
}
}
}
MainMenu:
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class MainMenu extends MovieClip {
private var logo = new Logo();
public function MainMenu(main:Main) {
// constructor code
mainMenu = new MainMenu(this);
logo.addEventListener(MouseEvent.CLICK, main.initGame);
placeButtons(event);
}
public function placeButtons(event:Event){
logo.addEventListener(MouseEvent.CLICK, initGame);
logo.x = - logo.width/2;
logo.y = 50;
addChild(logo);
trace ("MainMenu added");
}
}
}
Thanks
A few pointers...
Be mindful of your indentation.
Datatype your variables, arguments, and function returns.
Your MainMenu class was self instantiating itself (that's an infinite loop)
If you really need direct access to another classes function, consider making the child class extend the parent class. Alternatively, you could make the specific function a static function and call the function directly off the class without passing variable references. For example: Main.initGame()
Here are your classes, with a potential solution...
Main:
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.display.Stage;
public class Main extends MovieClip {
public var mainMenu:MainMenu;
public function Main() {
mainMenu = new MainMenu();
addChild(mainMenu);
}
public function initGame(e:Event):void {
//Adding player and such..
}
}
}
MainMenu:
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class MainMenu extends MovieClip {
private var logo:Logo;
public function MainMenu() {
// Wait for it to be added to the parent.
logo = new Logo();
addChild(logo);
addEventListener(Event.ADDED_TO_STAGE, placeButton);
}
private function placeButton(e:Event):void {
// We only need this to happen once, so remove the listener
removeEventListener(Event.ADDED_TO_STAGE, placeButton);
// Now that we've formed the connection, we can reference the function dynamically
logo.addEventListener(MouseEvent.CLICK, this["parent"].initGame);
logo.x = - logo.width/2;
logo.y = 50;
}
}
}
I've left the structure as similar to your original intent as possible, but the above function reference is poor form. As a general rule, children should not have connections to their parents as it's a potential memory leak. You might instead add the event listener from your Main class.
I have the problem with Actionscript 3.0 in Adobe Flash. I can't run "gotoAndStop" from a class (not document class).
With the help of the Internet I tried several things, but none of them worked:
1)
MovieClip(root).gotoAndStop(3);
2)
package
{
import flash.display.MovieClip;
public class CustomClassName extends MovieClip
{
public static var mainTimeline:MovieClip;
public function CustomClassName()
{
// constructor code
}
}
}
3)
public class np extends SimpleButton {
var _root:MovieClip;
public function np() {
this.addEventListener(Event.ADDED_TO_STAGE,init);
this.addEventListener(MouseEvent.CLICK,nextF);
}
private function init(e:Event):void{
_root = MovieClip(this.root);
}
private function nextF(e:MouseEvent):void{
_root.addEventListener(Event.RENDER,renderF);
stage.invalidate();
_root.nextScene();
}
private function renderF(e:Event):void {
_root.gotoAndStop(5);
}
}
I have these imports:
import flash.display.MovieClip;
import flash.display.Graphics;
import flash.display.Stage;
import flash.events.Event;
And if I run these lines of code:
trace('frame:',currentFrame);
super(this).gotoAndPlay(2);
trace('frame:',currentFrame);
... I get 0 as currentFrame as a result.
I have a class where I want to run gotoAndStop(2).
And in my .fla file I have these in the first frame:
stop();
import Buzzer.*;
var buzzerClip:Buzzer = new Buzzer();
stage.addChild(buzzerClip);
But the code doesn't run the gotoAndStop function. And actually no error will be returned. Does someone has another idea?
The property root is null until the display object has been added to the display list.
So to adjust your first attempt:
public function MyDisplayObject()
{
init();
}
private function init():void
{
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
private function addedToStageHandler()
{
MovieClip(root).gotoAndStop(3);
}
please note that I am a novice when it comes to Actionscript 3 and lot of what I could do with reasonable competency in AS2 I now can't in AS3, to my frustration! OK, I'm fleshing out a simple drag drop and decorate application in Flash. I'm wanting to use the external action script class/package to allow for it full screen from my desktop and I'm in a tangle, with constructor errors being thrown up and all sorts. Could anyone give any pointers?
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.display.Stage;
import flash.display.StageDisplayState;
public class fullmode extends MovieClip {
public function fullmode() {
fullbtn.addEventListener(MouseEvent.CLICK, fullScreen);
}// btn declared - - - - - - - -
//public function fullmode(event:MouseEvent):void {
stage.displayState=StageDisplayState.FULL_SCREEN;
}
}
//--------------------- drag item
public class DragDrop extends MovieClip {
public function DragDrop() {
dragme.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
dragme.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
}
private function mouseDownHandler(evt:MouseEvent):void {
var obj = evt.target;
obj.startDrag();
}
private function mouseUpHandler(evt:MouseEvent):void {
var obj = evt.target;
obj.stopDrag();
}
}
}
Thanks world!
You had a few syntax errors/typos, I've fixed them below:
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.display.Stage;
import flash.display.StageDisplayState;
public class Fullmode extends MovieClip
{
public function Fullmode()
{
fullbtn.addEventListener(MouseEvent.CLICK, fullScreen);
}
private function fullScreen(event:MouseEvent):void
{
stage.displayState = StageDisplayState.FULL_SCREEN;
}
}
}
Standard practice dictates that your class names should be capitalized, hence Fullmode instead of fullmode.
Additionally, you had named your MouseEvent.CLICK listener the same as your class, instead of what you intended to name it.