Coordinates not corresponding - java

I'm pretty new to Android and I'm really struggling trying to understand what is going on in my application.
I'm trying to build a small game in which a circle appears on the screen, in a random position and it disappears as soon as the user clicks on it. Then a new circle appears in another position.
The problem is that comparing the coordinates of the user's click, and the coordinates of the center of the circle, these seem to be totally different…
The problem seems to be in the circle coordinates, because if I try to force its position to the center of the view, it appears in a totally wrong position, at the right bottom of the view.
What am I doing wrong?
This is the code of the function drawing the circles in the view (which is as big as its parent).
public void drawDots(){
Paint paint = new Paint();
paint.setColor(Color.MAGENTA);
Bitmap bg = Bitmap.createBitmap(480, 800, Bitmap.Config.ARGB_8888);
View ll = (View) findViewById(R.id.circle);
ll.setBackground(new BitmapDrawable(bg));
centerX = rand.nextInt(ll.getWidth());
centerY = rand.nextInt(ll.getHeight());
Canvas canvas = new Canvas(bg);
canvas.drawCircle(centerX, centerY, radius, paint);
Log.i("Point center X :" + centerX, " Y " + centerY);
ll.setOnTouchListener(new View.OnTouchListener() {
int x = 0, y = 0;
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
x = (int) event.getX();
y = (int) event.getY();
Log.i("CLICK X: " + x, "click Y: " + y);
if((x < (centerX + radius) && x > (centerX - radius))) && ((y > centerY + radius) && (y < centerY - radius)) ){
Log.i("x ok: " + x + " y ok: " + y, "Counter: " + counter);
drawDots();
}else{
Log.i("x NOT ok " + x, " Circle area between: " + (centerX-radius) + " e " + (centerX + radius));
Log.i("Y NOT ok " + y, " Circle area between: " + (centerY-radius) + " e " + (centerY + radius));
}
}
return true;
}
});
}
And this is the layout. The textview and the button are needed to start a timer but they are removed from the layout as soon as the user clicks on the start button.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView
android:id="#+id/timerValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginBottom="37dp"
android:textSize="40sp"
android:textColor="#ffffff"
android:text="#string/timerVal" />
<Button
android:id="#+id/startButton"
android:layout_width="90dp"
android:layout_height="45dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="38dp"
android:text="#string/startButtonLabel" />
<View android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/circle"/>
Sorry for my bad explanation but I even dunno where the problem is.
EDIT I tried this solution and it actually seems to improve the situation but if i only consider the x-axis, for the y-axis there is any correspondence but in this way it seems the coordinates of the click are totally out of range... Circle drawn on canvas doesn't match the screen
even though i actually don't understand WHY it is needed

The problem is here:
centerX = rand.nextInt(ll.getWidth());
ll.getWidth() returns you 0 and rand.nextInt() won't work
when ll.getWidth() is 0.
so cannot call nextInt(0). Check out Random#nextInt().
to fix this make a check:
if(ll.getWidth() == 0)
centerX = 0;
else
centerX = rand.nextInt(ll.getWidth());
But I'm not certain what you are doing so hopefully you will find a better solution.
P.S - same you have to do with the other case, I still doubt what is the need of rand.nextInt(ll.getWidth());. (you may edit your question and make clear what you want to achieve)
as a newbie you code is nice enough to gain upvotes :)
~happycoding

I finally figured out the problem, which was here:
Bitmap bg = Bitmap.createBitmap(480, 800, Bitmap.Config.ARGB_8888);
with this call i was specifying a view of 480px of width and 800px of height, whereas my view is occupying the entire parent view (which is the screen).
This was a quite a newbie mistake, but i hope it could help someone else as i've been struggling for two days with it! :)

Related

custom seekbar with multi color

