1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/javen205-Sunflower

В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
README.md 32 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 06.03.2025 01:13 c3d3cf4

Краткое описание игры

Название игры: Жгучие солнцелюбки

Автор: Javen

Копирайт: ООО «Синьчжу Цзиши Чжунвэнь»

Язык программирования: JavaScript

Игровой движок: Cocos Creator v2.1.2

Внимание: Разрешено бесплатное использование для обучения и общения; коммерческое использование запрещено.

Описание игрового процесса

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

Основные функции:

  1. Авторизация через WeChat
  2. Дружеский рейтинг
  3. Индивидуальное распространение игры
  4. MiniApp-облачное развитие (получение информации пользователя, загрузка конфигурационных данных, отчет о достижении, рейтинг)
  5. Динамическая загрузка ресурсов (анимация Bone, предварительно загруженные ресурсы)
  6. Удалённая загрузка ресурсов (после сборки ресурсы размещаются на сервере, при первом запуске происходит удалённая загрузка)
  7. Отображение прогресса загрузки при переходе между сценами

Описание игровых сцен

Эта игра довольно простая и использует всего четыре сцены плюс проект облачного развития WeChat.- Сцена First: Включает одну картинку, которая загружается вместе с пакетом игры. Это сделано для решения проблемы черного экрана во время удалённой загрузки на iOS.

  • Сцена Welcome: Анимированное представление корпоративного бренда компании.
  • Сцена Loading: Переходная сцена для загрузки данных.
    • Инициализация среды облачного развития.
    • Получение OpenID.
    • Получение информации о пользователе.
  • Сцена Home: Основная сцена игры.
    • Инициализация UI (различные узлы Node, компонент обратного отсчёта времени, асинхронная загрузка анимации Bone, динамическая загрузка предварительно загруженных ресурсов).
    • Проверка авторизации, если она ещё не выполнена, создание кнопки для авторизации.
    • Реализация игрового процесса.
    • Отправка отчёта о достижении.
    • Дружеский рейтинг.

Примеры изображений

Облачная база данных

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

Ссылки на документацию:

Упаковка часто используемых методов WeChat API

  • Инициализация облачной среды
  • Упаковка вызова облачных функций
  • Получение информации о пользователе
  • Создание кнопки получения информации о пользователе
  • Вызов облачной базы данных для отправки последних результатов в облако
  • Упаковка методов рекламы WeChat
# WxApi.js
/**
 * @author Javen 
 * @copyright 2019-03-07 19:22:21 javendev@126.com 
 * @description Интерфейсы WeChat
 */
const Global = require('../common/Global');

class WxApi {
    constructor() {}

    /**
     * 1. Инициализация облачной среды
     * 2. Отображение меню для делиться
     * 3. Настройка передачи сообщений для мини-приложения
     */
    initCloud(envId) {
        wx.cloud.init({
            env: envId,
            traceUser: true
        });

        // Инициализация базы данных
        Global.wxDb = wx.cloud.database({
            env: envId
        });

        this.showShareMenu();
        this.onShareAppMessage();
    }

    /**
     * Упаковка вызова облачных функций
     */
    callFunction(funcName, params) {
        return new Promise((resolve, reject) => {
            wx.cloud.callFunction({
                name: funcName,
                data: params || {},
                success: res => {
                    resolve(res);
                    console.log(`[Облачная функция ${funcName}] успешно вызвана: `, res);
                },
                fail: err => {
                    resolve(null);
                    console.log(`[Облачная функция ${funcName}] не удалось вызвать: `, err);
                }
            });
        });
    }
}
``````markdown
    /**
     * Проверка наличия разрешений
     */
    getSetting(scope) {
        return new Promise((resolve, reject) => {
            wx.getSetting({
                success(res) {
                    if (res.authSetting[scope]) {
                        resolve('Разрешено');
                    } else {
                        reject('Не разрешено');
                    }
                }
            });
        });
    }

    /**
     * Получение информации о пользователе
     */
    getUserInfo() {
        return new Promise((resolve, reject) => {
            wx.getUserInfo({
                withCredentials: true,
                success(res) {
                    resolve(res);
                },
                fail(err) {
                    reject(err);
                }
            });
        });
    }
}
WxApi.prototype.login = function() {
    return new Promise(function(resolve, reject) {
        if (cc.sys.platform === cc.sys.WECHAT_GAME) {
            wx.login({
                success(res) {
                    if (res.code) {
                        resolve(res.code);
                    } else {
                        reject(res.errMsg);
                    }
                }
            });
        } else {
            reject('Не в среде WeChat');
        }
    });
};

