【Java】多角形クラスと矩形との当たり判定
本稿はJavaのPolygonクラスについて紹介します。
Polygonクラスは多角形を表すオブジェクトで、それに関連するいろいろなメソッドを利用できます。
オブジェクトの作成
オブジェクトの作成は
new Polygon(x座標配列,y座標配列,点の数)
で定義します。
各x座標とy座標は配列の添え字番号で一致しています。
例えば、x座標配列が[100,50,3000]でy座標配列が[200,400,600]とした場合は点(100,200)と点(50,400)と点(3000,600)を直線で結んだ図形が作成されます。
drawPolygonメソッドと同じ要領ですね。
- import java.awt.Polygon;
- import java.util.Arrays;
- public class Test {
- public static void main(String[] args) {
- Polygon po = new Polygon(new int[] {100,150,200}, new int[] {150,100,150}, 3);
- System.out.println(Arrays.toString(po.xpoints));
- System.out.println(Arrays.toString(po.ypoints));
- }
- }
[100, 150, 200]
[150, 100, 150]
translateメソッド
現在の座標から指定した座標分移動させることができます。
- import java.awt.Polygon;
- import java.util.Arrays;
- public class Test {
- public static void main(String[] args) {
- Polygon po = new Polygon(new int[] {100,150,200}, new int[] {150,100,150}, 3);
- po.translate(50, 50);
- System.out.println(Arrays.toString(po.xpoints));
- System.out.println(Arrays.toString(po.ypoints));
- }
- }
[150, 200, 250]
[200, 150, 200]
containsメソッド
多角形内に指定された座標が含まれているかを判定します。
contains(x座標,y座標)と定義しましょう。
点と多角形の当たり判定で利用できます。
- import java.awt.Polygon;
- public class Test {
- public static void main(String[] args) {
- Polygon po = new Polygon(new int[] {100,150,200}, new int[] {150,100,150}, 3);
- System.out.println(po.contains(150, 130));
- }
- }
true
intersectsメソッド
intersectsメソッドを利用することで、多角形と矩形の当たり判定が実装できます。
Polygonオブジェクト.intesects(Rectangleオブジェクト)と定義しましょう。
それではサンプルをご覧ください。
- import java.awt.Polygon;
- import java.awt.Rectangle;
- public class Test {
- public static void main(String[] args) {
- Polygon r1 = new Polygon(new int[] {100,150,200}, new int[] {150,100,150}, 3);
- Rectangle r2 = new Rectangle(100, 100, 50, 50);
- System.out.println(r1.intersects(r2));
- }
- }
true
多角形と矩形をアニメーションさせながら判定できているか確かめる
実際にアニメーションサンプルを実装して判定できているか確かめてみます。
- import java.awt.Color;
- import java.awt.Font;
- import java.awt.Graphics;
- import java.awt.Graphics2D;
- import java.awt.Insets;
- import java.awt.Polygon;
- import java.awt.Rectangle;
- import javax.swing.JFrame;
- import javax.swing.JPanel;
- public class Test {
- public static void main(String[] args) {
- TestWindow tw = new TestWindow("テスト", 400, 300);
- tw.change(new DrawCanvas());
- tw.setVisible(true);
- tw.startGameLoop();
- }
- }
- //ウィンドウクラス
- class TestWindow extends JFrame implements Runnable{
- private Thread th = null;
- private double sleepAddTime;
- private int fps=60;
- public TestWindow(String title, int width, int height) {
- super(title);
- setDefaultCloseOperation(EXIT_ON_CLOSE);
- setSize(width,height);
- setLocationRelativeTo(null);
- setLayout(null);
- setResizable(false);
- setFps(fps);
- }
- public synchronized void change(JPanel p) {
- getContentPane().removeAll();
- Insets inset = getInsets();
- p.setBounds(-inset.left,-inset.top,getWidth(),getHeight());
- add(p);
- validate();
- repaint();
- }
- public synchronized void startGameLoop(){
- if ( th == null ) {
- th = new Thread(this);
- th.start();
- }
- }
- public synchronized void stopGameLoop(){
- if ( th != null ) {
- th = null;
- }
- }
- public void run(){
- double nextTime = System.currentTimeMillis() + sleepAddTime;
- while(th != null){
- try{
- long res = (long)nextTime - System.currentTimeMillis();
- if ( res < 0 ) res = 0;
- Thread.sleep(res);
- repaint();
- nextTime += sleepAddTime;
- }catch(InterruptedException e){
- e.printStackTrace();
- }
- }
- }
- public void setFps(int fps){
- if ( fps < 10 || fps > 60 ) {
- throw new IllegalArgumentException("fpsの設定は10~60の間で指定してください。");
- }
- this.fps = fps;
- sleepAddTime = 1000.0 / fps;
- }
- }
- //移動アニメーション用クラス
- class VertexMove2D{
- private double x;
- private double y;
- private final int[] xpoints;
- private final int[] ypoints;
- private final int npoints;
- private boolean isInvert;
- private int currentPoint;
- private int nextPoint;
- private int speed;
- private double mx;
- private double my;
- private double checkValue;
- public VertexMove2D(int[] xpoints, int[] ypoints, int npoints, int speed, int initPoint) {
- this.xpoints = xpoints;
- this.ypoints = ypoints;
- this.npoints = npoints;
- this.speed = Math.abs(speed);
- this.isInvert = speed < 0;
- this.currentPoint = isInvert ? initPoint + 1 : initPoint - 1;
- prepareNext();
- }
- private void prepareNext() {
- if ( isInvert ) {
- int currentPoint = this.currentPoint - 1;
- if ( currentPoint < 0 ) currentPoint = npoints - 1;
- this.currentPoint = currentPoint;
- int nextPoint = currentPoint - 1;
- this.nextPoint = nextPoint < 0 ? npoints - 1 : nextPoint;
- } else {
- int currentPoint = this.currentPoint + 1;
- if ( currentPoint >= npoints ) currentPoint = 0;
- this.currentPoint = currentPoint;
- this.nextPoint = (currentPoint + 1) % npoints;
- }
- int sx = xpoints[currentPoint];
- int sy = ypoints[currentPoint];
- int ex = xpoints[nextPoint];
- int ey = ypoints[nextPoint];
- int vx = ex - sx;
- int vy = ey - sy;
- double rad = Math.atan2(vy, vx);
- mx = Math.cos(rad) * speed;
- my = Math.sin(rad) * speed;
- checkValue = vx * vx + vy * vy;
- x = sx;
- y = sy;
- }
- public void draw(Graphics g) {
- g.drawPolygon(xpoints, ypoints, npoints);
- }
- public void fill(Graphics g) {
- g.fillPolygon(xpoints, ypoints, npoints);
- }
- public void move() {
- double xx = x + mx;
- double yy = y + my;
- int sx = xpoints[currentPoint];
- int sy = ypoints[currentPoint];
- double vx = sx - xx;
- double vy = sy - yy;
- if ( checkValue <= vx * vx + vy * vy ) {
- prepareNext();
- } else {
- x = xx;
- y = yy;
- }
- }
- public void invert() {
- isInvert = !isInvert;
- }
- public boolean isInvert() {
- return isInvert;
- }
- public int getSpeed() {
- return speed;
- }
- public void setSpeed(int speed) {
- if ( speed < 0 ) {
- invert();
- speed = -speed;
- }
- this.speed = speed;
- }
- public double getX() {
- return x;
- }
- public double getY() {
- return y;
- }
- }
- class DrawCanvas extends JPanel{
- int[] x = {60,150,280,340,270,160,90,70};
- int[] y = {80,200,90,120,150,250,240,260};
- //図形の頂点を移動するオブジェクト。
- VertexMove2D m1 = new VertexMove2D(
- x
- ,y
- ,8//頂点の数
- ,2//移動速度
- ,0//配列の0番を開始地点に
- );
- //もう一つの図形の頂点を移動するオブジェクト。
- VertexMove2D m2 = new VertexMove2D(
- x
- ,y
- ,8//頂点の数
- ,-3//移動速度
- ,4//配列の4番を開始地点に
- );
- Polygon r1 = new Polygon(new int[] {100,150,200}, new int[] {150,100,150}, 3);
- Rectangle r2 = new Rectangle(100, 100, 50, 50);
- public void paintComponent(Graphics g){
- Graphics2D g2 = (Graphics2D)g;
- g.setColor(Color.RED);
- g2.draw(r1);
- g.setColor(Color.BLUE);
- g2.draw(r2);
- g.setColor(Color.GREEN);
- m1.draw(g2);
- m1.move();
- Rectangle r1_rect = r1.getBounds();
- r1.translate((int)(m1.getX()-r1_rect.getCenterX()), (int)(m1.getY()-r1_rect.getCenterY()));
- m2.move();
- r2.x = (int) (m2.getX()-r2.width / 2);
- r2.y = (int) (m2.getY()-r2.height / 2);
- g.setFont(new Font(Font.MONOSPACED,Font.BOLD,20));
- if ( r1.intersects(r2) ) {
- g.setColor(Color.RED);
- g.drawString("当たっています", 50,50);
- } else {
- g.setColor(Color.BLUE);
- g.drawString("当たってません", 50,50);
- }
- }
- }
これでちゃんと当たり判定ができていることが確認できました。
ディスカッション
コメント一覧
まだ、コメントがありません