ФлеймФорумПроЭкты

Президентский этаж [Android][Tutorial] пишем на ObjectScript (есть видео, exe, исходники)

#0
17:44, 31 авг 2014

Всем привет! Наконец-то я нашел отличный 2d framework, который можно адаптировать для использования на ObjectScript и сделать туториал от начала разработки и до релиза игры.

В этой теме я покажу, как сделать простую мобильную игру под андроид на ObjectScript шаг за шагом.

Игра: Президентский этаж

Описание: Даже у президентов бывают тяжелые дни. Нашего президента пригласила "дружественная" страна для обсуждения международных вопросов. Ему нужно подняться на сотый этаж, но оппоненты норовят сорвать встречу, устраивая разные провокации на каждом этаже. Помогите нашему президенту попасть на встречу.

Платформа: Android, Windows (вообще кроссплатформенный движок)

Движок: OS2D (сделан поверх Oxygine framework адаптированного для ObjectScript, респект автору Oxygine)

ObjectScript - это кроссплатформенный скриптовой язык программирования (http://objectscript.org).

Буквально немного слов об OS2D

OS2D - бесплатный, с открытым исходным кодом 2d движок для мобильных игр, его можно забрать с гитхаба по ссылке https://github.com/unitpoint/os2d (прошу лайкнуть, форкнуть или просто скачать). В репозитории все уже настроено, достаточно открыть в студии examples\DemoFloorOS\proj.win32\DemoFloor_vs2010.sln и запустить.

Основной код игры находится в файле examples\DemoFloorOS\data\main.os. В той же папке находятся остальные скрипты. Это и будет наш проект. Суть игры - переходить на следующий этаж, решая головоломки, простые или сложные (да, идея не нова, но такая игра на мой взгляд хорошо подходит для нашего туториала).

Поехали.

Президентский этаж dev-01 | Президентский этаж [Android][Tutorial] пишем на ObjectScript (есть видео, exe, исходники)
#1
17:48, 31 авг 2014

reserved

#2
17:48, 31 авг 2014

reserved

#3
18:59, 31 авг 2014

День 1: разработка шаблона игры.

Наша игра запускается с файла main.os, в нем мы подключаем стандартную библиотеку std,  в ней реализован механизм автоматической подгрузки (и при необходимости компиляции) наших классов (будем размещать классы в отдельных файлах),
а также некоторые полезные функции, кот. могут нам понадобиться.

require "std.os"

настраиваем масштабирование экрана, мы будем ориентироваться на портретный экран разрешением 540х960, т.к. наши ассеты поумолчанию будут сделаны под это разрешение (это не мешает нам в будущем использовать более детальные ассеты при необходимости)

GAME_SIZE = vec2(540, 960)
var displaySize = stage.size
var scale = displaySize / GAME_SIZE
// scale = math.max(scale.x, scale.y)
scale = math.min(scale.x, scale.y)
stage.size = displaySize / scale
stage.scale = scale

запускает саму игру

GameScene()

Архитектура GUI нашей игры будет выглядеть примерно следующим образом:

+ Показать

GameScene - будет самым верхним объектом в игре, он будет отвечать за текущий уровень и делать его смену

Level - объект самого уровня, в нем мы реализуем базовую логику построения лифтовой комнаты и логику работы
текущей головоломки

Hud - наш интерфейс, где будут показываться предметы, которые мы будем использовать для решения головоломок
d1-hud | Президентский этаж [Android][Tutorial] пишем на ObjectScript (есть видео, exe, исходники)

Room - комната с лифтом
d1-room-1 | Президентский этаж [Android][Tutorial] пишем на ObjectScript (есть видео, exe, исходники)

Elevator - сам лифт
d1-elevator | Президентский этаж [Android][Tutorial] пишем на ObjectScript (есть видео, exe, исходники)

Left & Right doors - двери лифта
d1-doors | Президентский этаж [Android][Tutorial] пишем на ObjectScript (есть видео, exe, исходники)

Давайте реализуем основную логику построения уровня в классе Level:

+ Показать

Синтаксис с @ называется сахарный this и описан более детально в документации.

Теперь добавим наш уровень на игровую сцену в классе GameScene:

+ Показать

Данный код позволит нам увидеть статическую сцену: комната с лифтом, двери, хад со слотами под объекты.

В следующий раз мы добавим интерактивности, научим наши двери открываться при клике на кнопки и реализуем первый уровень.

#4
21:51, 2 сен 2014

День 2: разработка логики первого этажа.

Описание логики первого этажа

На первом этаже давайте сделаем все как можно проще. По бокам дверей лифта будут находится кнопки.

При нажатии на левую кнопку, она загорится зеленным цветом и откроется левая дверь. Аналогично для правой кнопки и двери. После того, как обе двери лифта откроются, появится стрелка вверх.

При нажатии на стрелку вверх, мы перейдем на следующий этаж (т.к. у нас пока один этаж, то он просто перезагрузится).

Разработка этажа №1

В прошлый раз мы реализовали базовый функционал в классе Level (посмотреть полную версию файла). Давайте сейчас реализуем функционал первого этажа в классе Level_1, при этом унаследуемся от Level. Напоминаю, что мы пишем код на языке ObjectScript.

+ Показать

Готово, теперь посмотрим, что у нас получилось:

+ Показать

Вы можете посмореть полные исходники на ObjectScript к данному примеру в папке DemoFloorOS/data (см. файлы *.os).

#5
3:58, 5 сен 2014

День 3: разработка логики второго этажа, создание библиотеки для использования на др. уровнях.

Описание логики второго этажа

Я пока не буду полностью описывать логику, интересно узнать у вас, насколько это сложно получилось, нужно ли делать такие уровни?

Чтобы попробовать, что у нас получается, возьмите откомпилированную версию демки и запустите DemoFloorOS\run.cmd

Что примечательно, вы можете изменить скрипты на ObjectScript (см. DemoFloorOS\data\*.os) и запустить вашу версию игры без перекомпиляции exe! Измененные скрипты откомпилируются автоматически при запуске.

Вот небольшое видео "игры", но там специально не показано само прохождение, поэтому нужно подумать.

Запустить видео по клику - Как делать игрыЗапустить видео по клику - Как делать игры

Как сделана качающаяся платформа на 2 уровне?

Смысл такого качания заключается в использовании следующего алгоритма:

1. Установить пивот платформы в ту точку, вокруг которой наша платформа будет вращаться
2. Запустить твин по углу для вращения платформы сначала в одну сторону, используя EASE_INOUTQUAD. Такой тип твина начинает движение медленно, потом ускоряется, и в конце опять замедляется. График движения выглядит следующим образом:

qeasingcurve-inoutquad | Президентский этаж [Android][Tutorial] пишем на ObjectScript (есть видео, exe, исходники)

3. Запустить твин по углу для вражения платформы в обратную сторону по тому же EASE_INOUTQUAD.

В результате мы получим такое плавное качание платформы (как на видео), очень похожее на реальное качание физического объекта.

А теперь сам код на ObjectScript (см. Level_2.os) для запуска качания платформы.

  startPanelSwing = function(){
    // будем качать между этими углами
    var angles = [50, 30]
    // создаем последовательность из твинов
    var seq = SequenceTween()
    // добавляем первый твин в одну сторону
    seq.add("angle", angles[0], 1000, 1, false, 0, Tween.EASE_INOUTQUAD)
    // добавляем второй твин в другую сторону
    seq.add("angle", angles[1], 1000, 1, false, 0, Tween.EASE_INOUTQUAD)
    // при завершении последовательности, перезапускаем весь процесс
    seq.doneCallback = function(){ @startPanelSwing() }.bind(this)
    // добавляет последовательность из твинов на нашу платформу
    @brokenPanel.addTween(seq)
  },

Создание библиотеки для использования на др. уровнях

Мы уже знаем, что суть игры заключается в том, чтобы открыть лифт. Для этого используются некоторые предметы на уровне, которые можно брать в инвентарь, можно передвигать предметы или вращать (как собственно обстоит ситуация с качающейся платформой).

Для того, чтобы нам было удобно работать с предметами в будущем, давайте поделим их на несколько типов и реализуем для каждого типа свой функционал.

1. предметы, кот можно схватить и вращать
2. предметы, кот. можно двигать (пусть пока по горизонтали)
3. предметы, кот. можно брать в инвентарь и использовать

Для первого типа объектов подготовим функцию initRotatableObject (см. Level.initRotatableObject), ее можно использовать следующим образом:

  // создадим наш предмет - платформа
  @brokenPanel = Sprite().attrs {
    resAnim = res.getResAnim("broken-panel"),
    pivot = vec2(0.01, 0.99),
    pos = vec2(@width/2 - 200, 208),
    angle = 0,
    parent = this,
    priority = 10,
  }
  @initRotatableObject {
    // наш предмет, который мы инициализирует, как вращающийся пользователем
    @brokenPanel, 
    // можно установить границы вращения предмета
    // минимальный угол в градусах
    // minAngle = -10,
    // и максимальный угол 
    // maxAngle = 65,
    onBegin = function(){
      // тут наш код, который вызывается, когда пользователь 
      // кликнул на предмете
    },
    onRotate = function(){
      // вызывается в процессе самого вращения
    },
    onEnd = function(){
      // этот код вызывается, когда пользователь отпустил предмет
    },
  }

Для второго типа (двигать по горизонтали) - initHorizMovableObject, например, на втором уровне есть ваза, кот. инициализируется примерно так:

  @vase = Sprite().attrs {
    resAnim = res.getResAnim("obj-01"),
    pivot = vec2(0.5, 0.9),
    pos = vec2(@width/2 - 210, @elevatorInside.y + @elevatorInside.height + 60),
    parent = this,
    priority = 12,
  }
  @initHorizMovableObject{
    // наш предмет, который мы инициализирует, как передвигаемый пользователем
    @vase,
    onBegin = function(){
      // вызывается при старте процесса, кстати, 
      // эта фукнция может вернуть false, 
      // если мы хотим прервать процесс
    },
    onMove = function(){
      // вызывается в процессе самого передвижения
    },
    onEnd = function(){
      // вызывается при завершении
    },
  }

Для третьего типа (можно брать в инвентарь) - initSlotObject, например, код для болта на втором уровне:

  @bolt = Sprite().attrs {
    resAnim = res.getResAnim("obj-02"),
    pivot = vec2(0.5, 0.5),
    pos = vec2(@width/2 - 210, @elevatorInside.y + @elevatorInside.height + 30),
    parent = this,
    priority = 11,
    onSlotSelected = function(){
      // вызывается, когда предмет уже забрали в инвентарь 
      // а затем там выбрали
    },
  }
  @initSlotObject{
    // наш предмет, который мы инициализирует, как "инвентарный"
    // при клике на этот предмет, он поместится в инвентарь
    // а с уровня изчезнет
    @bolt
  }

На этой основе можно делать разные уровни для всей игры.

Буду рад ответить на вопросы и предложения.

P.S. Предложите сценарий уровня, кот. вы бы хотели увидеть в демке?

#6
14:44, 10 сен 2014

Внес большие добавления в движок OS2D (см. описание) и переделал пример, в частности с твинов перешел на экшены (они более гибкие). Процесс качания платформы теперь выглядит без запуска функций с большим количеством параметров (кот. надо запоминать), а более интуитивно понятно:

    var action = RepeatForeverAction(SequenceAction(
      TweenAction {
        duration = 1,
        angle = angles[0],
        ease = Ease.QUAD_IN_OUT,
      },
      TweenAction {
        duration = 1,
        angle = angles[1],
        ease = Ease.QUAD_IN_OUT,
      },
    ))
ФлеймФорумПроЭкты

Тема в архиве.