【问题标题】:How to make circle clickable如何使圆圈可点击
【发布时间】:2014-04-04 13:11:52
【问题描述】:

我正在使用画布开发游戏。我已经使用循环绘制了圆圈网格。我想得到圆的 x,y 坐标。为此,我必须使这些圆圈可点击,以便每当玩家点击一个圆圈时,它应该返回其坐标。我会将这些坐标传递给 lineDraw() 方法,以便在这些圆圈之间画线。 这个循环定义了圆圈网格:

for (int y=0;y<rows;y++)
        {
            for (int x=0;x<cols;x++)
            {
               canvas.drawCircle((x + 1) * dw, (y + 1) *(3* dh), 20, pDot);
}
}

这里dw是(displayWidth),dh是(displayHeight)。请建议我应该如何使这些圈子可点击?

【问题讨论】:

  • 希望这个链接能给你一些想法stackoverflow.com/a/20588487/3110609
  • 如果我没记错的话,这个方法会检测运动事件,并返回 x,y。虽然我已经用修复 x 和 y 绘制了圆圈,但我想让这些圆圈可点击。我不想移动那些圆圈,我唯一想要的就是有 x 和 y 坐标。我会将这些坐标传递给 line draw 方法,以便在两个圆之间画线。

标签: java android android-canvas actionlistener


【解决方案1】:

在您之前的问题之后,我已经玩过这个项目了。我确信这不是最优化的方法,但在不知道您打算如何实现游戏逻辑的情况下,我认为这足够灵活以适应。以下是您的自定义 View 类,我已将其重命名为 Board,以符合 Java 命名约定。

public class Board extends View
{
    Paint pBack = new Paint();
    Paint pDot = new Paint();
    Paint pLine = new Paint();

    int cols = 5; 
    int rows = 6;

    // Default initialization = false
    boolean[][] dots = new boolean[cols][rows];     

    int canWidth = 0;
    int canHeight = 0;

    float xStep = 0;
    float yStep = 0;

    float[] xCoords = new float[cols];
    float[] yCoords = new float[rows];

    public Board(Context context)
    {
        super(context); 
        pBack.setARGB(255, 255, 102, 0);
        pDot.setARGB(255, 255, 255, 255);

        pLine.setStrokeWidth(5);
        pLine.setARGB(255, 90, 10, 0);
    }

    public void setDots(boolean[][] dotSelected)
    {
        this.dots = dotSelected;
    }

    public boolean[][] getDots()
    {
        return dots;
    }

    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        canWidth = w;
        canHeight = h;

        xStep = canWidth / (cols + 1);
        yStep = canHeight / (rows + 1);

        for (int y = 0; y < rows; y++)
        {
            yCoords[y] = (y + 1) * yStep;
        }

        for (int x = 0; x < cols; x++)
        {
            xCoords[x] = (x + 1) * xStep;
        }           
    }

    protected void onDraw(Canvas canvas) 
    {
        super.onDraw(canvas);
        canvas.drawPaint(pBack);

        // Grid, lines and box markings
        for (int y = 0; y < rows; y++)
        {
            canvas.drawLine(xStep, yCoords[y], cols * xStep, yCoords[y], pDot);

            for (int x = 0; x < cols; x++)
            {
                if (y == 0)
                {
                    canvas.drawLine(xCoords[x], yStep, xCoords[x], rows * yStep, pDot);
                }

                if (dots[x][y])
                {
                    boolean left = x > 0 && dots[x - 1][y];
                    boolean up = y > 0 && dots[x][y - 1];

                    if (left)
                    {
                        canvas.drawLine(xCoords[x], yCoords[y], xCoords[x - 1], yCoords[y], pLine);
                    }

                    if (up)
                    {
                        canvas.drawLine(xCoords[x], yCoords[y], xCoords[x], yCoords[y - 1], pLine);
                    }

                    if (left && up && dots[x - 1][y - 1])
                    {
                        canvas.drawCircle(xCoords[x] - xStep / 2, yCoords[y] - yStep / 2, 10, pLine);
                    }
                }
            }
        }

        // Dots
        for (int y = 0; y < rows; y++)
        {
            for (int x = 0; x < cols; x++)
            {
                canvas.drawCircle(xCoords[x], yCoords[y], 20, pDot);                    
                if (dots[x][y])
                {
                    canvas.drawCircle(xCoords[x], yCoords[y], 15, pBack);                       
                }                                       
            }
        }
    }

    public boolean onTouchEvent(MotionEvent event)
    {
        super.onTouchEvent(event);

        if (event.getAction() != MotionEvent.ACTION_DOWN)
            return true;

        int xNear = 0;
        int yNear = 0;

        float xMin = canWidth;
        float yMin = canHeight;

        for (int x = 0; x < cols; x++)
        {
            if (Math.abs(xCoords[x] - event.getX()) < xMin)
            {
                xMin = Math.abs(xCoords[x] - event.getX());
                xNear = x;
            }
        }

        for (int y = 0; y < rows; y++)
        {
            if (Math.abs(yCoords[y] - event.getY()) < yMin)
            {
                yMin = Math.abs(yCoords[y] - event.getY());
                yNear = y;
            }
        }

        dots[xNear][yNear] = !dots[xNear][yNear];
        invalidate();

        return true;
    }
}

【讨论】:

  • 你能从Play商店下载这个游戏吗? play.google.com/store/apps/details?id=com.ruslana.dotsandboxes它会让你清楚我的游戏想法。
  • 我照原样复制这个想法。
  • 我测试了你的代码。它允许对角线选择。这是不允许的。它应该一次只允许两个圆圈来绘制线条。
  • 还有一件事,它允许用户同时选择和取消选择。这是不允许的,而是应该允许玩家在一个回合中选择两个圆圈。选择一个圆圈后,他只能选择紧邻其上或左或右或下侧的圆圈。
  • 如何限制对角线选择?
【解决方案2】:

将你的圆圈的数据(例如位置和半径)存储在一个列表中,并检查每个圆圈是否有鼠标碰撞(注册一个 mouseeventlistener)。

public class Circle
{
private int radius;
private int positionX;
private int positionY;

public Circle(int positionX, int positionY, int radius)
{
this.radius = radius;
this.positionX = positionX;
this.positionY = positionY;
}

public int getPositionX()
{
return this.positionX;
}

public int getPositionY()
{
return this.positionY;
}


public boolean contains(int posX, int posY)
{
int distanceX = this.positionX - posX;
int distanceY = this.positionY - posY;

return Math.sqrt((distanceX * distanceX) + (distanceY * distanceY)) <= this.radius;
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多