Реализовать синтетический большой арбуз из 0

JavaScript

Эта статья синхронизирована в личном блогеshymean.comвверх, добро пожаловать, чтобы следовать

В последнее время на Weibo выставлено много дынь, а также очень популярна игра «Синтетический большой арбуз», и в нее довольно интересно играть какое-то время. Изучив принцип, я обнаружил, что все циркулирующие на данный момент версии являются скомпилированными версиями магической модификации, код сжат и нечитаем, поэтому я решил реализовать его самостоятельно.

Этот проект в основном используется для практики создания кокосов.Все художественные материалы и аудиоматериалы взяты изУуууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууу.com/game/654/.

Спасибо оригинальному автору и дань уважения каждому разработчику игры!

Все материалы здесь и размещены в кодеgithubвыше, вы также можете пройтиАдрес онлайн-просмотраопыт

Логика игры

Вся игровая логика относительно проста, она сочетает в себе основной игровой процесс Тетриса и игры на выбывание.

  • В поколении фруктов
  • Нажмите на экран, фрукт переместится в соответствующее положение по оси X и свободно упадет.
  • Каждый фрукт будет сталкиваться с другими фруктами, и когда два одинаковых фрукта сталкиваются, они сливаются и переходят на более высокий уровень фруктов.

Есть 11 видов фруктов,

Цель игры — синтезировать самый совершенный фрукт: большой арбуз! Игра окончена, когда сложенные фрукты превышают верхнюю красную линию.

Разберите основную логику, которую необходимо реализовать

  • генерировать плоды
  • Падение фруктов и столкновение
  • Анимационный эффект устранения фруктов и логика обновления

подготовительная работа

Основная концепция создателя кокосов

Весь проект реализован с помощью cocos Creator v2.4.3, рекомендуется, чтобы студенты, которые знают его впервые, могли пройти его первыми.официальная документация, эта статья не будет слишком много рассказывать об использовании создателя (в основном потому, что я не очень опытен, ха)

игровой материал

В первую очередь необходимо подготовить художественные ресурсы.Все художественные материалы и аудиоматериалы для этого стандарта взяты изУуууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууу.com/game/654/.

Сначала заходим на сайт игры, открываем сетевую панель, там видны все арт ресурсы от которых зависит игра, можем скачать нужные нам файлы

Требуемые ресурсы изображения включают

  • 11 фруктовых наклеек
  • Каждая карта эффекта фруктовой композиции, в том числе
    • Картинка с фруктами
    • Изображение круглой капли воды
    • карта взрыва
  • При объединении двух арбузов появятся эффекты освещения и рассеивания цветов, которые пока не будут реализованы.

То же самое относится и к аудиофайлам, которые можно выбрать в столбце «Фильтр»..mp3Запросите быструю фильтрацию соответствующего ресурса для компилятора.

  • Звук взрыва и воды при удалении фруктов

Создание игровых сцен и фонов

Откройте Cocos Creator и создайте новый проект (вы также можете напрямую импортировать изgithubЗагрузите исходный код проекта).

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

Создание узлов сцены и фона

После инициализации проекта создайте новую игру в диспетчере ресурсов в левом нижнем углуScene, назвал игру основной сценой игры

После создания вы можете увидеть только что созданную сцену с именем game в активах менеджера ресурсов.

Выберите игровую сцену, вы можете увидеть корневой узел холста холста сцены в диспетчере иерархии в верхнем левом углу, холст кокосов по умолчанию - горизонтальный экран960*640, вы можете выбрать корневой узел, а затем отрегулировать ширину и высоту в инспекторе свойств справа, чтобы640*960

Затем создайте фоновый слой Мы создаем новый фоновый узел под узлом Canvas, потому что весь фон сплошного цвета.#FBE79D, так что залейте его одноцветным спрайтом

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

Теперь вся игровая сцена выглядит так

Затем спроектируйте часть логического сценария игры.

Компонент сценария сцены

Создайте новый js-скрипт в каталоге ресурсов и выполните команду следующим образом.Game.js, создатель создастcc.ClassФайл шаблона

