Shortest path to solve a maze - java

This class uses graphics to print a maze. The program will be run 3 times. After the first, I save a steps array that counts the number of times the character steps over a spot. I then write this array to a file. Before the next run, I open the file. I need to use the contents of the file to "learn" where not to go for the next trial (ie. avoid dead ends, find quickest path to finish).
I have a method hasBadBranch() that I want to return true for all intersections that have branches (north, south, east, and west of the intersection) with "steps" > 1. I'm getting array index out of bounds and the character no longer goes through the maze correctly when I add the hasBadBranch condition in my solve() method. If anyone sees any flaws in my logic, I would greatly appreciate the feedback. Thanks.
public class Maze extends JFrame {
private static final int MAX_WIDTH = 255;
private static final int MAX_HEIGHT = 255;
private char[][] maze = new char[MAX_HEIGHT][MAX_WIDTH];
private int[][] steps = new int[MAX_HEIGHT][MAX_WIDTH];
private Random random = new Random();
private JPanel mazePanel = new JPanel();
private int width = 0;
private int height = 0;
private boolean step = false;
private boolean timerFired = false;
private Timer timer;
private final int TIMER_DELAY = 20;
private final int SPRITE_WIDTH = 25;
private final int SPRITE_HEIGHT = 25;
private BufferedImage mazeImage;
private ImageIcon ground = new ImageIcon("sprites/ground.png");
private ImageIcon wall1 = new ImageIcon("sprites/cactus.png");
private ImageIcon wall2 = new ImageIcon("sprites/rock.png");
private ImageIcon finish = new ImageIcon("sprites/well.png");
private ImageIcon south1 = new ImageIcon("sprites/cowboy-forward-1.png");
private ImageIcon south2 = new ImageIcon("sprites/cowboy-forward-2.png");
private ImageIcon north1 = new ImageIcon("sprites/cowboy-back-1.png");
private ImageIcon north2 = new ImageIcon("sprites/cowboy-back-2.png");
private ImageIcon west1 = new ImageIcon("sprites/cowboy-left-1.png");
private ImageIcon west2 = new ImageIcon("sprites/cowboy-left-2.png");
private ImageIcon east1 = new ImageIcon("sprites/cowboy-right-1.png");
private ImageIcon east2 = new ImageIcon("sprites/cowboy-right-2.png");
private long startTime;
private long currentTime;
private static final int MAX_TIME = 500000;
/**
* Constructor for class Maze. Opens a text file containing the maze, then
* attempts to solve it.
*
* #param fname String value containing the filename of the maze to open.
*/
//Notes to user:
//delete steps.txt BEFORE testing begins and AFTER third run of program
//use appropriate file paths
public Maze(String fname) throws FileNotFoundException, IOException {
openMaze(fname);
mazeImage = printMaze();
readInFile();
timer = new Timer(TIMER_DELAY, new TimerHandler()); // setup a Timer to slow the animation down.
timer.start();
addWindowListener(new WindowHandler()); // listen for window event windowClosing
setTitle("Cowboy Maze");
setSize(width * SPRITE_WIDTH + 10, height * SPRITE_HEIGHT + 30);
setVisible(true);
add(mazePanel);
setContentPane(mazePanel);
solveMaze();
}
public void readInFile() throws FileNotFoundException, IOException {
//Note to user: adjust file path accordingly
File stepsFile = new File("C:\\Users\\Ashley Bertrand\\Desktop\\Data Structures\\Lab6\\mazeStartSourceMazesGraphics\\steps.txt");
if (stepsFile.isFile()) {
Scanner scanner = new Scanner(stepsFile);
int lineCount = 0;
while (scanner.hasNextLine()) {
String[] currentLine = scanner.nextLine().trim().split("\\s+");
for (int i = 0; i < currentLine.length; i++) {
steps[lineCount][i] = Integer.parseInt(currentLine[i]);
}
lineCount++;
}
System.out.println("Contents of steps.txt:");
for (int m = 0; m < width; m++) {
for (int n = 0; n < height; n++) {
System.out.print(steps[m][n]);
}
System.out.println();
}
System.out.println();
} else {
System.out.println("Running first trial so steps.txt does not exist");
}
}
/**
* Called from the operating system. If no command line arguments are
* supplied, the method displays an error message and exits. Otherwise, a
* new instance of Maze() is created with the supplied filename from the
* command line.
*
* #param args[] Command line arguments, the first of which should be the
* filename to open.
*/
public static void main(String[] args) throws FileNotFoundException, IOException {
int runny = 1;
if (args.length > 0) {
new Maze(args[0]);
} else {
System.out.println();
System.out.println("Usage: java Maze <filename>.");
System.out.println("Maximum Maze size:" + MAX_WIDTH + " x " + MAX_HEIGHT + ".");
System.out.println();
System.exit(1);
}
}
/**
* Finds the starting location and passes it to the recursive algorithm
* solve(x, y, facing). The starting location should be the only '.' on the
* outer wall of the maze.
*/
public void solveMaze() throws FileNotFoundException {
boolean startFound = false;
if (!startFound) {
for (int i = 0; i < width; i++) { // look for the starting location on the top and bottom walls of the Maze.
if (maze[0][i] == '.') {
maze[0][i] = 'S';
steps[0][i]++;
preSolve(i, 0, "south");
startFound = true;
} else if (maze[height - 1][i] == '.') {
maze[height - 1][i] = 'S';
steps[height - 1][i]++;
preSolve(i, height - 1, "north");
startFound = true;
}
}
}
if (!startFound) {
for (int i = 0; i < height; i++) { // look for the starting location on the left and right walls of the Maze.
if (maze[i][0] == '.') {
maze[i][0] = 'S';
steps[i][0]++;
preSolve(0, i, "east");
startFound = true;
} else if (maze[i][width - 1] == '.') {
maze[i][width - 1] = 'S';
steps[i][width - 1]++;
preSolve(width - 1, i, "west");
startFound = true;
}
}
}
if (!startFound) {
System.out.println("Start not found!");
}
}
public void preSolve(int x, int y, String facing) throws FileNotFoundException {
Scanner input = new Scanner(System.in);
System.out.println("Press 1 to start");
input.nextLine();
startTime = System.currentTimeMillis();
solve(x, y, facing);
}
/**
* Recursive algorithm to solve a Maze. Places an X at locations already
* visited. This algorithm is very inefficient, it follows the right hand
* wall and will never find the end if the path leads it in a circle.
*
* #param x int value of the current X location in the Maze.
* #param y int value of the current Y location in the Maze.
* #param facing String value holding one of four cardinal directions
* determined by the current direction facing.
*/
private void solve(int x, int y, String facing) throws FileNotFoundException {
Graphics2D g2 = (Graphics2D) mazePanel.getGraphics(); //don't mess with the next
while (!timerFired) { // wait for the timer.
try {
Thread.sleep(10);
} catch (Exception e) {
}
}
timerFired = false;
currentTime = System.currentTimeMillis();
if ((currentTime - startTime) > MAX_TIME) {
closingMethod();
}
if (maze[y][x] != 'F') { //this is if it doesn't find the finish on a turn.........
g2.drawImage(mazeImage, null, 0, 0);
g2.drawImage(printGuy(facing), x * SPRITE_WIDTH, y * SPRITE_HEIGHT, null, null);
mazePanel.setSize(width * SPRITE_WIDTH + 10, height * SPRITE_HEIGHT + 30);
maze[y][x] = 'X'; // mark this spot as visited. This is how you can keep track of where you've been.
if (facing.equals("east")) {
if (maze[y + 1][x] != '#' && maze[y + 1][x] != '%' && maze[y + 1][x] != 'S' && !hasBadBranch(y+1, x)) {
steps[y + 1][x]++;
solve(x, y + 1, "south");
} else if (maze[y][x + 1] != '#' && maze[y][x + 1] != '%' && maze[y][x + 1] != 'S' && !hasBadBranch(y, x+1)) {
steps[y][x + 1]++;
solve(x + 1, y, "east");
} else {
solve(x, y, "north");
}
} else if (facing.equals("west")) {
if (maze[y - 1][x] != '#' && maze[y - 1][x] != '%' && maze[y - 1][x] != 'S' && !hasBadBranch(y-1, x)) {
steps[y - 1][x]++;
solve(x, y - 1, "north");
} else if (maze[y][x - 1] != '#' && maze[y][x - 1] != '%' && maze[y][x - 1] != 'S'&& !hasBadBranch(y, x-1)) {
steps[y][x - 1]++;
solve(x - 1, y, "west");
} else {
solve(x, y, "south");
}
} else if (facing.equals("south")) {
if (maze[y][x - 1] != '#' && maze[y][x - 1] != '%' && maze[y][x - 1] != 'S' && !hasBadBranch(y, x-1)) {
steps[y][x - 1]++;
solve(x - 1, y, "west");
} else if (maze[y + 1][x] != '#' && maze[y + 1][x] != '%' && maze[y + 1][x] != 'S' && !hasBadBranch(y+1, x)) {
steps[y + 1][x]++;
solve(x, y + 1, "south");
} else {
solve(x, y, "east");
}
} else if (facing.equals("north")) {
if (maze[y][x + 1] != '#' && maze[y][x + 1] != '%' && maze[y][x + 1] != 'S' && !hasBadBranch(y, x+1)) {
steps[y][x + 1]++;
solve(x + 1, y, "east");
} else if (maze[y - 1][x] != '#' && maze[y - 1][x] != '%' && maze[y - 1][x] != 'S' && !hasBadBranch(y-1, x)) {
steps[y - 1][x]++;
solve(x, y - 1, "north");
} else {
solve(x, y, "west");
}
}
} else {
writeToFile();
System.out.println("Found the finish!");
currentTime = System.currentTimeMillis();
long endTime = currentTime - startTime;
long finalTime = endTime / 1000;
System.out.println("Final Time = " + finalTime);
}
}
public boolean hasBadBranch(int y, int x) {
//9999 will be used to tell character not to take that branch
if (steps[y][x] > 1) {
if (steps[y + 1][x] > 1) {
steps[y + 1][x] = 9999;
return true; //south
}
if (steps[y - 1][x] > 1) {
steps[y - 1][x] = 9999;
return true; //north
}
if (steps[y][x + 1] > 1) {
steps[y][x + 1] = 9999;
return true; //east
}
if (steps[y][x - 1] > 1) {
steps[y][x - 1] = 9999;
return true; //west
}
}
return false;
}
/**
* Opens a text file containing a maze and stores the data in the 2D char
* array maze[][].
*
* #param fname String value containing the file name of the maze to open.
*/
public void openMaze(String fname) {
String in = "";
int i = 0;
try {
Scanner sc = new Scanner(new File(fname));
while (sc.hasNext()) {
in = sc.nextLine();
in = trimWhitespace(in);
if (in.length() <= MAX_WIDTH && i < MAX_HEIGHT) {
for (int j = 0; j < in.length(); j++) {
if (in.charAt(j) == '#') { // if this spot is a wall, randomize the wall peice to display
if (random.nextInt(2) == 0) {
maze[i][j] = '#';
} else {
maze[i][j] = '%';
}
} else {
maze[i][j] = in.charAt(j);
}
}
} else {
System.out.println("Maximum maze size exceeded: (" + MAX_WIDTH + " x " + MAX_HEIGHT + ")!");
System.exit(1);
}
i++;
}
width = in.length();
height = i;
System.out.println("(" + width + " x " + height + ") maze opened.");
System.out.println();
sc.close();
} catch (FileNotFoundException e) {
System.err.println("File not found: " + e);
}
}
/**
* Removes white space from the supplied string and returns the trimmed
* String.
*
* #param s String value to strip white space from.
* #return String stripped of white space.
*/
public String trimWhitespace(String s) {
String newString = "";
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) != ' ') {
newString += s.charAt(i);
}
}
return newString;
}
/**
* Returns the sprite facing the direction supplied.
*
* #param facing String value containing 1 of 4 cardinal directions to make
* the sprite face.
* #return Image of the sprite facing the proper direction.
*/
private Image printGuy(String facing) {
if (facing.equals("south")) { // draw sprite facing south
if (step) {
step = false;
return south1.getImage();
} else {
step = true;
return south2.getImage();
}
} else if (facing.equals("north")) { // draw sprite facing north
if (step) {
step = false;
return north1.getImage();
} else {
step = true;
return north2.getImage();
}
} else if (facing.equals("east")) { // draw sprite facing east
if (step) {
step = false;
return east1.getImage();
} else {
step = true;
return east2.getImage();
}
} else if (facing.equals("west")) { // draw sprite facing west
if (step) {
step = false;
return west1.getImage();
} else {
step = true;
return west2.getImage();
}
}
return null;
}
/**
* Prints the Maze using sprites.
*
* #return BufferedImage rendition of the maze.
*/
public BufferedImage printMaze() {
BufferedImage mi = new BufferedImage(width * SPRITE_WIDTH, height * SPRITE_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics g2 = mi.createGraphics();
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
if (maze[i][j] == '#') { // draw wall
g2.drawImage(wall1.getImage(), j * SPRITE_WIDTH, i * SPRITE_HEIGHT, null, null);
} else if (maze[i][j] == '%') { // draw wall
g2.drawImage(wall2.getImage(), j * SPRITE_WIDTH, i * SPRITE_HEIGHT, null, null);
} else if (maze[i][j] == '.' || maze[i][j] == 'X') { // draw ground
g2.drawImage(ground.getImage(), j * SPRITE_WIDTH, i * SPRITE_HEIGHT, null, null);
} else if (maze[i][j] == 'F') { // draw finish
g2.drawImage(finish.getImage(), j * SPRITE_WIDTH, i * SPRITE_HEIGHT, null, null);
}
}
}
return mi;
}
public void writeToFile() throws FileNotFoundException {
PrintWriter printWriter = new PrintWriter("steps.txt");
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
printWriter.print(steps[i][j] + " ");
}
printWriter.println();
}
printWriter.close();
}
public void closingMethod() {
long endTime = currentTime - startTime;
long finalTime = endTime / 100;
System.exit(0);
}
private class TimerHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
timerFired = true;
}
}
private class WindowHandler extends WindowAdapter {
public void windowClosing(WindowEvent e) {
removeAll();
closingMethod();
System.exit(0);
}
}
}

