• Create Account

# Map Clipping

12 replies to this topic

### #1nerozero  Members   -  Reputation: 104

Like
0Likes
Like

Posted 08 October 2013 - 05:46 PM

Hi Guys,

I have a sprite that moves at a velocity of 1,1 across a background image. I want to draw the background image with the sprite always at the centre as the background is about 2000x2000. My problem is as the sprite moves the background repositions but its as if the sprite is moving at 2,2 and the background is moving at 1,1. So the sprite gradually moves off the screen even though the sprite is moving at 1,1 and the background surely cant be moving slower than that?

To update the velocity of sprite:

		Point car = new Point(
((GameBoard) findViewById(R.id.the_canvas)).getCarX(),
((GameBoard) findViewById(R.id.the_canvas)).getCarY());
car.x = car.x + carVelocity.x;
car.y = car.y + carVelocity.y;
((GameBoard) findViewById(R.id.the_canvas))
.setCarLocation(car.x, car.y);


Definition of velocity:

		carVelocity = new Point(1, 1);


Drawing the map around the car:

	public void drawMap(Canvas canvas) {

if (car.x > 0) {

int x = car.x - getWidth() / 2;
int y = car.y - getHeight() / 2;

Bitmap clipArea = Bitmap.createBitmap(map, x, y, getWidth(),
getHeight());
canvas.drawBitmap(clipArea, 0, 0, null);
}
}


So i can't see why the car would move off the screen as it looks to me as the background should always draw with the car in the middle of the screen. I have put logging on both and they both increase by 1 on the X and Y each time.

Any help would be appreciated!

### #2nerozero  Members   -  Reputation: 104

Like
0Likes
Like

Posted 09 October 2013 - 09:10 AM

Noone?

### #3Paragon123  Members   -  Reputation: 208

Like
0Likes
Like

Posted 09 October 2013 - 10:30 AM

I think you can solve the problem by replacing your cars displacement update code with

car.x = car.x + carVelocity.x;
car.y = car.y + carVelocity.y;

It looks like findViewById and setCarLocation is unnecessary because i *think* those values are referring to the screen location, which in your case is going to be constant.

I think the application is getting the cars Draw location (pixel X, pixel Y) confused with the cars world position (carX, carY).

Edited by Paragon123, 09 October 2013 - 10:31 AM.

### #4nerozero  Members   -  Reputation: 104

Like
0Likes
Like

Posted 09 October 2013 - 11:03 AM

Hi Paragon,

Thanks for the response. I have to use .setLocation as I have a custom view that holds the canvas and so I am passing the car location to this so it can be drawn.

Here is my cars draw method:

if (car.x > 0) {
m.reset();
m.postTranslate((float) (getWidth() / 2), (float) (getHeight() / 2));
m.postRotate(carRotation,
(float) (getWidth()/2 + carBounds.width() / 2.0),
(float) (getHeight()/2 + carBounds.height() / 2.0));
canvas.drawBitmap(carBitmap, m, null);
}


The above works but once I reach the end of the bitmap the car stay in the middle and i cant reach the true edge beacuse of getWidth()/2 and getHeight()/2. If i change this to car.x and car.y which is what it should be then the car gradually dissapears. The .setLocation method updates the cars coords car.x and car.y in my custom view ( the velocity calculations are seperate from the drawing).

### #5Paragon123  Members   -  Reputation: 208

Like
0Likes
Like

Posted 09 October 2013 - 12:00 PM

Sorry a bit confused. You have a car sprite, and you have a background image. Ignoring the specifics of how it is implemented there is two ways to have it look like the car is driving around.

The first is to move the car and keep the image still, this means that the car can move toward the edges of the drawing area, but will go off the screen at some point.

The second is to move the image and keep the car still, this means the car is always at the center of the screen but at some point you'll reach the edge of the background and you'll end up driving on a point where there is no background.

In the original post, the problem sounded like you were moving both the background and the car... thus moving the car 1 to the left and moving the image 1 to the right, causing it to seem like the car was moving left 2 instead of 1.

There is a Third method, but it is more a combination of the two. In the third method, as long as none of the background edges line up with the drawing area edges move the background, but if the a background edge does line up with a drawing edge, instead move the car. This sounds like what you are trying to accomplish in your most recent post.

Assume the drawing area is 100 x 100, and the background is 500 x 500 .

As long as 50<car.x<450 and 50<car.y<450 we can move the background and leave the car in the middle of the drawing area. As it turns out, there are 9 cases we must consider.

1) car.x<50 and car.y<50