Сначала свяжите компонент сценария с узлом, выберите корневой узел Canvas, добавьте компонент в инспекторе свойств справа, а затем выберите тот, который вы только что создали.Gameкомпоненты

Затем напишите конкретную логику кода и откройте файл Game.js (рекомендуется использовать vscode или webstrom, чтобы открыть корневой каталог всего проекта для редактирования)

Исходный код внутри выглядит так

// Game.js
cc.Class({
    extends: cc.Component,

    properties: {

    },
    onLoad(){

    },
    start(){ }
})

Здесь нам нужно поддерживать логику всей игры, а затем постепенно добавлять кодовый контент.

создавать фрукты

Фрукты являются основным элементом всей игры и часто создаются и уничтожаются в игре.

Генерирует один сборный ассет с фруктами

Доступ к таким динамически создаваемым узлам можно получить через готовые ресурсы.Prefabконтролировать,

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

Вот пример самого низкого сорта фрукта "виноград"

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

ИсправлятьGame.js, добавить атрибутfruitPrefab, тип которогоcc.Prefab,

// Game.js
properties: {
    fruitPrefab: {
        default: null,
        type: cc.Prefab
    },
}

Вернуться к создателю, . Выберите узел Canvas, который можно найти в инспекторе свойств.GameСтолбец компонента видит и изменяет это свойство. Мы перетаскиваем только что сделанный сборный ресурс из менеджера ресурсов, во время инициализации cocos отвечает за инициализацию соответствующих данных атрибутов.

Создайте один фрукт

Вернитесь к Game.js и начните писать настоящую логику: создайте виноградную лозу.

// Game.js
onLoad(){
    let fruit = cc.instantiate(this.fruitPrefab);
    fruit.setPosition(cc.v2(0, 400));

    this.node.addChild(fruit);
}

В режиме предварительного просмотра вы можете увидеть, что прямо вверху экрана находится виноградина.

красиво, очень хорошее начало!

Кроме того, поскольку Fruit также содержит определенную логику, мы можем добавитьFruitСкриптовый компонент, хотя на данный момент он не кажется особо полезным.

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

Динамическое обслуживание нескольких фруктов

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

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

const FruitItem = cc.Class({
    name: 'FruitItem',
    properties: {
        id: 0, // 水果的类型
        iconSF: cc.SpriteFrame // 贴图资源
    }
});

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

// Game.js
properties: {
    fruits: {
        default: [],
        type: FruitItem
    },
}

Вернитесь в редактор, в это время вы можете обнаружить, что под компонентом Game есть еще один атрибут.Fruitsатрибут, измените его длину на 11, затем напишите id каждого фрукта по очереди и вставьте его текстурные ресурсы из редактора ресурсов (физическая работа)

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

Логика этой инициализации должна поддерживаться самим фруктом, поэтому он помещается в только что созданныйFruitВ компоненте мы выставляем интерфейс инициализации

// Fruit.js
properties: {
    id: 0,
},
// 实例放在可以在其他组件中调用
init(data) {
    this.id = data.id
    // 根据传入的参数修改贴图资源
    const sp = this.node.getComponent(cc.Sprite)
    sp.spriteFrame = data.iconSF
},

Затем измените код выше, чтобы инициализировать фрукты

// Game.js
createOneFruit(num) {
    let fruit = cc.instantiate(this.fruitPrefab);
    // 获取到配置信息
    const config = this.fruits[num - 1]

    // 获取到节点的Fruit组件并调用实例方法
    fruit.getComponent('Fruit').init({
        id: config.id,
        iconSF: config.iconSF
    });
}

Таким образом, вы можете с удовольствием создавать различные фрукты

Прослушивание событий кликов

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

Вся игра создаст фрукт, когда нажат экран, просто слушайте глобальное событие Click, эта логика также находится вGameв компоненте сценария

onLoad() {
    // 监听点击事件
    this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this)
},
onTouchStart(){
    this.createOneFruit(1) // 生成水果
}

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

Физическая система: свободное падение и столкновение с твердым телом

Логика создания фруктов рассматривается выше. Во всей игре фрукты могут производить физические эффекты, такие как падение и упругое столкновение. Используя встроенный физический двигатель Кокоса, его можно легко реализовать.

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