Essentially what you did was to solve the maze using DFS with a fixed exploration rule (right hand). The info you should save is the number of times you stepped on a square. when you hit a dead end you will be going back to the intersection to try another branch.
So on the second solving, when you find an intersection with a score > 1, you should modify the explore rule to avoid branches that have score > 1 (1 means u never had to come back == previous solution path, 2 (or more) means you had to come back after a dead-end (or a few)). Hope that made sense.

Related

Creating new levels

As a beginner in Java, I'm working on a project of Space Invaders. Looking to add more levels.
private void LevelInit() {
aliens = new ArrayList<>();
int currentLevel = 1;
if (currentLevel == 1) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
var alien = new Alien(Constants.ALIEN_INIT_X + 18 * j, Constants.ALIEN_INIT_Y + 18 * i);
aliens.add(alien);
//System.out.println(currentLevel);
}
}
}
else if (currentLevel == 2) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
var alien = new Alien(Constants.ALIEN_INIT_X + 18 * j, Constants.ALIEN_INIT_Y + 18 * i);
aliens.add(alien);
// System.out.println(currentLevel);
}
}
}
else if (currentLevel == 3) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 6; j++) {
var alien = new Alien(Constants.ALIEN_INIT_X + 18 * j, Constants.ALIEN_INIT_Y + 18 * i);
aliens.add(alien);
//System.out.println(currentLevel);
}
}
}
player = new Player();
bullet = new Bullet();
}
This function is the logic behind the code that initializes the game and gets called by the constructor. The simple way of adding levels is adding more Aliens.
This is how it looks after being updated from yesterday, levels are being added but the arraylists are being stuck together. Like the 12 - 16 - 24 aliens are together printed, some spaceships take 1 hit some 2 and some 3 and when they are all destroyed system give message of You passed level 1 and 2 and 3 together which is confusing me why are they bound together like that and not being passed.
And I can't figure it out. Also,
private void update() {
if (deaths == 12) {
inGame = false;
timer.stop();
message = "Next Level!";
}
// player
player.act();
// shot
if (bullet.isVisible()) {
int shotX = bullet.getX();
int shotY = bullet.getY();
for (Alien alien : aliens) {
int alienX = alien.getX();
int alienY = alien.getY();
if (alien.isVisible() && bullet.isVisible()) {
if (shotX >= (alienX)
&& shotX <= (alienX + Constants.ALIEN_WIDTH)
&& shotY >= (alienY)
&& shotY <= (alienY + Constants.ALIEN_HEIGHT)) {
var ii = new ImageIcon(explImg);
alien.setImage(ii.getImage());
alien.setDying(true);
deaths++;
bullet.die();
}
}
}
int y = bullet.getY();
y -= 4;
if (y < 0) {
bullet.die();
} else {
bullet.setY(y);
}
}
// aliens
for (Alien alien : aliens) {
int x = alien.getX();
if (x >= Constants.BOARD_WIDTH - Constants.BORDER_RIGHT && direction != -1) {
direction = -1;
for(Alien a2 : aliens) {
a2.setY(a2.getY() + Constants.GO_DOWN);
}
}
if (x <= Constants.BORDER_LEFT && direction != 1) {
direction = 1;
for(Alien a : aliens) {
a.setY(a.getY() + Constants.GO_DOWN);
}
}
}
for(Alien alien : aliens) {
if (alien.isVisible()) {
int y = alien.getY();
if (y > Constants.GROUND - Constants.ALIEN_HEIGHT) {
inGame = false;
message = "Invasion!";
}
alien.act(direction);
}
}
// bombs
var generator = new Random();
for (Alien alien : aliens) {
int shot = generator.nextInt(15);
Alien.Bomb bomb = alien.getBomb();
if (shot == Constants.CHANCE && alien.isVisible() && bomb.isDestroyed()) {
bomb.setDestroyed(false);
bomb.setX(alien.getX());
bomb.setY(alien.getY());
}
int bombX = bomb.getX();
int bombY = bomb.getY();
int playerX = player.getX();
int playerY = player.getY();
if (player.isVisible() && !bomb.isDestroyed()) {
if (bombX >= (playerX)
&& bombX <= (playerX + Constants.PLAYER_WIDTH)
&& bombY >= (playerY)
&& bombY <= (playerY + Constants.PLAYER_HEIGHT)) {
var ii = new ImageIcon(explImg);
player.setImage(ii.getImage());
player.setDying(true);
bomb.setDestroyed(true);
}
}
if (!bomb.isDestroyed()) {
bomb.setY(bomb.getY() + 1);
if (bomb.getY() >= Constants.GROUND - Constants.BOMB_HEIGHT) {
bomb.setDestroyed(true);
}
}
}
}
This function is to update the game whenever anything happens. The code is made from a bunch of YouTube videos and GitHubs, so excuse the copying if you see any.
I need to create new levels by simply adding more aliens, tried using a for loop but that resulted in either the aliens move faster or the bullet doesn't destroy an alien, it just hits.
Board class:
public class Board extends JPanel {
private Dimension d;
private List<Alien> aliens;
private Player player;
private Bullet bullet;
private int level;
private int direction = -1;
private int deaths = 0;
private boolean inGame = true;
private String explImg = "src/images/explosion.png";
private String message = "Game Over";
private Timer timer;
public Board() {
initBoard();
gameInit();
LevelInit();
}
private void initBoard() {
addKeyListener(new TAdapter());
setFocusable(true);
d = new Dimension(Constants.BOARD_WIDTH, Constants.BOARD_HEIGHT);
setBackground(Color.black);
timer = new Timer(Constants.DELAY, new GameCycle());
timer.start();
gameInit();
}
private void gameInit() {
aliens = new ArrayList<>();
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
var alien = new Alien(Constants.ALIEN_INIT_X + 18 * j,
Constants.ALIEN_INIT_Y + 18 * i);
aliens.add(alien);
}
}
player = new Player();
bullet = new Bullet();
}
private void LevelInit() {
inGame = true;
timer.start();
int level = 1;
if (aliens.isEmpty()) {
level++;
int AlienCount;if(level == 2) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 6; j++) {
var alien = new Alien(Constants.ALIEN_INIT_X + 18 * j, Constants.ALIEN_INIT_Y + 18 * i);
aliens.add(alien);
}
}
} else if (level == 3) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 6; j++) {
var alien = new Alien(Constants.ALIEN_INIT_X + 18 * j, Constants.ALIEN_INIT_Y + 18 * i);
aliens.add(alien);
}
}
}
}
player = new Player();
bullet = new Bullet();
}
private void drawAliens(Graphics g) {
for (Alien alien : aliens) {
if (alien.isVisible()) {
g.drawImage(alien.getImage(), alien.getX(), alien.getY(), this);
}
if (alien.isDying()) {
alien.die();
}
}
}
private void drawPlayer(Graphics g) {
if (player.isVisible()) {
g.drawImage(player.getImage(), player.getX(), player.getY(), this);
}
if (player.isDying()) {
player.die();
inGame = false;
}
}
private void drawShot(Graphics g) {
if (bullet.isVisible()) {
g.drawImage(bullet.getImage(), bullet.getX(), bullet.getY(), this);
}
}
private void drawBombing(Graphics g) {
for (Alien a : aliens) {
Alien.Bomb b = a.getBomb();
if (!b.isDestroyed()) {
g.drawImage(b.getImage(), b.getX(), b.getY(), this);
}
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
private void doDrawing(Graphics g) {
g.setColor(Color.black);
g.fillRect(0, 0, d.width, d.height);
g.setColor(Color.green);
if (inGame) {
g.drawLine(0, Constants.GROUND,
Constants.BOARD_WIDTH, Constants.GROUND);
drawAliens(g);
drawPlayer(g);
drawShot(g);
drawBombing(g);
} else {
if (timer.isRunning()) {
timer.stop();
}
gameOver(g);
}
Toolkit.getDefaultToolkit().sync();
}
private void gameOver(Graphics g) {
g.setColor(Color.black);
g.fillRect(0, 0, Constants.BOARD_WIDTH, Constants.BOARD_HEIGHT);
g.setColor(new Color(0, 32, 48));
g.fillRect(50, Constants.BOARD_WIDTH / 2 - 30, Constants.BOARD_WIDTH - 100, 50);
g.setColor(Color.white);
g.drawRect(50, Constants.BOARD_WIDTH / 2 - 30, Constants.BOARD_WIDTH - 100, 50);
var small = new Font("Helvetica", Font.BOLD, 14);
var fontMetrics = this.getFontMetrics(small);
g.setColor(Color.white);
g.setFont(small);
g.drawString(message, (Constants.BOARD_WIDTH - fontMetrics.stringWidth(message)) / 2,
Constants.BOARD_WIDTH / 2);
}
private void update() {
if (deaths == aliens.size()) {
inGame = false;
timer.stop();
message = "Next Level!";
}
// player
player.act();
// shot
if (bullet.isVisible()) {
int shotX = bullet.getX();
int shotY = bullet.getY();
for (Alien alien : aliens) {
int alienX = alien.getX();
int alienY = alien.getY();
if (alien.isVisible() && bullet.isVisible()) {
if (shotX >= (alienX)
&& shotX <= (alienX + Constants.ALIEN_WIDTH)
&& shotY >= (alienY)
&& shotY <= (alienY + Constants.ALIEN_HEIGHT)) {
var ii = new ImageIcon(explImg);
alien.setImage(ii.getImage());
alien.setDying(true);
deaths++;
bullet.die();
}
}
}
int y = bullet.getY();
y -= 4;
if (y < 0) {
bullet.die();
} else {
bullet.setY(y);
}
}
// aliens
for (Alien alien : aliens) {
int x = alien.getX();
if (x >= Constants.BOARD_WIDTH - Constants.BORDER_RIGHT && direction != -1) {
direction = -1;
Iterator<Alien> i1 = aliens.iterator();
while (i1.hasNext()) {
Alien a2 = i1.next();
a2.setY(a2.getY() + Constants.GO_DOWN);
}
}
if (x <= Constants.BORDER_LEFT && direction != 1) {
direction = 1;
Iterator<Alien> i2 = aliens.iterator();
while (i2.hasNext()) {
Alien a = i2.next();
a.setY(a.getY() + Constants.GO_DOWN);
}
}
}
Iterator<Alien> it = aliens.iterator();
while (it.hasNext()) {
Alien alien = it.next();
if (alien.isVisible()) {
int y = alien.getY();
if (y > Constants.GROUND - Constants.ALIEN_HEIGHT) {
inGame = false;
message = "Invasion!";
}
alien.act(direction);
}
}
// bombs
var generator = new Random();
for (Alien alien : aliens) {
int shot = generator.nextInt(15);
Alien.Bomb bomb = alien.getBomb();
if (shot == Constants.CHANCE && alien.isVisible() && bomb.isDestroyed()) {
bomb.setDestroyed(false);
bomb.setX(alien.getX());
bomb.setY(alien.getY());
}
int bombX = bomb.getX();
int bombY = bomb.getY();
int playerX = player.getX();
int playerY = player.getY();
if (player.isVisible() && !bomb.isDestroyed()) {
if (bombX >= (playerX)
&& bombX <= (playerX + Constants.PLAYER_WIDTH)
&& bombY >= (playerY)
&& bombY <= (playerY + Constants.PLAYER_HEIGHT)) {
var ii = new ImageIcon(explImg);
player.setImage(ii.getImage());
player.setDying(true);
bomb.setDestroyed(true);
}
}
if (!bomb.isDestroyed()) {
bomb.setY(bomb.getY() + 1);
if (bomb.getY() >= Constants.GROUND - Constants.BOMB_HEIGHT) {
bomb.setDestroyed(true);
}
}
}
}
private void doGameCycle() {
update();
repaint();
}
private class GameCycle implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
doGameCycle();
}
}
private class TAdapter extends KeyAdapter {
#Override
public void keyReleased(KeyEvent e) {
player.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
player.keyPressed(e);
int x = player.getX();
int y = player.getY();
int key = e.getKeyCode();
if (key == KeyEvent.VK_SPACE) {
if (inGame) {
if (!bullet.isVisible()) {
bullet = new Bullet(x, y);
}
}
}
}
}
}
As #JoachimSauer mentioned, your code needs refactoring. Here is one possible solution to your problem.
Additions
You will need two extra variables and one extra method.
Variables
1: int currentLevel - keeps track of the current level
2: boolean isLevelOver - keeps track if the current level is still active or not
Method
private void levelInit(int currentlevel)
{
aliens = new ArrayList<>();
int alienCount = //calculate alien count depending upon the current level
//Add aliens to aliens ArrayList
player = new Player();
bullet = new Bullet();
}
You have to provide implementation of how alienCount will be calculated depending upon currentLevel. The nested loop you used earlier to add aliens to aliens will also change. You have to make the loop dependent upon currentLevel.
Changes
Few of your methods will require some change.
public Board()
{
initBoard();
}
private void initBoard()
{
addKeyListener(new TAdapter());
setFocusable(true);
d = new Dimension(Constants.BOARD_WIDTH, Constants.BOARD_HEIGHT);
setBackground(Color.black);
levelInit(currentLevel);
timer = new Timer(Constants.DELAY, new GameCycle());
timer.start();
}
private void update()
{
if (deaths == aliens.size())
{
isLevelOver = true;
currentLevel++;
message = "Next Level!";
return;
}
...
}
private void doGameCycle()
{
if (isLevelOver)
{
levelInit(currentLevel);
isLevelOver = false;
}
update();
repaint();
}
Notes
This is one of the possible ways to achieve what you want. There
might be other ways, probably better, but this is what I came up
with.
I tried to find as many additions and updation required in your code. However, I do not know its structure, you do. So there might be more additions or changes required.
I noticed you are were calling gameInit() in initBoard() and then again in Board() constructor. I think that might be unnecessary, please look into it.
You made one call to timer.stop() after setting isGame = false. This again might be unnecessary since you are already doing so inside doDrawing(...). Please also check that.
You should probably set a limit to either the levelCount() or max alien that can be on the screen since if you just keep on adding more aliens in each new level, they might fill up the entire screen.
I have provided many hints which should help you in your problem. If you still face any more problems or someone finds anything wrong with the answer, please comment.