I am trying to create custom seek bar in android with multicolor. I tried below code
customseekbar.java
int proBarWidth = getWidth();
int proBarHeight = getHeight();
int thumboffset = getThumbOffset();
int lastproX = 0;
int proItemWidth, proItemRight;
for (int i = 0; i < mproItemsList.size(); i++) {
proItem proItem = mproItemsList.get(i);
Paint proPaint = new Paint();
proPaint.setColor(getResources().getColor(proItem.color));
proItemWidth = (int) (proItem.proItemPercentage
* proBarWidth / 100);
proItemRight = lastproX + proItemWidth;
// for last item give right of the pro item to width of the
// pro bar
if (i == mproItemsList.size() - 1
&& proItemRight != proBarWidth) {
proItemRight = proBarWidth;
}
Rect proRect = new Rect();
proRect.set(lastproX, thumboffset / 2, proItemRight,
proBarHeight - thumboffset / 2);
canvas.drawRect(proRect, proPaint);
lastproX = proItemRight;
}
super.onDraw(canvas);
view
<mypackage.customseekbar
android:id="#+id/customseekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="0"
android:progressDrawable="#android:color/transparent"
android:thumb="#drawable/seek_thumb_normal"
android:thumbOffset="12dp" />
I used this method in MainMenuActivity. It gives me result something like below. I referred this link https://azzits.wordpress.com/2013/11/17/customseekbar/
But I am expecting something like below
Is there any way to draw this vertical gapped lines? How can I draw this vertical lines?
Progress bar with divider is a good place to look as mentioned by #Nilesh Rathod. Rather than using canvas.drawRect() you can use canvas.drawRoundRect(); Short example:
for (int i = 0; i < NUM_SEGMENTS; i++) {
float loLevel = i / (float) NUM_SEGMENTS;
float hiLevel = (i + 1) / (float) NUM_SEGMENTS;
if (loLevel <= level && level <= hiLevel) {
float middle = mSegment.left + NUM_SEGMENTS * segmentWidth * (level - loLevel);
canvas.drawRoundRect(mSegment.left, mSegment.top, middle, mSegment.bottom, mPaint);
mPaint.setColor(mBackground);
canvas.drawRoundRect(middle, mSegment.top, mSegment.right, mSegment.bottom, mPaint);
} else {
canvas.drawRoundRect(mSegment, mPaint);
}
mSegment.offset(mSegment.width() + gapWidth, 0);
}
I give full credit to the code above to the creator of the aforementioned link and don't claim any of it as mine as I am just illustrating the change that should be made to reach the desired effect. Please let me know if you run into further issues.

Android ACTION_MOVE image set image scrolling bounds outside its parent

