I recently took all my code a manually imported it into an eclipse project from BlueJ, I then got use to the settings up "Run Configurations", finally thinking I was home free. Then I ran the code, and I got this error
java.lang.NoSuchMethodError: main
Exception in thread "main"
so I figured I had to add a main method (I never had to do this in BlueJ, why?). So I did that just called the constructor method (in BlueJ I would just create a new object and the JFrame would show). So I did that, same error. After trying different things (such as moving the code in the constructor to a different method etc.). I just put this in for the main method:
public void main(String[] args)
{
System.out.println("Hello, this is main why won't Java find this.");
}
After that I still got the same error, so I then decided to add it to all my classes to make sure it wasn't using another class as the main class. Still same error, so I come to you wondering if any of you have encountered this problem. Also I did search Google and all I found was problems with private classes etc and sense all my classes are public (hey I come from Python :) ). I knew that wasn't the problem. Help Please :)
Picture of my Run Configuration
This is my main method code
WARNING: LONG
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class AppFrame extends JFrame
{
public String status = "Status:";// Status of Applet
public int paint_count = 1;// Number of times applet has been painted
public int[] mousePos = {-1, -1};// Stores Mouse's Last Clicked X and Y Cordinates
public int[] boardPos = {-1, -1};//Stores The Board's X and Y Cordinates
public int[] selectedSquarePos = {-1, -1};
public int[] boardSquare = {-1, -1};//Stores Last Clicked Square
public Color P1_Color = Color.GRAY;
public Color P2_Color = Color.WHITE;
public Color SquareEven = Color.BLACK;
public Color SquareOdd = Color.RED;// pieces move on this one
public int boardHeight = 400;
public int boardWidth = 400;
public boolean pieceSelected = false;
public boolean CheckersPiece = false;
public Board CheckersBoard = new Board();
public Image buffer = null;
public Graphics bg = null;
public void main(String[] args)
{
System.out.println("Hello, this is main why won't Java find this.");
}
public AppFrame()
{
super("JCheckers");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(900,900);
setVisible(true);
buffer = createImage(getWidth(), getHeight());
boardHeight = getHeight() - 40; // 20 pixel border at top and bottom and 20 pixels for blue bar
boardWidth = getWidth() - 40; // 20 pixel border at left and right
bg = buffer.getGraphics();
addMouseListener(new MouseAdapter()
{
public void mouseClicked (MouseEvent e)
{
handleClick(e);
}
}
);
}
public void handleClick(MouseEvent e)
{
/* Handles tracking of mouse clicks; DOES NOT HANDLE DISPLAY, it just updates the data and calls redraw */
mousePos[0] = e.getX();
mousePos[1] = e.getY();
repaint();
}
public void paint(Graphics g)
{
super.paint(g);
render(g);
}
public void render(Graphics g)
{
bg.clearRect(0,0, getWidth(), getHeight());
//Draw Chess Board and Pieces
renderChessBoard(bg, 20, 20);
// Display Info
System.out.println(status);
System.out.println(String.format("Last Mouse Click # (X:%d Y:%d)", mousePos[0], mousePos[1]) );
System.out.println("Paint #" + paint_count );
System.out.println(String.format("Board Square (x:%s, y:%s) %b", boardSquare[0], boardSquare[1], CheckersPiece) );
System.out.println(CheckersBoard.status );
paint_count += 1;
// Draw Image to Screen
g.drawImage(buffer, 0, 25, null);// so it does not get hidden by the blue close/min/max room
}
public boolean isValidSquare(int col, int row)
{
if (col > -1 & col < 8) {return true;}
return false;
}
public void renderChessBoard(Graphics g, int x, int y)
{
/* Renders board and pieces*/
// sense the row squares are well squares then the
// board will be a square also; so we draw it with whatever
// side is smallest, width or height
boardPos[0] = x;
boardPos[1] = y;
drawBoard(g, x, y, boardWidth, boardHeight);
boardSquare = getBoardSquare(mousePos[0], mousePos[1]);
CheckersPiece = isCheckersPiece(boardSquare[0], boardSquare[1]);
boolean validSquare = isValidSquare(boardSquare[0], boardSquare[1]);
if (validSquare)
{
if (CheckersPiece)
{
selectSquare(g, boardSquare[0], boardSquare[1]);
}
else
{
if (pieceSelected)
{
int selectedCol = selectedSquarePos[0];
int selectedRow = selectedSquarePos[1];
int toCol = boardSquare[0];
int toRow = boardSquare[1];
System.out.println(selectedCol + " " + selectedRow + " " + toCol + " " + toRow);
if (!CheckersBoard.move(selectedSquarePos, boardSquare)) // not a valid move;
{
pieceSelected = false;
}
}
}
}
parseBoard(CheckersBoard.board, g);
}
public void drawBoard(Graphics g, int Bx, int By, int Bw, int Bh)
{
int numberRowsDrawed = 0;
int rH = Bh / 8;
int rW = Bw; // Row width is the same as the Board's width because the board and the row share the same sides
while (numberRowsDrawed < 8)
{
int rY = (numberRowsDrawed * rH) + By;
// Row X is the same as the Board X because the board and the row share the same sides
int rX = Bx;
Color EVEN = SquareEven;
Color ODD = SquareOdd;
// Yes Yes The EVEN Color is now odd and vica versa its because rows only now there row counts and so they start at 0 and don't
// include the rows above
if ((numberRowsDrawed % 2) != 0) {EVEN = SquareOdd; ODD = SquareEven;}
drawRow(g, rX, rY, rW, rH, EVEN, ODD);
numberRowsDrawed +=1;
}
}
public void drawRow(Graphics g, int x, int y, int width, int height, Color EVEN, Color ODD)
{
System.out.println("Board Y: " + y);
int squareW = width / 8;
int squareH = height;
int numberSquaresCreated = 0;
while (numberSquaresCreated < 8)
{
// needs a special case because Java's modulo uses division (so it would give a divide by 0 error) STUPID JAVA!!!!!!
if (numberSquaresCreated == 0)
{
g.setColor(EVEN);
g.fillRect(x, y, squareW, squareH);
}
else
{
if (numberSquaresCreated % 2 == 0){g.setColor(EVEN);}
else {g.setColor(ODD);}
int sX = x + (squareW * numberSquaresCreated);
g.fillRect(sX, y, squareW, squareH);
}
numberSquaresCreated +=1;
}
}
public void drawMan(Graphics g, int boardRow, int boardCol, Color pieceColor)
{
int x = boardPos[0];
int y = boardPos[1];
int pixelPosX = x + ((boardWidth / 8) * boardRow);
int pixelPosY = y + ((boardHeight / 8) * boardCol);
g.setColor(pieceColor);
g.fillOval(pixelPosX + 13, pixelPosY + 13, (boardWidth / 8) - 26, (boardHeight / 8) - 26);
}
public void drawKing(Graphics g, int boardRow, int boardCol, Color pieceColor, Color crownColor)
{
drawMan(g, boardRow, boardCol, pieceColor);
g.setColor(crownColor);
int x = boardPos[0];
int y = boardPos[1];
double DsizeFactor = ( (float) boardHeight / 8.0) / 3.75;
int sizeFactor = (int) DsizeFactor;
int pixelPosX = x + ((boardWidth / 8) - sizeFactor) / 2 + ((boardWidth / 8) * boardRow);
int pixelPosY = y + ((boardHeight / 8) - sizeFactor) / 2 + ((boardHeight / 8) * boardCol);
int[] xPoints = {pixelPosX, pixelPosX, pixelPosX + sizeFactor, pixelPosX + sizeFactor, pixelPosX + ((sizeFactor * 3) / 4), pixelPosX + (sizeFactor / 2), pixelPosX + (sizeFactor / 4) };
int[] yPoints = {pixelPosY, pixelPosY + sizeFactor, pixelPosY + sizeFactor, pixelPosY, pixelPosY + (sizeFactor / 2), pixelPosY, pixelPosY + (sizeFactor / 2)};
g.fillPolygon(xPoints, yPoints, 7);
}
public void selectSquare(Graphics g, int bSX, int bSY)
{
g.setColor(Color.YELLOW);
/*+10 is to offset text (the xy cordinates are the bottom left side of the text NOT top left.*/
pieceSelected = true;
int squareX = boardPos[0] + (boardWidth / 8) * bSX;
int squareY = 10 + boardPos[1] + (boardHeight / 8) * bSY;
selectedSquarePos[0] = bSX;
selectedSquarePos[1] = bSY;
g.drawString("Selected", squareX, squareY);
}
// Data Handling and Retreiving methods
public void parseBoard(String[][] Board, Graphics g)
{
int row = 0;
int col = 0;
for (String[] rowOfPieces : Board)
{
for (String piece : rowOfPieces)
{
if (piece != "X")
{
Color PIECE_COLOR = P1_Color;
if (piece.contains("P2")) {PIECE_COLOR = P2_Color;}
if (piece.contains("C"))
{
drawMan(g, col, row, PIECE_COLOR);
}
if (piece.contains("K"))
{
Color Crown_Color = P2_Color;
if (PIECE_COLOR != P1_Color) {Crown_Color = P1_Color;}
drawKing(g, col, row, PIECE_COLOR, Crown_Color);
}
}
col+=1;
}
row +=1;
col = 0;
}
}
public int[] getBoardSquare(int x, int y)
{
//row or col = boardpos - offset / row height or width
if ((x < boardPos[0]) | (y < boardPos[1]) | (x > (boardPos[0] + boardWidth)) | (y > (boardPos[1] + boardHeight)) )
{
int[] BS = {-1, -1};
return BS;
}
int col = (x - boardPos[0]) / (boardWidth / 8);
int row = (y - boardPos[1]) / (boardHeight / 8);
int[] BS = {col, row};
return BS;
}
public boolean isCheckersPiece(int BoardSquareX, int BoardSquareY)
{
int Px = BoardSquareX;
int Py = BoardSquareY;
if (Px == -1 & Py == -1)
{
return false;
}
String Square = CheckersBoard.board[Py][Px];
return Square != "X";
}
}
You forgot static:
public static void main(String[] args)
But in order to really start your application, you should launch it from that method, not merely have it. Here is how to start it:
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
AppFrame frame = new AppFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
It's important to note the EXIT_ON_CLOSE - this will make the JVM exit when you press the X button. Otherwise your application will continue running, and you might even not notice.
Make main static.
Related
I am well and truly stuck on this method. I need to create an attack method for a ComputerPlayer that chooses a random location and attacks the other player's board. Then, there is an attack method where I have to just attack the other player's board. However, when I run the program and place my guesses on my board (GUI), the dots just appear on the ComputerPlayer's board. I don't know why my methods are wrong though.
/**
* Attack the specified Location loc. Marks
* the attacked Location on the guess board
* with a positive number if the enemy Player
* controls a ship at the Location attacked;
* otherwise, if the enemy Player does not
* control a ship at the attacked Location,
* guess board is marked with a negative number.
*
* If the enemy Player controls a ship at the attacked
* Location, the ship must add the Location to its
* hits taken. Then, if the ship has been sunk, it
* is removed from the enemy Player's list of ships.
*
* Return true if the attack resulted in a ship sinking;
* false otherwise.
*
* #param enemy
* #param loc
* #return
*/
#Override
public boolean attack(Player enemy, Location loc)
{
int[][] array = getGuessBoard();
if(!enemy.hasShipAtLocation(loc))
array[loc.getRow()][loc.getCol()] = -1;
else
{
array[loc.getRow()][loc.getCol()] = 1;
enemy.getShip(loc).takeHit(loc);
}
if(enemy.getShip(loc).isSunk()) {
enemy.removeShip(enemy.getShip(loc));
return true;
}
return false;
}
#Override
public boolean attack(Player enemy, Location loc)
{
int range = (10 - 0) + 1;
int r = (int) Math.random() * range;
int c = (int) Math.random() * range;
int[][] array = getGuessBoard();
if(array[r][c] != -1)
{
if(!enemy.hasShipAtLocation(loc))
array[loc.getRow()][loc.getCol()] = -1;
else
{
array[loc.getRow()][loc.getRow()] = 1;
enemy.getShip(loc).takeHit(loc);
}
if(getShip(loc).isSunk())
{
enemy.removeShip(enemy.getShip(loc));
return true;
}
}
return false;
}
GUI for Game
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class BattleshipDriver extends Canvas implements MouseListener
{
public static final int WIDTH = 1024, HEIGHT = WIDTH / 12 * 9;
private Battleship battleship;
private int x, y, squareSize, len;
private Player p1, p2;
private BufferedImage logo, end;
public BattleshipDriver()
{
battleship = new Battleship();
battleship.addPlayer(new HumanPlayer("Mr. Hubbard"));
battleship.addPlayer(new ComputerPlayer("AlphaBattleship"));
x = 90;
y = 200;
squareSize = 36;
len = squareSize * 10 - 1;
p1 = battleship.getPlayer(0);
p2 = battleship.getPlayer(1);
// Get Battleship Logo
try {
logo = ImageIO.read(new File("src/Logo.png"));
} catch (IOException e) {
e.printStackTrace();
}
// Get End Screen
try {
end = ImageIO.read(new File("src/End.png"));
} catch (IOException e) {
e.printStackTrace();
}
addMouseListener(this);
new Window(WIDTH, HEIGHT, "Battleship", this);
try {
Thread.sleep(100);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
render();
}
private void render()
{
Graphics g = getGraphics();
// Background
g.setColor(Color.DARK_GRAY);
g.fillRect(0, 0, WIDTH, HEIGHT);
if(!battleship.gameOver())
{
// Boards
renderGrid(g, x, y, squareSize);
renderGuesses(g, p1, x, y, squareSize);
renderGrid(g, 570, y, squareSize);
renderGuesses(g, p2, 570, y, squareSize);
// Names
g.setColor(Color.WHITE);
g.drawString(p1.getName(), x, y + 25 + len);
g.drawString(p2.getName(), 570, y + 25 + len);
}
else
{
// End Screen
g.drawImage(end, 0, 0, this);
g.setColor(Color.WHITE);
g.setFont(new Font("Arial", 1, squareSize));
String winner = battleship.getWinner().getName();
g.drawString(winner, WIDTH / 2 - (winner.length() * squareSize / 4), HEIGHT / 4);
g.drawString("Wins!", WIDTH / 2 - ("Wins!".length() * squareSize / 4), HEIGHT / 4 + squareSize);
}
// Battleship Logo
g.drawImage(logo, WIDTH / 2 - 246, 10, this);
g.dispose();
}
private void renderGrid(Graphics g, int x, int y, int s)
{
g.setColor(Color.WHITE);
g.setFont(new Font("Arial", 1, s / 2));
// Row Lines
for(int i = 0; i < 11; i++)
g.drawLine(x, y+i*s, x+len, y+i*s);
// Column Lines
for(int i = 0; i < 11; i++)
g.drawLine(x+i*s, y, x+i*s, y+len);
// Row Markers
for(int i = 0; i < 10; i++) //marks row coordinates on side
g.drawString(i + "", x-(int)(s*0.43), y+(int)(s*0.67)+s*i);
// Column Markers
for(int i = 0; i < 10; i++) //marks column coordinates on top
g.drawString(i + "", x+(int)(s*0.4)+s*i, y-(int)(s*0.2));
}
public void renderGuesses(Graphics g, Player player, int x, int y, int s)
{
int[][] guessBoard = player.getGuessBoard();
for(int r = 0; r < guessBoard.length; r++)
for(int c = 0; c < guessBoard[r].length; c++)
if(guessBoard[r][c] > 0) // hit
{
g.setColor(Color.RED);
g.fillOval(c*s+x+(int)(s*0.35), r*s+y+(int)(s*0.35), (int)(s*0.33), (int)(s*0.33));
}
else if(guessBoard[r][c] < 0) // miss
{
g.setColor(Color.WHITE);
g.fillOval(c*s+x+(int)(s*0.35), r*s+y+(int)(s*0.35), (int)(s*0.33), (int)(s*0.33));
}
}
#Override
public void mouseClicked(MouseEvent e)
{
int r = e.getY();
int c = e.getX();
int len = squareSize * 10 - 1;
if(r > y && r < y + len && c > x && c < x + len) // clicked on board
{
int row = (r - y) / squareSize;
int col = (c - x) / squareSize;
System.out.println(row + ", " + col);
Location loc = new Location(row, col);
if(p1.getGuessBoard()[row][col] == 0)
{
p1.attack(p2, loc);
p2.attack(p1, loc);
}
battleship.upkeep();
render();
}
System.out.println(r + ", " + c);
}
#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)
{
new BattleshipDriver();
}
}
I am not great at programming but I am trying to learn, I have been following a tutorial on youtube and the youtuber uses 4 shades of monochromatic colours but I find it difficult to make sprites with that limitation so I am trying to up it to 8 shades but when I try and change it it just loops the first 4 colours.
Below is the colour class, screen class and tile class. I can upload any other classes ye need.
package com.alan.game.level.tiles;
import com.alan.game.gfx.Colours;
import com.alan.game.gfx.Screen;
import com.alan.game.level.Level;
public abstract class Tile {
public static final Tile[] tiles = new Tile[256];
public static final Tile VOID = new BasicTile(0, 0, 0, Colours.get(000, -1, -1, -1, -1, -1, -1, -1));
public static final Tile STONE = new BasicTile(1, 1, 0, Colours.get(000, 002, 003, 004, 000, 000, 000, 000));
public static final Tile GRASS = new BasicTile(2, 2, 0, Colours.get(-1, 131, 141, -1, -1, -1,- 1, -1));
protected byte id;
protected boolean solid;
protected boolean emitter;
public Tile(int id, boolean isSolid, boolean isEmitter){
this.id = (byte) id;
if(tiles[id] != null) throw new RuntimeException("Duplicate tile id on " + id);
this.solid = isSolid;
this.emitter = isEmitter;
tiles[id] = this;
}
public byte getId(){
return id;
}
public boolean isSolid(){
return solid;
}
public boolean isEmitter(){
return emitter;
}
public abstract void render(Screen screen, Level level, int x, int y);
}
package com.alan.game.gfx;
public class Screen {
public static final int MAP_WIDTH = 64;
public static final int MAP_WIDTH_MASK = MAP_WIDTH - 1;
public int[] pixels;
public int xOffset = 0;
public int yOffset = 0;
public int width;
public int height;
public SpriteSheet sheet;
public Screen(int width, int height, SpriteSheet sheet){
this.width = width;
this.height = height;
this.sheet = sheet;
for(int i = 0; i < MAP_WIDTH * MAP_WIDTH; i++){
pixels = new int[width * height];
}
}
public void setOffset(int xOffset, int yOffset){
this.xOffset = xOffset;
this.yOffset = yOffset;
}
public void render(int xPos, int yPos, int tileIndex, int colour){
render(xPos, yPos, tileIndex, colour, false, false);
}
public void render(int xPos, int yPos, int tileIndex, int colour, boolean mirrorX, boolean mirrorY){
xPos -= xOffset;
yPos -= yOffset;
int xTile = tileIndex % 32;
int yTile = tileIndex / 32;
int tileOffset = (xTile << 3) + (yTile << 3) * sheet.width;
for(int y = 0; y < 8; y++){
int ySheet = y;
if(mirrorY) ySheet = 7 - y;
if(y + yPos < 0 || y + yPos >= height) continue;
for(int x = 0; x < 8; x++){
int xSheet = x;
if(mirrorX) xSheet = 7 - x;
if(x + xPos < 0 || x + xPos >= width) continue;
int col = (colour >> (sheet.pixels[xSheet + ySheet * sheet.width + tileOffset] * 8)) & 255;
if(col < 255) pixels[(x + xPos) + (y + yPos) * width] = col;
}
}
}
}
package com.alan.game.gfx;
public class Colours {
public static int get(int colour1, int colour2, int colour3, int colour4, int colour5, int colour6, int colour7, int colour8){
return (get(colour8) << 56) + (get(colour7) << 48) + (get(colour6) << 40) + (get(colour5) << 32) + (get(colour4) << 24) + (get(colour3) << 16) + (get(colour2) << 8) + get(colour1);
}
private static int get(int colour){
if(colour < 0) return 255;
int r = colour / 100 % 10;
int g = colour / 10 % 10;
int b = colour % 10;
return r * 36 + g * 6 + b;
}
}
I ran into the same problem. First thing I already think is a problem is that we're bitshifting 56 on colour 8. An integer can contain a maximum of 32 bits. So by shifting it 56, we're completely getting rid of any data that we had there (if I'm correct).
So I tried changing it to return a long, but that doesn't solve anything either. I know this is not a real answer, but I hope this regains some attention, because I'm stuck on this now too!
I have a problem with a hexagonal grid. I found this code you can see below on Internet, so it's not mine. There are two public classes: hexgame which generates the grid and hexmech which draws and fills every single hexagon. What I'd like to do is basically insert an image into a specific hexagon, but I don't know how to code this and in which part of the classes I should put it. Am I thinking the wrong way?
Thank you very much for your help!
Hexgame
package hex;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class hexgame
{
private hexgame() {
initGame();
createAndShowGUI();
}
final static Color COLOURBACK = Color.WHITE;
final static Color COLOURCELL = Color.WHITE;
final static Color COLOURGRID = Color.BLACK;
final static Color COLOURONE = new Color(255,255,255,200);
final static Color COLOURONETXT = Color.BLUE;
final static Color COLOURTWO = new Color(0,0,0,200);
final static Color COLOURTWOTXT = new Color(255,100,255);
final static Color COLOURSAFE = Color.WHITE;
final static Color COLOURDANGEROUS = Color.LIGHT_GRAY;
final static int EMPTY = 0;
final static int UNKNOWN = -1;
final static int SAFE = 1;
final static int DANGEROUS = 2;
final static int CLICKED = 3;
final static int COLUMN_SIZE = 23;
final static int ROW_SIZE = 14;
final static int HEXSIZE = 45;
final static int BORDERS = 15;
int[][] board = new int[COLUMN_SIZE][ROW_SIZE];
void initGame(){
hexmech.setXYasVertex(false);
hexmech.setHeight(HEXSIZE);
hexmech.setBorders(BORDERS);
for (int i=0;i<COLUMN_SIZE;i++) {
for (int j=0;j<ROW_SIZE;j++) {
board[i][j]=EMPTY;
}
}
board[5][5] = SAFE;
board[5][6] = SAFE;
board[5][7] = SAFE;
board[6][5] = SAFE;
board [6][6] = SAFE;
board[4][4] = UNKNOWN;
}
private void createAndShowGUI()
{
DrawingPanel panel = new DrawingPanel();
JFrame frame = new JFrame("Hex Testing 4");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
Container content = frame.getContentPane();
content.add(panel);
frame.setSize(825, 630);
frame.setResizable(true);
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
class DrawingPanel extends JPanel
{
public DrawingPanel()
{
setBackground(COLOURBACK);
MyMouseListener ml = new MyMouseListener();
addMouseListener(ml);
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setFont(new Font("TimesRoman", Font.PLAIN, 15));
super.paintComponent(g2);
for (int i=0;i<COLUMN_SIZE;i++) {
for (int j=0;j<ROW_SIZE;j++) {
if (board[i][j] != UNKNOWN)
hexmech.drawHex(i,j,g2);
}
}
for (int i=0;i<COLUMN_SIZE;i++) {
for (int j=0;j<ROW_SIZE;j++) {
if (board[i][j] != UNKNOWN)
hexmech.fillHex(i,j,board[i][j],g2);
}
}
}
class MyMouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
Point p = new Point( hexmech.pxtoHex(e.getX(),e.getY()) );
if (p.x < 0 || p.y < 0 || p.x >= COLUMN_SIZE || p.y >= ROW_SIZE) return;
board[p.x][p.y] = CLICKED;
repaint();
}
}
}
}
Hexmech
package hex;
import java.awt.*;
import javax.swing.*;
public class hexmech
{
#define HEXEAST 0
#define HEXSOUTHEAST 1
#define HEXSOUTHWEST 2
#define HEXWEST 3
#define HEXNORTHWEST 4
#define HEXNORTHEAST 5
public final static boolean orFLAT= true;
public final static boolean orPOINT= false;
public static boolean ORIENT= orFLAT;
public static boolean XYVertex=true;
private static int BORDERS=50
private static int s=0; // length of one side
private static int t=0; // short side of 30o triangle outside of each hex
private static int r=0; // radius of inscribed circle (centre to middle of each side). r= h/2
private static int h=0; // height. Distance between centres of two adjacent hexes. Distance between two opposite sides in a hex.
public static void setXYasVertex(boolean b) {
XYVertex=b;
}
public static void setBorders(int b){
BORDERS=b;
}
public static void setSide(int side) {
s=side;
t = (int) (s / 2); //t = s sin(30) = (int) CalculateH(s);
r = (int) (s * 0.8660254037844);
h=2*r;
}
public static void setHeight(int height) {
h = height;
r = h/2; // r = radius of inscribed circle
s = (int) (h / 1.73205); // s = (h/2)/cos(30)= (h/2) / (sqrt(3)/2) = h / sqrt(3)
t = (int) (r / 1.73205); // t = (h/2) tan30 = (h/2) 1/sqrt(3) = h / (2 sqrt(3)) = r / sqrt(3)
}
public static Polygon hex (int x0, int y0) {
int y = y0 + BORDERS;
int x = x0 + BORDERS;
if (s == 0 || h == 0) {
System.out.println("ERROR: size of hex has not been set");
return new Polygon();
}
int[] cx,cy;
if (XYVertex)
cx = new int[] {x,x+s,x+s+t,x+s,x,x-t}; //this is for the top left vertex being at x,y. Which means that some of the hex is cutoff.
else
cx = new int[] {x+t,x+s+t,x+s+t+t,x+s+t,x+t,x}; //this is for the whole hexagon to be below and to the right of this point
cy = new int[] {y,y,y+r,y+r+r,y+r+r,y+r};
return new Polygon(cx,cy,6);
}
public static void drawHex(int i, int j, Graphics2D g2) {
int x = i * (s+t);
int y = j * h + (i%2) * h/2;
Polygon poly = hex(x,y);
g2.setColor(hexgame.COLOURCELL);
//g2.fillPolygon(hexmech.hex(x,y));
g2.fillPolygon(poly);
g2.setColor(hexgame.COLOURGRID);
g2.drawString(String.format("%c;%d", 'A'+i, j+1), x+20, y+40);
g2.drawPolygon(poly);
}
public static void fillHex(int i, int j, int n, Graphics2D g2) {
char c='o';
int x = i * (s+t);
int y = j * h + (i%2) * h/2;
/*if (n < 0) {
g2.setColor(hexgame.COLOURONE);
g2.fillPolygon(hex(x,y));
g2.setColor(hexgame.COLOURONETXT);
c = (char)(-n);
g2.drawString(""+c, x+r+BORDERS, y+r+BORDERS+4); //FIXME: handle XYVertex
//g2.drawString(x+","+y, x+r+BORDERS, y+r+BORDERS+4);
}
if (n > 0) {
g2.setColor(hexgame.COLOURTWO);
g2.fillPolygon(hex(x,y));
g2.setColor(hexgame.COLOURTWOTXT);
c = (char)n;
if (n==3) {
g2.setColor(hexgame.COLOURTWO);
g2.fillPolygon(hex(x,y));
g2.setColor(hexgame.COLOURTWOTXT);
}
}
public static Point pxtoHex(int mx, int my) {
Point p = new Point(-1,-1);
//correction for BORDERS and XYVertex
mx -= BORDERS;
my -= BORDERS;
if (XYVertex) mx += t;
int x = (int) (mx / (s+t));
int y = (int) ((my - (x%2)*r)/h);
int dx = mx - x*(s+t);
int dy = my - y*h;
if (my - (x%2)*r < 0) return p; // prevent clicking in the open halfhexes at the top of the screen
//System.out.println("dx=" + dx + " dy=" + dy + " > " + dx*r/t + " <");
//even columns
if (x%2==0) {
if (dy > r) { //bottom half of hexes
if (dx * r /t < dy - r) {
x--;
}
}
if (dy < r) { //top half of hexes
if ((t - dx)*r/t > dy ) {
x--;
y--;
}
}
} else { // odd columns
if (dy > h) { //bottom half of hexes
if (dx * r/t < dy - h) {
x--;
y++;
}
}
if (dy < h) { //top half of hexes
//System.out.println("" + (t- dx)*r/t + " " + (dy - r));
if ((t - dx)*r/t > dy - r) {
x--;
}
}
}
p.x=x;
p.y=y;
return p;
}
In your implementation of paintComponent(), invoke setClip() with a suitable Shape, such as Polygon. You can size and translate the Polygon to match the destination hexagon using the createTransformedShape() method of AffineTransform. Use the coordinates of the polygon's boundary as the basis for the coordinates used in your call to drawImage(). A related example using Ellipse2D is shown here.
Aloha,
i have trouble finding the error in my java code. In my opinion everything is fine and correct but the function is not executed correctly and I dont understand why. The function should detect the difference between the colors and calculate the arithmetic mean of them.
The resilt of it should be draw under the original picture. What did I miss, please help me?
package edge;
import java.awt.Dimension;
import java.awt.FileDialog;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
import javax.swing.JComponent;
import javax.swing.JFrame;
/**
*
* #author Alaska
*/
public class Edge extends JComponent {
final int W = 500;
final int H = 300;
Image m_TrgImg, m_SrcImg;
public Edge(JFrame father) {
try {
FileDialog diag = new FileDialog(father);
diag.setVisible(true);
m_SrcImg = getToolkit().getImage(diag.getDirectory() + diag.getFile()).getScaledInstance(W, H, Image.SCALE_SMOOTH);
MediaTracker mt = new MediaTracker(this);
mt.addImage(m_SrcImg, 0);
mt.waitForAll();
int[] srcPix = new int[W * H];
int[] trgPix = new int[W * H];
PixelGrabber grab = new PixelGrabber(m_SrcImg, 0, 0, W, H, srcPix, 0, W);
grab.getPixels();
MemoryImageSource imgProd = new MemoryImageSource(W, H, trgPix, 0, W);
m_TrgImg = createImage(imgProd);
detectEdges(srcPix, trgPix);
m_TrgImg.flush();
} catch (InterruptedException e) {
System.out.println(e);
}
}
#Override
public void paintComponent(Graphics g) {
g.drawImage(m_SrcImg, 0, 0, this);
g.drawImage(m_TrgImg, 0, H, this);
}
#Override
public Dimension getPreferredSize() {
return getMinimumSize();
}
#Override
public Dimension getMinimumSize() {
return new Dimension(W, H * 2);
}
private void detectEdges(int[] srcPix, int[] trgPix) {
for (int x = 0; x < W; ++x) {
for (int y = 0; y < H; ++y) {
trgPix[y * W + x] = compColor(srcPix, x, y);
}
}
}
private int getRed(int col) {
return (col >> 16) & 255;
}
private int getGreen(int col) {
return (col >> 8) & 255;
}
private int getBlue(int col) {
return col & 255;
}
private int compColor(int[] srcPix, int x, int y) {
int red = 0;
int green = 0;
int blue = 0;
int cnt = 0;
final int IDX = y * W + x;
final int RED = getRed(srcPix[IDX]);
final int GREEN = getGreen(srcPix[IDX]);
final int BLUE = getBlue(srcPix[IDX]);
for (int dx = -1; dx <= 1; ++dx) {
for (int dy = -1; dy <= 1; ++dy) {
if (dx != 0 || dy != 0) {
final int X = x + dx;
final int Y = y + dy;
final int LOCAL_IDX = Y * W + X;
if (0 <= X && X < W && 0 <= Y && Y < H) {
++cnt;
red += Math.abs(RED - getRed(srcPix[LOCAL_IDX]));
green += Math.abs(GREEN - getGreen(srcPix[LOCAL_IDX]));
blue += Math.abs(BLUE - getBlue(srcPix[LOCAL_IDX]));
}
}
}
}
return 0xff000000 | (255 - (red / cnt) << 16) | (255 - (green / cnt) << 8) | (255 - (blue / cnt));
}
public static void main(String[] args) throws Exception {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.getContentPane().add(new Edge(f));
f.pack();
f.setVisible(true);
}
}
You need to grab.grabPixels(), not grab.getPixels().
http://docs.oracle.com/javase/7/docs/api/java/awt/image/PixelGrabber.html
Also what trashgod said about Initial Threads. You need to create your GUI with SwingUtilities.invokeLater().
Edit
The method is executed correctly but you are getting all black values on the input because your pixel array contains only the initialized values which is 0.
How to Rotate Circle with Text on TouchEvent or on TrackBallMoveEvent.
How do I create this kind of circle?
I had created a circle and rotated it also, but it always starts from 0 degrees.
Is there any other option to create this kind of circle?
Each circle have different text and each of the circles can move independently.
So, this is definitely not complete, but I think it's most of what you need.
Limitations/Assumptions
I have so far only implemented touch handling, as I think that's more difficult. If I get time later, I'll come back and add trackball handling.
I did not give the spinning discs any momentum. After the user's finger leaves the disc, it stops spinning.
I'm not sure the focus transitions between discs are 100% right. You'll have to do some testing. They're mostly right, at least.
When you mentioned Canvas in the title, I assumed that didn't mean you required this to utilize the J2ME Canvas. Writing BlackBerry apps with the RIM UI libraries is pretty much all I've done.
Solution
Essentially, I created a Field subclass to represent each disc. You create the field by passing in an array of labels, to be spaced around the perimeter, a radius, and a color. Hardcoded in each DiscField is an edge inset for the text, which kind of assumes a certain size difference between discs. You should probably make that more dynamic.
public class DiscField extends Field {
/** Used to map Manager's TouchEvents into our coordinate system */
private int _offset = 0;
private int _radius;
private int _fillColor;
private double _currentRotation = 0.0;
private double _lastTouchAngle = 0.0;
private boolean _rotating = false;
private String[] _labels;
/** Text inset from outer disc edge */
private static final int INSET = 30;
private DiscField() {
}
public DiscField(String[] labels, int radius, int fillColor) {
super(Field.FOCUSABLE);
_labels = labels;
_radius = radius;
_fillColor = fillColor;
}
protected void layout(int width, int height) {
setExtent(Math.min(width, getPreferredWidth()), Math.min(height, getPreferredHeight()));
}
private void drawFilledCircle(Graphics g, int x, int y, int r) {
// http://stackoverflow.com/a/1186851/119114
g.fillEllipse(x, y, x + r, y, x, y + r, 0, 360);
}
private void drawCircle(Graphics g, int x, int y, int r) {
g.drawEllipse(x, y, x + r, y, x, y + r, 0, 360);
}
protected void paint(Graphics graphics) {
int oldColor = graphics.getColor();
graphics.setColor(_fillColor);
drawFilledCircle(graphics, _radius, _radius, _radius);
graphics.setColor(Color.WHITE);
drawCircle(graphics, _radius, _radius, _radius);
// plot the text around the circle, inset by some 'padding' value
int textColor = (_fillColor == Color.WHITE) ? Color.BLACK : Color.WHITE;
graphics.setColor(textColor);
// equally space the labels around the disc
double interval = (2.0 * Math.PI / _labels.length);
for (int i = 0; i < _labels.length; i++) {
// account for font size when plotting text
int fontOffsetX = getFont().getAdvance(_labels[i]) / 2;
int fontOffsetY = getFont().getHeight() / 2;
int x = _radius + (int) ((_radius - INSET) * Math.cos(i * interval - _currentRotation)) - fontOffsetX;
int y = _radius - (int) ((_radius - INSET) * Math.sin(i * interval - _currentRotation)) - fontOffsetY;
graphics.drawText(_labels[i], x, y);
}
graphics.setColor(oldColor);
}
protected void drawFocus(Graphics graphics, boolean on) {
if (on) {
int oldColor = graphics.getColor();
int oldAlpha = graphics.getGlobalAlpha();
// just draw a white shine to indicate focus
graphics.setColor(Color.WHITE);
graphics.setGlobalAlpha(80);
drawFilledCircle(graphics, _radius, _radius, _radius);
// reset graphics context
graphics.setColor(oldColor);
graphics.setGlobalAlpha(oldAlpha);
}
}
protected void onUnfocus() {
super.onUnfocus();
_rotating = false;
}
protected boolean touchEvent(TouchEvent event) {
switch (event.getEvent()) {
case TouchEvent.MOVE: {
setFocus();
// Get the touch location, within this Field
int x = event.getX(1) - _offset - _radius;
int y = event.getY(1) - _offset - _radius;
if (x * x + y * y <= _radius * _radius) {
double angle = MathUtilities.atan2(y, x);
if (_rotating) {
// _lastTouchAngle only valid if _rotating
_currentRotation += angle - _lastTouchAngle;
// force a redraw (paint) with the new rotation angle
invalidate();
} else {
_rotating = true;
}
_lastTouchAngle = angle;
return true;
}
}
case TouchEvent.UNCLICK:
case TouchEvent.UP: {
_rotating = false;
return true;
}
case TouchEvent.DOWN: {
setFocus();
int x = event.getX(1) - _offset - _radius;
int y = event.getY(1) - _offset - _radius;
if (x * x + y * y <= _radius * _radius) {
_lastTouchAngle = MathUtilities.atan2(y, x);
_rotating = true;
return true;
}
}
default:
break;
}
return super.touchEvent(event);
}
protected boolean trackwheelRoll(int arg0, int arg1, int arg2) {
return super.trackwheelRoll(arg0, arg1, arg2);
// TODO!
}
public int getPreferredHeight() {
return getPreferredWidth();
}
public int getPreferredWidth() {
return 2 * _radius;
}
public String[] getLabels() {
return _labels;
}
public void setLabels(String[] labels) {
this._labels = labels;
}
public int getRadius() {
return _radius;
}
public void setRadius(int radius) {
this._radius = radius;
}
public double getCurrentAngle() {
return _currentRotation;
}
public void setCurrentAngle(double angle) {
this._currentRotation = angle;
}
public int getOffset() {
return _offset;
}
public void setOffset(int offset) {
this._offset = offset;
}
}
Containing all the DiscField objects is the DiscManager. It aligns the child DiscFields in sublayout(), and handles proper delegation of touch events ... since the fields overlap, and a touch within a DiscFields extent that does not also fall within its radius (i.e. the corners) should be handled by a larger disc.
/**
* A DiscManager is a container for DiscFields and manages proper delegation
* of touch event handling.
*/
private class DiscManager extends Manager {
private int _maxRadius = 0;
public DiscManager(long style){
super(style);
DiscField outerDisc = new DiscField(new String[] { "1", "2", "3", "4", "5", "6" },
180, Color.BLUE);
_maxRadius = outerDisc.getRadius();
DiscField middleDisc = new DiscField(new String[] { "1", "2", "3", "4", "5" },
120, Color.GRAY);
middleDisc.setOffset(_maxRadius - middleDisc.getRadius());
DiscField innerDisc = new DiscField(new String[] { "1", "2", "3", "4" },
60, Color.RED);
innerDisc.setOffset(_maxRadius - innerDisc.getRadius());
// order matters here:
add(outerDisc);
add(middleDisc);
add(innerDisc);
}
protected void sublayout(int width, int height) {
setExtent(2 * _maxRadius, 2 * _maxRadius);
// each disc needs to have the same x,y center to be concentric
for (int i = 0; i < getFieldCount(); i++) {
if (getField(i) instanceof DiscField) {
DiscField disc = (DiscField) getField(i);
int xCenter = _maxRadius - disc.getRadius();
int yCenter = _maxRadius - disc.getRadius();
setPositionChild(disc, xCenter, yCenter);
layoutChild(disc, 2 * _maxRadius, 2 * _maxRadius);
}
}
}
protected boolean touchEvent(TouchEvent event) {
int eventCode = event.getEvent();
// Get the touch location, within this Manager
int x = event.getX(1);
int y = event.getY(1);
if ((x >= 0) && (y >= 0) && (x < getWidth()) && (y < getHeight())) {
int field = getFieldAtLocation(x, y);
if (field >= 0) {
DiscField df = null;
for (int i = 0; i < getFieldCount(); i++) {
if (getField(field) instanceof DiscField) {
int r = ((DiscField)getField(field)).getRadius();
// (_maxRadius, _maxRadius) is the center of all discs
if ((x - _maxRadius) * (x - _maxRadius) + (y - _maxRadius) * (y - _maxRadius) <= r * r) {
df = (DiscField)getField(field);
} else {
// touch was not within this disc's radius, so the one slightly bigger
// should be passed this touch event
break;
}
}
}
// Let event propagate to child field
return (df != null) ? df.touchEvent(event) : super.touchEvent(event);
} else {
if (eventCode == TouchEvent.DOWN) {
setFocus();
}
// Consume the event
return true;
}
}
// Event wasn't for us, let superclass handle in default manner
return super.touchEvent(event);
}
}
Finally, a screen to use them:
public class DiscScreen extends MainScreen {
public DiscScreen() {
super(MainScreen.VERTICAL_SCROLL | MainScreen.VERTICAL_SCROLLBAR);
add(new DiscManager(Field.USE_ALL_WIDTH));
}
}
Results