Error with hitTestObject - actionscript-3

I am trying to make a game similar to the world's hardest game, but I have trouble with the hitTestObject block. This is my code for the enemy mi:
package {
import flash.display.MovieClip;
import flash.events.Event;
public class enemys extends MovieClip {
public function enemys() {
stage.addEventListener(Event.ENTER_FRAME, hittrue)
}
public function hittrue(event:Event) {
if (this.hitTestObject(?)) {
while (numChildren > 0) {
removeChildAt(0)
}
gotoAndStop(2)
}
}
}
}
I don't know what to put into the question mark. When I put the instance name of my player, it says that it is undefined.

You're getting an error because enemys (sic) doesn't appear to have access to any sort of player instance.
You should move the hit testing out of the enemys class to somewhere you have access to both enemys and the instance of player. A good place for this would be some kind of GameEngine class.

How do you put the instance name of player? Do you pass the instance through the constructor?
From you main class you need to send a instance of your player to the enemys class.
(by the way plural for enemy is enemies)
public class Enemies extends Sprite{
private var player:PlayerClass;
public function Enemies(p:PlayerClass) {
stage.addEventListener(Event.ENTER_FRAME, hittrue);
player = p;
}
Then in you can put 'player' where the ? is. And in yout main class you would have something like:
var enemies:Enemies = new Enemies(player);
I changed MovieClip to Sprite. This is your choice but it is sometimes better to use Sprites because it will be faster then MovieClip. You may want to look into them especially if you are going to have multiple enemies on the stage at a time.
Another thing is the design of you ENTER_FRAME event.
You do not want multiple Enter_Frame events going on in multiple classes. A good design is to have one in your main class. Then from classes that need a clock cycle, call update methods on these objects in the main class's ENTER_FRAME event.
so in your main class's ENTER_FRAME event you would call:
enemies.hittrue();
Instead of having an EnterFrame event in you enemies class. This will also make it much easier to pause your game.
And as The other answer suggests. Your Collision detection should really be outside of your Enemies Class. But, this is how you would pass a reference of you player to another class.

Related

Referencing a object that is on the stage inside a class?

So I had the issue with ENTER FRAME so I moved it to a separate class and this is what the class looks like
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.accessibility.Accessibility;
import flash.display.DisplayObject;
import flash.display.Stage;
public class enemy extends MovieClip {
public function enemy() {
// constructor code
this.addEventListener(Event.ENTER_FRAME, moveEnemy);
}
public function moveEnemy(e:Event):void{
this.x += 5;
if(stage.player.scaleX == 1){
this.scaleX = 1;
}else {
this.scaleX = -1;
}
}
}
}
Now Im trying to adjust the enemies scalex according to the players but I get a error when referencing the player inside the class can anyone help me solve this?
The trick with using Event.ENTER_FRAME listener is that event.currentTarget will hold the link to the object that's processing the event, event.target will hold the link to the object that's received it first, so you can attach the listener not to the stage, but to the MovieClip of your choice, including having more than a single listener across your game. Say, you give your Enemy class a listener that's making it query stage's list of player's bullets and check collisiong against this, a player can do this too. Or, you use a single listener and do ALL the work inside it, using local arrays to store lists of enemies, bullets, player(s) and other objects.
In terms of passing parameter to enter frame listener - your event is automatically dispatched, so you shouldn't bother with this, and it does not accept more than one parameter.
Regarding your code, you should add enemy movement code in testPlayerCollisions() listener below querying for player collision. For this, you already have an enemy you're about to move, so you just have to call its move() function or whatever you have for it.
It looks like your enemy class doesn't have access to the stage; yet you're trying to reference stage.player. You can access the stage from your main class but not from other classes unless you pass it through the constructor.
Try passing the stage to the enemy class and create a class variable to store it. Ie:
private var stageInst:Stage;
public function enemy(s:Stage){
stageInst = s;
}
Then in moveEnemy use stageInst.player to access the player's clip.
When you create enemy's you'll have to pass in an instance of the stage from Main.
ie: var e:enemy = new enemy(stage);

Game stucture design