How to have recursive maze generator draw each step?

I finished writing a program that creates a maze recursively but have not been able to figure out how to have it draw the maze after each step. Any changes to the maze happen before the next recursive call. The maze is prerendered onto a JPanel as a grid of squares, and I have attempted to have the program render each step, by using JPanel.repaint before the next recursive call (I have comments within my generate method where I have previously tried to repaint. No matter what I try, the maze just simply renders the finished product (maze with all of the paths, walls, etc) all at once at the end. Attached is my recursive generate method.
private static boolean generate(int x, int y) {
System.out.println("xcord: " + x + ", ycord: " + y);
//panel.repaint(); when i have repaint here, it renders the entire maze at the end
a[x][y].visited = true;
if (unvisitedCells == 0) { // if you have visited all of the cells, maze is done generating
System.out.println("done");
return true;
}
int movesTried = 0; // keeps track of which directions have been tried
int currentMove = (int) (Math.random() * 4); // try moving a random direction first (0 = north, 1 = east, etc.)
while (movesTried < 4) { // continue as long as all four moves havent been tried
// north move
if (a[x][y].northCell != null && a[x][y].northCell.visited != true && currentMove == 0) {
a[x][y].northCell.visited = true;
a[x][y].northWall = false;
a[x][y].northCell.southWall = false;
unvisitedCells -= 1;
// tried repainting here, but had no effect
if (generate(x, y - 1)) {
return true; // move successful
}
}
// east move
if (a[x][y].eastCell != null && a[x][y].eastCell.visited != true && currentMove == 1) {
a[x][y].eastCell.visited = true;
a[x][y].eastWall = false;
a[x][y].eastCell.westWall = false;
unvisitedCells -= 1;
// tried repainting here, but had no effect
if (generate(x + 1, y)) {
return true; // move successful
}
}
// south move
if (a[x][y].southCell != null && a[x][y].southCell.visited != true && currentMove == 2) {
a[x][y].southCell.visited = true;
a[x][y].southWall = false;
a[x][y].southCell.northWall = false;
unvisitedCells -= 1;
// tried repainting here, but had no effect
if (generate(x, y + 1)) {
return true; // move successful
}
}
// west move
if (a[x][y].westCell != null && a[x][y].westCell.visited != true && currentMove == 3) {
a[x][y].westCell.visited = true;
a[x][y].westWall = false;
a[x][y].westCell.eastWall = false;
unvisitedCells -= 1;
// tried repainting here, but had no effect
if (generate(x - 1, y)) {
return true; // move successful
}
}
movesTried++; // another move has been tried
if (currentMove == 3 && movesTried < 4) {
currentMove = 0; // wraps back to north move if maze started at a move greater than 0, and you
// have more moves to try
} else {
currentMove++;
}
}
// at this point, all 4 moves have been tried, and there are no possible moves
// from the current maze cell
return false;
}
Each cell is rendered individually onto a JPanel, using information kept in a MazeCell class.
public class MazeCell {
public boolean northWall = true;
public boolean eastWall = true;
public boolean southWall = true;
public boolean westWall = true;
public MazeCell northCell = null;
public MazeCell eastCell = null;
public MazeCell southCell = null;
public MazeCell westCell = null;
public boolean visited = false;
}
Here I have set up a JPanel which draws each cell individually, based on whether there is a wall in each of 4 directions.
panel = new JPanel() {
private static final long serialVersionUID = 1L;
public void paintComponent(Graphics g) {
super.paintComponent(g);
a[0][0].northWall = false;
a[mazeSize - 1][mazeSize - 1].southWall = false;
for (int y = 0; y < mazeSize; y++) {
for (int x = 0; x < mazeSize; x++) {
if (a[x][y].northWall) {
g.drawLine(100 + (x * 25), 100 + (y * 25), 100 + (x * 25) + 25, 100 + (y * 25));
}
if (a[x][y].eastWall) {
g.drawLine(100 + (x * 25) + 25, 100 + (y * 25), 100 + (x * 25) + 25, 100 + (y * 25) + 25);
}
if (a[x][y].southWall) {
g.drawLine(100 + (x * 25), 100 + (y * 25) + 25, 100 + (x * 25) + 25, 100 + (y * 25) + 25);
}
if (a[x][y].westWall) {
g.drawLine(100 + (x * 25), 100 + (y * 25), 100 + (x * 25), 100 + (y * 25) + 25);
}
}
}
}
};
Warp the long process (generate(int x, int y)) with a SwingWorker, and let it update the GUI. Here is an example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
public class RecursiveGuiUpdate extends JFrame {
private final int SIZE = 4;
JLabel[][] grid = new JLabel[SIZE][SIZE];
RecursiveGuiUpdate() {
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
add(getGrid(), BorderLayout.NORTH);
JButton paint = new JButton("Paint");
paint.addActionListener(a -> updateGui());
add(paint, BorderLayout.SOUTH);
pack();
setVisible(true);
}
private void updateGui() {
new Task().execute();
}
private Component getGrid() {
JPanel panel = new JPanel(new GridLayout(SIZE, SIZE));
for(int i=0; i<=(SIZE-1); i++) {
for(int j=0; j<=(SIZE-1); j++) {
JLabel l = new JLabel(i+"-"+j, JLabel.CENTER);
l.setOpaque(true);
panel.add(l);
grid[i][j] = l;
}
}
return panel;
}
class Task extends SwingWorker<Void,Void> {
#Override
public Void doInBackground() {
updateGui(0, 0);
return null;
}
#Override
public void done() { }
//recursively set labels background
void updateGui(int i, int j) {
System.out.println(i+"-"+j);
//set random, background color
grid[i][j].setBackground(new Color((int)(Math.random() * 0x1000000)));
try {
Thread.sleep(500); //simulate long process
} catch (InterruptedException ex) { ex.printStackTrace();}
if((i==(SIZE-1))&&(j==(SIZE-1))) { return; }
if(i<(SIZE-1)) {
updateGui(++i, j);
}else {
i=0;
updateGui(i, ++j);
}
}
}
public static void main(String[] args) {
new RecursiveGuiUpdate();
}
}
If needed, you can override process(java.util.List) to get and process interim results.
If you need help with adapting such solution to your code, please post another question with mcve.

convert a dynamic circle layout to oval or ellipse in android

I have a image group with three images perpendicularly, those group forms a circle, i have created it as circle view couldn't adjust its width to make it oval, since i have three stacked images one above one i couldn't adjust all those images the code as below's
static int Standard_height = 160;
static int Cam_Size = 50;
static int Segment_Size = 55;
static int TextSize = 10;
private void SetLayoutDesign() {
Layout_Frame.removeAllViews();
Segments = sharedpreferences.getInt(Vars.Selected_Segment_Count, 4);
int imageGap = Segment_Size + 5;
int size = Segment_Size + ((16 - (Segments + 1)));
int imageSize = Cam_Size - Segments;
for (int i = 0; i < Segments; i++) {
// Create some quick TextViews that can be placed.
String StateName = Vars.Segment_State + "_" + i;
int state = sharedpreferences.getInt(StateName, 0);
String TypeName = Vars.Segment_Type + "_" + i;
int type = sharedpreferences.getInt(TypeName, 0);
Segment_Button[i] = new ImageButton(act);
Segment_Name[i] = new TextView(act);
if (type == 0) {
Segment_Name[i].setText((i + 1) + "");
if (state == 1) {
Segment_Button[i].setBackgroundResource(R.drawable.sort_none);
} else {
Segment_Button[i].setBackgroundResource(R.drawable.sort_off);
}
} else if (type == 1) {
Segment_Name[i].setText((i + 1) + "\nMS");
if (state == 1) {
Segment_Button[i].setBackgroundResource(R.drawable.sort_ms);
} else {
Segment_Button[i].setBackgroundResource(R.drawable.sort_off);
}
} else if (type == 2) {
Segment_Name[i].setText((i + 1) + "\nFR");
if (state == 1) {
Segment_Button[i].setBackgroundResource(R.drawable.sort_fr);
} else {
Segment_Button[i].setBackgroundResource(R.drawable.sort_off);
}
} else if (type == 3) {
Segment_Name[i].setText((i + 1) + "\nSR");
if (state == 1) {
Segment_Button[i].setBackgroundResource(R.drawable.sort_sr);
} else {
Segment_Button[i].setBackgroundResource(R.drawable.sort_off);
}
}
Segment_Name[i].setGravity(Gravity.CENTER);
Segment_Name[i].setTextColor(Color.WHITE);
Segment_Name[i].setTextSize(TextSize);
Segment_Name[i].setId(Segment_Text_Ids[i]);
Segment_Name[i].setTypeface(null, Typeface.BOLD);
Segment_Button[i].setId(Segment_Ids[i]);
FrameLayout.LayoutParams lp1 = new FrameLayout.LayoutParams(imageSize, imageSize);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(size, size);
lp.gravity = Gravity.CENTER;
lp1.gravity = Gravity.CENTER;
Segment_Button[i].setLayoutParams(lp);
Segment_Button[i].setOnClickListener(this);
Segment_Button[i].setOnLongClickListener(this);
Segment_Name[i].setLayoutParams(lp);
float angleDeg = i * 360.0f / Segments - 90.0f;
float angleRad = (float) (angleDeg * Math.PI / 180.0f);
Segment_Button[i].setTranslationX(Standard_height * (float) Math.cos(angleRad));
Segment_Button[i].setTranslationY(Standard_height * (float) Math.sin(angleRad));
Layout_Frame.addView(Segment_Button[i]);
Segment_Name[i].setTranslationX(Standard_height * (float) Math.cos(angleRad));
Segment_Name[i].setTranslationY(Standard_height * (float) Math.sin(angleRad));
if (Segments % 2 == 0 && Segments != 0) {
Segment_Name[i].setRotation((180 / Segments));
} else {
Segment_Name[i].setRotation(0);
}
Layout_Frame.addView(Segment_Name[i]);
FCam_Button[i] = new ImageButton(act);
FCam_Button[i].setId(FCam_Ids[i]);
String FCamName = Vars.FCam_State + "_" + i;
int FCamState = sharedpreferences.getInt(FCamName, 0);
if (FCamState == 0) {
FCam_Button[i].setBackgroundResource(R.drawable.f_camera_off_image);
} else {
FCam_Button[i].setBackgroundResource(R.drawable.f_camera_on_image);
}
FCam_Button[i].setLayoutParams(lp1);
FCam_Button[i].setOnClickListener(this);
FCam_Button[i].setTranslationX((Standard_height + imageGap) * (float) Math.cos(angleRad));
FCam_Button[i].setTranslationY((Standard_height + imageGap) * (float) Math.sin(angleRad));
FCam_Button[i].setRotation(angleDeg + 90.0f);
Layout_Frame.addView(FCam_Button[i]);
RCam_Button[i] = new ImageButton(act);
RCam_Button[i].setId(RCam_Ids[i]);
String RCamName = Vars.RCam_State + "_" + i;
int RCamState = sharedpreferences.getInt(RCamName, 0);
if (RCamState == 0) {
RCam_Button[i].setBackgroundResource(R.drawable.r_camera_off_image);
} else {
RCam_Button[i].setBackgroundResource(R.drawable.r_camera_on_image);
}
RCam_Button[i].setLayoutParams(lp1);
RCam_Button[i].setOnClickListener(this);
RCam_Button[i].setTranslationX((Standard_height - imageGap) * (float) Math.cos(angleRad));
RCam_Button[i].setTranslationY((Standard_height - imageGap) * (float) Math.sin(angleRad));
RCam_Button[i].setRotation(angleDeg + 90.0f);
Layout_Frame.addView(RCam_Button[i]);
}
if (Segments % 2 == 0 && Segments != 0) {
Layout_Frame.setRotation(-(180 / Segments));
} else {
Layout_Frame.setRotation(0);
}
SetUserLevelControls();
}
This is the current layout
This is the desired layout

Creating a snake game, when you press two directions quickly snake eats itself [Java]

I hope this makes sense, but I'm trying to make a snake-type game in Java and if you press two directions at the same time/ too fast the snake goes on top of itself making you lose.
For example if you you're going downwards, and hit right then up very fast, you get the snake going straight up on the same column and killing itself, but it should go right one then up one. If anyone can help me that'd be great, thanks!
package tk.sketchistgames.Snake;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.IOException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Board extends JPanel implements ActionListener{
/**
* Main graphical area for Snake
*/
private static final long serialVersionUID = 4085437479211945011L;
private final int WIDTH = 600;
private final int HEIGHT = 600;
private final int DOT_SIZE = 10;
private final int ALL_DOTS = 1200;
private final int RAND_POS = 59;
public static int DELAY = 90;
private int x[] = new int[ALL_DOTS];
private int y[] = new int[ALL_DOTS];
private int dots, food_x, food_y, pdown_x, pdown_y, rdouble_x, rdouble_y, powerUp_x, powerUp_y, half_x, half_y;
private boolean left = false;
private boolean right = true;
private boolean up = false;
private boolean down = false;
private boolean inGame = true;
private int score = 0;
private int fruitEaten = 0;
private boolean Bonus = false;
private boolean RDouble = false;
private boolean bpower = false;
private boolean halfpower = false;
private Timer timer;
private Image food;
private Image head;
private Image body;
private Image pdown;
private Image rdouble;
private Image powerUp;
private Image half;
public Board() {
addKeyListener(new TAdapter());
setBackground(Color.decode("0x3F919E"));
ImageIcon iid = new ImageIcon(this.getClass().getResource("/images/body.png"));
body = iid.getImage();
ImageIcon iia = new ImageIcon(this.getClass().getResource("/images/food.png"));
food = iia.getImage();
ImageIcon iih = new ImageIcon(this.getClass().getResource("/images/head.png"));
head = iih.getImage();
ImageIcon iipd = new ImageIcon(this.getClass().getResource("/images/pdown.png"));
pdown = iipd.getImage();
ImageIcon iird = new ImageIcon(this.getClass().getResource("/images/pup2.png"));
rdouble = iird.getImage();
ImageIcon iipu1 = new ImageIcon(this.getClass().getResource("/images/pup1.png"));
powerUp = iipu1.getImage();
ImageIcon iihd = new ImageIcon(this.getClass().getResource("/images/halfDown.png"));
half = iihd.getImage();
setFocusable(true);
initGame();
}
public void initGame() {
dots = 5;
for (int z = 0; z < dots; z++) {
x[z] = 50 - z*10;
y[z] = 50;
}
locateFood();
timer = new Timer(DELAY, this);
timer.start();
}
public void checkApple() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
if ((x[0] == pdown_x) && (y[0] == pdown_y)){
dots -= 1;
score -= 50;
AudioInputStream audioIn = AudioSystem.getAudioInputStream(Board.class.getResource("/sounds/powerdown.wav"));
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
bpower = false;
}
if ((x[0] == half_x) && (y[0] == half_y)){
dots = dots /2;
score = score /2;
AudioInputStream audioIn = AudioSystem.getAudioInputStream(Board.class.getResource("/sounds/powerdown.wav"));
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
clip.start();
halfpower = false;
}
if ((x[0] == powerUp_x) && (y[0] == powerUp_y)){
dots += 4;
score += 100;
AudioInputStream audioIn = AudioSystem.getAudioInputStream(Board.class.getResource("/sounds/powerup1.wav"));
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
Bonus = false;
}
if ((x[0] == rdouble_x) && (y[0] == rdouble_y)){
dots = dots * 2;
score += 1000;
AudioInputStream audioIn = AudioSystem.getAudioInputStream(Board.class.getResource("/sounds/powerup2.wav"));
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
RDouble = false;
}
if ((x[0] == food_x) && (y[0] == food_y)) {
dots++;
long r = Math.round(Math.random() * 10);
if(r == 4){
locatePowerUp();
Bonus = true;
}
long half = Math.round(Math.random() * 175);
System.out.println(half);
if(half == 89){
locateHalfDown();
halfpower = true;
}
long rdouble = Math.round(Math.random() * 100);
if(rdouble == 50){
locateDoubleUp();
RDouble = true;
}
long badpower = Math.round(Math.random() * 25);
if(badpower == 25 || badpower == 20 || badpower == 15|| badpower == 10 || badpower == 5|| badpower == 0){
locatePowerDown();
bpower = true;
}
score += (50 + fruitEaten);
AudioInputStream audioIn = AudioSystem.getAudioInputStream(Board.class.getResource("/sounds/eat.wav"));
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
fruitEaten++;
locateFood();
}
}
public void paint(Graphics g) {
super.paint(g);
if (inGame) {
if(halfpower){
g.drawImage(half, half_x, half_y, this);
}
if(Bonus){
g.drawImage(powerUp, powerUp_x, powerUp_y, this);
}
if(RDouble){
g.drawImage(rdouble, rdouble_x, rdouble_y, this);
}
if(dots <= 0) gameOver(g);
g.setColor(Color.white);
Font small1 = new Font("arcadepix", Font.PLAIN, 20);
g.setFont(small1);
g.drawString("Score: " + score + " Food Eaten: " + fruitEaten + " Length: " + dots, 15, 15);
g.drawImage(food, food_x, food_y, this);
if(bpower){
g.drawImage(pdown, pdown_x, pdown_y, this);
}
for (int z = 0; z < dots; z++) {
if (z == 0)
g.drawImage(head, x[z], y[z], this);
else g.drawImage(body, x[z], y[z], this);
}
if(Menu.pause){
g.drawString("Paused! 'P' To unpause!", 20, 100);
for (int z = 0; z < dots; z++) {
x[z] = 50 - z*10;
y[z] = 50;
}
}
Toolkit.getDefaultToolkit().sync();
g.dispose();
}else{
gameOver(g);
}
}
public void gameOver(Graphics g) {
if(dots >= 300){
String msg = "You won!";
Font small = new Font("arcadepix", Font.PLAIN, 20);
FontMetrics metr = this.getFontMetrics(small);
g.setColor(Color.white);
g.setFont(small);
g.drawString(msg, (WIDTH - metr.stringWidth(msg)) / 2, HEIGHT / 2);
g.drawString("Total Score: " + score +"!", (WIDTH - metr.stringWidth(msg)) /2 - 12, (HEIGHT / 2) - 18);
g.drawString("Total Food Eaten: " + dots + "!", (WIDTH - metr.stringWidth(msg)) /2 - 72, (HEIGHT / 2) - 38);
g.drawString("Press Space to play again!", (WIDTH - metr.stringWidth(msg)) /2 - 77, (HEIGHT / 2) + 18);
setBackground(Color.red);
}else{
String msg = "Game Over";
Font small = new Font("arcadepix", Font.PLAIN, 20);
FontMetrics metr = this.getFontMetrics(small);
g.setColor(Color.white);
g.setFont(small);
g.drawString(msg, (WIDTH - metr.stringWidth(msg)) / 2, HEIGHT / 2);
g.drawString("Total Score: " + score, (WIDTH - metr.stringWidth(msg)) /2 - 12, (HEIGHT / 2) - 18);
g.drawString("Press Space to Continue", (WIDTH - metr.stringWidth(msg)) /2 - 77, (HEIGHT / 2) + 18);
setBackground(Color.decode("0x3F919E"));
}
}
public void move() {
for (int z = dots; z > 0; z--) {
x[z] = x[(z - 1)];
y[z] = y[(z - 1)];
}
if (left) {
x[0] -= DOT_SIZE;
}
if (right) {
x[0] += DOT_SIZE;
}
if (up) {
y[0] -= DOT_SIZE;
}
if (down) {
y[0] += DOT_SIZE;
}
}
public void checkCollision() {
for (int z = dots; z > 0; z--) {
if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) {
inGame = false;
}
}
if (y[0] > HEIGHT) {
inGame = false;
}
if (y[0] < 0) {
inGame = false;
}
if (x[0] > WIDTH) {
inGame = false;
}
if (x[0] < 0) {
inGame = false;
}
}
public void locateFood() {
int r = (int) (Math.random() * RAND_POS);
food_x = ((r * DOT_SIZE));
r = (int) (Math.random() * RAND_POS);
food_y = ((r * DOT_SIZE));
}
public void locatePowerDown() {
int r = (int) (Math.random() * RAND_POS);
pdown_x = ((r * DOT_SIZE));
r = (int) (Math.random() * RAND_POS);
pdown_y = ((r * DOT_SIZE));
}
public void locateDoubleUp() {
int r = (int) (Math.random() * RAND_POS);
rdouble_x= ((r * DOT_SIZE));
r = (int) (Math.random() * RAND_POS);
rdouble_y = ((r * DOT_SIZE));
}
public void locatePowerUp() {
int r = (int) (Math.random() * RAND_POS);
powerUp_x= ((r * DOT_SIZE));
r = (int) (Math.random() * RAND_POS);
powerUp_y = ((r * DOT_SIZE));
}
public void locateHalfDown() {
int r = (int) (Math.random() * RAND_POS);
half_x= ((r * DOT_SIZE));
r = (int) (Math.random() * RAND_POS);
half_y = ((r * DOT_SIZE));
}
public void actionPerformed(ActionEvent e) {
if (inGame) {
if(Menu.pause){
}
try {
checkApple();
} catch (UnsupportedAudioFileException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} catch (LineUnavailableException e1) {
e1.printStackTrace();
}
checkCollision();
move();
}
repaint();
}
public void reset(){
left = false;
right = true;
up = false;
down = false;
inGame = true;
score = 0;
fruitEaten = 0;
for (int z = 0; z < dots; z++) {
x[z] = 50 - z*10;
y[z] = 50;
}
dots = 5;
bpower = false;
locatePowerDown();
RDouble = false;
locateDoubleUp();
locatePowerUp();
locateFood();
repaint();
}
private class TAdapter extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_SPACE){
if(inGame){
if(Menu.pause){
Menu.pause = false;
}else if(!Menu.pause){
Menu.pause = true;
}
}
if(!inGame){
reset();
}
}
if(key == KeyEvent.VK_P){
if(Menu.pause){
Menu.pause = false;
}else if(!Menu.pause){
Menu.pause = true;
}
}
if ((key == KeyEvent.VK_LEFT || key == KeyEvent.VK_A) && (!right)) {
left = true;
up = false;
down = false;
}
if ((key == KeyEvent.VK_RIGHT ||key == KeyEvent.VK_D) && (!left)) {
right = true;
up = false;
down = false;
}
if ((key == KeyEvent.VK_UP || key == KeyEvent.VK_W) && (!down)) {
up = true;
right = false;
left = false;
}
if ((key == KeyEvent.VK_DOWN || key == KeyEvent.VK_S) && (!up)) {
down = true;
right = false;
left = false;
}
}
}
}
Based on your description, your code is changing the boolean variables before the move occurs. A simple solution would be to store all moves in a Queue, and process them by removing them, that way you ensure you won't overwrite a move.
In other words, every time you record a key event that would change the booleans, store some sort of signal (an int, a String, an enum, etc.) in a Queue, and in your move method, simply remove the signal from the front of the Queue and process it like you process the boolean variables. If you were to use an enum for UP DOWN RIGHT LEFT it would be fairly readable and you could use a switch-case to process each movement.
ex.
switch (movement) {
case UP: /* up code */ break;
case LEFT: /* left code */ break;
case RIGHT: /* right code */ break;
case DOWN: /* down code */ break;
}
where movement is the signal you removed from the queue, and UP DOWN RIGHT LEFT are enum's (for that matter they could be int constants, but as Bloch recommends in Effective Java, prefer enum types to int constants.)
private enum Movement { UP, DOWN, RIGHT, LEFT }
This allows you to refer to these types in the switch above, and instantiate the Queue as follows:
Queue<Movement> movementQueue = new ArrayDeque<Movement>();
Which in turn means you can add whichever movement you need simply by doing the following:
movementQueue.offer(UP); // or DOWN or RIGHT or LEFT, whichever you want.
And when you're ready to use them, access them as follows:
Movement movement = movementQueue.poll();
For more info on Queues: http://docs.oracle.com/javase/6/docs/api/java/util/Queue.html
For more info on enums: http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
Also because you said you're new to Java, I'd recommend Head First: Java for an overhead view, and Effective Java to learn a good amount of best practices.

zoom in/out graph using AWT on Applet

I am newbie to the java....working on a piece of applet code...............as I am still going through the OOPs concepts and java understanding and need to develop below mentioned functionality.
The piece of code I have works like this :
First it reads all parameters from HTML tags and stores in global variables. Then it sends query to CGI to read graph data. Then it converts data for plotting and draws graph. There is a option for user to select 1-24 hours. Based on the selection graph will be plotted by plotting only selected data. Every 30 sec it sends query to CGI for collecting data.
The code uses following library and uses java 1.5 environment and i cannot change it due to embeded requirements :
I need to enchance it by implementing zoom in zoom out feature with x-y axis granuality changing with zoom in .
My worry is how to do that?I know its Frustrating question ...but i am here to get suggestion from the java experts so that I can quickly learn and implement this stuff.
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.applet.*;
import java.net.*;
import java.io.*;
import java.util.*;
import java.text.*;
/******************************************************************************
*
* Class - Graph
*
* This is the entry point.
* This class extends Applet class and implements Runnable.
*
*****************************************************************************/
public class GraphPerf extends Applet implements Runnable,ItemListener,MouseMotionListener
{
//Global variables
int MAX_DATA_X ;
int SIZE_X= 480;
int SIZE_Y= 250;
int SIZE_Y1= 240;
int MIN_ERROR = -1;
int MAX_LOG10_ERROR_COUNT = 1001;
int MAX_ERROR_COUNT = 101;
int SIZE_Y_EXTENDED_BOTTOM = 20;
int MAX_DISP_PARMS = 16;
int MAX_NUM_INTERVELL_PER_DAY = 96;
int MAX_DISP_PARMS_STD = 7;
int refreshTime;
String serverAddress,hostAddr;
Color plotColor1,plotColor8;
float graphData[][];
float graph_data_rf_east,graph_data_rf_west;
int xOffset = 50;
int yOffset = 40;
int Y1_MAX_VALUE = 100;
int Y2_MAX_VALUE = 3;
float RANGE2;
Thread graphThread;
Image Buffer;
Graphics plot;
Choice timeChoice, modeChoice, seloptChoice;
int duration=1, viewMode=1, line_type = 0,viewOpt = 1;
Label valueLabel1, valueLabel2,valueLabel3,valueLabel4,valueLabel5;
boolean GraphBottomExtendFlag=true;
/******************************************************************************
*
* method - init
*
* This is the method called first after applet loaded in to browser.
* This function reads configurable parameters from HTML tag and updates
* global variables.
*****************************************************************************/
public void init()
{
MAX_DATA_X = 672;//Integer.parseInt(getParameter("max_data_x"));
//refreshTime = 30;//Integer.parseInt(getParameter("refresh_sec"));
/*URL url = getDocumentBase();
String host = url.getHost();
try
{
InetAddress addr = InetAddress.getByName(host);
hostAddr=addr.getHostAddress();
}catch (UnknownHostException ex) {
ex.printStackTrace();
}
*/
//serverAddress = new String ( getParameter("access_str")+ hostAddr + getParameter("data_server"));
graphData = new float[MAX_DISP_PARMS][MAX_DATA_X+1];
/*initialize the array with -1 not with 0(0 also valid for graph data) */
int i =0,j = 0;
for( j=0; j<MAX_DISP_PARMS; j++)
{
for( i=0; i<MAX_DATA_X+1; i++)
{
graphData[j][i] = -1;
}
}
graph_data_rf_east = -1;
graph_data_rf_west = -1;
plotColor1 = Color.orange;
plotColor2 = Color.black;
plotColor8 = Color.red;
plotColor9 = Color.green;
setBackground(Color.white);
setLayout(null);
timeChoice = new Choice();
timeChoice.add("1");
timeChoice.add("2");
timeChoice.add("3");
timeChoice.add("4");
timeChoice.add("5");
timeChoice.add("6");
timeChoice.add("7");
add(timeChoice);
timeChoice.setBounds(190,340,40,23);
timeChoice.addItemListener(this);
Label timeLabel1 = new Label("View graph for last");
Label timeLabel2 = new Label("day(s)");
add(timeLabel1);
timeLabel1.setBounds(xOffset+30,340,160,23);
add(timeLabel2);
timeLabel2.setBounds(240,340,50,23);
valueLabel1 = new Label();
add(valueLabel1);
valueLabel1.setBounds(300,340,50,23);
valueLabel2 = new Label();
add(valueLabel2);
valueLabel2.setBounds(370,340,70,23);
valueLabel3 = new Label();
add(valueLabel3);
valueLabel3.setBounds(440,340,70,23);
valueLabel4 = new Label();
add(valueLabel4);
valueLabel4.setBounds(500,340,70,23);
valueLabel5 = new Label();
add(valueLabel5);
valueLabel5.setBounds(370,370,80,25);
modeChoice = new Choice();
modeChoice.add("East");
modeChoice.add("West");
/* Display this only for Protected and East-West Mode */
if(2/*Integer.parseInt(getParameter("mode"))*/ == 2)
{
add(modeChoice);
}
else
{
viewOpt = 1;
}
modeChoice.setBounds(xOffset+SIZE_X-55, 0, 60, 25);
modeChoice.addItemListener(this);
addMouseMotionListener(this);
}
public void start()
{
graphThread = new Thread(this);
graphThread.start();
}
public void stop()
{
graphThread = null;
}
/******************************************************************************
*
* This method will be called after starting the thread. This is a
* infinite loop which will call query method for every 30 sec to read data
* from CGI. Then it plots graph by calling plotGraph method
* the thread.
*****************************************************************************/
public void run()
{
/*while (false)
{
try
{//getData(serverAddress);
int sizeY = SIZE_Y;
if(GraphBottomExtendFlag)
{
sizeY += SIZE_Y_EXTENDED_BOTTOM;
}
repaint(xOffset+1,yOffset+1,SIZE_X-1,sizeY-1);
//graphThread.sleep(refreshTime*1000);
}catch (Exception e) { System.out.println(e); }
}*/
}
/******************************************************************************
*
* method - paint
*
* This method displays the graph plotted by plotGraph method
* in the screen. Then it draws axis for the graph
*
*****************************************************************************/
public void paint(Graphics g1)
{
int sizeY = SIZE_Y;
/*If Graph Bottom is to be Etended
*soo that zero is displayed properly
*/
if(GraphBottomExtendFlag)
{
sizeY += SIZE_Y_EXTENDED_BOTTOM;
}
if( duration <= 5 )
{
Buffer = createImage(SIZE_X, sizeY);
plot = Buffer.getGraphics();
plotGraph(plot);
g1.drawImage (Buffer,xOffset,yOffset,this);
}
else
{
Buffer = createImage(MAX_DATA_X*duration/7,sizeY);
plot = Buffer.getGraphics();
plotGraph(plot);
g1.drawImage (Buffer,xOffset,yOffset,SIZE_X,sizeY,this);
}
g1.setColor(Color.black);
g1.drawRect(70,150,270,80);
/*Dram Graph boarder */
g1.drawRect(xOffset,yOffset,SIZE_X,sizeY);
g1.drawRect(xOffset-1,yOffset-1,SIZE_X+2,sizeY+2);
/*Plot X axis*/
int max_x_marks = 8;
int temp = 1,cnt_graph = 0;
int float_temp,float_temp2;
/*max 8 plots on x axis*/
for(int x=max_x_marks; x>0; x--)
{
float_temp = (int)((MAX_NUM_INTERVELL_PER_DAY*duration)/max_x_marks)*((max_x_marks+1)-x);
float_temp2 = SIZE_X-(60*cnt_graph);
g1.drawString(String.valueOf(float_temp),(float_temp2-20) ,SIZE_Y+yOffset+35);
cnt_graph++;
}
/*Plot Y1 AXIS*/
temp = Y1_MAX_VALUE;
for(int x = 0; x <= SIZE_Y; x+= 25)
{
g1.drawString(String.valueOf(temp), 25, x + yOffset+10);
temp -= (Y1_MAX_VALUE - 0)/10;
}
temp = 1000;
/*Plot Y2 AXIS*/
int index_log = 1;
for(int x = 0; x <= SIZE_Y1; x+= 80)
{
if(x== 240)
index_log--;
if(temp>=1)
{
g1.drawString(String.valueOf(temp), 550, x+yOffset+8-index_log);
g1.drawLine(530,x+yOffset+5-index_log, 540, x+yOffset+5-index_log);
}
temp = temp/10;
}
Font thisFont = new Font("Times New Roman", Font.BOLD, 14);
g1.setFont(thisFont);
g1.drawString("Y2", 550, 160);
g1.drawString("Y1",5, 160);
}
/******************************************************************************
*
* method - plotGraph
*
* Depending on the mode, "East", "West" or "Combined", it plots
* single or two graphs in the same applet.
*
* Inputs :
* g - Graphics object
*****************************************************************************/
public void plotGraph(Graphics g)
{
g.setColor(new Color(255,255,220));
/*If Error-Sec-Count Graph
*Then extend the lower portion
*soo that zero is displayed properly
*/
if(GraphBottomExtendFlag)
{
g.fillRect(0,0,MAX_DATA_X,SIZE_Y + SIZE_Y_EXTENDED_BOTTOM);
}
else
{
g.fillRect(0,0,MAX_DATA_X,SIZE_Y);
}
switch(viewMode)
{
case 1 :
plot1(g);
plot_timeelapsed_east(g);
break;
case 2 :
plot8(g);
plot_timeelapsed_west(g);
break;
}
}
/******************************************************************************
*
* method - plot1
*
* This method uses graphData[0][] global variable and plots series of lines
* in the applet
*
* Inputs :
* g - Graphics object
*****************************************************************************/
void plot1(Graphics g)
{
int end = MAX_DATA_X;
int localPlotBuffer[];
localPlotBuffer = new int[2];
g.setColor(plotColor1);
if(duration > 5)
{
for(int x=(duration*MAX_NUM_INTERVELL_PER_DAY); x > 0 ; x--)
{
/*if data is valid data then plot else ignore*/
if((graphData[0][end]>MIN_ERROR)&&(graphData[0][end-1]<MAX_LOG10_ERROR_COUNT)&&(graphData[0][end-1]>MIN_ERROR)&&(graphData[0][end]<MAX_LOG10_ERROR_COUNT))
{
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[0][end] == 0)
{
localPlotBuffer[0] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[0][end]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[0][end])/(float)Y2_MAX_VALUE));
}
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[0][end-1] == 0)
{
localPlotBuffer[1] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[0][end-1]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[1] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[0][end-1])/(float)Y2_MAX_VALUE));
}
g.drawLine(x-1,(localPlotBuffer[0]+5), x-2,(localPlotBuffer[1]+5));
g.drawLine(x,(localPlotBuffer[0]+5), x-1,(localPlotBuffer[1]+5));
}
end--;
}
}
else
{
float temp = SIZE_X;
for(int x=(duration*MAX_NUM_INTERVELL_PER_DAY) ; x > 0 ; x--)
{
float LocalTemp1 = temp;
float LocalTemp2 = (int)(temp-(double)5/(double)duration);
/*Normalise the pixcel positions */
/*Normalise the pixcel positions */
if(duration == 1)
{
if(LocalTemp1>(SIZE_X-3))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-3))
LocalTemp2 = SIZE_X;
}
/*Normalise the pixcel positions */
else if(duration == 2)
{
if(LocalTemp1>(SIZE_X-2))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-2))
LocalTemp2 = SIZE_X;
}
/*Normalise the pixcel positions */
else if(duration == 3)
{
if(LocalTemp1>(SIZE_X-1))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-1))
LocalTemp2 = SIZE_X;
}
/*if data is valid data then plot else ignore*/
if((graphData[0][end]>MIN_ERROR)&&(graphData[0][end-1]<MAX_LOG10_ERROR_COUNT)&&(graphData[0][end-1]>MIN_ERROR)&&(graphData[0][end]<MAX_LOG10_ERROR_COUNT))
{
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[0][end] == 0)
{
localPlotBuffer[0] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[0][end]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[0][end])/(float)Y2_MAX_VALUE));
}
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[0][end-1] == 0)
{
localPlotBuffer[1] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[0][end-1]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[1] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[0][end-1])/(float)Y2_MAX_VALUE));
}
g.drawLine((int)LocalTemp1,(localPlotBuffer[0]+5), (int)LocalTemp2,(localPlotBuffer[1]+5));
}
temp-=(double)5/(double)duration;
end--;
}
}
}
/******************************************************************************
*
* method - plot8
*
* This method uses graphData[7][] global variable and plots series of lines
* in the applet
*
* Inputs :
* g - Graphics object
*****************************************************************************/
void plot8(Graphics g)
{
int end = MAX_DATA_X;
int localPlotBuffer[];
localPlotBuffer = new int[2];
g.setColor(plotColor1);
if(duration > 5)
{
for(int x=(duration*MAX_NUM_INTERVELL_PER_DAY); x > 0 ;x-- )
{
/*if data is valid data then plot else ignore*/
if((graphData[8][end]>MIN_ERROR)&&(graphData[8][end-1]<MAX_LOG10_ERROR_COUNT)&&(graphData[8][end-1]>MIN_ERROR)&&(graphData[8][end]<MAX_LOG10_ERROR_COUNT))
{
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[8][end] == 0)
{
localPlotBuffer[0] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[8][end]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[8][end])/(float)Y2_MAX_VALUE));
}
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[8][end-1]== 0)
{
localPlotBuffer[1] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[8][end-1]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[1] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[8][end-1])/(float)Y2_MAX_VALUE));
}
g.drawLine(x-1,(localPlotBuffer[0]+5), x-2,(localPlotBuffer[1]+5));
g.drawLine(x,(localPlotBuffer[0]+5), x-1,(localPlotBuffer[1]+5));
}
end--;
}
}
else
{
float temp = SIZE_X;
for(int x=(duration*MAX_NUM_INTERVELL_PER_DAY) ; x > 0 ; x--)
{
float LocalTemp1 = temp;
float LocalTemp2 = (int)(temp-(double)5/(double)duration);
/*Normalise the pixcel positions */
if(duration == 1)
{
if(LocalTemp1>(SIZE_X-3))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-3))
LocalTemp2 = SIZE_X;
}
/*Normalise the pixcel positions */
else if(duration == 2)
{
if(LocalTemp1>(SIZE_X-2))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-2))
LocalTemp2 = SIZE_X;
}
/*Normalise the pixcel positions */
else if(duration == 3)
{
if(LocalTemp1>(SIZE_X-1))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-1))
LocalTemp2 = SIZE_X;
}
/*if data is valid data then plot else ignore*/
if((graphData[8][end]>MIN_ERROR)&&(graphData[8][end-1]<MAX_LOG10_ERROR_COUNT)&&(graphData[8][end-1]>MIN_ERROR)&&(graphData[8][end]<MAX_LOG10_ERROR_COUNT))
{
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[8][end] == 0)
{
localPlotBuffer[0] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[8][end]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[8][end])/(float)Y2_MAX_VALUE));
}
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[8][end-1]== 0)
{
localPlotBuffer[1] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[8][end-1]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[1] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[8][end-1])/(float)Y2_MAX_VALUE));
}
g.drawLine((int)LocalTemp1,(localPlotBuffer[0]+5), (int)LocalTemp2,(localPlotBuffer[1]+5));
}
temp-=(double)5/(double)duration;
end--;
}
}
}
/******************************************************************************
*
* method - plot_timeelapsed_east
*
* This method uses graph_data_rf_east global variable and plots series of lines
* in the applet
*****************************************************************************/
void plot_timeelapsed_east(Graphics g)
{
int end = MAX_DATA_X;
int localPlotBuffer[];
int x= 0;
localPlotBuffer = new int[2];
x= (duration*MAX_NUM_INTERVELL_PER_DAY);
g.setColor(plotColor9);
/*if data is valid data then plot else ignore*/
if((graph_data_rf_east>0)&&(graph_data_rf_east<MAX_LOG10_ERROR_COUNT))
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graph_data_rf_east)/(float)Y2_MAX_VALUE));
if(duration>5)
g.drawLine(x-1,SIZE_Y+5, x-2,(localPlotBuffer[0]+5));
else
g.drawLine(SIZE_X,SIZE_Y+5, 474+duration,(localPlotBuffer[0]+5));
}
}/*End for plot_timeelapsed_east() */
/******************************************************************************
*
* method - plot_timeelapsed_west
*
* This method uses graph_data_rf_east global variable and plots series of lines
* in the applet
*****************************************************************************/
void plot_timeelapsed_west(Graphics g)
{
int end = MAX_DATA_X;
int localPlotBuffer[];
int x= 0;
localPlotBuffer = new int[2];
x= (duration*MAX_NUM_INTERVELL_PER_DAY);
g.setColor(plotColor9);
/*if data is valid data then plot else ignore*/
if((graph_data_rf_east>MIN_ERROR)&&(graph_data_rf_east<MAX_LOG10_ERROR_COUNT))
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graph_data_rf_west)/(float)Y2_MAX_VALUE));
if(duration>5)
g.drawLine(x-1,SIZE_Y+5, x-2,(localPlotBuffer[0]+5));
else
g.drawLine(SIZE_X,SIZE_Y+5, 474+duration,(localPlotBuffer[0]+5));
}
}
/******************************************************************************
*
* method - getData
*
* This method sends query to CGI to collect data. Then it converts the
* data for applet area then updates global variable.
*
* Inputs :
* serverAddress - server CGI path
*****************************************************************************/
public void getData(String serverAddress)
{
URL addr;
BufferedReader in;
String inputLine;
int count = 0;
int i=0,j = 0;
try
{
addr = new URL(serverAddress);
URLConnection connection = addr.openConnection();
in = new BufferedReader(new InputStreamReader(addr.openStream()));
/*Read data for first link */
for( j=0; j<MAX_DISP_PARMS_STD; j++)
{
for( i=0; i<MAX_DATA_X+1; i++)
{
inputLine = in.readLine();
graphData[j][i] = Integer.parseInt(inputLine);
}
}
for( i=0; i<MAX_DATA_X; i++)
{
inputLine = in.readLine();
graphData[7][i] = Integer.parseInt(inputLine);
if(graphData[7][i] == 1)
graphData[7][i] = 10;
}
inputLine = in.readLine();
graph_data_rf_east = Integer.parseInt(inputLine);
/*Reading data for second link */
if(Integer.parseInt(getParameter("mode")) == 2)
{
for( j=8; j<15; j++)
{
for( i=0; i<MAX_DATA_X+1; i++)
{
inputLine = in.readLine();
graphData[j][i] = Integer.parseInt(inputLine);
}
}
for( i=0; i<MAX_DATA_X; i++)
{
inputLine = in.readLine();
graphData[15][i] = Integer.parseInt(inputLine);
if(graphData[15][i] == 1)
graphData[15][i] = 10;
}
inputLine = in.readLine();
graph_data_rf_west = Integer.parseInt(inputLine);
}
in.close();
}catch (Exception e) { System.out.println("Server Data Read Error:"+e); }
}
/******************************************************************************
*
* method - itemStateChanged
*
* This method will be called whenever event occured on this choice.
* it read the current status and changes scale accordingly.
* *****************************************************************************/
public void itemStateChanged(ItemEvent evt)
{
if( evt.getSource() == timeChoice )
duration = Integer.parseInt(timeChoice.getSelectedItem());
else
viewMode = modeChoice.getSelectedIndex()+1;
repaint();
}
/******************************************************************************
*
* method - mouseMoved
*
* This method will be called whenever mouse cursor is moved over the
* applet. Depending on the cursor position, it will display Actual
* X and Y values of the graph.
*****************************************************************************/
public void mouseMoved(MouseEvent evt)
{
int x = evt.getX()-xOffset;
int y = evt.getY()-yOffset-5;
int a = evt.getX();
int b = evt.getY();
int duration = Integer.parseInt(timeChoice.getSelectedItem());
if( (x>=0) && (x<=SIZE_X) && (y>=0) && (y<=SIZE_Y) )
{
valueLabel1.setText("X ");
valueLabel2.setText("Y1 ");
valueLabel3.setText("Y2 ");
try
{
int x_max_value = ((SIZE_X*duration)/5);
int x1 = (int)((float)((float)((float)(SIZE_X*duration))/5) * ((float)((float)(SIZE_X - x))/((float)SIZE_X)));
/*For Durations less than 16 scale starts with 1*/
int y1 = (int)((float)Y1_MAX_VALUE * (((float)SIZE_Y - (float)y)/((float)SIZE_Y)));
int y2 = (int) Math.pow(10,((float)(3 * ((float)(1 - (float)y/((float)SIZE_Y1))))));
valueLabel1.setText("X="+x1);
valueLabel2.setText("X pix="+a);
valueLabel3.setText("Y="+y1);
valueLabel4.setText("Y pix="+b);
valueLabel5.setText("Y2="+y2);
}
catch(Exception e) {System.out.println("Mouse Moved Error" + e);}
}
else
{
valueLabel1.setText(" ");
valueLabel2.setText(" ");
valueLabel3.setText(" ");
}
}
public void mouseDragged(MouseEvent evt) { }
}
There are many ways to do this. Here are two:
You can simply scale the values: Multiply every coordinate with the zoom factor.
Use Java2D and AffineTransform:
AffineTransform transformer = new AffineTransform();
transformer.scale(zoom, zoom);
Graphics2D g2d = (Graphics2D)g;
g2d.setTransform(transformer);
// draw to g2d.
[EDIT] If you want to do everything yourself, see this page for a refresh of basic linear algebra: 2D Transformations
Don't mind the 3D example at the top; the rest of the page is about 2D.
I used JCC kit for my target platform and it's less than 100kb library. You need to understand the library and after that you can play without worrying about size. :)
Good library to use in embedded systems whether size is always the issue. it has inbuilt function o transform coordinates into screen coordinates and vice-verse.

Categories