{}
run-icon
Main.java
package JAVARuntime; public class PlayerMovement extends Component { // Tunables (editable in the Inspector) public float moveSpeed = 5f; // units per second public float turnLerp = 6f; // bigger = snappier facing public String uiAxisName = "Move"; // must match your SUIJoystick Axis Name public boolean faceMoveDirection = true; // Reusable vectors to avoid GC churn private Vector2 v2 = new Vector2(); private Vector3 localMove = new Vector3(); private Vector3 worldMove = new Vector3(); private Vector3 lookTarget = new Vector3(); @Override public void start() { // Ensure the Axis exists for the SUIJoystick; safe to call even if already created. Input.registerAxis(uiAxisName); // lets Input.getAxisValue(uiAxisName) work } @Override public void repeat() { // ---------- 1) Read input ---------- float x = 0f, z = 0f; // Keyboard (names depend on device layout; WASD and arrows are typical) if (Input.isKeyPressed("A") || Input.isKeyPressed("LEFT")) x -= 1f; if (Input.isKeyPressed("D") || Input.isKeyPressed("RIGHT")) x += 1f; if (Input.isKeyPressed("W") || Input.isKeyPressed("UP")) z += 1f; if (Input.isKeyPressed("S") || Input.isKeyPressed("DOWN")) z -= 1f; // Gamepad (left stick) v2 = Input.getLeftJoystick(); // returns [-1..1] per axis x += v2.getX(); z += v2.getY(); // SupremeUI (on-screen) joystick v2 = Input.getAxisValue(uiAxisName); // same range [-1..1] x += v2.getX(); z += v2.getY(); // Normalize so diagonal isn’t faster float len = (float)Math.sqrt(x*x + z*z); if (len > 1f) { x /= len; z /= len; } // ---------- 2) Convert local input to world space ---------- // Build a local movement vector (X=right, Z=forward in ItsMagic) localMove.set(x, 0f, z); // Transform the local vector by the object’s rotation to world space Transform t = getObject().getTransform(); worldMove = t.transformDirection(localMove); // accounts for current facing // Remove any Y drift and renormalize worldMove.setY(0f); float wlen = (float)Math.sqrt(worldMove.getX()*worldMove.getX() + worldMove.getZ()*worldMove.getZ()); if (wlen > 0f) { worldMove.setX(worldMove.getX() / wlen); worldMove.setZ(worldMove.getZ() / wlen); } // ---------- 3) Move (time-scaled) ---------- // translateInSeconds multiplies by Math.bySecond(1) internally t.translateInSeconds(worldMove.getX() * moveSpeed, 0f, worldMove.getZ() * moveSpeed); // ---------- 4) Optional: face the move direction ---------- if (faceMoveDirection && len > 0.01f) { // Build a target point slightly ahead along the worldMove direction Vector3 pos = getObject().getGlobalPosition(); lookTarget.set(pos.getX() + worldMove.getX(), pos.getY(), pos.getZ() + worldMove.getZ()); // Smoothly turn toward it, ignoring Y so you don't pitch up/down t.lerpLookToIgnoreY(lookTarget, turnLerp); } } }
Output