Ok. I have a question about AS3 game structure. How to structure simple shooter game.
I have a main Hero and ships that shoot bulets. I want to add two levels but I am not sure how to structure them properly or which way is properly.
I have main class that holds everything and should switch trough levels. So I separate each level as a separate class.
Sample code
package
{
// imports
public class Main extends Sprite
{
// properties
private var testLevel:Level1;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
testLevel = new Level1();
addChild(testLevel);
}
}
}
// Level1 code
package Levels
{
// imports
public class Level1 extends Sprite
{
// properties
private var ship:Ship;
public function Level1(stage:Object)
{
// do some stuff
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
public function onEnterFrame(e:Event):void
{
// do some stuff
}
}
}
So According to this code my question is: Should I add ship bullets using separate ENTER_FRAME function inside Ship or should I add them in the level loop?
I can do both ways but which is better for performance and for mintenance, because I plan to add some actions when the bulet reaches the end of the sceen or when hits the Hero.
This is a though compromise:
For performance is better to have one single ENTER_FRAME listener.
But for maintenance it should be better to have separate update functions inside the Ship class and inside each object (for example, Enemy class, Bullet class etc) in the game.
So usually the preferred method to deal with this and get the best of both options is to have one main ENTER_FRAME listener on your main class, which is usually referred to as the Main Game Loop. This should be the only ENTER_FRAME listener running in the game. From this Game Loop you should invoke an update function for each object currently in the game, which is the responsible for updating the object's position, status, etc inside the game.
From my opinion - make a level engine and describe a level with xml instead of createing a class for each level.
Make a shoot engine that holds a bulletes and update tham. Make a collision enginge to check the colisions.
A good example is code of Waste Invaders. link
Check src / com / shooty / engine code this will help you a lot.

Pan class in Flash AS3

I have a movieclip and I am going to add a pan feature to it. I want to add the pan as it's own class that the movieclip can reference.
When I create the pan class, I send the movieclip to it so I have it's position properties at all times.
What is the best way to access the stage in the pan class? I will need to be able to get the stage mouseX, mouseY, stageWidth, and stageHeight.
Right now, I have the pan class extend a sprite object and actually add it as a child of the movieclip I want to pan.
Would it be better to just send the stage itself into the pan class as well or is there a better way than this?
Create a singleton class that manages changes to the stage called StageManager and initialize it by passing it a reference to the stage:
//StageManager.as
import flash.display.Stage;
public class StageManager()
{
//publicly accessible singleton instance
public static var instance:StageManager = new StageManager();
private var m_stage:Stage;
//I'm using a custom getter and setter in just in case you need perform some other
//initialization when the stage gets set...
public function set stage(stg:Stage):void
{
m_stage = stg;
}
public function get stage():Stage
{
return m_stage;
}
}
Then somewhere else, like you main controller class:
StageManager.instance.stage = this.stage;
Now you can access the stage and its properties globally through the StageManager:
var stageW:int = StageManager.instance.stage.stageWidth;
This way, not just you Pan class, but anything else down the road can access the global stage any time it needs to. Pretty cool, huh?
As for how to design your Pan class, I agree with #The_asMan - extend MovieClip. Unless, that is, one Pan instance will be controlling several MovieClip instances, then it would probably make more sense to have it as its own thing (the way you describe above).

flash-as3 code execution order: accessing a flash pro instance after gotoAndStop()

this is a follow up question to this question
i have never actually got the flash-actionscript code execution order.
in flash pro i have an instance of a moveiclip on stage in frame one named tree1 and on frame 3 i have on the stage tree3.
in the document class i have this code:
stop();
var scaleFactor:Number = tree1.scaleX;
gotoAndStop(3);
tree3.scaleX = scaleFactor;
while this works when testing on the desktop, this app will go mobile at the end
is this the correct way to go or should i register for a frameComplete event before accessing instances on a certain frame
So, just dont use the Document Class cause you will need to declare all the scenes from the beginning and will be complicate to manage each scene.
I suggest you to instance a simple MovieClip linked with his own class like the example SceneTree, put it on each Keyframe. You will have more control when you are entering or exiting each frame.
package {
import flash.display.MovieClip;
import flash.events.Event;
public class SceneTree extends MovieClip {
public function SceneTree() {
super();
this.addEventListener(Event.ADDED_TO_STAGE, Init);
this.addEventListener(Event.REMOVED_FROM_STAGE, removed);
}
protected function Init (event:Event):void{
trace("added")
}
protected function removed (event:Event):void{
trace("removed")
}
}
}
waiting for Event.FRAME_CONSTRUCTED is the correct way whenever accessing assets on a timeline
it insures all assets have been created

Detecting when an object gets added to a movieclip

Alright, so I'm trying to figure out when a child is added to a movieclip "x", and handling/detouring this operation from within this "x" movieclip.
I tried overriding addChild and addChildAt at with no prevail. The movieclips that are placed on the stage via flash still don't trigger addChild or addChildAt. However, tracing this.numChildren shows '2' correctly.
Any hints?
You can add an event listener for the "added" event for the x movie clip.
x.addEventListener(Event.ADDED, addHandler);
function addHandler(e:Event){
// your code here
}
This link may explain it better:
AS3.0 – Event.ADDED and Event.ADDED_TO_STAGE
The documentation is also a good resource:
flash.events.Event
You can override the default methods of a movieclip by doing the following:
Create a class to extend a movieclip:
package {
import flash.display.*;
public class SuperMovieClip extends MovieClip {
public function SuperMovieClip() {
// constructor code
super();
}
override public function addChild(child:DisplayObject):DisplayObject {
trace("Hello, I am overriding add child");
// still perform the default behavior but you can do what ever you want.
return super.addChild(child);
}
}
}
Then in Flash create a new movieclip, and make sure it is marked as Enable for ActionScript. The Class should be any name you want, but the base class needs to be SuperMovieClip (or the name you chose for your extended class) See image:
Now when any stage clip is created of this base type (regardless if it's in the IDE or through code) it will be of type SuperMovieClip and anytime addChild is called it will override the original function.
For example, I placed an instance of this mc from library onto the stage at design time and compiled it using the following code on the timeline:
import flash.display.Sprite;
stage_mc.addChild(new Sprite());
And it output Hello, I am overriding add child