I implemented ACTION_MOVE for ImageView which is bigger then its parent (FrameLayout). Now I'm trying to add some code to stop movement (both drag and pinch zooming) when at least one of Image edges is inside its parent (so it won’t show background of a parent).
I used the code like in this question.
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) { //movement of first finger
matrix.set(savedMatrix);
float newX = event.getX() - start.x;
float newY = event.getY() - start.y;
if (view.getLeft() >= -392){
matrix.postTranslate(newX, newY);
}
}
else if (mode == ZOOM) { //pinch zooming
float[] f = new float[9];
float newDist = spacing(event);
if (newDist > 5f) {
matrix.set(savedMatrix);
scale = newDist / oldDist;
matrix.postScale(scale, scale, mid.x, mid.y);
}
matrix.getValues(f);
float scaleX = f[Matrix.MSCALE_X];
float scaleY = f[Matrix.MSCALE_Y];
if(scaleX <= MIN_ZOOM) {
matrix.postScale((MIN_ZOOM)/scaleX,
(MIN_ZOOM)/scaleY, mid.x, mid.y);
}
else if(scaleX >= MAX_ZOOM) {
matrix.postScale((MAX_ZOOM)/scaleX,
(MAX_ZOOM)/scaleY, mid.x, mid.y);
}
}
break;
I tried many things, and I know similar questions had been asked already but non of them fit my need so far.
My best guess was to add code below but it looks like mImageView.getLeft(), mImageView.getRight() etc returns parents edges not the images.
In onCreate():
DisplayMetrics displayMetrics =
getApplicationContext().getResources().getDisplayMetrics();
float screenWidth = displayMetrics.widthPixels;
float screenHeight = displayMetrics.heightPixels;
and in case MotionEvent.ACTION_MOVE
if (mImageView.getLeft() > 0 ||
mImageView.getRight() < screenWidth) {
matrix.postTranslate(0, newY);
break;
}
else if (mImageView.getTop() > 0 ||
mImageView.getBottom() < screenHeight) {
matrix.postTranslate(newX, 0);
break;
}
else {
matrix.postTranslate(newX, newY);
}
And this is my layout:
<RelativeLayout
android:id="#+id/imageViewContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/mag_background">
<TextView/>
<ImageView/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/imageViewHeadingLabel">
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/image"
android:scaleType="matrix"
android:layout_gravity="center_vertical|center_horizontal"
android:contentDescription="image to zoom"/>
</FrameLayout>
</RelativeLayout>
Thanks in advance for your help!
I found solution hire.
I reverse the checks so instead of not letting image to move outside layout I not letting image bounds to be move inside layout like this:
if (mode == DRAG) { //movement of first finger
matrix.set(savedMatrix);
matrix.getValues(matrixValues);
matrixX = matrixValues[2];
matrixY = matrixValues[5];
width = matrixValues[0] * (view.getDrawable().getIntrinsicWidth());
height = matrixValues[4] * (view.getDrawable().getIntrinsicHeight());
dx = event.getX() - start.x;
dy = event.getY() - start.y;
//if image will go inside left bound
if (matrixX + dx > 0){
dx = -matrixX;
}
//if image will go inside right bound
if(matrixX + dx + width < view.getWidth()){
dx = view.getWidth() - matrixX - width;
}
//if image will go inside top bound
if (matrixY + dy > 0){
dy = -matrixY;
}
//if image will go inside bottom bound
if(matrixY + dy + height < view.getHeight()){
dy = view.getHeight() - matrixY - height;
}
matrix.postTranslate(dx, dy);
}
However if you move zoomed image to the corner and then zoom out, it will show parent background until next touch event so problem is not fully solved.

Android property animations does not work when imageview's width uses dp units

