Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 21.04.2015, 18:26
Febz вне форума Посмотреть профиль Отправить личное сообщение для Febz Найти все сообщения от Febz
  № 1  
Ответить с цитированием
Febz

Регистрация: Jan 2014
Сообщений: 8
По умолчанию Простая система заклинаний

Как лучше организовать систему заклинаний, чтобы при нажатии на цифру вызывалось (или не вызывалось - в зависимости от cooldown'a) то заклинание, которое привязано к этой клавише?

На данный момент есть главный класс Main, и по одному классу (spell_1, spell_2...) на заклинание.
В Main идет проверка:
- если нажата цифра 1 и кулдаун 1го заклинания = 0, то создается экземпляр класса spell_1, ...
- если нажата цифра 2 и кулдаун 2го заклинания = 0, то создается экземпляр класса spell_2, ... и т.д

Соответственно, кулдауны всех заклинаний обрабатываются тоже в главном классе. Всё работает, но по мере роста количества заклинаний, переменных в Main становится все больше и больше, что не есть хорошо. Вот, ищу способ всё это унифицировать. Подскажите саму логику создания подобных систем...

Старый 21.04.2015, 18:37
caseyryan вне форума Посмотреть профиль Отправить личное сообщение для caseyryan Найти все сообщения от caseyryan
  № 2  
Ответить с цитированием
caseyryan
 
Аватар для caseyryan

Регистрация: Jun 2012
Адрес: Новосибирск
Сообщений: 6,644
Записей в блоге: 4
Почитайте про паттерн Фабрика (Factory). Можно с помощью него реализовать. Но вот эти spell_1, spell_2 и все такое, надо наследовать от какого-то базового класса, типа SpellBase

Старый 21.04.2015, 21:06
dimarik вне форума Посмотреть профиль Отправить личное сообщение для dimarik Найти все сообщения от dimarik
  № 3  
Ответить с цитированием
dimarik
.
 
Аватар для dimarik

модератор форума
Регистрация: Sep 2003
Адрес: Москва
Сообщений: 4,630
Записей в блоге: 20
Можно сделать один SpellController, ссылку на него пока хранить в Main. Подписать его на события клавиатуры. Но не забывать о том, что в разные состояния игры события должны обрабатываться по-разному. Иногда вы бываете, например, в меню настроек. Там точно не должны включатся спеллы.

Именно в нем сделать обработку клавиш и добавлять вью ваших спеллов в какой-нибудь контейнер, ссылку на который необходимо передать во время инициализации SpellController.

Добавлено через 6 минут
P.S. Я рекомендую ознакомиться чем класс отличается от объекта. Достаточно хорошо эта тема освещена в книге Колина Мука.
__________________
Воспитан в TimeZero. Работаю в Mail.ru.

Старый 21.04.2015, 23:23
OlmerDale вне форума Посмотреть профиль Отправить личное сообщение для OlmerDale Найти все сообщения от OlmerDale
  № 4  
Ответить с цитированием
OlmerDale
[+1 09.05.15]

Регистрация: Jan 2015
Сообщений: 113
Я бы сделал так..
Есть две фабрики для скинов мага и для самой магии -
Код AS3:
package 
{
	import flash.display.DisplayObject;
	import flash.utils.Dictionary;
 
	public class MageSkinFactory 
	{
		protected static const MAGE_SKINS:Dictionary = new Dictionary();
 
		public static function setMageSkinMap(skin:DisplayObject, id:uint):void
		{
			MageSkinFactory.MAGE_SKINS[id] = skin;
		}
 
		public static function getMageSkin(id:uint):DisplayObject
		{
			return MageSkinFactory.MAGE_SKINS[id];
		}
	}
 
}
Код AS3:
package 
{
	import flash.display.DisplayObject;
	import flash.utils.Dictionary;
 
	public class SpellFactory 
	{
		protected static const SPELLS:Dictionary = new Dictionary();
 
		public static function setSpellMap(spell:Class, id:uint):void
		{
			SpellFactory.SPELLS[id] = spell;
		}
 
		public static function getSpell(id:uint):DisplayObject
		{
			return new (SpellFactory.SPELLS[id] as Class)() as DisplayObject;
		}
	}
 
}
Как видно в фабрики добавляются ассеты по id, которые выносим в классы-константы -

Код AS3:
package 
{
	public class MageSkinType 
	{
		public static const DEFAULT_MAGE_SKIN:uint = 1;
		public static const FIRE_SPELL_MAGE_SKIN:uint = 2;
		public static const WATER_SPELL_MAGE_SKIN:uint = 3;
	}
}
}[/as3]
Код AS3:
package 
{
	public class SpellType 
	{
		public static const FIRE_SPELL_TYPE:uint = 49;
		public static const WATER_SPELL_TYPE:uint = 50;
	}
 
}
Ниже класс Mage, он по сути базовый класс и принимает в себя только скины, которые ему фабрика предоставляет.
Код AS3:
package 
{
	import aze.motion.eaze;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
 
	public class Mage extends Sprite
	{
		protected var _currentSkin:DisplayObject;
		protected var _currentState:uint;
 
		protected var _isRun:Boolean = false;
 
		public function setState(state:uint):void
		{
			if (this._isRun || state == this._currentState) return;
 
			super.removeChildren();
 
			this._currentState = state;
			this._currentSkin = MageSkinFactory.getMageSkin(this._currentState);
			super.addChild(this._currentSkin);
 
			this._isRun = true;
			this.animation();
		}
 
		protected function animation():void
		{
			eaze(this._currentSkin as Sprite).to(1, {rotation:360}).onComplete(this.animation_completeCallback);
		}
 
		protected function animation_completeCallback():void
		{
			this._isRun = false;
			super.removeChildren();
 
			this._currentState = MageSkinType.DEFAULT_MAGE_SKIN;
			this._currentSkin = MageSkinFactory.getMageSkin(this._currentState);
			super.addChild(this._currentSkin);
 
			super.dispatchEvent(new Event(Event.CHANGE));
		}
 
		public function get isRun():Boolean 
		{
			return _isRun;
		}
 
	}
 
}
Дальше идет базовый класс заклинания -
Код AS3:
package 
{
	import flash.display.Sprite;
 
	public class Spell extends Sprite
	{
		public function execute():void{}
	}
 
}
Далее конкретная реализация, заклинания огня и воды -
Код AS3:
package 
{
	import aze.motion.eaze;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
 
	public class FireSpell extends Spell 
	{
		private var _textField:TextField;
 
		public function FireSpell() 
		{
			super();
			this.init();
		}
 
		private function init():void 
		{
			this._textField = new TextField();
			this._textField.autoSize = TextFieldAutoSize.CENTER;
 
			var textFormat:TextFormat = new TextFormat();
			textFormat.size = 50;
			textFormat.color = 0xE24B4B;
			textFormat.bold = true;
 
			this._textField.defaultTextFormat = textFormat;
 
			this._textField.text = 'FIRE!!!';
 
			super.addChild(this._textField);
		}
 
		override public function execute():void 
		{
			eaze(this._textField).to(1, { alpha:0 } );
		}
 
	}
 
}
Код AS3:
package 
{
	import aze.motion.eaze;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
 
	public class WaterSpell extends Spell 
	{
		private var _textField:TextField;
 
		public function WaterSpell() 
		{
			super();
			this.init();
		}
 
		private function init():void 
		{
			this._textField = new TextField();
			this._textField.autoSize = TextFieldAutoSize.CENTER;
 
			var textFormat:TextFormat = new TextFormat();
			textFormat.size = 50;
			textFormat.color = 0x4FD5DF;
			textFormat.bold = true;
 
			this._textField.defaultTextFormat = textFormat;
 
			this._textField.text = 'WATER!!!';
 
			super.addChild(this._textField);
		}
 
		override public function execute():void 
		{
			eaze(this._textField).to(1, { alpha:0 } );
		}
	}
 
}

