From 160916ff53e662dd2afc94680162d0ef928d6197 Mon Sep 17 00:00:00 2001 From: felix <9202@htl.rennweg.at> Date: Fri, 2 Aug 2024 21:59:29 +0200 Subject: [PATCH 01/10] added warping title screen --- assets/config/assets.onj | 6 ++ assets/screens/title_screen.onj | 2 + assets/shaders/warp.glsl | 62 +++++++++++++++++++ .../fortyfive/screen/general/OnjScreen.kt | 14 +++++ 4 files changed, 84 insertions(+) create mode 100644 assets/shaders/warp.glsl diff --git a/assets/config/assets.onj b/assets/config/assets.onj index 12db10fc8..faef4fe44 100644 --- a/assets/config/assets.onj +++ b/assets/config/assets.onj @@ -1212,6 +1212,12 @@ shaders: [ constantArgs: { } }, + { + name: "warp_shader", + file: "shaders/warp.glsl", + constantArgs: { + } + }, { name: "slider_shader", file: "shaders/slider.glsl", diff --git a/assets/screens/title_screen.onj b/assets/screens/title_screen.onj index 144ce4400..f26d32111 100644 --- a/assets/screens/title_screen.onj +++ b/assets/screens/title_screen.onj @@ -35,6 +35,7 @@ assets: { "main_theme", "swoosh_sound", "button_2_sound", + "warp_shader", ] }, @@ -99,6 +100,7 @@ var confirmationPopup = $Box { } children [ $Box { + name:"myTestScreenForWarp", styles: [ { width: 1_100#points, diff --git a/assets/shaders/warp.glsl b/assets/shaders/warp.glsl new file mode 100644 index 000000000..20403295e --- /dev/null +++ b/assets/shaders/warp.glsl @@ -0,0 +1,62 @@ +~~~section vertex + +%include shaders/includes/default_vertex.glsl + +~~~section fragment + +#ifdef GL_ES +#define LOWP lowp +precision mediump float; +#else +#define LOWP +#endif + +varying LOWP vec4 v_color; +varying vec2 v_texCoords; +uniform sampler2D u_texture; + +%uniform u_time +uniform float u_progress; +uniform vec2 u_center; + + +float getNewDist(float oldDist){ + float e=3.0;//steepness of the curve, can be changed + float a = pow(2, e); + a=a/(a-1.0); + return a-a/pow(oldDist+1.0, e);//from 0-1 returns 0-1 but "warped" +} + +void main() { + + float progress = abs(sin(abs(float(u_time*0.85))));//TODO change back to u_progress + vec2 center = vec2(0.5, 0.2);//TODO change back to u_center + + vec2 tc = v_texCoords; + vec2 distToCenter= tc-center; + + vec2 totalDistanceInThatDirection=vec2(0.0); + if (distToCenter.x<0) totalDistanceInThatDirection.x=-center.x; + else totalDistanceInThatDirection.x=1-center.x; + + if (distToCenter.y<0) totalDistanceInThatDirection.y=-center.y; + else totalDistanceInThatDirection.y=1-center.y; + + vec2 percent=distToCenter/totalDistanceInThatDirection; + + vec2 newPercent=vec2(getNewDist(percent.x),getNewDist(percent.y)); + + vec2 strechedPos=center+newPercent*totalDistanceInThatDirection; + + vec2 diffOldNew=strechedPos-tc; + + + vec4 result = texture2D(u_texture, tc+diffOldNew*progress); + + if (sqrt((tc.x-center.x)*(tc.x-center.x)+(tc.y-center.y)*(tc.y-center.y))<0.0018){ + result=vec4(1.0,0.0,0.0,1.0); + } +// result.a=progress; + gl_FragColor = result; + // gl_FragColor = vec4(0.0); +} diff --git a/core/src/com/fourinachamber/fortyfive/screen/general/OnjScreen.kt b/core/src/com/fourinachamber/fortyfive/screen/general/OnjScreen.kt index 28b110613..6b8820857 100644 --- a/core/src/com/fourinachamber/fortyfive/screen/general/OnjScreen.kt +++ b/core/src/com/fourinachamber/fortyfive/screen/general/OnjScreen.kt @@ -24,6 +24,7 @@ import com.fourinachamber.fortyfive.game.GraphicsConfig import com.fourinachamber.fortyfive.keyInput.KeyInputMap import com.fourinachamber.fortyfive.keyInput.KeySelectionHierarchyBuilder import com.fourinachamber.fortyfive.keyInput.KeySelectionHierarchyNode +import com.fourinachamber.fortyfive.rendering.BetterShader import com.fourinachamber.fortyfive.rendering.Renderable import com.fourinachamber.fortyfive.screen.ResourceBorrower import com.fourinachamber.fortyfive.screen.ResourceHandle @@ -422,6 +423,11 @@ open class OnjScreen @MainThreadOnly constructor( actor.localToStageCoordinates(Vector2(actor.width / 2, actor.height / 2)) } + + private val warpShader : BetterShader by lazy { + ResourceManager.get(this, "warp_shader") + } + @MainThreadOnly override fun render(delta: Float) = try { // Thread.sleep(800) //TODO remove // (please don't, its great to find this method) @@ -431,6 +437,14 @@ open class OnjScreen @MainThreadOnly constructor( if (stage.batch.isDrawing) stage.batch.end() stage.viewport.apply() doRenderTasks(earlyRenderTasks, additionalEarlyRenderTasks) + if (namedActorOrNull("myTestScreenForWarp") != null){ + warpShader.let { + stage.batch.flush() + it.shader.bind() + it.prepare(this) + stage.batch.shader = it.shader + } + } stage.draw() doRenderTasks(lateRenderTasks, additionalLateRenderTasks) styleManagers From 3c6449dbd113ca01fd3fe710e1256ea3c3a19cfd Mon Sep 17 00:00:00 2001 From: felix <9202@htl.rennweg.at> Date: Sat, 3 Aug 2024 01:06:30 +0200 Subject: [PATCH 02/10] finished warp shader and removed it from the title screen again --- assets/screens/title_screen.onj | 1 - assets/shaders/warp.glsl | 97 ++++++++++++++----- .../fortyfive/screen/general/OnjScreen.kt | 12 --- 3 files changed, 74 insertions(+), 36 deletions(-) diff --git a/assets/screens/title_screen.onj b/assets/screens/title_screen.onj index f26d32111..60eb1b6ba 100644 --- a/assets/screens/title_screen.onj +++ b/assets/screens/title_screen.onj @@ -35,7 +35,6 @@ assets: { "main_theme", "swoosh_sound", "button_2_sound", - "warp_shader", ] }, diff --git a/assets/shaders/warp.glsl b/assets/shaders/warp.glsl index 20403295e..0c5203b7e 100644 --- a/assets/shaders/warp.glsl +++ b/assets/shaders/warp.glsl @@ -16,47 +16,98 @@ varying vec2 v_texCoords; uniform sampler2D u_texture; %uniform u_time -uniform float u_progress; -uniform vec2 u_center; +uniform float u_progress;// between 0-1 +uniform vec2 u_center;// between 0-1 for x and y +uniform float u_depth;// recommended beween 3 and 30, how strong it zooms float getNewDist(float oldDist){ - float e=3.0;//steepness of the curve, can be changed - float a = pow(2, e); + float depth=5.0; + if (u_depth>1.0){ + depth=u_depth; + } + float a = pow(2.0, depth); a=a/(a-1.0); - return a-a/pow(oldDist+1.0, e);//from 0-1 returns 0-1 but "warped" + return a-a/pow(oldDist+1.0, depth);//from 0-1 returns 0-1 but "warped" +} + +float hypo(vec2 oldDist){ + return sqrt(oldDist.x*oldDist.x+oldDist.y*oldDist.y); + // return abs(oldDist.x)+abs(oldDist.y); } void main() { - float progress = abs(sin(abs(float(u_time*0.85))));//TODO change back to u_progress - vec2 center = vec2(0.5, 0.2);//TODO change back to u_center + // float progress = (sin(abs(float(u_time*0.85)))+1.0)/2.0; + // float progress = 1.0; + float progress = u_progress; + + // vec2 center = vec2(0.5, 0.8); + vec2 center = u_center; vec2 tc = v_texCoords; vec2 distToCenter= tc-center; - vec2 totalDistanceInThatDirection=vec2(0.0); - if (distToCenter.x<0) totalDistanceInThatDirection.x=-center.x; - else totalDistanceInThatDirection.x=1-center.x; - - if (distToCenter.y<0) totalDistanceInThatDirection.y=-center.y; - else totalDistanceInThatDirection.y=1-center.y; + float k = distToCenter.y/distToCenter.x; + float d = tc.y - tc.x * k; - vec2 percent=distToCenter/totalDistanceInThatDirection; + //the position where the extended line between the center and the pixel hits the 00-01-11-10 square + vec2 borderIntersection; + if (tc.x > center.x) borderIntersection= vec2(1.0, k+d); + else borderIntersection=vec2(0.0, d); - vec2 newPercent=vec2(getNewDist(percent.x),getNewDist(percent.y)); + if (borderIntersection.y>1.0) borderIntersection=vec2((1.0-d) / k, 1.0); + else if (borderIntersection.y<0.0) borderIntersection=vec2(-d/k, 0.0); - vec2 strechedPos=center+newPercent*totalDistanceInThatDirection; + vec2 borderToCenter =borderIntersection-center; + float newPercent=getNewDist(hypo(distToCenter)/hypo(borderToCenter)); + vec2 strechedPos = center+borderToCenter*newPercent; vec2 diffOldNew=strechedPos-tc; - - vec4 result = texture2D(u_texture, tc+diffOldNew*progress); - if (sqrt((tc.x-center.x)*(tc.x-center.x)+(tc.y-center.y)*(tc.y-center.y))<0.0018){ - result=vec4(1.0,0.0,0.0,1.0); - } -// result.a=progress; gl_FragColor = result; - // gl_FragColor = vec4(0.0); } + +// //bad warp, as a backup or future refernce +// +//float getNewDist(float oldDist){ +// float e=3.0;//steepness of the curve, can be changed +// float a = pow(2, e); +// a=a/(a-1.0); +// return a-a/pow(oldDist+1.0, e);//from 0-1 returns 0-1 but "warped" +//} +// +//void main() { +// +// float progress = abs(sin(abs(float(u_time*0.85)))); +// vec2 center = vec2(0.5, 0.2); +// +// vec2 tc = v_texCoords; +// vec2 distToCenter= tc-center; +// +// vec2 totalDistanceInThatDirection=vec2(0.0); +// if (distToCenter.x<0) totalDistanceInThatDirection.x=-center.x; +// else totalDistanceInThatDirection.x=1-center.x; +// +// if (distToCenter.y<0) totalDistanceInThatDirection.y=-center.y; +// else totalDistanceInThatDirection.y=1-center.y; +// +// vec2 percent=distToCenter/totalDistanceInThatDirection; +// +// vec2 newPercent=vec2(getNewDist(percent.x),getNewDist(percent.y)); +// +// vec2 strechedPos=center+newPercent*totalDistanceInThatDirection; +// +// vec2 diffOldNew=strechedPos-tc; +// +// +// vec4 result = texture2D(u_texture, tc+diffOldNew*progress); +// +// if (sqrt((tc.x-center.x)*(tc.x-center.x)+(tc.y-center.y)*(tc.y-center.y))<0.0018){ +// result=vec4(1.0,0.0,0.0,1.0); +// } +//// result.a=progress; +// gl_FragColor = result; +// // gl_FragColor = vec4(0.0); +//} diff --git a/core/src/com/fourinachamber/fortyfive/screen/general/OnjScreen.kt b/core/src/com/fourinachamber/fortyfive/screen/general/OnjScreen.kt index 6b8820857..a49142329 100644 --- a/core/src/com/fourinachamber/fortyfive/screen/general/OnjScreen.kt +++ b/core/src/com/fourinachamber/fortyfive/screen/general/OnjScreen.kt @@ -424,10 +424,6 @@ open class OnjScreen @MainThreadOnly constructor( } - private val warpShader : BetterShader by lazy { - ResourceManager.get(this, "warp_shader") - } - @MainThreadOnly override fun render(delta: Float) = try { // Thread.sleep(800) //TODO remove // (please don't, its great to find this method) @@ -437,14 +433,6 @@ open class OnjScreen @MainThreadOnly constructor( if (stage.batch.isDrawing) stage.batch.end() stage.viewport.apply() doRenderTasks(earlyRenderTasks, additionalEarlyRenderTasks) - if (namedActorOrNull("myTestScreenForWarp") != null){ - warpShader.let { - stage.batch.flush() - it.shader.bind() - it.prepare(this) - stage.batch.shader = it.shader - } - } stage.draw() doRenderTasks(lateRenderTasks, additionalLateRenderTasks) styleManagers From 23112d2e93c05d26fd1a30e182a3d5f96c03145d Mon Sep 17 00:00:00 2001 From: felix <9202@htl.rennweg.at> Date: Sat, 3 Aug 2024 01:07:20 +0200 Subject: [PATCH 03/10] removed unnecessary name from titlescreen which was there only for testing the warp --- assets/screens/title_screen.onj | 2 -- 1 file changed, 2 deletions(-) diff --git a/assets/screens/title_screen.onj b/assets/screens/title_screen.onj index 60eb1b6ba..36db7d8a0 100644 --- a/assets/screens/title_screen.onj +++ b/assets/screens/title_screen.onj @@ -97,9 +97,7 @@ var confirmationPopup = $Box { ], touchable: "enabled" } children [ - $Box { - name:"myTestScreenForWarp", styles: [ { width: 1_100#points, From 7701b820128f6a162d19bce0c046ec1c876dfbde Mon Sep 17 00:00:00 2001 From: felix <9202@htl.rennweg.at> Date: Mon, 5 Aug 2024 00:21:40 +0200 Subject: [PATCH 04/10] warp rotation works up to PI/4 radians --- assets/screens/title_screen.onj | 1 + assets/shaders/warp.glsl | 87 +++++++++++++++---- .../fortyfive/screen/general/OnjScreen.kt | 11 +++ 3 files changed, 80 insertions(+), 19 deletions(-) diff --git a/assets/screens/title_screen.onj b/assets/screens/title_screen.onj index 36db7d8a0..7ba0401af 100644 --- a/assets/screens/title_screen.onj +++ b/assets/screens/title_screen.onj @@ -34,6 +34,7 @@ assets: { "common_button_default", "common_button_hover", "main_theme", + "warp_shader", "swoosh_sound", "button_2_sound", ] }, diff --git a/assets/shaders/warp.glsl b/assets/shaders/warp.glsl index 0c5203b7e..110168a8a 100644 --- a/assets/shaders/warp.glsl +++ b/assets/shaders/warp.glsl @@ -21,14 +21,15 @@ uniform vec2 u_center;// between 0-1 for x and y uniform float u_depth;// recommended beween 3 and 30, how strong it zooms -float getNewDist(float oldDist){ - float depth=5.0; +float getNewDist(float dist, float maxDist){ + float oldDist=dist/maxDist; + float depth=35.0; if (u_depth>1.0){ depth=u_depth; } float a = pow(2.0, depth); a=a/(a-1.0); - return a-a/pow(oldDist+1.0, depth);//from 0-1 returns 0-1 but "warped" + return (a-a/pow(oldDist+1.0, depth));//from 0-1 returns 0-1 but "warped" } float hypo(vec2 oldDist){ @@ -36,37 +37,85 @@ float hypo(vec2 oldDist){ // return abs(oldDist.x)+abs(oldDist.y); } + +vec2 getBorderIntersection(float k, vec2 pointOnLine, bool rightOfCenter){ + //the position where the extended line between the center and the pixel hits the (0|0),(0|1),(1|1),(1|0) square + + float d = pointOnLine.y - pointOnLine.x * k; + vec2 borderIntersection; + if (rightOfCenter) borderIntersection= vec2(1.0, k+d); + else borderIntersection=vec2(0.0, d); + + if (borderIntersection.y>1.0) borderIntersection=vec2((1.0-d) / k, 1.0); + else if (borderIntersection.y<0.0) borderIntersection=vec2(-d/k, 0.0); + return borderIntersection; +} + + +float rotate(float oldSlope, float rotation){ + float oldRotation=atan(oldSlope, 1.0); + float newRotation=oldRotation+rotation; + float pi=radians(180.0); + // while(newRotation < -pi){ + // newRotation+=pi; + // } + // while(newRotation>pi){ + // newRotation-=pi; + // } + + return tan(newRotation); +} + void main() { - // float progress = (sin(abs(float(u_time*0.85)))+1.0)/2.0; - // float progress = 1.0; - float progress = u_progress; + float progress = (sin(abs(float(u_time*0.85)))+1.0)/2.0; +// float progress = (sin(abs(float(u_time*0.05)))+1.0)/2.0; + // float progress = 1.0; + // float progress = u_progress; + + vec2 center = vec2(0.5, 0.8); + // vec2 center = u_center; + + float PI = radians(float(180)); + float rotation = 2*PI*progress/4; - // vec2 center = vec2(0.5, 0.8); - vec2 center = u_center; +// float rotation = PI*1.51; +// float rotation = 0; vec2 tc = v_texCoords; vec2 distToCenter= tc-center; float k = distToCenter.y/distToCenter.x; - float d = tc.y - tc.x * k; - //the position where the extended line between the center and the pixel hits the 00-01-11-10 square - vec2 borderIntersection; - if (tc.x > center.x) borderIntersection= vec2(1.0, k+d); - else borderIntersection=vec2(0.0, d); + bool rotationRightOfCenter=tc.x>center.x; - if (borderIntersection.y>1.0) borderIntersection=vec2((1.0-d) / k, 1.0); - else if (borderIntersection.y<0.0) borderIntersection=vec2(-d/k, 0.0); + vec2 borderIntersection= getBorderIntersection(k, tc, rotationRightOfCenter); + float strechedPercent=getNewDist(hypo(distToCenter), hypo(borderIntersection-center)); + + float newRot=rotate(k, rotation); + if ((newRot<0 && k>0)) { + rotationRightOfCenter=!rotationRightOfCenter; + } - vec2 borderToCenter =borderIntersection-center; - float newPercent=getNewDist(hypo(distToCenter)/hypo(borderToCenter)); - vec2 strechedPos = center+borderToCenter*newPercent; + vec2 rotatedBorderToCenter = getBorderIntersection(newRot, tc, rotationRightOfCenter) - center; + + vec2 strechedPos = center+rotatedBorderToCenter*strechedPercent; +// vec2 strechedPos = center+rotatedBorderToCenter*((hypo(distToCenter)/ hypo(borderIntersection-center))); vec2 diffOldNew=strechedPos-tc; - vec4 result = texture2D(u_texture, tc+diffOldNew*progress); + vec4 result = texture2D(u_texture, tc+diffOldNew*progress); +// vec4 result = texture2D(u_texture, strechedPos); gl_FragColor = result; + + // if(borderIntersection.x>center.x && borderIntersection.y==1.0){ + // gl_FragColor = vec4(1.0,0.0,0.0,1.0); + // } + // if(atan(tc.x*4*PI-2*PI,1.0)>0){ + // gl_FragColor = vec4(0.0,atan(tc.x*4*PI-2*PI,1.0),0.0,1.0); + // }else{ + // gl_FragColor = vec4(atan(-(tc.x*4*PI-2*PI),1.0),0.0,0.0,1.0); + // } } // //bad warp, as a backup or future refernce diff --git a/core/src/com/fourinachamber/fortyfive/screen/general/OnjScreen.kt b/core/src/com/fourinachamber/fortyfive/screen/general/OnjScreen.kt index a49142329..a27b0cc23 100644 --- a/core/src/com/fourinachamber/fortyfive/screen/general/OnjScreen.kt +++ b/core/src/com/fourinachamber/fortyfive/screen/general/OnjScreen.kt @@ -424,6 +424,10 @@ open class OnjScreen @MainThreadOnly constructor( } + private val warpShader: BetterShader by lazy { + ResourceManager.get(this, "warp_shader") + } + @MainThreadOnly override fun render(delta: Float) = try { // Thread.sleep(800) //TODO remove // (please don't, its great to find this method) @@ -433,7 +437,14 @@ open class OnjScreen @MainThreadOnly constructor( if (stage.batch.isDrawing) stage.batch.end() stage.viewport.apply() doRenderTasks(earlyRenderTasks, additionalEarlyRenderTasks) + warpShader.let { + stage.batch.flush() + it.shader.bind() + it.prepare(this) + stage.batch.shader = it.shader + } stage.draw() + stage.batch.flush() doRenderTasks(lateRenderTasks, additionalLateRenderTasks) styleManagers .filter { it !in oldStyleManagers } From 6a40459a08c9b5a9aebdbfa7ed32e3478c848a32 Mon Sep 17 00:00:00 2001 From: felix <9202@htl.rennweg.at> Date: Mon, 5 Aug 2024 00:50:17 +0200 Subject: [PATCH 05/10] warp rotation works, but not with the zoom of the warp --- assets/shaders/warp.glsl | 163 ++++++++++++++++++++++++++++++++------- 1 file changed, 137 insertions(+), 26 deletions(-) diff --git a/assets/shaders/warp.glsl b/assets/shaders/warp.glsl index 110168a8a..b4f623efc 100644 --- a/assets/shaders/warp.glsl +++ b/assets/shaders/warp.glsl @@ -52,35 +52,30 @@ vec2 getBorderIntersection(float k, vec2 pointOnLine, bool rightOfCenter){ } -float rotate(float oldSlope, float rotation){ +vec2 rotate(float oldSlope, float rotation, bool isRightOfCenter){ + float PI=radians(180.0); float oldRotation=atan(oldSlope, 1.0); + if(!isRightOfCenter) oldRotation+=PI; float newRotation=oldRotation+rotation; - float pi=radians(180.0); - // while(newRotation < -pi){ - // newRotation+=pi; - // } - // while(newRotation>pi){ - // newRotation-=pi; - // } - return tan(newRotation); + if(cos(newRotation)>0) return vec2(tan(newRotation),1.0); + else return vec2(tan(newRotation),0.0); } void main() { - float progress = (sin(abs(float(u_time*0.85)))+1.0)/2.0; -// float progress = (sin(abs(float(u_time*0.05)))+1.0)/2.0; - // float progress = 1.0; + float progress = (sin(abs(float(u_time*0.85)))+1.0)/2.0; +// float progress = 1.0; // float progress = u_progress; vec2 center = vec2(0.5, 0.8); // vec2 center = u_center; float PI = radians(float(180)); - float rotation = 2*PI*progress/4; + float rotation = 4*PI*progress; + + -// float rotation = PI*1.51; -// float rotation = 0; vec2 tc = v_texCoords; vec2 distToCenter= tc-center; @@ -89,22 +84,19 @@ void main() { bool rotationRightOfCenter=tc.x>center.x; - vec2 borderIntersection= getBorderIntersection(k, tc, rotationRightOfCenter); + vec2 borderIntersection= getBorderIntersection(k, center, rotationRightOfCenter); float strechedPercent=getNewDist(hypo(distToCenter), hypo(borderIntersection-center)); - float newRot=rotate(k, rotation); - if ((newRot<0 && k>0)) { - rotationRightOfCenter=!rotationRightOfCenter; - } + vec2 newRot = rotate(k, rotation, rotationRightOfCenter); //first element new slope, second == 1 if new point is right - vec2 rotatedBorderToCenter = getBorderIntersection(newRot, tc, rotationRightOfCenter) - center; + vec2 rotatedBorderToCenter = getBorderIntersection(newRot.x, center, newRot.y==1.0) - center; - vec2 strechedPos = center+rotatedBorderToCenter*strechedPercent; -// vec2 strechedPos = center+rotatedBorderToCenter*((hypo(distToCenter)/ hypo(borderIntersection-center))); +// vec2 strechedPos = center+rotatedBorderToCenter*strechedPercent; + vec2 strechedPos = center+rotatedBorderToCenter*((hypo(distToCenter)/ hypo(borderIntersection-center))); - vec2 diffOldNew=strechedPos-tc; - vec4 result = texture2D(u_texture, tc+diffOldNew*progress); -// vec4 result = texture2D(u_texture, strechedPos); +// vec2 diffOldNew=strechedPos-tc; +// vec4 result = texture2D(u_texture, tc+diffOldNew*progress); + vec4 result = texture2D(u_texture, strechedPos); gl_FragColor = result; @@ -118,6 +110,125 @@ void main() { // } } + + + + +//another backup + +// +//float getNewDist(float dist, float maxDist){ +// float oldDist=dist/maxDist; +// float depth=35.0; +// if (u_depth>1.0){ +// depth=u_depth; +// } +// float a = pow(2.0, depth); +// a=a/(a-1.0); +// return (a-a/pow(oldDist+1.0, depth));//from 0-1 returns 0-1 but "warped" +//} +// +//float hypo(vec2 oldDist){ +// return sqrt(oldDist.x*oldDist.x+oldDist.y*oldDist.y); +// // return abs(oldDist.x)+abs(oldDist.y); +//} +// +// +//vec2 getBorderIntersection(float k, vec2 pointOnLine, bool rightOfCenter){ +// //the position where the extended line between the center and the pixel hits the (0|0),(0|1),(1|1),(1|0) square +// +// float d = pointOnLine.y - pointOnLine.x * k; +// vec2 borderIntersection; +// if (rightOfCenter) borderIntersection= vec2(1.0, k+d); +// else borderIntersection=vec2(0.0, d); +// +// if (borderIntersection.y>1.0) borderIntersection=vec2((1.0-d) / k, 1.0); +// else if (borderIntersection.y<0.0) borderIntersection=vec2(-d/k, 0.0); +// return borderIntersection; +//} +// +// +//float rotate(float oldSlope, float rotation){ +// float oldRotation=atan(oldSlope, 1.0); +// float newRotation=oldRotation+rotation; +// float pi=radians(180.0); +// // while(newRotation < -pi){ +// // newRotation+=pi; +// // } +// // while(newRotation>pi){ +// // newRotation-=pi; +// // } +// +// return tan(newRotation); +//} +// +//void main() { +// +// float progress = (sin(abs(float(u_time*0.85)))+1.0)/2.0; +// // float progress = (sin(abs(float(u_time*0.05)))+1.0)/2.0; +// // float progress = 1.0; +// // float progress = u_progress; +// +// vec2 center = vec2(0.5, 0.8); +// // vec2 center = u_center; +// +// float PI = radians(float(180)); +// float rotation = 2*PI*progress/4; +// +// // float rotation = PI*1.51; +// // float rotation = 0; +// +// vec2 tc = v_texCoords; +// vec2 distToCenter= tc-center; +// +// float k = distToCenter.y/distToCenter.x; +// +// bool rotationRightOfCenter=tc.x>center.x; +// +// vec2 borderIntersection= getBorderIntersection(k, tc, rotationRightOfCenter); +// float strechedPercent=getNewDist(hypo(distToCenter), hypo(borderIntersection-center)); +// +// float newRot=rotate(k, rotation); +// if ((newRot<0 && k>0)) { +// rotationRightOfCenter=!rotationRightOfCenter; +// } +// +// vec2 rotatedBorderToCenter = getBorderIntersection(newRot, tc, rotationRightOfCenter) - center; +// +// // vec2 strechedPos = center+rotatedBorderToCenter*strechedPercent; +// vec2 strechedPos = center+rotatedBorderToCenter*((hypo(distToCenter)/ hypo(borderIntersection-center))); +// +// // vec2 diffOldNew=strechedPos-tc; +// // vec4 result = texture2D(u_texture, tc+diffOldNew*progress); +// vec4 result = texture2D(u_texture, strechedPos); +// +// gl_FragColor = result; +// +// // if(borderIntersection.x>center.x && borderIntersection.y==1.0){ +// // gl_FragColor = vec4(1.0,0.0,0.0,1.0); +// // } +// // if(atan(tc.x*4*PI-2*PI,1.0)>0){ +// // gl_FragColor = vec4(0.0,atan(tc.x*4*PI-2*PI,1.0),0.0,1.0); +// // }else{ +// // gl_FragColor = vec4(atan(-(tc.x*4*PI-2*PI),1.0),0.0,0.0,1.0); +// // } +//} +// + + + + + + + + + + + + + + + // //bad warp, as a backup or future refernce // //float getNewDist(float oldDist){ From 794016e99313bc31cb8e66c582e0906214d6e3b1 Mon Sep 17 00:00:00 2001 From: felix <9202@htl.rennweg.at> Date: Mon, 5 Aug 2024 01:02:19 +0200 Subject: [PATCH 06/10] it works, but its kinda ugly and needs some cleanup --- assets/shaders/warp.glsl | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/assets/shaders/warp.glsl b/assets/shaders/warp.glsl index b4f623efc..abbdc21fd 100644 --- a/assets/shaders/warp.glsl +++ b/assets/shaders/warp.glsl @@ -23,7 +23,7 @@ uniform float u_depth;// recommended beween 3 and 30, how strong it zooms float getNewDist(float dist, float maxDist){ float oldDist=dist/maxDist; - float depth=35.0; + float depth=25.0; if (u_depth>1.0){ depth=u_depth; } @@ -72,7 +72,7 @@ void main() { // vec2 center = u_center; float PI = radians(float(180)); - float rotation = 4*PI*progress; + float rotation = getNewDist(progress, 1) * PI/2.0; @@ -87,16 +87,13 @@ void main() { vec2 borderIntersection= getBorderIntersection(k, center, rotationRightOfCenter); float strechedPercent=getNewDist(hypo(distToCenter), hypo(borderIntersection-center)); - vec2 newRot = rotate(k, rotation, rotationRightOfCenter); //first element new slope, second == 1 if new point is right + vec2 newRot = rotate(k, rotation*(1.0-strechedPercent), rotationRightOfCenter); //first element new slope, second == 1 if new point is right vec2 rotatedBorderToCenter = getBorderIntersection(newRot.x, center, newRot.y==1.0) - center; -// vec2 strechedPos = center+rotatedBorderToCenter*strechedPercent; - vec2 strechedPos = center+rotatedBorderToCenter*((hypo(distToCenter)/ hypo(borderIntersection-center))); - -// vec2 diffOldNew=strechedPos-tc; -// vec4 result = texture2D(u_texture, tc+diffOldNew*progress); - vec4 result = texture2D(u_texture, strechedPos); + vec2 rotatedPos = center+rotatedBorderToCenter*((hypo(distToCenter)/ hypo(borderIntersection-center))); + vec2 rotatedStrechedPos=center+rotatedBorderToCenter*strechedPercent; + vec4 result = texture2D(u_texture, rotatedPos+(rotatedStrechedPos-rotatedPos)*progress); gl_FragColor = result; @@ -193,7 +190,7 @@ void main() { // rotationRightOfCenter=!rotationRightOfCenter; // } // -// vec2 rotatedBorderToCenter = getBorderIntersection(newRot, tc, rotationRightOfCenter) - center; +// vec2 rotatedBorderToCenter = getBorderIntersection(newRot, center, rotationRightOfCenter) - center; // // // vec2 strechedPos = center+rotatedBorderToCenter*strechedPercent; // vec2 strechedPos = center+rotatedBorderToCenter*((hypo(distToCenter)/ hypo(borderIntersection-center))); From 13c0a89ac873725374a941f52f145a3bb3c6098f Mon Sep 17 00:00:00 2001 From: felix <9202@htl.rennweg.at> Date: Mon, 5 Aug 2024 13:00:42 +0200 Subject: [PATCH 07/10] added rotation to the warp --- assets/shaders/warp.glsl | 81 ++++++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/assets/shaders/warp.glsl b/assets/shaders/warp.glsl index abbdc21fd..227d1f9ff 100644 --- a/assets/shaders/warp.glsl +++ b/assets/shaders/warp.glsl @@ -19,13 +19,13 @@ uniform sampler2D u_texture; uniform float u_progress;// between 0-1 uniform vec2 u_center;// between 0-1 for x and y uniform float u_depth;// recommended beween 3 and 30, how strong it zooms +uniform float u_rotation;// rotation in radians -float getNewDist(float dist, float maxDist){ - float oldDist=dist/maxDist; - float depth=25.0; +float getNewDist(float oldDist, float depthMulti){ + float depth=15.0*depthMulti; if (u_depth>1.0){ - depth=u_depth; + depth=u_depth*depthMulti; } float a = pow(2.0, depth); a=a/(a-1.0); @@ -37,9 +37,8 @@ float hypo(vec2 oldDist){ // return abs(oldDist.x)+abs(oldDist.y); } - +//the position where the extended line between the center and the pixel hits the (0|0),(0|1),(1|1),(1|0) square vec2 getBorderIntersection(float k, vec2 pointOnLine, bool rightOfCenter){ - //the position where the extended line between the center and the pixel hits the (0|0),(0|1),(1|1),(1|0) square float d = pointOnLine.y - pointOnLine.x * k; vec2 borderIntersection; @@ -51,55 +50,83 @@ vec2 getBorderIntersection(float k, vec2 pointOnLine, bool rightOfCenter){ return borderIntersection; } - +// rotates the slope, and the isRightOfCenter says if the direction is (oldSlope,1) if true or (-oldslope,-1) if false vec2 rotate(float oldSlope, float rotation, bool isRightOfCenter){ float PI=radians(180.0); float oldRotation=atan(oldSlope, 1.0); if(!isRightOfCenter) oldRotation+=PI; float newRotation=oldRotation+rotation; - if(cos(newRotation)>0) return vec2(tan(newRotation),1.0); + if(cos(newRotation)>0.0) return vec2(tan(newRotation),1.0); else return vec2(tan(newRotation),0.0); } -void main() { +// This programm takes the following steps: +// 1. calculate the line between the current position and the center +// 2. get the point on the line where it hits the min/max box (Rectangle with coordiantes: (0|0),(0|1),(1|1),(1|0)) +// 3. calculate the distance in percent to that point from the center +// 4. strech this position exponentially, so that the closer you are to the center, the stronger it streches and goes away from it +// 5. then it rotates the line from 1 +// 6. repeat step 2 with the new line +// 7. takes the percentages of the line from 1 and puts them on the line of line 2 - float progress = (sin(abs(float(u_time*0.85)))+1.0)/2.0; -// float progress = 1.0; - // float progress = u_progress; - - vec2 center = vec2(0.5, 0.8); - // vec2 center = u_center; +void main() { - float PI = radians(float(180)); - float rotation = getNewDist(progress, 1) * PI/2.0; +// float progress = (sin(abs(float(u_time*0.85)))+1.0)/2.0; + float progress = u_progress; + vec2 center = u_center; + if(u_center.x==0.0 && u_center.y==0.0) center=vec2(0.5, 0.5); +// float PI = radians(180.0); +// float rotation = getNewDist(progress, -1/10.0) * PI/2.0*16.0; + float rotation = getNewDist(progress, -0.1) * u_rotation; vec2 tc = v_texCoords; vec2 distToCenter= tc-center; - float k = distToCenter.y/distToCenter.x; + // 1. + float k = distToCenter.y/distToCenter.x; // slope of line from + + bool pointRightOfCenter=tc.x>center.x; + + // 2. + vec2 borderIntersection= getBorderIntersection(k, center, pointRightOfCenter); + - bool rotationRightOfCenter=tc.x>center.x; + // 3. + float maxDist=hypo(borderIntersection-center); - vec2 borderIntersection= getBorderIntersection(k, center, rotationRightOfCenter); - float strechedPercent=getNewDist(hypo(distToCenter), hypo(borderIntersection-center)); - vec2 newRot = rotate(k, rotation*(1.0-strechedPercent), rotationRightOfCenter); //first element new slope, second == 1 if new point is right + float maxDistToFurthestCorner=max(max(hypo(center),hypo(center-vec2(0.0,1.0))), max(hypo(center-vec2(1.0)),hypo(center-vec2(1.0,0.0)))); + float outSideMultiplier=maxDist/maxDistToFurthestCorner; //this makes it from a rectangle to a circle + float oldPercent=hypo(distToCenter)/maxDist; + // 4. + float strechedPercent=getNewDist(oldPercent, outSideMultiplier); + + + //5. + vec2 newRot = rotate(k, rotation*(1.0-strechedPercent), pointRightOfCenter); //newRot[0]= new slope, newRot[1] == 1 if new point is right of center + + + //6 vec2 rotatedBorderToCenter = getBorderIntersection(newRot.x, center, newRot.y==1.0) - center; - vec2 rotatedPos = center+rotatedBorderToCenter*((hypo(distToCenter)/ hypo(borderIntersection-center))); + + //7 + float maxRotatedDist=hypo(borderIntersection-center); + vec2 rotatedPos = center+rotatedBorderToCenter*((hypo(distToCenter)/ maxRotatedDist)); vec2 rotatedStrechedPos=center+rotatedBorderToCenter*strechedPercent; - vec4 result = texture2D(u_texture, rotatedPos+(rotatedStrechedPos-rotatedPos)*progress); + + vec4 result = texture2D(u_texture, rotatedPos+(rotatedStrechedPos-rotatedPos)*progress); gl_FragColor = result; - // if(borderIntersection.x>center.x && borderIntersection.y==1.0){ - // gl_FragColor = vec4(1.0,0.0,0.0,1.0); - // } +// if(maxDist/maxDistToFurthestCorner> 0.95){ +// gl_FragColor = vec4(1.0,0.0,0.0,1.0); +// } // if(atan(tc.x*4*PI-2*PI,1.0)>0){ // gl_FragColor = vec4(0.0,atan(tc.x*4*PI-2*PI,1.0),0.0,1.0); // }else{ From ae16fe81d5321015b8b07f6e2544ec314d23cec0 Mon Sep 17 00:00:00 2001 From: felix <9202@htl.rennweg.at> Date: Mon, 5 Aug 2024 13:22:25 +0200 Subject: [PATCH 08/10] added documentation to the warp and did some cleanup --- assets/shaders/warp.glsl | 194 ++------------------------------------- 1 file changed, 10 insertions(+), 184 deletions(-) diff --git a/assets/shaders/warp.glsl b/assets/shaders/warp.glsl index 227d1f9ff..4dd4c2a26 100644 --- a/assets/shaders/warp.glsl +++ b/assets/shaders/warp.glsl @@ -21,7 +21,7 @@ uniform vec2 u_center;// between 0-1 for x and y uniform float u_depth;// recommended beween 3 and 30, how strong it zooms uniform float u_rotation;// rotation in radians - +// "streches" a value, fe. oldDistance 0.1=>0.23; 0.9=>0.96 (examplevalues with depth=2) float getNewDist(float oldDist, float depthMulti){ float depth=15.0*depthMulti; if (u_depth>1.0){ @@ -64,11 +64,11 @@ vec2 rotate(float oldSlope, float rotation, bool isRightOfCenter){ // This programm takes the following steps: // 1. calculate the line between the current position and the center // 2. get the point on the line where it hits the min/max box (Rectangle with coordiantes: (0|0),(0|1),(1|1),(1|0)) -// 3. calculate the distance in percent to that point from the center -// 4. strech this position exponentially, so that the closer you are to the center, the stronger it streches and goes away from it +// 3. calculate the distance from in percent between the center and that point for my position +// 4. strech this position, so that the closer you are to the center, the stronger it streches and goes away from it // 5. then it rotates the line from 1 // 6. repeat step 2 with the new line -// 7. takes the percentages of the line from 1 and puts them on the line of line 2 +// 7. takes the percentages from point 3 and puts them on the line from point 6 void main() { @@ -76,10 +76,10 @@ void main() { float progress = u_progress; vec2 center = u_center; - if(u_center.x==0.0 && u_center.y==0.0) center=vec2(0.5, 0.5); + if(u_center.x==0.0 && u_center.y==0.0) center=vec2(0.5, 0.8); // float PI = radians(180.0); -// float rotation = getNewDist(progress, -1/10.0) * PI/2.0*16.0; +// float rotation = getNewDist(progress, -0.1) * PI/2.0*16.0; float rotation = getNewDist(progress, -0.1) * u_rotation; @@ -100,7 +100,7 @@ void main() { float maxDistToFurthestCorner=max(max(hypo(center),hypo(center-vec2(0.0,1.0))), max(hypo(center-vec2(1.0)),hypo(center-vec2(1.0,0.0)))); - float outSideMultiplier=maxDist/maxDistToFurthestCorner; //this makes it from a rectangle to a circle + float outSideMultiplier=maxDist/maxDistToFurthestCorner; //this makes it from a rectangle to a ellipse float oldPercent=hypo(distToCenter)/maxDist; // 4. @@ -116,182 +116,8 @@ void main() { //7 - float maxRotatedDist=hypo(borderIntersection-center); - vec2 rotatedPos = center+rotatedBorderToCenter*((hypo(distToCenter)/ maxRotatedDist)); - vec2 rotatedStrechedPos=center+rotatedBorderToCenter*strechedPercent; - + vec2 rotatedPos = center+rotatedBorderToCenter*oldPercent; + vec4 result = texture2D(u_texture, rotatedPos + (strechedPercent-oldPercent) * rotatedBorderToCenter * progress); - vec4 result = texture2D(u_texture, rotatedPos+(rotatedStrechedPos-rotatedPos)*progress); gl_FragColor = result; - -// if(maxDist/maxDistToFurthestCorner> 0.95){ -// gl_FragColor = vec4(1.0,0.0,0.0,1.0); -// } - // if(atan(tc.x*4*PI-2*PI,1.0)>0){ - // gl_FragColor = vec4(0.0,atan(tc.x*4*PI-2*PI,1.0),0.0,1.0); - // }else{ - // gl_FragColor = vec4(atan(-(tc.x*4*PI-2*PI),1.0),0.0,0.0,1.0); - // } -} - - - - - -//another backup - -// -//float getNewDist(float dist, float maxDist){ -// float oldDist=dist/maxDist; -// float depth=35.0; -// if (u_depth>1.0){ -// depth=u_depth; -// } -// float a = pow(2.0, depth); -// a=a/(a-1.0); -// return (a-a/pow(oldDist+1.0, depth));//from 0-1 returns 0-1 but "warped" -//} -// -//float hypo(vec2 oldDist){ -// return sqrt(oldDist.x*oldDist.x+oldDist.y*oldDist.y); -// // return abs(oldDist.x)+abs(oldDist.y); -//} -// -// -//vec2 getBorderIntersection(float k, vec2 pointOnLine, bool rightOfCenter){ -// //the position where the extended line between the center and the pixel hits the (0|0),(0|1),(1|1),(1|0) square -// -// float d = pointOnLine.y - pointOnLine.x * k; -// vec2 borderIntersection; -// if (rightOfCenter) borderIntersection= vec2(1.0, k+d); -// else borderIntersection=vec2(0.0, d); -// -// if (borderIntersection.y>1.0) borderIntersection=vec2((1.0-d) / k, 1.0); -// else if (borderIntersection.y<0.0) borderIntersection=vec2(-d/k, 0.0); -// return borderIntersection; -//} -// -// -//float rotate(float oldSlope, float rotation){ -// float oldRotation=atan(oldSlope, 1.0); -// float newRotation=oldRotation+rotation; -// float pi=radians(180.0); -// // while(newRotation < -pi){ -// // newRotation+=pi; -// // } -// // while(newRotation>pi){ -// // newRotation-=pi; -// // } -// -// return tan(newRotation); -//} -// -//void main() { -// -// float progress = (sin(abs(float(u_time*0.85)))+1.0)/2.0; -// // float progress = (sin(abs(float(u_time*0.05)))+1.0)/2.0; -// // float progress = 1.0; -// // float progress = u_progress; -// -// vec2 center = vec2(0.5, 0.8); -// // vec2 center = u_center; -// -// float PI = radians(float(180)); -// float rotation = 2*PI*progress/4; -// -// // float rotation = PI*1.51; -// // float rotation = 0; -// -// vec2 tc = v_texCoords; -// vec2 distToCenter= tc-center; -// -// float k = distToCenter.y/distToCenter.x; -// -// bool rotationRightOfCenter=tc.x>center.x; -// -// vec2 borderIntersection= getBorderIntersection(k, tc, rotationRightOfCenter); -// float strechedPercent=getNewDist(hypo(distToCenter), hypo(borderIntersection-center)); -// -// float newRot=rotate(k, rotation); -// if ((newRot<0 && k>0)) { -// rotationRightOfCenter=!rotationRightOfCenter; -// } -// -// vec2 rotatedBorderToCenter = getBorderIntersection(newRot, center, rotationRightOfCenter) - center; -// -// // vec2 strechedPos = center+rotatedBorderToCenter*strechedPercent; -// vec2 strechedPos = center+rotatedBorderToCenter*((hypo(distToCenter)/ hypo(borderIntersection-center))); -// -// // vec2 diffOldNew=strechedPos-tc; -// // vec4 result = texture2D(u_texture, tc+diffOldNew*progress); -// vec4 result = texture2D(u_texture, strechedPos); -// -// gl_FragColor = result; -// -// // if(borderIntersection.x>center.x && borderIntersection.y==1.0){ -// // gl_FragColor = vec4(1.0,0.0,0.0,1.0); -// // } -// // if(atan(tc.x*4*PI-2*PI,1.0)>0){ -// // gl_FragColor = vec4(0.0,atan(tc.x*4*PI-2*PI,1.0),0.0,1.0); -// // }else{ -// // gl_FragColor = vec4(atan(-(tc.x*4*PI-2*PI),1.0),0.0,0.0,1.0); -// // } -//} -// - - - - - - - - - - - - - - - -// //bad warp, as a backup or future refernce -// -//float getNewDist(float oldDist){ -// float e=3.0;//steepness of the curve, can be changed -// float a = pow(2, e); -// a=a/(a-1.0); -// return a-a/pow(oldDist+1.0, e);//from 0-1 returns 0-1 but "warped" -//} -// -//void main() { -// -// float progress = abs(sin(abs(float(u_time*0.85)))); -// vec2 center = vec2(0.5, 0.2); -// -// vec2 tc = v_texCoords; -// vec2 distToCenter= tc-center; -// -// vec2 totalDistanceInThatDirection=vec2(0.0); -// if (distToCenter.x<0) totalDistanceInThatDirection.x=-center.x; -// else totalDistanceInThatDirection.x=1-center.x; -// -// if (distToCenter.y<0) totalDistanceInThatDirection.y=-center.y; -// else totalDistanceInThatDirection.y=1-center.y; -// -// vec2 percent=distToCenter/totalDistanceInThatDirection; -// -// vec2 newPercent=vec2(getNewDist(percent.x),getNewDist(percent.y)); -// -// vec2 strechedPos=center+newPercent*totalDistanceInThatDirection; -// -// vec2 diffOldNew=strechedPos-tc; -// -// -// vec4 result = texture2D(u_texture, tc+diffOldNew*progress); -// -// if (sqrt((tc.x-center.x)*(tc.x-center.x)+(tc.y-center.y)*(tc.y-center.y))<0.0018){ -// result=vec4(1.0,0.0,0.0,1.0); -// } -//// result.a=progress; -// gl_FragColor = result; -// // gl_FragColor = vec4(0.0); -//} +} \ No newline at end of file From 300c68b8f0c985c45000b1328caf34dd1e4e2de9 Mon Sep 17 00:00:00 2001 From: Marvin Kurka <8013@htl.rennweg.at> Date: Wed, 14 Aug 2024 00:02:24 +0200 Subject: [PATCH 09/10] warden of time bullet --- assets/config/cards.onj | 19 ++++ assets/screens/game_screen.onj | 2 +- .../fortyfive/game/GameController.kt | 42 ++++++++- .../fortyfive/game/card/Card.kt | 63 ++++++++++++- .../fortyfive/rendering/RenderPipeline.kt | 94 ++++++++++++++++++- .../fortyfive/screen/general/OnjScreen.kt | 11 --- .../general/customActor/ActorInterfaces.kt | 20 ++++ 7 files changed, 234 insertions(+), 17 deletions(-) diff --git a/assets/config/cards.onj b/assets/config/cards.onj index ba67bcc84..6dc14202b 100644 --- a/assets/config/cards.onj +++ b/assets/config/cards.onj @@ -1515,6 +1515,25 @@ cards: [ tags: ["pool1", "rarity2"], price: 50, }, + { + name: "wardenOfTimeBullet", + title: "Warden Of Time Bullet", + flavourText: "", + description: "3 revolver rotations after that this gets shot: destroy the bullet in slot 5 " + slot.5 + " and this bullet gets put there instead. If there is no bullet, nothing gets destroyed and this Bullet just appears.", + baseDamage: 4, + coverValue: 0, + traitEffects: [ "wardenOfTime" ], + rotation: $Right { amount: 1 }, + highlightType: "standard", + effects: [ + ], + forceLoadCards: [], + dark: false, + cost: 2, + type: $Bullet { }, + tags: ["pool2", "rarity1"], + price: 50, + }, ], diff --git a/assets/screens/game_screen.onj b/assets/screens/game_screen.onj index 55278c715..a14f187ca 100644 --- a/assets/screens/game_screen.onj +++ b/assets/screens/game_screen.onj @@ -65,7 +65,7 @@ assets: { "holster_sound", "money_sound", "revolver_drum_sound", "parry_sound", "swoosh_sound", "button_2_sound", "card_destroy_sound", "holster_remove_sound", "metal_on_metal_sound", - "screen_shake_popout_shader", + "screen_shake_popout_shader", "warp_shader", "map_theme", "encounter_theme", diff --git a/core/src/com/fourinachamber/fortyfive/game/GameController.kt b/core/src/com/fourinachamber/fortyfive/game/GameController.kt index 330201baa..f46c77f99 100644 --- a/core/src/com/fourinachamber/fortyfive/game/GameController.kt +++ b/core/src/com/fourinachamber/fortyfive/game/GameController.kt @@ -139,6 +139,10 @@ class GameController(onj: OnjNamedObject) : ScreenController() { private var selectedCard: Card? = null + private val _limbo: MutableList = mutableListOf() + val limbo: List + get() = _limbo + /** * counts up every turn; starts at 0, but gets immediately incremented to one */ @@ -368,6 +372,13 @@ class GameController(onj: OnjNamedObject) : ScreenController() { updateStatusEffects() updateGameAnimations() updateTutorialText() + val limboTimeline = _limbo.mapNotNull { it.updateInLimbo(this) } + if (limboTimeline.isEmpty()) return + appendMainTimeline(limboTimeline.collectTimeline()) + } + + fun removeFromLimbo(card: Card) { + _limbo.remove(card) } private fun updateTutorialText() { @@ -553,6 +564,30 @@ class GameController(onj: OnjNamedObject) : ScreenController() { ) }) + fun placeBulletInRevolverDirect(card: Card, slot: Int): Timeline = Timeline.timeline { + val triggerInfo = TriggerInformation(sourceCard = card, controller = this@GameController) + action { + revolver.setCard(slot, card) + card.onEnter(this@GameController) + } + includeLater( + { + encounterModifiers + .mapNotNull { it.executeAfterBulletWasPlacedInRevolver(card, this@GameController) } + .collectTimeline() + }, + { true } + ) + includeLater( + { checkEffectsSingleCard(Trigger.ON_ENTER, card, triggerInfo) }, + { true } + ) + includeLater( + { checkEffectsActiveCards(Trigger.ON_ANY_CARD_ENTER, triggerInfo) }, + { true } + ) + } + fun putCardFromRevolverBackInHand(card: Card) { FortyFiveLogger.debug(logTag, "returning card $card from the revolver to the hand") revolver.removeCard(card) @@ -707,13 +742,15 @@ class GameController(onj: OnjNamedObject) : ScreenController() { curScreen.leaveState(showEnemyAttackPopupScreenState) gameRenderPipeline.stopParryEffect() if (parryCard.shouldRemoveAfterShot(this@GameController)) { - if (!parryCard.isUndead) { + if (!parryCard.isUndead && !parryCard.isWardenOfTime) { SoundPlayer.situation("orb_anim_playing", curScreen) gameRenderPipeline.addOrbAnimation(cardOrbAnim(parryCard.actor)) } revolver.removeCard(parryCard) if (parryCard.isUndead) { cardHand.addCard(parryCard) + } else if (parryCard.isWardenOfTime) { + _limbo.add(parryCard) } else { putCardAtBottomOfStack(parryCard) } @@ -861,7 +898,7 @@ class GameController(onj: OnjNamedObject) : ScreenController() { ) action { if (cardToShoot.shouldRemoveAfterShot(this@GameController)) { - if (!cardToShoot.isUndead) { + if (!cardToShoot.isUndead && !cardToShoot.isWardenOfTime) { putCardAtBottomOfStack(cardToShoot) SoundPlayer.situation("orb_anim_playing", curScreen) gameRenderPipeline.addOrbAnimation(cardOrbAnim(cardToShoot.actor)) @@ -869,6 +906,7 @@ class GameController(onj: OnjNamedObject) : ScreenController() { revolver.removeCard(cardToShoot) } if (cardToShoot.isUndead) cardHand.addCard(cardToShoot) + if (cardToShoot.isWardenOfTime) _limbo.add(cardToShoot) cardToShoot.afterShot(this@GameController) } } diff --git a/core/src/com/fourinachamber/fortyfive/game/card/Card.kt b/core/src/com/fourinachamber/fortyfive/game/card/Card.kt index 140db8185..251cbed6f 100644 --- a/core/src/com/fourinachamber/fortyfive/game/card/Card.kt +++ b/core/src/com/fourinachamber/fortyfive/game/card/Card.kt @@ -153,6 +153,8 @@ class Card( private set var isAlwaysAtTop: Boolean = false private set + var isWardenOfTime: Boolean = false + private set fun shouldRemoveAfterShot(controller: GameController): Boolean = !( (isEverlasting && !controller.encounterModifiers.any { it.disableEverlasting() }) || @@ -255,6 +257,59 @@ class Card( } } + private var wardenOfTimeRotationCounter: Int = -1 + + fun updateInLimbo(controller: GameController): Timeline? { + if (!isWardenOfTime || wardenOfTimeRotationCounter == -1) return null + if (wardenOfTimeRotationCounter + 4 > controller.revolverRotationCounter) return null + wardenOfTimeRotationCounter = -1 + val growAction = ScaleToAction() + growAction.duration = 0.3f + growAction.setScale(3f) + growAction.interpolation = Interpolation.pow5In + val shrinkAction = ScaleToAction() + shrinkAction.duration = 0.5f + shrinkAction.setScale(1f) + shrinkAction.interpolation = Interpolation.smoother + + return Timeline.timeline { + action { + controller.removeFromLimbo(this@Card) + } + includeLater( + { controller.destroyCardTimeline(controller.revolver.getCardInSlot(5)!!) }, + { controller.revolver.getCardInSlot(5) != null } + ) + parallelActions( + Timeline.timeline { + delay(800) + parallelActions( + controller.placeBulletInRevolverDirect(this@Card, 5).asAction(), + controller.gameRenderPipeline.liftActor(1000, actor).asAction(), + Timeline.timeline { + action { + actor.setScale(0.3f) + actor.addAction(growAction) + } + delayUntil { growAction.isComplete } + action { + actor.removeAction(growAction) + actor.addAction(shrinkAction) + } + delayUntil { shrinkAction.isComplete } + action { actor.removeAction(shrinkAction) } + }.asAction(), + Timeline.timeline { + delay(250) + include(controller.gameRenderPipeline.getScreenShakePopoutTimeline()) + }.asAction() + ) + }.asAction(), + controller.gameRenderPipeline.getTimeWarpTimeline().asAction() + ) + } + } + fun activeModifiers(controller: GameController): List = modifiers.filter { it.activeChecker(controller) } @@ -268,6 +323,7 @@ class Card( * called by gameScreenController when the card was shot */ fun afterShot(controller: GameController) { + wardenOfTimeRotationCounter = controller.revolverRotationCounter if (shouldRemoveAfterShot(controller)) leaveGame() if (protectingModifiers.isNotEmpty()) { val effect = protectingModifiers.first() @@ -621,6 +677,7 @@ class Card( "rotten" -> card.isRotten = true "alwaysAtBottom" -> card.isAlwaysAtBottom = true "alwaysAtTop" -> card.isAlwaysAtTop = true + "wardenOfTime" -> card.isWardenOfTime = true else -> throw RuntimeException("unknown trait effect $effect") } @@ -666,13 +723,16 @@ class CardActor( override val screen: OnjScreen, val enableHoverDetails: Boolean ) : Widget(), ZIndexActor, KeySelectableActor, DisplayDetailsOnHoverActor, HoverStateActor, HasOnjScreen, StyledActor, - OffSettable, AnimationActor { + OffSettable, AnimationActor, LiftableActor { override val actor: Actor = this override var actorTemplate: String = "card_hover_detail" // TODO: fix override var detailActor: Actor? = null + override var inLift: Boolean = false + override var inLiftRender: Boolean = false + override var inAnimation: Boolean = false override var mainHoverDetailActor: String? = "cardHoverDetailMain" @@ -781,6 +841,7 @@ class CardActor( } override fun draw(batch: Batch?, parentAlpha: Float) { + if (!shouldRender) return validate() if (drawPixmapMessage?.isFinished ?: false) { finishPixmapDrawing() diff --git a/core/src/com/fourinachamber/fortyfive/rendering/RenderPipeline.kt b/core/src/com/fourinachamber/fortyfive/rendering/RenderPipeline.kt index fd990a354..17b9249e9 100644 --- a/core/src/com/fourinachamber/fortyfive/rendering/RenderPipeline.kt +++ b/core/src/com/fourinachamber/fortyfive/rendering/RenderPipeline.kt @@ -10,8 +10,8 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.glutils.FrameBuffer import com.badlogic.gdx.graphics.glutils.ShapeRenderer import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType -import com.badlogic.gdx.math.CatmullRomSpline -import com.badlogic.gdx.math.Vector2 +import com.badlogic.gdx.math.* +import com.badlogic.gdx.scenes.scene2d.Actor import com.badlogic.gdx.scenes.scene2d.utils.Drawable import com.badlogic.gdx.utils.Align import com.badlogic.gdx.utils.Disposable @@ -20,12 +20,15 @@ import com.badlogic.gdx.utils.TimeUtils import com.badlogic.gdx.utils.viewport.ExtendViewport import com.fourinachamber.fortyfive.game.GraphicsConfig import com.fourinachamber.fortyfive.game.UserPrefs +import com.fourinachamber.fortyfive.game.card.Card import com.fourinachamber.fortyfive.screen.Resource import com.fourinachamber.fortyfive.screen.ResourceHandle import com.fourinachamber.fortyfive.screen.ResourceManager import com.fourinachamber.fortyfive.screen.general.OnjScreen +import com.fourinachamber.fortyfive.screen.general.customActor.LiftableActor import com.fourinachamber.fortyfive.utils.* import java.lang.Long.max +import kotlin.math.abs import kotlin.math.absoluteValue interface Renderable { @@ -74,6 +77,11 @@ open class RenderPipeline( } private val gaussianBlurShader: BetterShader by gaussianBlurShaderDelegate + private val warpShaderDelegate = lazy { + ResourceManager.get(screen, "warp_shader") + } + private val warpShader: BetterShader by warpShaderDelegate + private var orbFinisesAt: Long = -1 private val isOrbAnimActive: Boolean get() = TimeUtils.millis() <= orbFinisesAt @@ -92,6 +100,41 @@ open class RenderPipeline( shaderPostProcessingStep(screenShakePopoutShader) } + private var warpStartTime: Long = 0 + private var warpDuration: Int = 0 + + private val warpPostProcessingStep: () -> Unit = lambda@{ + val time = TimeUtils.millis() + val passedTime = time - warpStartTime + val absoluteProgress = passedTime.toFloat() / warpDuration.toFloat() + val progress = (1f - abs(absoluteProgress - 0.5f) - 0.5f) * 2f + val shader = warpShader + val (_, inactive) = frameBufferManager.getPingPongFrameBuffers("pp") ?: return@lambda + batch.flush() + batch.shader = shader.shader + shader.shader.bind() + shader.prepare(screen) + + var interpolated: Float = progress + interpolated = Interpolation.smoother.apply(interpolated) + interpolated = Interpolation.swing.apply(interpolated) + + shader.shader.setUniformf("u_progress", interpolated) + shader.shader.setUniformf("u_center", Vector2(0.5f, 0.38f)) + shader.shader.setUniformf("u_depth", 2.9f) + shader.shader.setUniformf("u_rotation", 0.19f * interpolated) + batch.enableBlending() + batch.draw( + inactive.colorBufferTexture, + 0f, 0f, + screen.viewport.worldWidth, + screen.viewport.worldHeight, + 0f, 0f, 1f, 1f // flips the y-axis + ) + batch.flush() + batch.shader = null + } + private val fadeToBlackTask: () -> Unit = { val now = TimeUtils.millis() screen.viewport.apply() @@ -112,6 +155,52 @@ open class RenderPipeline( // postPreprocessingSteps.add(shaderPostProcessingStep(ResourceManager.get(screen, "test_shader"))) } + fun liftActor(time: Int, actor: LiftableActor): Timeline = Timeline.timeline { + val task = liftActorTask(actor.actor, actor) + action { + actor.inLift = true + lateTasks.add(task) + } + delay(time) + action { + actor.inLift = false + lateTasks.remove(task) + } + } + + private fun liftActorTask(actor: Actor, liftableActor: LiftableActor): () -> Unit = { + screen.viewport.apply() + shapeRenderer.projectionMatrix = screen.viewport.camera.combined + + val (x, y) = actor.localToStageCoordinates(Vector2(0f, 0f)) + + val oldTransform = batch.transformMatrix.cpy() + val worldTransform = Affine2() + worldTransform.set(oldTransform) + worldTransform.translate(x - actor.x, y - actor.y) + val computed = Matrix4() + computed.set(worldTransform) + batch.transformMatrix = computed + + liftableActor.inLiftRender = true + actor.draw(batch, 1f) + liftableActor.inLiftRender = false + batch.transformMatrix = oldTransform + } + + fun getTimeWarpTimeline(): Timeline = Timeline.timeline { + val duration = 2000 + action { + warpStartTime = TimeUtils.millis() + warpDuration = duration + postPreprocessingSteps.add(warpPostProcessingStep) + } + delay(duration) + action { + postPreprocessingSteps.remove(warpPostProcessingStep) + } + } + fun getFadeToBlackTimeline(fadeDuration: Int, stayBlack: Boolean = false): Timeline = Timeline.timeline { action { this@RenderPipeline.fadeDuration = fadeDuration @@ -386,6 +475,7 @@ open class RenderPipeline( if (alphaReductionShaderDelegate.isInitialized()) alphaReductionShader.dispose() if (screenShakeShaderDelegate.isInitialized()) screenShakeShader.dispose() if (screenShakePopoutShaderDelegate.isInitialized()) screenShakePopoutShader.dispose() + if (warpShaderDelegate.isInitialized()) warpShader.dispose() } data class OrbAnimation( diff --git a/core/src/com/fourinachamber/fortyfive/screen/general/OnjScreen.kt b/core/src/com/fourinachamber/fortyfive/screen/general/OnjScreen.kt index a27b0cc23..a49142329 100644 --- a/core/src/com/fourinachamber/fortyfive/screen/general/OnjScreen.kt +++ b/core/src/com/fourinachamber/fortyfive/screen/general/OnjScreen.kt @@ -424,10 +424,6 @@ open class OnjScreen @MainThreadOnly constructor( } - private val warpShader: BetterShader by lazy { - ResourceManager.get(this, "warp_shader") - } - @MainThreadOnly override fun render(delta: Float) = try { // Thread.sleep(800) //TODO remove // (please don't, its great to find this method) @@ -437,14 +433,7 @@ open class OnjScreen @MainThreadOnly constructor( if (stage.batch.isDrawing) stage.batch.end() stage.viewport.apply() doRenderTasks(earlyRenderTasks, additionalEarlyRenderTasks) - warpShader.let { - stage.batch.flush() - it.shader.bind() - it.prepare(this) - stage.batch.shader = it.shader - } stage.draw() - stage.batch.flush() doRenderTasks(lateRenderTasks, additionalLateRenderTasks) styleManagers .filter { it !in oldStyleManagers } diff --git a/core/src/com/fourinachamber/fortyfive/screen/general/customActor/ActorInterfaces.kt b/core/src/com/fourinachamber/fortyfive/screen/general/customActor/ActorInterfaces.kt index 5a22a1bdc..2c76aed5e 100644 --- a/core/src/com/fourinachamber/fortyfive/screen/general/customActor/ActorInterfaces.kt +++ b/core/src/com/fourinachamber/fortyfive/screen/general/customActor/ActorInterfaces.kt @@ -333,3 +333,23 @@ interface ActorWithAnimationSpawners { inline fun ActorWithAnimationSpawners.findAnimationSpawner(): T? = animationSpawners.find { it is T } as? T + +interface LiftableActor { + + var inLift: Boolean + var inLiftRender: Boolean + + val shouldRender: Boolean + get() = !inLift || (inLift && inLiftRender) + + val actor: Actor + + fun beginLift() { + inLift = true + } + + fun endLift() { + inLift = false + } + +} From 0489dd31b52727bf289a5669490be566d19ca876 Mon Sep 17 00:00:00 2001 From: Marvin Kurka <8013@htl.rennweg.at> Date: Wed, 14 Aug 2024 09:53:03 +0200 Subject: [PATCH 10/10] made warden of time bullet dark --- assets/config/cards.onj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/config/cards.onj b/assets/config/cards.onj index 6dc14202b..8a617f3fa 100644 --- a/assets/config/cards.onj +++ b/assets/config/cards.onj @@ -1528,7 +1528,7 @@ cards: [ effects: [ ], forceLoadCards: [], - dark: false, + dark: true, cost: 2, type: $Bullet { }, tags: ["pool2", "rarity1"],