I am creating a game, where there will be a lot of clickable ImageView(s), and one unclickable imageView, when the clickable ImageView is clicked, it should swap its position with the unclickable ImageView (in this example, its called imageView2).
Everything works fine when I am using px unit for my imageView(s). However, as you know using px units will resulted in different display on different devices. However, the property animations does not work when I use dp units. How do I get it working with dp units ??
MainActivity.java
public class MainActivity extends Activity implements View.OnClickListener {
ImageView imageView1, imageView2;
float x, x_9, y, y_9;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView1 = (ImageView) findViewById(R.id.imageView1);
imageView2 = (ImageView) findViewById(R.id.imageView2);
imageView1.setOnClickListener(this);
}
#Override
public void onClick(View v) {
// Get x position of clicked imageView
x = v.getX();
// Get x position of imageView2
x_9 = imageView2.getX();
// Get y position of clicked imageView
y = v.getY();
// Get y position of imageView2
y_9 = imageView2.getY();
// Check if imageViews are align with each other either horizontally or vertically
if((x == x_9 && y + 100 == y_9) || (x == x_9 && y - 100 == y_9) || (x + 100 == x_9 && y == y_9) || (x - 100 == x_9 && y == y_9)) {
// If they are aligned, swap their position with property animation
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("translationX", x_9);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("translationY", y_9);
PropertyValuesHolder pvhX9 = PropertyValuesHolder.ofFloat("translationX", x);
PropertyValuesHolder pvhY9 = PropertyValuesHolder.ofFloat("translationY", y);
ObjectAnimator blockAnim = ObjectAnimator.ofPropertyValuesHolder(v, pvhX, pvhY);
blockAnim.setDuration(500);
blockAnim.setRepeatCount(0);
blockAnim.start();
ObjectAnimator blockAnim2 = ObjectAnimator.ofPropertyValuesHolder(imageView2, pvhX9, pvhY9);
blockAnim2.setDuration(500);
blockAnim2.setRepeatCount(0);
blockAnim2.start();
}
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<RelativeLayout
android:id="#+id/relative"
android:background="#color/grey"
android:layout_width="400dp"
android:layout_height="400dp"
>
<ImageView
android:id="#+id/imageView1"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#drawable/smiley1"/>
<ImageView
android:id="#+id/imageView2"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#drawable/smiley2"
android:translationX="100dp"/>
</RelativeLayout>
</RelativeLayout>
How do I work around this problem ? All suggestions are greatly welcomed. Thank you.
As suggested by Nikola Milutinovic, I added GlobalLayoutListener like below
this.findViewById(R.id.relative).getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
x = v.getX();
x_9 = imageView2.getX();
y = v.getY();
y_9 = imageView2.getY();
}
});
I think the way to do it is to change your hard coded referece to the width and height by the actual value contained by the imageViews. In your if condition change 100 to getHeight() or getWidth();
int height = imageView1.getHeight();
int width = imageView1.getWidth();
if((x == x_9 && y + height == y_9) || (x == x_9 && y - height == y_9) ||
(x + width == x_9 && y == y_9) || (x - width == x_9 && y == y_9)){
}
This way you do not have a reference to px. The "100" value that your were using meant 100px. The real width or height for an hdpi device would of been something like 1.5*100 = 150px. By using getWidth() and getHeight(), you are using the actual value of px in your screen. I hope it is clear. You will need to modify your if condition for more than 2 imageViews, but the principle is the same.
Finally it is better to use AnimatorSet if you want your animations to be synchronized.
ArrayList <Animator> animations = new ArrayList<Animator>();
animations.add(ObjectAnimator.ofPropertyValuesHolder(v, pvhX, pvhY));
animations.add(ObjectAnimator.ofPropertyValuesHolder(imageView2, pvhX9, pvhY9));
AnimatorSet animatoreSet = new AnimatorSet();
animatorSet.setDuration(500);
animatorSet.setRepeatCount(0);
animatorSet.playTogether(animations);
animatorSet.start();
By doing this if you need to add listeners you just add them once.
See documentation for these two methods below and find which one suits you the most. container would be your root layout (this RelativeLayout at the top or this with id relative)
container.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
}
});
container.getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
#Override
public void onDraw() {
}
});
Here is the example of my implementation of this listener.
I do all sorts of stuff inside. Please take a look.
public class CustomOnGlobalLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener {
private Context context;
private View fragment;
private float x1;
private float y1;
private float x2;
private float y2;
public CustomOnGlobalLayoutListener(Context context, View view, float x1, float y1, float x2, float y2) {
this.context = context;
this.fragment = view;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
#Override
public void onGlobalLayout() {
fragment.setX(x1);
fragment.setY(y1);
removeOnGlobalLayoutListener();
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) fragment.getLayoutParams();
fragment.setLayoutParams(layoutParams);
fragment.setPivotX(0);
fragment.setPivotY(0);
fragment.setScaleX((x2 - x1) / fragment.getMeasuredWidth());
fragment.setScaleY((y2 - y1) / fragment.getMeasuredHeight());
fragment.setAlpha(0f);
PropertyValuesHolder pA = PropertyValuesHolder.ofFloat(View.ALPHA, 1f);
PropertyValuesHolder pX = PropertyValuesHolder.ofFloat(View.X, 0f);
PropertyValuesHolder pY = PropertyValuesHolder.ofFloat(View.Y, 0f);
PropertyValuesHolder pSx = PropertyValuesHolder.ofFloat(View.SCALE_X, 1);
PropertyValuesHolder pSy = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1);
final ObjectAnimator animator1 = ObjectAnimator.ofPropertyValuesHolder(fragment, pA, pX, pY, pSx, pSy);
animator1.setInterpolator(new AccelerateDecelerateInterpolator());
animator1.setDuration(200);
animator1.start();
}
private void removeOnGlobalLayoutListener() {
if (Build.VERSION.SDK_INT < 16) {
//noinspection deprecation
fragment.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
fragment.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
}
DO NOT FORGET TO REMOVE GLOBAL LAYOUT LISTENER;
If you have any problem implementing this, write and we will think something out :)
You can also check my github repo where I am actually using this to achieve opening fragment with viewpager from point of touch.
https://github.com/mrnmilutinovic/HumanityTestProject
Check ImagePagerFragment class to see it's usage.
This code is compilable, so you can also run and see that it works.