Ну а дальше немного сложней... Я с час думал, как же сделать пример без всяких парадигм и мне пришло только то, что нужно создать класс, который будет обрабатывать нажатия кнопок. Нажатия кнопок мы будем связывать с классами-заданиями, в которых и будем вызывать методы мага и заклинаний. Это немного неправильно, но если Вы говорите о переполнения класса Main, то для Вас это будет самое то.

Вот класс, который обрабатывает нажатия -
Код AS3:
package 
{
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
 
	public class Controller
	{
		private var _keys:Object = { };
		private var _tasks:Object = { };
 
		public function Controller() 
		{
 
		}
 
		public function setDependence(keyCode:uint, task:Task):void
		{
			trace(keyCode, task)
			this._tasks[String(keyCode)] = task;
		}
 
		public function update():void
		{
			var isKeyDownValid:Boolean;
 
			for (var item:String in this._keys)
			{
				isKeyDownValid = this._tasks[item];
				trace(item, this._tasks[item])
				if (isKeyDownValid)
				{
					(this._tasks[item] as Task).execute();
					return;
				}
			}
		}
 
		public function clearKeys():void
		{
			for (var item:String in this._keys)
			{
				delete this._keys[item];
			}
		}
 
		public function get keys():Object 
		{
			return _keys;
		}
 
	}
 
}
И вот классы-задания -
Код AS3:
package 
{
	import flash.display.DisplayObjectContainer;
	import flash.geom.Point;
 
	public class FireSpellTask extends SpellTask 
	{
		private var _mage:Mage;
		private var _view:DisplayObjectContainer;
 
		public function FireSpellTask(view:DisplayObjectContainer, mage:Mage) 
		{
			this._view = view;
			this._mage = mage;
		}
 
		override public function execute():void 
		{
			if (this._mage.isRun) return;
 
			this._mage.setState(MageSkinType.FIRE_SPELL_MAGE_SKIN);
			var spell:Spell = SpellFactory.getSpell(SpellType.FIRE_SPELL_TYPE) as Spell;
			var randomPoint:Point = super.getPointImpakt();
 
			spell.x = randomPoint.x;
			spell.y = randomPoint.y;
 
			this._view.addChild(spell);
 
			spell.execute();
		}
 
	}
 
}
Код AS3:
package 
{
	import flash.display.DisplayObjectContainer;
	import flash.geom.Point;
 
	public class WaterSpellTask extends SpellTask 
	{
		private var _mage:Mage;
		private var _view:DisplayObjectContainer;
 
		public function WaterSpellTask(view:DisplayObjectContainer, mage:Mage) 
		{
			this._view = view;
			this._mage = mage;
		}
 
		override public function execute():void 
		{
			if (this._mage.isRun) return;
 
			this._mage.setState(MageSkinType.WATER_SPELL_MAGE_SKIN);
 
			var spell:Spell = SpellFactory.getSpell(SpellType.WATER_SPELL_TYPE) as Spell;
			var randomPoint:Point = super.getPointImpakt();
 
			spell.x = randomPoint.x;
			spell.y = randomPoint.y;
 
			this._view.addChild(spell);
 
			spell.execute();
		}
	}
 
}
И их базовый класс -
Код AS3:
package 
{
	public class Task 
	{
		public function execute():void{}
 
	}
 
}
А связываем это все в классе-конфигурации приложения -
Код AS3:
package 
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.ui.Keyboard;
	import flash.ui.KeyboardType;
 
	public class Config 
	{
		private var _viewPort:DisplayObjectContainer;
		private var _whiteMage:Mage;
		private var _world:World;
		private var _controller:Controller;
 
		public function Config(viewPort:DisplayObjectContainer) 
		{
			this.init(viewPort);
		}
 
 
 
		private function init(viewPort:DisplayObjectContainer):void
		{
			this._viewPort = viewPort;
			this._controller = new Controller();
 
			this.installMageSkinFactory();
			this.installSpellFactory();
 
 
			this._whiteMage = this.createMage();
			this._whiteMage.setState(MageSkinType.DEFAULT_MAGE_SKIN);
 
			this.installSpellTaskMap();
 
			this._viewPort.addChild(this._whiteMage);
 
 
			this.installViewPort();
 
 
		}
 
		private function installSpellTaskMap():void
		{
			this.setSpellTaskMap(Keyboard.NUMBER_1, new FireSpellTask(this._viewPort, this._whiteMage));
			this.setSpellTaskMap(Keyboard.NUMBER_2, new WaterSpellTask(this._viewPort, this._whiteMage));
		}
 
		private function setSpellTaskMap(keyCode:uint, task:Task):void
		{
			this._controller.setDependence(keyCode, task);
		}
 
		private function installViewPort():void
		{
			this._viewPort.stage.addEventListener(KeyboardEvent.KEY_DOWN, viewPort_keyDownHandler);
			this._viewPort.stage.addEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMoveHandler);
		}
 
		private function stage_mouseMoveHandler(event:MouseEvent):void 
		{
			this._whiteMage.x = event.stageX;
			this._whiteMage.y = event.stageY;
		}
 
		private function viewPort_keyDownHandler(event:KeyboardEvent):void 
		{
			this._controller.keys[event.keyCode] = true;
			this._controller.update();
			this._controller.clearKeys();
		}
 
		private function createMage():Mage
		{
			return new WhiteMage();
		}
 
		private function installSpellFactory():void
		{
			SpellFactory.setSpellMap(this.createFireSpell(), SpellType.FIRE_SPELL_TYPE);
			SpellFactory.setSpellMap(this.createWaterSpell(), SpellType.WATER_SPELL_TYPE);
		}
 
		private function installMageSkinFactory():void
		{
			MageSkinFactory.setMageSkinMap(this.createDefaultMageSkin(), MageSkinType.DEFAULT_MAGE_SKIN);
			MageSkinFactory.setMageSkinMap(this.createFireSpellMageSkin(), MageSkinType.FIRE_SPELL_MAGE_SKIN);
			MageSkinFactory.setMageSkinMap(this.createWaterSpellMageSkin(), MageSkinType.WATER_SPELL_MAGE_SKIN);
		}
 
		private function createDefaultMageSkin():DisplayObject
		{
			var circle:DisplayObjectContainer = this.createCircle(30, 0x9D9191);
 
			var rect:DisplayObject = this.createRect(30, 30, 0x9FB37B);
			rect.x -= rect.width / 2;
			rect.y -= rect.height / 2;
 
			circle.addChild(rect);
 
			return circle;
		}
 
		protected function createCircle(radius:Number, color:uint):DisplayObjectContainer
		{
			var circle:Sprite = new Sprite();
			circle.graphics.beginFill(color);
			circle.graphics.drawCircle(0, 0, radius);
			circle.graphics.endFill();
 
			return circle;
		}
 
		protected function createRect(width:Number, height:Number, color:uint):DisplayObject
		{
			var rect:Shape = new Shape();
			rect.graphics.beginFill(color);
			rect.graphics.drawRect(0, 0, width, height);
			rect.graphics.endFill();
 
			return rect;
		}
 
		private function createFireSpellMageSkin():DisplayObject
		{
			var circle:DisplayObjectContainer = this.createCircle(30, 0xEC4242);
 
			var rect:DisplayObject = this.createRect(30, 30, 0xFDAB31);
			rect.x -= rect.width / 2;
			rect.y -= rect.height / 2;
 
			circle.addChild(rect);
 
			return circle;
		}
 
		private function createWaterSpellMageSkin():DisplayObject
		{
			var circle:DisplayObjectContainer = this.createCircle(30, 0x46E8C8);
 
			var rect:DisplayObject = this.createRect(30, 30, 0x4E49E4);
			rect.x -= rect.width / 2;
			rect.y -= rect.height / 2;
 
			circle.addChild(rect);
 
			return circle;
		}
 
		private function createFireSpell():Class
		{
			return FireSpell;
		}
 
		private function createWaterSpell():Class
		{
			return WaterSpell;
		}
 
 
	}
 
}
Обработку событий конечно тоже нужно вынести в отдельный класс, но для примера пойдет, если что сами вынесите.
Ну и напоследок главный класс -
Код AS3:
package 
{
	import flash.display.Sprite;
 
	public class Main extends Sprite 
	{
 
		public function Main() 
		{
			super();
			new Config(this);
		}
 
	}
 
}
Я понимаю, что понять это тяжело и кода много, но а чего Вы хотели?