/**
 * Создание кнопки с информацией о пользователе
 */
WxApi.prototype.createUserInfoBtnByImg = function(left, top, imgUrl, width, height, callBack) {
    if (cc.sys.platform === cc.sys.WECHAT_GAME) {
        let button = wx.createUserInfoButton({
            type: 'image',
            image: imgUrl,
            style: {
                left: left,
                top: top,
                width: width,
                height: height,
            }
        });
        button.onTap((res) => {
            if (callBack) {
                callBack(res);
            }
        });
        button.show();
        return button;
    } else {
        console.log("createUserInfoBtnByImg Не в среде WeChat...");
    }
};

/**
 * Создание кнопки для открытия страницы обратной связи
 */
WxApi.prototype.createFeedbackButtonByImg = function(left, top, imgUrl, width, height, callBack) {
    if (cc.sys.platform === cc.sys.WECHAT_GAME) {
let button = wx.createFeedbackButton({
    type: 'image',
    image: imgUrl,
    style: {
        left: left,
        top: top,
        width: width,
        height: height,
    }
});
button.onTap((res) => {
    if (callBack) {
        callBack(res);
    }
});
button.show();
return button;
} else {
console.log("createFeedbackButtonByImg Не в среде WeChat...");
}
};
WxApi.prototype.getShareInfo = function(название, imageUrl, openId) {
    if (!название) {
        название = "Следующее содержание очень впечатляющее";
    }
    if (!imageUrl) {
        imageUrl = "https://7072-pro-15ec75-1258808161.tcb.qcloud.la/static/share_01.png?sign=f246f9cc5f05eece2ae92bbd4444cc16&t=1552447069";
    }
    let query = "";
    if (!openId) {
        query = 'openId=' + openId;
    }
    return {
        название: название,
        imageUrl: imageUrl,
        query: query,
        success(res) {
            console.log("Поделиться завершено...", res);
        },
        fail(res) {
            console.log("Поделиться не удалось...", res);
        }
    };
}
WxApi.prototype.showShareMenu = function() {
    if (cc.sys.platform === cc.sys.WECHAT_GAME) {
        wx.showShareMenu({
            withShareTicket: true
        });
    }
}

WxApi.prototype.onShareAppMessage = function(shareInfo) {
    if (!shareInfo) {
        shareInfo = this.getShareInfo();
    }
    if (cc.sys.platform === cc.sys.WECHAT_GAME) {
        // Поделиться · мини-приложение
        wx.onShareAppMessage(function() {
            return shareInfo;
        });
    } else {
        console.log("onShareAppMessage не в среде WeChat...");
    }
}

WxApi.prototype.shareAppMessage = function(shareInfo) {
    if (cc.sys.platform === cc.sys.WECHAT_GAME) {
        if (!shareInfo) {
            shareInfo = this.getShareInfo();
        }
        // Активное распространение
        wx.shareAppMessage(shareInfo);
    } else {
        console.log("shareAppMessage не в среде WeChat...");
    }
}
``````javascript
WxApi.prototype.loadVideoAd = function(adUnitId) {
    if (!Global.videoAd && cc.sys.platform === cc.sys.WECHAT_GAME) {
        let rewardedVideoAd = wx.createRewardedVideoAd({
            adUnitId: adUnitId
        });
        rewardedVideoAd.onLoad(() => {
            console.log('Рекламное видео успешно загружено');
            Global.videoAd = rewardedVideoAd;
            Global.videoAdLoadCount = 0;
        });
        rewardedVideoAd.onClose(res => {
            console.log('Рекламное видео закрыто');
            Global.videoAd = undefined;
        });
        rewardedVideoAd.onError(err => {
            console.log('Не удалось загрузить рекламное видео');
            Global.viewAdLoadCount += 1;
            if (Global.viewAdLoadCount < 4) {
                rewardedVideoAd.load();
            }
        });
    }
}

