How to make rect.intersects just check outside boundaries - java

I am trying to determine if clickRectangle, a rectangle created by the click of a mouse, on a canvas intersects with a drawnRectangle or not.
However, I don't want the intersects method to return true if I click anywhere in the drawnRectangle (i.e. the interior of the rectangle), I just want it to return true if an outer boundary of drawnRectangle was clicked.
How can I do that?
P.S: For clickRectangle and drawnRectangle see my comment below.

If I understand the question correctly, you want
public static boolean pointNearEdge(Point click, Rectangle drawnRectangle, int howNear){
Rectangle clickRect = new Rectangle(click.x-howNear, click.y-howNear, howNear*2, howNear*2);
if (drawnRectangle.contains(clickRect)) // totally inside -> false
return false;
// test if there is a partial intersection - i.e. we are near the edge
return drawnRectangle.intersects(clickRect);
}

Related

Rectangle created from mouse x and y not being translated with Graphics2D.translate (other rectangles do)

I'm making a side-scroller game with survival elements. (kinda like Terraria) When i'm walking to the right, all of the hitboxes and other objects are moved to the left, using Graphics2D.translate() (that's good) but when I use the mouse to click something, it appears that the rectangle/hitbox of the mouse isn't being "translated". I'm sure the problem lays with the rectangle of the mouse because if I remove the two lines of Graphics2D.translate() the digging of blocks work, but you can't walk around freely.
I already tried using the Area object, but also didn't fix it, it was still the same problem.
Rectangle rec = new Rectangle((int)e.getPoint().getX, (int)e.getPoint().getY(), 1, 1);
System.out.println("X: " + (int)e.getPoint().getX());
System.out.println("Y: " + (int)e.getPoint().getY());
bHandler.digBlock(rec); //bHandler is my class BlockHandler:
BlockHandler class:
public void digBlock(Rectangle rec) {
for (int i = 0; i < handler.block.size(); i++) {
Block block = handler.block.get(i);
if(rec.intersects(block.getBounds())) {
System.out.println("CLICKED");
block.setDigging(true);
}
}
}
The block.getBounds() method returns a Rectangle.
The block.setDigging(true) will set the Block.digging boolean to true.
What I want is a rectangle that is correctly being translated or/and I want to get the outprint "CLICKED" in my console when I click on a block!
Thanks for helping!
I solved it by adding the x variable from my Camera object to the x of my mouse rectangle! Again, thanks for helping!

Clearing textbox from StdDraw to write new input

I'm not sure if this would be a simple question to answer on here, just because I'm using the Standard Draw class written by Princeton University, and I'm not sure if it's a globally known class.
But I'd much appreciate any feedback from those familiar with the StdDraw library.
What I'm trying to do is fairly straight-forward; check to see if the mouse of the user clicks onto an input box I drew, and if it is clicked, clear the existing text (which simply says "input") to make an empty String.
This is what it looks like so far:
public boolean handleClick(double x, double y) {
if(!super.handleClick(x,y)){
value = false;}
else {
if(highlighted){
value = true;
StdDraw.textLeft(xCentre+0.005,yCentre," ");} //Add the label
else{
value = false;}
}
return value; //I handled it. Nobody else should.}
}//handleClick
super.handleClick(x,y) is simply a method in the super class that draws the dimensions of the box:
public void draw(){
StdDraw.setPenColor(StdDraw.WHITE);
StdDraw.filledRectangle(xCentre,yCentre,halfWidth,halfHeight);
StdDraw.setPenColor(StdDraw.BLACK);
StdDraw.setPenRadius(); //Default thin line.
StdDraw.rectangle(xCentre,yCentre,halfWidth,halfHeight);
}
value is simply an instance variable of this class that will return true if all conditions are satisfied:
private boolean value;
highlighted is a boolean instance variable from the super class that simply states if the box is an input or output box.
My main question would be, is the line
StdDraw.textLeft(xCentre+0.005,yCentre," ");
the right way to clear the existing text and create an empty String with StdDraw? As it's not clearing the line, but maybe there's a bug elsewhere in my code that I'm missing and this line should work?

how to define a class with an instance variable and methods to make it alternate between two values, and to modify it

I am trying to define a class that I could use for my board game.
I think I will use the accesor method(getTurn()) as my argument to the board game class.
When the game starts, it should give "BLACK", "BLACK" at the first two times, and then it should alternate between "WHITE" and "BLACK".
My startTurn() method returns this.
In the middle of the game, after the current player(WLOG, say his BLACK) makes a move, I need to check some condition(if the next player has no move possible), and depending on it, I want to change the order of it.
The methods I need to define is (so we are assuming the current turn was BLACK and now proceeding to the next one)
1) If the next player chooses to skip his/her turn, it should give BLACK again, and then alternate between WHITE and BLACK as before.
Like this : B-> B-> W -> B ->........ W -> B| -> B -> W -> B -> .....
or if the current player was white,
Like this : B-> B-> W -> B ->........ B -> W| -> W -> B -> W -> .....
, where '|' after B or W is just the symbol I use to explain the point where I test if the next player has possible move (using a method), and if not, changing the turn like that.
(I guess reverseTurn() method does this, and this may not be too difficult.)
2) If the next player chooses to move the other player's piece, it should give BLACK(so that WHITE can move a BLACK piece), then give BLACK(so that BLACK has his/her turn), and then alternate between WHITE and BLACK as before.
Like this : B-> B-> W -> B ->........ W -> B| -> B -> B -> W -> B -> .....
or if the current player was white,
Like this : B-> B-> W -> B ->........ B -> W| -> W-> W -> B -> W -> .....
, where '|' after B or W is just the symbol I use to explain the point where I test if the next player has possible move (using a method), and if not, changing the turn like that.
3) Another question is if I have the answer for the above two questions, how I could use this in my board game classes? All I could think of is initialize TurnIndicator, and call startTurn() in the constructor, and assign getTurn() when I pass the string as the turn argument, and call startTurn() every time a player makes a move?
Would this work?(because I am very unsure)
If it does, what about when I want to change the order? Should I then call that method conditionally instead of startTurn() method?
I have been stuck at this problem for very long. Especially question 2..
Any words of advice would be greatly appreciated.
Below is what I have done so far for TurnIndicator class.
Thank you!!
public class TurnIndicator {
private boolean _isWhite;
private int _count = 0;
private String _currentTurn;
public void startTurn() {
if(_count<3)
_count++;
if(_count == 1 || _count == 2) {
_currentTurn = "BLACK";
}
else {
_isWhite = !_isWhite;
_currentTurn = _isWhite ? "WHITE" : "BLACK";
}
}
public String getTurn() {
return _currentTurn;
}
public void reverseTurn() {
_currentTurn = _currentTurn == "WHITE" ? "BLACK" : "WHITE";
}
public String skipTurn() {
?
}
public String takeOthersTurn() {
?
}
}
"When the game starts, it should give "BLACK", "BLACK" at the first two times, and then it should alternate between "WHITE" and "BLACK"."
Inside startTurn() why not just do:
if(_count<3) {
_count++;
_currentTurn = "BLACK";
}
While I'm looking at the code (and notwithstanding the below), why don't you just get your reverseTurn() method to set isWhite == !isWhite and then call startTurn()?
Moving on to the questions.
1) "If the next player chooses to skip his/her turn, ..."
Don't think 'choosing to skip his/her turn', think 'choosing not to move his/her piece'. Therefore the logic still works: playerNext takes a turn which (it seems) could be moving his/her piece, moving playerFirst's piece, or not moving any pieces.
2) "If the next player chooses to move the other player's piece, it should give BLACK(so that WHITE can move a BLACK piece), ..."
Really? seems to me that it is still WHITE, because it is WHITE's turn, regardless of which colour piece gets moved. Around now, I'm thinking that you may want to call your players: player1 and player2 (or playerFirst & playerNext like I did earlier) to a) maintain a conceptual difference between the player and the piece colour and b) not have to go into two definitions of what's happening when trying to explain the logic
3) ... Would this work?
Think of the game as in real life. Should you call startTurn() every time a player makes a move? In a game of, say, scrabble, when a player makes a move do they always start their turn? Ie, do they always check tiles in their hand against tiles on the board, before consulting their mental dictionary? If the objects do this in real life, then it should work in an object oriented language (I'm assuming java, despite the c++ tag). But, the only way is to try and see. All this assumes I haven't interpreted the rules to your game all wrong resulting in the above making no sense in this context.
I think you are putting too much logic into your "TurnIndicator". Skip Turn is just "Next Turn" - the fact that the current player didn't make a move/play doesn't alter the order of the turns.
Also, you have two variables indicating whose turn it is. _isWhite and _currentTurn both. Just to make matters worse, your reverseTurn alters one without altering the other. I would suggest using a bool [assuming you actually mean to only ever have two players], and if you need the "string" of whose turn it is, call a function that returns it:
std::string playerColour()
{
if (_isWhite) return "WHITE";
return "BLACK";
}

java tetris: how to make a tetris piece move as 4 distinct tiles

I'm trying to make the game tetris in Java as a fun side project.
My game board is a grid of tiles:
grid = new Tile[height][width];
And within the grid, I create a new Tile object: activetile = new Tile(this,0, 0); //add new tile to "this" board
Currently:
I'm able to control a single tile- move it down, left and right
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if(keyCode == KeyEvent.VK_DOWN) {
checkBottomFull(0,4);
collisionCheck(activetile.getX(),activetile.getY());
checkEndGame(activetile.getX(), activetile.getY());
activetile.setLocation(activetile.getX(), activetile.getY()+1);
System.out.println("coordinates: " + activetile.getX() + ", " + activetile.getY());
repaint();
}
...right key and left key code omitted
As you can see from the keyPressed method, checkBottomFull() will clear bottom row if full, collisionCheck() will generate a new piece if block hits floor or another piece below, and checkEndGame() will end the game if block is stuck at the top.
I'm struggling with the following:
To create an actual tetris piece, I was thinking I should just generate 3 other instances of Tile, and based on what piece it is (L, O, Bar, Z, etc), set their locations at the appropriate places according to activetile (the single tile I have control over), like so:
if (piece == "Bar") {
block2 = new Tile(this, activetile.getX(), activetile.getY());
block3 = new Tile(this, activetile.getX()+2, activetile.getY());
block4 = new Tile(this, activetile.getX()+3, activetile.getY());
}
The problem with this is, my collision detection for activetile won't allow it to move appropriately because it will run into its other blocks. I tried to fix that in keyPressed() by setting the location of block2, block3, block4 AFTER the activetile's new location has been set, like so: (so once activetile moves down, all the others are allowed to move down so they don't overlap)
activetile.setLocation(activetile.getX(), activetile.getY()+1);
block2.setLocation(activetile.getX(), activetile.getY()+1);
block3.setLocation(activetile.getX(), activetile.getY()+1);
block4.setLocation(activetile.getX(), activetile.getY()+1);
This may work for going down, but it won't work for moving left or right because the tiles will overlap.
So, am I correctly creating a new instane of a Bar piece by generating new blocks like that? Is my thinking correct?
executable
https://www.dropbox.com/s/oyh26dfbmsvt5c8/my_tetris_test.jar
link to source code zip
https://www.dropbox.com/s/9kt3sl6qqo54amk/Tetris%20Two.rar
Thanks!
I would take a look at the Polygon class: http://docs.oracle.com/javase/6/docs/api/java/awt/Polygon.html
There are methods provided that can test for collision (insideness) with points on another object. You can also use translate(deltaX, deltaY) to greatly simplify the "motion" of your objects.

In Java, is there a way to obtain the component where an event is being handled?

Suppose I have 4 squares colored blue, white, red and green (myComponent) associated with the mouse press event. At one point, the mouse is pressed over one of them - say, the yellow one - and the event is activated.
Now, the control flux is inside the event handling function. How do I get the MyComponent - the yellow square - that caused this from here?
EDIT
I have another question. Is there a way to tell the position of the component? My problem is a bit more complicated than what I said.
Basically, I have a grid full of squares. When I click one of the squares, I have to know which one it is, so I can update my matrix. The thing is, if I calculate it myself, it only works on a given resolution.
I have a GridBagLayout, and inside it are the myComponents. I have to know which one of the components exactly - like, component[2][2] - caused the interruption.
I mean, I can tell which one of the components did it, but not where in the matrix it is located.
MouseEvent.getSource() returns the object on which the event initially occurred.
I have a GridBagLayout, and inside it
are the myComponents. I have to know
which one of the components exactly -
like, component[2][2] - caused the
interruption.
You could store the indices, e.g. (2,2), inside each myComponent when you add them to the matrix. That way, given the component, you can always identify its position in the matrix.
class MyComponent extends JButton
{
final int i; // matrix row
final int j; // matrix col
// constructor
MyComponent(String text, int i, int j)
{
super(text);
this.i = i;
this.j = j;
}
...
}
By adding a MouseListener (or alternatively, a MouseAdapter, if you don't need to override all the MouseListener' methods) to each of your colored boxes, when an event such as a mouse click occurs, theMouseListenerwill be called with a [MouseEvent`]3, which can be used to obtain the component that was clicked.
For example:
final MyBoxComponent blueBox = // ... Initialize blue box
final MyBoxComponent whiteBox = // ... Initialize white box
final MyBoxComponent redBox = // ... Initialize red box
final MyBoxComponent greenBox = // ... Initialize green box
MouseListener myListener = new MouseAdapter() {
public void mouseClicked(MouseEvent e)
{
// Obtain the Object which caused the event.
Object source = e.getSource();
if (source == blueBox)
{
System.out.println("Blue box clicked");
}
else if (source == whiteBox)
{
System.out.println("White box clicked");
}
// ... and so on.
}
};
blueBox.addMouseListener(myListener);
whiteBox.addMouseListener(myListener);
redBox.addMouseListener(myListener);
greenBox.addMouseListener(myListener);

Categories

Resources