2) 50<car.x<450 and car.y<50

3) 450<car.x and car.y<50

4) car.x<50 and 50<car.y<450

5) 50<car.x<450 and 50<car.y<450

6) 450<car.x and 50<car.y<450

7) car.x<50 and 450<car.y

8) 50<car.x<450 and 450<car.y

9) 450<car.x and 450<car.y

Given a car position car.x, car.y we need to first translate it to drawing positions with a function like:

: x<50 = x

px(x)=  : 50<x<450=50

: 450<x=x-400

and

:  x<50=x

py(x)= : 50<x<450 = 50

: 450<x=x-400

so P(car)=(px(car.x), py(car.y))

px and py are separate functions but in the case of a square viewing area they are equivalent, in a rectangular viewing area they would be different.

Then we need to find the top left coord of the background clipping area. Cx and Cy

x<50=0

Cx(x) = 50<x<450=x-50

450<x= 400

x<50=0

Cy(x)= 50<x<450 = x-50

450<x = 400

And the clipping cord ends up being
C(car)=(Cx(car.x),Cy(car.y))

Car.x and Car.y still needs to be constrained to 0<Car.x<500 and 0<Car.y<500

In all the above, you can replace
50 by either CanvasWidth/2 or CanvasHeight/2 depending on working with x or y
450 by BackgroundWidth-CanvasWidth/2 or Backgroundheight-CanvasHeight/2  depending on working with x or y
400 by BackgroundWidht-CanvasWidth or BackgroundHeight-CanvasHeight depending on working with x or y

Edited by Paragon123, 09 October 2013 - 12:09 PM.

### #6nerozero  Members   -  Reputation: 104

Like
0Likes
Like

Posted 10 October 2013 - 03:40 AM

Sorry a bit confused. You have a car sprite, and you have a background image. Ignoring the specifics of how it is implemented there is two ways to have it look like the car is driving around.

The first is to move the car and keep the image still, this means that the car can move toward the edges of the drawing area, but will go off the screen at some point.

The second is to move the image and keep the car still, this means the car is always at the center of the screen but at some point you'll reach the edge of the background and you'll end up driving on a point where there is no background.

In the original post, the problem sounded like you were moving both the background and the car... thus moving the car 1 to the left and moving the image 1 to the right, causing it to seem like the car was moving left 2 instead of 1.

There is a Third method, but it is more a combination of the two. In the third method, as long as none of the background edges line up with the drawing area edges move the background, but if the a background edge does line up with a drawing edge, instead move the car. This sounds like what you are trying to accomplish in your most recent post.

Assume the drawing area is 100 x 100, and the background is 500 x 500 .

As long as 50<car.x<450 and 50<car.y<450 we can move the background and leave the car in the middle of the drawing area. As it turns out, there are 9 cases we must consider.

1) car.x<50 and car.y<50

2) 50<car.x<450 and car.y<50

3) 450<car.x and car.y<50

4) car.x<50 and 50<car.y<450

5) 50<car.x<450 and 50<car.y<450

6) 450<car.x and 50<car.y<450

7) car.x<50 and 450<car.y

8) 50<car.x<450 and 450<car.y

9) 450<car.x and 450<car.y

Given a car position car.x, car.y we need to first translate it to drawing positions with a function like:

: x<50 = x

px(x)=  : 50<x<450=50

: 450<x=x-400

and

:  x<50=x

py(x)= : 50<x<450 = 50

: 450<x=x-400

so P(car)=(px(car.x), py(car.y))

px and py are separate functions but in the case of a square viewing area they are equivalent, in a rectangular viewing area they would be different.

Then we need to find the top left coord of the background clipping area. Cx and Cy

x<50=0

Cx(x) = 50<x<450=x-50

450<x= 400

x<50=0

Cy(x)= 50<x<450 = x-50

450<x = 400

And the clipping cord ends up being
C(car)=(Cx(car.x),Cy(car.y))

Car.x and Car.y still needs to be constrained to 0<Car.x<500 and 0<Car.y<500

In all the above, you can replace
50 by either CanvasWidth/2 or CanvasHeight/2 depending on working with x or y
450 by BackgroundWidth-CanvasWidth/2 or Backgroundheight-CanvasHeight/2  depending on working with x or y
400 by BackgroundWidht-CanvasWidth or BackgroundHeight-CanvasHeight depending on working with x or y

Hi,

I see what you mean and I think the above will work but is this always how this is implemented? It seems very complicated I assumed I could just draw the background around the cars location which is what I was trying to achieve.

