tags:

views:

221

answers:

2
+2  Q: 

Crosshairs in Java

I am making a game that needs a crosshair. I have been playing with the java.awt.cursor class and that is easy enough, but the problem is that I do not want the crosshairs to be able to leave the window I create for my game, so I tried this instead:

  private void drawCrossHair(Graphics g){
    Ellipse2D ellipse = new Ellipse2D.Float();
    ellipse.setFrame(crossHair.x, crossHair.y, 36, 36);
    Color yellow = new Color (0xEDFF62);
    g.setColor(yellow);            
    g.fillOval(crossHair.x, crossHair.y, 40, 40);
    g.setClip(ellipse);
    g.clip(ellipse);

Basically I am trying to remove the "ellipse" from "g" leaving only a small ring behind. The problem here is that "g.clip(ellipse);" gives me an error. My objective with this code is to create a circle with a transparent center, like a donut. Once the donut is created I will add some small points on the inside of it so it looks more like crosshairs. One thing that may or may not be an issue is that I plan on moving the crosshairs with a joystick, not a mouse... I do not know if that will limit my options for what kind of object my crosshairs can be.

EDIT:

Here is a SSCCE version (well almost... does not compile due to "g2 = bf.getDrawGraphics()")

package game;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
import java.awt.geom.Ellipse2D;

public class Game extends JFrame {

    private int windowWidth = 1280;
    private int windowHeight = 1024;
        private Ball crossHair;

    public static void main(String[] args) {
        new Game();
    }
    public Game() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(windowWidth, windowHeight);
        this.setResizable(false);
        this.setLocation(0,0);
        this.setVisible(true);
        this.createBufferStrategy(2);
        initGame();
        gameLoop();
    }
    private void initGame() {
            crossHair = new Ball (windowWidth/2, windowHeight/2, 3, 3);
    }

        private void gameLoop() {
            //game logic
            drawFrame();              
        }

        private void drawFrame() {

            //Setting up Double Buffering
            BufferStrategy bf = this.getBufferStrategy();
            Graphics2D g2 = (Graphics2D)bf.getDrawGraphics();

            try {
                g2 = bf.getDrawGraphics();
                Color darkBlue = new Color(0x010040);

                g2.setColor(darkBlue);
                g2.fillRect(0, 0, windowWidth, windowHeight);

                drawCrossHair(g2);
            } finally {
                // dispose of graphic.
                g2.dispose();
            }

            // show contents of backbuffer on screen
            bf.show();

            Toolkit.getDefaultToolkit().sync();
        }

        private void drawCrossHair(Graphics2D g2){
            Color yellow = new Color (0xEDFF62);
            g2.setColor(yellow);            
            g2.fillOval(crossHair.x, crossHair.y, 40, 40);
            Ellipse2D ellipse = new Ellipse2D.Float();
            ellipse.setFrame(crossHair.x, crossHair.y, 36, 36);
            g2.setClip(ellipse);
            g2.clip(ellipse);
        }  
}

And here is another class in the same package:

package game;

public class Ball {
    public int x;
    public int y;
    public int dx;
    public int dy;

    public Ball(int x, int y, int dx, int dy) {
        this.x = x;
        this.y = y;
        this.dx = dx;
        this.dy = dy;
    }
}

EDIT 2:

Here is my latest attempt, this seems to work ok... please let me know if this is bad coding (I got the idea here):

private void drawCrossHair(Graphics g){
    Color yellow = new Color (0xEDFF62);
    g.setColor(yellow);
    for (int i = 0; i < 1; i++) {
    g.drawOval(crosshair.x + i, crosshair.y + i, 40 - i - i, 40 - i - i);
    }
    g.fillArc(crosshair.x + 10, crosshair.y + 21 , 20, 20, -45, -90);
    g.fillArc(crosshair.x - 1, crosshair.y + 10, 20, 20, -135, -90);
    g.fillArc(crosshair.x + 10, crosshair.y - 1, 20, 20, -225, -90);
    g.fillArc(crosshair.x + 21, crosshair.y + 10, 20, 20, -315, -90);
}
+2  A: 

What kind of error?

A compilation error I'm thinking because Graphics doesn't have a clip method. Graphics2D does.

You can draw a donut shape just with an ellipse and a stroke size < radius.

g.setStroke(new BasicStroke(2.0f));
g.drawOval(crossHair.x, crossHair.y, 40, 40);
tom
I didn't realize there was a difference between Graphic and Graphic2D, thank you for enlightening me. So far all of my code is based on Graphics, not Graphics2D, so if I can stick with Graphics I think that would make my life easier. Is there another way I can do this with Graphics?
typoknig
As far as I'm aware, the graphics object used is always actually a Graphics2D, but is declared as Graphics due to the method signature.Graphics2D g2 = (Graphics2D) g;If you're worried about encountering a DebugGraphics or something you could do an instanceof first
tom
I am using BufferStrategy getDrawGraphics, and that does not work with Graphics2D. Since I am a Java noob what would be the BufferStrategy getDrawGraphics equivalent in Graphics2D?
typoknig
not sure. I don't think you need the clip() method, which means you don't need Graphics2D.
tom
Isn't the code you posted based on Graphics2D?
typoknig
Sorry maybe I wasn't clear. The code I gave will work with any Graphics. The only reason I mention Graphics2D is that it has a clip method, which your code tried to use. You don't need it
tom
+2  A: 

but the problem is that I do not want the crosshairs to be able to leave the window I create for my game,

It doesn't. The cursor gets reset when the mouse moves off the frame or component.

Again, post your SSCCE showing the problem.

camickr
What I meant was that the crosshairs should be captured in the window if the crosshairs are being created from the mouse (like how a virtual machine captures the mouse and will not let it leave) OR the crosshairs need to be independent of the mouse (since they are going to be controlled by a joystick). I didn't think that posting my entire code would be necessary for such a simple problem, but if you need it I will gladly provide it.
typoknig
Well, I still don't know what you are trying to do and you still haven't posted a SSCCE. The code you posted does not compile. I tried to fix it but don't know if I made any mistakes. When I run the code I simple see an empty frame with no painting. I don't know why you are use a BufferStrategy. Swing is double buffered by default. Read the section from the Swing tutorial on Custom Painting: http://java.sun.com/docs/books/tutorial/uiswing/TOC.html.
camickr
I stated that it did not compile. I used BufferStrategy because that is what the tutorial I was using said to use. I am very new at Java so I am far from knowing what should be used where and when, I just read as much as I can to get the info I need to make stuff work. I will read through the link you posted.
typoknig
I'm not going to have time to get back on this project for another couple of months. Camickr, you have helped me before so maybe when I have some more time I will post a revised edition of this question for you to ponder. Thanks for your help guys.
typoknig