Sign in to follow this  
Followers 0
jeteran

AS3.0 Moving a character (listener) doesn't work

26 posts in this topic

Hello guys.

I have been working in this single thing for more than 3 hours and can't get it done.

I want to add a listener to the main character in the game.

I'm using MainCharacter.as file to have al the properties and movements of it.

So far, everything works (appears in the scene, I can even click on it and trace works)

But when I want it to move when I press a button, it doesn't work.

I have an instance of the Main.as file that I'm using to addChild all the things of the game (including the main char, and works great)

Ok well,I tried:

addEventListener(KeyboardEvent.KEY_DOWN,keyDown);
scene.addEventListener(KeyboardEvent.KEY_DOWN,keyDown);
Main._instanceMain.addEventListener(KeyboardEvent.KEY_DOWN,keyDown);

and so much more I can't remember. But it doesn't work.

I even try to do it inside PlayGame.as and didn't work either.

What could it be??!

Thanks guys, ANY ANY suggestions will be much appreciated !!
0

Share this post


Link to post
Share on other sites
Keyboard events are from the stage. You want to do:

[CODE]
addEventListener(Event.ADDED_TO_STAGE, onStage);
function onStage(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, onStage);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
addEventListener(Event.REMOVED_FROM_STAGE, offStage);
}

function offStage(e:Event):void {
removeEventListener(Event.REMOVED_FROM_STAGE, offStage);
stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
[/CODE] Edited by greenvertex
2

Share this post


Link to post
Share on other sites
Hey greenvertex, it's good to see you around.

Awesome I'm going to try that. Just one thing (and sorry to ask I'm truly tired !!)

The function onStage I add it in the Main.as file? and the offStage in the MainCharacter.as ?

Thanks once again !!
0

Share this post


Link to post
Share on other sites
If you want to move your character, it makes sense to add the whole thing to MainCharacter.as:

When your character is added to the stage, he starts listening for key events. When one is pressed, some property changes (position or whatever else).
When your character gets removed from the stage, make sure to remove all those event listeners that he was listening to. Now he can't move anyway...
2

Share this post


Link to post
Share on other sites
Thanks greenvertex for your response.

But crap I can't get it move. It doesn't show any error.

I paste your code and show and error that onKeyDown was not found, so I change it for the name of the function that I want to run and nothing.

Then I add the instance of the Main.as, where everything is getting add, and nothing either.

What can be??

Thanks for your time greenvertex !!
0

Share this post


Link to post
Share on other sites
[quote name='JETerán' timestamp='1346273753' post='4974568']
Thanks greenvertex for your response.

But crap I can't get it move. It doesn't show any error.

I paste your code and show and error that onKeyDown was not found, so I change it for the name of the function that I want to run and nothing.

Then I add the instance of the Main.as, where everything is getting add, and nothing either.

What can be??

Thanks for your time greenvertex !!
[/quote]
If you want handle whole keyboard events for control game object, use stage, and not your custom objects.
When you add keyboard event listener to stage, this is applied for all of your objects (this is not trully in lower-level of action script, but you can imaginate it like I said :)).
Just like a simple example:
[source lang="java"]myGameObject.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);[/source]
1

Share this post


Link to post
Share on other sites
Sure thing, thanks greenvertex.

I will paste it before adding your code to see what I'm wrong:

MainChar.as
[CODE]
package com.jeteran
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.events.Event;

public class MainChar extends MovieClip
{
public var charObject:Object; //create the object
public var char:Char; //call the mc in the lib

//BTW this is a new approach I was working, creating an object of the character:
charObject = new Object();
char = new Char;

charObject._image = char;
charObject._id = 0;
charObject._moveLeft = false;
charObject._moveRight = false;

Main._instaceMain.addChild(charObject._image) // The _instanceMain is an instance I created in the Main.as to make everything work there

addEventListener(KeyboardEvent.KEY_DOWN, keyPressed); //I tried Main._instanceMain. ... and stage, , but the same, doesn't work

function keyPressed(event:KeyboardEvent)
{
if (event.keyCode == 39)
{
trace("RIGHT");
}

else if (event.keyCode == 37)
{
trace("LEFT");
}
}
[/CODE]

That's it, thanks so much for your kindly help guys !!!
0

Share this post


Link to post
Share on other sites
[quote name='Deft' timestamp='1346277154' post='4974589']
If you want handle whole keyboard events for control game object, use stage, and not your custom objects.
[/quote]
I CAN'T believe it !! It worked !!

My God I have hours on this and finally got it, thanks to you !!!

BTW, can you explain me a little more about this?! I want to learn ;)

