スプライトをらせん状に見せる簡単な方法の 1 つは、時計の針のように、らせんの中心を中心に回転する腕にスプライトが取り付けられているように見せることです。そのアームが回転するにつれて、スプライトをアームの中心に向かってゆっくりと動かします。最終的に得られるのは、古典的なアルキメダンスパイラルです
コードのモックアップを作成できますが、数分かかります。
さて、これがコードです。
public static double getArmX(double length, double angle) {
return Math.cos(angle) * length;
}
public static double getArmY(double length, double angle) {
return Math.sin(angle) * length;
}
これらは数学の核心です。これらは、中心から指定された距離 (長さ) と中心からの角度 (角度) にあるエンティティの x 値と y 値を返します。
さて、あなたのコードがどのように設定されているかはわかりませんが、あなたのエンティティがどの程度スパイラルに入っているかを表すdouble
名前があるとしましょう。spiralProgress
ではspiralProgress == 0
、エンティティは開始されたばかりでありspiralProgress == 1
、 ではエンティティが中心にあります。
エンティティの x と y を取得するコードは次のようになります。
double startingRadius = 64;
double rotations = 10;
double x = getArmX(startingRadius * (1-t), t * rotations * Math.PI * 2);
double y = getArmY(startingRadius * (1-t), t * rotations * Math.PI * 2);
そのスニペットでstartingRadius
は、エンティティが中心から離れて開始する必要がある単位数 (ピクセル、プログラムで x と y が意味する場合) であり、エンティティがrotations
中心に到達する前に中心をループする回数です。
これが返す座標は、{0, 0} を中心とした螺旋の座標です。したがって、他の点を中心に螺旋を描きたい場合は、たとえばにとを{screenWidth / 2, screenHeight / 2}
追加screenWidth / 2
します。x
screenHeight / 2
y
この計算を示す完全な Java プログラムを次に示します。ウィンドウ内の任意の場所でマウスをクリックして、らせんをリセットします。
package net.eonz.stackoverflow.spiral;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
public class Game extends Canvas implements Runnable, MouseListener {
private static final long serialVersionUID = 1L;
public static final String NAME = "untitled";
public static final int HEIGHT = 600;
public static final int WIDTH = 600;
public static final int SCALE = 1;
private boolean running = false;
public void start() {
running = true;
new Thread(this).start();
this.addMouseListener(this);
}
public void stop() {
running = false;
}
public void run() {
long last = System.currentTimeMillis();
while (running) {
long now = System.currentTimeMillis();
double dt = (now - last) / 1000.0;
last = now;
update(dt);
render();
}
}
double t = 0;
public void update(double dt) {
t += dt / 16;
if (t > 1)
t = 1;
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
/* SPIRAL MATH IS HERE */
double startingRadius = this.getHeight() * 0.40;
double rotations = 10;
double x = getArmX(startingRadius * (1 - t), t * rotations * Math.PI
* 2);
double y = getArmY(startingRadius * (1 - t), t * rotations * Math.PI
* 2);
g.setColor(Color.black);
g.fillRect((int) (x - 8) + this.getWidth() / 2,
(int) (y - 8) + this.getHeight() / 2, 16, 16);
/* END SPIRAL MATH */
g.dispose();
bs.show();
}
public static double getArmX(double length, double angle) {
return Math.cos(angle) * length;
}
public static double getArmY(double length, double angle) {
return Math.sin(angle) * length;
}
@Override
public void mouseClicked(MouseEvent e) {
this.t = 0;
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
public static void main(String[] args) {
Game game = new Game();
game.setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
game.setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
game.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
JFrame frame = new JFrame(Game.NAME);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(game, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
game.start();
}
}