Примечание: Исходный текст был на английском языке, поэтому перевод выполнен на русский язык в соответствии с указанным требованием.```javascript WxApi.prototype.loadBannerAd = function(adUnitId) { if (!Global.bannerAd && cc.sys.platform === cc.sys.WECHAT_GAME) {

            adUnitId: adUnitId,
            style: {
                left: 10,
                top: Global.windowHeight - 180,
                width: Global.windowWidth - 20,
            }
        });
        bannerAd.onError(err => {
            console.log('Загрузка баннерной рекламы не удалась', err);
            Global.bannerAdLoadCount += 1;
            if (Global.bannerAdLoadCount < 4) {
                loadBannerAd();
            }
        });
        bannerAd.onLoad(() => {
            console.log('Баннерная реклама успешно загружена');
            Global.bannerAd = bannerAd;
            Global.viewAdLoadCount = 0;
        });
    }
}```markdown
WxApi.prototype.showBannerAd = function() {
    if (Global.bannerAd) {
        Global.bannerAd.show();
    } else {
        loadBannerAd();
    }
}

WxApi.prototype.hideBannerAd = function() {
    if (Global.bannerAd) {
        // Global.bannerAd.hide();
        Global.bannerAd.destroy();
        Global.bannerAd = undefined;
        loadBannerAd();
    } else {
        console.log('Ресурс отсутствует, скрывать не требуется');
    }
}

Примечание: В данном примере комментарий // Global.bannerAd.hide(); был оставлен без изменения, так как он относится к коду и не требует перевода.```markdown WxApi.prototype.post = function(postUrl, params) { return new Promise(function(resolve, reject) { wx.request({ url: postUrl, method: 'POST', header: { 'content-type': 'application/x-www-form-urlencoded' }, data: params || {}, success: function(res) { resolve(res); console.log([post ${postUrl}] Запрос выполнен успешно: , res); }, fail: function(error) { reject(error); console.log(`[post ${postUrl}] Запрос завершился ошибкой: `, error); } }); }); }

/**

  • Установка данных пользователя в облачном хранилище */ WxApi.prototype.setUserCloudStorage = function(score) { return new Promise(function(resolve, reject) { wx.setUserCloudStorage({ KVDataList: [{ key: "score", value: score.toString() }], success: function(res) { console.log("Данные отправлены успешно:", res); resolve(res); }, fail: function(err) { console.log("Отправка данных не удалась:", err); reject(err); }, complete: function() { console.log("Завершение отправки данных"); } }); }); }
/**
 * Вызов облачной функции для загрузки последнего результата в облако
 */
WxApi.prototype.uploadScore = function(score) {
    let that = this;
    // 1. Получение результата
    // 2. Если нет данных, добавляем
    // 3. Если есть данные, проверяем является ли это новым рекордом
    return new Promise(function(resolve, reject) {
        Global.wxDb.collection('scores').where({
            _openid: Global.openId,
        }).get({
            success(res) {
                if (res.data.length > 0) {
                    let data = res.data[0];
                    let oldScore = data.score;

                    if (oldScore < score) {
                        // Новая запись Обновление
                        Global.wxDb.collection('scores').doc(data._id).update({
                            data: {
                                score: score,
                                updateDate: Global.wxDb.serverDate()
                            },
                            success(res) {
                                that.setUserCloudStorage(score);
                                // Новая запись
                                resolve(1);
                            },
                            fail(err) {
                                reject(err);
                            }
                        });
                    } else {
                        resolve(-1);
                    }
                } else {
                    // Отсутствие записи Добавление данных
                    Global.wxDb.collection('scores').add({
                        data: {
                            score: score,
                            createDate: Global.wxDb.serverDate(),
                            updateDate: Global.wxDb.serverDate()
                        },
                        success(res) {
                            that.setUserCloudStorage(score);
                            // Новая запись
                            resolve(1);
                        },
                        fail(err) {
                            reject(err);
                        }
                    });
                }
            },
            fail(err) {
                reject(err);
            }
        });
    });
};
``````markdown
## Отображение кнопки распространения

