How to navigate

Sorry about cross posting but no one didn't answer to this in game programming board.

Here is sample program that paints hearts randomly. Then it is possible to change selection using arrow keys. Currently the movement is based on random but I would like to make it working e.g. like windows desktop.

Could you help me with the navigation or provide some links to documentation where 2D navigation algorithm is explained?

import java.io.*;

import java.awt.*;

import java.awt.event.*;

import java.awt.image.*;

import javax.imageio.*;

import javax.swing.*;

import java.util.ArrayList;

import java.util.Random;

import java.util.List;

publicclass CanvasDemoextends JPanel

{

static String imageFileName ="hearts_original.png";

List<SpriteImage> images =new ArrayList<SpriteImage>();

Random rand =new Random();

boolean init =true;

public CanvasDemo ()

{

init();

Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener()

{

publicvoid eventDispatched(AWTEvent event)

{

KeyEvent ke = (KeyEvent) event;

int direction = ke.getKeyCode();

if (ke.getID() == KeyEvent.KEY_PRESSED && (

direction == KeyEvent.VK_UP ||

direction == KeyEvent.VK_DOWN ||

direction == KeyEvent.VK_LEFT ||

direction == KeyEvent.VK_RIGHT ) )

{

changeSelection( direction );

}

}

}, AWTEvent.KEY_EVENT_MASK);

}

publicvoid init()

{

buildUI();

}

publicvoid paint(Graphics g)

{

super.paint( g );

for (SpriteImage image : images)

{

image.paint2( g );

}

}

publicvoid changeSelection(int direction )

{

if( images.size() == 0 )

{

return;

}

// find out selected image

SpriteImage selected =null;

for (SpriteImage image : images)

{

if( image.getSelect() )

{

selected = image;

break;

}

}

// hack to change selection, might return the original

SpriteImage random = images.get( rand.nextInt( images.size() ) );

selected.select(false );

random.select(true );

repaint();

// someone selected (should be always one)

if( selected !=null )

{

//get its location

int selectedX = selected.getXCoord();

int selectedY = selected.getYCoord();

if (direction == KeyEvent.VK_UP)

{

System.out.println("VK_KP_UP");

}

elseif (direction == KeyEvent.VK_DOWN)

{

System.out.println("VK_KP_DOWN");

}

elseif (direction == KeyEvent.VK_LEFT)

{

System.out.println("VK_KP_LEFT");

}

elseif (direction == KeyEvent.VK_RIGHT)

{

System.out.println("VK_KP_RIGHT");

}

}

}

publicvoid generate()

{

int x = rand.nextInt( 250 );

int y = rand.nextInt( 250 );

SpriteImage image =new SpriteImage(new File( imageFileName ), x, y );

image.select( init );

// first one is selected

init =false;

images.add(image);

repaint();

}

publicvoid buildUI(){

JButton jumbleButton =new JButton("Generate");

jumbleButton.addActionListener(new ActionListener(){

publicvoid actionPerformed(ActionEvent e){

CanvasDemo.this.generate();

};

});

add("South", jumbleButton);

}

publicstaticvoid main(String s[])

{

JFrame f =new JFrame("Jumbled Image");

f.addWindowListener(new WindowAdapter(){

publicvoid windowClosing(WindowEvent e){System.exit(0);}

});

CanvasDemo jumbler =new CanvasDemo();

f.add("Center", jumbler);

f.setSize(new Dimension( 300, 300 ) );

f.setVisible(true);

}

}

class SpriteImage

{

privateint xCoord, yCoord;

private BufferedImage bi, select;

privateboolean isSelected;

public SpriteImage( File image,int x,int y )

{

this( image );

xCoord = x;

yCoord = y;

}

public SpriteImage(File imageSrc){

try{

bi = ImageIO.read(imageSrc);

select = ImageIO.read(new File("hearts_selection.png") );

}catch (IOException e){

System.out.println("Image could not be read");

System.exit(1);

}

}

publicint getXCoord()

{

return xCoord;

}

publicint getYCoord()

{

return yCoord;

}

publicvoid select(boolean state )

{

isSelected = state;

}

publicboolean getSelect()

{

return isSelected;

}

publicvoid paint2(Graphics g)

{

g.drawImage(isSelected ? select : bi, xCoord, yCoord,null);

}

}