Java Slick2d - how to keep a shape allways inside a window?

I'm moving a circle across the window by dragging it with the mouse. I'm supposed to make it always inside the window.
So by the default, when you drag the circle in a way that your mouse exits the frame, half of the circle will disappear (because it exits the frame), and half of it won't. I need to make it visible whole all the time, even if your cursor exits the frame. Here's the code:
if(draggingcircle)
{
g.drawString("Dragging circle = " + draggingcircle, 50, 110);
circle.setCenterX( gc.getInput().getMouseX() );
circle.setCenterY( gc.getInput().getMouseY() );
}
whatever the circle is contained in, lets call id , you can keep it in the container with simple math if you know the radius or the diameter (i forget which)
so
if(draggingcircle)
{
g.drawString("Dragging circle = " + draggingcircle, 50, 110);
circle.setCenterX( gc.getInput().getMouseX() );
circle.setCenterY( gc.getInput().getMouseY() );
}
becomes
var width = $('#container').width();
var height = $('#container').height();
var radius = 2;
if(draggingcircle)
{
g.drawString("Dragging circle = " + draggingcircle, 50, 110);
if (gc.getInput().getMouseX() > radius && gc.getInput().getMouseX() < width - radius)
{
circle.setCenterX( gc.getInput().getMouseX() );
}
if (gc.getInput().getMouseY() > radius && gc.getInput().getMouseY() < height - radius)
{
circle.setCenterY( gc.getInput().getMouseY() );
}
}
Sorry for my poor syntax, I am not familiar with Slick2d, but something along these lines should work.

A fast collision detection between a circle and a sprite in pixel perfect