Старый 21.04.2015, 23:25
OlmerDale вне форума Посмотреть профиль Отправить личное сообщение для OlmerDale Найти все сообщения от OlmerDale
  № 5  
Ответить с цитированием
OlmerDale
[+1 09.05.15]

Регистрация: Jan 2015
Сообщений: 113
Жать 1 и 2...
mage.swf   (24.0 Кб)
Вложения
Тип файла: swf mage.swf (24.0 Кб, 118 просмотров)

Старый 22.04.2015, 00:00
dimarik вне форума Посмотреть профиль Отправить личное сообщение для dimarik Найти все сообщения от dimarik
  № 6  
Ответить с цитированием
dimarik
.
 
Аватар для dimarik

модератор форума
Регистрация: Sep 2003
Адрес: Москва
Сообщений: 4,630
Записей в блоге: 20
Нормально. Только это не люблю:

Код AS3:
override public function execute():void
За модификатор доступа после оверрайда. Можно чуть человечнее...

Код AS3:
public override function execute():void
За if в одну строчку. Не поставить никак бряк на return.
Код AS3:
if (this._mage.isRun) return;
Можно так
Код AS3:
if (this._mage.isRun) 
    return;
или
Код AS3:
if (this._mage.isRun) {
    return;
}
__________________
Воспитан в TimeZero. Работаю в Mail.ru.