```javascript
function showShareMenu() {
    wxApi.showShareMenu();
}
```

## Обработка сообщений

```javascript
// Передача данных в виде мини-приложения
function onShareAppMessage() {
    wxApi.onShareAppMessage();
}

// Активное открытие экрана передачи данных
function shareAppMessage() {
    wxApi.shareAppMessage();
}
```

## Отображение модальных окон

```javascript
function showModal(заголовок, содержимое) {
    wxApi.showModal(заголовок, содержимое);
}

function showLoading(заголовок) {
    wxApi.showLoading(заголовок);
}

function hideLoading() {
    wxApi.hideLoading();
}
```

## Динамическое создание кнопок

```javascript
// Создание кнопки получения информации о пользователе
function createUserInfoBtnByImg(лево, верх, imgUrl, ширина, высота, callback) {
    return wxApi.createUserInfoBtnByImg(лево, верх, imgUrl, ширина, высота, callback);
}

// Создание кнопки обратной связи
function createFeedbackButtonByImg(лево, верх, img_url, ширина, высота, callback) {
    return wxApi.createFeedbackButtonByImg(лево, верх, img_url, ширина, высота, callback);
}
```
```## Рекламные объявления

```javascript
function loadVideoAd() {
    wxApi.loadVideoAd('adunit-5b6b4a914e14b53e');
}

function loadBannerAd() {
    wxApi.loadBannerAd('adunit-0ebd781de8250e17');
}

function showBannerAd() {
    wxApi.showBannerAd();
}

function hideBannerAd() {
    wxApi.hideBannerAd();
}
```

## Запросы и отправка данных

```javascript
function post(postUrl, params) {
    return wxApi.post(postUrl, params);
}