[10430 byte] By [coladaa] at [2007-10-3 10:33:37]
# 1

I don't understand the question.

If you have a component that is currently at location (x, y) and you want to move the component to the "right" 5 pixels then you would do something like:

Point location = component.getLocation();

component.setLocation(location.x + 5, location.y);

You define what the up, down, left, and right key actions are and then implement the action.

camickra at 2007-7-15 5:56:48 > top of Java-index,Desktop,Core GUI APIs...
# 2

There are two icons: "hearts_original.png" and hearts_selection.png".

The first icon is displayed repeatedly at random positions.

Among these images there is always one and only one "selected".

The selected image is always represented by the second icon,

so we can see that it is selected.

With arrow keys we should be able to navigate through all the displayed images,

so that the selected image becomes the next in right, left, down or up direction:

...

SpriteImage nextImage = navigate(selectedImage, direction);

...

private SpriteImage navigate(SpriteImage selectedImage, int direction) {

if (direction == KeyEvent.VK_UP) {

return getUp(selectedImage);

} else if (direction == KeyEvent.VK_DOWN) {

return getDown(selectedImage);

} else if (direction == KeyEvent.VK_LEFT) {

return getLeft(selectedImage);

}

return getRight(selectedImage);

}

private SpriteImage getLeft(SpriteImage selectedImage) {

List<SpriteImage> imagesTry = new ArrayList<SpriteImage>();

for (int i = selectedImage.getXCoord()-1; i > -1; i--) {

for (int j = 0; j < 251; j++) {

for (SpriteImage image: images) {

if(image.getXCoord() == i && image.getYCoord() == j){

imagesTry.add(image);

}

}

}

}

return getNext(selectedImage, imagesTry);

}

private SpriteImage getRight(SpriteImage selectedImage) {

List<SpriteImage> imagesTry = new ArrayList<SpriteImage>();

for (int i = selectedImage.getXCoord()+1; i < 251; i++) {

for (int j = 0; j < 251; j++) {

for (SpriteImage image: images) {

if(image.getXCoord() == i && image.getYCoord() == j){

imagesTry.add(image);

}

}

}

}

return getNext(selectedImage, imagesTry);

}

private SpriteImage getUp(SpriteImage selectedImage) {

List<SpriteImage> imagesTry = new ArrayList<SpriteImage>();

for (int i = selectedImage.getYCoord()-1; i > -1; i--) {

for (int j = 0; j < 251; j++) {

for (SpriteImage image: images) {

if(image.getYCoord() == i && image.getXCoord() == j){

imagesTry.add(image);

}

}

}

}

return getNext(selectedImage, imagesTry);

}

private SpriteImage getDown(SpriteImage selectedImage) {

List<SpriteImage> imagesTry = new ArrayList<SpriteImage>();

for (int i = selectedImage.getYCoord()+1; i < 251; i++) {

for (int j = 0; j < 251; j++) {

for (SpriteImage image: images) {

if(image.getYCoord() == i && image.getXCoord() == j){

imagesTry.add(image);

}

}

}

}

return getNext(selectedImage, imagesTry);

}

private SpriteImage getNext(SpriteImage selectedImage, List<SpriteImage> imagesTry) {

Point a = new Point(selectedImage.getXCoord(), selectedImage.getYCoord());

Point b = null;

double distance = 99999;

SpriteImage nextImage = null;

for (SpriteImage image : imagesTry) {

b = new Point(image.getXCoord(), image.getYCoord());

if(a.distance(b) < distance){

distance = a.distance(b);

nextImage = image;

}

}

return nextImage == null?selectedImage:nextImage;

}

...

Andre_Uhresa at 2007-7-15 5:56:48 > top of Java-index,Desktop,Core GUI APIs...
# 3
Thank you Andre, you're the man! That was exactly what I was looking for.
coladaa at 2007-7-15 5:56:48 > top of Java-index,Desktop,Core GUI APIs...
# 4

However, there may be a pitfall with this algorithm. Consider, for example, the following situation:

o

o

x

o

o

o

ooo

o

With arrow keys you will never be able to reach the group of icons in the lower left corner.

Could this cause a problem to your game?

Andre_Uhresa at 2007-7-15 5:56:48 > top of Java-index,Desktop,Core GUI APIs...