TowerDefence #1. Структура игры
Самое сложное и страшное практически в любом деле — это начать. А когда начинаешь, то дальше уже все не так страшно и сложно :) С чего же начинаются игры?
Несомненно игры начинаются с идеи, частично или детально проработанной в голове или на бумаге. В нашем случае идея уже есть, и уже не раз успешно проверена на практике другими разработчиками. Поэтому задача значительно упрощается, и в нашем случае начинать следует непосредственно с представления того, как наша игра будет устроена внутри. А проще говоря, реализация любой игры начинается с продумывания её основной структуры, на которой все будет держаться.
Как правило, для большинства игр используется одинаковый «скелет», который от игры к игре отличается лишь заменой или добавлением некоторых «суставов» и «пальчиков» для реализации уникальных особенностей отдельных игр. В общем, я тут сейчас еще бесконечно много могу писать о структуре игры, поэтому не будем тратить время и перейдем сразу к делу, составим базовую структуру нашей игры.
Базовая структура практически любой игры может выглядеть следующим образом:
По ходу развития игры данная схема будет обрастать дополнительными классами, что в итоге покажет нам как все будет взаимодействовать.
Preloader.as — это общий класс, который можно написать один раз и использовать во всех своих играх. Он отслеживает загрузку флешки и красиво демонстрирует этот процесс нашему игроку. После того как флешка загружена в нем инициализируется наше приложение App.as.
App.as — это точка входа в игру. В этом классе я обычно инициализирую общие игровые параметры, а так же при необходимости выполняю кэширование игровых ресурсов. Этот класс является уникальным для каждой игры, но его принцип работы одинаков для всех игр. Когда все параметры инициализированны и выполнено кэширование необходимых объектов или графики, этот класс создает непосредственно нашу игру Game.as.
Game.as — это ядро игры. В этом классе у меня, как правило, живут и общаются между собой игровые экраны/меню. Так же в этом классе создается и живет ядро игрового мира World.as.
World.as — это фактически игровой движок. В него загружаются и обрабатываются игровые уровни, а значит там живут и взаимодействуют между собой все игровые объекты и обрабатывается игровая логика.
Все эти четыре класса вместе — это базовая структура, которая подойдет практически для любой игры. А далее за счет дополнительных классов игра обретет свою уникальную форму. Когда базовая структура известна, остается только приступить к её реализации.
Я пока решил пропустить этап создания прелоадера, так как это довольно скучная процедура и начинать с нее не особо интересно. Тем более на данном этапе в игре нет почти никаких ресурсов, поэтому прелоадер мы интегрируем в игру чуть позже. Раз нет пока загрузчика, значит и класса Preloader.as пока тоже не будет, так что начнем с точки входа в нашу игру, с App.as. Но прежде, чем начать, я сделаю отступление и расскажу о том, как мы будем структурировать ресурсы игры и исходники.
Структурирование исходников и ресурсов игры
Мой программисткий опыт показал, что один из самых главных факторов комфортной разработки игр или приложений — это четкая и понятная структура хранения исходников и различных ресурсов. Чтобы к середине разработки игры не возникал жуткий фарш из безумного количества файлов классов и ресурсов, сваленных в одной или нескольких папках, нужно хорошенько думать над именами и аккуратно раскладывать все по папкам. Данное правило относится не только к способу хранения файлов на диске, но и к формированию исходного *.fla.
В отношении языка ActionScript 3 существует некоторое соглашение формирования исходников, которым, к сожалению, многие пренебрегают, и в следствии этого использование их классов может вызывать неудобства и потребует их правки, а конкретно я имею в виду формирование пакетов (Package).
Любой, кто хоть чуть-чуть работал с ООП, знает, что набор из нескольких классов может выполнять какую-то одну задачу, например, будь это небольшой твиннер или движок поиска пути на карте. Как правило, все классы, (основные и вспомогательные) сосредоточенные на выполнении какой-то одной задачи, группируются в один пакет. В AS3 пакет — это всего лишь обычная папка с классами, поэтому для создания пакета нам нужно просто создать папку, например «pathfinder» и положить туда класс, выполняющий поиск пути с вспомогательными для него классами. Пакеты не только облегчают работу с классами, но и решают проблему классов с одинаковыми именами.
Правила формирования пакетов и классов: имя пакета всегда начинается с маленькой буквы и не должно иметь в названии заглавных букв. Названия и имена классов начинаются всегда с заглавной буквы. Помните, имя файла класса всегда должно полностью соотвествовать имени находящемуся в нем класса. В одном файле может быть только один класс.
? так, за время работы над флеш играми я выработал для себя общую структуру хранения исходников, которую я применяю во всех своих играх. В данном уроке структура будет такой:
Обратите внимание, все исходники заключены в папку com — это нужно делать, следуя стандарту формирования пакетов во избежании случаев повторяющихся имен пакетов и классов. Название этой папки может соотвествовать зоне вашего доменного имени, например если у вас есть сайт в зоне .ru или .net то вы можете в место com использовать эти имена. Далее согласно стандарту все ваши исходные коды должны быть в папке с именем вашего домена, что в будущем позволяет их использовать в других проектах, не нарушая структуры этих проектов. Но пакет towerdefence врядли попадет в какой-то другой проект, поэтому о его имени не переживаем и называем его в честь игры. А вот папку framework следует назвать именем своего доменного имени или ника, так как в будущем она сможет легко кочевать из проекта в проект, в качестве набора инструментов, используемых в разработке, или даже как небольшой собственный движок. Кстати, класс Preloader.as туда попал как раз по той причине, что каждый раз его нет никакого смысла писать, и он будет частью набора инструментов.
Если вы что-то не поняли о формировании имен пакетов и классов или хотите узнать подробнее, то обратитесь к книге Колина Мука, там этот вопрос затрагивается более подробно.
Пишем первый код
Что же, со структурой игры и структурой исходников вроде определились и настало самое время приступить к работе. Первым делом создаем папки в таком порядке, как показано выше. Когда все папки созданы запускаем Adobe Flash и создаем новый ActionScript 3 документ и сохраняем его как TowerDefence.fla в папку Project TowerDefence.
Если вы совсем не писали ранее код для Flash, то не переживайте об этом. Никаких дополнительных редакторов и компиляторов для работы с ресурсами и кодом кроме Flash IDE вам не понадобится. Для новичков все самое необходимое есть в нативном редакторе, даже простой менеджер проекта, с которым мы и будем работать. Чтобы открыть его следуйте меню Window > Other panels > Project.
Перед вами должна появиться такая панель.
Теперь создадим новый проект. Кликните по выпадающему списку Project и выберите пункт New Project. В качестве имени проекта вводим название нашей игры TowerDefence и указываем основную папку Project TowerDefence с нашими исходниками, а после жмем кнопку Create.
Если все сделано правильно, то содержимое окна должно выглядеть примерно так.
Теперь мы можем быстро создавать новые классы и папки (пакеты), а также открывать и редактировать уже существующие, не покидая окна Flash IDE.
Совет: для комфортной работы с проектом во Flash IDE вы можете расставить панели инструментов как на этом скриншоте — 270кб
App.as
Настало время создать точку входа в приложение и написать первый код. Откройте папку towerdefence в панели проекта и нажмите кнопочку создания нового класса в панели проекта. Теперь в поле Class допишите к уже существующему пути название нового класса, чтобы получилось так: com.towerdefence.App и нажмите кнопку Create Class. Новый класс должен появиться в папке towerdefence и тут же открыться в новом окне для редактирования. В будущем все эти действия должны стать для вас привычными действиями создания новых классов.
Теперь необходимо связать наш класс App.as с TowerDefence.fla. Но прежде чем это сделать, давайте изменим код следующим образом:
package com.towerdefence { // Подключаем стандартный класс Sprite import flash.display.Sprite; // Наследуем от него наш класс public class App extends Sprite { // Initialization: public function App() { trace("Hello world!!1"); } } }
Это позволит нам тут же проверить работоспособность приложения после того как мы свяжем его с документом.
Переключаемся на вкладку с нашим чистым документом и находим панель Properties. Она должна быть включена по умолчанию, но если вдруг по какой-то причине её нет, то включите её через меню Window. ? на ней в поле class вписываем путь и имя нашего класса: com.towerdefence.App, а так же заодно меняем fps на 35 кадров и размеры документа на 640x480. После этого сохраняем изменения в документе и изменения в классе App.as и жмем ctrl+enter. Если все сделано правильно, то перед вами должно появиться белое окно и в панели output строка "Hello world!!1" — это значит что все работает как нужно и пора приступать к созданию класса Game.as.
Game.as
Для создания класса с игрой мы повторяем все те же самые действия, что и для App.as. Попробуйте сделать это сами, это будет полезной практикой. Только содержимое trace(); в App.as и в Game.as замените на что-то более информативное, например "Application initialized...", "Game initialized...", позже это позволит увидеть в какой последовательности создаются классы.
После того как создали Game.as модифицируем код класса App.as следующим образом:
package com.towerdefence { import flash.display.Sprite; public class App extends Sprite { public static const APP_VERSION:String = "TowerDefence 0.1 - Oct 15, 2010"; // Размер документа по ширине/высоте public static const SCR_W:int = 640; public static const SCR_H:int = 480; // Середина документа по ширине/высоте public static const SCR_WDIV:int = 320; public static const SCR_HDIV:int = 240; // Vars private var _game:Game; // Initialization: public function App() { trace(APP_VERSION); _game = new Game(); addChild(_game); } } }
Обратите внимание, я сразу добавил статические константы в которых содержится параметры нашего документа, позже мы их будем использовать везде в коде, чтобы если вдруг когда-нибудь понадобится изменить эти параметры, нам не пришлось переписывать пол игры под новые размеры :)
?нформация: Все переменные, доступные только внутри класса, всегда должны начинаться с _подчеркивания — так нам будет проще отличать внутренние переменные от глобальных. А все константы всегда пишутся ЗАГЛАВНЫМ?_БУКВАМ? и их содержимое нельзя менять в ходе выполнения программы.
Код выше создает экземпляр класса Game.as, сохраняет ссылку на него в переменной _game и добавляет на сцену внутрь класса App методом addChild(); после чего Game.as становится рабочей частью приложения.
Если все сделано правильно, то после компиляции (ctrl+enter) в окне output должны появится две строки:
TowerDefence 0.1 - Oct 15, 2010 Game initialized...
Домашнее задание
Я решил, что в конце каждого урока буду придумывать небольшое домашнее задание, целью которого будет вносить какие-либо изменения в код и получать требуемый результат. Это поможет вам быстрее понимать что к чему и вносить любые изменения в игру самостоятельно. Его выполнение лежит полностью на вашей совести :) Решение домашнего задания будет обязательно продемонстрировано в следующей части за счет чего вы сможете проверять свои решения.
Сегодняшнее домашнее задание будет достаточно простым: вам необходимо добавить в игру класс World.as так же как мы это сделали с предыдущими двумя классами.
Внимание! В ходе небольшого разбирательства стало известно, что в новой версии Flash CS5 имя World зарезервированно под какой-то еще не документированный системный класс. Поэтому в качестве имени класса для игрового мира следует использовать Universe.as.
Заключение
Это первый вводный урок, который показывает простой принцип создания нового документа и основных классов. Я думаю, что он будет мало интересен опытным разработчикам, но все же без вводного урока никак не обойтись, так что гуру программирования прошу меня извинить :) В последующих частях будет больше упора на создание игры, а не на подробные описания действий.
Ссылка на исходники — CS4, *.zip, 12 кб.
Что дальше?
В следующем уроке мы разберем игровую логику, создадим игровую карту и получим первый визуальный результат.
Содержание
- Вступление
- Структура игры
- Карта проходимости
- Первый враг
- Готовимся к поиску пути
- Поиск пути
- Редактор уровней
- Движение врагов
- Первая башня
- Кэширование объектов
- Полоса жизни
- Вражеские волны
- Загрузка вражеских волн
- Продолжение следует...
Ох, братюнь, не думал, что ты с САМОГО начала будешь. Гляди как бы миллиардами клонов не заполонили рынок ибо ОЧЕНЬ детально.
Спасибо за пост и куда дз то показывать?
Огромное сасибо за труд.
Антон молодца ;)
@Zarkua, начать-то с чего-то нужно. В числе моих читателей как совсем «зеленые» новички, так и матерые профи, чтобы всем было интересно мне прийдется балансировать по серединке.
Рынок и без меня уже переполнен ТоверДефенсами, впрочем этот вопрос мы уже детально обсудили на флешгеймдев.ру — я сделал выводы и упростил программу урока.
Домашку никуда показывать не нужно — это лишь мотиватор для читателей покопаться в исходниках и разобраться что к чему. А так же повод включить мозк и научится немножко фантазировать, а не просто копипастить готовый результат :)
Антон, у тебя очень профессионально и грамотно получается писать статьи! Его приятно и понятно читать. Я, хоть и все это знаю, но мне тоже интересно читать подобные тексты и смотреть, как работают другие.
Не ужели я дождался :) Спасибо Антон. Все здорово. Жду продолжения!!!
Думаю наплыва клонов не будет, если количество уроков будет 10+ и сложность будет нарастать. То к финалу создания игры доберутся только самые стойкие и понимающие.
Жду продолжения. Антон,а ты полную структуру игры себе представляешь уже перед тем как делать?
?ли за основу берешь предыдущие игры(класс для меню, паузы, выбор уровня, подсчёт очков и т.п.).
Мне как раз интересно про структуру узнать :)
Замечательно. Хорошее начало, для начала:). А то что легко это только +. Насчет клонов - это все ерунда.
Супер!!!!! Хочу дальше!! А можно поинтересовать сколько всего планируется уроков? =)
При данной структуре проекта, после написания App.as, этот класс установился в качестве главного только с формулировкой towerdefence.App (т.е. без com), соответственно и в самом коде класса пришлось убрать com из строки указания пакета. Почему именно так?
Ох и непростую задачу ты перед собой поставил! Могу лишь пожелать удачи и терпения. Самое сложное для начинающих это правильно зацепить классы друг за друга, чтобы затем игры делались просто и удобно. Насколько я понял - ты решил показать как это делается. Супер!
По поводу клонов - механика игр повторяется в миллионах проектов. Какие из них успешны? Зависит ли успех от открытости технологий? Успели ли надоесть шутеры за почти 20 лет своей истории? Так ли часто новаторские игры успешнее чем клоны? Считаю что делать клон работа адская. Собственно этим сейчас и занимаюсь :D
@Руслан, о количестве уроков я не думал поэтому не знаю сколько их получится. Все зависит от количества и сложности задач которые возникнут по ходу разработки.
@?лья, такая проблема скорее всего возникла потому что TowerDefence.fla сохранен в папку com, а не в папку Project TowerDefence. *.fla докумен должен быть за приделами папки com.
@RaymondGames, успешны те клоны, которые по настоящему интересны и увлекательны. Открытость технологий позволяет делать более качественные игры с наименьшими затратами. Шутеры как и игры любого другого жанра бывают разными, поэтому тут на вкус и цвет. В любом случае сделать клон всегда намного проще и возможно выгоднее чем придумать и разработать что-то новое и оригинальное ;)
Знаю, что Mining Truck 2 был продан 15 октября. Когда будет релиз? Очень поиграть хочется:)
Сделать успешный клон ~= придумать новое и оригинальное :D Либо мы о разных вещах говорим. Пример - воркрафт и старкрафт. Два клона от одной компании. Ужели сделать старкрафт было на порядок проще чем придумать...тетрис-реверси?
? возможно я неправильно понимаю слово клон. По мне так все игры внутри одного жанра и со схожей механикой - клон. ? что теперь не делать экшен платформеры? Забросить сайд скроллеры? Забыть о тавер дефенсах??? Ну нет)) А про то что делать клоны проще - очень спорно. В нашей раше допустим очень долго не могли склонировать жанр экшен не смотря на доступность технологий. Видимо не всё так просто?
Вобщем я так понял ты против клонов.
@Ant.Karlov, да, все верно. Спасибо. Перенес fla-файл, поправил в нужных местах записи - все работает. Просто по скриншотам не совсем понятно, где именно должен лежать fla-файл.
Снимаю вопрос, наиграюсь на FGL:)
Привет! Классный урок!
Тока вот мне лично не понравились имена классов и переменных. )) По моему программерскому опыту... а он исходит из 5го флеша, проходит через си шарп и ас3, я бы посоветовал не использовать сокращения в именах классов и особенно переменных. Все должно называться своими именами и тогда это становится очень прозрачным.
Например SCR_W - лучше называть SCREEN_WIDTH - от этого никто не пострадает - автокомплит все сделает за вас. ?ли например класс App - можно заменить на Main, т.к. это стандарт для вхождение в любую апликацию, и именно с этого класса начинается все.
Спасибо, Антон. Я хоть и не новичек и все это знаю и использую, но всегда ж приятно почитать как работают другие, жду продолжения)))
@RaymondGames, да, похоже ты путаешь понятие клон игры с понятием жанр игры. Клон — это когда новая игра копирует ключевые особенности старой игры. ?гры в одном жанре не могут быть клонами одной игры, так как они могут иметь не только уникальное графическое представление но и оригинальные ключевые особенности которые очень сильно влияют на геймплей и в итоге игры существенно могут отличатся. При этом общая игровая концепция может оставаться прежней, что объединяет разные игры в один жанр. Тут как в кино, есть типичные боивики клоны, а есть очень оригинальные боевики.
Клон сделать просто как раз потому, что есть уже готовая игра-прототип с которой делается клон с изменением лишь его внешней части.
Я к клонам равнодушен так как просто клоны не несут ничего нового интересного, они скучные. Но если брать готовую игровую концепцию и координально её изменять, то можно получить если не новый жанр, то хотя бы просто отличную игру которая уже не будет клоном ;)
@SuperMan, согласен. Но для меня лично сокращение SCR уже давно стало полноценным словом SCREEN и эти константы наиболее часто используемые в коде игры, поэтому для очевидных констант и переменных я использую очевидные сокращения. В остальных случаях название констант пишу полностью. В урок внесу исправления.
А вот на счет Main.as не знал :) Но App.as мне нравится больше не только потому что оно везде в списках отображается в числе первых (согласно алфавиту), но и то, что это имя более емко отражает суть класса нежеле просто Main.as — что главный? Зачем главный? Куда главный? :) Спасибо за замечания!
@SuperMan, кстати App.as так же записан в сокращенной форме потому что в нем используются все основные статические константы и к ним приходится часто обращатся в любых других классах и строки:
myButton = new Button(Application.SCREEN_WIDTH_HALF, Application.SCREEN_HEIGHT_HALF);
// Например создание кнопки в центре экрана
— начинают быстро раздражать и мешают читаемости кода. Поэтому использование сокращений и полных имен нужно применять с умом (?МХО).
@p0lter, дата релиза игры Mining Truck 2 пока не известна. Но судя по тому как все движется и согласно моим правилам продажи игры — я чувствую, что релиз состоится не раньше ноября.
зеленые-презеленые, к тому же блондинки... ну почти :) К чему это я... а, да, хотела сказать СПАС?БО!!! Пока все понятно, даже домашка получилась "с лету". Есть пара вопросов, но это к Муку/Розенцвейгу, а не к Антону (пошла читать).
Спасибо за урок. Очень мало где можно найти описание базовой структуры игры. А я думаю, это очень важно, уметь с самого начала правильно спроектировать "скелет".
Дождались наконец! :) Надеюсь, принцип "главное - начать" будет перенесен на сами уроки и они будут появляться регулярно.
Вопрос не совсем по игре: какой плагин используется для оформления кода в статье?
Привет! По поводу
/*
myButton = new Button(Application.SCREEN_WIDTH_HALF, Application.SCREEN_HEIGHT_HALF);
// Например создание кнопки в центре экрана
*/
1. Не создаем константы - половина экрана, зачем они? они легко получаются из SCREEN_WIDTH и SCREEN_HEIGHT умножением на 0.5.
2. Создаем функцию которая создает кнопки в нужных месте и вешает им слушатели:
private function createButton(x:Number, y:Number, clickHandler:Function):Button
{
var button:Button = new Button();
button.x = x;
button.y = y;
button.addEventListener(MouseEvent.CLICK, clickHandler);
//здесь можно сделать дофига всего, потому как создание кнопки не ограничивается тока заданием слушателя
addChild(button);
return button;
}
3. В итоге в коде будет нечто типа:
createButton(Application.SCREEN_WIDTH * 0.5, Application.SCREEN_HEIGHT * 0.5. myButtonClickHandler);
//и вот эта функция сокращает сильно код создания кнопок
//вообще функции и сделаны для того что бы избегать повторение кода
Наконец мы все дождались :)
Вопрос: при такой организации получается что класс World.as вырастает в очень длинную колбасу, потому что содержит всю логику игры и обработку управлением всех объектов в игре?
Ну вот понеслось :) Сколько кодеров столько и вариантов называть переменные функций и их использование не напугайте Антона....
Че-то не получается world.as добавить (((
Пишет: Game.as, Line 10 1136:Incorrect number of arguments. Expected 2.
Вот класс Game.as
package com.towerdefence{
import flash.display.Sprite;
public class Game extends Sprite {
private var _world:World;
public function Game() {
trace("Game initialized...");
_world = new World();
addChild(_world);
}
}
}
вот класс World.as
package com.towerdefence {
import flash.display.Sprite;
public class World extends Sprite{
public function World() {
trace("World initialized...");
}
}
}
@SuperMan,
> 1. Не создаем константы - половина экрана, зачем они? они легко получаются из SCREEN_WIDTH и SCREEN_HEIGHT умножением на 0.5.
Как правило элементы пользовательского интерфейса рассполагаются где угодно, но только не посередине экрана, а значит помимо получения середины экрана в строке будут и другие различные вычисления чтобы получить нужную позицию. Честно, еще в MT2 я делал точно так же как ты говоришь. За счет чего при создании кнопок и других элементов у меня в коде постоянно дублируется умножение ширины и высоты на .5 — посмотрев на все это я решил, что в следующем проекте обязательно заведу отдельную константу чтобы избежать лишних вычеслений и повысить читаемость кода. Более того 2-3 раза я умудрился забыть поставить точку в .5 при делении ширины или высоты, что в последующем убило 5-10 минут времени на поиск кнопок на экране и на поиск этого бага соответственно :) Когда в строке большая формула расчета выравнивая кнопки относительно чего либо, то недостающей точки можно легко не заметить.
> 2. Создаем функцию которая создает кнопки в нужных месте и вешает им слушатели:
Все правильно. Но поскольку я обычно пишу отдельный класс для кнопок, то вся инициализация кнопок производится в нем согласно указанной разновидности кнопки :)
@jarofed, я тоже очень надеюсь, что уроки будут появляться регулярно :)
Для подсветки кода используется SyntaxHighlighter — ссылку на сайт разработчика можно узнать наведя мышку на код и кликнув на кнопку с «вопросиком» в появившейся панели.
@shaman4d, переживать не стоит, World.as — это лишь ядро игровой логики, в нем будет выполнятся основной процесс для всех объектов и будут выполнятся только самые важные условия для игровой логики. Логика отдельных объектов не имеющих особого отношения к игровому миру в целом, будет существовать внутри их классов. Представленная структура игры является базовой и она пока не отражает сути всей игры.
Антон, приветствую.
Всё же кодить во FlashIDE - удел суровых челябинских флэшеров.
Настоятельно советую тебе попробовать FlashDevelop - особенно последний релиз - там столько вкусного..
Потрать один день - разберись. После этого ни за какие коврижки на Flash обратно не перейдёшь.
@pkasha, ошибка в 10ой строке класса Game.as, компилятор указывает на то, что при создании класса указано не верное количество параметров. К сожалению 10 строку я в коде заключенного в комментарий я точно определить не могу, как и наличие ошибки на глаз. Можете прислать исходник мне на почту.
Прежде чем компилировать игру, не забывайте сохранять все измененные классы (ctrl+s), у измененных и не сохраненных классов в названии файла (на вкладке) отображается звездочка. Если вы внесли изменения в класс и не сохранили его, то компилироваться будет та версия класса, что находится на диске (то есть от предыдущего сохранения).
@k0t0vich, спасибо за совет! Сам я не пишу код во Flash IDE так как давно бы уже убил себя об стену :) В статье написал лишь как можно кодить не имея ничего кроме Flash IDE.
Flash Develop отличная вещь, но нет версии под Mac, поэтому я пользуюсь не менее удобным TextMate.
Здравствуйте, Антон.
А как Вы относитесь к различным фрейворкам типа Flixel или PBE? Не легче ли использовать велосипед, изобретенный кем-то другим? Какие их недостатки?
Такая же ошибка, как и у pkasha. Ругается на эти две строчки:
1. _world= new World();
2. addChild(_world);
Line 1 1136: Incorrect number of arguments. Expected 2.
Line 2 1067: Implicit coercion of a value of type World to an unrelated type flash.display:DisplayObject.
World.as аналогичен Game.as - не понимаю в чем ошибка.
Уже взял на вооружение часть статьи. Делаю свою первую личную игру и поэтому хочу немного забежать вперед с вопросами. Где ты предполагаешь осуществлять перерисовку элементов? Будет ли это единая перерисовка элементов? Ведь скажем в Game.as могут быть какие-то элементы для перерисовки, ну и понятно, что в World.as тоже много чего будет перерисовываться. Ну и последний вопрос, графика кешируется в App, а передача будет осуществляться дочерний класс в виде параметра в конструктор?
Max D, с Flixel легко можно и так разобраться. В обще там довольно много лишнего. ? для максимальной оптимизации лучше их почистить. Я лично пишу на flixel, начал еще летом, сейчас поднатарел во Flash, хочу свой движок сделать, максимально узкоспециализированный под свой проект, потому что иногда flixel жутко мешает, хотя плюсов у него конечно больше.
@Max D, к сторонним фремворкам я положительно отношусь. Но я считаю, что прежде чем использовать сторонние разработки нужно немного разобраться с тем как все устроено и как работает без каких-либо движков и библиотек.
@dada, ну вот. Не такая уж и простая домашняя работа оказалась для некоторых :)
К сожалению я тоже не понимаю в чем может быть ошибка, так как в самом коде что вы мне демонстрируете все верно написано. Пришлите свой исходник мне на почту (адрес есть на странице «Об авторе»). Спасибо!
@Антон, сам по себе флеш устроен так, что мы оперируем уже визуальными объектами рендер которых флеш выполняет самостоятельно поэтому буквального рендера для юнитов, игровой карты и для элементов меню нам не потребуется.
В случае с отображением игровой карты и игровых интерфейсов — все делится на слои которые могут перекрывать друг друга. Например для карты будет свой слой, для игровых меню свой, и если вдруг нужно будет открыть игровое меню, то слой содержащий меню окажется над игровой картой и перекроет её. Работая с игровым меню мы будем обрабатывать содержимое слоя в котором находится меню отключая обработку других слоев с элементами. Это если в кратце.
Для кэширования графики будет использоваться специальный класс контейнер в котором хранится кэш и к которому мы сможем получить доступ из любой точки программы не храня и не передавая прямую ссылку на него.
Я хотел спросить немного не про это, но спасибо, что ответил). По второму вопросу я все понял спасибо. Теперь по первой части, я немного не то хотел спросить, проще говоря, где будет расположен eventListener и eventHandler (для таймера ну или ENTER_FRAME)? Будет это один листенер и хандлер? Заранее спасибо).
@Антон, в своих проектах я обычно делаю два перехватчика ENTER_FRAME, для Game.as и World.as отдельно. Нужно это для того чтобы ставить на паузу игру когда включаем меню и наоборот. Можно конечно делать общий перехватчик на два класса — но мне это не очень нравится так как это немного нарушает целостность классов и делает их взаимосвязанными.
Кстати, если заменить имя классы World на другое, то ошибка пропадает. Похоже на то, что класс World уже существует... Как это можно проверить?
Очень рад появлению серии уроков от великого мастера!! Буду следить и учиться.
p.s. судя по комментариям, многие уже сталкиваются с проблемами, хотя всё наглядно было показано и описано. Представляю, что же будет дальше...
Ребята у кого не получается, то в конце статьи выложены исходники, посмотрите их и сверьте со своими и сразу увидите, где вы ошиблись.
@pkasha, действительно судя по ошибке похоже что класс World уже где-то существует и возникает их конфликт (может быть добавили клип World в библиотеку и сделали его экспорт в AS?). Я добавил в свой код класс World и у меня не возникло никаких проблем. Было бы здорово если кто-нибудь пришлет свои исходники чтобы посмотреть где может быть допущена ошибка.
?сходник для проверки работоспособности программы с World.as — 12 кб.
Ant.Karlov, к сожалению, с твоим исходником выдает ту же самую ошибку :) Я думаю, что проблема в версии, у меня стоит CS5 (думаю, что и у других, у кого не работает).
Видимо в CS5-ой версии существует какой-то системный класс World. Но я не нашел никакой документации по этому вопросу.
В любом случае простое переименование с World на Universe решает проблему и все работает.
Единственное, что мне удалось найти, - это чей-то комментарий на форуме:
So Flash CS5 has two new undocumented root classes: World & Joint. I tried the CS5 demo and WCK blew up, eventually traced the problem back to this. If you create a new project and on the timeline:
trace(Joint);
trace(World);
You will see those classes are defined. Very interesting...
Действительно интересно:) Нужно будет активнее поискать информацию об этих классах.
В любом случае, пока что единственное очевидное решение - не использовать имя World.
@Dyrk, большое спасибо за комментарий! Это действительно похоже на правду. Мне лично вообще ничего не удалось найти по этому поводу, когда я пытался понять может ли существовать какой-то стандартный класс с таким именем.
В общем прийдется использовать другое название для игрового мира и я думаю, что Universe.as хорошая альтернатива :)
Поэтому я его давно назвал GameWorld
Случайно наткнулся на не плохой урок
http://www.guahanweb.com/2009/01/31/tower-defense-in-as3-part-iv/
там же есть и
http://code.guahanweb.com/viewsource/td04/
Ну все! Приступаем к написанию клонов! )))
Антон, спасибо большое за запуск цикла уроков!
иван +1, в свое время по нему и пытался написать TD игру + пара других примеров )
Антон, здравствуйте, к сожалению не смог найти вашу контактную информацию на сайте и в интернете, потому пишу сюда.
Если вам интересно предложение о долговременном сотрудничестве, то напишите мне на почту, и я опишу суть предложения подробнее: pvmajev at gmail dot com
О, спасибо.
А я уже думал ты уже забросил идею с туторами)
Мне как раз нужна игра для рекламы моего новоиспечённого портала, сделаю дефенс. :)
Филипп, в разделе "Об авторе", в шапке блога, там есть email
Вчера вечером неспешно под кофе и музычку сделал этот урок (и домашнее задание). Теперь с нетерпением ожидаю следующего.
@KUSAKA: похоже этой осенью будет TD-бум! Главное чтобы в последствии те, кто поторопился выпустить чисто геймплейный продукт не кричал на тех, кто сидел днями доводил игру до совершенства, что мол идеи у них спёрли и все дела)) ДАВАЙТЕ ДЕЛАТЬ КАЧЕСТВЕННЫЕ ?ГРЫ! да и вообще...думаю сейчас планка на TD игры ооочень высока. Если все кто сделают игру по этому тутору запостят её на FGL...выживут только сильнейшие. Так что уважаемые товарищи клоны...успехов!))))
RaymondGames, мало кто преследует цель сделать дефенс по этим урокам, чтобы потом пытаться на нем заработать. Чтобы получить хоть какие-то копейки за игру, нужно сделать ее максимально не похожей на ту, что будет в уроках. Поэтому я не думаю, что появится много клонов. А если и появятся, то сразу и исчезнут.
Лично для меня эти уроки интересны только с общеобрзовательной точки зрения. Знать методы создания игр на флеше - это хорошо, и девушкам похвастаться можно:)
? еще один плюс - это то, что возможно именно благодаря таким урокам и определится мой дальнейший жизненный путь. Пока я еще студент на содержании у родителей, можно переучиваться с web-программиста на разработчика флеш-игр :)
Привет Антон. Спасибо за урок. Я как раз занимаюсь в тек. момент ТД темой... Очень кстати... :) Насчёт структуры игр оч. всем советую книгу "The Essential Guide to Flash Games"... Правда на английском. Там как раз разбирается тема написания своего фреймворка для игровых проектов.
@Alxs, спасибо за подсказку о книге. К сожалению в рамках этого урока я не буду стараться охватить основы создания своего фремворка. Урок больше ориентирован на то, как можно что-то создать на ровном месте.
Думаю, что еще больший интерес к той или иной игре будет проявляться, если в ней сделать какие-то дополнительные возможности (например, какие-нибудь бонусы или мини-игры).
Я совсем недавно наткнулся на этот блог и стало очень интересно, тем более что небольшой опыт кода и анимации во Flash я приобрел. Кстати, благодаря все той же книге Колина Мука, всем рекомендую.
Антон, спасибо большое за этот блог, надеюсь, что уроки удадутся на славу :)
@Dyrk: мой тебе совет - не надо делать туторы - делай игру. Вот возьми блокнот, набросай там за пару дней/неделю геймплей (МАКС?МАЛЬНО ПРОСТОЙ). Затем добавь к нему геймплейные фишки (МАКС?МАЛЬНО ПРОСТЫЕ НО СВО?). ? все это дело распиши на технические задания себе же. Будет сложно, зато если ты реально сделаешь игру - это будет в тысячи тысяч миллионов раз лучше чем повторение туториала/изучение темы. Поверь мне, я на этих граблях был лет десять. Как пример можешь действительно взять за основу этот замечательный туториал, но с помощью него сделать свою полноценную игру и выпустить и получить копейку как ты говоришь. Вот тогда ты действительно поймешь твой это путь или сила в web-программизме.
@Ant.Karlov - Жду поста про MiningTruck2!
"В одном файле может быть только один класс."
Скорее должен быть один класс, так как в .as файл их можно впихнуть и больше =)
Совсем недавно наткнулся на блог =) ?нтересно читать и сравнивать со своим подходом. Спасибо! Удачи!
извини за тупой вопрос, я хотел у вас спросить я учился по диску на http://easyflash.org/ , но там он делал игру без скелета, просто все хронилось в fla, вы не могли бы мне обьяснить пожалуйста зачем такая структура, и что такое классы?
@Max, классы используются для Объектно Ориентированного Программирования — это когда игра собирается из «кирпичиков» (классов с разными методами и свойствами) которые между собой грамотно взаимодействуют. ООП позволяет быстро и доступно собирать сложные приложения с возможностью быстро вносить изменения в структуру программы и понимать, что и как работает.
Пример по приведенной вами ссылки я посмотреть не могу, но подозреваю, что в том уроке автор пишет код прямо в кадрах *.fla файла, что для больших игр не подходит и затрудняет последующий реюз отдельных возможностей разрабатываемой игры в будущем. Чтобы понять, что такое классы и как они используются, я настоятельно рекомендую почитать вам книжку Колина Мука — Actions Script 3.
Огромное вам спасибо за то что уделили мне время и за быстрый ответ, а насчет урока, да он делал это прямо в кадрах, на отдельном слое "actions" спасибо за совет буду читать.
Спасибо. супер.
Добрый день. Вылезает такая ошибка.
1067: Implicit coercion of a value of type com.towerdefence:Game to an unrelated type flash.display:DisplayObject.
Не могу понять что такое. Помогите пожалуйста.
@PRIZRAK, это значит, что происходит неявное приведение класса Game к типу DisplayObject но таковым он не является (хотя должен, так как Game.as унаследован от Sprite). Где именно вы допустили ошибку я едвали догадаюсь, поэтому советую вам сверится с исходниками.
Говорит что ошибка в 28 строке, addChild(_game);
Понял в чем ошибка была)
Шикарная статья, спасибо! У вас опечатка. Ск?лет.
исправь скилет на скелет;)
спс за урок. Бум учиццо. ?деи есть, осталось реализовать. 8)
Параллельно буду изучать фрэймворк моего друга - синглетон+интерфейс.
Спасибо за урок!
Огроменнейшее спасибо!
Действительно стартовать очень сложно...
Есть идеи. есть желание, не хватало Вашего туториала для старта! Теперь, надеюсь. приобретя навыки и знания буду пробовать воплощать свои идеи в жизнь.
Почему не завести отдельный класс для глобальных игровых констант? Получается Game.as какой-то полуфабрикат.
@pavezlo, можно поместить глобальные игровые константы и в отдельный класс — это кому как удобнее. Но большинство констант имеет отношения к определенным классам поэтому на мой взгляд их логично там и размещать.
Антон, спасибо большое, всегда нахожу что-то новое для себя в твоих уроках. Очень полезный и нужный урок как для новичков так и для тех кто уже знаком с AS3. Respect.
А у меня такая шняга:
C:Users*******DesktopProject ******com******App.as, Line 1 5000: The class `com.******.App` must subclass `flash.display.MovieClip` since it is linked to a library symbol of that type.
Как решить? =((
@Lx4:
Попробуй в строчке:
public class App extends Sprite
поменять Sprite на MovieClip
@BuxomBerry:
Не, не помогает =(( Уже и программу сносил, проект тоже...
Можно ли класс App поменять? На какой либо другой? ?ли не будет работать?
@Lx4, дело скорее всего не в названии класса App.as. У вас класс App унаследован от класса Sprite или MovieClip?
public class App extends MovieClip
{
...
}
Есть выделенная жирным строчка в классе App?
@Ant.Karlov
У меня public class App extends Sprite
Менял на МувиКлип - таже фигня. Даже если просто в Prop. там где class написать com.названиеигры.App, а в самом классе не чего не писать и скомпилировать, то он все ровно ругается. Если кликнуть на ошибку (в компиляторе), то он на 1 строку показывает, независимо, есть там что-то или нет.
@Ant.Karlov
Можно ли как-то настроить прогу по умолчанию? Чтобы не сносить. Просто такая ошибка возникла когда я экспериментировал.
@Lx4, если не сложно, то пришлите мне ваш проект на почту, потому что я ничего понять вообще не могу. Возможно причина этой проблемы до безобразия банальна, но гадать на кофейной гуще нет возможности.
Мой контактный email можно найти на странице «Об авторе».
@Ant.Karlov
Хорошо. Завтра вышлю. =)
@Ant.Karlov:
О! Все сделал занова, не торопился и все заработало! Спасибо за быстрые ответы и сорри за потраченное время =))
1) // Наследуем от него наш класс
public class App extends Sprite
Что такое наследование и зачем наследовать класс Sprite для класса App?
2)// Vars
private var _game:Game;
что ето за сменная _game(не понятно что ето у неё за тип Game)?
3) _game = new Game();[/b]
У книге Мука вроде сказано, еслы не ошибаюсь, что ето сменной _game присваивается экземпляр класса Game, но я не пойму что такое экземпляр класса.
4) не совсем понятен метод addChild(); а именно не понятно что значит "добавляет на сцену класс Game.as внутрь класса App "
@Рома, на все заданные вами вопросы есть ответы в книгах, причем все эти знания являются базовыми.
1. Наследуя класс App от класса Sprite мы получаем в классе App все возможности класса Sprite, но при этом можем добавить ему свои методы и свойства которые сделают его более подходящим под наши нужды.
2. Переменная _game хранит указатель на созданный класс игры Game.
3. Экземпляр класса — это созданный объект на основе нашего класса, например Game. Благодаря переменной _game мы можем обратится к нашему созданному объеку типа Game.
4. Метод addChild() является стандартным методом почти для всех визуальных объектов. Вызывая этот метод и передавая в него указатель на наш только что созданный объект мы добавляем наш объект в визуальную структуру программы. Если не вызывать метод addChild() (не добавить объект в визуальную структуру), то он никогда не будет видимым.
P.S.: Не называйте переменные "сменными" чтобы не путать себя и других.
@Ant.Karlov, та согласен что есть в книге, но так как опыта в программировании всего лишь паскаль и то СОВСЕМ на базовом уровне, то есть з ООП совсем не встречался, то книга Мука даеться ОЧЕНЬ сложно
1)теперь понятно что такое наследование...а в нашем случае с какой целью делаем наследование класса Sprite?
4)"никогда не будет видимым" это значит что к нему нельзя будет обращаться?
P.S. что то у меня на початковом етапе написания класса App та же ошибка что и у Lx4 была...
Спасибо, начинаю изучать флеш по твоим урокам!
Огромное спасибо! Для новичка вроде меня это просто великолепный материал!
Антон, вот в этом месте:
Код выше создает класс Game.as, сохраняет ссылку на него в переменной _game и добавляет на сцену внутрь класса App методом addChild(); после чего Game.as становится рабочей частью приложения.
вместо слова "класс" вы хотели сказать объект класса или я что-то не понял?
@Владимир, да, более понятно звучало бы «экземпляр класса».
> Код выше создает экземпляр класса Game.as, сохраняет ссылку на него в переменной _game и добавляет на сцену внутрь класса App методом addChild(); после чего Game.as становится рабочей частью приложения.
Спасибо что обратили внимание.
Да, экземпляр класса, хотел отредактировать, но не нашел как =)
Антон, спасибо вам за уроки!
Начал изучать AS по ним. До этого с Flash вообще не имел дела.
Очень хорошо написано.
Также скачал рекомендуемую вами книгу, буду изучать. Ещё раз спасибо!
Добрый день.
Насчет расстановки панелей в IDE - у вас какая диагональ?
такое ощущение что стопитьсот ) и все помещается )
@Hudson, в основном я работаю на 24" с разрешением ~ 1900x1600, но сейчас все чаще на ноутбуке 15" с разрешением 1440x900 — и как показывает практика на ноутбуке тоже не так уж и тесно :)
У меня уже проблемы... Нету вкладки "проекты" то есть есть но там нельзя классы создавать... ? не правильно вообще проект создается.. А через деволм получилось криво, и не хочет привязываться... Не выводить Hello world...
Ну никак не хочет выводить Hello word, уже даже скачал CS 5.5 ,.. Ну что за..
Выставил просто так, ошибка:
http://clip2net.com/clip/m51167/1325808136-clip-73kb.png
Если нормальный класс выставлен все равно ошибка:
http://clip2net.com/clip/m51167/1325808185-clip-75kb.png
Уже не надо, я решил сам..
Странно если такую функцию делать через Деволп и CS3, то не привязывается... Установил CS5 и работает..
@Макс, если хотите получить какую-либо помощь по своим проблемам, то пожалуйста, излагайте свои мысли полнее и давайте более подробное описание того что вы делайте и что у вас не получается.
Вот смотрите, надпись "Hello Word" Не выводится в версии CS3, а в версии CS5 выводится, почему же? Всё делал так же..
Зачем вообще нужны эти 2 строки:
var rect:Rectangle;
rect = grid.getRect(grid);
Не проще просто указать тут :
matrix.translate(0, 0);
0 0 ? Ведь так же получается
? зачем вообще стоит минут? (-rect.x, - rect.y);
?звините, не туда написал..
Подскажите, пожалуйста, как осуществить очистку ресурсов после прохождения уровня:
1) Univesre и все кто имел на него ссылку (враги, башни, панели управления...) должны подписываться на
removeEventListener(Event.REMOVED_FROM_STAGE, destroyObject),
а в обработчиках destroyObject обнулять все свои ссылке.
2) ?ли с точки зрения производительности лучше чтоб, подписывался только Universe и в этом обработчике вызвать всем своим объектам скажем deinit, а они в свою очередь для своих мемберов дергают deinit?
@FirstFlashGame, объектам не нужно подписываться на какие-либо события. Архитектура игры построена таким образом что Universe управляет всеми объектами через ObjectController. Таким образом при очищении мира достаточно для каждого экземпляра контроллера вызывать метод clear() и все объекты будут корректно освобождены и помещены в кэш. А обнуление парамтров каждого из объектов происходит перед их добавлением в игровой мир (перед повторным использованием).
Сам игровой мир Universe не может удалятся и пересоздаваться потому что этот класс является синглтоном.
@Макс, я использовал старый код из своего другого проекта где это нужно было.
Тогда я попытаюсь описать архитектуру приложения согласно Вашым подсказкам:
App создает Game.
Game берет на себя работу менеджера окон, переключая между собой: Credits, ChooseProfile, LevelSelect, Win/Lose, Universe.
В отличии от других окон – Universe инициализируется один раз и более не уничтожается (синглтон)
Когда загружается новый уровень, или рестартует старый то вызывается startGame которая заново инициализирует панель статистики, панель башен.
При наступлении условия выигрыша или проигрыша Universe вызывает очистку clear() для towers, enemies, bullets и просит Game переключить окна на Win/Lose
Только вот что еще делает App кроме как создает Game? Ведь кешированием объектов занимается Universe, также и перегонкой вектора в растр после загрузки уровня…
Все ли верно я понял?
@FirstFlashGame, App.as — это технический класс, по сути точка входа в приложение. В этом классе обычно выполняются всякие технические вещ, например: сбор статистики (вызов мочиботов), инициализация спонсорского API, демонстрация спонсорской заставки, возможна проверка на сайт-лок, запуск кэширования графических ресурсов (векторные анимации перегоняются в растровые ленты), и т.п. То есть что-то вроде тамбура где игра готовится к запуску. Обычно в законченной игре точкой входа в приложение является класс Preloader.as который будет создавать App.as и так далее.
Universe.as перегоняет сейчас фактически графику игрового уровня из вектора в растр, а в классе App обычно перегоняется вся спрайтов (или основная часто используемая графика, боевых единиц, постройки), которая используется в игре. Кэширование графики самих уровней допускается в процессе игры перед запуском уровня, так как на прекэширование графики непосредственно игровых уровней — памяти не хватит.
Я пошел другим путем, и он оказался очень дремучим. Теперь, переработав классы согласно Вашим рекомендациям, головоломка помаленьку начинает складываться в голове. Уже нет противоречий в архитектуре, и понятны многие вещи, оставшиеся “за кадром” при делании уроков. Это чувство всегда приятно, когда пелена спадает пред глазами. Все работает! Спасибо!
Антон, а почему фреймрейт 35?
Всегда считал, что общепринятый стандарт = 30 fps.
?ли у меня устаревшие сведения? )
Ant.Karlov, а как вы обрабатываете? После окончания игры нужно отправлять пользовательское событие? Я просто не могу понять как связать менеджер экранов и события в игре
Прошу прощения, я создал класс App.as путь к нему если через доменное имя сайта выходит такой: ru.towerdefence.App, я его прописал но при компиляции файл TowerDefence.fla выдает только пустое окно флеша, но окна output нету ( в чем может быть проблема не подскажете пожалуйста)
все получилось, почему то если пишу в пакете ru.towerdefence и при "вызове" класса на чистый лист пишу ru.towerdefence.App не работает, а если изменить название пакета на towerdefence и вызов класса на towerdefence.App то все работает
Здравствуйте, вы написали что для новичков хватает flash ide, а в дальнейшем потребуется ли какой нибудь редактор кода, нужен ли он вообще?
Если да, то какой(под Mac)?
@Visal, потребуется ли вам альтернативный редактор кода в будущем — это зависит только от ваших требований к редактору кода.
Хорошие альтернативные редакторы кода под Mac, работающие с AS3:
IntelliJ IDEA
FDT
TextMate
Как настроить TextMate для работы с AS3 я писал здесь...
Антон, нашел видео где с твоего поста все слизано, да же слова говорит как ты написал, блин даже обидно как-то стало за тебя=) Хоть бы упомянул что ресурс взят с твоего блога.
http://www.youtube.com/watch?v=kEdvoU5wz6Q
@Vladimir, забавное видео. Но расстраиваться и унывать не стоит, я уроки пишу и публикую просто так и мне не жалко если их кто-то пытается переделать и/или выдать за свои без указания источника, пусть это останется на их совести. Спасибо за информацию! :)
Спасибо большое за инструктаж в нете мало что то подобное найдешь короче низкий Вам поклон!!!
Антон, интересно узнать, почему ты используешь 35 кадров / сек?
Человеку вроде как 24 кадра хватает что бы воспринимать картинку как видео. Понятное дело если обрабатывать действия в ENTER_FRAME, то они будут выполняться чаще, но игру можно выполнять и по тикам в таймере. Где-то читал, что Flash`у "удобнее" работать с определенной частотой, хотя не думаю что это критично, хотел бы узнать твое мнение.
@?горь, Для видео достаточно 24 кадров, да. А вот для игр чем fps больше тем лучше — все будет рассчитываться и рендерится намного плавнее.
Я выбрал 35 кадров как компромисс между скоростью и производительностью. 24 кадра в флеш играх мне уже категорически не нравится — не приятно глазу смотреть на дерганья. В идеале я бы ставил все 60 кадров :)
От тиков и таймеров для процессинга игры я настоятельно вам рекомендую отказаться так как во флеше они могут давать существенные временные сбои, для флеша идеально использовать ENTER_FRAME.
Всем кто столкнулся с
5000: The class `com.******.App` must subclass `flash.display.MovieClip` since it is linked to a library symbol of that type.
или
должен входить подкласс "flash.display.MovieClip", так как он связывается с символом такого же типа в библиотеке.
Лично у меня была проблема в том, что я привык что компилятор сохраняет весь проект перед компилированием. Флеш же так не делает. Так что сохраните то, что набрали (ктрл+С) а после запускайте.
Спасибо за уроки
Антон, а в CS6 нет output?
привет.
изучаю флеш, спасибо за урок. вчера столкнулся с ошибкой, которая описана в комментариях, а именно - 1067: Implicit coercion of a value of type com.towerdefence:Game to an unrelated type flash.display:DisplayObject.
в комментариях выше вы пришли к выводу, что класс World является встроенным или системным, но это не так.
Как говорится, утро вечера мудренее, поэтому, сегодня утром я обнаружил, что эта ошибка выскакивает, если создать класс и не прописать в нём вот такую конструкцию:
import flash.display.Sprite;
public class Game extends Sprite
теперь и World.as работает без проблем
Спасибо. То, что ты делаешь, - очень круто. Для меня flash - это хобби, и благодаря урокам вроде твоих, дождливым осенним вечером можно сесть за компьютер и сделать игру для поднятия настроения:)
17 Октября 2010
— 00:56
#