diff --git a/.gitignore b/.gitignore index f6ccf4a..2a748d9 100755 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,5 @@ quick_gen_project_*_autogen.sh.meta .vscode/ packages/pngquant/ + +LocalStorage/ diff --git a/assets/Scene/Home/BackHomeBtn.ts b/assets/Scene/Home/BackHomeBtn.ts index 7ec30c7..866b2d7 100644 --- a/assets/Scene/Home/BackHomeBtn.ts +++ b/assets/Scene/Home/BackHomeBtn.ts @@ -8,6 +8,7 @@ export default class BackHomeBtn extends cc.Component { cc.game.addPersistRootNode(this.node); BackHomeBtn.instance = this; this.toggleActive(false); + cc.director.on('setBackBtnVisibility', this.toggleActive.bind(this)); } toggleActive(flag: boolean) { diff --git a/assets/Scene/Home/Home.fire b/assets/Scene/Home/Home.fire index d76ca8d..a3709fd 100755 --- a/assets/Scene/Home/Home.fire +++ b/assets/Scene/Home/Home.fire @@ -18,6 +18,9 @@ }, { "__id__": 48 + }, + { + "__id__": 54 } ], "_active": true, @@ -189,7 +192,7 @@ "array": [ 0, 0, - 452.93128617926146, + 769.0305585605815, 0, 0, 0, @@ -1210,8 +1213,8 @@ }, "_contentSize": { "__type__": "cc.Size", - "width": 168, - "height": 90.4 + "width": 335.99, + "height": 63.28 }, "_anchorPoint": { "__type__": "cc.Vec2", @@ -1222,8 +1225,8 @@ "__type__": "TypedArray", "ctor": "Float64Array", "array": [ - -462.767, - -88.825, + -466.456, + -85.319, 0, 0, 0, @@ -1261,10 +1264,10 @@ } ], "_useOriginalSize": false, - "_string": "我是 异名\n用代码实现想法", - "_N$string": "我是 异名\n用代码实现想法", - "_fontSize": 24, - "_lineHeight": 40, + "_string": "写作对我来说是一种特殊的行动\n是对”我“的存在的理解,消化和修正的过程", + "_N$string": "写作对我来说是一种特殊的行动\n是对”我“的存在的理解,消化和修正的过程", + "_fontSize": 18, + "_lineHeight": 28, "_enableWrapText": true, "_N$file": null, "_isSystemFontUsed": true, @@ -1294,8 +1297,8 @@ "_right": 0, "_top": 0, "_bottom": 0, - "_verticalCenter": -88.825, - "_horizontalCenter": -462.767, + "_verticalCenter": -85.319, + "_horizontalCenter": -466.456, "_isAbsLeft": true, "_isAbsRight": true, "_isAbsTop": true, @@ -1998,7 +2001,7 @@ }, { "__type__": "cc.Node", - "_name": "back_home_btn", + "_name": "BackHomeBtnFreeze", "_objFlags": 0, "_parent": { "__id__": 1 @@ -2219,5 +2222,83 @@ }, "_enabled": true, "_id": "f1IGHg+lpP16AlzNEKM60q" + }, + { + "__type__": "cc.Node", + "_name": "SceneTransition", + "_objFlags": 0, + "_parent": { + "__id__": 1 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 55 + } + ], + "_prefab": null, + "_opacity": 255, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 0, + "height": 0 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_trs": { + "__type__": "TypedArray", + "ctor": "Float64Array", + "array": [ + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1 + ] + }, + "_eulerAngles": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_skewX": 0, + "_skewY": 0, + "_is3DNode": false, + "_groupIndex": 0, + "groupIndex": 0, + "_id": "eeaY/+TfZLz4P/SykmO5T3" + }, + { + "__type__": "1cd9dHF3nRI24w/zAzyk3Q3", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 54 + }, + "_enabled": true, + "time": 0, + "materials": [ + { + "__uuid__": "a869ac13-ffed-4334-b5df-1251273f2b07" + } + ], + "_id": "606YRpjk1JGqOLoeXBmJQ3" } ] \ No newline at end of file diff --git a/assets/Scene/Home/Home.ts b/assets/Scene/Home/Home.ts index eee2bb8..88d862c 100644 --- a/assets/Scene/Home/Home.ts +++ b/assets/Scene/Home/Home.ts @@ -2,25 +2,26 @@ import BackHomeBtn from './BackHomeBtn'; const { ccclass, property } = cc._decorator; const LOAD_SCENE_MIN_SEC: number = 1.2; enum sceneList { - 'Water_spread' = '水波扩散效果(shader)', - 'Specular_gloss' = '镜面光泽效果(shader)', - 'Dissolve_color' = '溶解效果(shader)', - 'Follow_spot' = '追光效果(shader)', - 'Metaball' = '融球效果(shader)', - 'Circle_avatar' = '圆形头像(shader)', - 'Scratch_ticket' = '刮刮卡实现', - 'Coin_fly_to_wallet' = '金币落袋效果', - 'Moving_ghost' = '移动残影效果', 'Magnifying_mirror' = '放大镜效果', + 'Scratch_ticket' = '刮刮卡实现', + 'Moving_ghost' = '移动残影效果', + 'Water_spread' = '水波扩散效果(shader)', + 'Follow_spot' = '追光效果(shader)', + 'Mosaic' = '马赛克/像素风(shader)', + 'Dissolve_color' = '溶解效果(shader)', 'Typer' = '打字机效果', + 'Specular_gloss' = '镜面光泽效果(shader)', + 'Metaball' = '融球效果(shader)', 'Bullet_Tracking' = '子弹跟踪效果', + 'SwitchScene__SquaresWire' = '场景切换(Squares Wire)', + 'Circle_avatar' = '圆形头像(shader)', + 'Coin_fly_to_wallet' = '金币落袋效果', 'Infinite_bg_scroll' = '背景无限滚动', 'Change_clothes' = '换装', 'Screen_vibrating' = '震屏效果+动画恢复第一帧', 'Joystick' = '遥控杆', 'Filter' = '颜色滤镜', - 'Mosaic' = '马赛克/像素风(shader)', - 'Photo_gallery' = '渐变过渡的相册(shader)' + 'Photo_gallery' = '渐变过渡的相册(shader)', } @ccclass @@ -68,10 +69,7 @@ export default class Home extends cc.Component { scrollItem.on( cc.Node.EventType.TOUCH_END, () => { - cc.tween(scrollItem) - .to(0.1, { scale: 1.05 }) - .to(0.1, { scale: 1 }) - .start(); + cc.tween(scrollItem).to(0.1, { scale: 1.05 }).to(0.1, { scale: 1 }).start(); this.loadScene(key); }, this diff --git a/assets/Scene/Home/Transition.ts b/assets/Scene/Home/Transition.ts new file mode 100644 index 0000000..dd4c9a6 --- /dev/null +++ b/assets/Scene/Home/Transition.ts @@ -0,0 +1,180 @@ +const { ccclass, property } = cc._decorator; + +const TRANSITION_TIME = 2; + +@ccclass +export default class Transition extends cc.Component { + @property() time: number = 0; + @property(cc.Material) materials = []; + + private _inited = false; + private _texture1: cc.Texture2D; + private _texture2: cc.Texture2D; + private _sprite: cc.Sprite; + private _spriteNode: cc.Node; + private _camera: cc.Camera; + private _cameraNode: cc.Node; + private _spriteMaterial: cc.Material; + private _onLoadFinished = () => {}; + + loading = false; + + private materialIndex = 0; + + onLoad() { + cc.game.addPersistRootNode(this.node); + } + + start() { + this.init(); + cc.director.on(cc.Director.EVENT_AFTER_SCENE_LAUNCH, this._onLoadFinished, this); + cc.director.on('switchSceneByTransition', this.switchSceneByTransition.bind(this)); + } + + switchSceneByTransition() { + this.materialIndex = this.materialIndex + 1 > this.materials.length ? 0 : this.materialIndex + 1; + this.loadScene('Scene/Home/Home', 'Canvas/Main Camera', 'Canvas/Main Camera'); + } + + init() { + if (this._inited) return; + this._inited = true; + + this.time = 0; + + this._texture1 = this.createTexture(); + this._texture2 = this.createTexture(); + + let spriteNode = cc.find('TRANSITION_SPRITE', this.node); + if (!spriteNode) { + spriteNode = new cc.Node('TRANSITION_SPRITE'); + this._sprite = spriteNode.addComponent(cc.Sprite); + spriteNode.parent = this.node; + } else { + this._sprite = spriteNode.getComponent(cc.Sprite); + } + let spriteFrame = new cc.SpriteFrame(); + spriteFrame.setTexture(this._texture1); + this._sprite.spriteFrame = spriteFrame; + + spriteNode.active = false; + spriteNode.scaleY = -1; + this._spriteNode = spriteNode; + + let cameraNode = cc.find('TRANSITION_CAMERA', this.node); + if (!cameraNode) { + cameraNode = new cc.Node('TRANSITION_CAMERA'); + this._camera = cameraNode.addComponent(cc.Camera); + cameraNode.parent = this.node; + } else { + this._camera = cameraNode.getComponent(cc.Camera); + } + cameraNode.active = false; + this._cameraNode = cameraNode; + + // @ts-ignore + this.node.groupIndex = cc.Node.BuiltinGroupIndex.DEBUG - 1; + this._camera.cullingMask = 1 << this.node.groupIndex; + + this.updateSpriteMaterial(); + } + + updateSpriteMaterial() { + if (!this._sprite) return; + + let newMaterial = cc.MaterialVariant.create(this.materials[this.materialIndex], this._sprite); + newMaterial.setProperty('texture', this._texture1); + newMaterial.setProperty('texture2', this._texture2); + newMaterial.setProperty('screenSize', new Float32Array([this._texture2.width, this._texture2.height])); + + this._sprite.setMaterial(0, newMaterial); + this._spriteMaterial = newMaterial; + } + + _onSceneLaunched() { + window['camera'] = cc.Camera.cameras; + } + + loadScene(sceneUrl, fromCameraPath, toCameraPath) { + this.scheduleOnce(() => { + cc.director.preloadScene(sceneUrl, null, () => { + this._loadScene( + sceneUrl, + fromCameraPath, + toCameraPath, + () => {}, + () => {} + ); + }); + }); + return true; + } + + createTexture() { + let texture = new cc.RenderTexture(); + // @ts-ignore + texture.initWithSize(cc.visibleRect.width, cc.visibleRect.height, cc.gfx.RB_FMT_D24S8); + return texture; + } + + _loadScene(sceneUrl, fromCameraPath, toCameraPath, onSceneLoaded, onTransitionFinished) { + this.init(); + this._spriteNode.active = true; + this._cameraNode.active = true; + let fromCameraNode = cc.find(fromCameraPath); + let fromCamera = fromCameraNode && (fromCameraNode.getComponent(cc.Camera) as any); + if (!fromCamera) { + cc.warn(`Can not find fromCamera with path ${fromCameraPath}`); + return; + } + let originTargetTexture1 = fromCamera.targetTexture; + fromCamera.cullingMask &= ~this._camera.cullingMask; + fromCamera.targetTexture = this._texture1; + fromCamera.render(cc.director.getScene()); + fromCamera.targetTexture = originTargetTexture1; + + return cc.director.loadScene(sceneUrl, (arg) => { + onSceneLoaded && onSceneLoaded(...arg); + + let toCameraNode = cc.find(toCameraPath); + let toCamera = toCameraNode && (toCameraNode.getComponent(cc.Camera) as any); + + if (!toCamera) { + cc.warn(`Can not find toCamera with path ${toCameraPath}`); + return; + } + toCamera.cullingMask &= ~this._camera.cullingMask; + let originTargetTexture2 = toCamera.targetTexture; + toCamera.targetTexture = this._texture2; + toCamera.render(cc.director.getScene()); + + this._camera.depth = toCamera.depth; + this._camera.clearFlags = toCamera.clearFlags; + + this._onLoadFinished = () => { + toCamera.targetTexture = originTargetTexture2; + + this._spriteNode.active = false; + this._cameraNode.active = false; + onTransitionFinished && onTransitionFinished(); + }; + + this.time = 0; + this.loading = true; + }); + } + + update(dt) { + if (this.loading) { + this.time += dt; + if (this.time >= TRANSITION_TIME) { + this.time = TRANSITION_TIME; + this.loading = false; + + this._onLoadFinished && this._onLoadFinished(); + this._onLoadFinished = null; + } + this._spriteMaterial.setProperty('time', this.time / TRANSITION_TIME); + } + } +} diff --git a/assets/Scene/Home/Transition.ts.meta b/assets/Scene/Home/Transition.ts.meta new file mode 100644 index 0000000..914ef47 --- /dev/null +++ b/assets/Scene/Home/Transition.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "1.0.5", + "uuid": "1cd9d1c5-de74-48db-8c3f-cc0cf2937437", + "isPlugin": false, + "loadPluginInWeb": true, + "loadPluginInNative": true, + "loadPluginInEditor": false, + "subMetas": {} +} \ No newline at end of file diff --git a/assets/Scene/SwitchScene__SquaresWire.meta b/assets/Scene/SwitchScene__SquaresWire.meta new file mode 100644 index 0000000..518a7e7 --- /dev/null +++ b/assets/Scene/SwitchScene__SquaresWire.meta @@ -0,0 +1,7 @@ +{ + "ver": "1.0.1", + "uuid": "b453c4d4-c9a8-4d49-ac01-0ea206687177", + "isSubpackage": false, + "subpackageName": "", + "subMetas": {} +} \ No newline at end of file diff --git a/assets/Scene/SwitchScene__SquaresWire/LocalStorage.meta b/assets/Scene/SwitchScene__SquaresWire/LocalStorage.meta new file mode 100644 index 0000000..4113a4e --- /dev/null +++ b/assets/Scene/SwitchScene__SquaresWire/LocalStorage.meta @@ -0,0 +1,7 @@ +{ + "ver": "1.0.1", + "uuid": "d1c25e17-c4ab-49e9-914a-946b38dc5365", + "isSubpackage": false, + "subpackageName": "", + "subMetas": {} +} \ No newline at end of file diff --git a/assets/Scene/SwitchScene__SquaresWire/Materials.meta b/assets/Scene/SwitchScene__SquaresWire/Materials.meta new file mode 100644 index 0000000..fe01207 --- /dev/null +++ b/assets/Scene/SwitchScene__SquaresWire/Materials.meta @@ -0,0 +1,7 @@ +{ + "ver": "1.0.1", + "uuid": "8ad96fc3-49f7-40be-a4a4-8cf2479d7b1e", + "isSubpackage": false, + "subpackageName": "", + "subMetas": {} +} \ No newline at end of file diff --git a/assets/Scene/SwitchScene__SquaresWire/Materials/SquaresWire.effect b/assets/Scene/SwitchScene__SquaresWire/Materials/SquaresWire.effect new file mode 100644 index 0000000..8f96a08 --- /dev/null +++ b/assets/Scene/SwitchScene__SquaresWire/Materials/SquaresWire.effect @@ -0,0 +1,100 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +CCEffect %{ + techniques: + - passes: + - vert: vs + frag: fs + blendState: + targets: + - blend: true + rasterizerState: + cullMode: none + properties: + texture: { value: white } + smoothness: { value: 0.4 } + time: {value: 0} + squares: {value: [10, 10]} + direction: {value: [1.0, -0.5]} +}% + +CCProgram vs %{ + precision highp float; + + #include + #include + + in vec3 a_position; + in vec4 a_color; + out vec4 v_color; + + #if USE_TEXTURE + in vec2 a_uv0; + out vec2 v_uv0; + #endif + + void main () { + vec4 pos = vec4(a_position, 1); + + #if CC_USE_MODEL + pos = cc_matViewProj * cc_matWorld * pos; + #else + pos = cc_matViewProj * pos; + #endif + + #if USE_TEXTURE + v_uv0 = a_uv0; + #endif + + v_color = a_color; + + gl_Position = pos; + } +}% + +CCProgram fs %{ + precision highp float; + uniform sampler2D texture; + uniform sampler2D texture2; + uniform Common { + vec2 squares; + vec2 direction; + float smoothness; + float time; + }; + float progress = time; + + in mediump vec2 v_uv0; + in vec4 v_color; + + vec4 getFromColor(vec2 uv) { + return texture(texture, uv); + } + vec4 getToColor(vec2 uv) { + return texture(texture2, uv); + } + vec4 transition(vec2 p) { + const vec2 center = vec2(0.5, 0.5); + // 根据进度计算当前方向 + vec2 v = normalize(direction); + v /= abs(v.x) + abs(v.y); + float d = v.x * center.x + v.y * center.y; + float offset = smoothness; + + // 计算当前进度 + float pr = smoothstep(-offset, 0.0, v.x * p.x + v.y * p.y - (d - 0.5 + progress * (1.0 + offset))); + + // 按照 squares 划分成小方块的坐标,squares 表示每行/列的方块数 + vec2 squarep = fract(p * squares); + vec2 squaremin = vec2(pr / 2.0); + vec2 squaremax = vec2(1.0 - pr / 2.0); + + // 通过 step 函数计算当前像素位置是否在当前方块内,并返回一个混合系数 a + float a = (1.0 - step(progress, 0.0)) * step(squaremin.x, squarep.x) * step(squaremin.y, squarep.y) * step(squarep.x, squaremax.x) * step(squarep.y, squaremax.y); + return mix(getFromColor(p), getToColor(p), a); + } + + void main () { + gl_FragColor = v_color * transition(v_uv0); + } +}% diff --git a/assets/Scene/SwitchScene__SquaresWire/Materials/SquaresWire.effect.meta b/assets/Scene/SwitchScene__SquaresWire/Materials/SquaresWire.effect.meta new file mode 100644 index 0000000..c65c0cc --- /dev/null +++ b/assets/Scene/SwitchScene__SquaresWire/Materials/SquaresWire.effect.meta @@ -0,0 +1,17 @@ +{ + "ver": "1.0.25", + "uuid": "7b2efda6-cd4d-436b-b504-691ff4a12f8c", + "compiledShaders": [ + { + "glsl1": { + "vert": "\nprecision highp float;\nuniform mediump mat4 cc_matViewProj;\nuniform mat4 cc_matWorld;\nattribute vec3 a_position;\nattribute vec4 a_color;\nvarying vec4 v_color;\n#if USE_TEXTURE\nattribute vec2 a_uv0;\nvarying vec2 v_uv0;\n#endif\nvoid main () {\n vec4 pos = vec4(a_position, 1);\n #if CC_USE_MODEL\n pos = cc_matViewProj * cc_matWorld * pos;\n #else\n pos = cc_matViewProj * pos;\n #endif\n #if USE_TEXTURE\n v_uv0 = a_uv0;\n #endif\n v_color = a_color;\n gl_Position = pos;\n}", + "frag": "\nprecision highp float;\nuniform sampler2D texture;\nuniform sampler2D texture2;\nuniform vec2 squares;\nuniform vec2 direction;\nuniform float smoothness;\nuniform float time;\nfloat progress = time;\nvarying mediump vec2 v_uv0;\nvarying vec4 v_color;\nvec4 getFromColor(vec2 uv) {\n return texture2D(texture, uv);\n}\nvec4 getToColor(vec2 uv) {\n return texture2D(texture2, uv);\n}\nvec4 transition(vec2 p) {\n const vec2 center = vec2(0.5, 0.5);\n vec2 v = normalize(direction);\n v /= abs(v.x) + abs(v.y);\n float d = v.x * center.x + v.y * center.y;\n float offset = smoothness;\n float pr = smoothstep(-offset, 0.0, v.x * p.x + v.y * p.y - (d - 0.5 + progress * (1.0 + offset)));\n vec2 squarep = fract(p * squares);\n vec2 squaremin = vec2(pr / 2.0);\n vec2 squaremax = vec2(1.0 - pr / 2.0);\n float a = (1.0 - step(progress, 0.0)) * step(squaremin.x, squarep.x) * step(squaremin.y, squarep.y) * step(squarep.x, squaremax.x) * step(squarep.y, squaremax.y);\n return mix(getFromColor(p), getToColor(p), a);\n}\nvoid main () {\n gl_FragColor = v_color * transition(v_uv0);\n}" + }, + "glsl3": { + "vert": "\nprecision highp float;\nuniform CCGlobal {\n highp vec4 cc_time;\n mediump vec4 cc_screenSize;\n mediump vec4 cc_screenScale;\n mediump vec4 cc_nativeSize;\n highp mat4 cc_matView;\n mediump mat4 cc_matViewInv;\n mediump mat4 cc_matProj;\n mediump mat4 cc_matProjInv;\n mediump mat4 cc_matViewProj;\n mediump mat4 cc_matViewProjInv;\n mediump vec4 cc_cameraPos;\n};\nuniform CCLocal {\n mat4 cc_matWorld;\n mat4 cc_matWorldIT;\n};\nin vec3 a_position;\nin vec4 a_color;\nout vec4 v_color;\n#if USE_TEXTURE\nin vec2 a_uv0;\nout vec2 v_uv0;\n#endif\nvoid main () {\n vec4 pos = vec4(a_position, 1);\n #if CC_USE_MODEL\n pos = cc_matViewProj * cc_matWorld * pos;\n #else\n pos = cc_matViewProj * pos;\n #endif\n #if USE_TEXTURE\n v_uv0 = a_uv0;\n #endif\n v_color = a_color;\n gl_Position = pos;\n}", + "frag": "\nprecision highp float;\nuniform sampler2D texture;\nuniform sampler2D texture2;\nuniform Common {\n vec2 squares;\n vec2 direction;\n float smoothness;\n float time;\n};\nfloat progress = time;\nin mediump vec2 v_uv0;\nin vec4 v_color;\nvec4 getFromColor(vec2 uv) {\n return texture(texture, uv);\n}\nvec4 getToColor(vec2 uv) {\n return texture(texture2, uv);\n}\nvec4 transition(vec2 p) {\n const vec2 center = vec2(0.5, 0.5);\n vec2 v = normalize(direction);\n v /= abs(v.x) + abs(v.y);\n float d = v.x * center.x + v.y * center.y;\n float offset = smoothness;\n float pr = smoothstep(-offset, 0.0, v.x * p.x + v.y * p.y - (d - 0.5 + progress * (1.0 + offset)));\n vec2 squarep = fract(p * squares);\n vec2 squaremin = vec2(pr / 2.0);\n vec2 squaremax = vec2(1.0 - pr / 2.0);\n float a = (1.0 - step(progress, 0.0)) * step(squaremin.x, squarep.x) * step(squaremin.y, squarep.y) * step(squarep.x, squaremax.x) * step(squarep.y, squaremax.y);\n return mix(getFromColor(p), getToColor(p), a);\n}\nvoid main () {\n gl_FragColor = v_color * transition(v_uv0);\n}" + } + } + ], + "subMetas": {} +} \ No newline at end of file diff --git a/assets/Scene/SwitchScene__SquaresWire/Materials/SquaresWire.mtl b/assets/Scene/SwitchScene__SquaresWire/Materials/SquaresWire.mtl new file mode 100644 index 0000000..0680f76 --- /dev/null +++ b/assets/Scene/SwitchScene__SquaresWire/Materials/SquaresWire.mtl @@ -0,0 +1,31 @@ +{ + "__type__": "cc.Material", + "_name": "SquaresWire", + "_objFlags": 0, + "_native": "", + "_effectAsset": { + "__uuid__": "7b2efda6-cd4d-436b-b504-691ff4a12f8c" + }, + "_techniqueIndex": 0, + "_techniqueData": { + "0": { + "defines": { + "USE_TEXTURE": true + }, + "props": { + "smoothness": 0.4, + "time": 0, + "squares": { + "__type__": "cc.Vec2", + "x": 30, + "y": 20 + }, + "direction": { + "__type__": "cc.Vec2", + "x": 1, + "y": -0.5 + } + } + } + } +} \ No newline at end of file diff --git a/assets/Scene/SwitchScene__SquaresWire/Materials/SquaresWire.mtl.meta b/assets/Scene/SwitchScene__SquaresWire/Materials/SquaresWire.mtl.meta new file mode 100644 index 0000000..009da19 --- /dev/null +++ b/assets/Scene/SwitchScene__SquaresWire/Materials/SquaresWire.mtl.meta @@ -0,0 +1,6 @@ +{ + "ver": "1.0.3", + "uuid": "a869ac13-ffed-4334-b5df-1251273f2b07", + "dataAsSubAsset": null, + "subMetas": {} +} \ No newline at end of file diff --git a/assets/Scene/SwitchScene__SquaresWire/SwitchScene.ts b/assets/Scene/SwitchScene__SquaresWire/SwitchScene.ts new file mode 100644 index 0000000..e8e26c0 --- /dev/null +++ b/assets/Scene/SwitchScene__SquaresWire/SwitchScene.ts @@ -0,0 +1,89 @@ +const { ccclass, property } = cc._decorator; + +@ccclass +export default class SwitchScene extends cc.Component { + @property(cc.Node) separator = null; + + @property(cc.SpriteFrame) spriteFrame1 = null; + @property(cc.SpriteFrame) spriteFrame2 = null; + @property(cc.Sprite) bgSprite = null; + @property(cc.Material) material = null; + private _spriteMaterial: cc.Material; + + touchStartPos = cc.Vec2.ZERO; + separatorStartPos = cc.Vec2.ZERO; + + start() { + this.bgSprite.spriteFrame.setTexture(this.spriteFrame1._texture); + this.initSpriteMaterial(); + this.playTransitionAnimation(); + } + + onLoad() { + this.separatorStartPos = this.separator.getPosition(); + this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this); + this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this); + } + + switchSceneByTransition() { + cc.director.emit('setBackBtnVisibility', false); + cc.director.emit('switchSceneByTransition'); + } + + playTransitionAnimation() { + let progress = 0; + let targetProgress = cc.winSize.width; + let totalTime = 3; + let startTime = Date.now(); + + const loop = () => { + if (!this._spriteMaterial || !this.touchStartPos) return; + if (!this.touchStartPos.equals(cc.Vec2.ZERO)) return; + + let currentTime = Date.now(); + let elapsedTime = (currentTime - startTime) / 1000; + let _progress = (elapsedTime / totalTime) * targetProgress; + progress = Math.min(_progress, targetProgress); + + this._spriteMaterial.setProperty('time', progress / cc.winSize.width); + this.separator.setPosition({ x: progress, y: 0 }); + + if (progress < targetProgress) { + requestAnimationFrame(loop.bind(this)); + } + }; + loop(); + } + + onTouchStart(event) { + this.separatorStartPos = this.separator.getPosition(); + this.touchStartPos = this.node.convertToNodeSpaceAR(event.getLocation()); + } + + private onTouchMove(event) { + // 获取当前触摸点的位置 + let touchPos = this.node.convertToNodeSpaceAR(event.getLocation()); + // 计算触摸点相对于起始位置的偏移量 + let offset = touchPos.sub(this.touchStartPos); + let targetPos = this.separatorStartPos.add(offset); + let targetX = Math.max(0, Math.min(targetPos.x, cc.winSize.width)); + this.separator.setPosition({ + x: targetX, + y: 0 + }); + this._spriteMaterial.setProperty('time', targetX / cc.winSize.width); + } + + initSpriteMaterial() { + let newMaterial = cc.MaterialVariant.create(this.material, this.bgSprite); + newMaterial.setProperty('texture', this.spriteFrame1._texture); + newMaterial.setProperty('texture2', this.spriteFrame2._texture); + newMaterial.setProperty('screenSize', new Float32Array([cc.winSize.width, cc.winSize.height])); + newMaterial.setProperty('time', 0.25); + + this.spriteFrame1._texture.setFlipY(true); + this.spriteFrame2._texture.setFlipY(true); + this.bgSprite.setMaterial(0, newMaterial); + this._spriteMaterial = newMaterial; + } +} diff --git a/assets/Scene/SwitchScene__SquaresWire/SwitchScene.ts.meta b/assets/Scene/SwitchScene__SquaresWire/SwitchScene.ts.meta new file mode 100644 index 0000000..25cafeb --- /dev/null +++ b/assets/Scene/SwitchScene__SquaresWire/SwitchScene.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "1.0.5", + "uuid": "d3f4aa83-177e-4b31-b4f8-168797fa6b26", + "isPlugin": false, + "loadPluginInWeb": true, + "loadPluginInNative": true, + "loadPluginInEditor": false, + "subMetas": {} +} \ No newline at end of file diff --git a/assets/Scene/SwitchScene__SquaresWire/SwitchScene__SquaresWire.fire b/assets/Scene/SwitchScene__SquaresWire/SwitchScene__SquaresWire.fire new file mode 100644 index 0000000..18d7a32 --- /dev/null +++ b/assets/Scene/SwitchScene__SquaresWire/SwitchScene__SquaresWire.fire @@ -0,0 +1,740 @@ +[ + { + "__type__": "cc.SceneAsset", + "_name": "", + "_objFlags": 0, + "_native": "", + "scene": { + "__id__": 1 + } + }, + { + "__type__": "cc.Scene", + "_objFlags": 0, + "_parent": null, + "_children": [ + { + "__id__": 2 + }, + { + "__id__": 11 + }, + { + "__id__": 13 + }, + { + "__id__": 8 + } + ], + "_active": true, + "_components": [], + "_prefab": null, + "_opacity": 255, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 0, + "height": 0 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0, + "y": 0 + }, + "_trs": { + "__type__": "TypedArray", + "ctor": "Float64Array", + "array": [ + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1 + ] + }, + "_is3DNode": true, + "_groupIndex": 0, + "groupIndex": 0, + "autoReleaseAssets": false, + "_id": "4b414e09-dbb9-49d1-9e08-d40df17461b3" + }, + { + "__type__": "cc.Node", + "_name": "Canvas", + "_objFlags": 512, + "_parent": { + "__id__": 1 + }, + "_children": [ + { + "__id__": 3 + } + ], + "_active": true, + "_components": [ + { + "__id__": 5 + }, + { + "__id__": 6 + }, + { + "__id__": 7 + } + ], + "_prefab": null, + "_opacity": 255, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 1334, + "height": 750 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_trs": { + "__type__": "TypedArray", + "ctor": "Float64Array", + "array": [ + 667, + 375, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1 + ] + }, + "_eulerAngles": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_skewX": 0, + "_skewY": 0, + "_is3DNode": false, + "_groupIndex": 0, + "groupIndex": 0, + "_id": "a5esZu+45LA5mBpvttspPD" + }, + { + "__type__": "cc.Node", + "_name": "Main Camera", + "_objFlags": 0, + "_parent": { + "__id__": 2 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 4 + } + ], + "_prefab": null, + "_opacity": 255, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 960, + "height": 640 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_trs": { + "__type__": "TypedArray", + "ctor": "Float64Array", + "array": [ + 0, + 0, + 769.0305585605815, + 0, + 0, + 0, + 1, + 1, + 1, + 1 + ] + }, + "_eulerAngles": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_skewX": 0, + "_skewY": 0, + "_is3DNode": false, + "_groupIndex": 0, + "groupIndex": 0, + "_id": "e1WoFrQ79G7r4ZuQE3HlNb" + }, + { + "__type__": "cc.Camera", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 3 + }, + "_enabled": true, + "_cullingMask": 4294967295, + "_clearFlags": 7, + "_backgroundColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_depth": -1, + "_zoomRatio": 1, + "_targetTexture": null, + "_fov": 60, + "_orthoSize": 10, + "_nearClip": 1, + "_farClip": 4096, + "_ortho": true, + "_rect": { + "__type__": "cc.Rect", + "x": 0, + "y": 0, + "width": 1, + "height": 1 + }, + "_renderStages": 1, + "_alignWithScreen": true, + "_id": "81GN3uXINKVLeW4+iKSlim" + }, + { + "__type__": "cc.Canvas", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 2 + }, + "_enabled": true, + "_designResolution": { + "__type__": "cc.Size", + "width": 1334, + "height": 750 + }, + "_fitWidth": false, + "_fitHeight": true, + "_id": "59Cd0ovbdF4byw5sbjJDx7" + }, + { + "__type__": "cc.Widget", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 2 + }, + "_enabled": true, + "alignMode": 1, + "_target": null, + "_alignFlags": 45, + "_left": 0, + "_right": 0, + "_top": 0, + "_bottom": 0, + "_verticalCenter": 0, + "_horizontalCenter": 0, + "_isAbsLeft": true, + "_isAbsRight": true, + "_isAbsTop": true, + "_isAbsBottom": true, + "_isAbsHorizontalCenter": true, + "_isAbsVerticalCenter": true, + "_originalWidth": 0, + "_originalHeight": 0, + "_id": "29zXboiXFBKoIV4PQ2liTe" + }, + { + "__type__": "d3f4aqDF35LMbT4FoeX+msm", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 2 + }, + "_enabled": true, + "separator": { + "__id__": 8 + }, + "spriteFrame1": { + "__uuid__": "4e0f593c-d4b5-4485-83a0-0934fbc70808" + }, + "spriteFrame2": { + "__uuid__": "01d6486a-e29c-4227-854c-6b3cf263f243" + }, + "bgSprite": { + "__id__": 10 + }, + "material": { + "__uuid__": "a869ac13-ffed-4334-b5df-1251273f2b07" + }, + "_id": "baVBIwAahNp5q/xqS/DqnM" + }, + { + "__type__": "cc.Node", + "_name": "Separator", + "_objFlags": 0, + "_parent": { + "__id__": 1 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 9 + } + ], + "_prefab": null, + "_opacity": 255, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 171, + "b": 23, + "a": 255 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 10, + "height": 750 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0 + }, + "_trs": { + "__type__": "TypedArray", + "ctor": "Float64Array", + "array": [ + 333, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1 + ] + }, + "_eulerAngles": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_skewX": 0, + "_skewY": 0, + "_is3DNode": false, + "_groupIndex": 0, + "groupIndex": 0, + "_id": "00zwOFnw9A9Y2jJcAfpxGt" + }, + { + "__type__": "cc.Sprite", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 8 + }, + "_enabled": true, + "_materials": [ + { + "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432" + } + ], + "_srcBlendFactor": 770, + "_dstBlendFactor": 771, + "_spriteFrame": { + "__uuid__": "5c3bb932-6c3c-468f-88a9-c8c61d458641" + }, + "_type": 0, + "_sizeMode": 0, + "_fillType": 0, + "_fillCenter": { + "__type__": "cc.Vec2", + "x": 0, + "y": 0 + }, + "_fillStart": 0, + "_fillRange": 0, + "_isTrimmedMode": true, + "_atlas": null, + "_id": "bfovdQprtLZrbQA9328iTr" + }, + { + "__type__": "cc.Sprite", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 11 + }, + "_enabled": true, + "_materials": [ + { + "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432" + } + ], + "_srcBlendFactor": 770, + "_dstBlendFactor": 771, + "_spriteFrame": { + "__uuid__": "a23235d1-15db-4b95-8439-a2e005bfff91" + }, + "_type": 0, + "_sizeMode": 0, + "_fillType": 0, + "_fillCenter": { + "__type__": "cc.Vec2", + "x": 0, + "y": 0 + }, + "_fillStart": 0, + "_fillRange": 0, + "_isTrimmedMode": true, + "_atlas": null, + "_id": "b70P96s8FD1LitaZ7aobMA" + }, + { + "__type__": "cc.Node", + "_name": "Bg", + "_objFlags": 0, + "_parent": { + "__id__": 1 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 10 + }, + { + "__id__": 12 + } + ], + "_prefab": null, + "_opacity": 255, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 1334, + "height": 750 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_trs": { + "__type__": "TypedArray", + "ctor": "Float64Array", + "array": [ + 667, + 375, + 0, + 0, + 0, + 0, + 1, + 1, + -1, + 1 + ] + }, + "_eulerAngles": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_skewX": 0, + "_skewY": 0, + "_is3DNode": false, + "_groupIndex": 0, + "groupIndex": 0, + "_id": "34YKVYdF5MoYlFN+Zfb6wk" + }, + { + "__type__": "cc.Widget", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 11 + }, + "_enabled": true, + "alignMode": 1, + "_target": null, + "_alignFlags": 45, + "_left": 0, + "_right": 0, + "_top": 0, + "_bottom": 0, + "_verticalCenter": 0, + "_horizontalCenter": 0, + "_isAbsLeft": true, + "_isAbsRight": true, + "_isAbsTop": true, + "_isAbsBottom": true, + "_isAbsHorizontalCenter": true, + "_isAbsVerticalCenter": true, + "_originalWidth": 1024, + "_originalHeight": 445, + "_id": "711M5JfuBPs5F7P5bDVb/1" + }, + { + "__type__": "cc.Node", + "_name": "Btn", + "_objFlags": 0, + "_parent": { + "__id__": 1 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 14 + }, + { + "__id__": 16 + }, + { + "__id__": 17 + } + ], + "_prefab": null, + "_opacity": 255, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 1477, + "height": 118 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_trs": { + "__type__": "TypedArray", + "ctor": "Float64Array", + "array": [ + 667, + 528.7, + 0, + 0, + 0, + 0, + 1, + 0.7, + 0.7, + 1 + ] + }, + "_eulerAngles": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_skewX": 0, + "_skewY": 0, + "_is3DNode": false, + "_groupIndex": 0, + "groupIndex": 0, + "_id": "bcVNNAEfFEJL7tftaCUB7n" + }, + { + "__type__": "cc.Button", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 13 + }, + "_enabled": true, + "_normalMaterial": null, + "_grayMaterial": null, + "duration": 0.1, + "zoomScale": 1.2, + "clickEvents": [ + { + "__id__": 15 + } + ], + "_N$interactable": true, + "_N$enableAutoGrayEffect": false, + "_N$transition": 0, + "transition": 0, + "_N$normalColor": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_N$pressedColor": { + "__type__": "cc.Color", + "r": 211, + "g": 211, + "b": 211, + "a": 255 + }, + "pressedColor": { + "__type__": "cc.Color", + "r": 211, + "g": 211, + "b": 211, + "a": 255 + }, + "_N$hoverColor": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "hoverColor": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_N$disabledColor": { + "__type__": "cc.Color", + "r": 124, + "g": 124, + "b": 124, + "a": 255 + }, + "_N$normalSprite": null, + "_N$pressedSprite": null, + "pressedSprite": null, + "_N$hoverSprite": null, + "hoverSprite": null, + "_N$disabledSprite": null, + "_N$target": { + "__id__": 13 + }, + "_id": "fdJg28i7pE6pi4D1ovRRp0" + }, + { + "__type__": "cc.ClickEvent", + "target": { + "__id__": 2 + }, + "component": "", + "_componentId": "d3f4aqDF35LMbT4FoeX+msm", + "handler": "switchSceneByTransition", + "customEventData": "" + }, + { + "__type__": "cc.Sprite", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 13 + }, + "_enabled": true, + "_materials": [ + { + "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432" + } + ], + "_srcBlendFactor": 770, + "_dstBlendFactor": 771, + "_spriteFrame": { + "__uuid__": "86714285-13db-44f6-86aa-11838e0d4831" + }, + "_type": 0, + "_sizeMode": 1, + "_fillType": 0, + "_fillCenter": { + "__type__": "cc.Vec2", + "x": 0, + "y": 0 + }, + "_fillStart": 0, + "_fillRange": 0, + "_isTrimmedMode": true, + "_atlas": null, + "_id": "c1sR5klVZHraEr68/UTkLE" + }, + { + "__type__": "cc.Widget", + "_name": "", + "_objFlags": 0, + "node": { + "__id__": 13 + }, + "_enabled": true, + "alignMode": 1, + "_target": null, + "_alignFlags": 17, + "_left": 0, + "_right": 0, + "_top": 180, + "_bottom": 0, + "_verticalCenter": 157.942, + "_horizontalCenter": 0, + "_isAbsLeft": true, + "_isAbsRight": true, + "_isAbsTop": true, + "_isAbsBottom": true, + "_isAbsHorizontalCenter": true, + "_isAbsVerticalCenter": true, + "_originalWidth": 0, + "_originalHeight": 0, + "_id": "a6rm0uXY9DlbNNnoWq9hN0" + } +] \ No newline at end of file diff --git a/assets/Scene/SwitchScene__SquaresWire/SwitchScene__SquaresWire.fire.meta b/assets/Scene/SwitchScene__SquaresWire/SwitchScene__SquaresWire.fire.meta new file mode 100644 index 0000000..4ecf41c --- /dev/null +++ b/assets/Scene/SwitchScene__SquaresWire/SwitchScene__SquaresWire.fire.meta @@ -0,0 +1,7 @@ +{ + "ver": "1.2.6", + "uuid": "4b414e09-dbb9-49d1-9e08-d40df17461b3", + "asyncLoadAssets": false, + "autoReleaseAssets": false, + "subMetas": {} +} \ No newline at end of file diff --git a/assets/Scene/SwitchScene__SquaresWire/Texture.meta b/assets/Scene/SwitchScene__SquaresWire/Texture.meta new file mode 100644 index 0000000..a548a78 --- /dev/null +++ b/assets/Scene/SwitchScene__SquaresWire/Texture.meta @@ -0,0 +1,7 @@ +{ + "ver": "1.0.1", + "uuid": "dda83645-8387-450f-96e6-a4018b9a7121", + "isSubpackage": false, + "subpackageName": "", + "subMetas": {} +} \ No newline at end of file diff --git a/assets/Scene/SwitchScene__SquaresWire/Texture/bg1.jpeg b/assets/Scene/SwitchScene__SquaresWire/Texture/bg1.jpeg new file mode 100644 index 0000000..f905b16 Binary files /dev/null and b/assets/Scene/SwitchScene__SquaresWire/Texture/bg1.jpeg differ diff --git a/assets/Scene/SwitchScene__SquaresWire/Texture/bg1.jpeg.meta b/assets/Scene/SwitchScene__SquaresWire/Texture/bg1.jpeg.meta new file mode 100644 index 0000000..324d253 --- /dev/null +++ b/assets/Scene/SwitchScene__SquaresWire/Texture/bg1.jpeg.meta @@ -0,0 +1,36 @@ +{ + "ver": "2.3.4", + "uuid": "bdc5b1b7-faf4-4186-9895-f5ee7ed31093", + "type": "sprite", + "wrapMode": "clamp", + "filterMode": "bilinear", + "premultiplyAlpha": false, + "genMipmaps": false, + "packable": true, + "width": 1600, + "height": 1200, + "platformSettings": {}, + "subMetas": { + "bg1": { + "ver": "1.0.4", + "uuid": "4e0f593c-d4b5-4485-83a0-0934fbc70808", + "rawTextureUuid": "bdc5b1b7-faf4-4186-9895-f5ee7ed31093", + "trimType": "auto", + "trimThreshold": 1, + "rotated": false, + "offsetX": 0, + "offsetY": 0, + "trimX": 0, + "trimY": 0, + "width": 1600, + "height": 1200, + "rawWidth": 1600, + "rawHeight": 1200, + "borderTop": 0, + "borderBottom": 0, + "borderLeft": 0, + "borderRight": 0, + "subMetas": {} + } + } +} \ No newline at end of file diff --git a/assets/Scene/SwitchScene__SquaresWire/Texture/bg2.jpeg b/assets/Scene/SwitchScene__SquaresWire/Texture/bg2.jpeg new file mode 100644 index 0000000..a5a3c9c Binary files /dev/null and b/assets/Scene/SwitchScene__SquaresWire/Texture/bg2.jpeg differ diff --git a/assets/Scene/SwitchScene__SquaresWire/Texture/bg2.jpeg.meta b/assets/Scene/SwitchScene__SquaresWire/Texture/bg2.jpeg.meta new file mode 100644 index 0000000..5d6a5eb --- /dev/null +++ b/assets/Scene/SwitchScene__SquaresWire/Texture/bg2.jpeg.meta @@ -0,0 +1,36 @@ +{ + "ver": "2.3.4", + "uuid": "c8b7f468-dad7-41d2-892a-13b1e106ec06", + "type": "sprite", + "wrapMode": "clamp", + "filterMode": "bilinear", + "premultiplyAlpha": false, + "genMipmaps": false, + "packable": true, + "width": 1600, + "height": 1200, + "platformSettings": {}, + "subMetas": { + "bg2": { + "ver": "1.0.4", + "uuid": "01d6486a-e29c-4227-854c-6b3cf263f243", + "rawTextureUuid": "c8b7f468-dad7-41d2-892a-13b1e106ec06", + "trimType": "auto", + "trimThreshold": 1, + "rotated": false, + "offsetX": 0, + "offsetY": 0, + "trimX": 0, + "trimY": 0, + "width": 1600, + "height": 1200, + "rawWidth": 1600, + "rawHeight": 1200, + "borderTop": 0, + "borderBottom": 0, + "borderLeft": 0, + "borderRight": 0, + "subMetas": {} + } + } +} \ No newline at end of file diff --git a/assets/Scene/SwitchScene__SquaresWire/Texture/btn.png b/assets/Scene/SwitchScene__SquaresWire/Texture/btn.png new file mode 100644 index 0000000..bc4283d Binary files /dev/null and b/assets/Scene/SwitchScene__SquaresWire/Texture/btn.png differ diff --git a/assets/Scene/SwitchScene__SquaresWire/Texture/btn.png.meta b/assets/Scene/SwitchScene__SquaresWire/Texture/btn.png.meta new file mode 100644 index 0000000..6f56cb8 --- /dev/null +++ b/assets/Scene/SwitchScene__SquaresWire/Texture/btn.png.meta @@ -0,0 +1,36 @@ +{ + "ver": "2.3.4", + "uuid": "ad45580f-04d5-48f7-83b9-4f1852099c1c", + "type": "sprite", + "wrapMode": "clamp", + "filterMode": "bilinear", + "premultiplyAlpha": false, + "genMipmaps": false, + "packable": true, + "width": 1477, + "height": 118, + "platformSettings": {}, + "subMetas": { + "btn": { + "ver": "1.0.4", + "uuid": "86714285-13db-44f6-86aa-11838e0d4831", + "rawTextureUuid": "ad45580f-04d5-48f7-83b9-4f1852099c1c", + "trimType": "auto", + "trimThreshold": 1, + "rotated": false, + "offsetX": 0, + "offsetY": 0, + "trimX": 0, + "trimY": 0, + "width": 1477, + "height": 118, + "rawWidth": 1477, + "rawHeight": 118, + "borderTop": 0, + "borderBottom": 0, + "borderLeft": 0, + "borderRight": 0, + "subMetas": {} + } + } +} \ No newline at end of file diff --git a/assets/Scene/Water_spread/Water_spread.effect b/assets/Scene/Water_spread/Water_spread.effect index ea0a307..442106c 100644 --- a/assets/Scene/Water_spread/Water_spread.effect +++ b/assets/Scene/Water_spread/Water_spread.effect @@ -16,6 +16,7 @@ CCEffect %{ center: { value: [ 0.5, 0.5 ] } wave_radius: { value: 0.18 } wave_offset: { value: 2.0 } + time: { value: 0 } }% @@ -72,6 +73,7 @@ CCProgram fs %{ vec2 canvas_size; float wave_radius; float wave_offset; + float time; }; void main() { @@ -81,7 +83,7 @@ CCProgram fs %{ // distance小于1,但是我们希望能有多个波峰波谷,所以在sin的内部乘上一个比较大的倍数 // sin函数的值在-1到1之间,我们希望偏移值很小,所以输出的时候需要缩小一定的倍数倍 - float sin_factor = sin(distance * 100.0 + cc_time.x) * 0.05; + float sin_factor = sin(distance * 100.0 + time) * 0.05; float discard_factor = clamp(wave_radius - abs(wave_offset - distance), 0.0, 1.0); // 计算总的uv的偏移值 diff --git a/assets/Scene/Water_spread/Water_spread.effect.meta b/assets/Scene/Water_spread/Water_spread.effect.meta index 127882c..6d81ab5 100644 --- a/assets/Scene/Water_spread/Water_spread.effect.meta +++ b/assets/Scene/Water_spread/Water_spread.effect.meta @@ -5,11 +5,11 @@ { "glsl1": { "vert": "\nprecision highp float;\nuniform mediump mat4 cc_matViewProj;\nuniform mat4 cc_matWorld;\nattribute vec3 a_position;\nattribute vec4 a_color;\nvarying vec4 v_color;\n#if USE_TEXTURE\nattribute vec2 a_uv0;\nvarying vec2 v_uv0;\n#endif\nvoid main () {\n vec4 pos = vec4(a_position, 1);\n #if CC_USE_MODEL\n pos = cc_matViewProj * cc_matWorld * pos;\n #else\n pos = cc_matViewProj * pos;\n #endif\n #if USE_TEXTURE\n v_uv0 = a_uv0;\n #endif\n v_color = a_color;\n gl_Position = pos;\n}", - "frag": "\nprecision highp float;\n#if USE_ALPHA_TEST\n#endif\nuniform highp vec4 cc_time;\nvarying vec4 v_color;\n#if USE_TEXTURE\nvarying vec2 v_uv0;\nuniform sampler2D texture;\n#endif\nuniform vec2 center;\nuniform vec2 canvas_size;\nuniform float wave_radius;\nuniform float wave_offset;\nvoid main() {\n vec2 distance_vec = center - v_uv0;\n distance_vec = distance_vec * vec2(canvas_size.x / canvas_size.y, 1.0);\n float distance = sqrt(distance_vec.x * distance_vec.x + distance_vec.y * distance_vec.y);\n float sin_factor = sin(distance * 100.0 + cc_time.x) * 0.05;\n float discard_factor = clamp(wave_radius - abs(wave_offset - distance), 0.0, 1.0);\n vec2 offset = normalize(distance_vec) * sin_factor * discard_factor;\n vec2 uv = offset + v_uv0;\n gl_FragColor = texture2D(texture, uv);\n}" + "frag": "\nprecision highp float;\n#if USE_ALPHA_TEST\n#endif\nvarying vec4 v_color;\n#if USE_TEXTURE\nvarying vec2 v_uv0;\nuniform sampler2D texture;\n#endif\nuniform vec2 center;\nuniform vec2 canvas_size;\nuniform float wave_radius;\nuniform float wave_offset;\nuniform float time;\nvoid main() {\n vec2 distance_vec = center - v_uv0;\n distance_vec = distance_vec * vec2(canvas_size.x / canvas_size.y, 1.0);\n float distance = sqrt(distance_vec.x * distance_vec.x + distance_vec.y * distance_vec.y);\n float sin_factor = sin(distance * 100.0 + time) * 0.05;\n float discard_factor = clamp(wave_radius - abs(wave_offset - distance), 0.0, 1.0);\n vec2 offset = normalize(distance_vec) * sin_factor * discard_factor;\n vec2 uv = offset + v_uv0;\n gl_FragColor = texture2D(texture, uv);\n}" }, "glsl3": { "vert": "\nprecision highp float;\nuniform CCGlobal {\n highp vec4 cc_time;\n mediump vec4 cc_screenSize;\n mediump vec4 cc_screenScale;\n mediump vec4 cc_nativeSize;\n highp mat4 cc_matView;\n mediump mat4 cc_matViewInv;\n mediump mat4 cc_matProj;\n mediump mat4 cc_matProjInv;\n mediump mat4 cc_matViewProj;\n mediump mat4 cc_matViewProjInv;\n mediump vec4 cc_cameraPos;\n};\nuniform CCLocal {\n mat4 cc_matWorld;\n mat4 cc_matWorldIT;\n};\nin vec3 a_position;\nin vec4 a_color;\nout vec4 v_color;\n#if USE_TEXTURE\nin vec2 a_uv0;\nout vec2 v_uv0;\n#endif\nvoid main () {\n vec4 pos = vec4(a_position, 1);\n #if CC_USE_MODEL\n pos = cc_matViewProj * cc_matWorld * pos;\n #else\n pos = cc_matViewProj * pos;\n #endif\n #if USE_TEXTURE\n v_uv0 = a_uv0;\n #endif\n v_color = a_color;\n gl_Position = pos;\n}", - "frag": "\nprecision highp float;\n#if USE_ALPHA_TEST\n uniform ALPHA_TEST {\n float alphaThreshold;\n };\n#endif\nuniform CCGlobal {\n highp vec4 cc_time;\n mediump vec4 cc_screenSize;\n mediump vec4 cc_screenScale;\n mediump vec4 cc_nativeSize;\n highp mat4 cc_matView;\n mediump mat4 cc_matViewInv;\n mediump mat4 cc_matProj;\n mediump mat4 cc_matProjInv;\n mediump mat4 cc_matViewProj;\n mediump mat4 cc_matViewProjInv;\n mediump vec4 cc_cameraPos;\n};\nin vec4 v_color;\n#if USE_TEXTURE\nin vec2 v_uv0;\nuniform sampler2D texture;\n#endif\nuniform ARGS{\n vec2 center;\n vec2 canvas_size;\n float wave_radius;\n float wave_offset;\n};\nvoid main() {\n vec2 distance_vec = center - v_uv0;\n distance_vec = distance_vec * vec2(canvas_size.x / canvas_size.y, 1.0);\n float distance = sqrt(distance_vec.x * distance_vec.x + distance_vec.y * distance_vec.y);\n float sin_factor = sin(distance * 100.0 + cc_time.x) * 0.05;\n float discard_factor = clamp(wave_radius - abs(wave_offset - distance), 0.0, 1.0);\n vec2 offset = normalize(distance_vec) * sin_factor * discard_factor;\n vec2 uv = offset + v_uv0;\n gl_FragColor = texture(texture, uv);\n}" + "frag": "\nprecision highp float;\n#if USE_ALPHA_TEST\n uniform ALPHA_TEST {\n float alphaThreshold;\n };\n#endif\nuniform CCGlobal {\n highp vec4 cc_time;\n mediump vec4 cc_screenSize;\n mediump vec4 cc_screenScale;\n mediump vec4 cc_nativeSize;\n highp mat4 cc_matView;\n mediump mat4 cc_matViewInv;\n mediump mat4 cc_matProj;\n mediump mat4 cc_matProjInv;\n mediump mat4 cc_matViewProj;\n mediump mat4 cc_matViewProjInv;\n mediump vec4 cc_cameraPos;\n};\nin vec4 v_color;\n#if USE_TEXTURE\nin vec2 v_uv0;\nuniform sampler2D texture;\n#endif\nuniform ARGS{\n vec2 center;\n vec2 canvas_size;\n float wave_radius;\n float wave_offset;\n float time;\n};\nvoid main() {\n vec2 distance_vec = center - v_uv0;\n distance_vec = distance_vec * vec2(canvas_size.x / canvas_size.y, 1.0);\n float distance = sqrt(distance_vec.x * distance_vec.x + distance_vec.y * distance_vec.y);\n float sin_factor = sin(distance * 100.0 + time) * 0.05;\n float discard_factor = clamp(wave_radius - abs(wave_offset - distance), 0.0, 1.0);\n vec2 offset = normalize(distance_vec) * sin_factor * discard_factor;\n vec2 uv = offset + v_uv0;\n gl_FragColor = texture(texture, uv);\n}" } } ], diff --git a/assets/Scene/Water_spread/Water_spread.fire b/assets/Scene/Water_spread/Water_spread.fire index 38fab07..7c115fb 100644 --- a/assets/Scene/Water_spread/Water_spread.fire +++ b/assets/Scene/Water_spread/Water_spread.fire @@ -174,7 +174,7 @@ "array": [ 0, 0, - 452.93128617926146, + 443.4050067376326, 0, 0, 0, diff --git a/assets/Scene/Water_spread/Water_spread.ts b/assets/Scene/Water_spread/Water_spread.ts index a58e854..0692222 100644 --- a/assets/Scene/Water_spread/Water_spread.ts +++ b/assets/Scene/Water_spread/Water_spread.ts @@ -19,6 +19,7 @@ export default class Water_spread extends cc.Component { } update(dt) { + this.material.setProperty('time', dt); if (this.waveOffset > 2.0) return; this.waveOffset += dt; diff --git a/doc/SwitchScene__SquaresWire/resource/SquaresWire.gif b/doc/SwitchScene__SquaresWire/resource/SquaresWire.gif new file mode 100644 index 0000000..bec24b0 Binary files /dev/null and b/doc/SwitchScene__SquaresWire/resource/SquaresWire.gif differ diff --git a/doc/SwitchScene__SquaresWire/resource/ewm.png b/doc/SwitchScene__SquaresWire/resource/ewm.png new file mode 100644 index 0000000..e666769 Binary files /dev/null and b/doc/SwitchScene__SquaresWire/resource/ewm.png differ diff --git a/doc/SwitchScene__SquaresWire/矩形网格转场.md b/doc/SwitchScene__SquaresWire/矩形网格转场.md new file mode 100644 index 0000000..91769cb --- /dev/null +++ b/doc/SwitchScene__SquaresWire/矩形网格转场.md @@ -0,0 +1,117 @@ +# 效果演示 + +早些时候在社区见到一个元宇宙的项目,做了一个前后场景方块碎片过渡的效果,十分有科技感,异名就有了复刻的想法;加上两个场景切换的过渡效果比较实用,社区上已经有了开源的方案,异名复刻的成本很低,但是收获不少 +![demo](http://cdn.blog.ifengzp.com/switch-scene/SquaresWire.gif) + +# 实现思路 + +因为最终效果需要应用到两个场景切换中,所以借助了常驻节点来实现全局共享的能力。常驻节点是一种特殊类型的节点,它们在场景切换时不会被销毁,而是保持在内存中。常驻节点在整个游戏生命周期中都存在,可以用于实现一些需要在多个场景之间共享的功能或数据,它的开启很简单:`cc.game.addPersistRootNode(this.node)` + +在常驻节点中,我们创建一个内部Camera和Sprite来渲染场景的过渡画面 +```c++ +// 同样的方式创建一个内部的渲染Sprite, +let cameraNode = cc.find('TRANSITION_CAMERA', this.node); +if (!cameraNode) { + cameraNode = new cc.Node('TRANSITION_CAMERA'); + this._camera = cameraNode.addComponent(cc.Camera); + cameraNode.parent = this.node; +} else { + this._camera = cameraNode.getComponent(cc.Camera); +} +``` + +这样我们就拥有了三个Camera,当场景A切换到场景B的时候,我们把 `TRANSITION_CAMERA` 激活,用这个相机来渲染过渡的画面,具体细节看核心的过渡逻辑 + +```c++ +_loadScene(sceneUrl, fromCameraPath, toCameraPath, onSceneLoaded, onTransitionFinished) { + this._spriteNode.active = true; + this._cameraNode.active = true; + let fromCameraNode = cc.find(fromCameraPath); + let fromCamera = fromCameraNode && (fromCameraNode.getComponent(cc.Camera) as any); + + let originTargetTexture1 = fromCamera.targetTexture; + fromCamera.cullingMask &= ~this._camera.cullingMask; + fromCamera.targetTexture = this._texture1; + fromCamera.render(cc.director.getScene()); + fromCamera.targetTexture = originTargetTexture1; + + return cc.director.loadScene(sceneUrl, (arg) => { + onSceneLoaded && onSceneLoaded(...arg); + + let toCameraNode = cc.find(toCameraPath); + let toCamera = toCameraNode && (toCameraNode.getComponent(cc.Camera) as any); + + toCamera.cullingMask &= ~this._camera.cullingMask; + let originTargetTexture2 = toCamera.targetTexture; + toCamera.targetTexture = this._texture2; + toCamera.render(cc.director.getScene()); + + this._camera.depth = toCamera.depth; + this._camera.clearFlags = toCamera.clearFlags; + + this._onLoadFinished = () => { + toCamera.targetTexture = originTargetTexture2; + + this._spriteNode.active = false; + this._cameraNode.active = false; + }; + }); + } +``` + +这里面有一个"Render-To-Texture(RTT)"的操作,它将图形渲染的结果直接绘制到一个纹理(Texture)上,而不是直接渲染到屏幕上,核心代码是这三行 + +```c++ +// 设置渲染目标:将渲染目标设置为一个纹理,而不是默认的屏幕缓冲区。这样,所有的渲染操作都会直接渲染到这个纹理上 +fromCamera.targetTexture = this._texture1; +// 进行渲染:执行需要渲染的图形绘制操作,渲染结果会直接绘制到纹理上 +fromCamera.render(cc.director.getScene()); +// 恢复渲染目标:渲染完成后,将渲染目标恢复为默认的屏幕缓冲区,以便后续的渲染操作正常进行 +fromCamera.targetTexture = originTargetTexture1; +``` + +这里面还有一个我们不常用的位运算 `fromCamera.cullingMask &= ~this._camera.cullingMask;`,其目的是通过对摄像机的 cullingMask 属性进行位操作,来控制哪些图层的对象会被摄像机忽略。cullingMask 是在图形编程中用于决定摄像机渲染哪些图层的一个掩码(mask),它通常用于指定摄像机在渲染时应该考虑哪些图层中的对象,哪些图层中的对象应该被忽略 + +其中 `~this._camera.cullingMask` 使用了位求反操作符 ~,它会将 `this._camera.cullingMask` 的每个位都取反,即将 0 变为 1,将 1 变为 0通过按位与运算符;然后通过 `&=` 将 fromCamera.cullingMask 和 ~this._camera.cullingMask 的结果进行按位与操作,以得到新的掩码。这个新的掩码会在不影响其他位的情况下,将与参考摄像机的 cullingMask 相关的位设置为 0,从而排除这些层级的对象不被当前摄像机渲染 + +获得了前后场景的画面,接下来就可以基于此实现两张Texture的切换效果;在这个demo中,我们要实现一个渐进的、基于小方块的过渡动效,方块从起始颜色逐渐变化到目标颜色,我们定义三个参数:progress(time) 控制过渡的进度,smoothness 控制过渡边缘的平滑度,squares 控制方块的数量,核心函数如下 +![demo](http://cdn.blog.ifengzp.com/switch-scene/canshu.png) + +```c++ + vec4 transition(vec2 p) { + const vec2 center = vec2(0.5, 0.5); + // 根据进度计算当前方向 + vec2 v = normalize(direction); + v /= abs(v.x) + abs(v.y); + float d = v.x * center.x + v.y * center.y; + float offset = smoothness; + + // 计算当前进度 + float pr = smoothstep(-offset, 0.0, v.x * p.x + v.y * p.y - (d - 0.5 + progress * (1.0 + offset))); + + // 按照 squares 划分成小方块的坐标 + vec2 squarep = fract(p * squares); + vec2 squaremin = vec2(pr / 2.0); + vec2 squaremax = vec2(1.0 - pr / 2.0); + + // 通过 step 函数计算当前像素位置是否在当前方块内,并返回一个混合系数 a + float a = (1.0 - step(progress, 0.0)) * step(squaremin.x, squarep.x) * step(squaremin.y, squarep.y) * step(squarep.x, squaremax.x) * step(squarep.y, squaremax.y); + return mix(getFromColor(p), getToColor(p), a); + } +``` + +切分小方块代码是 `vec2 squarep = fract(p * squares)`, 这行代码的作用是将输入坐标 p 乘以 squares 后,取其小数部分,这种操作通常用于在纹理坐标或屏幕空间坐标上创建重复的图案或效果 + +举例如果 p 是 (0.3, 0.7) 且 squares 是 4,则 p * squares 是 (1.2, 2.8),而 fract(1.2, 2.8) 是 (0.2, 0.8),这样,原始坐标 (0.3, 0.7) 被映射到一个在 [0, 1) 范围内的新坐标。通过这种方式,就能实现将图像或屏幕空间分割成多个小方块的效果,然后通过step函数算出每个像素点是否处于方块内,最后进行色彩的插值,从而实现画面的切换,最终效果如下 + +![demo](http://cdn.blog.ifengzp.com/switch-scene/SquaresWire.gif) + +# 效果预览 + +**源码**获取请点击**查看原文**,长按二维码**查看效果**👇 + +![ewm](http://cdn.blog.ifengzp.com/switch-scene/ewm.png) + + + +