diff --git a/core/src/com/riiablo/entity/DirectionUtils.java b/core/src/com/riiablo/entity/DirectionUtils.java new file mode 100644 index 00000000..86f1c06d --- /dev/null +++ b/core/src/com/riiablo/entity/DirectionUtils.java @@ -0,0 +1,216 @@ +package com.riiablo.entity; + +import com.badlogic.gdx.math.MathUtils; + +public class DirectionUtils { + private DirectionUtils() {} + + public static final int SOUTH = 0; + public static final int WEST = 1; + public static final int NORTH = 2; + public static final int EAST = 3; + public static final int DOWN = 4; + public static final int LEFT = 5; + public static final int UP = 6; + public static final int RIGHT = 7; + + static final float RADIANS_4[] = { + MathUtils.atan2(-4, 0), + MathUtils.atan2( 0, 8), + MathUtils.atan2( 4, 0), + MathUtils.atan2( 0, -8), + }; + static final int DIRS_4M[] = {1, 2, 3, 0}; + static final float RADIANS_4M[]; + static { + RADIANS_4M = new float[4]; + float min = -RADIANS_4[3]; + for (int i = 0; i < 4; i++) { + RADIANS_4M[i] = (min + RADIANS_4[i]) / 2; + min = RADIANS_4[i]; + } + } + + static final float RADIANS_8[] = { + MathUtils.atan2(-2, -4), + RADIANS_4[0], + MathUtils.atan2(-2, 4), + RADIANS_4[1], + MathUtils.atan2( 2, 4), + RADIANS_4[2], + MathUtils.atan2( 2, -4), + RADIANS_4[3], + }; + static final int DIRS_8M[] = {1, 6, 2, 7, 3, 4, 0, 5}; + static final float RADIANS_8M[]; + static { + RADIANS_8M = new float[8]; + float min = -RADIANS_8[7]; + for (int i = 0; i < 8; i++) { + RADIANS_8M[i] = (min + RADIANS_8[i]) / 2; + min = RADIANS_8[i]; + } + } + + static final float RADIANS_16[] = { + MathUtils.atan2(-1, -6), + RADIANS_8[0], + MathUtils.atan2(-3, -2), + RADIANS_8[1], + MathUtils.atan2(-3, 2), + RADIANS_8[2], + MathUtils.atan2(-1, 6), + RADIANS_8[3], + MathUtils.atan2( 1, 6), + RADIANS_8[4], + MathUtils.atan2( 3, 2), + RADIANS_8[5], + MathUtils.atan2( 3, -2), + RADIANS_8[6], + MathUtils.atan2( 1, -6), + RADIANS_8[7], + }; + static final int DIRS_16M[] = {1, 11, 6, 12, 2, 13, 7, 14, 3, 15, 4, 8, 0, 9, 5, 10}; + static final float RADIANS_16M[]; + static { + RADIANS_16M = new float[16]; + float min = -RADIANS_16[15]; + for (int i = 0; i < 16; i++) { + RADIANS_16M[i] = (min + RADIANS_16[i]) / 2; + min = RADIANS_16[i]; + } + } + + static final float RADIANS_32[] = { + MathUtils.atan2(-0.5f, -7), + RADIANS_16[0], + MathUtils.atan2(-1.5f, -5), + RADIANS_16[1], + MathUtils.atan2(-2.5f, -3), + RADIANS_16[2], + MathUtils.atan2(-3.5f, -1), + RADIANS_16[3], + MathUtils.atan2(-3.5f, 1), + RADIANS_16[4], + MathUtils.atan2(-2.5f, 3), + RADIANS_16[5], + MathUtils.atan2(-1.5f, 5), + RADIANS_16[6], + MathUtils.atan2(-0.5f, 7), + RADIANS_16[7], + MathUtils.atan2(0.5f, 7), + RADIANS_16[8], + MathUtils.atan2(1.5f, 5), + RADIANS_16[9], + MathUtils.atan2(2.5f, 3), + RADIANS_16[10], + MathUtils.atan2(3.5f, 1), + RADIANS_16[11], + MathUtils.atan2(3.5f, -1), + RADIANS_16[12], + MathUtils.atan2(2.5f, -3), + RADIANS_16[13], + MathUtils.atan2(1.5f, -5), + RADIANS_16[14], + MathUtils.atan2(0.5f, -7), + RADIANS_16[15], + }; + static final int DIRS_32M[] = {1, 22, 11, 23, 6, 24, 12, 25, 2, 26, 13, 27, 7, 28, 14, 29, 3, 30, 15, 31, 4, 16, 8, 17, 0, 18, 9, 19, 5, 20, 10, 21}; + static final float RADIANS_32M[]; + static { + RADIANS_32M = new float[32]; + float min = -RADIANS_32[31]; + for (int i = 0; i < 32; i++) { + RADIANS_32M[i] = (min + RADIANS_32[i]) / 2; + min = RADIANS_32[i]; + } + } + + public static int radiansToDirection(float radians, int directions) { + switch (directions) { + case 1: return 0; + case 4: return radiansToDirection4(radians); + case 8: return radiansToDirection8(radians); + case 16: return radiansToDirection16(radians); + case 32: return radiansToDirection32(radians); + default: return 0; + } + } + + @Deprecated + static int _radiansToDirection4(float radians) { + for (int i = 0; i < 4; i++) { + if (radians < RADIANS_4M[i]) { + return DIRS_4M[i]; + } + } + + return DIRS_4M[0]; + } + + static int radiansToDirection4(float radians) { + if (radians >= RADIANS_4M[3]) return DIRS_4M[0]; + int index = (radians < RADIANS_4M[1]) ? 0 : 2; + index |= (radians < RADIANS_4M[index]) ? 0 : 1; + return DIRS_4M[index]; + } + + @Deprecated + static int _radiansToDirection8(float radians) { + for (int i = 0; i < 8; i++) { + if (radians < RADIANS_8M[i]) { + return DIRS_8M[i]; + } + } + + return DIRS_8M[0]; + } + + static int radiansToDirection8(float radians) { + if (radians >= RADIANS_8M[7]) return DIRS_8M[0]; + int index = (radians < RADIANS_8M[3]) ? 0 : 4; + index |= (radians < RADIANS_8M[index|1]) ? 0 : 2; + index |= (radians < RADIANS_8M[index ]) ? 0 : 1; + return DIRS_8M[index]; + } + @Deprecated + static int _radiansToDirection16(float radians) { + for (int i = 0; i < 16; i++) { + if (radians < RADIANS_16M[i]) { + return DIRS_16M[i]; + } + } + + return DIRS_16M[0]; + } + + static int radiansToDirection16(float radians) { + if (radians >= RADIANS_16M[15]) return DIRS_16M[0]; + int index = (radians < RADIANS_16M[7]) ? 0 : 8; + index |= (radians < RADIANS_16M[index|3]) ? 0 : 4; + index |= (radians < RADIANS_16M[index|1]) ? 0 : 2; + index |= (radians < RADIANS_16M[index ]) ? 0 : 1; + return DIRS_16M[index]; + } + + @Deprecated + static int _radiansToDirection32(float radians) { + for (int i = 0; i < 32; i++) { + if (radians < RADIANS_32M[i]) { + return DIRS_32M[i]; + } + } + + return DIRS_32M[0]; + } + + static int radiansToDirection32(float radians) { + if (radians >= RADIANS_32M[31]) return DIRS_32M[0]; + int index = (radians < RADIANS_32M[15]) ? 0 : 16; + index |= (radians < RADIANS_32M[index|7]) ? 0 : 8; + index |= (radians < RADIANS_32M[index|3]) ? 0 : 4; + index |= (radians < RADIANS_32M[index|1]) ? 0 : 2; + index |= (radians < RADIANS_32M[index ]) ? 0 : 1; + return DIRS_32M[index]; + } +} diff --git a/tools/src/com/riiablo/entity/DirectionTool.java b/tools/src/com/riiablo/entity/DirectionTool.java new file mode 100644 index 00000000..0c684996 --- /dev/null +++ b/tools/src/com/riiablo/entity/DirectionTool.java @@ -0,0 +1,133 @@ +package com.riiablo.entity; + +import com.badlogic.gdx.Application; +import com.badlogic.gdx.ApplicationAdapter; +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.InputAdapter; +import com.badlogic.gdx.backends.lwjgl.LwjglApplication; +import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; +import com.badlogic.gdx.graphics.GL20; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.math.MathUtils; +import com.badlogic.gdx.utils.StringBuilder; + +import java.util.Arrays; + +public class DirectionTool extends ApplicationAdapter { + private static final String TAG = "DirectionTool"; + + public static void main(String[] args) { + LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); + config.title = TAG; + config.resizable = false; + config.width = 256; + config.height = 256; + config.vSyncEnabled = false; + config.foregroundFPS = config.backgroundFPS = 144; + new LwjglApplication(new DirectionTool(), config); + } + + Batch batch; + BitmapFont font; + ShapeRenderer shapes; + float width, height; + float x1, y1; + float x2, y2; + StringBuilder builder = new StringBuilder(); + + DirectionTool() {} + + @Override + public void create() { + Gdx.app.setLogLevel(Application.LOG_DEBUG); + + print(DirectionUtils.RADIANS_4); + print(DirectionUtils.RADIANS_4M); + print(DirectionUtils.RADIANS_8); + print(DirectionUtils.RADIANS_8M); + print(DirectionUtils.RADIANS_16); + print(DirectionUtils.RADIANS_16M); + print(DirectionUtils.RADIANS_32); + print(DirectionUtils.RADIANS_32M); + + font = new BitmapFont(); + batch = new SpriteBatch(); + shapes = new ShapeRenderer(); + + width = Gdx.graphics.getWidth(); + height = Gdx.graphics.getHeight(); + x1 = width / 2; + y1 = height / 2; + + Gdx.input.setInputProcessor(new InputAdapter() { + @Override + public boolean touchDown(int screenX, int screenY, int pointer, int button) { + update(screenX, screenY); + return true; + } + + @Override + public boolean touchDragged(int screenX, int screenY, int pointer) { + update(screenX, screenY); + return true; + } + + void update(int screenX, int screenY) { + x2 = screenX; + y2 = height - screenY; + } + }); + } + + void print(float[] a) { + Gdx.app.log(TAG, Arrays.toString(a)); + } + + @Override + public void render() { + Gdx.gl.glClearColor(0.3f, 0.3f, 0.3f, 1.0f); + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); + + float radius = 64; + float angle = MathUtils.atan2(y2 - y1, x2 - x1); + float x = radius * MathUtils.cos(angle); + float y = radius * MathUtils.sin(angle); + + builder.setLength(0); + builder + .append("x,y: ").append("(" + x2 + "," + y2 + ")").append('\n') + .append("angle: ").append(angle).append('\n') + .append("dir4: ").append(DirectionUtils.radiansToDirection(angle, 4)).append('\n') + .append("dir8: ").append(DirectionUtils.radiansToDirection(angle, 8)).append('\n') + .append("dir16: ").append(DirectionUtils.radiansToDirection(angle, 16)).append('\n') + .append("dir32: ").append(DirectionUtils.radiansToDirection(angle, 32)).append('\n'); + + shapes.begin(ShapeRenderer.ShapeType.Line); + drawDiamond(shapes, x1 - 80, y1 - 40, 160, 80); + shapes.line(x1, y1, x1 + x, y1 + y); + shapes.end(); + + batch.begin(); + font.draw(batch, builder.toString(), 0, Gdx.graphics.getHeight()); + batch.end(); + } + + @Override + public void dispose() { + font.dispose(); + batch.dispose(); + shapes.dispose(); + } + + static void drawDiamond(ShapeRenderer shapes, float x, float y, int width, int height) { + int hw = width >>> 1; + int hh = height >>> 1; + shapes.line(x, y + hh, x + hw, y + height); + shapes.line(x + hw, y + height, x + width, y + hh); + shapes.line(x + width, y + hh, x + hw, y); + shapes.line(x + hw, y, x, y + hh); + } +}