Включить физический движок и обнаружение столкновений

Первый — открыть физический движок и установить размер гравитации.

const instance = cc.director.getPhysicsManager()
instance.enabled = true
// instance.debugDrawFlags = 4
instance.gravity = cc.v2(0, -960);

Затем вам нужно включить обнаружение столкновений, которое по умолчанию отключено.

const collisionManager = cc.director.getCollisionManager();
collisionManager.enabled = true

Затем установите окружающие стены на столкновение, чтобы фрукты не падали бесконечно.

 // 设置四周的碰撞区域
let width = this.node.width;
let height = this.node.height;

let node = new cc.Node();

let body = node.addComponent(cc.RigidBody);
body.type = cc.RigidBodyType.Static;

const _addBound = (node, x, y, width, height) => {
    let collider = node.addComponent(cc.PhysicsBoxCollider);
    collider.offset.x = x;
    collider.offset.y = y;
    collider.size.width = width;
    collider.size.height = height;
}

_addBound(node, 0, -height / 2, width, 1);
_addBound(node, 0, height / 2, width, 1);
_addBound(node, -width / 2, 0, 1, height);
_addBound(node, width / 2, 0, 1, height);

node.parent = this.node;

Теперь мы включили физический движок игрового мира, а затем нам нужно настроить узлы, на которые нужно воздействовать движком, то есть наш фрукт.

Компонент твердого тела плода и компонент столкновения

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

Первый компонент Rigid Body.

Затем есть компонент физического столкновения, так как наши фрукты круглые, мы можем выбрать компонент PhysicsCircleCollider.Если есть нерегулярный многоугольный край, такой как банан, рабочая нагрузка сильно возрастет~

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

Идеально! !

обратный вызов столкновения фруктов

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

Этот обратный вызов столкновения также написан в компоненте скрипта Fruit,

// Fruit.js
onBeginContact(contact, self, other) {
    // 检测到是两个相同水果的碰撞
    if (self.node && other.node) {
        const s = self.node.getComponent('Fruit')
        const o = other.node.getComponent('Fruit')
        if (s && o && s.id === o.id) {
            self.node.emit('sameContact', {self, other});
        }
    }
},

Чтобы обеспечить функциональное единство компонента Fruit, при столкновении двух одинаковых фруктов мы уведомляем их через событиеGame.js, чтобы его можно было зарегистрировать при инициализации плодаsameContactКак обрабатывать пользовательские события

// Game.js
createOneFruit(num) {
    let fruit = cc.instantiate(this.fruitPrefab);
    // ...其他初始化逻辑
     fruit.on('sameContact', ({self, other}) => {
        // 两个node都会触发,临时处理,看看有没有其他方法只展示一次的
        other.node.off('sameContact') 
        // 处理水果合并的逻辑,下面再处理
        this.onSameFruitContact({self, other})
     })
}

Таким образом, мы можем прослушивать и обрабатывать логику эскалации устранения, когда фрукты сталкиваются.

Убрать анимацию фруктов

Без анимационной версии

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

self.node.removeFromParent(false)
other.node.removeFromParent(false)

const {x, y} = other.node // 获取合并的水果位置
const id = other.getComponent('Fruit').id

const nextId = id + 1
const newFruit = this.createFruitOnPos(x, y, nextId) // 在指定位置生成新的水果

Выглядит немного странно, но играть можно!

Анализировать анимацию

Откройте исходный сайт и проанализируйте эффект анимации через панель «Производительность» (здесь не будет записано изображение GIF)

Вы можете увидеть эффекты анимации при компоновке, в том числе

  • Плод столкновения перемещается в центр исходного фрукта.
  • Эффект частиц фруктового взрыва
  • Эффект частиц взрыва капель воды
  • Увеличить анимацию лужи сока

Кроме того, есть звуковые эффекты для взрывов и звуков воды.

Управление активами взрыва

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

Сначала определитеJuiceItem, сохраните материал, необходимый для взрыва одного фрукта

// Game.js
const JuiceItem = cc.Class({
    name: 'JuiceItem',
    properties: {
        particle: cc.SpriteFrame, // 果粒
        circle: cc.SpriteFrame, // 水珠
        slash: cc.SpriteFrame, // 果汁
    }
});