function uploadScore(score) {
    return wxApi.uploadScore(score);
}
```

### Экспортированные функции

```javascript
module.exports = {
    initCloud: initCloud,
    getSetting: getSetting,
    login: login,
    getUserInfo: getUserInfo,
    showShareMenu: showShareMenu,
    onShareAppMessage: onShareAppMessage,
    shareAppMessage: shareAppMessage,
    createUserInfoBtnByImg: createUserInfoBtnByImg,
    createFeedbackButtonByImg: createFeedbackButtonByImg,
    loadVideoAd: loadVideoAd,
    loadBannerAd: loadBannerAd,
    showBannerAd: showBannerAd,
    hideBannerAd: hideBannerAd,
    showModal: showModal,
    showLoading: showLoading,
    hideLoading: hideLoading,
    post: post,
    callFunction: callFunction,
    uploadScore: uploadScore,
};
```

### Описание открытых областей WeChatОткрытые области WeChat Mini Games используют старую версию реализации [см. документацию](https://docs.cocos.com/creator/manual/zh/publish/publish-wechatgame-sub-domain.html)

```javascript
let ITEM_TYPE = cc.Enum({
    TOP3: 0,
    OTHERS: 1,
    SELF: 2,
});
cc.Class({
    extends: cc.Component,
    properties: {
        content: cc.Node,
        selfNode: cc.Node,
        prefab: cc.Prefab,
        itemBgs: {
            default: [],
            type: cc.SpriteFrame
        },
        itemNumberTop3: {
            default: [],
            type: cc.SpriteFrame
        },
        _dataArray: []
    },
    start() {
        let _self = this;
        if (cc.sys.platform === cc.sys.WECHAT_GAME) {
            wx.onMessage((data) => {
                console.log("onMessage.", data);
                if (data.message === 'getFriendRank') {
                    let selfOpenId = data.openId;
                    console.log("selfOpenId:", selfOpenId);
                    // очистка предыдущих данных
                    _self.content.children.forEach((element) => {
                        element.destroy();
                    });
                    _self._dataArray = [];
                    // конец очистки предыдущих данных
                    // получение данных рейтинга друзей
                    wx.getFriendCloudStorage({
                        keyList: ['score'],
                        success: function(res) {
                            console.log('friend success', res);
                            let length = res.data.length;
                            if (length > 0) {
                                for (let i = 0; i < res.data.length; i++) {
                                    let friendInfo = res.data[i];
                                    if (friendInfo) {
                                        let openId = friendInfo.openid;
                                        let nickName = friendInfo.nickname;
                                        let avatarUrl = friendInfo.avatarUrl;
                                        let score = friendInfo.KVDataList[0].value;
                                        _self._dataArray.push({
                                            openId: openId,
                                            nickName: nickName,
                                            avatarUrl: avatarUrl,
                                            score: score
                                        });
                                    }
                                }
                            }
                        }
                    });
                }
            });
        }
    }
});
```_dataArray.push(_self._itemObj(0, openId, avatarUrl, nickName, score));
                                }
                            }
                            // сортировка
                            _self._dataArray.sort(function (m, n) {
                                if (parseInt(m.score) < parseInt(n.score)) return 1;
                                else if (parseInt(m.score) > parseInt(n.score)) return -1;
                            });```javascript
                                     else return 0;
                                 });
                                 // отображение данных
                                 _self.displayData();
                             }
                         }, fail: function () {
                             console.log('Не удалось получить облачное хранилище друзей');
                         }
                     });
                 }
             });
         }
     },
     
     _itemObj(index, openId, avatarUrl, nickName, score) {
         let node = cc.instantiate(this.prefab);
         node.getComponent(cc.Label).string = `${nickName}\n${openId}\n${avatarUrl}\n${score}`;
         this.content.addChild(node);
         return { index, openId, avatarUrl, nickName, score };
     },

     displayData() {
         this._dataArray.forEach(item => {
             this._itemObj(item.index, item.openId, item.avatarUrl, item.nickName, item.score);
         });
     }
 });
``````markdown
                                     в противном случае вернуть 0
                                  });
                                  console.log("Отсортированные данные:", _self._dataArray);
                                  let temp = _self._dataArray.length > 10 ? 10 : _self._dataArray.length;
                                  for (let index = 0; index < temp; index++) {
                                      let node = _self.createPrefab();
                                      let itemData = _self._dataArray[index];
                                      itemData.id = index + 1;
                                      _self._setItemNode(
                                          node,
                                          itemData.id < 4 ? ITEM_TYPE.TOP3 : ITEM_TYPE.OTHERS,
                                          itemData
                                      );
                                  }
                                   _self.selfNode.active = false;
                                  // Устанавливаем свой ранг
                                  for (let index = 0; index < _self._dataArray.length; index++) {
                                      let tempData = _self._dataArray[index];
                                      tempData.id = index + 1;
                                      if (selfOpenId === tempData.openId) {
                                          console.log("selfData:", tempData);
                                          _self._setItemNode(_self.createPrefab(), ITEM_TYPE.SELF, tempData);
                                          _self.selfNode.active = true;
                                          break;
                                      }
                                  }
                              }
                          },
                          fail: function (res) {
                              console.error(res);
                          }
                      });
                  }
              });
          } else {
              // тестовые данные вне окружения WeChat
              console.log('Не WeChat среда...');
  ```
```markdown
             для (пусть index = 1; index < 11; index++) {
                  пусть node = это.createPrefab();
                  пусть itemData = новое это._itemObj(index, "", "http://192.168.1.134:12888/img/head.png",
                      "Javen", 100 + index);
                  это._setItemNode(node, index < 4 ? ITEM_TYPE.TOP3 : ITEM_TYPE.OTHERS, itemData);
              }
              пусть itemData = новое это._itemObj(100, "", "http://192.168.1.134:12888/img/head.png",
                  "Javen001", 100);
              пусть this._setItemNode(this.createPrefab(), ITEM_TYPE.SELF, itemData);
          }
      },
      _setItemNode(newNode, type, itemObj) {
          // Устанавливаем очки
          newNode.getChildByName("score").getComponent(cc.Label).string = itemObj.score;
          // Устанавливаем изображение
          пусть headNode = newNode.getChildByName("head").getChildByName("head");
          это.loadImgByUrl(headNode, itemObj.avatarUrl);
          // Устанавливаем фон элемента
          newNode.getComponent(cc.Sprite).spriteFrame = это.itemBgs[type];
          // Устанавливаем имя игрока
          newNode.getChildByName("bannerId").getChildByName("name")
              .getComponent(cc.Label).string = это.stringTodo(itemObj.nickName, 8);
          // Устанавливаем место
          пусть noNode = newNode.getChildByName("no");
          пусть numberNode = newNode.getChildByName("number");
          пусть numImgNode = newNode.getChildByName("numImg");
          noNode.active = false;
          numberNode.active = false;
          numImgNode.active = false;
      }
