#actionscript-3 #flash #air
#actionscript-3 #flash #air
Вопрос:
У меня возникла проблема с тем, что мои кнопки работают только один раз. Кнопка запускает пользовательское событие. Пользовательское событие срабатывает, и прослушиватель в моем DocumentClass улавливает его в первый раз, но после этого не отвечает.
Чтобы повторить, нажмите здесь, затем нажмите «Начать игру», затем кнопку меню вверху справа, затем нажмите главное меню, затем нажмите «Начать игру», затем кнопку меню вверху справа, затем обратите внимание, что вы не можете снова нажать главное меню. Это моя проблема. Он должен продолжать работать.
DocumentClass добавляет дочерний openScreen. openScreen запускает событие для DocumentClass, чтобы добавить дочерний экран воспроизведения и удалить openScreen. экран воспроизведения добавляет дочерний экран меню при нажатии кнопки меню на экране воспроизведения. ** При нажатии кнопки главного меню запускается событие, которое прослушивается DocumentClass. Запускаемая функция удаляет экран воспроизведения и добавляет открытый экран. Эта серия событий работает только один раз полностью, прежде чем повесить трубку при выполнении шага **.
Класс документа
public class DocumentClass extends MovieClip
{
public var playScreen:PlayScreen = new PlayScreen();
public var openScreen:OpenScreen = new OpenScreen();
public var started:Boolean = false;
public function DocumentClass()
{
openScreen.addEventListener( GameEvent.STAR, OnPlayClick);
playScreen.addEventListener( GameEvent.NG, NewGame);
playScreen.menuScreen.addEventListener( GameEvent.NG, NewGame, true, 0, true);
playScreen.menuScreen.addEventListener( GameEvent.MM, onMain);
addChild(openScreen)
}
public function OnPlayClick(gameEvent:GameEvent):void{
trace("start")
addChildAt(playScreen,0)
var tweenX:Tween = new Tween(openScreen, "x", None.easeIn, 0, -480, .5, true);
tweenX.addEventListener(TweenEvent.MOTION_FINISH, onTweenDone);
}
public function NewGame(gameEvent:GameEvent):void{
removeChild(playScreen)
playScreen = new PlayScreen();
addChild(playScreen)
playScreen.begin()
}
public function onMain(gameEvent:GameEvent):void{
playScreen.removeChild(playScreen.menuScreen)
this.removeChild(playScreen)
//openScreen = new OpenScreen();
openScreen.x = 0
addChild(openScreen)
playScreen = new PlayScreen();
MenuScreen
общедоступный класс MenuScreen расширяет MovieClip
{
public function MenuScreen()
{
backButton.buttonMode = true
backButton.addEventListener( MouseEvent.CLICK, OnBackClick );
exitButton.buttonMode = true
exitButton.addEventListener( MouseEvent.CLICK, OnExitClick );
restartButton.buttonMode = true
restartButton.addEventListener( MouseEvent.CLICK, OnRestartClick );
mainButton.buttonMode = true
mainButton.addEventListener( MouseEvent.CLICK, OnMainClick );
//NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_DOWN, onSystemKey);
backButton.AnswerText.text = "Return to Game"
restartButton.AnswerText.text = "Restart"
mainButton.AnswerText.text = "Main Menu"
exitButton.AnswerText.text = "Exit"
}
public function OnBackClick(myEvent:MouseEvent):void{
this.dispatchEvent( new GameEvent( GameEvent.BAC ))
}
public function OnExitClick(myEvent:MouseEvent):void{
//NativeApplication.nativeApplication.exit();
}
public function OnRestartClick(myEvent:MouseEvent):void{
this.dispatchEvent( new GameEvent( GameEvent.NG ))
trace("restrt click")
}
public function OnMainClick(myEvent:MouseEvent):void{
this.dispatchEvent( new GameEvent( GameEvent.MM ))
trace("main click")
}
protected function onSystemKey(e:KeyboardEvent):void
{
if(e.keyCode == Keyboard.BACK)
{
e.preventDefault();
this.dispatchEvent( new GameEvent( GameEvent.BAC ))
}
else if(e.keyCode == Keyboard.HOME)
{
//handle the button press here.
}
else if(e.keyCode == Keyboard.MENU)
{
//handle the button press here.
}
}
}
Открытый экран
public class OpenScreen extends MovieClip
{
public var hs:String
public function OpenScreen()
{
startButton.buttonMode = true
startButton.addEventListener( MouseEvent.CLICK, OnStartClick );
exitButton.buttonMode = true
exitButton.addEventListener( MouseEvent.CLICK, OnExitClick );
//NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_DOWN, onSystemKey);
readObject()
highScoreText.text = String(hs)
trace(highScoreText.text)
startButton.AnswerText.text = "Start"
//restartButton.AnswerText.text = "Restart"
//mainButton.AnswerText.text = "Main Menu"
exitButton.AnswerText.text = "Exit"
}
public function OnStartClick(myEvent:MouseEvent):void{
trace(this.hasEventListener( GameEvent.STAR ))
this.dispatchEvent( new GameEvent( GameEvent.STAR ))
}
public function OnExitClick(myEvent:MouseEvent):void{
//NativeApplication.nativeApplication.exit();
}
protected function onSystemKey(e:KeyboardEvent):void
{
if(e.keyCode == Keyboard.BACK)
{
//NativeApplication.nativeApplication.exit();
}
else if(e.keyCode == Keyboard.HOME)
{
//handle the button press here.
}
else if(e.keyCode == Keyboard.MENU)
{
}
}
Ответ №1:
Похоже, причина в том, что в вашем onMain
методе вы удаляетесь со сцены, а затем создаете совершенно новый экземпляр экрана воспроизведения. таким образом, ваши слушатели подключены к старому. Это также создает утечку памяти.
public function onMain(gameEvent:GameEvent):void{
playScreen.removeChild(playScreen.menuScreen)
this.removeChild(playScreen)
//openScreen = new OpenScreen();
openScreen.x = 0
addChild(openScreen)
playScreen = new PlayScreen(); //RIGHT HERE - this is creating a whole new play screen, your listeners are attached to the old one.
}
Вероятно, должно выглядеть так: (удалите код экрана воспроизведения в конструкторе и не создавайте его при его объявлении)
//Create a function that kill your current play screen
public function clearPlayScreen():void {
if(!playScreen) return; //don't do anything if there isn't a play screen
playScreen.removeChild(playScreen.menuScreen)
this.removeChild(playScreen);
//remove your listeners so the old play screen can be garbage collected - other they will all stay in memory causing a memory leak
playScreen.removeEventListener( GameEvent.NG, NewGame);
playScreen.menuScreen.removeEventListener( GameEvent.NG, NewGame, true);
playScreen.menuScreen.removeEventListener( GameEvent.MM, onMain);
playScreen = null;
}
public function NewGame(gameEvent:GameEvent):void{
clearPlayScreen(); //kill the old play screen if it exists
playScreen = new PlayScreen();
addChild(playScreen);
//add the listeners to the new play screen
playScreen.addEventListener( GameEvent.NG, NewGame);
playScreen.menuScreen.addEventListener( GameEvent.NG, NewGame, true, 0, true);
playScreen.menuScreen.addEventListener( GameEvent.MM, onMain);
playScreen.begin();
}
public function onMain(gameEvent:GameEvent):void{
clearPlayScreen();
//openScreen = new OpenScreen();
openScreen.x = 0;
addChild(openScreen);
}
Комментарии:
1. Имеет смысл, что это проблема, и это устраняет мою проблему с неработающими кнопками. Новый экран воспроизведения был моим способом создания новой игры, поскольку вся игровая механика заключена в экран воспроизведения. Есть ли лучший способ восстановить этот дочерний элемент таким, каким он был до его вызова?
2. Возможно, это более эффективный способ, но это будет зависеть от вашего приложения в целом. Нет ничего плохого в очистке и повторном создании экземпляра, если он достаточно производителен — просто убедитесь, что в памяти нет ничего, что сохраняло бы предыдущий экран воспроизведения (например, прослушиватели событий)