From 35c47c50b8a7b6ec4b003605ffd19085e34fbde2 Mon Sep 17 00:00:00 2001 From: Nilstrieb Date: Fri, 11 Dec 2020 22:33:18 +0100 Subject: [PATCH] better rotation mechanics --- src/main/java/core/ExMath.java | 28 ++++++++++++++++++ src/main/java/core/Vector2D.java | 28 ++++++++++++++++++ src/main/java/objects/ships/BattleShip.java | 4 +-- src/main/java/objects/ships/Submarine.java | 18 +++++++++++ src/main/java/objects/ships/Turret.java | 20 +++++++++---- src/test/java/core/Vector2DTest.java | 8 +++++ target/classes/core/Vector2D.class | Bin 2860 -> 3228 bytes target/classes/objects/ships/BattleShip.class | Bin 3014 -> 2936 bytes target/classes/objects/ships/Turret.class | Bin 3491 -> 3567 bytes target/test-classes/core/Vector2DTest.class | Bin 2457 -> 2672 bytes 10 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 src/main/java/core/ExMath.java create mode 100644 src/main/java/objects/ships/Submarine.java diff --git a/src/main/java/core/ExMath.java b/src/main/java/core/ExMath.java new file mode 100644 index 0000000..4c21516 --- /dev/null +++ b/src/main/java/core/ExMath.java @@ -0,0 +1,28 @@ +package core; + +/** + * Extended Math functions for the game engine + */ +public class ExMath { + + private ExMath(){ + } + + /** + * Lerp an angle in radians + * + * @param from The start angle + * @param to The target angle + * @param t The value + * @return The new angle + * + * @see + */ + public static double angleLerp(double from, double to, double t) { + double max = Math.PI * 2; + double da = (to - from) % max; + double shortAngleDist = 2 * da % max - da; + + return from + shortAngleDist * t; + } +} diff --git a/src/main/java/core/Vector2D.java b/src/main/java/core/Vector2D.java index 2e1ecef..9dcc49d 100644 --- a/src/main/java/core/Vector2D.java +++ b/src/main/java/core/Vector2D.java @@ -133,6 +133,30 @@ public class Vector2D { return new Vector2D(rotatedX + center.x, rotatedY + center.y); } + /** + * Rotate a point around another point + * + * This method can now be trusted + * + * @param center The center of the rotation + * @param value The point to be rotated, absolut to the center + * @param rotation The rotation angle in radians + * @return The rotated point + */ + public static Vector2D rotateAround(Vector2D center, Vector2D value, double rotation){ + return rotateAround(center, value, rotation, COUNTERCLOCKWISE); + } + + + /** + * Get a unit vector with magnitude 1 and the direction + * @param direction The direction of the vector + * @return The unit vector + */ + public static Vector2D getUnitVector(double direction){ + return rotateAround(new Vector2D(), new Vector2D(0, 1), direction); + } + /** * Copy this object * @return A copy of this object @@ -165,4 +189,8 @@ public class Vector2D { if (Double.compare(vector2D.x, x) != 0) return false; return Double.compare(vector2D.y, y) == 0; } + + public double getRotation() { + return Math.atan2(y, x); + } } \ No newline at end of file diff --git a/src/main/java/objects/ships/BattleShip.java b/src/main/java/objects/ships/BattleShip.java index cd946e3..107f4aa 100644 --- a/src/main/java/objects/ships/BattleShip.java +++ b/src/main/java/objects/ships/BattleShip.java @@ -18,8 +18,8 @@ public class BattleShip extends GameObject { super(20, 20, 5, 40); turrets = new ArrayList<>(); turrets.add(new Turret(this, 25, 25, 50, 3)); - turrets.add(new Turret(this, 25, 10, 50, 2)); - turrets.add(new Turret(this, 25, 70, 50, 2)); + //turrets.add(new Turret(this, 25, 10, 50, 2)); + //turrets.add(new Turret(this, 25, 70, 50, 2)); this.mainColor = mainColor; } diff --git a/src/main/java/objects/ships/Submarine.java b/src/main/java/objects/ships/Submarine.java new file mode 100644 index 0000000..a9cdd6e --- /dev/null +++ b/src/main/java/objects/ships/Submarine.java @@ -0,0 +1,18 @@ +package objects.ships; + +import core.Master; +import objects.GameObject; + +import java.awt.*; + +public class Submarine extends GameObject { + @Override + public void draw(Graphics2D g2d, int w, Master master) { + + } + + @Override + public void update(Master master) { + + } +} diff --git a/src/main/java/objects/ships/Turret.java b/src/main/java/objects/ships/Turret.java index acf0fa2..c115c15 100644 --- a/src/main/java/objects/ships/Turret.java +++ b/src/main/java/objects/ships/Turret.java @@ -1,5 +1,6 @@ package objects.ships; +import core.ExMath; import core.Master; import core.Vector2D; import objects.GameObject; @@ -11,18 +12,21 @@ import java.awt.*; */ public class Turret extends GameObject { - private static final double ROTATION_SPEED = 2; + private static final double ROTATION_SPEED = 0.05; + private static final int SHOT_EFFECT_TIME = 300; + private static final int SHELL_SPEED = 10; BattleShip battleShip; private int barrelAmount = 3; + private double rotation; + private Color mainColor; private long lastShot = 0; - private static int SHOT_EFFECT_TIME = 300; - private static int SHELL_SPEED = 10; - private double rotation; + + //private double rotation; public Turret(BattleShip battleShip, double x, double y, double size, int barrelAmount) { super(x, y, size, size); @@ -58,6 +62,7 @@ public class Turret extends GameObject { g2d.setPaint(Color.BLACK); int barrelSpacing = sizeAbs / (barrelAmount + 1); g2d.rotate(rotation, xCenterAbs, yCenterAbs); + for (int i = 0; i < barrelAmount; i++) { int barrelX = xAbs + (i + 1) * barrelSpacing; int frontPosY = yAbs - sizeAbs / 2; @@ -82,7 +87,10 @@ public class Turret extends GameObject { int yCenterAbs = yAbs + sizeAbs / 2; Point msLoc = master.getMouseLocation(); - rotation = -Math.atan2(xCenterAbs - msLoc.x, yCenterAbs - msLoc.y); + double targetRotation = -Math.atan2(xCenterAbs - msLoc.x, yCenterAbs - msLoc.y); + + + rotation = ExMath.angleLerp(rotation, targetRotation, ROTATION_SPEED); int barrelSpacing = sizeAbs / (barrelAmount + 1); @@ -93,7 +101,7 @@ public class Turret extends GameObject { if (master.isMousePressed()) { lastShot = System.currentTimeMillis(); - Vector2D shellVel = new Vector2D(xCenterAbs - msLoc.x, yCenterAbs - msLoc.y).normalized().negative().multiply(SHELL_SPEED); + Vector2D shellVel = Vector2D.getUnitVector(rotation).negative().multiply(SHELL_SPEED); Vector2D pos = Vector2D.rotateAround(new Vector2D(xCenterAbs, yCenterAbs), new Vector2D(barrelX, frontPosY), rotation, Vector2D.COUNTERCLOCKWISE); master.create(new Shell(pos, new Vector2D(10, 10), shellVel)); diff --git a/src/test/java/core/Vector2DTest.java b/src/test/java/core/Vector2DTest.java index 973444c..c20b23d 100644 --- a/src/test/java/core/Vector2DTest.java +++ b/src/test/java/core/Vector2DTest.java @@ -67,7 +67,15 @@ class Vector2DTest { assertEquals(round(expected), round(rotated)); } + public static Vector2D round(Vector2D a){ return new Vector2D(Math.round(a.x*10000d)/10000d, Math.round(a.y*10000d)/10000d); } + + @Test + void getUnitVectorSimple() { + double dir = Math.PI; + Vector2D expected = new Vector2D(0, -1); + assertEquals(round(expected), round(Vector2D.getUnitVector(dir))); + } } \ No newline at end of file diff --git a/target/classes/core/Vector2D.class b/target/classes/core/Vector2D.class index 33893d8c931f4fd11026ce990aee4e68d1f00e1f..8567c8a44e65f40e0f4223b14876e7ece68fa1cf 100644 GIT binary patch delta 1421 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 CYqPfi delta 1299 zcmew%c1)b>)W2Q(7#J9=7-nwda%GfZb5LOb12%`i1~7w@L6|{{he4Y`XL2N?vZfvn zgFb@+BLibOBLkx+NYaRh!5A!(!Np+8V8+g1&ck5AU^#gyqcxi~4}%SZ?c`^S^4#_e z4(tq$JPb|@&XWb0WISAX7~B}#85#J}Q%l10i*iz&^Ye>RiWwPLHC&=JT{s!+89aFy zycnDr85k=;_W1BH_%hfsGO!e9R;7Zh^5-I0vbNa`9-PvzKO*psYTYBVO$In z3`sl;$qXr*JD8K0_*%FaS{d5d8QOUmIv6@P|6pZdWbB^&mrdHRmy1D|p^t~5j-g(F zp^~4CVIoLi5)VTSLoFi%k7r(9YLRnJVsUY5F+0OlMh4Z%25hR#>y42%ri4CxGv3>gdz47(Y)8JHLt81g4yWjCwe!XUJpK_XI1 zgh5J#K~;o7hIKoG+%^Wqa4i%Wbz~XstqhtQ!DeSNFfhn5urn|)2r&pS2s21Ch%lHk zh%)#yh%sa`h%@9dNHAnEFffQgY-Gr0$N|TDJ}Al=7#SEj7`Pd7K@OW7#-Ub^WU3GY z3j+g#Gy@ld41*|xEQ2(I9M~i~1~vu;1{t_XGN3qTU<8YKF*q|YgIReD&J3(zRz8C> z*nKi!8#x&mL6HEmkb!}bhk=8EgMopeLQ7^VgRYiLy?{WD0B6Ql219MFEex957)-RZ zwlG+2VX$M_#^BOt#scMfFoU_QAg(uDmJP~<%Cc*VvWT*ZvWc?G2yo?q@HPfNP@rnd z=h+-D3W7Kb?#T*<0)|4cCo4c11RR(Z3`GpZ49pDb z41o+K3U48{y)3wkO1*GgBt@A*bF|f zdv-BIAzV|>0E$yCu(SaKFM}aC)FJW52X_!3*m6b&MurN8N~obuP(!)EhJun1!g~<& zOc*#BOp(mvf}6+1P{mNqz$n1QP+!AP3pLORY9O1o);5M%gkfypkT5_phz;xc!%fd!nHICQn7b+$1iqMM`*Hc1PjCJG$XAfq_IK@Cb-9AM)?d4>aQJTn6` v1E~CBVrXP&f~M|f24;pXh8~7~1_)~cLqEf01_lN$21bS{4AU59Fh~Lb`eng_ diff --git a/target/classes/objects/ships/Turret.class b/target/classes/objects/ships/Turret.class index 6b61a94902281595bb07d2c4f07540642ac9d1b6..d9652396cb679ca4e26038fd071672884b725253 100644 GIT binary patch delta 1556 zcmZ21{a%{u)W2Q(7#J9=7*22GQeqZkWdH+49WI7sh7@*&R33&jhV;o{%!V?VJPcV3 zQj832k*+>I{^48Tot$5ks_$Cin^=;;$iSJH zm!6aAlUh{3$iSxI;^Ly|0dL515W%FaguD3{qg4pFx0ufq{jA zk%5(A6$2x~>dE)nEsfVOFfhn5urn|)C@^p{h%yK;NHd5sC^ASfC^0B7C^M)ts4%Q$ zU|_IgU}Iol&|p}{uzs>Phb8LLA_V6sit(Eh7UX!$yWpAd?svm~m0yG* zA#n#o(v*1&irSkPGA4iElxJKvS%6El9%O4AgE#{NgFXW{g8_pugCTPAgC#>PgB?Q)gFQn(g9F1{1}BD<49*N&8C)3lF}O0EVsK};$>728 zfWedD1A`aCcLpbhzYM;NJPdwdm$xwRGHhjVV%W^U!@$k3kHL~*3j+@WPd&o|hFFHJ z3_J{6ASc5-#>mUCjbS?jBUo$)0}sgCjJymx8Fn!+GpI1UWZ2EX!@$B|%5Z~W4+AL4 zxiK7P*vr7fz{cRuu#aIM0}lf`Lj=QChW!jY3>*yo40Q|#7s84iLYi1|Om0tRk& z1`c*@1~o=@h8#u+U|{&o5cZ3Km4T7r5W`_;c&adPfnuDIVX_~$OMSK#yC|z9`xb`6 zly*@z5Ti7ueFsB%xh02|))s~^2@Vm4+8qq_TN%PcS+uq=u(KrOm~k zFo+aoZ5L&0uiwrv1EDZ?#Cd^z`zj9Aixm9puiByV8{^0V95~9;K&fk;LZ@m z5YG_Hkk1g$P{okQ(8iF&Fp(jdVJ1T=!-9H-G=}9284NoaG8yhNWHbC^NM!iWkOz+9 z84UakI~g1pjxgvk@G;zFkYPB=pvS<^Fp(hx9POY2Bmo@lybQGrP2gDPW&lO`iH+G`=v4vlekh9YK0Mo_F*Lt_0TIESAC0M9=? A>Hq)$ delta 1494 zcmaDay;z#-)W2Q(7#J9=7!GaZQexKPWZ+;(FVR-AI`;)%aF&;kk7+Vz)(23pV@+~ zn4yH7p>* zFt9STFfy=exVUJBaWNP$wDB;sGjuRAaOLF}njbc2*~NRFq#2|bWEd0}WEs>MxH0lFxP!gYQqRE4u$94?VI>0(12@Ay z1}lbD3_J`x3=0_I7*;dzFmQqV0P`s$AHy1kwG514v2_eQpm1R1V_46yfq|Jph2a&$ zMg|@R76wy>n+%&6KncQ);RM5G1|9}B27iYA3|km@7}yyi7`8ENW#D1pVCZM4XK>uc zz{9}Fu$_T{L4kq!Kf?kBZgvI^b_O*@c7|L=2w-6N%@FN%k!aMJer~Y#>HiO8X9mit?=tVWKQrTNv0`5^~Hqn9VpvIYGQd z43lI;Iav}!IWiK=xMW3HSaVX$xV5)2)Xiil(%Qk0yp@4>H-kYWrlH#znzk{tZe!@& z#L&~ejiKL)XE#GVNMXAuTl;o~Ca^B9c2RB+2Nbs~I~XQg@oMj8m>ww!HdBPbON7B| zJ42Hs&vu5H+Zg7wa566cpN)ulF9sn71_mDn0R~?N1qMF`Lk52aONIajM}{B+40;Sa3{M$k7YJ>?P0QDbKq3`9pa)Z!NtJN5XQq0&Je-Kz?+_05}KD; z5|)}=l3&EgAf(}<>64sal&TLAF>V4g*9L4?_Y&JVOElBZCA(2ty)60s|9+8iN}{5<>z5GlL<6HA6B( z0s{*}3e>JtkiiTpP?Hl`L&8C>5CfYj!NA2J$socY&0xeJ!{Edq3wD(P12Y2ygEQ1V zE(S}eeIg9{Q2S8LPJ^1w!&c82HMxfk+0}VaQ+ODXpr%MLgh5SFWAK2x+7_#;)1f9a zvHLJaP4;J(M+y&XsL5Omh71|t@DO282iw8Kpuix_kO>YCJqBKeEG*%X4K;Z$yB}lJ zWF8J=lWpN98$(SNgPW`bH`xG($vIGyt2hD}qb8q5G1(q!G6#b>++?%a$44d;t-Us7#KXjaRy0A8ep?P5uOKe1p@;^CIcG-3j+g# zya+?E$8HApNInq;zU>U$e!4pt%+z-BL4biD>|SP+G{?wL05-A^0QDt!DgXcg delta 691 zcmew$GEk|BzLkwJnXgdv(Cih+qijlqo}h9Qc9nZc03njw}Uih+e8 z4r*6C$Y2H)sL5MdLl{FQbFoQVgG^RnU}j)oaE6-9#b60FS%g6!YBH)R2~blK*y^}LRP?BO`V_;y=W#D4aV*t5E zfx&=5kHL_^iopmRa*!~whT6%+V91aJ4igaub+GMB3