I am making a simple game.
I have 6 buttons and i want to shuffle them each time on different locations.
So i've made a simple method to achieve this.
private void changeButtonPlace(ImageView button) {
Random r = new Random();
int newXloc = r.nextInt(getScreenWidth() - (2 * button.getLayoutParams().width));
int newYloc = r.nextInt(getScreenHeight() - (3 * button.getLayoutParams().height));
button.setX(newXloc);
button.setY(newYloc);
}
It works pretty well, but sometimes the buttons override each other which means that it goes on the almost the same location. I want each button to be on a unique location and don't touch other buttons.
Any idea how i can achieve this?
Thanks in advance!
What you are looking for is collision detection, and my answer will greatly simplified this process. I suggest searching for collision detection algorithms to learn more.
So, for super simple starts, we can compare the position, length, and height of 2 boxes. For my example, I am going to assume the origin of these to boxes are their upper left corner.
if((boxA.xPos + boxA.length ) < boxB.xPos || boxA.xPos > (boxB.xPos + boxB.length))
That will check if the two boxes are touching along the x-axis, and we can change the values for the y-axis as well
if((boxA.yPos + boxA.height ) < boxB.yPos || boxA.yPos > boxB.yPos + boxB.height)
Now, this is not a very efficient way of doing this. There are lots and lots of better ways to simplified this logic, and save on resources. But, it is quick and dirty, and probably good enough for a small application like your simple game involving only 6 buttons.
So, with these two equations, you can either nest them then run your collision code inside, or you can OR them together to one equation like this:
if(((boxA.yPos + boxA.height) < boxB.yPos || boxA.yPos > (boxB.yPos + boxB.height)) || ((boxA.xPos + boxA.length ) < boxB.xPos || boxA.xPos > (boxB.xPos + boxB.length)))
That is a lot to read for one line, and if you just starting out, I would suggest nesting them so you can better see the flow of logic through the equations. But, keep in mind for the future, if you ever need to squeeze those few extra bits of performance, OR them together to one if statement is alright place to start.
One way would be to make a grid and instead of a random location on the screen use a random point on the grid. That way you can check if the current grid location has a button on it already.
If you want them to be more scattered you could add each button to an array and check that the new doesn't touch the other buttons. Loop infinitely creating random locations and another loop to check they don't hit the other buttons in the array. Once a new location is found add the button and break out of the infinite loop.
You should take in account the width of the button , and before setting the location of the button make sure no button intersect with a simple if, if they do just randomize the intersecting buttons, should be easy to programm
Edit :
Lets make it a bit simpler an assume you have 3 buttons an assuming they are located on a 2d axis with these coordinates
A : 1,0
B : 2,0
C : 5,0
button width : X=2 Y=2
As you can see in this example at first glance it seems as though no button intersects with each other yet if you add the width to B you understand that is real location is B [1,3] ,[-1,1] intersects with the real location of C [4,6],[-1,1] assuming the coordinates are the center of the button
first [,] represents X axis second [,] represents Y axis
therefore your check will be something like so:
For each Button x
For each button x
calculate real coordinates of button x and y check intersection
if exists recalculate the coordinates and start the loop over
this solution is a bit expensive when talking about running time but once you get the idea you will be able to find something easier.
Related
I'm trying to write a tetris clone. My board is a 10x20 array of integers on which 0 means no tile, 1-7 means a tile of specific color. It is constantly translated to graphic interpretation. My shapes are 4x4 arrays of integers. I've just come to a realisation that while making all of the shapes 4x4 makes some things easier, it also causes a problem when moving a piece left and right. Let's say we've got the I shape:
0010
0010
0010
0010
Now, if I move it to left wall there will always be a two units long gap, since the 0s cant move outside of the main board array. What would be the easiest way to allow the 1s to move to the left wall without causing an out of bounds exception?
Using your described method, one way to simply avoid getting the IndexOutOfBoundsException would be to expand your board to be 18 x 24 instead of 10 x 24, and then write in additional code that doesn't let you move a block left/right if there would be any 1's in the object array that leave the middle 10 squares of the grid. By adding this 'padding' to your grid, you avoid the exception and should still be able to implement.
I hope this approach makes sense to you. If not I can provide a more pseudo-code driven answer, but I hope you get the idea. (Just comment if you have any questions.)
BTW, #assylias makes a very good point. It is important to have a good design/plan before you start implementing things to avoid road-bumps like these. It comes with experience, so keep practicing and you will get the hang of it.
NOTE: As Nick pointed out in the comment, another way of doing this is to simply check if any 1's leave the grid before moving any of the arrays. This is certainly possible (and arguably a more elegant/simple solution), although it may be a bit harder to get right.
You need a way of detecting collisions with borders and existing pieces.
You would probably have a fixed handle on each piece, you'll also have an X and Y offest for the piece which indicates it's position as it moves down the grid.
To stop a piece moving out of bounds, loop through the 4*4 matrix of the moving piece and for the bits which are set to 1 simply check
to make sure that the X position + X offset is >= 0 and <=9 and the Y Position is >=0 and <=19 if either of these checks fail
then your piece would be moving outside the limits of the board array so stop the change to x or y offest as appropriate.
Translating the co-ordinates of the set bits in your piece matrix with the board array also allows you to check and see whether your piece has collided with a tile already in the board.
You should be doing these collision checks when a piece rotates as well I would have thought.
I am working on a small game in Java where you are playing as one small box and the goal is to touch other boxes. You move around using buttons and when you touch another box I want the box that isn't the one the player is to disappear.
I am not sure how to detect when the boxes are touching each other.
I am thinking something like:
if (mainBox is touching otherBox){
otherBox.disappears();
}
Any help would be appreciated.
Typical collision logic is done by comparing points.
Since the typical draw point of your square is the top left, the basic logic is this:
p = playerBox
t = targetBox
if((t.x>=p.x && t.x<=p.x+p.w) || (t.x+t.w>=p.x && t.x+t.w<=p.x+p.w)){
if((t.y>=p.y && t.y<=p.y+p.h) || (t.y+t.h>=p.y && t.y+t.h<=p.y+p.h){
System.out.println("Player p collided with target t!");
}
}
May be a bit hard to read but the basic idea is to check if any point of the target is inside the player.
My first thought is to maintain a hash map of no-user boxes where the key= position of a box and value = box object. Every time the players box moves you want to fire an event that triggers a check for collisions.
When the event is triggered you just say
public void checkForCollision(Position currentPosition){
// do not go further if no collision
if (!boxes.containsKey(currentPosition)){ return }
//this part will only execute if there is a collission
boxes.get(currentPosition).makeItDissapear();
}
Prerequisites:
- an object describing the boxes properties
- research google's EventBus to easily manage envents
I'm writing my first own chess game in Java.
My code already works for two players, manually playing from the keyboard, and I would like to expand it to a player against the computer game.
My problem is that I've never dealt with random actions.
The method which is moving a piece on the board, needs to receive 4 inputs:
two integers for the piece location, and two integers for the destination on the board.
Choosing the wrong inputs is OK since the movePiece method already checks if the integers are not out of the board's bounds, that they really reach a piece of the current player's color, that there's a piece in the coordination and its not empty, etc.
But how do I get these 4 integerss randomly? And how do I make them as closest as possible to "real" inputs (so I don't spend a lot of time disqualifying bad inputs)?
Java provides at least two options to generate random values:
http://docs.oracle.com/javase/6/docs/api/java/util/Random.html
http://docs.oracle.com/javase/6/docs/api/java/lang/Math.html#random()
E.g. to get random int values bounded by 4:
int x = new Random().nextInt(4);
int y = (int) (Math.random() * 4);
System.out.println(x + " " + y);
>> 2 3
If you really would like to create a computer player who just moves about randomly, I think it would be better to do it it like this:
Randomly select one of the existing chess pieces on the board
Compute all legal destinations to which that chess piece could move
If there are no legal destinations, choose a new piece amongst the previously not selected pieces
Randomly select one of the computed legal destinations
However, letting a computer player move about randomly is rather silly. A computer player would need to have some form of logic to compare which out of two moves is better. Implementing such logic is probably rather complex, and you're probably better off using a chess library as someone suggested in the comments.
You don't need 4 ints. You only need 1.
A way of doing this:
Iterate the pieces on the board.
For each piece, determine its available moves and stick all the available moves in a list.
Pick one move from the list at random (or at non-random, if you feel so-inclined).
I'm having some unique trouble determining the order in which objects should be rendered, particularly in the case of when a player is behind a wall. I'll try and explain thoroughly, so prepare for a lot of information.
I render things back to front (as recommended here: Drawing Isometric game worlds) and that is, for the most part, simple enough.
I determine what is in the back using a simple comparator:
private Comparator<Entity> spriteSorter = new Comparator<Entity>(){
public int compare(Entity e1, Entity e2){
if(e1.getPhysics().getY() > e2.getPhysics().getY()) return 1;
if(e1.getPhysics().getY() < e2.getPhysics().getY())return -1;
return 0;
}
};
This uses the hitbox of an entity to determine its render order, and it works flawlessly for entities with a rectangular hitbox (as almost all my characters do). The actual draw call looks like this:
ArrayList<Entity> spriteList = new ArrayList<>();
spriteList.add(player);
for(int i = 0; i < walls.size(); i++){
spriteList.add(walls.get(i));
}
Collections.sort(spriteList, spriteSorter);
for(int i = 0; i < spriteList.size(); i++){
spriteList.get(i).render(g);
}
Here's where things get tricky though, all my characters use an instance of Rectangle, and their ordering works with no problem at all, but my walls (due to the nature of an isometric game) cannot use a rectangle, and thus use a Polygon that fits their size.
See picture:
I have to use a Polygon because if I use a rectangle, I get a stupid unpassable space near the wall like so:
Unfortunately, due to the nature of polygons, there is no immediately apparent test to see if the player is in front or behind the wall. Line 3 seems to be a likely candidate as a test, but there are two triangles on either side of the wall that would pass the player.getPhysics.getY() > wall.getPhysics.getY() test and mark him as in front, when he could be both in front and behind the wall.
So, how can I devise a test to tell me when he is behind the diagonal lines? The nature of Shapes and Polygons in Java seems to be limiting me a lot, but I'm sure there's a way to do it. I've played with points a lot, and getCenterY() has gotten fairly close, but it's still not perfect. The problem cases that arise with all of the methods I've tried look like this:
Actually behind, rendered in front
or this:
Actually in front, rendered behind.
Any one got any ideas?
Suppose your character is located at (x, y) and the wall has a central line which leads from (a, b) to (c, d). Then you can use the sign of the determinant
| x a c |
| y b d | = ab + ad + cy - ay - cb - xd
| 1 1 1 |
to decide whether the triangle formed by these three points is oriented clockwise or counter-clockwise. You can compute a similar determinant for the camera instead of the character, and multiply the results. If the product is positive, then camera and character are on the same side of the wall, and you want to draw the character after the wall. If the product is negative, then camera and character are on opposite sides and you want to draw the character before the wall.
This simplification assumes your walls are lines or line segments, not rotated rectangles, but unless your player can actually move inside the wall, the difference should not matter unless the camera looks pretty much head-on onto the short side of the wall. So perhaps you want a big rectangular bounding box for the wall after all, to do rough ordering, and only use the above if the player is inside this (still passable) bounding box.
It's not so easy!!!. Why? Because you have others sprites involucred in the scene (Not only 2. By example, you need have 2 players + 1 wall). How do you order them for rendering?
You must always work using x, y, z which determinate respectevely "front, back, behind of" position.
NOTE: After 2 (hard) months of analysis of the problem I finally found and implemented a "correct render drawing" for my new cocos2d-js game. Solution consists in mapping, for each tile (susceptible), which sprites are "front, back and behind".
Once doing that you can draw them following a "recursive logic".
I have made threads in the past about similar questions but because of my lack of detail the answers have not really been related to what I needed so I am going to try explain my question in as much detail as I can and hopefully it will be easier for you to understand what I require.
I watched Bucky's slick game tutorials on youtube and made a 2D Java game, the game is basically a 2D player viewed from above (birds eye view) can move around a 2D map with user key input (up, down, left, right). The map the player moves around is very small so that meant boundaries had to be set so that the player could not walk off of the map, to give you a better idea of how this was done, here is the tutorial for setting up the voundries:
http://www.youtube.com/watch?v=FgGRHId8Fn8
The video will also show you exactly what the game is like.
The problem is, these boundaries only require one axis meaning that if the player is walking down you say something like "if player gets to the coordinate (number) on the X axis change the player movement to the opposite direction so that he can not go any further."
Now this creates a problem for me because this only requires one axis so it easy to set up and understand but if you look on the video, on the map there is a house and I want my player not to be able to walk over that also but this deals with 2 dimensions, I have looked at things like rectangle collisions and have seen things relating to them in the other posts but I get confused because I am new to Java and havent really done much with it at the moment apart from watching Bucky's tutorials.
My code at the moment for my game class has got the following methods: init, render and update. So to sum it up I really just want to set up a way of not letting my player walk through the house, I will mention also (I should have mentioned it in my other threads) as I am very new to Java, could you please take a step by step method of showing me how to set up the collisions, I mean even the basics of things like making the rectangle if required.
If my code is required please tell me and I will post it as soon as possible.
Thank you in advance.
You can set up the board as a 2x2 grid of a class that has has property such as 'isBlocked'. By default the edges of the board would have this property set to true to prevent the character from walking off the edge. When you add other obstacles such as a house or a wall the grid position(s) the object occupies would also have the property set to true. Then when moving a character you just check if the grid position the character moves to has the property set to false to see if it's an allowable move. This also makes it quite trivial to save the level data so you can just load them from disk later on.
Two possible options:
Extend Shape or Rectangle or the relevant Slick objects (they should exist IMO) and just check for intersect()
Look for (x1,y1) and (x2,y2) values such that it starts outside and ends up inside.
Assuming you have intersect() methods:
//Grab the previous position
prevPosX = movingobject.X;
prevPosY = movingobject.Y;
//Update the position
movingobject.update();
//Test for collision
if(movingobject.intersects(targetobj)) {
//If it collided, move it back
movingobject.X = prevPosX;
movingobject.Y = prevPosY;
//And reverse the direction
//(might want to do other stuff - e.g. just stop the object)
movingobject.speed *= -1; //Reverse the speed
}
in this case your update class should also add one more condition to look for the house. let say the cooridnates of house(assuming rectanglular house here for other shape just change x and y values) are (x1,y1)(x1,y2)(x2,y2)(x3,y1) you have to add a condition to make sure
x value is not between x1 and x2 and at the same time y value cannot between y1 and y2.