So the car moves in a direction and then I clip the background at car.x-getWidth()/2 and car.y-getHeight()/2 and I thought this should keep the camera moving along with the car but this doesn't work? Am I missing something or is the way you said above the only way to achieve this?

### #7nerozero  Members   -  Reputation: 104

Like
0Likes
Like

Posted 10 October 2013 - 03:41 AM

I think I am seeing what you mean though, if the car is in the corner of the background then drawing around the car wouldn't work as there isn't anymore background to draw. I guess your way is the way and I was oversimplifying

### #8nerozero  Members   -  Reputation: 104

Like
0Likes
Like

Posted 10 October 2013 - 03:57 AM

Or is the proper way to follow the car with the camera until it reaches one of the corner zones and then just draw the background corner area. This way seems the 'real' way to me but then I have the original problem.

I will give your third method a try though! thanks

Edited by nerozero, 10 October 2013 - 04:01 AM.

### #9markr  Crossbones+   -  Reputation: 1608

Like
0Likes
Like

Posted 10 October 2013 - 04:40 AM

I think fundamentally the problem is that you need to move the viewport, not the world.

You need to be thinking about everything internally in world-space coordinates, and only convert to screen-coordinates just before rendering. Doing anything else will cause you to lose your sanity.

You need to independently maintain the location of the viewport and the car, even if one is derived from the other.

http://marksverbiage.blogspot.co.uk/2012/04/move-viewport-not-world.html

### #10nerozero  Members   -  Reputation: 104

Like
0Likes
Like

Posted 10 October 2013 - 04:56 AM

I think fundamentally the problem is that you need to move the viewport, not the world.

You need to be thinking about everything internally in world-space coordinates, and only convert to screen-coordinates just before rendering. Doing anything else will cause you to lose your sanity.

You need to independently maintain the location of the viewport and the car, even if one is derived from the other.

http://marksverbiage.blogspot.co.uk/2012/04/move-viewport-not-world.html

Hi Markr,

I do have the car in world-space coordinates this being car.x and car.y. I then clip the background image at car.x-getWidth()/2 and car.y-getHeight()/2. So I think I am doing it right, however when I draw the car at car.x and car.y the car will gradually move off the screen when it moves even though the background is being drawn like I just said. This is what I am having trouble with. i now see why it doesn't work as the velocity is moving the car across the view and the bitmap I guess but I can't figure away around this unless i draw the car at getWidth()/2 and getHeight()/2 and then check for when it reaches the corners as Paragon said.

### #11nerozero  Members   -  Reputation: 104

Like
0Likes
Like

Posted 10 October 2013 - 05:33 AM

I have figured the problem now. When near the edge of the screen car.x == 1560! So when I try to draw at car.x this doesn't exist as the max view is 800. So I need to translate between world coordinates and the screen coordinates, I wasn't doing this and so the car was gradually moving off the screen and dissapeared when car.x > 800. Any ideas how to translate between world coordinates and the screen view?

For example when car.x ==1560 its should be drawn on the screen at 800 as this is the maxX on the physical screen?

Edited by nerozero, 10 October 2013 - 06:16 AM.

### #12Paragon123  Members   -  Reputation: 208

Like
0Likes
Like

Posted 10 October 2013 - 07:22 AM

If you think it is to complicated to switch to moving the car instead of the background at the edges, one trick that is commonly used is to make the background a drawing area width and height larger than neccessary and put a boundary half a screen from the edges.  If you have a 100x100 drawing area and you have a driving area of 500x500, you would make a background that is 600x600 and put a 50 pixel wide swath of water around the edge. Using this method, the car would be constrained to 50< x < 550. Now you can keep the car in the center of the drawing area no matter where they are in the allowable driving area and there will also still be a background image covering the entire drawing area.

### #13nerozero  Members   -  Reputation: 104

Like
0Likes
Like

Posted 10 October 2013 - 11:57 AM

If you think it is to complicated to switch to moving the car instead of the background at the edges, one trick that is commonly used is to make the background a drawing area width and height larger than neccessary and put a boundary half a screen from the edges.  If you have a 100x100 drawing area and you have a driving area of 500x500, you would make a background that is 600x600 and put a 50 pixel wide swath of water around the edge. Using this method, the car would be constrained to 50< x < 550. Now you can keep the car in the center of the drawing area no matter where they are in the allowable driving area and there will also still be a background image covering the entire drawing area.

Hi,

I did it how you said originally above took me a while lol 9 different ways of drawing and also had to account for the car rotation but all working now! thanks

PARTNERS