package com.mediamonks.googleflip.pages.game.physics.levels;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.util.Log;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.mediamonks.googleflip.BuildConfig;
import com.mediamonks.googleflip.GoogleFlipGameApplication;
import com.mediamonks.googleflip.R;
import org.andengine.extension.physics.box2d.PhysicsFactory;
import org.andengine.extension.physics.box2d.PhysicsWorld;
import org.andengine.extension.physics.box2d.util.Vector2Pool;
import temple.core.utils.PaintUtils;
/**
* Base class for game levels
*/
public abstract class AbstractGameLevel {
private static final String TAG = AbstractGameLevel.class.getSimpleName();
private static final float DEG2RAD = (float) (Math.PI / 180.0);
private Bitmap _bitmap;
private Canvas _bitmapCanvas;
private Bitmap _tmpBitmap;
private Canvas _tmpCanvas;
private Paint _bitmapPaint;
private Paint _erasePaint;
private int _circleThickness = 30;
protected int _width;
protected int _height;
protected boolean _isInitialized;
protected float _density;
protected float _scaledDensity;
protected float _originalWidth = 1080;
protected float _originalHeight = 1920;
protected float _scale;
public void init(int width, int height, float scale, float density) {
_width = width;
_height = height;
_scale = scale;
_density = density;
_scaledDensity = _density / _scale;
_bitmap = Bitmap.createBitmap(_width, _height, Bitmap.Config.ARGB_8888);
_bitmapCanvas = new Canvas(_bitmap);
_bitmapPaint = PaintUtils.createFillPaint(GoogleFlipGameApplication.sContext.getResources().getColor(R.color.grey));
_erasePaint = PaintUtils.createFillPaint(GoogleFlipGameApplication.sContext.getResources().getColor(R.color.red));
_erasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
_isInitialized = true;
}
protected Vector2 getScaledVector(int x, int y) {
return Vector2Pool.obtain((float) x * _scale, _height - (float) y * _scale);
}
protected void assertInitialized() {
if (BuildConfig.DEBUG && !_isInitialized) throw new AssertionError("Call init first");
}
/**
* Utility methods
*/
protected void createBox(PhysicsWorld world, FixtureDef fixtureDef, float x, float y, float width, float height) {
createBox(world, fixtureDef, x, y, width, height, 0);
}
protected void createBox(PhysicsWorld world, FixtureDef fixtureDef, float x, float y, float width, float height, float rotation) {
createBoxBody(world, fixtureDef, x, y, width, height, rotation);
drawBox(x, y, width, height, rotation);
}
protected void createOpenCircle(PhysicsWorld world, FixtureDef fixtureDef, float startAngle, float endAngle,
float radius, float centerX, float centerY, int segmentCount) {
createOpenCircleBody(world, fixtureDef, startAngle, endAngle, radius, centerX, centerY, segmentCount);
drawOpenCircle(startAngle, endAngle, radius, centerX, centerY);
}
protected void createOpenCircle(PhysicsWorld world, FixtureDef fixtureDef, float startAngle, float endAngle,
float radius, float centerX, float centerY, int segmentCount, float startAngleOffset, float endAngleOffset) {
createOpenCircleBody(world, fixtureDef, startAngle, endAngle, radius, centerX, centerY, segmentCount);
drawOpenCircle(startAngle, endAngle, radius, centerX, centerY, startAngleOffset, endAngleOffset);
}
protected void createBoxBody(PhysicsWorld world, FixtureDef fixtureDef, float x, float y, float width, float height) {
createBoxBody(world, fixtureDef, x, y, width, height, 0);
}
protected void createBoxBody(PhysicsWorld world, FixtureDef fixtureDef, float x, float y, float width, float height, float rotation) {
PhysicsFactory.createBoxBody(world, x * _scale, _height - y * _scale, width * _scale, height * _scale, rotation,
BodyDef.BodyType.StaticBody, fixtureDef);
}
protected void createOpenCircleBody(PhysicsWorld world, FixtureDef fixtureDef, float startAngle, float endAngle,
float radius, float centerX, float centerY, int segmentCount) {
createOpenCircleBody(world, fixtureDef, startAngle, endAngle, radius, radius - _circleThickness, centerX, centerY, segmentCount);//18
}
protected void createOpenCircleBody(PhysicsWorld world, FixtureDef fixtureDef, float startAngle, float endAngle,
float radius, float innerRadius, float centerX, float centerY, int segmentCount) {
float angleStep = (endAngle - startAngle) / (float) segmentCount;
float curAngle = startAngle + angleStep / 2;
float width = 3;
float height = (radius - innerRadius);
float x;
float y;
float angleRad;
float radiusCorrection = (float) Math.cos(angleStep * DEG2RAD / 2);
while (curAngle < endAngle) {
float angleLeft = (curAngle - angleStep / 2) * DEG2RAD;
float xLeft = centerX + radius * (float) Math.cos(angleLeft);
float yLeft = centerY + radius * (float) Math.sin(angleLeft);
float angleRight = (curAngle + angleStep / 2) * DEG2RAD;
float xRight = centerX + radius * (float) Math.cos(angleRight);
float yRight = centerY + radius * (float) Math.sin(angleRight);
float dx = xRight - xLeft;
float dy = yRight - yLeft;
width = height / segmentCount + (float) (Math.sqrt(dx * dx + dy * dy));
angleRad = curAngle * DEG2RAD;
x = centerX + (radius * radiusCorrection) * (float) Math.cos(angleRad);
y = centerY + (radius * radiusCorrection) * (float) Math.sin(angleRad);
createBoxBody(world, fixtureDef, x, y, width, height, 90 - curAngle);
curAngle += angleStep;
}
}
protected void createWave(PhysicsWorld world, FixtureDef fixtureDef, float amplitude, float frequency,
float x, float y, float waveLength, float waveStart) {
float steps = 100;
for (int i = 0; i < steps; i++) {
float angle = 2 * (float) Math.PI * frequency * (i + waveStart) / steps;
float sin = (float) Math.sin(angle);
createBox(world, fixtureDef, x + waveLength * (i / steps), y - amplitude * sin, 3, 40);
}
}
/**
* DRAW
*/
protected void drawBox(float x, float y, float width, float height) {
drawBox(x, y, width, height, 0);
}
protected void drawBox(float x, float y, float width, float height, float rotation) {
float left = (x - (width * .5f)) * _scale;
float top = (y - (height * .5f)) * _scale;
float right = left + (width * _scale);
float bottom = top + (height * _scale);
_bitmapCanvas.save();
_bitmapCanvas.rotate(-rotation, x * _scale, y * _scale);
_bitmapCanvas.drawRect(left, top, right, bottom, _bitmapPaint);
_bitmapCanvas.restore();
}
protected void drawOpenCircle(float startAngle, float endAngle, float radius, float centerX, float centerY) {
drawOpenCircle(startAngle, endAngle, radius, radius - _circleThickness, centerX, centerY, 0, 0);//18
}
protected void drawOpenCircle(float startAngle, float endAngle, float radius, float centerX, float centerY,
float startAngleOffset, float endAngleOffset) {
drawOpenCircle(startAngle, endAngle, radius, radius - _circleThickness, centerX, centerY, startAngleOffset, endAngleOffset);//18
}
protected void drawOpenCircle(float startAngle, float endAngle, float radius, float innerRadius, float centerX, float centerY, float startAngleOffset,
float endAngleOffset) {
float height = (radius - innerRadius);
radius += height * .5f;
startAngle += startAngleOffset;
endAngle += endAngleOffset;
float left = (centerX - radius) * _scale;
float top = (centerY - radius) * _scale;
float right = (centerX + radius) * _scale;
float bottom = (centerY + radius) * _scale;
radius -= height * .5f;
float thickness = (radius - innerRadius) * _scale;
_tmpBitmap = Bitmap.createBitmap(_width, _height, Bitmap.Config.ARGB_8888);
_tmpCanvas = new Canvas(_tmpBitmap);
_tmpCanvas.drawArc(new RectF(left, top, right, bottom), startAngle, endAngle - startAngle, true, _bitmapPaint);
_tmpCanvas.drawOval(new RectF(left + thickness, top + thickness, right - thickness, bottom - thickness), _erasePaint);
_bitmapCanvas.drawBitmap(_tmpBitmap, 0, 0, _bitmapPaint);
}
protected void drawPath(Point[] points) {
Path path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
int total = points.length;
for (int i = 0; i < total; i++) {
Point point = points[i];
if (i == 0) {
path.moveTo(point.x * _scale, point.y * _scale);
} else {
path.lineTo(point.x * _scale, point.y * _scale);
}
}
path.close();
_bitmapCanvas.drawPath(path, _bitmapPaint);
}
/**
* Default level duration
*/
public float getLevelDuration() {
return 25;
}
/**
* Background bitmap
*
* @return Bitmap
*/
public Bitmap getBackground() {
return _bitmap;
}
public void dispose() {
_bitmap = null;
_tmpBitmap = null;
_bitmapCanvas = null;
_tmpCanvas = null;
_bitmapPaint = null;
_erasePaint = null;
}
}