package com.gebauz.pingk.effects;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
import com.gebauz.Bauzoid.graphics.model.GeometryUtil;
import com.gebauz.Bauzoid.graphics.model.SimpleGeometry;
import com.gebauz.Bauzoid.graphics.renderstates.RenderStates;
import com.gebauz.Bauzoid.graphics.renderstates.BlendingStates.BlendingMode;
import com.gebauz.Bauzoid.graphics.shader.ShaderProgram;
import com.gebauz.Bauzoid.graphics.shader.ShaderUniform;
import com.gebauz.Bauzoid.graphics.shader.ShaderUtil;
import com.gebauz.Bauzoid.math.MathUtil;
import com.gebauz.Bauzoid.math.Matrix4;
import com.gebauz.Bauzoid.math.Vector2;
import com.gebauz.pingk.entities.Entity;
import com.gebauz.pingk.game.GameConsts;
import com.gebauz.pingk.game.GameLogic;
/** Handles all powerup effects that are done via offscreen rendering/postprocessing. */
public class OffscreenEffect
extends Entity
{
private FrameBuffer mOffscreen =
null;
private SimpleGeometry mQuad =
null;
private ShaderProgram mShader =
null;
private ShaderUniform mTextureHandle =
null;
private ShaderUniform mDx =
null;
private ShaderUniform mDy =
null;
private ShaderUniform mAlpha =
null;
private ShaderUniform mWaveMax =
null;
private ShaderUniform mMoveX =
null;
private ShaderUniform mMoveY =
null;
private ShaderUniform mTime =
null;
private ShaderUniform mFlashFactor =
null;
private float mCurrentMosaicFade = 0.0f
;
private float mPixelationFactor = 1.0f
;
private float mCurrentFlowerFade = 0.0f
;
private float mMoveDirX = 0.0f
;
private float mMoveDirY = 0.0f
;
private float mShaderTime = 0.0f
;
private float mFlashTime = -1.0f
;
private float mTotalFlashTime = 1.0f
;
public OffscreenEffect
(GameLogic gameLogic
)
{
super(gameLogic
);
}
@
Override
public void init
()
{
//mOffscreen = new FrameBuffer(Pixmap.Format.RGB565, GameConsts.POWERUP_MOSAIC_OFFSCREEN_WIDTH, GameConsts.POWERUP_MOSAIC_OFFSCREEN_HEIGHT, false);
int w =
Math.
min(getGraphics
().
getWidth(),
800);
int h =
Math.
min(getGraphics
().
getHeight(),
480);
mOffscreen =
new FrameBuffer
(Pixmap.
Format.
RGB565, w, h,
false);
//mQuad = GeometryUtil.createQuad(getGraphics(), 0.0f, 0.0f, GameConsts.VIRTUAL_SCREEN_WIDTH, getGameLogic().getPlayField().getVirtualHeight());
//mQuad = GeometryUtil.createSubdividedQuad(getGraphics(), 0.0f, 0.0f, GameConsts.VIRTUAL_SCREEN_WIDTH, GameConsts.VIRTUAL_SCREEN_HEIGHT, 5, 4);
mQuad = GeometryUtil.
createSubdividedQuad(getGraphics
(), -1.0f, 1.0f, 1.0f, -1.0f,
5,
4);
//ShaderUtil.verbose = true;
mShader = ShaderUtil.
createShaderFromFile(getGraphics
(), Gdx.
files.
internal("data/shaders/offscreen.vert"),
Gdx.
files.
internal("data/shaders/offscreen.frag"));
if (mShader
!=
null)
{
mTextureHandle = mShader.
getUniform("uDiffuse");
mDx = mShader.
getUniform("uDx");
mDy = mShader.
getUniform("uDy");
mAlpha = mShader.
getUniform("uAlpha");
mMoveX = mShader.
getUniform("uMoveX");
mMoveY = mShader.
getUniform("uMoveY");
mTime = mShader.
getUniform("uTime");
mWaveMax = mShader.
getUniform("uWaveMax");
mFlashFactor = mShader.
getUniform("uFlashFactor");
}
mCurrentMosaicFade = 0.0f
;
mShaderTime = 0.0f
;
}
@
Override
public void exit
()
{
if (mShader
!=
null)
{
mTextureHandle =
null;
mDx =
null;
mDy =
null;
mAlpha =
null;
mTime =
null;
mFlashFactor =
null;
mShader.
dispose();
mShader =
null;
}
if (mOffscreen
!=
null)
{
mOffscreen.
dispose();
mOffscreen =
null;
}
if (mQuad
!=
null)
{
mQuad.
dispose();
mQuad =
null;
}
}
@
Override
public void update
(float deltaTime
)
{
mFlashTime -= deltaTime
;
mShaderTime += deltaTime
;
updateMosaic
(deltaTime
);
updateSlowMo
(deltaTime
);
updateFlower
(deltaTime
);
}
public void updateMosaic
(float deltaTime
)
{
if (getGameLogic
().
getPowerUpLogic().
isMosaicActive())
{
float mosaicTime = getGameLogic
().
getPowerUpLogic().
getMoasicTime();
float mosaicFade = 1.0f
;
if (mosaicTime
< GameConsts.
POWERUP_MOSAIC_FADE_TIME)
{
mosaicFade = MathUtil.
clamp(mosaicTime / GameConsts.
POWERUP_MOSAIC_FADE_TIME, 0.0f, 1.0f
);
}
else if (mosaicTime
> (GameConsts.
POWERUP_MOSAIC_TIME - GameConsts.
POWERUP_MOSAIC_FADE_TIME))
{
float v = mosaicTime -
(GameConsts.
POWERUP_MOSAIC_TIME - GameConsts.
POWERUP_MOSAIC_FADE_TIME);
mosaicFade = 1.0f - MathUtil.
clamp(v / GameConsts.
POWERUP_MOSAIC_FADE_TIME, 0.0f, 1.0f
);
}
// go to target
float diff = mosaicFade - mCurrentMosaicFade
;
mCurrentMosaicFade +=
(diff
* deltaTime
* GameConsts.
POWERUP_MOSAIC_FADE_TIME);
mPixelationFactor = 1.0f +
(float)Math.
floor(14.0f
* mCurrentMosaicFade
) / 2.0f
;
}
else
{
mPixelationFactor = 1.0f
;
}
}
public void updateSlowMo
(float deltaTime
)
{
if (getGameLogic
().
getPowerUpLogic().
isSlowMoActive())
{
Vector2 move = getGameLogic
().
getBall().
getMoveDirection();
move.
normalize();
float diff = move.
x - mMoveDirX
;
mMoveDirX +=
(diff
* deltaTime
* 2.0f
);
diff = move.
y - mMoveDirY
;
mMoveDirY +=
(diff
* deltaTime
* 2.0f
);
}
else
{
mMoveDirX = 0.0f
;
mMoveDirY = 0.0f
;
}
}
public void updateFlower
(float deltaTime
)
{
if (getGameLogic
().
getPowerUpLogic().
isFlowerActive())
{
float flowerTime = getGameLogic
().
getPowerUpLogic().
getFlowerTime();
float flowerFade = 1.0f
;
if (flowerTime
< GameConsts.
POWERUP_FLOWER_FADE_TIME)
{
flowerFade = MathUtil.
clamp(flowerTime / GameConsts.
POWERUP_FLOWER_FADE_TIME, 0.0f, 1.0f
);
}
else if (flowerTime
> (GameConsts.
POWERUP_FLOWER_TIME - GameConsts.
POWERUP_FLOWER_FADE_TIME))
{
float v = flowerTime -
(GameConsts.
POWERUP_MOSAIC_TIME - GameConsts.
POWERUP_FLOWER_FADE_TIME);
flowerFade = 1.0f - MathUtil.
clamp(v / GameConsts.
POWERUP_FLOWER_FADE_TIME, 0.0f, 1.0f
);
}
// go to target
float diff = flowerFade - mCurrentFlowerFade
;
mCurrentFlowerFade +=
(diff
* deltaTime
* GameConsts.
POWERUP_FLOWER_FADE_TIME);
}
else
{
mCurrentFlowerFade = 0.0f
;
}
}
@
Override
public void render
()
{
RenderStates rs = getGraphics
().
renderStates;
//Matrix4 modelMatrix = Matrix4.createIdentity();
//rs.pushModelMatrix();
{
//rs.model = modelMatrix;
mShader.
activate();
{
mTextureHandle.
set(0);
rs.
getTextureStage(0).
bindTexture(mOffscreen.
getColorBufferTexture());
mDx.
set(mPixelationFactor
* (1.0f / GameConsts.
VIRTUAL_SCREEN_WIDTH));
mDy.
set(mPixelationFactor
* (1.0f / GameConsts.
VIRTUAL_SCREEN_HEIGHT));
mAlpha.
set(1.0f
);
//mMoveX.set(mMoveDirX / 100.0f);
//mMoveY.set(mMoveDirY / 100.0f);
if (mTime
!=
null)
mTime.
set(mShaderTime
);
if (mWaveMax
!=
null)
mWaveMax.
set(mCurrentFlowerFade
* GameConsts.
POWERUP_FLOWER_WAVE_MAX);
float flashAmount = MathUtil.
clamp(mFlashTime/mTotalFlashTime, 0.0f, 1.0f
);
if (mFlashFactor
!=
null)
mFlashFactor.
set(flashAmount
);
rs.
blending.
setEnabled(true);
rs.
blending.
setBlendingMode(BlendingMode.
ALPHABLEND);
rs.
culling.
setEnabled(false);
rs.
depthTest.
setEnabled(false);
rs.
activate();
{
mQuad.
render();
}
rs.
deactivate();
}
mShader.
deactivate();
}
//rs.popModelMatrix();
}
/** Called before the game is rendered. */
public void beginRenderToTexture
()
{
mOffscreen.
begin();
getGraphics
().
clear(0.05f, 0.05f, 0.05f, 0.0f
);
getGraphics
().
renderStates.
pushProjectionMatrix();
getGraphics
().
renderStates.
projection = Matrix4.
createOrtho(
0.0f,
GameConsts.
VIRTUAL_SCREEN_WIDTH-
1,
GameConsts.
VIRTUAL_SCREEN_HEIGHT-
1,
0.0f,
0.0f,
1.0f
);
}
/** Called after the game is rendered. */
public void endRenderToTexture
()
{
mOffscreen.
end();
getGraphics
().
renderStates.
popProjectionMatrix();
}
public void startFlash
(float time
)
{
mFlashTime = time
;
mTotalFlashTime = time
;
}
}