Hey i am making a game that you are a spaceship and enemys are falling on you so far i have made the spaceship shoot and the
enemy falling fron the top of the screen (i have already made that if the bullet hits the enemy you get points)
but i have one problem that im stuck on for 2 days already the problem is to detect spaceship and enemy hit (they hit each other)
when they hitting each other it works but also when they far away from each other..
the code of the hit check is
if(invaders.getx0()-(iwidth/2)>=this.x-(pwidth/2)&&invaders.getx0()+iwidth<=this.x+pwidth&&invaders.gety0()+iheight>this.y&&invaders.gety0()<=this.y) {
invaders.setbitmap(1);
}
it checks if enemy 0 hitted the spaceship
iwidth is the enemy bitmap width
iheight is enemy bitmap height
pwidth is spaceship bitmap width
pheight is spaceship bitmap height
this.x and this.y is spaceship x and y
invaders.getx0 and invaders.gety0 is the enemy x and y
and invaders.setbitmap() is to set the life
please help me thanks
You can use Rect to detect intersections. For example you can describe the location and size of the objects on screen with Rect like this:
Rect rect1 = new Rect(0, 0, 100, 10);
Rect rect2 = new Rect(20, 0, 10, 10);
And when you want to check if they intersect you just call intersect:
if(rect1.intersect(rect2)) {
// Rectangles intersect
} else {
// Rectangles don't intersect
}
Related
I am developing an application for technical drawing and I need to add a few tools to draw lines, circles, rectangles and corners. Now I can draw lines and free hand drawing but I cannot draw circles, rectangles and corners. I found in lot of websites how to draw it but static, I mean, draw the shape in the position you pre-set or the position where you touch but I need to know how to draw, for example, a circle in the position I touch and make it bigger than I separate my fingers. I hope you understand what I mean.
You can have two variables x and y, then every time you touch the screen set x and y to that value, while drawing draw the circle with coordinates x and y.
If you are drawing and you just want to keep a painted circle, you can paint the circle and add it inside your canvas on x and y, then the next time you touch the screen a new circle will be painted on x and y and the old one will remain painted.
Are you using Canvas ? if so you can find out how to do this here (Canvas documentation) and here (Bitmap documentation). Depending on your situation you can create a new Bitmap and assign it to Canvas then draw on the Canvasand inside your bitmap you will have your desired circles and other shapes, on the next drawing frame, draw new shapes and the changes will remain.
Edit: In order to have dynamic radius follow this logic, when you touch the screen, set x and y to that point (the center of the circle), while moving the finger on the screen, calculate the radius comparing to x and y, when lifting your finger apply the drawing on the bitmap as told above.
Some code:
public boolean onTouchEvent(MotionEvent e)
{
switch (e.getAction())
{
case MotionEvent.ACTION_DOWN:
x = (int) event.getX();
y = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
//If I'm not wrong this is how to calculate radius,
//I'm at work and can't test this now, you can use your way
int distanceX = (int) event.getX() -x;
int distanceY = (int) event.getY() -y;
radius = sqrt(distanceX *distanceX + distanceY *distanceY);
break;
case MotionEvent.ACTION_UP:
//Draw circle inside your bitmap here
//This is like a flag to notify the program that no new shape is being drawn
x = -1;
break;
}
public void draw(Canvas canvas)
{
canvas.drawBitmap(myBitmap, 0, 0, null);
//A new shape is being drawn
if (x != -1)
//In here you place a switch to decide which shape you are drawing
//for this example i assume circle
canvas.drawCircle(radius, x, y, paint);
}
When you are lifting your finger the new circle should be painted on your bitmap so you don't have to add extra code for each new circle.
Edit2: I will add more code with the Bitmap and Canvas method i described.
Bitmap myBitmap;
Canvas myCanvas;
//Constructor
public myActivity(Bundle bundle) //or whatever your constructor is
{
myBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
myCanvas = new Canvas(myBitmap);
}
Now anything you draw on "myCanvas" will be applied to "myBitmap", when ACTION_UP activates draw circle on "myCanvas" which is drawn on the draw function.
case MotionEvent.ACTION_UP:
myCanvas.drawCircle(radius, x, y, paint);
x = -1;
break;
I have an Activity in which the user touches the eye positions on a picture, and this is supposed to draw a little white circle over each. I have a working bit of code that, using the Android FaceDetector tools, finds the eye positions and facial midpoint and draws a rectangle. The drawing part of that code, for reference, is this:
private void drawRectangles(){
Canvas canvas = new Canvas(mBitmap);
Paint paint = new Paint();
paint.setStrokeWidth(2);
paint.setColor(Color.BLUE);
paint.setStyle(Style.STROKE);
for (int i=0; i < faceFrames.length; i++) {
RectF r = faceFrames[i];
if (r != null){
canvas.drawRect(r, paint);
Log.d(TAG, "Drew rectangle");
}
}
mImageView.setImageResource(0);
mImageView.setImageBitmap(mBitmap);
mImageView.draw(canvas);
}
That part's fine. I figured, as a method that is called from onTouchEvent, that I could use the following to draw a circle:
private void makeDrawableLayer(int x, int y, int touchCount){
if (touchCount == 1){
Bitmap eyeOneBmp = Bitmap.createBitmap(mBitmap);
Canvas c1 = new Canvas(eyeOneBmp);
c1.drawCircle(x, y, 5, eyePaint);
mImageView.setImageResource(0);
mImageView.setImageBitmap(eyeOneBmp);
mImageView.draw(c1);
}
}
Here are screen shots showing the result of each code snippet. The first picture is the rectangle drawn on the face. The second picture shows the very strange result I get when I attempt to draw using the second code snippet. Note, however, that I had specified x and y as 10, 10 for the circle's position when drawing the second output. It's the same thing when I give it the passed-in eye position coordinates, just with the pixelated circle coming from wherever the eye is.
Does anyone have any idea what the heck is going on with this behavior?
Thanks so much.
So I found that you can basically only draw one time to the canvas before needing to make a class that extends View to start calling methods from. What I ended up needing to do was: customView.prepareCircle(), customView.invalidate(), and then parentView.addView(customView). And actually, I could only prepare, invalidate, and re-add the modified custom view to the canvas once before having to make any subsequent calls from a Runnable on the UI thread. I am not under the impression this is an ideal way to do it (certainly doesn't feel elegant), but it is giving me the results I want:
I'm performing a very small test to debug something larger, and am having trouble figuring out what's causing this issue.
I have an ImageView, a Canvas and a Bitmap. I initialize the ImageView and set it to the Bitmap, and then set the Canvas to the bitmap, as such:
_image.setImageBitmap(bitmap);
Canvas canvas = new Canvas(bitmap);
I then attach an onTouchListener to _image and listen for MotionEvent.ACTION_UP to be detected. At that point I draw a Rect on the Canvas, as such:
Rect rect = new Rect((int)event.getX(),event.getY(),event.getX()+20,event.getY()+20);
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawRect(rect,paint);
I've tried this with bitmap images of different sizes, to smaller than the full display, to very nearly the exact size, to larger, and I can never get the Rect to draw right where my finger touches the screen. I've tried different conversions on getX(), attempting to convert to dp, from dp, used getRawX/Y() instead; basically a bunch of different solutions, none of which have worked. I've tried getting the ratio of the bitmap's size to the screen size and multiplying/dividing by that; nothing has been able to solve this very simple issue.
Quite possibly I've tried the right approach at some point and simply implemented it incorrectly. I'd really appreciate some advice on what's causing the Rect to draw where it is, what conversion is needed to get it to draw right where the touch occurs, and why. The 'why' is because I want to learn from this.
Edit: This is an approximation of what happens. The red rectangle is where the actual touch occurs, and the blue is where it is drawn. It scales the further from X=Y=0 you get. Also, I just noticed that it also scales depending on the width and height of the image you're using.
So, I believe I've figured out the math which allows me to transform the onTouch coordinates onto the Canvas.
The reason I really wanted to go this route (as opposed to a custom subclass for ImageView) is because I'm not really that interested in the drawing of the rectangles: I'm more interested in accurately mapping onTouch coordinates onto specific OCRed text strings in the bitmap. The reason I was performing this exercise was to figure out why the touches weren't being attributed to the correct lines of text, and I was using drawn Rects to estimate where the touches were being recorded.
So, on to the math, which turned out to be a lot simpler than I'd feared:
int x1 = (int)(event.getX() * ((float) canvas.getWidth() / _image.getRight()));
int y1 = (int)(event.getY() * ((float) canvas.getHeight() / _image.getBottom()));
I multiply the onTouch coordinates by the ratio of the Canvas's dimensions to the ImageView's dimensions, which I cast to a float. Painting this as follows:
rect = new Rect(x1-10,y1-10,x1+10,y1+10);
//I took the advice about centering the Rect around the touch for clarity
paint = new Paint();
paint.setColor(Color.RED);
canvas.drawRect(rect,paint);
And the Rect is exactly where the touch was, regardless of bitmap size.
I found it interesting that it didn't cause any problems that I had called
_image.setAdjustViewBounds(true);
earlier in my program, which I did in order to remove some padding from the bitmap (which was showing up for some reason, possible due to the scaling). Also interesting is the fact that the ImageView is contained in a ScrollLayout, but even if the image is large enough to scroll though, it doesn't seem to need to take the scroll displacement into account.
Thanks to kcoppock for taking the time to help me out, and to the other user (whose comment was deleted when he realized he had misunderstood me) for taking the time as well.
I'd imagine your actual Bitmap is larger than the View and is scaled down. Since you're drawing in the coordinates of your bitmap, and that bitmap is being scaled down, the location will also be scaled down to match.
What you more likely want to do is make a subclass of ImageView, and then draw the Rect in onDraw() based on the location received in onTouchEvent(). Alternatively, you could do some math to figure out how much the bitmap is being scaled down relative to the view size, and scale up your coordinates by the inverse. A quick implementation of this touchable ImageView would be something like this:
public class DrawableImageView extends ImageView {
private final int mRectSize;
private final Paint mPaint;
private final Rect mRect = new Rect();
public DrawableImageView(Context context) {
super(context);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.RED);
mRectSize = (int) (getResources().getDisplayMetrics().density * 20);
}
// Other constructors omitted for brevity
#Override public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
final int x = (int) event.getX();
final int y = (int) event.getY();
mRect.set(x, y, x + mRectSize, y + mRectSize);
mRect.offset(-(mRectSize / 2), -(mRectSize / 2));
invalidate();
return true;
} else {
return super.onTouchEvent(event);
}
}
#Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(mRect, mPaint);
}
}
I have been battling with trying to draw a bitmap and then highlighting a region on it with a rectangle. Originally, I was drawing a bitmap with alpha black in paint to make image darker and then on top drawing original bitmap in a region creating effect of highlight. I discovered that largest slowdown was because of alpha in Paint. So I have reworked the code and ended up with following in my draw thread:
private synchronized void drawSquare(int xStart, int yStart, int xEnd, int yEnd) {
Canvas c = holder.lockCanvas();
if(c != null) {
// Draw the background picture on top with some changed alpha channel to blend
Paint paint = new Paint();
paint.setAntiAlias(true);
if(bg != null && cWidth > 0 && cHeight > 0) {
c.clipRect(xStart, yStart, xEnd, yEnd, Region.Op.DIFFERENCE);
c.drawBitmap(bg, gTransform, blackSqr); // Draw derker background
c.clipRect(xStart, yStart, xEnd, yEnd, Region.Op.REPLACE);
c.drawBitmap(bg, gTransform, paint); ///draw original in selection
c.clipRect(0, 0, cWidth, cHeight,Region.Op.REPLACE);
}
Matrix RTcorner = new Matrix();
RTcorner.setRotate(90);
RTcorner.postTranslate(xEnd + 13, yStart - 13);
Matrix RBcorner = new Matrix();
RBcorner.setRotate(180);
RBcorner.postTranslate(xEnd + 13, yEnd + 13);
Matrix LBcorner = new Matrix();
LBcorner.setRotate(270);
LBcorner.postTranslate(xStart - 13, yEnd + 13);
// Draw the fancy bounding box
c.drawRect(xStart, yStart, xEnd, yEnd, linePaintB);
// Draw corners for the fancy box
c.drawBitmap(corner, xStart - 13, yStart - 13, new Paint());
c.drawBitmap(corner, RBcorner, new Paint());
c.drawBitmap(corner, LBcorner, new Paint());
c.drawBitmap(corner, RTcorner, new Paint());
}
holder.unlockCanvasAndPost(c);
}
So this clips out my selection area, I draw with paint that has this code to make it darker.
blackSqr.setColorFilter(new LightingColorFilter(Color.rgb(100,100,100),0));
And in the area inside the clip I draw my original bitmap. It works. But I am not happy with response time. After profiling Bitmap is what takes the longest. I have scaled the bitmap to the size of the screen already so it's drawing 300x800-ish image. The biggest resource hog seems to be the Lighting effect. Because when I turn it off I get decent response time.
So I was wondering if I have missed anything to improve how quickly bitmap is drawn, maybe caching? Or am I just stuck with this because I want darker image and actually should rethink the "highlighting/selection" altogether? Why is is so expensive to draw a bitmap with alpha colour in 2D image?
if I understand what you want, you want a rectangle (with rounded corners) to highlight a part from another image.
if it is that, then I would use an image with the square wit draw9patch and use it as a floating view over the image view
RelativeLaoyut (Image container)
+- ImageView (your actual image)
+- view (it has the square as a background, and you only have to move it to the area you want to highlight)
I'm sorry, I'm not good explaining myself.
For anyone that is interested, perhaps facing similar problem. This solution applies to my particular situation, but I have a separate background bitmap with darkened pixels manually set using:
for(int i = 0; i < cWidth; i++){
for(int j = 0; j < cHeight; j++){
int c = bg2.getPixel(i, j);
float mult = 0.15f;
int r = (int) (Color.red(c) * mult);
int g = (int) (Color.green(c) * mult);
int b = (int) (Color.blue(c) * mult);
bg2.setPixel(i, j, Color.rgb(r, g, b));
}
}
Then use the bg2 to draw main part and the original (not darkened) for the clip rectangle of the selection. There is a bit of overhead for creating and maintaining the second bitmap but the draw speed and response time is quick and smooth in comparison to bitmaps with alpha.
I have this sprite rotating algorithm (its poorly named and just used for testing). It is so close, sprites drawn with it do rotate. Everyframe I can add +5 degrees to it and see my nice little sprite rotate around. The problem is, the other stuff drawn to the canvas now flickers. If I don't do the rotation the regular drawn sprites work great. I think I am close but I just don't know what piece I am missing. Below is my two "Draw_Sprite" methods, one just draws the previously resource loaded bitmap to the canvas passed in. The other one, does some rotation the best I know how to rotate the sprite by so x many degrees..and then draw it. If I have a nice game loop that draws several objects, one type is the rotated kind. Then the non-rotated sprites flicker and yet the rotated sprite never does. Though if I draw the non-rotated sprites first, all is well, but then the Z-Ordering could be messed up (sprites on top of UI elements etc)... The method definitions:
/*************************************************
* rotated sprite, ignore the whatever, its for ease of use and testing to have this argument list
* #param c canvas to draw on.
* #param whatever ignore
* #param rot degrees to rotate
* #return
*/
public int Draw_Sprite(Canvas c, int whatever, int rot) {
//rotating sprite
Rect src = new Rect(0, 0, width, height);
Rect dst = new Rect(x, y, x + width, y + height);
Matrix orig = c.getMatrix();
mMatrix = orig;
orig.setTranslate(0, 0);
orig.postRotate(rot, x+width/2, y+height/2);
c.setMatrix(orig);
c.drawBitmap(images[curr_frame], src, dst, null);
c.setMatrix(mMatrix); //set it back so all things afterwards are displayed correctly.
isScaled=false;
return 1;
}
/********************************************************
* draw a regular sprite to canvas c
* #param c
* #return
*/
public int Draw_Sprite(Canvas c) {
Rect src = new Rect(0, 0, width, height);
Rect dst = new Rect(x, y, x + width, y + height);
c.drawBitmap(images[curr_frame], src, dst, null);
isScaled=false;
return 1;
}
And now the usage:
void onDraw(Canvas c)
{
canvas.drawRect( bgRect, bgPaint); //draw the background
//draw all game objects
// draw the normal items
for (GameEntity graphic : _graphics) {
graphic.toScreenCoords((int)player_x, (int)player_y);
if(graphic.getType().equals("planet")) //draw planets
graphic.Draw_Sprite(canvas); //before the rotation call draws fine
else
{
//rotate all space ships every frame so i see them spinning
//test rotation
mRot +=5;
if(mRot>=360)
mRot=0;
graphic.Draw_Sprite(canvas, 0, mRot); //yes function name will be better in future. this rotates spins draws fine
}
}
thePlayer.Draw_Sprite(canvas); //FLICKERS
drawUI(canvas);//all things here flickr
}
So it does do it, things after a call to a rotational draw are drawn correctly. But the problem is it flickrs. Now One could say I should just do all my non rotational stuff and save that last, but the zordering would be off.... suggestions as to how to tackle this issue of zordering or the flickering?
Just for the next guy who may read this. You can do this with only a few lines of code:
canvas.save();
canvas.rotate(rotation_angle, x + (widthofimage / 2), y + (heightofimage / 2));
canvas.drawBitmap(bitmap, x, y, null);
canvas.restore();
Try using canvas.save() before the rotation and canvas.restore() after manipulation is complete.
When performing manipulations on the canvas in order to change the way an object is drawn you have to remember the manipulations set how the canvas handles origins etc... So if you translate or rotate the canvas, that will be set for the lifetime of that canvas. In order to avoid this you first call save, which saves a snapshot of the canvas matrix before you manipulate it, then you run all your changes, then call restore which will restore the canvas back to the last saved point. Otherwise all your changes build up and you get unintended results.