Просмотр полной версии : Структура написания приложения
zzSpirit
10.04.2013, 04:57
Здравствуйте, уважаемые программисты!
После процедурного программирования все не могу понять, как всетаки начать писать игру...
До паттернов еще не дошел, хочу что-нибудь простенькое для себя пока написать, что бы убрать непонятки.
К примеру, у меня в игре есть меню и сама игра. Пробовал сделать 2 класса Menu и Game и вызывать их из главного класса, но тут возникает проблема - приходится передавать ссылки на класс Main и на прочие...
Решил сделать такую структуру:
package sources
{
import flash.display.*;
import flash.events.*;
public class Main extends Sprite
{
public function Main():void
{
if(stage) init(); else addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE,init);
// тут инициализация
menu();
}
private function menu():void
{
// тут главное меню
}
private function game():void
{
// тут код игры
function somethingFunction(e:Event):void
{
}
function enterFrameHandler(e:Event):void
{
}
}
}
}
Но тут мне не нравится что все в одном классе, получится слишком длинный код в итоге, где сложно что-то найти поменять и т.д. + неудобно что у меня функции somethingFunction() и enterFrameHandler() располагаются в методе game(). А если я вынесу их за пределы метода game() - то теряется структура и читаемость кода, хотя так читаемость кода тоже не очень хорошая.
Кто как делает?
Добавлено через 1 минуту
Читал другие топики, но там тоже советуют посмотреть как другие приложения написаны, я смотрел, но в основном они также и написаны))) В главном файле
приходится передавать ссылки на класс Main и на прочие...Приходится? Кому и зачем они вдруг понадобились?
ООП предполагает наличие объекта, над которым производятся какие то процедуры. Например, в JS большая сложная функция jQuery работает над DOM. В AS это Object поэтому от "процедурного" программирования Вы никуда не уйдете. Только процедуры называются функциями и работают они по большей частью со ссылками на разные объекты:) Нарисовали бы логику для начала по-детальнее - что куда? Так и замысел ваш станет более понятен вам самому, а за ним и умысел увидим.
zzSpirit
10.04.2013, 06:54
Приходится? Кому и зачем они вдруг понадобились?
Недавно я писал *****код, в котором передал ссылку на Main в класс Game, чтобы там создать экземпляр класса APIConnection (vkontakte api). Все получилось и даже выполнял запросы, хотя код очень корявый.
Зачем я так сделал? Перед этим я создавал экземпляр APIConnection в Main классе и передавал ссылку на экземпляр в экземпляр класса Game, но это выдало несколько ошибок, причем не в моих классах, а в классах VK... Понял что это неправильно и так больше делать не стал.
Теперь понял что все это бред и все это надо писать в классе Main. Только код то длинный получается, я в нем начинаю путаться, а если ошибки возникать начинают, в которых компилятор не указывает номер строки - то я полчаса мучаюсь с этим кодом и в итоге создаю новый проект и пишу все снова.
А если так писать всю игру - то несколько тысяч строк кода в классе Main будет в итоге - так и должно быть?
Добавлено через 11 минут
ООП предполагает наличие объекта, над которым производятся какие то процедуры. Например, в JS большая сложная функция jQuery работает над DOM. В AS это Object поэтому от "процедурного" программирования Вы никуда не уйдете. Только процедуры называются функциями и работают они по большей частью со ссылками на разные объекты:) Нарисовали бы логику для начала по-детальнее - что куда? Так и замысел ваш станет более понятен вам самому, а за ним и умысел увидим.
Вроде бы все понятно, но ведь в главном файле код получится на несколько тысяч строк кода - меня это пугает, т.к. сложно найти ошибку и очень запутанно все будет. Еще методы VK.api работают так, что они не возращают значение в переменную, а вызывают 1 функцию при удаче и другую при неудаче. И у меня получается куча функций, куча api-запросов, причем в этих функциях по одной строчке кода. То есть идет запрос, потом функция возврата значения, потом функция ошибки, потом опять запрос и т.д.
В общем куча таких непоняток, которые мне кайф от программирования прям ломают.
Никакого прогресса, стою на месте, сдвинуться не могу, т.к. не понимаю куда двигаться. Но спать не иду :)
В вашем словесном потоке очень трудно разобраться, а значит и помочь вам. Код в студию и комменты к нему. А вообще есть видеокурсы по программированию на апи вк. Согласен, апи неидеально, но вполне се работоспособно :)
iflamberg
10.04.2013, 13:44
Я уже много раз говорил. Не придумывайте велосипеды. Сначала посмотрите как работают чужие. Изучите движки, как там построено, почитайте туторы по играм. Зачем мучаться? Один уже помучался - скопируйте его наработки.
MikroAcse
10.04.2013, 13:49
А я использую кастрированный MVC без модели. Т.е. главный класс создает Controller, который загружает и парсит данные, а потом создает вьюшку, которая использует состояния для отображения (MenuState, GameState extends acse.display.State).
Получается очень простая структура.
А я использую кастрированный MVC без модели Это не MVC .
Это другой паттерн :) Это паттерн пылесос : vacuum cleaner :faceplam
несколько тысяч строк кода в классе Main будет в итоге - так и должно быть?
Так быть не должно, Б-же упаси от такого.
Код должен быть разбит по мелким и понятным классам. Объекты создаются по мере надобности. Тот, кто создал объект, дергает его методы и слушает его события. Созданный объект ничего не знает о своем создателе и шлет наверх события в надежде, что их кто-то услышит.
Перед этим я создавал экземпляр APIConnection в Main классе и передавал ссылку на экземпляр в экземпляр класса Game, но это выдало несколько ошибок, причем не в моих классах, а в классах VK... Понял что это неправильно и так больше делать не стал.
Создавать APIConnection в Main и передавать его в Game - это как раз очень правильно, вы зря отказались от этого направления. То, что RTE вылетело из библиотеки вконтакта, еще не означает, что ошибка там. Скорее всего, вы кормите туда кривые данные. Продолжайте копать (:
zzSpirit
12.04.2013, 04:02
Наверное лучший совет:
Я уже много раз говорил. Не придумывайте велосипеды. Сначала посмотрите как работают чужие. Изучите движки, как там построено, почитайте туторы по играм. Зачем мучаться? Один уже помучался - скопируйте его наработки.
Действительно, когда смотрю чужие коды, туторы и т.д. - много вопросов сами с собой решаются и это большое удовольствие мне приносит. Иногда бывает даже создаю новую тему с вопросом, пока сформулирую вопрос и пока попробую написать код чтобы показать в чем проблема - вопрос решается.
В вашем словесном потоке очень трудно разобраться, а значит и помочь вам. Код в студию и комменты к нему. А вообще есть видеокурсы по программированию на апи вк. Согласен, апи неидеально, но вполне се работоспособно
Да хрен с ним, с кодом, уже это все не так важно :)
В общем, забью на лень и буду все подряд по теме изучать. iflameberg похоже наставил меня на путь истинный :)
Всем спасибо.
Добавлено через 22 минуты
А хотя, убежусь кое в чем, пользуясь случаем:
Так быть не должно, Б-же упаси от такого.
Код должен быть разбит по мелким и понятным классам. Объекты создаются по мере надобности. Тот, кто создал объект, дергает его методы и слушает его события. Созданный объект ничего не знает о своем создателе и шлет наверх события в надежде, что их кто-то услышит.
Это я и так знал, но спасибо за то что напомнил об этом и я лучше все обдумал сейчас о структуре.
Создавать APIConnection в Main и передавать его в Game - это как раз очень правильно, вы зря отказались от этого направления. То, что RTE вылетело из библиотеки вконтакта, еще не означает, что ошибка там. Скорее всего, вы кормите туда кривые данные. Продолжайте копать (:
Вроде бы данные были правильные, т.к. в Main запросы работали, в Game - нет, хотя если передать Main ссылкой в Game или написать parent.stage и т.д. - все работало. Ладно, фиг с ним, ща это не так важно, сам разберусь думаю.
Меня очень волнует - правилен ли сам подход такой? прям не терпится узнать... Описываю:
если бы я делал кадрами - то я бы сделал на первом кадре экран загрузки, на втором меню, на третьем игру, на четвертом магазин...
Правильно ли сделать также классами(вместо каждого кадра по классу), что бы не писать все это в главном классе?
То есть у меня будет главный класс Main, который будет создавать экземпляры след. классов и запускать их:
Main - главный класс, который запускает все остальные
LoadGame - экран загрузки игры
Menu - меню игры
Game - сама игра
Shop - магазин игры
То есть Main первым делом запускает загрузку и слушает ее, как игра загрузилась, делаем LoadGame = null, чтоб не засорять память и создаем класс Menu... Блин, вот опять лажа получилась. Как я из класса Menu вызову класс Game, не используя parent?
Также, при выходе из класса Game как я скажу классу Main чтоб он обнулил класс Game и запустил класс Menu? Хм... По идее Main слушает все классы, но я не пойму как сделать прослушивание не покадрово, не с какой-то переодичностью типа таймера, а чтоб память не засорялась. Т.е. чтоб прослушка не была ежесекундной к примеру, а чтоб Game сказал классу Main что игра окончилась и все, а не было постоянной проверки окончилась ли игра, в игре ведь и так расчетов много очень, нефиг проц грузить.
Кароче нифига я не знаю, фигню понаписал, буду исходники изучать... Но если ответите как это теоритически все работает - очень рад буду. А то пока не пойму как это работает - к паттернам как-то очень хочется переходить, т.к. напишу код, я в нем путаюсь, мне он не нравится, он становится большим - удаляю, замучился уже.
Ну ладно, iflamberg дал мне совет, воспользуюсь им...
Psycho Tiger
13.04.2013, 10:19
Ну, я бы сделал вот так (код писал прямо на форуме, не ручаюсь что работает):
class AbstractStep extends Sprite {
public static const GAME_SCREEN:String = 'gameScreen';
public static const LOAD_SCREEN:String = 'loadScreen';
protected function gotoScreen(screenName):void{
//вызываем на рассылку собственное событие, внутри передаем screenName
dispatchEvent(new MyEvent(MyEvent.CHANGE_SCREEN, screenName));
}
}
Классы наследуются от AbstractStep.
class Game extends AbstractStep
Когда нужно перейти на другой экран, то дёргается метод AbstractStep'а.
Т.е. внутри Game, например:
gotoScreen(LOAD_SCREEN);
А в Main:
private var _currentScreen:AbstractScreen;
private var _hash:Object ={}
public function Main(){
//присваиваем классы
_hash[AbstractScreen.GAME] = Game;
_hash[AbstractScreen.LOAD_SCREEN] = LoadScreen;
_currentScreen = new Game();
addChild(_currentScreen);
_currentScreen.addEventListener(MyEvent.CHANGE_SCREEN, onScreenChanged);
}
private function onScreenChanged(event:MyEvent):void{
_currentScreen.removeEventListener(MyEvent.CHANGE_SCREEN, onScreenChanged);
removeChild(_currentScreen);
_currentScreen = _hash[event.screenName]();
addChild(_currentScreen);
_currentScreen.addEventListener(MyEvent.CHANGE_SCREEN, onScreenChanged);
}
Также, при выходе из класса Game как я скажу классу Main чтоб он обнулил класс Game и запустил класс Menu? Хм... По идее Main слушает все классы, но я не пойму как сделать прослушивание не покадрово, не с какой-то переодичностью типа таймера, а чтоб память не засорялась. Т.е. чтоб прослушка не была ежесекундной к примеру, а чтоб Game сказал классу Main что игра окончилась и все, а не было постоянной проверки окончилась ли игра, в игре ведь и так расчетов много очень, нефиг проц грузить.События. Main слушает событие GameEvent.GAME_OVER от Game. Тот посылает это событие, когда игра закончилась. Мейн ловит его, обнуляет игру и показывает меню.
И так со всем.
Psycho Tiger,
var xml=<screens>
<screen id="1" name="gameScreen"/>
<screen id="2" name="loadScreen"/>
</screens>
var screen:XMLList=xml.screen.(@id=='1').
Babylon - действительно зачем придумывать архитектуры разные, паттерны проектирования и т.п. - когда есть xml - который можно пихнуть отовсюду... ужос
В чем противоречия между ПП и Xml? Если XML относится к модели, чем плохо?
Ну причем тут вообще хмл как таковой? Хмл - если вы вкурсе - язык разметки. Тоесть отдельный язык так сказать. As3 - язык. Никто не против совмещать 2 языка, и это приходится делать в ряде стандартов, но не стоит в любую кашу сувать другой язык. Я могу поддержать вас только в том, что это ваша фича ( или баг хД) - что никто так не делает собственно.
хмл он для чего нужен по сути? для удобства работы с данными, которые переданы из вне. Будь это конфиг или локализатор.
caseyryan
13.04.2013, 15:45
хмл он для чего нужен по сути? для удобства работы с данными, которые переданы из вне. Будь это конфиг или локализатор.
Совсем нет. Я частенько использую XML вшитый в программу. Просто потому что это удобный формат хранения данных, с простой и понятной структурой
XML - язык разметки только для веб дизайнеров, а для кодеров это не что другое. Для некоторых конечно нет ничего хорошего в разметке модели, рендеринге видов и внешнем коммандере :)
Александр Мостовой
13.04.2013, 17:59
С xml работать впринципе можно как с быстрым промежуточным вариантом, но только если следовать правилу: изменять его только через методы и сеттеры соотвтетствующего объекта-хранителей этого XML.
Тогда не сложно будет в случае необходимости перейти на более формализованную структуру.
С xml работать впринципе можно как с быстрым промежуточным вариантом, но только если следовать правилу: изменять его только через методы и сеттеры соотвтетствующего объекта-хранителей этого XML.
Тогда не сложно будет в случае необходимости перейти на более формализованную структуру.
Насчет сеттеров и геттеров. XML вообще должен "торчать" только из модели. Во всех остальных случаях должна быть инкапсуляция. XML может и избыточен в описании, но он с лихвой перекрывает избыточность кодирования другими способами.
Psycho Tiger
14.04.2013, 12:54
Psycho Tiger,
var xml=<screens>
<screen id="1" name="gameScreen"/>
<screen id="2" name="loadScreen"/>
</screens>
var screen:XMLList=xml.screen.(@id=='1').
Ну в принципе да, но это бесполезно если не подразумевается загрузка отдельных экранов через разные swf, например.
Ну, то есть, если этот XML вшивать в флешку – получим ряд проблем. Например, никто не гарантирует уникальность ID'шника (он может не существовать, а может существовать аж 2), проблемы из за рефлекшена (в моём примере мы жестко ссылаемся на класс – мистайп контроллируется компилятором, в XML – строки).
У меня вообще отношение к XML'у весьма своеобразное. e4x одновременно и тащит, и требует особой внимательности. Достаточно часто и обидно падаю по RTE из за несовпадения XML / XMLList типов. По идее, это должно контроллироваться компилятором – почему он не контроллирует – не понятно...
Вообще, например, в Ruby такими штуками являются YAML файлы. Что то вроде HAML'a для XML'a, например
key1:
key2:
value1: 'hello'
value2: 'world'
Подобная штука для флеша на каком-нибудь нативном уровне была бы просто чудесна. XML действительно избыточен, в 2 из 3 случаев уместнее использовать что - то такое. Некоторый Object, который удобоварим для чтения-заполенения.
XMLList это список xml нод, а XML - это xml нода. Компилятор здесь не при делах. Он определяет несоответствие типов, и делает абсолютно корректно.
E4X появился только в AS3. До этого были костыли типа XMLtoOutput , XML2Object и др. Поэтому появление в стандарте XMLList было ожидаемо. XML в первую очередь нужен для агрегации и запросов. На JSON агрегацию также технично не сделаешь, а jQuery для AS тоже нет, в отличии от XPath
caseyryan
15.04.2013, 07:24
По идее, это должно контроллироваться компилятором - почему он не контроллирует – не понятно...
Потому что не знает он, что туда попадет в рантайме, будет это XML или XMLList ему по барабану
Я просто не представляю как еще компилятор должен обработать данную ситуацию, иначе чем выдать ошибку о не соответствии типов.
Psycho Tiger
15.04.2013, 11:34
Я просто не представляю как еще компилятор должен обработать данную ситуацию, иначе чем выдать ошибку о не соответствии типов.
Потому что не знает он, что туда попадет в рантайме, будет это XML или XMLList ему по барабану
XMLList может состоять и из одной ноды ) Поэтому это компилятор и должен контроллировать.
Это никогда не будет XML
root.node // XMLList
root.(@id == 'attr') //XMLList
А это никогда не будет XMLList'ом
root.node[0] //XML
Компилятор же выдает предупреждение о неправильном кол-ве элементов.
Simplifier
15.04.2013, 21:32
Так XML и XMLList же динамические классы, поэтому компилятор тут вообще не при делах, по идее
namespaces
16.04.2013, 00:27
Вот здесь (http://xitri.com/2010/10/10/flash-game-interface-template.html)есть хороший пример для заготовки шаблона, на начальном этапе этого хватит.
Для дальнейшего развития копайте в сторону готовых разработок, я бы посоветовал присмотреться к Gaia Framework. (https://github.com/stevensacks/Gaia-Framework). Давно уже в открытом доступе.
Psycho Tiger
16.04.2013, 09:46
Компилятор же выдает предупреждение о неправильном кол-ве элементов.
Хм. Ну у меня в стрикте не выдаёт :(
Если уж нравится xml - тогда используйте
MXML - так хотя бы получите проверку и автокомплиты в редакторе.
что-то вроде
<?xml version="1.0" encoding="utf-8"?>
<EventDispatcher xmlns="flash.events.*"
xmlns:fx="http://ns.adobe.com/mxml/2009"
<fx:Declarations>
<screen:Screen id="gameScreen" name="gameScreen"/>
<screen:Screen id="loadScreen" name="loadScreen"/>
<screen:Screen id="currentScreen" />
</fx:Declarations>
<fx:Script>
<![CDATA[
currentScreen = gameScreen;
]]>
</fx:Script>
</EventDispatcher>
К, сожалению, MXML не дорос до агрегатирования и боюсь уже не дорастет :).
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.