游戏通用配置模块提到框架中成为复用功能模块

This commit is contained in:
dgflash
2022-08-05 17:21:45 +08:00
parent 9767037086
commit 27138767c6
18 changed files with 405 additions and 19 deletions

View File

@@ -2,18 +2,20 @@
* @Author: dgflash
* @Date: 2021-07-03 16:13:17
* @LastEditors: dgflash
* @LastEditTime: 2022-08-02 09:58:15
* @LastEditTime: 2022-08-05 17:20:11
*/
import { Component, director, game, Game, log, Node, view, _decorator } from "cc";
import { ecs } from "../libs/ecs/ECS";
import { LanguageManager } from "../libs/gui/language/Language";
import { HttpRequest } from "../libs/network/HttpRequest";
import { config } from "../module/config/Config";
import { AudioManager } from "./common/audio/AudioManager";
import { EventMessage } from "./common/event/EventMessage";
import { Message } from "./common/event/MessageManager";
import { TimerManager } from "./common/manager/TimerManager";
import { GameManager } from "./game/GameManager";
import { GUI } from "./gui/GUI";
import { LanguageManager } from "../libs/gui/language/Language";
import { LayerManager } from "./gui/layer/LayerManager";
import { HttpRequest } from "../libs/network/HttpRequest";
import { oops, version } from "./Oops";
const { ccclass, property } = _decorator;
@@ -35,6 +37,26 @@ export class Root extends Component {
console.log(`Oops Framework v${version}`);
this.init();
config.init(this.run.bind(this));
}
update(dt: number) {
oops.ecs.execute(dt);
}
/** 初始化游戏界面 */
protected initGui() {
}
/** 初始化游戏业务模块 */
protected initEcsSystem() {
}
/** 加载完引擎配置文件后执行 */
protected run() {
}
protected init() {
@@ -42,8 +64,12 @@ export class Root extends Component {
oops.timer = new TimerManager(this);
oops.audio = AudioManager.instance;
oops.http = new HttpRequest();
oops.gui = new LayerManager(this.gui!);
oops.game = new GameManager(this.game!);
oops.gui = new LayerManager(this.gui!);
this.initGui();
oops.ecs = new ecs.RootSystem();
this.initEcsSystem();
oops.ecs.init();
// 游戏显示事件
game.on(Game.EVENT_SHOW, () => {

View File

@@ -62,7 +62,7 @@ export class LayerManager {
private configs: { [key: number]: UIConfig } = {};
/** 是否为竖屏显示 */
public get portrait() {
get portrait() {
return this.root.getComponent(GUI)!.portrait;
}
@@ -70,7 +70,7 @@ export class LayerManager {
* 初始化所有UI的配置对象
* @param configs 配置对象
*/
public init(configs: { [key: number]: UIConfig }): void {
init(configs: { [key: number]: UIConfig }): void {
this.configs = configs;
}
@@ -79,7 +79,7 @@ export class LayerManager {
* @param content 文本表示
* @param useI18n 是否使用多语言
*/
public toast(content: string, useI18n: boolean = false) {
toast(content: string, useI18n: boolean = false) {
this.notify.show(content, useI18n)
}
@@ -88,12 +88,12 @@ export class LayerManager {
* @param uiId 要设置的界面id
* @param config 要设置的配置
*/
public setConfig(uiId: number, config: UIConfig): void {
setConfig(uiId: number, config: UIConfig): void {
this.configs[uiId] = config;
}
/** 设置界面地图配置 */
public setUIMap(data: any) {
setUIMap(data: any) {
if (this.uiMap == null) {
this.uiMap = new UIMap();
}
@@ -107,7 +107,7 @@ export class LayerManager {
* @param callbacks 回调对象
* @returns
*/
public open(uiId: number, uiArgs: any = null, callbacks?: UICallbacks): void {
open(uiId: number, uiArgs: any = null, callbacks?: UICallbacks): void {
var config = this.configs[uiId];
if (config == null) {
warn(`打开编号为【${uiId}】的界面失败,配置信息不存在`);
@@ -136,7 +136,7 @@ export class LayerManager {
* @param uiArgs 窗口参数
* @returns
*/
public async openAsync(uiId: number, uiArgs: any = null): Promise<Node | null> {
async openAsync(uiId: number, uiArgs: any = null): Promise<Node | null> {
return new Promise<Node | null>((resolve, reject) => {
var callbacks: UICallbacks = {
onAdded: (node: Node, params: any) => {
@@ -148,7 +148,7 @@ export class LayerManager {
}
/** 缓存中是否存在指定标识的窗口 */
public has(uiId: number) {
has(uiId: number) {
var config = this.configs[uiId];
if (config == null) {
warn(`编号为【${uiId}】的界面失败,配置信息不存在`);
@@ -173,7 +173,7 @@ export class LayerManager {
return result;
}
public remove(uiId: number, isDestroy = true) {
remove(uiId: number, isDestroy = true) {
var config = this.configs[uiId];
if (config == null) {
warn(`删除编号为【${uiId}】的界面失败,配置信息不存在`);
@@ -197,7 +197,7 @@ export class LayerManager {
}
/** 删除一个通过this框架添加进来的节点 */
public removeByNode(node: Node, isDestroy: boolean = false) {
removeByNode(node: Node, isDestroy: boolean = false) {
if (node instanceof Node) {
let comp = node.getComponent(DelegateComponent);
if (comp && comp.viewParams) {
@@ -213,14 +213,14 @@ export class LayerManager {
}
/** 清除所有窗口 */
public clear(isDestroy: boolean = false) {
clear(isDestroy: boolean = false) {
this.ui.clear(isDestroy);
this.popup.clear(isDestroy);
this.dialog.clear(isDestroy);
this.alert.clear(isDestroy);
}
public constructor(root: Node) {
constructor(root: Node) {
this.root = root;
this.camera = this.root.getComponentInChildren(Camera)!;

View File

@@ -1,10 +1,11 @@
{
"ver": "1.0.1",
"importer": "text",
"ver": "1.0.0",
"importer": "*",
"imported": true,
"uuid": "75bee78b-9817-4c58-a8a2-ac3626541dc2",
"files": [
".json"
".json",
".md"
],
"subMetas": {},
"userData": {}

12
assets/module.meta Normal file
View File

@@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "160e4538-8053-451b-ad7e-8d51300731bb",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

12
assets/module/common.meta Normal file
View File

@@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "0bb68e2b-ea6e-4969-9d2c-c6751d909f6d",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

View File

@@ -0,0 +1,31 @@
/*
* @Author: dgflash
* @Date: 2021-11-11 19:05:32
* @LastEditors: dgflash
* @LastEditTime: 2022-08-05 10:31:47
*/
import { _decorator } from 'cc';
import { GameComponent } from '../../core/game/GameComponent';
import { ecs } from '../../libs/ecs/ECS';
const { ccclass, property } = _decorator;
/**
* ECS结合Cocos Creator组件
* 使用方法:
* 1、对象拥有Cocos引擎组件功能、ECS 组件全局访问功能
* 2、网络游戏优先有数据对象在才创建视图组件的流程在释放视图组件时不释放数据对象
* 3、对象自带监听、释放、发送全局消息功能
* 4、对象管理的所有节点摊平直接通过节点名获取cc.Node对象节点名不能有重名
*/
@ccclass('CCComp')
export abstract class CCComp extends GameComponent implements ecs.IComp {
static tid: number = -1;
static compName: string;
canRecycle!: boolean;
ent!: ecs.Entity;
abstract reset(): void;
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "dd2077e2-c862-4b7f-9afe-6e488c83076d",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,31 @@
/*
* @Author: dgflash
* @Date: 2021-11-11 19:05:32
* @LastEditors: dgflash
* @LastEditTime: 2022-08-05 10:31:44
*/
import { _decorator } from 'cc';
import { ecs } from '../../libs/ecs/ECS';
import VMParent from '../../libs/model-view/VMParent';
const { ccclass, property } = _decorator;
/**
* Cocos Creator Component + ECS Comp + VM VMParent
* 使用方法:
* 1、对象拥有Cocos引擎组件功能、ECS 组件全局访问功能、显示对象与数据结构绑定功能
* 2、网络游戏优先有数据对象然后才创建视图组件在释放视图组件时不释放数据对象
* 3、对象自带监听、释放、发送全局消息功能
* 4、对象管理的所有节点摊平直接通过节点名获取cc.Node对象节点名不能有重名
*/
@ccclass('CCVMParentComp')
export abstract class CCVMParentComp extends VMParent implements ecs.IComp {
static tid: number = -1;
static compName: string;
canRecycle!: boolean;
ent!: ecs.Entity;
abstract reset(): void;
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "5908a4e6-3359-48b6-95e0-a3b44ea50790",
"files": [],
"subMetas": {},
"userData": {}
}

12
assets/module/config.meta Normal file
View File

@@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "ca1994dc-b0e8-4b45-8748-976ae4f5d0b9",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

View File

@@ -0,0 +1,23 @@
/*
* @Author: dgflash
* @Date: 2021-07-03 16:13:17
* @LastEditors: dgflash
* @LastEditTime: 2022-08-02 14:25:27
*/
import * as buildTimeConstants from 'cc/env';
const keys = (Object.keys(buildTimeConstants) as (keyof typeof buildTimeConstants)[]).sort();
/* 游戏运行环境 */
export class BuildTimeConstants {
constructor() {
const keyNameMaxLen = keys.reduce((len, key) => Math.max(len, key.length), 0);
var enviroment = `${keys.map((key) => {
const value = buildTimeConstants[key];
const valueRep = typeof value === 'boolean' ? (value ? 'true' : 'false') : value;
return `\n${key.padStart(keyNameMaxLen, ' ')} : ${valueRep}`;
})}`;
console.log(enviroment);
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "21a39ff8-1dc8-4974-9912-40a28a90b87d",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,48 @@
/*
* @Author: dgflash
* @Date: 2021-07-03 16:13:17
* @LastEditors: dgflash
* @LastEditTime: 2022-08-05 17:20:01
*/
import { game, JsonAsset } from "cc";
import { resLoader } from "../../../../../extensions/oops-plugin-framework/assets/core/common/loader/ResLoader";
import { oops } from "../../../../../extensions/oops-plugin-framework/assets/core/Oops";
import { BuildTimeConstants } from "./BuildTimeConstants";
import { GameConfig } from "./GameConfig";
import { GameQueryConfig } from "./GameQueryConfig";
/** 游戏配置静态访问类 */
export class Config {
/** 构建时环境常量 */
public btc!: BuildTimeConstants;
/** 配置数据,版本号、支持语种等数据 */
public game!: GameConfig;
/** 处理浏览器地址栏参数包括服务器ip、端口等数据 */
public query!: GameQueryConfig;
public init(callback: Function) {
let config_name = "config/config";
resLoader.load(config_name, JsonAsset, () => {
var config = resLoader.get(config_name);
this.btc = new BuildTimeConstants();
this.query = new GameQueryConfig();
this.game = new GameConfig(config);
// 初始化每秒传输帧数
game.frameRate = this.game.frameRate;
// Http 服务器地址
oops.http.server = this.game.httpServer;
// Http 请求超时时间
oops.http.timeout = this.game.httpTimeout;
// 初始化本地存储加密
oops.storage.init(this.game.localDataKey, this.game.localDataIv);
callback();
});
}
}
export const config = new Config()

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "5034d11e-ce8e-45ae-be9d-8591958264e1",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,59 @@
/*
* @Author: dgflash
* @Date: 2021-07-03 16:13:17
* @LastEditors: dgflash
* @LastEditTime: 2022-08-05 17:06:44
*/
import { oops } from "../../core/Oops";
/* 游戏配置解析,对应 resources/config/config.json 配置 */
export class GameConfig {
/** 客户端版本号配置 */
get version(): string {
return this._data["config"]["version"];
}
/** 包名 */
get package(): string {
return this._data["config"]["package"];
}
/** 游戏每秒传输帧数 */
get frameRate(): number {
return this._data.config.frameRate;
}
/** 本地存储内容加密 key */
get localDataKey(): string {
return this._data.config.localDataKey;
}
/** 本地存储内容加密 iv */
get localDataIv(): string {
return this._data.config.localDataIv;
}
/** Http 服务器地址 */
get httpServer(): string {
return this._data.config.httpServer;
}
/** Http 请求超时时间 */
get httpTimeout(): number {
return this._data.config.httpTimeout;
}
/** 获取当前客户端支持的语言类型 */
get language(): Array<string> {
return this._data.language.type || ["zh"];
}
get languagePathJson(): string {
return this._data.language.path.json || "language/json";
}
get languagePathTexture(): string {
return this._data.language.path.texture || "language/texture";
}
private _data: any = null;
constructor(config: any) {
let data = config.json;
this._data = Object.freeze(data);
oops.log.logConfig(this._data, "游戏配置");
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "54585cc1-b26b-467d-9103-7332c6dd21f9",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,77 @@
/*
* @Author: dgflash
* @Date: 2022-04-14 17:08:01
* @LastEditors: dgflash
* @LastEditTime: 2022-08-05 10:47:51
*/
import { sys } from "cc";
import { guid } from "../../core/common/manager/TimerManager";
import { oops } from "../../core/Oops";
/**
* 获取和处理浏览器地址栏参数
* @example
* config.query.data.username
*/
export class GameQueryConfig {
/** 调试模式开关 */
public get debug(): string {
return this._data["debug"];
}
/** 玩家帐号名 */
public get username(): string {
return this._data["username"];
}
/** 语言 */
public get lang(): string {
return this._data["lang"] || "zh";
}
private _data: any = null;
/** 浏览器地址栏原始参数 */
public get data(): any {
return this._data;
}
constructor() {
if (!sys.isBrowser) {
this._data = {};
return;
}
this._data = this.parseUrl();
if (!this._data["username"]) {
this._data["username"] = guid();
}
oops.log.logConfig(this._data, "查询参数");
}
private parseUrl() {
if (typeof window !== "object") return {};
if (!window.document) return {};
let url = window.document.location.href.toString();
let u = url.split("?");
if (typeof (u[1]) == "string") {
u = u[1].split("&");
let get: any = {};
for (let i = 0, l = u.length; i < l; ++i) {
let j = u[i];
let x = j.indexOf("=");
if (x < 0) {
continue;
}
let key = j.substring(0, x);
let value = j.substring(x + 1);
get[decodeURIComponent(key)] = value && decodeURIComponent(value);
}
return get;
}
else {
return {};
}
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "d09ac531-714e-4783-8914-8cac551162f2",
"files": [],
"subMetas": {},
"userData": {}
}