```
        if (type === ITEM_TYPE.TOP3) {
            numImgNode.getComponent(cc.Sprite).spriteFrame = this.itemNumberTop3[itemObj.id - 1];
            numImgNode.active = true;
        } else if (type === ITEM_TYPE.OTHERS) {
            numberNode.getComponent(cc.Label).string = itemObj.id;
            numberNode.active = true;
        } else if (type === ITEM_TYPE.SELF) {
            if (itemObj.id <= 0) {
                noNode.active = true;
            } else {
                numberNode.getComponent(cc.Label).string = itemObj.id;
                numberNode.active = true;
            }
        }

        if (type === ITEM_TYPE.SELF) {
            newNode.parent = this.selfNode;
        }
    },
    _itemObj(id, openId, avatarUrl, nickName, score) {
        return {
            id: id,
            openId: openId,
            nickName: nickName,
            score: score,
            avatarUrl: avatarUrl,
        };
    },
    createPrefab() {
        let node = cc.instantiate(this.prefab);
        node.parent = this.content;
        return node;
    },
    loadImgByUrl(imgNode, remoteUrl, imageType) {
        let _self = this;
        if (!imageType) {
            imageType = 'png';
        }
        cc.loader.load(
            {url: remoteUrl, type: imageType},
            function(err, texture) {
                if (err) {
                    return;
                }
                imgNode.getComponent(cc.Sprite).spriteFrame = new cc.SpriteFrame(texture);
            }
        );
    },
    ```markdown
            _self.setImg(imgNode, new cc.SpriteFrame(texture));
         });
     },
     setImg(imgNode, spriteFrame) {
         imgNode.getComponent(cc.Sprite).spriteFrame = spriteFrame;
     },
     stringTodo(str, len) {
         let reg = /[\u4e00-\u9fa5]/g,
             slice = str.substring(0, len),
             chineseCharNum = (~~(slice.match(reg) && slice.match(reg).length)),
             realen = slice.length * 2 - chineseCharNum;
         return str.substr(0, realen) + (realen < str.length ? ". . . " : "");
     }
  });
 ```
### Ресурсное удалённое загрузка

**Ссылки для справки:** 

- [Подготовка окружения для разработки WeChat Mini Games](https://javen.blog.csdn.net/article/details/86545971)
- [Развертывание CCC в WeChat Mini Game](https://docs.cocos.com/creator/manual/zh/publish/publish-wechatgame.html)### Объявление

- Шаблон для разработки публичного аккаунта WeChat: https://gitee.com/javen205/TNW
- IJPay: сделать платежи доступными: https://gitee.com/javen205/IJPay
- SpringBoot_Guide: руководство по работе с Java back-end: https://gitee.com/javen205/SpringBoot_Guide

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/javen205-Sunflower.git
git@api.gitlife.ru:oschina-mirror/javen205-Sunflower.git
oschina-mirror
javen205-Sunflower
javen205-Sunflower
master