Старый 22.04.2015, 10:48
caseyryan вне форума Посмотреть профиль Отправить личное сообщение для caseyryan Найти все сообщения от caseyryan
  № 7  
Ответить с цитированием
caseyryan
 
Аватар для caseyryan

Регистрация: Jun 2012
Адрес: Новосибирск
Сообщений: 6,644
Записей в блоге: 4
Цитата:
За if в одну строчку. Не поставить никак бряк на return.
Код AS3:
if (this._mage.isRun) return;
ибо если отключить return, то и само условие не нужно
Код AS3:
//if (this._mage.isRun) return;
Но лучше так, да.
Код AS3:
if (this._mage.isRun) {
    return;
}
Цитата:
Нормально. Только это не люблю:
Код AS3:
override public function execute():void
в FD это шаблон по умолчанию. Дело привычки

Старый 22.04.2015, 20:33
dimarik вне форума Посмотреть профиль Отправить личное сообщение для dimarik Найти все сообщения от dimarik
  № 8  
Ответить с цитированием
dimarik
.
 
Аватар для dimarik

модератор форума
Регистрация: Sep 2003
Адрес: Москва
Сообщений: 4,630
Записей в блоге: 20
Цитата:
Сообщение от caseyryan Посмотреть сообщение
ибо если отключить return, то и само условие не нужно
Код AS3:
//if (this._mage.isRun) return;
Но лучше так, да.
Код AS3:
if (this._mage.isRun) {
    return;
}
Я не понял. Я имел ввиду точку останова на строке, содержащей return при выполнении условия, а не только на самом условии.
__________________
Воспитан в TimeZero. Работаю в Mail.ru.

