Commit bf370dff authored by 张超's avatar 张超 🎱

1st

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
<!--
* @Author: super
* @Date: 2021-05-19 10:24:09
* @LastEditTime: 2021-05-25 15:04:32
* @LastEditors: super
* @Description:
-->
<!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: #501481;
/* 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);
if (!/(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent)) {
canvas.addEventListener("mousedown", mouseEvent, false);
canvas.addEventListener("mousemove", mouseEvent, false);
canvas.addEventListener("mouseup", mouseEvent, false);
} else {
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>
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
{}
\ No newline at end of file
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
/*
* @Author: super
* @Date: 2021-05-20 14:32:12
* @LastEditTime: 2021-05-27 11:52:08
* @LastEditors: super
* @Description:
*/
/** 游戏配置 */
export namespace Config {
/** 设计稿尺寸、 */
export const PSD_SIZE = [750, 1624];
/** 红,绿,蓝,分,黄,灰、 */
export const GRID_COLORS = [0xe23e29, 0xbccc45, 0x54b5be, 0xeb90f9, 0xfad06c, 0x888888];
/** 6个按钮的做坐标 */
export const BTN_POS = [];
/** 格子的尺寸 */
export const GRID_SIZE = 40;
/** 格子的数量 */
export const GRID_COUNT = 10;
/** 最大可玩次数 */
export const MAX_MOVES = 2;
}
/*
* @Author: super
* @Date: 2021-05-19 15:57:24
* @LastEditTime: 2021-05-27 14:36:27
* @LastEditors: super
* @Description:
*/
import { Grid } from "./components/Grid";
import { Config } from "./GameCfg";
/** 颜色类型 */
export type Color = string;
export class GameScene extends FYGE.Container {
private moves: number = 0;
private btns: FYGE.Graphics[] = [];
private grids: Grid[][] = [];
private gameContainer: FYGE.Container;
private matched: Grid[] = [];
constructor() {
super();
this.initUi();
}
initUi() {
this.initBtns();
this.createMap();
}
/**
* @description: 初始化6个按钮
*/
initBtns() {
this.btns = [];
for (let i = 0; i < Config.GRID_COLORS.length; i++) {
let sx = 0;
let sy = 110 * i + 50;
let color = Config.GRID_COLORS[i];
let _rect = this.addChild(new FYGE.Graphics()).lineStyle(0.5, 0xffffff, 1).beginFill(color, 1).drawRect(sx, sy, 100, 100).endFill();
_rect.name = String(color);
_rect.addEventListener(FYGE.MouseEvent.CLICK, () => this.handleBtnClick(String(color)), this);
this.btns[i] = _rect;
}
}
/**
* @description: 点击按钮
* @param {*} color
*/
handleBtnClick(btnColor: Color) {
// TODO: 第二次点击不变了
console.log("dd", btnColor);
let oldColor = this.grids[0][0].oldColor;
console.log(oldColor);
this.moves++;
this.matched = [];
this.doMatch(oldColor, btnColor, 0, 0);
if (this.matched.length > 0) this.doChangeColor();
}
/**
* @description: 匹配色块
* @param {Color} oldColor
* @param {Color} newColor
* @param {number} x
* @param {number} y
* @return {*}
*/
doMatch(oldColor: Color, newColor: Color, x: number, y: number) {
if (oldColor === newColor || this.grids[x][y].newColor !== oldColor) {
return;
}
this.grids[x][y].newColor = newColor;
if (this.matched.indexOf(this.grids[x][y]) === -1) {
this.matched.push(this.grids[x][y]);
}
// 上下左右搂一圈
if (x > 0) {
this.doMatch(oldColor, newColor, x - 1, y);
}
if (x < Config.GRID_COUNT - 1) {
this.doMatch(oldColor, newColor, x + 1, y);
}
if (y > 0) {
this.doMatch(oldColor, newColor, x, y - 1);
}
if (y < Config.GRID_COUNT - 1) {
this.doMatch(oldColor, newColor, x, y + 1);
}
}
/**
* @description: 开始更新格子
* @param {*}
* @return {*}
*/
doChangeColor() {
console.log("doChangeColor");
this.matched.map((item) => {
item
.clear()
.beginFill(+item.newColor, 1)
.drawRect(0, 0, Config.GRID_SIZE, Config.GRID_SIZE)
.endFill();
item.oldColor = item.newColor;
});
if (this.checkWin()) {
console.log("你赢了");
} else if (this.moves >= Config.MAX_MOVES) {
console.log("你输了");
}
}
checkWin() {
let startColor = this.grids[0][0].newColor;
for (var x = 0; x < Config.GRID_COUNT; x++) {
for (var y = 0; y < Config.GRID_COUNT; y++) {
if (this.grids[x][y].newColor !== startColor) {
return false;
}
}
}
return true;
}
/**
* @description: 创建格子地图
*/
createMap() {
this.grids = [];
this.gameContainer = new FYGE.Container();
this.addChild(this.gameContainer);
let gSize = Config.GRID_SIZE;
// 起始X
let startX = (Config.PSD_SIZE[0] - gSize * Config.GRID_COUNT) / 2;
for (var x = 0; x < Config.GRID_COUNT; x++) {
this.grids[x] = [];
for (var y = 0; y < Config.GRID_COUNT; y++) {
let sx = startX + x * gSize;
let sy = 66 + y * gSize;
// 随机颜色
let _index = Math.floor(Math.random() * 6);
let _rect = this.gameContainer.addChild(new Grid());
_rect.lineStyle(1, 0xffffff, 1).beginFill(Config.GRID_COLORS[_index], 1).drawRect(0, 0, gSize, gSize).endFill();
_rect.position.x = sx;
_rect.position.y = sy;
let color = String(Config.GRID_COLORS[_index]);
_rect.oldColor = color;
_rect.newColor = color;
this.grids[x][y] = _rect;
}
}
}
}
import { Config } from "./GameCfg";
import { GameScene } from "./GameScene";
/**
* 全局事件,为了和小程序交互
* 有可能多处页面用到,所以单开
*/
export const GDispatcher = new FYGE.EventDispatcher();
export class Main {
//主舞台
stage: FYGE.Stage;
private requestID;
private _pause: boolean;
private canvas: HTMLCanvasElement;
constructor(canvas: HTMLCanvasElement) {
var sysInfo;
//淘宝小程序环境就用canvas初始化
if (!window) {
//自行处理吧,这么判断也不保险,万一淘宝小程序加进了window
FYGE.initedByCanvas(canvas); //里面会设置env为tb,这个很重要
//@ts-ignore 存在my就初始化
sysInfo = my.getSystemInfoSync();
}
//建舞台
var stage = new FYGE.Stage(
canvas,
Config.PSD_SIZE[0], //设计宽度,按设计搞给的就行
Config.PSD_SIZE[1], //设计高度
(sysInfo && sysInfo.windowWidth) || document.body.clientWidth,
(sysInfo && sysInfo.windowHeight) || document.body.clientHeight,
FYGE.RENDERER_TYPE.WEBGL,
false //视窗居中裁切
);
this.stage = stage;
this.canvas = canvas; //赋值下,为了下面的destroy的cancelAnimationFrame
//stage初始化
stage.addEventListener(FYGE.Event.INIT_STAGE, this.onAddToStage, this);
//循环
var self = this;
loop();
function loop() {
if (!self._pause) {
// stats.begin();
FYGE.Tween.flush();
stage.flush();
// stats.end();
}
//@ts-ignore
//为了兼容多page的canvas
FYGE.getEnv() == "tb" ? (self.requestID = canvas.requestAnimationFrame(loop)) : (self.requestID = window.requestAnimationFrame(loop));
}
}
private async onAddToStage() {
//@ts-ignore
const scene: GameScene = this.stage.addChild(new GameScene());
}
/**
* 添加全局事件,用于小程序的交互调用
* 一直很犹豫要不要放在main的实例里,还是和Main同级导出,还有上面的pause,run,下面的事件等
* @param name
* @param fun
* @param thisObj
*/
addGlobalEvent(name: string, fun: Function, thisObj?: any, once: boolean = false) {
if (once) {
GDispatcher.once(name, fun, thisObj);
} else {
GDispatcher.addEventListener(name, fun, thisObj);
}
}
/**
* 派发全局事件,用于小程序的交互调用
* @param name 可以是事件名,也可以是事件
* @param data
*/
dispatchGlobalEvent(name: string | any, data?: any) {
GDispatcher.dispatchEvent(name, data);
}
/**
* 移除全局事件,用于小程序交互调用
* @param name
* @param fun
* @param thisObj
*/
removeGlobalEvent(name: string, fun: Function, thisObj?: any) {
GDispatcher.removeEventListener(name, fun, thisObj);
}
destroy() {
//Tween都移除,注意吧,可能原先的也被移除,,对于多page时注意,会把其他页面的也去掉
FYGE.Tween.removeAllTweens();
//停掉计时器
//@ts-ignore 为了兼容多page的canvas
FYGE.getEnv() == "tb" ? this.canvas.cancelAnimationFrame(this.requestID) : window.cancelAnimationFrame(this.requestID);
//舞台销毁
this.stage.destroy();
//全局事件置空
GDispatcher.removeAllEventListener();
}
}
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
/*
* @Author: super
* @Date: 2021-05-25 20:24:10
* @LastEditTime: 2021-05-26 20:30:12
* @LastEditors: super
* @Description:
*/
import { Color } from "../GameScene";
export class Grid extends FYGE.Graphics {
private _oldColor: Color;
private _newColor?: Color;
set oldColor(color: Color) {
this._oldColor = color;
}
/** 旧颜色 */
get oldColor(): Color {
return this._oldColor;
}
set newColor(color: Color) {
this._newColor = color;
}
/** 新颜色 */
get newColor(): Color {
return this._newColor;
}
}
/*
* @Author: super
* @Date: 2021-05-20 16:57:00
* @LastEditTime: 2021-05-20 18:01:01
* @LastEditors: super
* @Description:
*/
export class Icons extends FYGE.Container{
}
\ No newline at end of file
<script type="module">
import * as THREE from '//techbrood.com/threejs/build/three.module.js';
import {OrbitControls} from '//techbrood.com/threejs/examples/jsm/controls/OrbitControls.js';
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});
renderer.autoClearColor = false;
const fov = 75;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 100;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 3;
const controls = new OrbitControls(camera, canvas);
controls.target.set(0, 0, 0);
controls.update();
const scene = new THREE.Scene();
{
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(-1, 2, 4);
scene.add(light);
}
const boxWidth = 1;
const boxHeight = 1;
const boxDepth = 1;
const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
function makeInstance(geometry, color, x) {
const material = new THREE.MeshPhongMaterial({color});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
cube.position.x = x;
return cube;
}
const cubes = [
makeInstance(geometry, 0x44aa88, 0),
makeInstance(geometry, 0x8844aa, -2),
makeInstance(geometry, 0xaa8844, 2),
];
{
const loader = new THREE.CubeTextureLoader();
const texture = loader.load([
'/uploads/1911/pos-x.jpg',
'/uploads/1911/neg-x.jpg',
'/uploads/1911/pos-y.jpg',
'/uploads/1911/neg-y.jpg',
'/uploads/1911/pos-z.jpg',
'/uploads/1911/neg-z.jpg',
]);
scene.background = texture;
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render(time) {
time *= 0.001;
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
cubes.forEach((cube, ndx) => {
const speed = 1 + ndx * .1;
const rot = time * speed;
cube.rotation.x = rot;
cube.rotation.y = rot;
});
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
</script>
\ No newline at end of file
{
"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
const path = require('path');
module.exports = {
entry: './src/Main.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
output: {
filename: 'output.js',
path: __dirname,
libraryTarget: 'umd',
}
};
\ No newline at end of file
/*
* @Author: super
* @Date: 2021-05-19 10:24:09
* @LastEditTime: 2021-05-24 15:22:20
* @LastEditors: super
* @Description:
*/
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const webpack = require('webpack');
const MockWebpackPlugin = require('mock-webpack-plugin');
module.exports = merge(common, {
mode: "development",
devtool: 'eval-source-map',
devServer: {
contentBase: '.',
hot:true,
proxy: {
'/plugin/*':'http://localhost:3000',
'/ngapi/*': 'http://localhost:3000',
'/ngame/*': 'http://localhost:3000',
'/hdtool/*': 'http://localhost:3000',
}
},
plugins: [
new MockWebpackPlugin({
config: {},
port: 3000
})
]
});
\ No newline at end of file
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const webpack = require('webpack');
module.exports = merge(common, {
mode: "production",//production development
devtool: 'source-map',
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
]
});
\ No newline at end of file
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