Collision Detection in Box2D - java

So I'm using Box2D for collision detection in a game. I have a tilemap that contains information on the terrain: for now it's just a char[][] that has either road or grass. Now, at the start of each level I wanted to create rectangles to describe the different terrains, but I wanted these rectangles to be optimized and apparently that takes quite an algorithm.
My first approach was to create an individual terrain for EVERY tile in the map at the start of the level. The FPS was reduced to 5.
My second idea was to simply create the different rectangles for terrains as the player moved along the map, deleting the rectangles that were out of view. Although it would still be a lot of rectangles, it would be considerably less.
I haven't attempted the second method yet, but I want to know: is there any easy way for me to efficiently perform collision detection against terrain with a large tilemap?
Thanks.

Try combining tiles. For example, if you have 16 rectangular collision volumes for 16 tiles like so...
* * * *
* * * *
* * * *
* * * *
You can obviously combine these tiles into one large rectangle.
Now, things get more difficult if you have tiles in a weird arrangement, maybe like this...
**---
****-
*--**
-*-*-
I just recently solved this problem in my game using a quad tree and sweep and prune. (Sweep and prune isn't strictly necessary, its an optimization.)
Quad tree partitions your square tiles into bigger rectangles, then you iterate over the rectangles the quad tree produces, and combine them if they have the same width, then iterate over them again and combine them by similar heights. Repeat until you can't combine them anymore, then generate your collision volumes.
Here's a link to a question I asked about a more optimal reduction. I probably won't implement this as it sounds difficult, and my current approach is working well.
Some code:
do {
lastCompressSize = currentOutput;
this.runHorizontalCompression(this.output1, this.output2);
this.output1.clear();
this.runVerticalCompression(this.output2, this.output1);
this.output2.clear();
currentOutput = this.output1.size;
iterations += 1;
}while (lastCompressSize > currentOutput);
public void runHorizontalCompression(Array<SimpleRect> input,
Array<SimpleRect> output) {
input.sort(this.xAxisSort);
int x2 = -1;
final SimpleRect newRect = this.rectCache.retreive();
for (int i = 0; i < input.size; i++) {
SimpleRect r1 = input.get(i);
newRect.set(r1);
x2 = newRect.x + newRect.width;
for (int j = i + 1; j < input.size; j++) {
SimpleRect r2 = input.get(j);
if (x2 == r2.x && r2.y == newRect.y
&& r2.height == newRect.height) {
newRect.width += r2.width;
x2 = newRect.x + newRect.width;
input.removeIndex(j);
j -= 1;
} else if (x2 < r2.x)
break;
}
SimpleRect temp = this.rectCache.retreive().set(newRect);
output.add(temp);
}
}
public void runVerticalCompression(Array<SimpleRect> input,
Array<SimpleRect> output) {
input.sort(this.yAxisSort);
int y2 = -1;
final SimpleRect newRect = this.rectCache.retreive();
for (int i = 0; i < input.size; i++) {
SimpleRect r1 = input.get(i);
newRect.set(r1);
y2 = newRect.y + newRect.height;
for (int j = i + 1; j < input.size; j++) {
SimpleRect r2 = input.get(j);
if (y2 == r2.y && r2.x == newRect.x
&& r2.width == newRect.width) {
newRect.height += r2.height;
y2 = newRect.y + newRect.height;
input.removeIndex(j);
j -= 1;
} else if (y2 < r2.y)
break;
}
SimpleRect temp = this.rectCache.retreive().set(newRect);
output.add(temp);
}
}

Related

Is there any way to detect image is Blurry after capturing from Camera in Android (Except OpenCV )

I am working with Camera2 API and want to detect captured image is blurry or clear, i used OpenCV for this but result is not satisfactory and it increases APK size 3 times, So is there any way to detect blurry?
Measuring image focus/blur involves iterating of the pixels of the bitmap, or at least a portion thereof.
While you don't need OpenCV to iterate over the pixels of a bitmap on Android, its not for the faint of heart. Doing so in a performant way would require you to drop into JNI native code, or perhaps a technology like RenderScript, as iterating over pixels in Java or Kotlin might prove too slow.
There are many algorithms and techniques for measuring focus, or sharpness, or contrast, this is one I've used with reasonable success.
Luma is the luminosity of a pixel, i.e. grayscale pixel value. You'll want to convert each pixel to a grayscale value for this focus measure. e.g. using the NTSC formula:
pixelLuma = (red * 0.299) + (green * 0.587) + (blue * 0.114)
Here is a suggested formula to measure focus score:
FocusScore = Max({Video_Gradient}) / {Gray_Level_Dynamic_Range} * {Pixel_Pitch}
Max{Video_Gradient} = a measure of the maximum luminosity difference between adjacent pixels (x,y) across the bitmap.
e.g.:
horizontally measure pixel[x] - pixel[x+1]
vertically measure pixel[y] - pixel[y+1]
{Gray_Level_Dynamic_Range} = difference between average of N lightest pixels and N darkest pixels across the bitmap. A typical value for N is 64, in my case working on images around 1200w x 500h. Smaller images should use smaller N.
{Pixel_Pitch} = 1 / DPI = 1/200 = 0.005
This will result in a score, higher values are more in focus. You can determine a reasonable threshold.
Here is a code snippet written in C:
width = width of bitmap
height = height of bitmap
pixels = an array of bytes of size (width * height) holding pixel luminosity values
VFOCUS_N = 64
int gradientHorizontal[256];
int *pGradientHorizontal = gradientHorizontal;
int gradientVertical[256];
int *pGradientVertical = gradientVertical;
int luminanceHistogram[256];
int *pLuminance = luminanceHistogram;
int maxGradient = 0;
for (int i = 0;i < 256;i++)
{
gradientHorizontal[i] = 0;
gradientVertical[i] = 0;
luminanceHistogram[i] = 0;
}
// pixel by pixel math...
for (nRow = 0; nRow < height-1; nRow++)
{
nRowOffset = nRow * width;
nNextRowOffset = (nRow+1) * width;
for (nCol = 0; nCol < width-1; nCol++)
{
int gC = pixels[nRowOffset + nCol];
int gH = abs(gC - pixels[nRowOffset + nCol + 1]);
int gV = abs(gC - pixels[nNextRowOffset + nCol]);
pLuminance[gC]++;
pGradientHorizontal[gH]++;
pGradientVertical[gV]++;
}
}
// find max gradient
for (int i = 255;i >= 0;i--)
{
// first one with a value
if ((gradientHorizontal[i] > 0) || (gradientVertical[i] > 0))
{
maxGradient = i;
break;
}
}
// calculate dynamic range
int rangeLow = 0;
int rangeHi = 0;
int p;
p = 0;
for (int i = 0;i < 256;i++)
{
if (luminanceHistogram[i] > 0)
{
if (p + luminanceHistogram[i] > VFOCUS_N)
{
rangeLow += (i * (VFOCUS_N - p));
p = VFOCUS_N;
break;
}
p += luminanceHistogram[i];
rangeLow += (i * luminanceHistogram[i]);
}
}
if (p)
rangeLow /= p;
p = 0;
for (int i = 255;i >= 0;i--)
{
if (luminanceHistogram[i] > 0)
{
if (p + luminanceHistogram[i] > VFOCUS_N)
{
rangeHi += (i * (VFOCUS_N - p));
p = VFOCUS_N;
break;
}
p += luminanceHistogram[i];
rangeHi += (i * luminanceHistogram[i]);
}
}
if (p)
rangeHi /= p;
float mFocusScore = (float)fmin((float)maxGradient / (fabs((float)rangeHi - (float)rangeLow) * 0.005), 100.00);
Low focus scores means a blurry image. Values close to or in excess of 100 indicate a sharp image, the code above caps the score at 100.

How to create a sine wave in processing?

I would like to create a sine wave using vectors (as I am using box2d).
So far I have (in void draw())
Vec2 mov2 = new Vec2(sin(angle)*scalar,0);
for (int j = 0; j <= 10; j++) {
bridge.particles.get(j).body.setLinearVelocity(mov2);
}
where bridge is a chain of particles. However, this makes all the particles move back and forth at the same time whereas I would like to move like a sine wave so that each particle moves just slightly after the previous one.
You need to add some sort of offset between each of the particles inside your loop.
Example:
for( int i=0; i < 360; i++ ){
float x = 1 + i;
float y = (float)(Math.sin( Math.toRadians(i+currentOffset)));
bridge.particles.get(j).setTransform(x, y, 0);
}
currentOffset+=1;

How can I effectively implement collision for a 2D game?

I just started a new 2D game using Java, LWJGL, and Slick Util but I can't seem to figure out a good way to make collision detection.
If I wanted to, it would be easy to detect collision between 2 entities with the Rectangle intersect method, but it can only check the collision with a certain area you specify.
I have thought that I could make a list of every entity and its coordinates as its created and then run the intersect method through the list, but then it would check for collision with every entity on the entire map for every time the game updated and I think that would be too inefficient.
Does anyone know a more efficient way to create collision detection? If there was some way i could check if there was an entity at every point the character moved that would probably be the best.
If I have not enough information or I made this sound too confusing please tell me and I can try to clarify things. Also as a side question, what are the benefits of using slick util or slick 2D over one another. Thanks for the help!
The usual way to solve this is a scene graph, a hierarchical system of the objects of the game world.
You might want to look at this and this.
Shortened: you logically group your objects under nodes and assign the nodes a bounding rectangle that encompasses all its sub-nodes and leaves(objects). Everything is grouped again under one main node to access the tree. Now you can test a object for collision with a node, usually starting from the main node. If you get a hit you check its sub-nodes and leaves.
This will take some time to implement but can cut down on CPU usage if the tree structure/grouping is done right. It has also the benefit that you can implement local transforms which makes moving objects relative to each other easier.
Because I hate "The usual way", I made an array of all the coordinates and then checked if a single point hit the coordinate.
Here is a slight modification of my code to demonstrate (It is in 3D):
for (CannonBall can : GameServer.ballss){ //Go through all cannonballs
if (can.owner != cl){ //Can.owner is the ship, cl is the player the cannonball is being checked with to see if colliding.
int distancex = (int) (can.x - cl.z);
int distancez = (int) (can.z - cl.x);
final int distancey = (int) (can.y - cl.y);
double xRot = Math.cos(Math.toRadians(cl.rotation)) * (distancex - 0) - Math.sin(Math.toRadians(cl.rotation)) * (distancez - 0) + 0;
double zRot = Math.sin(Math.toRadians(cl.rotation)) * (distancex - 0) - Math.cos(Math.toRadians(cl.rotation)) * (distancez - 0) + 0;
distancex = (int) xRot;
distancez = (int) zRot;
try{
if (true){ //Skip different coordinates for different ships for demonstration purposes
i = GameServer.coords[GameServer.DELTA + distancex][GameServer.DELTA + distancez][GameServer.DELTA + (distancey)];
}
if (i == 1){
if (can.owner != cl){
remcan.add(can);
if (can.type == 0){
double damage = (100 + Math.random()*25);
if (cl.type == 1){
damage/=2;
}
if (cl.type == 2){
damage*=2;
}
cl.damage-=damage;
}
if (can.type == 1){
double damage = (Math.random() * 500);
if (cl.type == 1){
damage/=2;
}
if (cl.type == 2){
damage*=2;
}
cl.damage-=damage;
}else{
double damage = (100 + Math.random()*25);
if (cl.type == 1){
damage/=2;
}
if (cl.type == 2){
damage*=2;
}
cl.damage-=damage;
}
crash = true;
if (cl.damage < 1){
if (!cl.sinking){
cl.sinking = true;
}
}
}
}
}catch (Exception e){
e.printStackTrace();
}
}
GameServer.coords is an int[][][], which is given coordinates like so:
public static int[][][] coords;
public void CollisionSetup(){
try{
File f = new File("res/coords.txt");
String coords = readTextFile(f.getAbsolutePath());
for (int i = 0; i < coords.length();){
int i1 = i;
for (; i1 < coords.length(); i1++){
if (String.valueOf(coords.charAt(i1)).contains(",")){
break;
}
}
String x = coords.substring(i, i1).replace(",", "");
i = i1;
i1 = i + 1;
for (; i1 < coords.length(); i1++){
if (String.valueOf(coords.charAt(i1)).contains(",")){
break;
}
}
String y = coords.substring(i, i1).replace(",", "");;
i = i1;
i1 = i + 1;
for (; i1 < coords.length(); i1++){
if (String.valueOf(coords.charAt(i1)).contains(",")){
break;
}
}
String z = coords.substring(i, i1).replace(",", "");;
i = i1 + 1;
//buildx.append(String.valueOf(coords.charAt(i)));
////System.out.println(x);
////System.out.println(y);
////System.out.println(z);
//x = String.valueOf((int)Double.parseDouble(x));
//y = String.valueOf((int)Double.parseDouble(y));
//z = String.valueOf((int)Double.parseDouble(z));
double sx = Double.valueOf(x);
double sy = Double.valueOf(y);
double sz = Double.valueOf(z);
javax.vecmath.Vector3f cor = new javax.vecmath.Vector3f(Float.parseFloat(x), Float.parseFloat(y), Float.parseFloat(z));
//if (!arr.contains(cor)){
if (cor.y > 0)
arr.add(new javax.vecmath.Vector3f(cor));
if (!ship.contains(new Vector3f((int) sx, (int) sy, (int) sz)))
ship.add(new Vector3f((int) sx, (int) sy, (int) sz));
Float.parseFloat(z)));
}
}
public void setUpPhysics() {
//coords = new int[20][20];
coords = new int[80][80][80];
coords1 = new int[80][80];
//coords[-5 + DELTA][7 + DELTA] = 11;
for (javax.vecmath.Vector3f vec : arr){
coords[DELTA+(int) vec.x][DELTA+(int) vec.z][DELTA + (int) vec.y] = 1; //This is line 124
coords1[DELTA+(int) vec.x][DELTA+(int) vec.z] = 1;
}
}
Though it has limitations on collision interaction, it works for cannonballs colliding with a ship and checking the front of a ship to see if it has hit another ship. Also, it uses barely any CPU.
No idea on the opinions of other programmers on such a method.

How to get the last value that an integer had before a method were executed

I have two squares that moves around on the screen, both of the squares are from the same class (it's the same square that was drawn two times). I have already figured out how to do the collision detection between them so thats not a problem. The problem is that the squares can go through each other so I was thinking that I could make it so that when the squares hit each other they will teleport to the latest x and y position they were on before they collided. I have tried some things but non of them works. In my thread I have this code for now.
for(int i = 0; i < rectangles.size(); i++){
Rectangle rect = (Rectangle) rectangles.get(i);
x = rect.getXPos();
y = rect.getYPos();
checkRectCollisionAndMovement();
for(int j = i + 1; j < rectangles.size(); j++){
Rectangle rect2 = (Rectangle) rectangles.get(j);
Rectangle r1 = rect.getBounds();
Rectangle r2 = rect2.getBounds();
if(r1.intersects(r2)){
rect.setXPos(x);
rect.setYPos(y);
}
}
}
How would I make it so that it gets the x and y position before they colided and not the one they had while they were colliding?
This is the checkCollisionAndMovement method
public void checkRectCollisionAndMovement(){
for(int i = 0; i < rectangles.size(); i++){
Rectangle rect = (Rectangle) rectangles.get(i);
if(rect.getYPos() > 500){
rect.setYPos(rect.getYPos() - .1);
}
if(rect.getYPos() < 500){
rect.setYPos(rect.getYPos() + .1);
}
if(rect.getXPos() > 500){
rect.setXPos(rect.getXPos() - .1);
}
if(rect.getXPos() < 500){
rect.setXPos(rect.getXPos() + .1);
}
if(rect.isVisibe()){
rect.move();
}else{
rect.remove(i);
}
}
}
You can either store all previous x,y positions in a list and traceback one step when there is a collision or Store only last co-ordinates in temporary variables.
But as Duncan has mentioned I feel your new path should reflect along the axis orthogonal to the impact

Blocking light on a tiled level

I'm making a tiled(tiles size is 16px) level scrolling game in Java.
Right now I'm dealing with the lighting system.
I calculated the light gradient(as shown on the picture) with this code for each light(yellow blocks and tiles):
visMap = new int[level.getWidth() * level.getHeight()];
int lighted = 0;
for (int x = 0; x < level.getWidth(); x++) {
for (int y = 0; y < level.getHeight(); y++) {
double xd = (this.x >> 4) - x;
double yd = (this.y >> 4) - y;
double distance = Math.sqrt(xd * xd + yd * yd);
double p = power * 1.0;
double bright = p - distance;
visMap[x + y * level.getWidth()] = (int) (bright * power);
}
}
And now I'm trying to make the block somehow block the light(like in real life).
Is there a good method for this?
Thank's in advance,
Zaplik
The Picture: click
Spread light recursively. Decrease with each level of recursion the light intensity with the appropriated amount. Keep also track of the direction light is moving. Once you hit an obstacle, stop that branch of the recursion.

Categories