Старый 22.04.2015, 21:12
OlmerDale вне форума Посмотреть профиль Отправить личное сообщение для OlmerDale Найти все сообщения от OlmerDale
  № 9  
Ответить с цитированием
OlmerDale
[+1 09.05.15]

Регистрация: Jan 2015
Сообщений: 113
Вот по поводу if в одну строчку я с Вами полностью согласен. Когда-то у меня прям мания была писать в одну строчку или не писать скобки. Но потом я понял, что нужно уважать людей, которые будут работать с твоим кодом и пришлось отказаться от привычки. Но иногда, как это видно, в черновом варианте все ещё проскальзывает.
А вот по поводу override я несогласен с Вами. Как правило все методы, свойства и аксессоры помеченные, как public, кучкуются рядом и когда изучаешь код визуально, то лично мне кажется лучше смотреть -
Код AS3:
public function
override public function
public function
чем -
Код AS3:
public function
public override function
public function
Добавлено через 44 секунды
В первом случаи визуально, как-то быстрее определяешь что метод переопределен.

Добавлено через 1 минуту
И в автокомплите так быстрее, ведь стоит только набрать override, а не public override.

Старый 22.04.2015, 22:27
dimarik вне форума Посмотреть профиль Отправить личное сообщение для dimarik Найти все сообщения от dimarik
  № 10  
Ответить с цитированием
dimarik
.
 
Аватар для dimarik

модератор форума
Регистрация: Sep 2003
Адрес: Москва
Сообщений: 4,630
Записей в блоге: 20
"несогласен" пишется раздельно.
__________________
Воспитан в TimeZero. Работаю в Mail.ru.

Создать новую тему Ответ Часовой пояс GMT +4, время: 17:10.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


Часовой пояс GMT +4, время: 17:10.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.