Search code examples
javaobjectblockvelocity

How can I make each block move in the opposite direction once they reach a certain point on the side of the screen?


I am trying to get three different blocks to move back and forth from one side of the screen to the other. If the block on the far right reaches the game frame's width, it's velocity is reversed and it starts moving to the left side. However, my problem exists with the other two blocks. I put in my code a method that states once the second block reaches the (game width - 100), with 100 just being the width of each blocks, it's velocity should be reversed. The third block is suppose to work the same except once it reaches the x point (game width - 200). My attempt to change the velocity of the second and third blocks can be seen under the UpdateBlocks method in the PlayState class posted below.

Another thing I want to point out is that in update method in the block class, the x value is being reversed too. I tried at first to make it read the blocks from the PlayState then change the corresponding velocities but I got a thread error. That's why I am bringing my current predicament to you.

Here is the block class:

package com.jamescho.game.model;

import java.awt.Rectangle;

import com.jamescho.framework.util.RandomNumberGenerator;
import com.jamescho.game.main.GameMain;
import com.jamescho.game.state.PlayState;

public class Block {
private float x, y;
private int width, height, velX = 700;
private Rectangle rect;
private PlayState play;
private boolean visible;
private static final int UPPER_Y = 275;
private static final int LOWER_Y = 355;

public Block(float x, float y, int width, int height) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    rect = new Rectangle((int) x, (int) y, width, height);
    visible = false;
}

// Note: Velocity value will be passed in from PlayState!
public void update(float delta) {
    x += velX * delta;
    if (x <= 0 || x >= GameMain.GAME_WIDTH - 100) {
        velX = -velX;
    }
    updateRect();
}

public void updateRect() {
    rect.setBounds((int) x, (int) y, width, height);
}

public void invisible() {
    visible = false;
}

public void visible() {
    visible = true;
}

public void stop() {
    velX = 0;
}

public void reverse() {
    velX = -velX;
}
public float getX() {
    return x;
}

public float getY() {
    return y;
}

public boolean isVisible() {
    return visible;
}

public Rectangle getRect() {
    return rect;
}
}

Here is the PlayState where everything is going on:

package com.jamescho.game.state;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import com.jamescho.game.main.GameMain;
import com.jamescho.game.main.Resources;
import com.jamescho.game.model.Block;


public class PlayState extends State {

private ArrayList<Block> row1;
private ArrayList<Block> row2;
private ArrayList<Block> row3;

private Block block;
private Font scoreFont;
private int playerScore = 0;

private static final int BLOCK_HEIGHT = 100;
private static final int BLOCK_WIDTH = 100;
private int blockSpeed = -200;

private static final int PLAYER_WIDTH = 66;
private static final int PLAYER_HEIGHT = 92;

@Override
public void init() {

    row1 = new ArrayList<Block>();
    row2 = new ArrayList<Block>();

    scoreFont = new Font("SansSerif", Font.BOLD, 25);
    for (int i = 0; i < 3; i++) {
        Block b = new Block(i * 105, GameMain.GAME_HEIGHT - 101,
                BLOCK_WIDTH, BLOCK_HEIGHT);
        row1.add(b);
        b.visible();

    for (int h = 0; h < 3; h++) {
        Block b2 = new Block(h * 105, b.getY() - 208,
            BLOCK_WIDTH, BLOCK_HEIGHT);
            row2.add(b2);
            b2.invisible();
            }

    }

}

@Override
public void update(float delta) {

    playerScore += 1;
    if (playerScore % 500 == 0 && blockSpeed > -280) {
        blockSpeed -= 10;
    }

    Resources.runAnim.update(delta);// starts iterating through its frames

    updateBlocks(delta); 
}

private void updateBlocks(float delta) { // time from last update
    for (Block b : row1) { //foreach statement; for each iteration of "b" the     code is executed, one "b" at a time
        if(row1.get(1).getX() == GameMain.GAME_WIDTH - BLOCK_WIDTH - 5) {
            row1.get(1).reverse();
        }
        else if(row1.get(2).getX() == GameMain.GAME_WIDTH - 2 * BLOCK_WIDTH - 5) {
            row1.get(2).reverse();
        }
        b.update(delta);

}
    for (Block c : row2) { //foreach statement; for each iteration of "b" the code is executed, one "b" at a time
        // used with objects; can't use primitive
        c.update(delta);
        if (c.isVisible()) {

        }
    }
}


@Override
public void render(Graphics g) {
    g.setColor(Color.BLACK);
    g.fillRect(0, 0, GameMain.GAME_WIDTH, GameMain.GAME_HEIGHT);
    renderPlayer(g);
    renderBlocks(g);
    renderScore(g);
}

private void renderScore(Graphics g) {
    g.setFont(scoreFont);
    g.setColor(Color.GRAY);
    g.drawString("" + playerScore / 100, 20, 30);
}

private void renderPlayer(Graphics g) {

    }


private void renderBlocks(Graphics g) {
    for (Block b : row1) {
        if (b.isVisible()) {
            g.drawImage(Resources.blue_panel, (int) b.getX(), (int) b.getY(),
                    BLOCK_WIDTH, BLOCK_HEIGHT, null); // change null if you want the object to know about object
        }
    }
    for (Block c : row2) {
        if (c.isVisible()) {
            g.drawImage(Resources.blue_panel, (int) c.getX(), (int) c.getY()+105,
                    BLOCK_WIDTH, BLOCK_HEIGHT, null); // change null if you want the object to know about object
        }
    }
}

@Override
public void onClick(MouseEvent e) {
}

@Override
public void onKeyPress(KeyEvent e) {
    if (e.getKeyCode() == KeyEvent.VK_SPACE) {
        for (Block b : row1) {
            b.stop();
        for (Block c : row2) {
            if (c.isVisible() == true) {
                c.stop();
            }
            }
        }
    }

     else if (e.getKeyCode() == KeyEvent.VK_DOWN) {

    }
}

@Override
public void onKeyRelease(KeyEvent e) {
    if(e.getKeyCode() == KeyEvent.VK_SPACE) {
        for (Block c: row2) {
            c.visible();
        }
    }
}

public float getb1X() {
    return row1.get(1).getX();
}
}

Solution

  • Sorry I haven't gone through your entire code. But this is how I would do it:

    int x , int y -- are the coordinates of each block on the screen.

    a block can move on the screen in 4 ways / directions / quadrants:

    1) x = x + deltaX, y = y + deltaY  
    2) x = x - deltaX, y = y + deltaY  
    3) x = x + deltaX, y = y - deltaY
    4) x = x - deltaX, y = y - deltaY
    

    Thus in order to change the direction when a block hits any side you should multiply deltaX with -1 if it hits left or right side and deltaY with -1 if it hits the bottom or top. this will reverse its direction.