Затем добавьте новый для игрового компонента.juicesАтрибуты

// Game.js
properties: {
    juices: {
        default: [],
        type: JuiceItem
    },
    juicePrefab: {
        default: null,
        type: cc.Prefab
    },
}

Далее пришло время продавать рабочую силу, перетаскивая текстурные ресурсы наjuicesв свойствах

Затем добавьте пустой сборный ресурс, в основном для монтирования компонента скрипта, который выглядит следующим образом:Juicescript, а затем не забудьте смонтировать сборный ресурс в Game'sjuicePrefabначальство.

Наконец, создайте новыйJuiceКомпонент, используемый для реализации анимационной логики взрыва, также должен предоставлять интерфейс инициализации.

// Juice.js
cc.Class({
    extends: cc.Component,

    properties: {
        particle: {
            default: null,
            type: cc.SpriteFrame
        },
        circle: {
            default: null,
            type: cc.SpriteFrame
        },
        slash: {
            default: null,
            type: cc.SpriteFrame
        }
    },
    // 同样暴露一个init接口
    init(data) {
        this.particle = data.particle
        this.circle = data.particle
        this.slash = data.slash
    },
    // 动画效果
    showJuice(){

    }
}

Таким образом, при слиянии мы инициализируем узел Juice и одновременно показываем эффект взрыва.

// Game.js
let juice = cc.instantiate(this.juicePrefab);
this.node.addChild(juice);

const config = this.juices[id - 1]
const instance = juice.getComponent('Juice')
instance.init(config)
instance.showJuice(pos, n) // 对应的爆炸逻辑

Анимация частиц взрыва

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

Сказав это, правильная анимация — это немного хлопотно, требуя контроля над различными случайными параметрами.

showJuice(pos, width) {
    // 果粒
    for (let i = 0; i < 10; ++i) {
        const node = new cc.Node('Sprite');
        const sp = node.addComponent(cc.Sprite);
        sp.spriteFrame = this.particle;
        node.parent = this.node;
        // ... 一堆随机的参数

        node.position = pos;
        node.runAction(
            cc.sequence(
                // ...各种action对应的动画逻辑
                cc.callFunc(function () {
                    // 动画结束后消除粒子
                    node.active = false
                }, this))
        )
    }

    // 水珠
    for (let f = 0; f < 20; f++) {
        // 同果粒,使用的spriteFrame切换成 this.circle
    }
    
    // 果汁只有一张贴图,使用this.slash,展示常规的action缩放和透明动画即可
},

используется в коде исходного проектаcreateFruitLЭтот метод используется для работы с анимацией взрыва.Хотя код сжат, соответствующая логика параметров анимации может быть смутно видна.Если вы не хотите настраивать параметры анимации, вы можете извлечь из этого уроки.

Таким образом, завершается отображение эффекта взрыва, что, вероятно, похоже на это, хотя это немного некрасиво.

звуковой эффект

пройти черезcc.audioEngineИграть напрямуюAudioClipресурсы для реализации звуковых эффектов

Добавлены два ресурса типа AudioClip под компонентом Game для облегчения доступа к компоненту скрипта.

properties: {
    boomAudio: {
        default: null,
        type: cc.AudioClip
    },
    waterAudio: {
        default: null,
        type: cc.AudioClip
    }
}

Как и выше, в инспекторе свойств перетащите два аудиоресурса из диспетчера ресурсов под свойства игрового компонента.

onSameFruitContact(){
    cc.audioEngine.play(this.boomAudio, false, 1);
    cc.audioEngine.play(this.waterAudio, false, 1);
}

Таким образом, вы можете услышать звук при столкновении.

пакет сборки

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

резюме

Я не знаю, как написать это до конца, кажется! ! Работа сделана! !

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

На прохождение этой игры ушло субботнее утро + одна ночь.Поскольку я не очень хорошо знаком с Cocos Creator, я потратил некоторое время на чтение документов, проверку материалов и даже просмотр некоторых обучающих видео на станции B. Однако чувство достижения и удовлетворения от урожая все равно велико, и его можно расценивать как серьезную игру.

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