Thanks SO SO much Deft, you are the man of the day !!
0

Share this post


Link to post
Share on other sites
[quote name='JETerán' timestamp='1346278225' post='4974593']
[quote name='Deft' timestamp='1346277154' post='4974589']
If you want handle whole keyboard events for control game object, use stage, and not your custom objects.
[/quote]
I CAN'T believe it !! It worked !!

My God I have hours on this and finally got it, thanks to you !!!

BTW, can you explain me a little more about this?! I want to learn ;)

Thanks SO SO much Deft, you are the man of the day !!
[/quote]
The thing is keyboard events working only when user focused on it.
For example, you can't input into text area until you'll not selected it by clicking mouse or click "tab-tab-tab" to go into area (this is mean focus). When your pointer blinking in input area, you can enter characters. Yeap? This mean that you was focused on text area. For another object, such as text labels and other (including sprites/movie clips/etc.) focus rules are the same.
So, your keyboard events didn't worked because of your game object wasn't focused. So adding global KB event onto display object is not better choice. Just do KB handling on the stage, that is focused always by default (again, this is not same on low-level, but you understand what I mean)

P.S. But if you want implement such things like a input fields, you need to add KB event [b]only[/b] onto object itself. Edited by Deft
1

Share this post


Link to post
Share on other sites
Hi. try this;
.......
Main._instaceMain.addChild(charObject._image) // The _instanceMain is an instance I created in the Main.as to make everything work there
Main._instaceMain.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed); //I tried Main._instanceMain. ... and stage, , but the same, doesn't work

[b]Main._instaceMain.addEventListener(MouseEvent.MOUSE_DOWN, function(e:Event):void[/b]
[b]{[/b]
[b] stage.focus = Main._instaceMain;[/b]
[b]});[/b]

function keyPressed(event:KeyboardEvent)

..............
1

Share this post


Link to post
Share on other sites
Thanks so much guys for your help.

Thanks fdn2012, sincerely I didn't try your code now that Deft's code was effective. But I can see that has the same logic.

I'm now working on making that character move inside the map. This is what I have:

I have 3 different MCs, one for each level. Inside Missions.as I have an array that captures each MCs.

I have a main character that is created inside MainCharacter.as.

I have a file called GameStart.as that runs both. I managed to put the character inside the scene, as well the levels.

Now what I want to do is, when the character hits an invisible MC inside the level, addChild the second MC of the array.

So far so good. But when I want to touch the next invisible MC inside the second level, still behaves like if it were from the first level. I tried to removeChild the first level but I sends me an error that the character can't hitTestObject a null object :S What could this be?

In my desperation, I created another MC, this one has 3 frames, one of each level and they all share 2 invisible MCs, one to the left of the scene and one to the right.

In this way, instead of creating another child, I just .gotoAndStop(#) the MC and works perfectly, but, as before, when I want to go to the 3rd room (gotoAndStop(3)) it doesn't work. I don't know what's happening with that number :S BUT I tried play() and works great.

But now coming back so the character touches the left invisible MC, I'm creating an if statement that if the character touches the leftLimit MC and his actualPosition is room3, trace("something"); but doesnt work. I changed the property ._actualLevel of the character when it is in the second level, but actualy is not happening.

I wish i make myself clear. I'm deeply tired guys I can't think clearly anymore. Please ANY ANY suggestion will work A LOT !!

Thanks once again !!
0

Share this post


Link to post
Share on other sites
Can you paste the code?
[img]http://public.gamedev.net//public/style_emoticons/default/rolleyes.gif[/img] Sorry. I did not understand all of your post.
1

Share this post


Link to post
Share on other sites
Hey fdn2012, thanks for your reply.

I feel good today, let's keep on the good work.

Ok I'm going to paste the code and the files I'm using to create the game.

For the missions, I will paste only the first mission's code:

Missions.as
[CODE]
import all the flash. i will use

public class Missions extends MovieClip {

public var mission1:Array; //BTW I tried to use it as an object but didn't work
public var mission1room1:Mission1room1; //This is the instance of the MC of the first room
public var mission1room2:Mission1room2; //The same but second room
public var mission1room3:Mission1room3; //the same but third room

public function Missions() {

mission1 = new Array();
mission1room1 = new Mission1room1;
mission1room2 = new Mission1room2;
mission1room3 = new Mission1room3;

}

//Ok here is the code for that first mission and I just addChild to the scene using an instance of the Main.as file
public function mission1() {

mission1[0] = mission1room1;
mission1[1] = mission1room2;
mission1[2] = mission1room3;

Main._instanceMain.addChild(mission1[0]); // I add the first room to the Main scene.
}
}
}
[/CODE]