I've been thinking on some fast and brilliant pixel - perfect collision detection between a circle and any sprite. I need to get 2 points of collision to be able to calculate a normal vector out of them later. I managed to come up with some solution but the more scaling is done in my game, the more inaccurate and unprecise this collision is...It seems as if the code I posted below, was good and correct becouse I have been checking it already a few times and spent a few days reading it again and again... I also checked visually that the collision masks and areas of collision are calculated perfectly fine in the code below so the problem definitely doesn't lay there but in this method.
So I guess that the problem here is the loss of data in floating point arithmetic unless somebody finds a flaw in this method?
If however the problem is really with the float loss of data, what other solution would you recommend to find 2 points of collision between circle and any other sprite in pixel perfect? I really liked my solution becouse it was relatively fast
int xOffset1 = (int)colRectLeft; // left boundary of the collision area for the first sprite
int xOffset2 = (int)colCircleLeft; // left boundary of the collision area for the circle sprite
int yOffset1 = (int)colRectBottom; // bottom boundary of the collision area for the first sprite
int yOffset2 = (int)colCircleBottom; // bottom boundary of the collision area for the circle sprite
int width = (int)(colCircleRight - colCircleLeft); //width of the collision area - same for both sprites
int height = (int)(colCircleTop - colCircleBottom); // height of the collision area same for both sprites
// Pixel-perfect COLLISION DETECTION between circle and a sprite
// my custom vector classes - nothing special
Math2D.Vector_2 colRightPoint = new Math2D.Vector_2(-1, -1); // The right point of collision lying on the circle's circumference
Math2D.Vector_2 colLeftPoint = new Math2D.Vector_2(-1, -1); // the left point of collision lying on the circle's circumference
boolean colRightFound = false;
boolean colLeftFound = false;
// I'm going through y in the circle's area of collision
for (float y = yOffset2; y < yOffset2 + height; y += 1)
{
// from equation: (x-Sx)^2 + (y-Sy)^2 = r^2
// x1/2 = (+-)sqrt(r^2 - (y - Sy)^2) + Sx
//(Sx, Sy) is (circle's radius, circle's radius) becouse I want the points on the circle's circumference to have positive coordinates
float x1 = (float) (Math.sqrt(radius*radius - (y - radius)*(y - radius)) + radius); // the right pixel on the circumference
float x2 = (float) (-x1 + 2*radius); // the left pixel on the circumference
//first I check if the calculated x is inside of the previously calculated area of collision for both circle's area and a sprite's area
if (x1 >= xOffset2 &&
x1 <= xOffset2 + width &&
xOffset1 + x1 - xOffset2 < rectFrameW &&
yOffset1 + (int)y-yOffset2 < rectFrameH &&
yOffset1 + (int)y-yOffset2 > 0 &&
xOffset1 + x1 - xOffset2 > 0)
{
//I don't have to check if the point on the circle's circumference is opaque becouse it's always so just check if the same point translated to sprite's area of collision is opaque
boolean opaqueRectPixel = go.gameData.images.get(go.pic_nr)
.collision_mask[(int)((yOffset1 + (int)y-yOffset2)*rectFrameW +
(xOffset1 + x1 - xOffset2))];
if(opaqueRectPixel)
{
if(!colRightFound)
{
colRightPoint.x = (xOffset1 + x1 - xOffset2);
colRightPoint.y = (yOffset1 + (int)y - yOffset2);
colRightFound = true;
}
else if(!colLeftFound)
{
colLeftPoint.x = (xOffset1 + x1 - xOffset2);
colLeftPoint.y = (yOffset1 + (int)y - yOffset2);
}
}
}
//the same logic for the left point on the circle's circumference
if (x2 >= xOffset2 &&
x2 <= xOffset2 + width &&
xOffset1 + x2 - xOffset2 < rectFrameW &&
yOffset1 + (int)y-yOffset2 < rectFrameH &&
yOffset1 + (int)y-yOffset2 > 0 &&
xOffset1 + x2 - xOffset2 > 0)
{
boolean opaqueRectPixel = go.gameData.images.get(go.pic_nr)
.collision_mask[(int)((yOffset1 + (int)y-yOffset2)*rectFrameW +
(xOffset1 + x2 - xOffset2))];
if(opaqueRectPixel)
{
if(!colLeftFound)
{
colLeftPoint.x = (xOffset1 + x2 - xOffset2);
colLeftPoint.y = (yOffset1 + (int)y - yOffset2);
colLeftFound = true;
}
else if(!colRightFound)
{
colRightPoint.x = (xOffset1 + x2 - xOffset2);
colRightPoint.y = (yOffset1 + (int)y - yOffset2);
}
}
}
// if both points are already found, finish
if(colLeftFound && colRightFound)
break;
}
edit: Actually, what I'm doing in this method is finding points of intersection between circle and a sprite
edit: Ok, I'm uploading images to describe my algorithm a bit better. I really tried my best to explain it but if there's still something missing, let me know please!
Also I would accept any other good solutions to find intersection points between a circle and any sprite in pixel perfect, if you don't want to check my code :(... Eh, I'm always having problems with collisions...
If you absolutely want (or need) pixel perfect, your solution looks good.
don't forget to first make a rectangle-to-rectangle collision before testing a pixel perfect detection, to avoid unneeded processings.
If you want another accurate method which maybe more efficient, look for Separating Axis Theorem.
You can find more information about it here :
http://rocketmandevelopment.com/blog/separation-of-axis-theorem-for-collision-detection/
and here :
http://www.metanetsoftware.com/technique/tutorialA.html
The last one have nice interactive explanation and demonstration. Enjoy :)
...as I was not able to show the raster in the comments:
I did not mentally parse your code, however from the image I see that you try to detect borderline collisions. Putting round or diagonal (border)lines into a raster may cause occasions, where two crossing lines do not overlay each other - like this:
1 2
2 1
whereby 1 would be line 1 and 2 would be line 2.
However I still like the idea of checking border lines combined with rectangle pre-checks. If you would render an array of raster proved-closed line coordinates by sprites you could check them against each other. This could also be enriched by border line segmenting (such as North, East, West and South or a bit more fine grain - I guess there is an optimum). A diagonal proved-closed line in the check data set must represent something like this:
x _
x x
whereby the x represent the pixels of your line and the _ is an empty raster seat.

Categories

Resources