Commit 463dcf14 authored by 熊东起's avatar 熊东起

first

parents
# project ignores
node_modules
released
.DS_Store
.idea
output.js
output.js.map
\ No newline at end of file
# 最新模板分支newTemplate0805
### psd命名规则
按钮单图 图层名字_btn_id
按钮多图 组名_btn_id (里面多图层,0常态,1不可点击,2按钮)
普通图片png 图层名字_id
普通图片jpg 图层名字_jpg_id
矩形 图层名字_id
文本 图层名字_id (默认都居左,未改文本前, 调整调用Tool里方法changeTextAlign)
贴图 图层名字_tex (只切图,不进皮肤)
作为item的皮肤不进root 组名_item (比如自定义的类或滚动列表的item)
(组名,图层名字,id均为动态)
(id为英文,显示对象原属性名不能作为id,比如"name")
(同名的的图片只要图片相同就行,用clearSameImg脚本将同图移进common)
(能合并的图自行合并)
(视图模块名字命名成...Panel,...Scene,例如StartScene,RulePanel,方便生成模块传参,否则自行修改createModule脚本里的参数)
(id必须是英文,作为item的组名必须是英文,因为会生成类)
### psd解析
生成./resource/skinJson.json和./src/SkinJson.ts,
初始一致,json只用于脚本createModule.js生成场景或弹框模块,实际作用数据是ts,有需要自行修改SkinJson.ts
执行,会刷新资源配置及覆盖SkinJson.ts,注意
```shell script
#多视图解析,会解析./psd文件夹内所有psd及内视图
npm run psd
#单视图解析,主要用于处理后添加的视图,传参./psd文件夹内psd名字,
#资源及皮肤数据skin.json会在./psd文件夹内生成,自行处理进./resource/skin.json和./src/SkinJson.ts文件
npm run psdSin
```
### 生成模块 有psd生成皮肤数据时使用
会根据参数Panel或者Scene生成ts文件写入./src/panels或./src/scenes文件夹
```shell script
npm run createModule RulePanel
```
### 资源配置刷新
有资源删除或增加时执行
会根据resource里的子级文件夹分组
文件夹名字用于各模块里的groupNames,用于按需资源加载
```shell script
npm run flushRes
```
### 本地开发
```shell script
npm run dev
```
### 图集工具安装
```shell script
#全局安装
cnpm install pack_textures -g
#终端输入packTextures检查环境变量是否存在
```
### 淘宝打包流程
```shell script
#带资源打包,并生成./released/resource文件夹和./released/output.js文件
npm run build
#只打包代码,
npm run buildTS
#脚本copyJs.js自行修改小程序output.js文件路径,嫌麻烦自行修改package.json里的build和buildTS,也可自行复制output.js
npm run copyJs
```
### web打包流程
```shell script
#带资源打包,并生成./released/resource文件夹和./output.js文件及./released/index.html,可复制进皮肤
npm run buildWeb
#只打包代码,并生成./output.js文件及./released/index.html,会打印版本号,可直接更换皮肤的版本号
npm run buildWebTS
```
### 适配
./module/views/layers.ts可设置所有层级适配(弹框场景等等)
单独模块的适配自行在模块里处理,修改this.y
### psd导出文本
部分文案尺寸错误自行在SkinJson,ts里修改
居中居右,在未修改文本字号字符等属性前调用Tools.changeTextAlign修改,可与psd表现保持一致
\ No newline at end of file
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Document</title>
<meta name="viewport"
content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="full-screen" content="true" />
<meta name="screen-orientation" content="portrait" />
<meta name="x5-fullscreen" content="true" />
<meta name="360-fullscreen" content="true" />
<!-- 渲染引擎 -->
<!-- <script src="//yun.duiba.com.cn/db_games/libs0924/fyge2020.min.js" crossorigin="anonymous"></script> -->
<!-- svga解析库 -->
<script src="//yun.duiba.com.cn/db_games/libs0924/svgaParser.minWeb.js" crossorigin="anonymous"></script>
<!-- 本地的js,需要souremap调试的用本地js -->
<script src="libs/fyge.min.js"></script>
<script src="//yun.duiba.com.cn/db_games/libs0924/howler.min.js"></script>
<!-- <script src="libs/svgaParser.min.js"></script> -->
<!-- <script src="libs/svgaParser.min1.js"></script> -->
<style>
html,
body {
padding: 0;
margin: 0;
border: 0;
width: 100%;
height: 100%;
overflow: hidden;
position: absolute;
background-color: #ffffff;
/* background: linear-gradient(#93dbb7,#ff0,#b5d89a); */
/* background: linear-gradient(#93dbb7,#b5d89a); */
/* 背景图片,解决加载太慢,白屏问题,加了这个下面的__loading__可以删掉了 */
/* background-size: 100%;
background-position: center;
background-image: url("https://yun.duiba.com.cn/db_games/activity/game/1550472986/resource/assets/playscene/playscenebg.jpg"); */
}
</style>
</head>
<body>
<div id="__loading__" style="position:absolute;left:50%;top:50%;margin-left:-45px;color:#ffffff">拼命加载中...</div>
<div id="cusEngine" style="line-height:0;font-size:0;position: absolute;">
<canvas id="canvas" style="width: 100%;height: 100%"></canvas>
</div>
<!-- 帧率检测 -->
<!-- <script src="//yun.duiba.com.cn/db_games/libs0924/stats.js"></script> -->
<script src="https://yun.duiba.com.cn/db_games/libs0126/stats.js"></script>
<script src="libs/matter.min.js"></script>
<script>
window.addEventListener("load", function () {
//获取canvas
var canvas = document.getElementById("canvas");
canvas.width = document.body.clientWidth * (window.devicePixelRatio || 1)
canvas.height = document.body.clientHeight * (window.devicePixelRatio || 1)
var main = new Main(canvas);
var mouseEvent = main.stage.onMouseEvent.bind(main.stage);
canvas.addEventListener("touchstart", mouseEvent, false);
canvas.addEventListener('touchmove', mouseEvent, false);
canvas.addEventListener('touchend', mouseEvent, false);
window.stage = main.stage
})
</script>
<!-- 构建的js -->
<script src="output.js" crossorigin="anonymous"></script>
</body>
</html>
\ No newline at end of file
This diff is collapsed.
declare module SvgaParser {
/**
* 加载方法
* @param url 资源路径
* @param success
* @param failure
*/
export function loadSvga(url: string, success: (videoItem: VideoEntity) => void, failure?: (err: string) => void): void;
/**
* 导出只是当作类型接口用
*/
export interface VideoEntity {
/**
* SVGA 文件版本
*/
version: string;
/**
* 影片尺寸
*/
videoSize: {
width: number;
height: number;
};
/**
* 帧率,60,30等每秒
*/
FPS: number;
/**
* 总帧数
*/
frames: number;
/**
* base64图片数据记录
*/
images: {
[key: string]: string
};
/**
* 图片是否已被缓存,缓存全局,注意名字覆盖
*/
hasBeenCached: boolean;
/**
* sprite对象数据
*/
sprites: SpriteEntity[];
}
interface SpriteEntity {
/**
* 标识
*/
matteKey: string;
/**
* 图片key值
*/
imageKey: string;
/**
* 帧数据数组
*/
frames: FrameEntity[];
}
/**
* 还有很多其他数据,暂不需要,比如矢量路径和遮罩路径暂时都无
*/
interface FrameEntity {
/**
* 透明度
*/
alpha: number;
/**
* 2维矩阵数据
*/
transform: {
a: number,
b: number,
c: number,
d: number,
tx: number,
ty: number,
};
}
}
declare module "svga-parser" { export = SvgaParser; }
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
// Type definitions for howler.js v2.1.1
// Project: https://github.com/goldfire/howler.js
// Definitions by: Pedro Casaubon <https://github.com/xperiments>
// Alexander Leon <https://github.com/alien35>
// Nicholas Higgins <https://github.com/nicholashza>
// Carlos Urango <https://github.com/cjurango>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
interface HowlerGlobal {
mute(muted: boolean): this;
volume(): number;
volume(volume: number): this;
codecs(ext: string): boolean;
unload(): this;
usingWebAudio: boolean;
html5PoolSize: number;
noAudio: boolean;
autoUnlock: boolean;
autoSuspend: boolean;
ctx: AudioContext;
masterGain: GainNode;
stereo(pan: number): this;
pos(x: number, y: number, z: number): this | void;
orientation(x: number, y: number, z: number, xUp: number, yUp: number, zUp: number): this | void;
}
declare let Howler: HowlerGlobal;
interface IHowlSoundSpriteDefinition {
[name: string]: [number, number] | [number, number, boolean]
}
interface IHowlProperties {
src: string | string[];
volume?: number;
html5?: boolean;
loop?: boolean;
preload?: boolean;
autoplay?: boolean;
mute?: boolean;
sprite?: IHowlSoundSpriteDefinition;
rate?: number;
pool?: number;
format?: string[] | string;
xhrWithCredentials?: boolean;
onload?: () => void;
onloaderror?: (soundId: number, error: any) => void;
onplay?: (soundId: number) => void;
onplayerror?: (soundId: number, error: any) => void;
onend?: (soundId: number) => void;
onpause?: (soundId: number) => void;
onstop?: (soundId: number) => void;
onmute?: (soundId: number) => void;
onvolume?: (soundId: number) => void;
onrate?: (soundId: number) => void;
onseek?: (soundId: number) => void;
onfade?: (soundId: number) => void;
onunlock?: (soundId: number) => void;
}
interface Howl {
play(spriteOrId?: string | number): number; // .play() is not chainable; the other methods are
pause(id?: number): this;
stop(id?: number): this;
mute(): boolean;
mute(muted: boolean, id?: number): this;
volume(): number;
volume(idOrSetVolume: number): this | number;
volume(volume: number, id: number): this;
fade(from: number, to: number, duration: number, id?: number): this;
rate(): number;
rate(idOrSetRate: number): this | number;
rate(rate: number, id: number): this;
seek(seek?: number, id?: number): this | number;
loop(id?: number): boolean;
loop(loop: boolean, id?: number): this;
playing(id?: number): boolean;
duration(id?: number): number;
state(): 'unloaded' | 'loading' | 'loaded';
load(): this;
unload(): void;
on(event: 'load', callback: () => void, id?: number): this;
on(event: 'loaderror', callback: (soundId: number, error: any) => void, id?: number): this;
on(event: 'play', callback: (soundId: number) => void, id?: number): this;
on(event: 'playerror', callback: (soundId: number, error: any) => void, id?: number): this;
on(event: 'end', callback: (soundId: number) => void, id?: number): this;
on(event: 'pause', callback: (soundId: number) => void, id?: number): this;
on(event: 'stop', callback: (soundId: number) => void, id?: number): this;
on(event: 'mute', callback: (soundId: number) => void, id?: number): this;
on(event: 'volume', callback: (soundId: number) => void, id?: number): this;
on(event: 'rate', callback: (soundId: number) => void, id?: number): this;
on(event: 'seek', callback: (soundId: number) => void, id?: number): this;
on(event: 'fade', callback: (soundId: number) => void, id?: number): this;
on(event: string, callback: Function, id?: number): this;
on(event: 'unlock', callback: (soundId: number) => void, id?: number): this;
once(event: 'load', callback: () => void, id?: number): this;
once(event: 'loaderror', callback: (soundId: number, error: any) => void, id?: number): this;
once(event: 'play', callback: (soundId: number) => void, id?: number): this;
once(event: 'playerror', callback: (soundId: number, error: any) => void, id?: number): this;
once(event: 'end', callback: (soundId: number) => void, id?: number): this;
once(event: 'pause', callback: (soundId: number) => void, id?: number): this;
once(event: 'stop', callback: (soundId: number) => void, id?: number): this;
once(event: 'mute', callback: (soundId: number) => void, id?: number): this;
once(event: 'volume', callback: (soundId: number) => void, id?: number): this;
once(event: 'rate', callback: (soundId: number) => void, id?: number): this;
once(event: 'seek', callback: (soundId: number) => void, id?: number): this;
once(event: 'fade', callback: (soundId: number) => void, id?: number): this;
once(event: string, callback: Function, id?: number): this;
once(event: 'unlock', callback: (soundId: number) => void, id?: number): this;
off(event: string, callback?: Function, id?: number): this;
off(): this;
stereo(pan: number, id?: number): this | void;
pos(x: number, y: number, z: number, id?: number): this | void;
orientation(x: number, y: number, z: number, xUp: number, yUp: number, zUp: number): this | void;
pannerAttr(o: {
coneInnerAngle?: number,
coneOuterAngle?: number, coneOuterGain?: number,
distanceModel: 'inverse' | 'linear', maxDistance: number,
panningModel: 'HRTF' | 'equalpower', refDistance: number, rolloffFactor: number
}, id?: number): this;
}
interface HowlStatic {
new(properties: IHowlProperties): Howl;
}
declare let Howl: HowlStatic;
declare module "howler" {
export let Howler: HowlerGlobal;
export let Howl: HowlStatic;
}
This diff is collapsed.
This diff is collapsed.
var Stats = function () {
var startTime = Date.now(), prevTime = startTime;
var ms = 0, msMin = Infinity, msMax = 0;
var fps = 0, fpsMin = Infinity, fpsMax = 0;
var frames = 0, mode = 0;
var container = document.createElement('div');
container.id = 'stats';
container.addEventListener('mousedown', function (event) { event.preventDefault(); setMode(++mode % 2) }, false);
container.style.cssText = 'width:80px;opacity:0.9;cursor:pointer';
var fpsDiv = document.createElement('div');
fpsDiv.id = 'fps';
fpsDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#002';
container.appendChild(fpsDiv);
var fpsText = document.createElement('div');
fpsText.id = 'fpsText';
fpsText.style.cssText = 'color:#0ff;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';
fpsText.innerHTML = 'FPS';
fpsDiv.appendChild(fpsText);
var fpsGraph = document.createElement('div');
fpsGraph.id = 'fpsGraph';
fpsGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0ff';
fpsDiv.appendChild(fpsGraph);
while (fpsGraph.children.length < 74) {
var bar = document.createElement('span');
bar.style.cssText = 'width:1px;height:30px;float:left;background-color:#113';
fpsGraph.appendChild(bar);
}
var msDiv = document.createElement('div');
msDiv.id = 'ms';
msDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;display:none';
container.appendChild(msDiv);
var msText = document.createElement('div');
msText.id = 'msText';
msText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';
msText.innerHTML = 'MS';
msDiv.appendChild(msText);
var msGraph = document.createElement('div');
msGraph.id = 'msGraph';
msGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0f0';
msDiv.appendChild(msGraph);
while (msGraph.children.length < 74) {
var bar = document.createElement('span');
bar.style.cssText = 'width:1px;height:30px;float:left;background-color:#131';
msGraph.appendChild(bar);
}
var setMode = function (value) {
mode = value;
switch (mode) {
case 0:
fpsDiv.style.display = 'block';
msDiv.style.display = 'none';
break;
case 1:
fpsDiv.style.display = 'none';
msDiv.style.display = 'block';
break;
}
}
var updateGraph = function (dom, value) {
var child = dom.appendChild(dom.firstChild);
child.style.height = value + 'px';
}
return {
REVISION: 11,
domElement: container,
setMode: setMode,
begin: function () {
startTime = Date.now();
},
end: function () {
var time = Date.now();
ms = time - startTime;
msMin = Math.min(msMin, ms);
msMax = Math.max(msMax, ms);
msText.textContent = ms + ' MS (' + msMin + '-' + msMax + ')';
updateGraph(msGraph, Math.min(30, 30 - (ms / 200) * 30));
frames++;
if (time > prevTime + 1000) {
fps = Math.round((frames * 1000) / (time - prevTime));
fpsMin = Math.min(fpsMin, fps);
fpsMax = Math.max(fpsMax, fps);
fpsText.textContent = fps + ' FPS (' + fpsMin + '-' + fpsMax + ')';
updateGraph(fpsGraph, Math.min(30, 30 - (fps / 100) * 30));
prevTime = time;
frames = 0;
}
return time;
},
update: function () {
startTime = this.end();
}
}
};
//执行
var stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
document.body.appendChild(stats.domElement);
aa();
function aa() {
stats.update();
requestAnimationFrame(aa)
}
\ No newline at end of file
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "tbgame",
"version": "1.0.0",
"description": "",
"main": "index.html",
"devDependencies": {
"ali-oss": "^4.11.4",
"chalk": "^2.3.0",
"co": "^4.6.0",
"del": "^2.2.1",
"fs": "0.0.2",
"imagemin": "^7.0.1",
"imagemin-mozjpeg": "^8.0.0",
"imagemin-pngquant": "^8.0.0",
"mock-webpack-plugin": "^2.0.0",
"path": "^0.12.7",
"progress": "^2.0.0",
"psd": "^3.2.0",
"readline": "^1.3.0",
"ts-loader": "^4.0.0",
"tslint": "^5.9.1",
"typescript": "^3.5.1",
"webpack": "^4.1.0",
"webpack-cli": "^3.1.1",
"webpack-dev-server": "^3.1.0",
"webpack-merge": "^4.1.2"
},
"dependencies": {
"matter-js": "^0.17.0"
},
"scripts": {
"psd": "node scripts/psdH && node scripts/flushRes",
"psdSin": "node scripts/psdHSin",
"clearSameImg": "node scripts/clearSameImg && node scripts/flushRes",
"createModule": "node scripts/createModule",
"createAllModule": "node scripts/createAllModule",
"flushRes": "node scripts/flushRes",
"handleRes": "node scripts/delRel && node scripts/copyRes && node scripts/createTm && node scripts/textureMerge && node scripts/delTm && node scripts/imageMin",
"upload": "node scripts/upload",
"build": "npm run handleRes && node scripts/mergeJson && npm run upload && npm run buildTS",
"watch": "webpack --watch",
"dev": "webpack-dev-server --open --config webpack.dev.js --host 0.0.0.0",
"dev1": "node scripts/devServer",
"buildTS": "webpack --config webpack.prod.js && node scripts/mergeJs",
"copyJs": "node scripts/copyJs",
"buildWeb": "npm run handleRes && node scripts/mergeJson && node scripts/upload 1",
"buildWebTS": "webpack --config webpack.prod.js && node scripts/uploadSingleJs 1"
},
"author": "MrKwon",
"license": "ISC"
}
{
"type": "activity",
"name": "template"
}
\ No newline at end of file
File added
{
"groups": [
{
"keys": "comCloseBtn.png,toastBg.png,waitingBg.png,waitingRot.png",
"name": "common"
}
],
"path": "./resource/"
}
\ No newline at end of file
This diff is collapsed.
var fs = require("fs");
var path = require('path');
var del = require('del');
var pathName = "./resource";
var inPath = "./resource/common/";
{
key: ["aa", "bb"]
}
var hash = {};//记录名字和所在文件夹
var files = fs.readdirSync(pathName);
files.forEach(function (file) {
//文件common,不处理
if (file == "common") return
//路径
let fPath = path.join(pathName, file);
//只处理文件夹
if (fs.statSync(fPath).isDirectory()) {
var sonFiles = fs.readdirSync(fPath);
//没有文件
if (!sonFiles.length) return;
sonFiles.forEach(function (s) {
if (!hash[s]) hash[s] = [];
hash[s + ""].push(file);
})
}
})
//遍历
for (var key in hash) {
//有重复的,拷贝到common,删除原文件夹里的文件,
if (hash[key].length > 1) {
// 拷贝到common
fs.writeFileSync(inPath + key, fs.readFileSync(pathName + "/" + hash[key][0] + "/" + key));
console.log("重复资源:" + key)
//删除原文件夹里的文件,
hash[key].forEach(function (s) {
del(pathName + "/" + s + "/" + key)
})
}
}
console.log("重复资源处理完成")
\ No newline at end of file
var fs = require("fs");
// fs.writeFileSync(
// "./released/output.js",
// fs.readFileSync("./output.js")
// )
// var endPath = 'D:/duibaGame/测试项目0527/taobaominiTest/client/pages/index1/';
var endPath = 'D:/duibaGame/淘宝项目/taobao_mini/babycare_xiaoxiaole/babycare_c_client/client/pages/index/';
var version = Math.round(new Date().getTime() / 1000);
// fs.writeFileSync(endPath + "output." + version + ".js", fs.readFileSync("./released/output.js"));
fs.writeFileSync(endPath + "output.js", fs.readFileSync("./released/output.js"));
// console.log("js覆盖完成")
console.log(`版本号:
${version}`)
// cp infile outfile 拷贝文件直接放指令里
\ No newline at end of file
var fs = require('fs');
var path = require("path");
function writeFile(p, text) {
fs.writeFile(p, text, function (err) {
// if (!err)
// console.log("写入成功!")
})
}
//递归创建目录 同步方法
function mkdirsSync(dirname) {
if (fs.existsSync(dirname)) {
return true;
} else {
if (mkdirsSync(path.dirname(dirname))) {
// console.log("mkdirsSync = " + dirname);
fs.mkdirSync(dirname);
return true;
}
}
}
function _copy(src, dist) {
var paths = fs.readdirSync(src)
paths.forEach(function (p) {
var _src = src + '/' + p;
var _dist = dist + '/' + p;
var stat = fs.statSync(_src)
if (stat.isFile()) {// 判断是文件还是目录
fs.writeFileSync(_dist, fs.readFileSync(_src));
} else if (stat.isDirectory()) {
copyDir(_src, _dist)// 当是目录是,递归复制
}
})
}
/*
* 复制目录、子目录,及其中的文件
* @param src {String} 要复制的目录
* @param dist {String} 复制到目标目录
*/
function copyDir(src, dist) {
var b = fs.existsSync(dist)
// console.log("dist = " + dist)
if (!b) {
// console.log("mk dist = ",dist)
mkdirsSync(dist);//创建目录
}
// console.log("_copy start")
_copy(src, dist);
}
function createDocs(src, dist, callback) {
// console.log("createDocs...")
copyDir(src, dist);
// console.log("copyDir finish exec callback")
if (callback) {
callback();
}
}
createDocs("./resource", "./released/resource/", function () {
console.log("资源拷贝成功")
})
\ No newline at end of file
var exec = require('child_process').exec;
var fs = require("fs");
//用这个生成所有的,最好把createModule里的warn去掉,否则子进程的打不到
const skinDataAll = JSON.parse(fs.readFileSync("./resource/skin.json"));
skinDataAll.children.forEach(c => {
const cmd = "node ./scripts/createModule.js " + c.name;
exec(cmd, { encoding: 'utf8' }, (e) => {
console.log("生成模块:" + c.name)
})
});
var fs = require("fs");
function createHtml(url) {
var js = `//yun.duiba.com.cn/db_games/${url}/output.js`;
var template = fs.readFileSync("./index.html").toString();
//写入released
fs.writeFileSync("./released/index.html", template.replace("output.js", js))
}
module.exports = createHtml
\ No newline at end of file
var fs = require("fs");
function createHtml(url) {
var template =
`<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Document</title>
<meta name="viewport"
content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="full-screen" content="true" />
<meta name="screen-orientation" content="portrait" />
<meta name="x5-fullscreen" content="true" />
<meta name="360-fullscreen" content="true" />
<!-- <script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script> -->
<!-- 小程序分享得用这个 -->
<!-- <script src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script> -->
<!-- 易盾js -->
<!-- <script type="text/javascript" src="//cstaticdun.126.net/load.min.js"></script> -->
<!-- 渲染引擎 -->
<script src="//yun.duiba.com.cn/db_games/libs0924/fyge158.min.js" crossorigin="anonymous"></script>
<!-- svga解析js(按需) -->
<!-- <script src="//yun.duiba.com.cn/db_games/libs0924/svgaParser.minWeb.js" crossorigin="anonymous"></script> -->
<!-- 音效引擎(按需) -->
<!-- <script src="//yun.duiba.com.cn/db_games/libs0924/howler.min.js"></script> -->
<!-- vConsole -->
<script src="//yun.duiba.com.cn/db_games/libs0924/vConsole.min.js"></script>
<!-- 淘宝小程序webview sdk -->
<!-- <script type="text/javascript" src="https://appx/web-view.min.js"></script> -->
<style>
html,
body {
padding: 0;
margin: 0;
border: 0;
width: 100%;
height: 100%;
overflow: hidden;
position: absolute;
background-color: #015581;
}
</style>
</head>
<body>
<div id="__loading__" style="position:absolute;left:50%;top:50%;margin-left:-45px;color:#ffffff">拼命加载中...</div>
<div id="cusEngine" style="line-height:0;font-size:0;position:absolute;">
<canvas id="canvas" style="width: 100%;height: 100%"></canvas>
</div>
</body>
<script>
window.addEventListener("load", function () {
//获取canvas
var canvas = document.getElementById("canvas");
canvas.width = document.body.clientWidth * (window.devicePixelRatio || 1)
canvas.height = document.body.clientHeight * (window.devicePixelRatio || 1)
var main = new Main(canvas);
var mouseEvent = main.stage.onMouseEvent.bind(main.stage);
canvas.addEventListener("touchstart", mouseEvent, false);
canvas.addEventListener('touchmove', mouseEvent, false);
canvas.addEventListener('touchend', mouseEvent, false);
window.stage = main.stage
})
</script>
<script src="//yun.duiba.com.cn/db_games/${url}/output.js" crossorigin="anonymous"></script>
</html>`;
//写入released
fs.writeFileSync("./released/index.html", template)
}
module.exports = createHtml
\ No newline at end of file
var fs = require("fs");
var warn = require("./warn")
//类型对应
const DISRES = {
'container': "Container",
'text': "TextField",
'button': "Button",
'sprite': "Sprite",
'rect': "Graphics",
// 'skin'
}
const skinDataAll = JSON.parse(fs.readFileSync("./resource/skin.json"))
//取指令后的参数
let arg = process.argv.splice(2);
//类名
var className = arg[0];
//皮肤名字
var skinName = arg[0]; //arg[1];
//是否弹框,存在参数就是场景
var moduleType = className.indexOf("Scene") > -1 ? "Scene" : "Panel";
// console.log('类名:',className)
// console.log('皮肤名字:',skinName)
var skinData = getSkinDataByName(skinName, skinDataAll);
if (!skinData) {
console.log(skinName + "皮肤不存在");
return
}
var groupName = skinData.name;
var endPath = moduleType == "Panel" ? "./src/panels/" : "./src/scenes/";
// var template =
// (moduleType == "Panel" ?
// 'import { Panel } from "../../module/views/Panel";\n' :
// 'import { Scene } from "../../module/views/Scene";\n') +
// 'export class ' + className + ' extends ' + moduleType + ' {\n' +
// '\tget groupNames() { return ["' + groupName + '"] }\n' +
// '\tget skinName() { return "' + skinName + '" }\n' +
// '\t' + getIds(skinData) + "\n" +
// '\tinitUi() {\n' +
// ' \n' +
// '\t}\n' +
// '\tstart(data) {\n' +
// '\t\tsuper.start();\n' +
// '\t}\n' +
// '\tinitEvents() {\n' +
// '\t\tsuper.initEvents();' +
// ' \n' +
// '\t}\n' +
// '\tremoveEvents() {\n' +
// '\t\tsuper.removeEvents();' +
// ' \n' +
// '\t}\n' +
// '}\n'
var template =
(moduleType == "Panel" ?
'import { Panel } from "../../module/views/Panel";\n' :
'import { Scene } from "../../module/views/Scene";\n') +
`export class ${className} extends ${moduleType} {
get groupNames() { return ["${groupName}"] };
get skinName() { return "${skinName}" };
${getIds(skinData)}
initUi() {
}
start(data) {
super.start();
}
initEvents() {
super.initEvents();
}
removeEvents() {
super.removeEvents();
}
}\n\n`
//取出skinName里的Item
var skins = getItemSkins(skinData)
if (skins.length) template = 'import { Item } from "../../module/views/Item";\n' + template;
for (var i = 0; i < skins.length; i++) {
var skin = skins[i];
// template +=
// 'class ' + upperCaseFirstChar(skin.name) + ' extends Item {\n' +
// '\tget skinName() { return "' + skin.name + '" }\n' +
// '\t' + getIds(skin) + "\n" +
// '\tinitUi(data?) {\n' +
// ' \n' +
// '\t}\n' +
// '\tupdateData(data?) {\n' +
// ' \n' +
// '\t}\n' +
// '\tinitData(id: number, data: any): void {\n' +
// '\t\tsuper.initData(id,data);\n' +
// ' \n' +
// '\t}\n' +
// '\tresetData() {\n' +
// ' \n' +
// '\t}\n' +
// '}\n'
template +=
`class ${upperCaseFirstChar(skin.name)} extends Item {
get skinName() { return "${skin.name}" }
${getIds(skin)}
initUi(data?) {
}
updateData(data?) {
}
initData(id: number, data: any): void {
if (id < 0 || !data) return;
super.initData(id,data);
}
resetData() {
}
}\n\n`;
}
//不存在时建一个
if (!fs.existsSync(endPath)) fs.mkdirSync(endPath);
//判断ts文件是否已存在
if (fs.existsSync(endPath + className + ".ts")) {
warn(
className + ".ts已存在,是否覆盖",
() => {
fs.writeFileSync(endPath + className + ".ts", template)
},
() => { }
)
} else {
fs.writeFileSync(endPath + className + ".ts", template)
}
// function cutIds(ids) {
// var str = ''
// var arr = ids.split(";")
// // console.log(arr)
// arr.forEach(element => {
// if (element) str += element + ";\n\t"
// });
// return str
// }
/**
* 获取皮肤数据
* @param {*} skinName
* @param {*} skinNode
*/
function getSkinDataByName(skinName, skinNode) {
if (!skinNode || !skinNode.children || !skinNode.children.length) return null;
for (var i = 0; i < skinNode.children.length; i++) {
var child = skinNode.children[i];
//皮肤数据得是容器
if (child.name == skinName && (child.type == "container" || child.type == "item")) return child;
var gson = getSkinDataByName(skinName, child);
if (gson) return gson
}
return null;
}
//取出所有的Item的皮肤,标记为item的
function getItemSkins(skinNode) {
var arr = []
for (var i = 0; i < skinNode.children.length; i++) {
var c = skinNode.children[i];
if (c.type == 'item') arr.push(c);
if (c.children) getItemSkins(c).forEach((cc) => {
arr.push(cc);
})
}
return arr
}
function getIds(skinNode, str) {
str = str || ''
for (var i = 0; i < skinNode.children.length; i++) {
var c = skinNode.children[i];
if (c.id) str += c.id + ": FYGE." + DISRES[c.type] + ";\n\t";
//作为item的不进
if (c.type == "container" && c.type != "item") str = getIds(c, str);
}
return str
}
function upperCaseFirstChar(str) {
return str.charAt(0).toUpperCase() + str.slice(1)
}
var fs = require("fs");
var iconv = require('iconv-lite');
var del = require('del');
var readPath = "./released/resource/";
//读取json文件
var data = iconv.decode(fs.readFileSync(readPath + "res.json"), "utf-8");//GBK
//反序列化
data = JSON.parse(data); //eval(data)
//取出里面的图片,暂存到tm文件夹中,同时删除文件夹里的,和本身json里的
if (!fs.existsSync("./released/tm"))
fs.mkdirSync("./released/tm");
for (var i = 0; i < data.groups.length; i++) {
var name = data.groups[i].name;
var path = readPath + name + "/";
var arr = data.groups[i].keys.split(",");
//取出图片的,注意已排除jpg
var images = arr.filter((f) => { return (f.substr(-4) == ".png" /*|| f.substr(-4) == ".jpg"*/) })
//没有图片,
if (!images.length) continue;
//去掉原先数据里的
// data.groups[i].keys = arr.filter((f) => { return (f.substr(-4) != ".png" && f.substr(-4) != ".jpg") }).join(",");
//添加新的json,加到atlas里
// if (data.groups[i].keys) data.groups[i].keys += ","
data.groups[i].atlas = name + ".json"
//读取原先路径里的图片,写到tm的文件夹里,并删除原文件夹里的图片
fs.mkdirSync("./released/tm/" + name);
for (var m = 0; m < images.length; m++) {
fs.writeFileSync(
"./released/tm/" + name + "/" + images[m],
fs.readFileSync(path + images[m])
)
del(path + images[m])
}
}
//序列化
fs.writeFileSync(readPath + "res.json", JSON.stringify(data, "", "\t"));
var fs = require("fs");
var del = require('del');
function delDir(path, isSelf) {
let files = [];
if (fs.existsSync(path)) {
files = fs.readdirSync(path);
files.forEach((file, index) => {
let curPath = path + "/" + file;
if (fs.statSync(curPath).isDirectory()) {
delDir(curPath); //递归删除文件夹
} else {
fs.unlinkSync(curPath); //删除文件
}
});
if (!isSelf) fs.rmdirSync(path);
}
}
var paths = './released/';//设置删除路径
// delDir(paths, true);//删除文件夹
del(paths).then(() => {
fs.mkdirSync(paths);
}).catch(()=>{
fs.mkdirSync(paths);
})
// var tasks = [];
// function addTask(task) {
// tasks.push(task);
// }
// function next() {
// if (tasks.length > 0) {
// tasks.shift()();
// } else {
// return;
// }
// }
// var delRel = function () {
// del(paths).then(() => {
// // console.log("del")
// next();
// })
// }
// var createRel = function () {
// fs.mkdirSync(paths);
// // console.log("create")
// next();
// }
// addTask(delRel)
// addTask(createRel)
// next();
\ No newline at end of file
var del = require('del');
del("./released/tm")
\ No newline at end of file
var fs = require("fs")
var skinUrl = "./resource/skin.json";
fs.watchFile(skinUrl, { persistent: true, interval: 2000 }, (curr, prev) => {
const skinDataAll = fs.readFileSync(skinUrl)
var endFile = `export const SkinJson = ${skinDataAll}`
fs.writeFileSync("./src/SkinJson.ts", endFile);
console.log("SkinJson.ts文件已更新")
})
const webpackDevServer = require('webpack-dev-server');
const webpack = require('webpack');
const config = require('../webpack.dev.js');
const options = {
open: true,
contentBase: '.',
hot: true,
host: 'localhost',
};
webpackDevServer.addDevServerEntrypoints(config, options);
const compiler = webpack(config);
const server = new webpackDevServer(compiler, options);
server.listen(8080, '0.0.0.0', () => {
});
\ No newline at end of file
//生成res.json
//遍历资源文件夹,生成
var fs = require('fs');
var path = require("path");
var readPath = "./resource/"
var files = fs.readdirSync(readPath);
var obj = { groups: [] };//每项包括keys合name
files.forEach(function (file) {
//路径
let fPath = path.join(readPath, file);
//只处理文件夹
if (fs.statSync(fPath).isDirectory()) {
//继续读每个子文件夹,json和png名字有相同的,只留json,
var sonFiles = fs.readdirSync(fPath);
//没有文件
if (!sonFiles.length) return
//取出所有json
var jsons = sonFiles.filter((f) => { return f.substr(-5) == ".json" })
//去掉json所带png的图片
sonFiles = sonFiles.filter((f) => { return jsons.indexOf(f.substring(0, f.length - 4) + ".json") == -1 })
//去掉mac上的缓存文件
sonFiles = sonFiles.filter((f) => { return f != '.DS_Store' })
var group = {
keys: "",
name: file
}
for (var i = 0; i < sonFiles.length; i++) {
if (i != 0) group.keys += ",";
group.keys += sonFiles[i]
}
obj.groups.push(group)
}
})
obj.path="./resource/"
console.log("资源更新完成")
//生成json
fs.writeFileSync(readPath + "res.json", JSON.stringify(obj, "", "\t"));
//TS也更新
var endPath = './src/';
var endFile = `export const ResJson = ${JSON.stringify(obj, "", "\t")}`
fs.writeFileSync(endPath + "ResJson.ts", endFile);
\ No newline at end of file
var fs = require("fs");
var iconv = require('iconv-lite');
var path = require('path');
const trans = require("./trans")
//用于处理带base64图片的lottie文件,取出图片,同名lottie文件夹,写入代码"./src/lotties/"中;
//别再执行,会覆盖
// return
var hashBase64 = {};
var pathName = "./lotties";
var outPath = "./resource"
//读文件夹
var files = fs.readdirSync(pathName);
//对每个json文件作处理
files.forEach(function (lottiesFileName) {
// console.log(lottiesFileName)
//后缀不是json的,不处理
if (path.extname(lottiesFileName).indexOf(".json") < 0) return;
//用文件名作为类名和资源文件夹名
const cusName = lottiesFileName.substring(0, lottiesFileName.lastIndexOf(".json"));
//读数据
var data = iconv.decode(fs.readFileSync(pathName + "/" + lottiesFileName), "utf-8");//GBK
//反序列化
data = JSON.parse(data);
//存图片
var assets = data.assets;
if (!assets || !assets.length) return;
//删除属性
delete data.assets;
var imgOutPath = outPath + "/" + cusName//data.nm
//建文件夹data.nm
if (!fs.existsSync(imgOutPath)) fs.mkdirSync(imgOutPath);
assets.forEach((e) => {
//没有base64数据
if (!e.p) return
let id = e.id;
// let uuid = guid();
// //存图片
var base64 = e.p.replace(/^data:image\/\w+;base64,/, "");//去掉图片base64码前面部分data:image/png;base64
var dataBuffer = /*new Buffer*/Buffer.from(base64, 'base64'); //把base64码转成buffer对象,
//用用到该图片的图层的名字当作图片名,必须是.png结尾,为了图片去重
var name = data.layers.find((l) => { return l.refId === id })
//没找到图层,不存
if (!name) return;
//如果缓存过了,refId,统一把refId当作必有图片
if (hashBase64[base64]) {
name = hashBase64[base64];
} else {
//取图层名字,如果没有。png,用uuid
// if (name.nm.indexOf(".png") == -1) {
name = guid();
// } else {
// //取名字
// name = name.nm.replace(".png", "");
// }
hashBase64[base64] = name
}
//修改所有的refId
data.layers.forEach((l) => { l.refId === id && (l.refId = name) })
fs.writeFile(imgOutPath + "/" + name + ".png", dataBuffer, () => { });
})
//开始删东西
//是否3d
delete data.ddd;
//版本号,版本必须5.6.10,否则可能有问题
delete data.v;
//遍历删除图层东西
for (var i = 0; i < data.layers.length; i++) {
var l = data.layers[i];
//是否3d,后缀,sr,ao,开始时间,混合模式,特效
["ddd", "cl", "sr", "ao", "st", "bm", "ef"].forEach((e) => { delete l[e]; });
//ks删除
["o", "r", "p", "a", "s"].forEach((e) => {
var d = l.ks[e];
//ix不知道干嘛用,删了
delete d.ix;
//貌似标记0是没有关键帧的,1是有关键帧的
delete d.a;
//删除k里数据,都要用了,不能删,看情况用吧,如果不需要补间的,用Tween拼的,就删掉,不删只是文件大点
if (d.k.length && typeof d.k[0] == "object") {
d.k.forEach((ee) => {
["i", "o", "ti", "to"/*, "h"*/].forEach((eee) => { delete ee[eee]; })//h需要判断是否是缓动
})
}
})
}
//导出代码到src的lotties文件夹,名字就是lottie动画名字,资源名字临时处理了,首页加载动画用图层的nm,bonustime用refid
var endPath = './src/lotties';
if (!fs.existsSync(endPath)) fs.mkdirSync(endPath);
//文件名字修改,中划线变成下划线,中文变拼音
var fileName = trans(cusName/*data.nm*/).replace(/-/g, "_")
//导出对象直接用lottie动画名字
var endFile = `export const ${fileName} = ${JSON.stringify(data, "", "\t")}`
//文件名字用lottie动画名字
fs.writeFileSync(endPath + "/" + fileName + ".ts", endFile);
console.log("生成文件:" + fileName + ".ts")
})
function guid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0,
v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
const imagemin = require('imagemin');
// const imageminJpegtran = require('imagemin-jpegtran');imagemin-mozjpeg
const imageminJpegtran = require('imagemin-mozjpeg');
const imageminPngquant = require('imagemin-pngquant');
var fs = require('fs');
var path = require('path');
// 要处理的图片文件夹路径
var altasPath = "./released/resource/"
var folders = getFolders(altasPath);
folders.map(async function (folder) {
const files = await imagemin([altasPath + folder + '/*.{png,jpg}'], {
destination: altasPath + folder,
plugins: [
imageminJpegtran(),
imageminPngquant({
quality: [0.6, 0.8]
})
]
});
if (files && files.length) {
files.forEach((v) => {
console.log("压缩图片成功:", v.sourcePath.substring(v.sourcePath.lastIndexOf("/") + 1, v.sourcePath.length))
})
}
});
function getFolders(dir) {
return fs.readdirSync(dir)
.filter(function (file) {
return fs.statSync(path.join(dir, file)).isDirectory();
});
}
\ No newline at end of file
var fs = require("fs");
// fs.writeFileSync(
// "./released/output.js",
// fs.readFileSync("./output.js")
// )
var endPath = './released/';
fs.writeFileSync(endPath + "output.js",
// 'import * as FYGE from "fyge-tbmini";\n' +
'import * as FYGE from "fyge";\n' +//以后改成这个
// 'import * as SvgaParser from "svga-parser";\n' +
fs.readFileSync("./output.js"));
console.log("js生成")
var fs = require("fs");
var path = require('path');
var del = require('del');
var iconv = require('iconv-lite');
const join = require('path').join;
//写入图集的文件夹,将文件夹内所有的json合并,并删除原先json
var readPath = "./released/resource/";
//读取json文件
var data = iconv.decode(fs.readFileSync(readPath + "res.json"), "utf-8");//GBK
//反序列化
data = JSON.parse(data);
var files = fs.readdirSync(readPath);
// let obj = {};
let count = 0;
let countAll = files.length
files.forEach(function (file) {
//路径
let fPath = join(readPath, file);
//只处理文件夹
if (fs.statSync(fPath).isDirectory()) {
//读文件夹fPath里的json文件
fs.readdir(fPath, function (err, files) {
if (err) {
console.warn(err)
} else {
var hasJson
//遍历
for (var i = 0; i < files.length; i++) {
let filename = files[i];
if (filename.indexOf(".json") == -1) continue
hasJson = true;
//获取当前文件的绝对路径
let filedir = path.join(fPath, filename);
let content = fs.readFileSync(filedir, 'utf-8');
let group = getGroupByName(filename.replace(".json", ""), data.groups)
group.atlas = JSON.parse(content);
//删除原先json
del(filedir)
if (++count == countAll) endFun();
}
if(!hasJson)if (++count == countAll) endFun();
//序列化,不格式化,节省内存
}
})
} else {
if (++count == countAll) endFun();
}
})
function endFun() {
console.log("资源配置js生成完毕")
// del(join(readPath, "res.json"))
fs.writeFileSync(readPath + "res.json", JSON.stringify(data, "", "\t"));
}
function getGroupByName(name, groups) {
var group;
for (var i = 0; i < groups.length; i++) {
if (groups[i].name === name) {
group = groups[i];
break;
}
}
return group
}
This diff is collapsed.
This diff is collapsed.
var fs = require("fs");
var exec = require('child_process').exec;
var iconv = require('iconv-lite');
var del = require('del');
const join = require('path').join;
// var packTextures = require("pack_textures")
//写入图集的文件夹
var outPath = "./released/resource/";
//读取散图的文件夹
var readPath = "./released/tm/";
var files = fs.readdirSync(readPath);
files.forEach(function (file) {
//路径
let fPath = join(readPath, file);
//只处理文件夹
if (fs.statSync(fPath).isDirectory()) {
//判断文件夹内是否有图片
if (!judgeHasImage(fPath)) return;
//如果文件夹不存在
if (!fs.existsSync(outPath + file)) {
fs.mkdirSync(outPath + file);
}
else {
//图集文件存在就删除
if (fs.existsSync(outPath + file + "/" + file + ".json")) {
del(outPath + file + "/" + file + ".json")
}
if (fs.existsSync(outPath + file + "/" + file + ".png")) {
del(outPath + file + "/" + file + ".png")
}
}
// packTextures(
// fPath,
// outPath + file + "/" + file,
// 4096,
// 4096,
// false,
// 2,
// 2,
// true,
// true
// )
//全局命令装过,就直接用命令行
exec(
'packTextures' + //基础指令
' -i ' + fPath + //要合图集的文件夹路径
' -o ' + outPath + file + "/" + file + //输出路径及名字
' --mw ' + 4096 + //最大宽度
' --mh ' + 4096 +//最大高度
' -p ' + false + //长宽是否2的指数,canvas下没必要,false
' --sp ' + 2 + //图片间隔
' --bp ' + 2 + //边界间隔
' -r ' + true + //是否允许图片旋转
' -t ' + true //是否允许裁切图片边缘透明像素
, { encoding: 'utf8' }, (e) => {
if (e) {
console.log(e)
return
}
console.log("生成图集:" + file)
}
)
}
})
/**
* 判断文件夹内是否有图片
* @param {*} path
*/
function judgeHasImage(path) {
var files = fs.readdirSync(path);
for (var i = 0; i < files.length; i++) {
var itm = files[i]
var stat = fs.statSync(path + "/" + itm);
if (stat.isDirectory()) {
//递归读取文件
if (judgeHasImage(path + "/" + itm + "/")) return true;
} else {
if (itm.substr(-4) == ".jpg" || itm.substr(-4) == ".png") return true;
}
}
return false;
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
var fs = require('fs');
var path = require('path');
const co = require('co');
const OSS = require('ali-oss');
const chalk = require('chalk');
const ProgressBar = require('progress');
class TuiaAutoUpload {
constructor(props, type) {
this.type = type;
const defaultOptions = {
dir: undefined,
originDir: undefined
}
this.options = Object.assign({}, defaultOptions, props);
if (!this.options.dir || !this.options.originDir) {
console.log(chalk.red('缺少参数,初始化失败'))
return;
}
this.init();
}
init() {
var _this = this;
this.client = new OSS({
region: 'oss-cn-hangzhou',
accessKeyId: 'LTAI4Fw25WcfcGv7FvcHoiHK',
accessKeySecret: 'NZk1NtT9J5HFaAolNbtQdzTzLLvLYm',
bucket: _this.type === 'prod' ? 'duiba' : 'daily-duiba'
});
this.bar = new ProgressBar(chalk.yellow(` 文件上传中 [:bar] :current/${this.files().length} :percent :elapseds`), {
complete: '●',
incomplete: '○',
width: 20,
total: this.files().length,
callback: () => {
console.log(chalk.green('\n All complete.'));
console.log(chalk.blue(`\n 本次队列文件共${this.files().length}个,已存在文件${this.existFiles}个,上传文件${this.uploadFiles}个,上传失败文件${this.errorFiles}个\n`));
}
})
return this;
}
files() {
var _this = this;
if (this._files) return this._files;
this._files = [];
/**
* 文件遍历方法
* @param filePath 需要遍历的文件路径
*/
function fileDisplay(filePath) {
//根据文件路径读取文件,返回文件列表
var files = fs.readdirSync(filePath);
files.forEach(function (filename) {
//获取当前文件的绝对路径
var filedir = path.join(filePath, filename);
//根据文件路径获取文件信息,返回一个fs.Stats对象
var stats = fs.statSync(filedir);
var isFile = stats.isFile();//是文件
var isDir = stats.isDirectory();//是文件夹
if (isFile) {
var sep = '/';
if ('win32' == process.platform)
sep = '\\';
var newDirArr = filedir.split(sep);
newDirArr.shift();
_this._files.push(newDirArr.join('/'));
}
if (isDir) {
fileDisplay(filedir);//递归,如果是文件夹,就继续遍历该文件夹下面的文件
}
});
}
//调用文件遍历方法
fileDisplay(this.options.dir);
return this._files;
}
start() {
this.files().map((file, index) => {
let _this = this;
const path1 = path.join(path.resolve(__dirname, '..'), 'released', file);
let originFile;
this.existFiles = 0;
this.uploadFiles = 0;
this.errorFiles = 0;
co(function* () {
const originPath = `${_this.options.originDir}${file}`;
try {
originFile = yield _this.client.head(originPath);
} catch (error) {
originFile = error;
}
if (_this.type === 'prod') {
if (originFile.status === 404) {
yield _this.client.put(originPath, path1);
_this.uploadFiles += 1;
} else {
_this.existFiles += 1;
}
} else if (_this.type === 'dev') {
if (originFile.status === 404 || originFile.status === 200) {
_this.existFiles += 1;
}
yield _this.client.put(originPath, path1, {
headers: {
'Cache-Control': 'no-cache'
}
})
_this.uploadFiles += 1;
}
_this.bar.tick();
}).catch(function (err) {
_this.errorFiles += 1;
console.log(err);
});
});
}
}
const configFileName = 'project.json';
if (!fs.existsSync(configFileName)) {
throw new Error(`${configFileName}不存在.`)
}
let config = fs.readFileSync('project.json');
config = JSON.parse(config + '');
if (!config.type) {
throw new Error(`${configFileName}的type不存在.`)
}
if (!config.name) {
throw new Error(`${configFileName}的name不存在.`)
}
const now = new Date();
const version = Math.round(now.getTime() / 1000);
console.log(`版本号:
${version}`)
const autoupload = new TuiaAutoUpload({
dir: './released/',
// dir: path.join(__dirname, './released/'),
originDir: `/db_games/${config.type}/${config.name}/${version}/`
}, "prod")
autoupload.start()
var iconv = require('iconv-lite');
var readPath = "./released/resource/";
//读取json文件
var data = iconv.decode(fs.readFileSync(readPath + "res.json"), "utf-8");//GBK
//反序列化
data = JSON.parse(data);
data.path = `https://yun.duiba.com.cn/db_games/${config.type}/${config.name}/${version}/resource/`
//写入目标文件夹,可配置,每个项目必须修改,或者直接和project的保持一致(淘宝项目文件固定后)
var endPath = './src/';
var endFile = `export const ResJson = ${JSON.stringify(data, "", "\t")}`
fs.writeFileSync(endPath + "ResJson.ts", endFile);
//根据参数吧,有就是web。需要生成皮肤和js,没有就不执行后续
let arg = process.argv.splice(2);
if (!arg[0]) return;
//有版本号了,模板也生成吧
require("./createHtml")(`${config.type}/${config.name}/${version}`);
var uploadSingleJs = require("./uploadSingleJs")
var exec = require('child_process').exec;
//打包js
exec("webpack --config webpack.prod.js", { encoding: 'utf8' }, (e) => {
if (e) {
console.log(e)
return
}
uploadSingleJs(`${config.type}/${config.name}/${version}`)
//再打印一次
console.log(`版本号:
${version}`)
})
\ No newline at end of file
const co = require('co');
const OSS = require('ali-oss');
var fs = require('fs');
let arg = process.argv.splice(2);
//只打包js时,自执行上传
if(arg[0])uploadSingleJs();
function uploadSingleJs(url) {
if (!url) {//不传的时候
const configFileName = 'project.json';
if (!fs.existsSync(configFileName)) {
throw new Error(`${configFileName}不存在.`)
}
let config = fs.readFileSync('project.json');
config = JSON.parse(config + '');
if (!config.type) {
throw new Error(`${configFileName}的type不存在.`)
}
if (!config.name) {
throw new Error(`${configFileName}的name不存在.`)
}
const now = new Date();
const version = Math.round(now.getTime() / 1000);
console.log(`版本号:
${version}`)
url = `${config.type}/${config.name}/${version}`;
require("./createHtml")(`${config.type}/${config.name}/${version}`);
}
//单js文件上传
co(function* () {
const originPath = `/db_games/${url}/output.js`;
var client = new OSS({
region: 'oss-cn-hangzhou',
accessKeyId: 'LTAI4Fw25WcfcGv7FvcHoiHK',
accessKeySecret: 'NZk1NtT9J5HFaAolNbtQdzTzLLvLYm',
bucket: 'duiba'
})
var originFile;
try {
originFile = yield client.head(originPath);
} catch (error) {
originFile = error;
}
if (originFile.status === 404)
yield client.put(originPath, "./output.js");
})
}
module.exports = uploadSingleJs
\ No newline at end of file
var readline = require('readline');//node上有,不为了锁版本,可以不用安装
// warn("aaasd",()=>{console.log(213)},()=>{console.log(65)})
/**
* 提醒脚本
* @param {string} msg 提示信息
* @param {Function} resolve yes回调
* @param {Function} reject no回调
*/
function warn(msg, resolve, reject) {
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question(msg + "[y/n]", function (answer) {
switch (answer) {
case 'y':
case 'Y':
case 'yes':
case 'YES':
resolve && resolve();
// 不加close,则不会结束
rl.close();
break;
case 'n':
case 'N':
case 'no':
case 'NO':
default:
reject && reject();
rl.close();
break;
}
});
}
module.exports = warn
\ No newline at end of file
// import { Geometry } from "../Geometry";
// import { Vector2 } from "../math/Vector2";
// import { Vector3 } from "../math/Vector3";
export class CylinderGeometry extends FYGE.Geometry {
constructor(
/**
* 上圆半径,默认1
*/
radiusTop: number = 1,
/**
* 下圆半径,默认1
*/
radiusBottom: number = 1,
/**
* 高度,默认1
*/
height: number = 1,
/**
* 径向分段数,整数,默认8
*/
radialSegments: number = 8,
/**
* 高度分段数,整数,默认1
*/
heightSegments: number = 1,
/**
* 是否开口,默认false
*/
openEnded = false,
/**
* 圆柱开始角度,默认0
*/
thetaStart: number = 0,
/**
* 圆柱结束角度,默认Math.PI * 2
*/
thetaLength: number = Math.PI * 2
) {
//避免小数和0
radialSegments = Math.floor(radialSegments) || 8;
heightSegments = Math.floor(heightSegments) || 1;
var indices = [];
var vertices = [];
var normals = [];
var uvs = [];
var index = 0;
var indexArray = [];
var halfHeight = height / 2;
var groupStart = 0;
// generate geometry
generateTorso();
if (!openEnded) {
if (radiusTop > 0) generateCap(true);
if (radiusBottom > 0) generateCap(false);
}
// build geometry
// this.setIndex(indices);
// this.addAttribute('position', new Float32BufferAttribute(vertices, 3));
// this.addAttribute('normal', new Float32BufferAttribute(normals, 3));
// this.addAttribute('uv', new Float32BufferAttribute(uvs, 2));
function generateTorso() {
var x, y;
var normal = new FYGE.Vector3();
var vertex = new FYGE.Vector3();
var groupCount = 0;
// this will be used to calculate the normal
var slope = (radiusBottom - radiusTop) / height;
// generate vertices, normals and uvs
for (y = 0; y <= heightSegments; y++) {
var indexRow = [];
var v = y / heightSegments;
// calculate the radius of the current row
var radius = v * (radiusBottom - radiusTop) + radiusTop;
for (x = 0; x <= radialSegments; x++) {
var u = x / radialSegments;
var theta = u * thetaLength + thetaStart;
var sinTheta = Math.sin(theta);
var cosTheta = Math.cos(theta);
// vertex
vertex.x = radius * sinTheta;
vertex.y = - v * height + halfHeight;
vertex.z = radius * cosTheta;
vertices.push(vertex.x, vertex.y, vertex.z);
// normal
normal.set(sinTheta, slope, cosTheta).normalize();
normals.push(normal.x, normal.y, normal.z);
// uv
// uvs.push(u, 1 - v);
uvs.push(u, v);
// save index of vertex in respective row
indexRow.push(index++);
}
// now save vertices of the row in our index array
indexArray.push(indexRow);
}
// generate indices
for (x = 0; x < radialSegments; x++) {
for (y = 0; y < heightSegments; y++) {
// we use the index array to access the correct indices
var a = indexArray[y][x];
var b = indexArray[y + 1][x];
var c = indexArray[y + 1][x + 1];
var d = indexArray[y][x + 1];
// faces
indices.push(a, b, d);
indices.push(b, c, d);
// update group counter
groupCount += 6;
}
}
// add a group to the geometry. this will ensure multi material support
//以后考虑每个面能各自改变
// scope.addGroup(groupStart, groupCount, 0);
// calculate new start value for groups
groupStart += groupCount;
}
function generateCap(top) {
var x, centerIndexStart, centerIndexEnd;
var uv = new FYGE.Vector2();
var vertex = new FYGE.Vector3();
var groupCount = 0;
var radius = (top === true) ? radiusTop : radiusBottom;
var sign = (top === true) ? 1 : - 1;
// save the index of the first center vertex
centerIndexStart = index;
// first we generate the center vertex data of the cap.
// because the geometry needs one set of uvs per face,
// we must generate a center vertex per face/segment
for (x = 1; x <= radialSegments; x++) {
// vertex
vertices.push(0, halfHeight * sign, 0);
// normal
normals.push(0, sign, 0);
// uv
uvs.push(0.5, 0.5);
// increase index
index++;
}
// save the index of the last center vertex
centerIndexEnd = index;
// now we generate the surrounding vertices, normals and uvs
for (x = 0; x <= radialSegments; x++) {
var u = x / radialSegments;
var theta = u * thetaLength + thetaStart;
var cosTheta = Math.cos(theta);
var sinTheta = Math.sin(theta);
// vertex
vertex.x = radius * sinTheta;
vertex.y = halfHeight * sign;
vertex.z = radius * cosTheta;
vertices.push(vertex.x, vertex.y, vertex.z);
// normal
normals.push(0, sign, 0);
// uv
uv.x = (cosTheta * 0.5) + 0.5;
uv.y = (sinTheta * 0.5 * sign) + 0.5;
uvs.push(uv.x, uv.y);
// increase index
index++;
}
// generate indices
for (x = 0; x < radialSegments; x++) {
var c = centerIndexStart + x;
var i = centerIndexEnd + x;
if (top === true) {
// face top
indices.push(i, i + 1, c);
} else {
// face bottom
indices.push(i + 1, i, c);
}
groupCount += 3;
}
// add a group to the geometry. this will ensure multi material support
// scope.addGroup(groupStart, groupCount, top === true ? 1 : 2);
// calculate new start value for groups
groupStart += groupCount;
}
super(vertices, indices, normals, null, uvs)
}
}
\ No newline at end of file
/**
* Created by _xdq on 2021/04/07.
* 公共方法
* @export
* @class GUtils
*/
export class GUtils {
/** 随机数 */
static getRandom(max: number, min: number): number {
return Number((Math.random() * (max - min) + min).toFixed(1));
}
/** 获取角度 */
static getAngle(dy: number, dx: number): number {
const angle = Math.atan2(dy, dx) / Math.PI * 180;
return (angle + 360) % 360;
}
/** 判断整数 */
static isInteger(obj: any) {
return typeof obj === 'number' && obj%1 === 0;
}
}
\ No newline at end of file
/** 资源配置 */
export const RES = {
target1: "//yun.duiba.com.cn/spark/assets/9aa5d0732bea222d58347bf435e7f67a851b9fc1.png",
target2: "//yun.duiba.com.cn/spark/assets/3e617cb1f2816a60acb08876ccfc7798c4425c96.png",
target3: "//yun.duiba.com.cn/spark/assets/1a20adb084e2acc96400a35f8cff1b07b7453947.png",
target4: "//yun.duiba.com.cn/spark/assets/615cd7b09e08cb5321cfde3bafbba21d07860cfc.png",
target5: "//yun.duiba.com.cn/spark/assets/c606874dfdf821ebff91c00a7812e85df2430806.png",
target6: "//yun.duiba.com.cn/spark/assets/a0d2f0ba64dd019849b75614ea381a716e8c3164.png",
particle1: "//yun.duiba.com.cn/spark/assets/b6810b80eebc63bb1c8cc23cc3741842e35ec8a9.png",
particle2: "//yun.duiba.com.cn/spark/assets/bce75bf3b7af0d3337a56ded85fd3eb6f86153e9.png"
}
/** 靶子配置 */
export const TARGET_CFG = {
target1: {
width: 2.2,
height: 2.2,
position: new FYGE.Vector3(-100, 0, 1),
},
target2: {
width: 2.2,
height: 2.2,
position: new FYGE.Vector3(-100, 0, 1),
},
target3: {
width: 2.2,
height: 2.2,
position: new FYGE.Vector3(-100, 0, 1),
},
target4: {
width: 2.2,
height: 2.2,
position: new FYGE.Vector3(-100, 0, 1),
},
target5: {
width: 1.8,
height: 3.6,
position: new FYGE.Vector3(-100, 3, 1),
},
target6: {
width: 2,
height: 6,
position: new FYGE.Vector3(-100, 0, 0.5),
}
}
/** 墙体色彩设置 */
export const LEVEL_COLOR = {
level1: {
mapTop: 0x8602cf,
mapBottom: 0x5c1ab2,
fog: 0x501481
},
level2: {
mapTop: 0x15b345,
mapBottom: 0x04ce60,
fog: 0x26532e
},
level3: {
mapTop: 0xa00318,
mapBottom: 0xf6009d,
fog: 0x321b1c
},
level4: {
mapTop: 0xac5b19,
mapBottom: 0xcd7f03,
fog: 0x78490f
},
level5: {
mapTop: 0x0564ff,
mapBottom: 0x2196f3,
fog: 0x0d0d3d
}
}
/**
* Created by _xdq on 2021/04/07.
* 静态方法
* @export
* @class GameCfg
*/
export class GameCfg {
private static _instance: GameCfg;
public static get Ins(): GameCfg {
if (!this._instance)
this._instance = new GameCfg();
return this._instance;
}
/**
* 获得texture纹理
* @param {string} url
* @memberof GameCfg
*/
createTexture(url: string) {
let _texture: FYGE.Texture = url ? FYGE.Texture.fromUrl(url) : null;
_texture.baseTexture.premultipliedAlpha = false;
return _texture;
}
}
\ No newline at end of file
export default class GamePool {
private static _instance: GamePool;
public static get Ins(): GamePool {
if (!this._instance)
this._instance = new GamePool();
return this._instance;
}
private MAX: number = 50;
private hashPools: { [key: string]: any[] } = {};
private initFuns: { [key: string]: () => void } = {};
private createFuns: { [key: string]: () => void } = {};
/**
* 注册对象池
* @param {string} name
* @param {() => void} createFun
* @param {() => void} [initFun]
* @memberof GamePool
*/
registerPool(name: string, createFun: () => void, initFun?: () => void) {
this.createFuns[name] = createFun;
this.initFuns[name] = initFun;
this.hashPools[name] = [];
}
/**
* 获取对象
* @static
* @param {string} name
* @param {*} cls
* @return {*}
* @memberof GamePool
*/
getObjFromPool(name: string,...params: any[]): any {
// var params = [];
// for (var _i = 1; _i < arguments.length; _i++) {
// params[_i - 1] = arguments[_i];
// }
var pool = this.hashPools[name];
if (!pool) {
console.warn(name + "没有注册在对象池中。");
return null;
}
var obj;
if (pool.length > 0) {
obj = pool.pop();
}
else {
var createMethod = this.createFuns[name];
obj = createMethod.apply(null, params);
}
var initFun = this.initFuns[name];
if (initFun) {
params.unshift(obj);
initFun.apply(null, params);
}
return obj;
}
/**
* 回收对象
* @param sign
* @param item
*/
recoverObj(name: string, obj: any) {
if (!obj) {
return;
}
var pool = this.hashPools[name];
if (!pool) {
console.warn(name + "没有注册在对象池中。");
return;
}
if (pool.indexOf(obj) < 0 && pool.length <= this.MAX) {
pool.push(obj);
}
}
}
\ No newline at end of file
This diff is collapsed.
import { CylinderGeometry } from "../CylinderGeometry";
/**
* Created by _xdq on 2021/04/13.
* 链接线
* @export
* @class PlayerSphere
*/
export class Line3DModule extends FYGE.Object3D {
private mesh3D: FYGE.Mesh3D;
private _line: CylinderGeometry;
constructor() {
super();
this._line = new CylinderGeometry(0.05, 0.05, 3.5);
var lineMaterial = new FYGE.BaseMaterial({
color: 0xfffce5
});
this.mesh3D = this.addChild(new FYGE.Mesh3D(this._line, lineMaterial));
this.mesh3D.position.y = -3.5 / 2;
this.position.set(20, 4.5, 1);
}
/**
* 重置
* @param {number} h
* @memberof Line3DModule
*/
onChangeLineHeight(h: number) {
if (this.mesh3D) {
this.removeChild(this.mesh3D);
this.mesh3D = null;
}
this._line = new CylinderGeometry(0.05, 0.05, h);
var lineMaterial = new FYGE.BaseMaterial({
color: 0xffffff
});
this.mesh3D = this.addChild(new FYGE.Mesh3D(this._line, lineMaterial));
this.mesh3D.position.y = -h / 2;
}
}
\ No newline at end of file
/**
* Created by _xdq on 2021/04/07.
* 材质管理
* @export
* @class MaterialMgr
*/
import { GameCfg } from "./GameMgr";
import { RES } from './GameCfg';
export class MaterialMgr {
private static _instance: MaterialMgr;
public static get Ins(): MaterialMgr {
if (!this._instance) {
this._instance = new MaterialMgr();
}
return this._instance;
}
public source: any;
constructor() {
var block1Material = {
color: 0x8602cf
} as FYGE.BaseMaterialParamsInt;
var block2Material = {
color: 0x5c1ab2
} as FYGE.BaseMaterialParamsInt;
var block3Material = {
color: 0x49165d
} as FYGE.BaseMaterialParamsInt;
var target1Material = {
map: GameCfg.Ins.createTexture(RES["target1"])
} as FYGE.BaseMaterialParamsInt;
var target2Material = {
map: GameCfg.Ins.createTexture(RES["target2"])
} as FYGE.BaseMaterialParamsInt;
var target3Material = {
map: GameCfg.Ins.createTexture(RES["target3"])
} as FYGE.BaseMaterialParamsInt;
var target4Material = {
map: GameCfg.Ins.createTexture(RES["target4"])
} as FYGE.BaseMaterialParamsInt;
var target5Material = {
map: GameCfg.Ins.createTexture(RES["target6"])
} as FYGE.BaseMaterialParamsInt;
var target6Material = {
map: GameCfg.Ins.createTexture(RES["target5"])
} as FYGE.BaseMaterialParamsInt;
var particle1Matial = {
map: GameCfg.Ins.createTexture(RES["particle1"]),
alpha: 1
} as FYGE.BaseMaterialParamsInt;
var particle2Matial = {
alpha: 0.5,
map: GameCfg.Ins.createTexture(RES["particle2"])
} as FYGE.BaseMaterialParamsInt;
this.source = {
block1Material,
block2Material,
block3Material,
target1Material,
target2Material,
target3Material,
target4Material,
target5Material,
target6Material,
particle1Matial,
particle2Matial
};
}
}
\ No newline at end of file
This diff is collapsed.
import { Rect3DBoxOption } from './types';
import { ParticleSystem } from "./ParticleSystem";
/**
* Created by _xdq on 2021/04/07.
* 发光球体
* @export
* @class PlayerSphere
*/
export class PlayerSphere extends FYGE.Object3D {
private mesh3D: FYGE.Mesh3D;
private _r: number;
/** 粒子 */
private particleSystem: ParticleSystem<Rect3DBoxOption>;
get radius(): number {
return this._r;
}
set radius(v: number) {
this._r = v;
}
constructor(r: number = 0.3) {
super();
var sphereBall = new FYGE.SphereGeometry(r, 50, 50);
this.radius = r;
var ballMaterial = new FYGE.BaseMaterial({
color: 0xfffce5
});
this.mesh3D = this.addChild(new FYGE.Mesh3D(sphereBall, ballMaterial));
this.position.set(20, 0, 1);
/** 添加点光 */
this.addChild(new FYGE.PointLight(0xffffff, 1)).position.set(0, 0, 0);
// /** 粒子 */
// let _p = this.addChild(new ParticleSystem());
// _p.position.set(0.2, -0.25, 0);
// this.particleSystem = _p;
}
onReduce() {
// this.particleSystem.onLunchParticles();
}
}
\ No newline at end of file
This diff is collapsed.
/**
* Created by _xdq on 2021/04/07.
* 创建天空盒
* @export
* @class SkyUtil
*/
export class SkyUtil {
static _NAME = "skybox";
static createSkyBox(){
var skyBoxGeometry = new FYGE.BoxGeometry(5000,5000,5000);
var skyBaseMaterial = new FYGE.BaseMaterial({
color: 0xdf74f4,
side: FYGE.RenderSideType.BackSide
});
var skybox = new FYGE.Mesh3D(skyBoxGeometry,skyBaseMaterial);
return skybox;
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
export const ResJson = {
"groups": [
{
"keys": "comCloseBtn.png,toastBg.png,waitingBg.png,waitingRot.png",
"name": "common",
"atlas": "common.json"
}
],
"path": "https://yun.duiba.com.cn/db_games/activity/template/1618970024/resource/"
}
\ No newline at end of file
This diff is collapsed.
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": true,
"removeComments": true,
"noEmitOnError":true,
"outDir":"dist",
/*"outFile": "./index.js",*/
"lib": [
"es5",
"dom",
"es2015.promise"
]
},
"exclude": [
"node_modules"
]
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment