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.
Related
So I wrote this code for a game and now that game is very speeded up. I want to lower the FPS so that the game slows down a bit.
I thought the only way out for me is to make a timer. But I'm finding it difficult to locate where to place the timer? Can anyone help me with this?
So I wrote this code for a game and now that game is very speeded up. I want to lower the FPS so that the game slows down a bit.
I thought the only way out for me is to make a timer. But I'm finding it difficult to locate where to place the timer? Can anyone help me with this?
public class Gamepanel extends JPanel implements Runnable, KeyListener {
private static final long serialVersionUID = 1L;
public static final int WIDTH = 500, HEIGHT = 500;
private Thread thread;
private boolean running;
private boolean right = false, left = false, up = false, down= false;
private BodyPart b;
private ArrayList<BodyPart> snake;
private Apple apple;
private ArrayList<Apple> apples;
private Random r;
private int xCoor = 10, yCoor = 10, size = 1;
private int ticks = 0;
public Gamepanel(){
setFocusable(true);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
addKeyListener(this);
snake = new ArrayList<BodyPart>();
apples = new ArrayList<Apple>();
r = new Random();
start();
}
public void start () {
running = true;
thread = new Thread(this);
thread.start();
}
public void stop() {
running = false;
try {
thread.join();
} catch(InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void tick() {
if(snake.size()==0) {
b= new BodyPart(xCoor, yCoor, 10);
snake.add(b);
}
ticks++;
if(ticks > 250000) {
if(right) xCoor++;
if(left) xCoor--;
if(up) yCoor--;
if(down) yCoor++;
ticks = 0;
b = new BodyPart(xCoor, yCoor, 10);
snake.add(b);
if(snake.size() > size) {
snake.remove(0);
}
}
if(apples.size()==0) {
int xCoor = r.nextInt(49);
int yCoor = r.nextInt(49);
apple = new Apple(xCoor,yCoor,10);
apples.add(apple);
}
for(int i = 0; i < apples.size(); i++) {
if(xCoor == apples.get(i).getxCoor() && yCoor == apples.get(i).getyCoor()) {
size++;
apples.remove(i);
i++;
}
}
//COLLISION ON SNAKE BODY
for (int i = 0; i < snake.size(); i++) {
if(xCoor == snake.get(i).getxCoor() && yCoor == snake.get(i).getyCoor()) {
if(i != snake.size() - 1) {
System.out.print("Game Over");
stop();
}
}
//COLLISION ON BORDER
if(xCoor < 0 || xCoor > 49 || yCoor < 0 || yCoor > 49) {
System.out.print("Game Over" + '\n');
System.out.println("Your Score is: " + snake.size());
stop();
}
}
}
public void paint(Graphics g) {
g.clearRect(0, 0, WIDTH, HEIGHT);
g.setColor(Color.BLACK);
g.fillRect(0, 0, WIDTH, HEIGHT);
for (int i=0; i< WIDTH/10; i++) {
g.drawLine(i * 10, 0, i * 10, HEIGHT);
}
for (int i=0; i< HEIGHT/10; i++) {
g.drawLine(0, i * 10, HEIGHT, i * 10);
}
for (int i = 0; i< snake.size(); i++) {
snake.get(i).draw(g);
}
for (int i = 0; i< apples.size(); i++) {
apples.get(i).draw(g);
}
}
#Override
public void run() {
while(running) {
tick();
repaint();
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_D && !left) {
right = true;
up = false;
down=false;
}
if(key == KeyEvent.VK_A && !right) {
left = true;
up = false;
down = false;
}
if(key == KeyEvent.VK_W && !down) {
up=true;
left=false;
right=false;
}
if(key == KeyEvent.VK_S && !up) {
down=true;
left=false;
right=false;
}
}
#Override
public void keyReleased(KeyEvent e) {
}
}
The problem with your code is that now, game speed won't be the same on different machines, as some computers may execute your code faster and some may execute slower.
If you want your game to execute on every computer with the same speed you need define some kind of speed for your snake (unit per second) and then in game loop update your snake position based on how much time elapsed from last frame (last call of tick method)
// snake speed
double speed = 1.0; // units per second
// in game loop (your tick method)
position = speed * deltaTime;
now your position is not anymore depended on game framerate. On faster devices game will update snake position more often but deltaTime will be smaller as well as changes of position, on the other hand on slower devices tick method will be called less frequent but deltaTime will be higher
I'm trying to set up a depth system of sorts in processing.
The goal is for it to function similar to a (Windows) window.
I have a class called 'Window' and that can take some arguments and it will successfully draw a window that can be dragged around.
The depth system works as it stands right now. I can't click on windows 'under' the current window and if I click on another window, the order of the windows is switched correctly.
The problem is that whenever I switch between windows, the previously selected window flashes (is not drawn) for a frame, and then appears again.
I cannot work out why this happens at all. Here's my code, let me know if you need any further info.
Windows.pde:
Window[] wins;
int win_count = 0;
boolean win_drag = false;
int win_selected = 2;
void setup()
{
size(800, 600);
wins = new Window[3];
wins[0] = new Window("Test", 20, 20, 300, 200);
wins[1] = new Window("Test 2", 20, 260, 350, 225);
wins[2] = new Window("Test 3", 400, 20, 250, 150);
}
void draw()
{
background(10);
for (int i = 0; i < wins.length; i ++)
{
wins[i].draw_window();
}
}
void bringToTop(Window winID)
{
Window[] new_wins;
new_wins = new Window[wins.length];
int win_pos = -1;
for (int i = 0; i < wins.length; i ++)
{
if (wins[i] == winID)
{
win_pos = i;
break;
}
}
arrayCopy(wins, 0, new_wins, 0, win_pos);
arrayCopy(wins, win_pos + 1, new_wins, win_pos, wins.length - win_pos - 1);
new_wins[wins.length - 1] = winID;
arrayCopy(new_wins, wins);
}
boolean isOnTop(Window winID)
{
int win_pos = -1;
for (int i = 0; i < wins.length; i ++)
{
if (wins[i] == winID)
{
win_pos = i;
break;
}
}
Window[] top_wins;
top_wins = new Window[wins.length];
int winTopCount = 0;
for (int i = 0; i < wins.length; i ++)
{
if (mouse_in_rect(wins[i].winX, wins[i].winY, wins[i].winW, wins[i].winH + 24))
{
top_wins[winTopCount] = wins[i];
winTopCount ++;
}
}
int last_real_win = -1;
for (int i = 0; i < top_wins.length; i ++)
{
if (top_wins[i] != null)
{
last_real_win = i;
}
}
return (wins[win_pos] == top_wins[last_real_win]);
}
WindowObj.pde:
class Window
{
String winT;
int winX;
int winY;
int winW;
int winH;
boolean dragging;
int winXOff;
int winYOff;
int winTH;
int my_id;
Window(String ttl, int WX, int WY, int WW, int WH)
{
winT = ttl;
winX = WX;
winY = WY;
winW = WW;
winH = WH;
dragging = false;
winXOff = 0;
winYOff = 0;
winTH = 24;
my_id = win_count ++;
}
void draw_window()
{
if (win_selected == my_id)
{
fill(60);
}
else
{
fill(40);
}
rect(winX, winY, winW, winTH);
fill(25);
rect(winX, winY + 24, winW, winH);
if (dragging == true)
{
winX = mouseX + winXOff;
winY = mouseY + winYOff;
if (winX < 0)
{
winX = 0;
}
if (winX > width - winW - 1)
{
winX = width - winW - 1;
}
if (winY < 0)
{
winY = 0;
}
if (winY > height - winH - winTH - 1)
{
winY = height - winH - winTH - 1;
}
}
Window win_pos = wins[0];
for (int i = 0; i < wins.length; i ++)
{
if (wins[i].my_id == my_id)
{
win_pos = wins[i];
}
}
if (mouse_in_rect(winX, winY, winW, 24) && mousePressed && mouseButton == LEFT && dragging == false && isOnTop(win_pos) && win_drag == false)
{
dragging = true;
winXOff = winX - mouseX;
winYOff = winY - mouseY;
win_drag = true;
win_selected = my_id;
bringToTop(win_pos);
}
if (mouse_in_rect(winX, winY + 24, winW, winH) && mousePressed && mouseButton == LEFT && dragging == false && isOnTop(win_pos) && win_drag == false)
{
win_selected = my_id;
bringToTop(win_pos);
}
if (dragging == true)
{
if (mouseButton != LEFT)
{
win_drag = false;
dragging = false;
winXOff = 0;
winYOff = 0;
}
}
}
}
mouseFunctions.pde:
boolean mouse_in_rect(int mX, int mY, int mW, int mH)
{
int but_x = mX;
int but_y = mY;
int but_w = mW;
int but_h = mH;
if (mouseX > but_x && mouseY > but_y && mouseX < but_x + but_w && mouseY < but_y + but_h)
{
return true;
}
else
{
return false;
}
}
The issue is caused, because you do the calculation of the window order and the drawing in a single loop.
If the position of a window has changed, the drawing of a window may be omitted, while the drawing of an other window is done twice. Note, the index of the windows in the array wins changed.
Split the drawing and the update of the windows to 2 separate methods:
class Window
{
// ...
void draw_window()
{
if (win_selected == my_id)
{
fill(60);
}
else
{
fill(40);
}
rect(winX, winY, winW, winTH);
fill(25);
rect(winX, winY + 24, winW, winH);
}
void update_window()
{
if (dragging == true)
{
// ...
}
// ...
}
First update the order of the windows and calculate its new position. After that draw all the windows in a separate loop:
void draw()
{
background(10);
for (int i = 0; i < wins.length; i ++) {
wins[i].update_window();
}
for (int i = 0; i < wins.length; i ++) {
wins[i].draw_window();
}
}
I'm writing a code which generates a random maze, every time i run the program it looks diffrent, but i cant get my reset button working. Here is some of my code:
public class MakeFrame extends JPanel implements ActionListener {
JFrame frame;
JPanel buttonPanel;
JButton solve1;
JButton solve2;
JButton solve3;
JButton clear;
JButton reset;
Maze maze = new Maze();
void buildframe() {
frame = new JFrame("maze"); //makes a frame, names it maze
frame.add(this, BorderLayout.CENTER);
frame.add(maze);
buttonPanel = new JPanel();
frame.add(buttonPanel, BorderLayout.NORTH);
solve1 = new JButton("solve 1"); // create some buttons
solve2 = new JButton("solve 2");
solve3 = new JButton("solve 3");
clear = new JButton("clear");
reset = new JButton("reset");
buttonPanel.add(solve1); // add the buttons to a panel
buttonPanel.add(solve2);
buttonPanel.add(solve3);
buttonPanel.add(clear);
buttonPanel.add(reset);
solve1.addActionListener(this);// assigns action listeners to buttons
solve2.addActionListener(this);
solve3.addActionListener(this);
clear.addActionListener(this);
reset.addActionListener(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // makes the frame visable, grey and close on exit.
frame.setSize(455, 320);
frame.setVisible(true);
setBackground(Color.GRAY);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == reset) {
frame.add(new Maze());
repaint();
}
}
}
I don't know what to put in the action performed method to make it work, can anybody help me?
here is my class maze:
public class Maze extends JPanel {
Cell[][] cells = new Cell[22][12];
String[][] route = new String[22][12];
Random random = new Random();
Maze() {
othersetroute();
createFloor();
createWalls();
setStartEnd();
}
void othersetroute() {
int x = 1;
int y = 1;
int downorright;
for (int i = 0; i < 50; i++) {
downorright = random.nextInt(3);
if (x == 20 && y == 10) {
break;
}
if (x > 20 || y > 10) {
break;
}
if (y == 10 || downorright == 0 || downorright == 1) {
x++;
} else {
y++;
}
route[x][y] = "floor";
}
for (int a = 0; a < 22; a++) {
for (int b = 0; b < 12; b++) {
if (route[a][b] == null) {
int floororwall;
floororwall = random.nextInt(4);
if (floororwall == 0 || floororwall == 1) {
route[a][b] = "walls";
} else {
route[a][b] = "floor";
}
if (a % 2 == 1 && b % 2 == 1) {
route[a][b] = "floor";
}
if (a % 2 == 0 && b % 2 == 0) {
route[a][b] = "walls";
}
}
}
}
}
void setRoute() {
int x = 1;
int y = 1;
int leftcounter = 0;
int rightcounter = 0;
int upcounter = 0;
int downcounter = 0;
for (int i = 0; i < 150; i++) {
String direction;
if (x > 20 || y > 10) {
break;
} else if (x == 20 && y == 10) {
break;
} else if (downcounter == 14 && upcounter == 5 && leftcounter == 10 && rightcounter == 29) {
break;
} else if (x == 20) {
int k = random.nextInt(3);
if (k == 0) {
direction = "left";
} else if (k == 1) {
direction = "up";
} else {
direction = "down";
}
} else if (y == 10) {
int k = random.nextInt(3);
if (k == 0) {
direction = "left";
} else if (k == 1) {
direction = "up";
} else {
direction = "right";
}
} else if (x == 1 || y == 1) {
int k = random.nextInt(3);
if (k == 0) {
direction = "down";
} else {
direction = "right";
}
} else {
int k = random.nextInt(4);
if (k == 0) {
direction = "left";
} else if (k == 1) {
direction = "up";
} else if (k == 2) {
direction = "right";
} else {
direction = "down";
}
}
if (direction.equals("right") && rightcounter < 30) {
x++;
rightcounter++;
} else if (direction.equals("down") && downcounter < 15) {
y++;
downcounter++;
} else if (direction.equals("left") && leftcounter < 11) {
x = x - 1;
leftcounter++;
} else if (direction.equals("up") && upcounter < 6) {
y = y - 1;
upcounter++;
}
System.out.println(x);
System.out.println(y);
route[x][y] = "floor";
}
for (int a = 0; a < 22; a++) {
for (int b = 0; b < 12; b++) {
if (route[a][b] == null) {
int floororwall;
floororwall = random.nextInt(4);
if (floororwall == 0 || floororwall == 1) {
route[a][b] = "walls";
} else {
route[a][b] = "floor";
}
if (a % 2 == 1 && b % 2 == 1) {
route[a][b] = "floor";
}
if (a % 2 == 0 && b % 2 == 0) {
route[a][b] = "walls";
}
}
}
}
}
void createFloor() {
for (int x = 0; x < 22; x++) {
for (int y = 0; y < 12; y++) {
if (route[x][y].equals("walls")) {
cells[x][y] = new Cell("walls");
}
if (route[x][y].equals("floor")) {
cells[x][y] = new Cell("floor");
}
}
}
}
void createWalls() {
for (int i = 0; i < 12; i++) {
cells[0][i] = new Cell("walls");
cells[21][i] = new Cell("walls");
}
for (int i = 0; i < 22; i++) {
cells[i][0] = new Cell("walls");
cells[i][11] = new Cell("walls");
}
for (int x = 0; x < 22; x++) {
for (int y = 0; y < 12; y++) {
if (cells[x][y] == null) {
cells[x][y] = new Cell("walls");
}
}
}
}
void setStartEnd() {
cells[1][1] = new Cell("start");
cells[20][10] = new Cell("end");
}
#Override
public void paintComponent(Graphics g) {
for (int x = 0; x < 22; x++) {
for (int y = 0; y < 12; y++) {
if (cells[x][y].getType().equals("#")) {
g.setColor(Color.GREEN);
g.fillRect(x * 20, y * 20, x * 20 + 20, y * 20 + 20);
}
if (cells[x][y].getType().equals(" ")) {
g.setColor(Color.WHITE);
g.fillRect(x * 20, y * 20, x * 20 + 20, y * 20 + 20);
}
if (cells[x][y].getType().equals("S") || cells[x][y].getType().equals("E")) {
g.setColor(Color.PINK);
g.fillRect(x * 20, y * 20, x * 20 + 20, y * 20 + 20);
}
}
}
}
void solutionOne(){ // least visited
int visits[][]= new int [20][10];
for (int i = 0; i<21; i++){
for (int j = 0; j<10; j++){
visits[i][j]=0;
}
}
for (int i = 0; i<100; i++){
}
}
}
and here is my class cell :p
public class Cell {
private String cell;
Cell(String type){
if (type.equals("walls")){
walls();
}
if (type.equals("floor")){
Floor();
}
if (type.equals("start")){
start();
}
if(type.equals("end")){
end();
}
}
void walls(){
cell = "#";
}
void start(){
cell = "S";
}
void end(){
cell = "E";
}
void Floor(){
cell = " ";
}
public String getType(){
return cell;
}
}
You had too much of this
MakeFrame extends JPanel
Which would make another JPanel but I could not find any main methods that ran the whole code, so here you go, enjoy xD
MakeFrame.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MakeFrame extends JFrame implements ActionListener{
JPanel buttonPanel;
JButton solve1;
JButton solve2;
JButton solve3;
JButton clear;
JButton reset;
Maze maze;
public MakeFrame(){
super("Maze");
init();
}
public void init() {
//makes a frame, names it maze
maze = new Maze();
super.getContentPane().add(maze, BorderLayout.CENTER);
buttonPanel = new JPanel();
super.getContentPane().add(buttonPanel, BorderLayout.NORTH);
solve1 = new JButton("solve 1"); // create some buttons
solve2 = new JButton("solve 2");
solve3 = new JButton("solve 3");
clear = new JButton("clear");
reset = new JButton("reset");
buttonPanel.add(solve1); // add the buttons to a panel
buttonPanel.add(solve2);
buttonPanel.add(solve3);
buttonPanel.add(clear);
buttonPanel.add(reset);
solve1.addActionListener(this);// assigns action listeners to buttons
solve2.addActionListener(this);
solve3.addActionListener(this);
clear.addActionListener(this);
reset.addActionListener(this);
super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// makes the frame visable, grey and close on exit.
super.setSize(455, 320);
super.setVisible(true);
super.setBackground(Color.GRAY);
}
public void repaint(){
init();
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == reset) {
super.getContentPane().removeAll();
repaint();
}
}
}
TestMaze.java
public class TestMaze {
public static void main(String [] args){
new MakeFrame();
}
}
private void b2ActionPerformed(java.awt.event.ActionEvent evt) {
jTextField.getText(");
}
I am making a fairly simple game in java and I keep getting this IndexOutofBoundsException from my arraylist. I have 1 that creates an arraylist of "bullets", and another that stores "missles". The program runs and I can fire bullets for about 5 seconds and then it freezes giving me this error. I'm not sure what is happening.
This is part of my Canvas class that creates the array lists.
ArrayList ms = craft.getMissles();
ArrayList bs = craft.getBullets();
for (int i = 0; i < ms.size(); i++ ) {
Missle m = (Missle) ms.get(i);
g2d.drawImage(m.getImage(), m.getX(), m.getY(), this);
}
for (int b = 0; b < bs.size(); b++ ) {
Bullet a = (Bullet) bs.get(b);
g2d.drawImage(a.getImage(), a.getX(), a.getY(), this);
}
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
public void actionPerformed(ActionEvent e) {
ArrayList ms = craft.getMissles();
ArrayList bs = craft.getBullets();
for (int i = 0; i < ms.size(); i++) {
Missle m = (Missle) ms.get(i);
if (m.isVisible())
m.move();
else ms.remove(i);
}
for (int b = 0; b < bs.size(); b++) {
Bullet a = (Bullet) bs.get(b);
if (a.isVisible())
a.move();
else ms.remove(b);
}
craft.move();
repaint();
}
And here are parts of my Craft class that has the actions for the missiles. I declare them above and the code worked fine when I only had the missile parts. The error came when I added a second arraylist.
public Craft() {
ImageIcon ii = new ImageIcon(this.getClass().getResource(craft));
image = ii.getImage();
missles = new ArrayList();
bullets = new ArrayList();
x = 1000;
y = 60;
}
private ArrayList missles;
private ArrayList bullets;
private final int CRAFT_SIZE = 85;
private final int CRAFT_SIZE2 = 20;
public void move() {
x += dx;
y += dy;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Image getImage() {
return image;
}
public ArrayList getMissles() {
return missles;
}
public ArrayList getBullets() {
return bullets;
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
dx = -2;
}
if (key == KeyEvent.VK_RIGHT) {
dx = 1;
}
if (key == KeyEvent.VK_UP) {
dy = -2;
}
if (key == KeyEvent.VK_DOWN) {
dy = 3;
}
if (key == KeyEvent.VK_SPACE) {
fire();
}
if (key == KeyEvent.VK_V) {
fire2();
}
}
public void fire() {
missles.add(new Missle(x + CRAFT_SIZE, y + CRAFT_SIZE/2));
}
public void fire2() {
bullets.add(new Bullet(x + CRAFT_SIZE2, y + CRAFT_SIZE/2));
}
I spotted one bug at least:
else ms.remove(b);
should be
else bs.remove(b);
I am trying to implement an undo / redo functionality in my line drawing/moving/deleting program. I am currently saving each line as a list of points and storing all the lines in a list. After every drawing/moving/deleting operation I will add the new list of lines to my buffer and increment the bufferIterator(counter) to be the last element of the buffer at every mouseReleased action. When I press ESC I am trying to make the current lines variable the previous list of lines and repaint, but the repaint part is not working. Does anyone have any idea what I am doing wrong ?
The code is here:
public class Kimp {
public static void main(String[] args) {
JFrame frame = new JFrame("Kimp!");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.add(new CanvasPanel());
frame.setVisible(true);
}
}
class CanvasPanel extends JPanel {
private List<List<List<Point>>> buffer = new LinkedList<List<List<Point>>>();
private List<List<Point>> lines = new LinkedList<List<Point>>();
private List<Point> points = new LinkedList<Point>();
public boolean ctrlPressed;
public int bufferIterator = 0;
public int pressedX = -999;
public int pressedY = -999;
public int differenceX;
public int differenceY;
public List<Point> pressedLine = new LinkedList<Point>();
public List<Point> movedLine = new LinkedList<Point>();
public Color lineColor = Color.BLUE;
public CanvasPanel() {
this.setFocusable(true);
this.requestFocusInWindow();
addKeyListener(keyAdapter);
addMouseListener(mouseAdapter);
addMouseMotionListener(mouseAdapter);
}
#Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.WHITE);
g2.setStroke(new BasicStroke(3));
g2.fillRect(0, 0, getWidth(), getHeight());
for (List<Point> line : lines) {
drawLine(line, g2);
}
drawLine(points, g2);
}
private void drawLine(List<Point> points, Graphics2D g2) {
if (points.size() < 2) return;
if (ctrlPressed) {
int lineS = points.size();
int lineP = pressedLine.size();
//Set the color to RED, if the line is being moved.
if (lineS == lineP) {
boolean first = comparePoints(points.get(0), pressedLine.get(0));
boolean second = comparePoints(points.get(lineS - 1), pressedLine.get(lineP - 1));
boolean third = comparePoints(points.get(lineS / 2), pressedLine.get(lineP / 2));
if (first && second && third) {
lineColor = Color.RED;
}
} else {
lineColor = Color.BLUE;
}
} else {
lineColor = Color.BLUE;
}
Point p1 = points.get(0);
for (int i=1, n=points.size(); i<n; i++) {
Point p2 = points.get(i);
g2.setColor(lineColor);
g2.drawLine(p1.x, p1.y, p2.x, p2.y);
p1 = p2;
}
}
private KeyAdapter keyAdapter = new KeyAdapter() {
#Override
public void keyPressed(KeyEvent ke) {
if(ke.getKeyCode() == ke.VK_ESCAPE) {
System.out.println("ESC PRESSED");
if (bufferIterator != 0) {
System.out.println("UNDOING!");
//UNDO
lines = new LinkedList<List<Point>>();
int index = bufferIterator - 1;
if (index >= 0) {
lines = buffer.get(index);
}
repaint();
} else {
int reply = JOptionPane.showConfirmDialog(null, "Do you want to exit?",
"Exit", JOptionPane.YES_NO_OPTION);
if (reply == JOptionPane.YES_OPTION) {
System.exit(0);
}
}
} else if(ke.getKeyCode() == ke.VK_CONTROL) {
ctrlPressed = true;
} else if (ke.getKeyCode() == ke.VK_SPACE) {
System.out.println("REDOING");
//REDO
}
}
#Override
public void keyReleased(KeyEvent ke) {
if(ke.getKeyCode() == ke.VK_CONTROL) {
ctrlPressed = false;
}
}
};
private MouseAdapter mouseAdapter = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
if (ctrlPressed) {
if (e.isMetaDown()) {
Point pointPressed = e.getPoint();
for (int j=0, m=lines.size(); j<m; j++) {
List<Point> line = lines.get(j);
for (int i=0, n=line.size(); i<n; i++) {
Point pt = line.get(i);
//This is, to allow a small margin of missing, but still only take 1 point.
if (pointPressed.x - pt.x <= 1 && pointPressed.y - pt.y <= 1) {
//Only the first point will be "the point clicked".
if (pressedX == -999 && pressedY == -999) {
pressedX = pt.x;
pressedY = pt.y;
pressedLine = line;
}
}
}
}
for (int x = 0, r = lines.size(); x < r; x++) {
int lenA = lines.get(x).size();
int lenB = pressedLine.size();
if (lenA == lenB) {
boolean first = comparePoints(lines.get(x).get(0), pressedLine.get(0));
boolean second = comparePoints(lines.get(x).get(lenA - 1), pressedLine.get(lenB - 1));
boolean third = comparePoints(lines.get(x).get(lenA / 2), pressedLine.get(lenB / 2));
if (first && second && third) {
lines.remove(x);
buffer.add(lines);
repaint();
break;
}
}
}
} else {
Point pointPressed = e.getPoint();
for (int j=0, m=lines.size(); j<m; j++) {
List<Point> line = lines.get(j);
for (int i=0, n=line.size(); i<n; i++) {
Point pt = line.get(i);
//This is, to allow a small margin of missing, but still only take 1 point.
if (pointPressed.x - pt.x <= 1 && pointPressed.y - pt.y <= 1) {
//Only the first point will be "the point clicked".
if (pressedX == -999 && pressedY == -999) {
pressedX = pt.x;
pressedY = pt.y;
pressedLine = line;
}
}
}
}
}
} else {
points.add(e.getPoint());
repaint();
}
}
#Override
public void mouseDragged(MouseEvent e) {
Point pointDragged = e.getPoint();
if (ctrlPressed) {
differenceX = pointDragged.x - pressedX;
differenceY = pointDragged.y - pressedY;
//Create the moved line
for (Point p : pressedLine) {
movedLine.add(new Point(p.x + differenceX , p.y + differenceY));
}
for (int i=0, n=lines.size(); i<n; i++) {
int lineS = lines.get(i).size();
int lineP = pressedLine.size();
//Choose 3 points in order to not go through all of them
boolean first = comparePoints(lines.get(i).get(0), pressedLine.get(0));
boolean second = comparePoints(lines.get(i).get(lineS - 1), pressedLine.get(lineP - 1));
boolean third = comparePoints(lines.get(i).get(lineS / 2), pressedLine.get(lineP / 2));
if (first && second && third) {
lines.set(i, movedLine);
pressedX = pressedX + differenceX;
pressedY = pressedY + differenceY;
pressedLine = movedLine;
movedLine = new LinkedList<Point>();
repaint();
break;
}
}
} else {
points.add(pointDragged);
repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
if (points.size() > 1) {
lines.add(points);
points = new LinkedList<Point>();
}
//Add the current canvas to buffer
buffer.add(lines);
System.out.println("Buffer size:");
System.out.println(buffer.size() );
System.out.println(buffer.get(buffer.size() - 1));
bufferIterator = buffer.size() - 1;
pressedX = -999;
pressedY = -999;
}
};
public boolean comparePoints (Point p1, Point p2) {
if (p1.x == p2.x && p1.y == p2.y) {
return true;
}
return false;
}
}
The issue is that you are not adding new objects to the buffer. Each time it is a reference to the same List. So when you get the list at the correct index out of the buffer you get the same list as any other index.
To fix this create a copy of the lines list to add to the buffer instead of adding lines each time.
Something like:
buffer.add(lines);
lines = new LinkedList<List<Point>(lines);