MainChar.as
[CODE]
the same, I import all the flash.* i will need

public class MainChar extends MovieClip {

public var hero:Object; //The hero is an object that has many properties
public var heroImage:HeroImage; // the instance of the MC in the lib

public function MainChar() {

hero = new Object();
heroImage = new HeroImage();

//Ok here I create some properties, like:

hero._image = heroImage;
hero._vel = 10;
hero._moveRight = false;
hero._moveLeft = false;
hero._curRoom = "room1" // I create this to have a track of which room is the hero
}

public function Movements() {

Main._instanceMain.addChild(hero._image); //I create hero in the scene

hero._image.stage.addEventListener(KeyboardEvent.KEY_DOWN, keyIsDown); //This works GREAT thanks to Deft !!!!
hero._image.stage.addEventListener(KeyboardEvent.KEY_UP, keyIsUp);
hero.addEventListener(Event.ENTER_FRAME, moveMyHero);

function keyIsDown(event:KeyboardEvent)
{
if (event.keyCode == 39)
{
hero._moveRight = true;
}

else if (event.keyCode == 37)
{
hero._moveLeft= true;
}
}
//Ok that was just a function that will trigger when the player hits left and right arrows. The very same for the keyIsUp function.
//Then I create the function for moveMyHero based on the info of both keyIsDown and keyIsUp functions.
[/CODE]

So far so good. Now comes the tricky part:

StartGame.as
[CODE]

public class StartGame extends MovieClip {

public var missions:Missions; //I import the file Missions.as
public var mainChar:MainChar; //I import the file MainChar.as

public function StartGame() {

missions = new Missions();

//Here I create and use some scenes before the game. After a while, theres a button that says start game, and then... :

mainChar = new MainChar(); //Load the .as in the scene;
mainChar.Movements(); //I run Movements function;

//Ok now, this is where things got messed. This is what I did to find a way to handle both the hero and the first mission:

addEventListener(Event.ENTER_FRAME, detectInitEnd); //This function is to detect when the hero is far left or far right the rooms

function detectInitEnd(event:Event) {

if (mainChar.hero._image.hitTestObject(mission1[0].leftLimit1)) //This is: if the instance of the char hitTest the first room's left limit (left limit 1 because each room has it's own limits, so the first room has leftLimit1 and rightLimit2, the second room leftLimit3 and rightLimit4 and so on), then:
{ trace("left touched"); } //This works.

else if (mainChar.hero._image.hitTestObject(mission1[0].rightLimit2)) //This starts to get confused... :S
{
mainChar.hero._image.x = 50 //restart hero's position , good
Main._instanceMain.removeChild(mission1[0]); //remove current level
Main._instanceMain.addChild(mission1[1]); //add next level
mainChar.hero._curRoom = "room2"; //This didn't work
}

else if (mainChar.hero._image.hitTestObject(mission1[1].rightLimit4)) //Twice confused :S :S
{
mainChar.hero._image.x = 50 //restart hero's position , good
Main._instanceMain.removeChild(mission1[1]); //remove current level
Main._instanceMain.addChild(mission1[2]); //add next level
mainChar.hero._curRoom = "room3";
}
[/CODE]

By this far, errors start to pop out, some say that I can't removeChild something is null, the third room never appeared, and so on :s

If you think there is a better way to do this, I will do it.

Please guys help me on this one, we are sooo close to it's conclusion, I just need this final thing.

ANY suggestions it's more than welcome !!

Happy day !! Edited by JETerán
0

Share this post


Link to post
Share on other sites
If you're deleting an object from game scene, first you should remove all event listeners, which can be connected to this object. Just like:
[source lang="java"]Main._instanceMain.removeEventListener(/* There is your collision event definition, i.e. detectInitEnd */);
Main._instanceMain.removeChild(mission[1]);[/source]
The thing is that flash do not removes event listeners automatically, developer should keep it in mind :)
And you should compare your hit test object and hittable object for null-instance. Edited by Deft
1

Share this post


Link to post
Share on other sites
As always, thanks Deft for your reply :D

Ok I saved that tip, I will always delete event listeners after use, thanks !!

About this code, what I have is just an event listener that's a ENTER_FRAME, if I wanted to remove it, will be a mess.

So, to make it more clearly, I think will be better to have many event listeners, one for each collision with the left and right invisible walls; am I right??

How can I add an event listener that knows f.i. leftLimits is touched by hero??

Thanks SO much once again !!
0

Share this post


Link to post
Share on other sites
[quote name='JETerán' timestamp='1346340729' post='4974830']
As always, thanks Deft for your reply [img]http://public.gamedev.net//public/style_emoticons/default/biggrin.png[/img]

Ok I saved that tip, I will always delete event listeners after use, thanks !!

About this code, what I have is just an event listener that's a ENTER_FRAME, if I wanted to remove it, will be a mess.

So, to make it more clearly, I think will be better to have many event listeners, one for each collision with the left and right invisible walls; am I right??

How can I add an event listener that knows f.i. leftLimits is touched by hero??

Thanks SO much once again !!
[/quote]
I've not recommend to add one event listener per each collision object, especially, if you call them for each call - it is overhead in performance, and be sure - it will be performance issue.
The problem is that you want to test object collisions after you removed this object from stage. You cannot test collisions if some object is out of stage.
If you had caught collision and do stage clean up, you may assume that collision tests should be stopped before doing this work. And moreover you need to clean up all events and objects, because in other cases you will get performance problems after loading few levels.

I hope, I understood what do you want ) Edited by Deft
1

Share this post


Link to post
Share on other sites
hehe, Sorry for my English. I can't express my meaning properly.[img]http://public.gamedev.net//public/style_emoticons/default/rolleyes.gif[/img]
If I do it, Like this:
[source lang="java"]var currentMission:Object = mission1;//this variable point at mission1 or mission1 or mission2 or mission3
function detectInitEnd(e:Event)
{
if(currentMission == null)
{
removeEventListener(Event.ENTER_FRAME, detectInitEnd)
return;
}
if(mainChar.hero._image.hitTestObject(currentMission.leftLimit1))
{
trace("left touched:" + currentMission);
}
else if(mainChar.hero._image.hitTestObject(currentMission.rightLimit2))
{
mainChar.hero._image.x = 50 //restart hero's position , good
if(Main._instanceMain.contains(currentMission))
{
Main._instanceMain.removeChild(currentMission); //remove current level
}
var i:int = mission1.indexOf(currentMission);
i ++;
currentMission = i < mission1.length ? mission1[i] : null;
if(currentMission != null)
{
Main._instanceMain.addChild(currentMission);
}
mainChar.hero._curRoom = currentMission != null ? "room" + i : "";
}
}[/source]
1

Share this post


Link to post
Share on other sites
Thanks Deft for your message.
[quote name='Deft' timestamp='1346343852' post='4974840']
I've not recommend to add one event listener per each collision object.
[/quote]
Actually that makes a lot of sense. It will be very hard to handle all the event listeners !!
[quote name='Deft' timestamp='1346343852' post='4974840']
The problem is that you want to test object collisions after you removed this object from stage.
[/quote]
That's true, but what about if I use just 2 objects to test collisions? That's something I was trying, having just 1 MC with 3 frames (each frame has each room) and have 2 objects to test left and right collision but not for each room, but globaly? Crap I think this is more messed up right? :S

Well the thing what I want (I think I should had start here) is have a mission where a char can move freely inside it. That mission has 3 rooms, at both ends has doors. When the player in the first room reaches the right door, player goes to next room; ; and so on.

Of course, the left door of the first room and the right door of the third room won't work. ;)

Thanks so much Deft !!

[quote name='fdn2012' timestamp='1346348633' post='4974855']
hehe, Sorry for my English. I can't express my meaning properly.
If I do it, Like this:
[/quote]
Don't worry fdn2012 !!! And thanks so much for your code, I'm gonna try it out ;)

Let's keep up the good work and ANY more suggestions will be more than awesome :)
0

Share this post


Link to post
Share on other sites
I think, you should remember in what room your player right now. After that you can use three containers: each container for 1 room.
These containers should contain list of objects for collision testing from each room. And I think that's will be goal: after that you can successfully remove collision objects from first room, when your player inside second or third room.
1

Share this post


Link to post
Share on other sites
Thanks Deft for your response.

What you say makes senses. In that way, I made a property for the character called currentRoom, starting at "room1" so it can have track of what room he is on.

About the container, that sounds great. If I have 3 containers, one for each room, I would have a hitTestObject with the left and right limit. If so, remove collision and addChild the second container, am I right?

I'm gonna approach it that way.

Thanks SO much guys !!
0

Share this post


Link to post
Share on other sites
Hello again guys.

Ok I followed both suggestions.

I first used your code fdn2012 using other files and using my vars and stuff of course, got many errors.

Then I tried to use 3 different containers with your code and it's happened something very similiar as before.

Now I'm back at your code but with a container object pointing to an array from mission1.

So far so good, but I'm still haveing the same problem as before, room3 is not showing.

Ok but I got something: when I'm in room2 and want to go to room3, still can touch the right limit of the room1, but why if I removeChild it??

This only question is driving me CRAZY !! Each room should remove from the scene. Or is sane to remove too both left and right limit when I change rooms?

ANY suggestions will be taken as a bless !!!!

Thanks guys.

[b]EDIT[/b]
GUYS, I did it.

I followed Deft suggestion that you have to remove the event listener if you want to really the child disappear (am I right?)

Well what I did was create 3 addEventListeners, one for each room. I know this is TOO many eventListeners, but this is the only way I was able to make it work.

What do you think??

[b]EDIT 2[/b]
Hey guys,

Ok now I can know when the hero hitTestObject one of the objects in the rooms (WOW the code is SO long)

Ok well, I'm going to work back again the Store, because now I need to put the objects in the inventory in the objects of the room.

I'm going to try now Deft suggestion !!
[url="http://www.gamedev.net/topic/630116-as30-using-arrays-for-game-inventory-and-how-to-track-objects/page__p__4974595#entry4974595"]http://www.gamedev.n...95#entry4974595[/url]

Thanks again Deft !! Edited by JETerán
0

Share this post


Link to post
Share on other sites
Always welcome [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]

What type of event listener you've added? You said, that you add 3 event listeners. I think, you should do that separately.

Player in first room.
Add event listener, that will test collisions for first room objects.
Player hits door to second room.
Remove event listener for first room collision testing.
Remove first room display objects from the scene.
Add all objects for second room to the scene.
Add event listener for second room collision testing.

When I say "Add event listener", I don't mean, that you should have three methods for each room. You may use only one method and store current room index, where player is at the moment. So, I can rewrite algo:


Player in first room.
[b]Set _currentRoom variable to 1[/b]
Add event listener, that will test collisions for first room objects. [b]Right here I'm using _collisionObjectsContainer[_currentRoom] and that's it - I've got list of first room collision objects[/b].
Player hits door to second room.
[b]Set _currentRoom variable to 2[/b]
Remove event listener for first room collision testing.
Remove first room display objects from the scene.
Add all objects for second room to the scene.
Add event listener for second room collision testing.

After such reimplementation you can adopt this algorithm as base for all of your game stages. Edited by Deft
1

Share this post


Link to post
Share on other sites
As always, thanks so much Deft for your cooperation.

Indeed this is the way I'm doing it :)

Ok so I have 3 ENTER_FRAMES events, one for each room. The first one detects both left and right collisions. Still inside this event, I add an If that returns me if the hero is touching the objects in that room.

So far so good, it works perfectly for the 3 rooms :D

Ok now the tricky thing, I have to make the hero be able to come back from others rooms. This is, from room 3 to room 2 and from 2 to 1.

I think that's not a problem. The thing is 2 things, one that if the hero touches the room1's left collision, it has to stop. The same for the right collision of the 3rd room. To do this, I will try to setup a flag that tells me if the hero touches it, stop movement. The thing is that it will always touch it once it touch it, you know what I mean??

Anyways I will start will all this.

Thanks so much Deft !!!
0

Share this post


Link to post
Share on other sites
I'm happy to tell you that, thanks to Deft, I'm able to move the hero freely in all the rooms [img]http://public.gamedev.net//public/style_emoticons/default/biggrin.png[/img]

Ok I will work now in the hero that should stop when he hits the left collision in first room and right collision in third room.

Any suggestions is welcome [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]

[b]EDIT 1:[/b]
Hello again.

I'm able now to stop the hero when hits left collision of first room. I ask if hero hit tests the left invisble collision AND if the left arrow key is pressed :) Too easy.

It's buggy tho, it's making some jumps when it reaches the end. But that it's not a worry, for now.

Thanks so much Deft for all your patient !!

Let's keep up the good work. Edited by JETerán
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0