On touch i create and move a bitmap. Now I want to scale the bitmap while i move it. How do i bring this effect ? Im using a sprite object to move it. I want to create an illusion of shooting . I guess this shall be achieved by the logic.
public class SpriteObject {
private Bitmap bitmap;
private int x;
private int y;
private int x_move = 0;
private int y_move = -1;
public SpriteObject(Bitmap bitmap, int x, int y) {
this.bitmap = bitmap;
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Bitmap getBitmap() {
return bitmap;
}
public void setMoveX(int movex){
x_move = movex;
}
public void setMoveY(int movey){
y_move = movey;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public void draw(Canvas canvas) {
canvas.drawBitmap(bitmap, x - (bitmap.getWidth() / 2), y - (bitmap.getHeight() / 2), null);
}
public void update(int adj_mov) {
x += (adj_mov * x_move);
y += (adj_mov * y_move);
}
public void still(int adj_still) {
x += (adj_still * x_move);
y += (adj_still * y_move);
}
}
Please try this:
int h = 100; // height in pixels
int w = 100; // width in pixels
Bitmap photoBitmap = Bitmap.createScaledBitmap(yourSelectedImageBitmap, h, w,true);
Related
I draw particles and move it successfully but when i draw a line between particles, it does not work correctly. I set the min distance is 20, so if the distance between 2 particles is smaller than 20 ,then drawing a line. But it still draws a line eventhough the distance is higher than 20. Here is the example problem picture. example problem
I found that the line is redrawed fastly, sometime it causes flashing redrawing line. Anyone have any ideas how to make smoother animation ?
Here is the code:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private canvasview canvasView;
final private int InitParticle=10;
final private ArrayList<particle> arrayList=new ArrayList<particle>(InitParticle);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
canvasView=new canvasview(this) ;
setContentView(canvasView);
// Create particles object and pass to the arrayList
InitArray();
// Passing particle arrayList to canvas
canvasView.passingArrFromMain(arrayList);
}
public void InitArray()
{
for(int i=0;i<InitParticle;i++)
{
particle Particle=new particle();
Particle.initialize(canvasView.get_WidthScreen(),canvasView.get_HeightScreen());
arrayList.add(Particle);
}
}
}
particle.java
public class particle {
private int x,y;
final private Random random=new Random();
private int xdirection,ydirection,randomdirection;
public particle()
{
this.x=0;
this.y=0;
this.xdirection=3;
this.ydirection=3;
this.randomdirection=random.nextInt(99); // random number for chosing direction
}
// Get position of particle
public int getx()
{
return x;
}
public int gety()
{
return y;
}
// Random position of particle
public void initialize(int a,int b)
{
this.x= random.nextInt(a);
this.y= random.nextInt(b);
}
public int getXdirection()
{
return xdirection;
}
public int getYdirection()
{
return ydirection;
}
public void setXdirection()
{
this.xdirection=-this.xdirection;
}
public void setYdirection()
{
this.ydirection=-this.ydirection;
}
public void move(int x,int y) {
if (this.randomdirection >= 0 && this.randomdirection < 25) {
this.x = this.x + x;
this.y = this.y + y;
} else if (this.randomdirection >= 25 && this.randomdirection < 50) {
this.x = this.x - x;
this.y = this.y + y;
} else if (this.randomdirection >= 50 && this.randomdirection < 75) {
this.x = this.x - x;
this.y = this.y - y;
} else if (this.randomdirection >= 75 && this.randomdirection < 100) {
this.x = this.x + x;
this.y = this.y - y;
}
}
}
canvasview.java
public class canvasview extends View {
final private int mindistance=20;
final private Paint paint;
final private int H=getContext().getResources().getDisplayMetrics().heightPixels;
final private int W=getContext().getResources().getDisplayMetrics().widthPixels;
private ArrayList<particle> arrayParticles;
final private Paint linepaint=new Paint(Paint.ANTI_ALIAS_FLAG);
public canvasview(Context context)
{
super(context);
// Set canvas background
setBackgroundColor(Color.parseColor("#898984"));
setLayoutParams(new RelativeLayout.LayoutParams(W,H));
// Set paint for drawing circle
paint=new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setColor(Color.parseColor("#E7E7E5"));
// Set paint for drawing line
linepaint.setStrokeWidth(5);
linepaint.setColor(Color.parseColor("#6B6C65"));
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
// Drawing Particles
for(int i=0;i<arrayParticles.size();i++) {
canvas.drawCircle(arrayParticles.get(i).getx(), arrayParticles.get(i).gety(), 20, paint);
}
// Drawing line between particles
for(int i=0;i<arrayParticles.size();i++) {
for(int j=i+1;j<arrayParticles.size();j++) {
int a=arrayParticles.get(i).getx()-arrayParticles.get(j).getx();
int b=arrayParticles.get(i).gety()-arrayParticles.get(j).gety();
if(Math.sqrt(a^2+b^2)<mindistance) {
canvas.drawLine(arrayParticles.get(i).getx(), arrayParticles.get(i).gety(), arrayParticles.get(j).getx(), arrayParticles.get(j).gety(), linepaint);
}
}
}
// Moving particles
update();
}
// Get Width and Height of Screen for random position of particle
public int get_WidthScreen()
{
return W;
}
public int get_HeightScreen()
{
return H;
}
// Get a copy of particle arrayList form MainActivity
public void passingArrFromMain(ArrayList<particle> arrayList)
{
this.arrayParticles=arrayList;
}
// Updating the new position of particles
public void update()
{
for (int i=0;i<arrayParticles.size();i++)
{
// Check edge of the screen
if(arrayParticles.get(i).getx()>get_WidthScreen())
arrayParticles.get(i).setXdirection();
if (arrayParticles.get(i).gety()>get_HeightScreen())
arrayParticles.get(i).setYdirection();
if (arrayParticles.get(i).getx()<0)
arrayParticles.get(i).setXdirection();
if (arrayParticles.get(i).gety()<0)
arrayParticles.get(i).setYdirection();
arrayParticles.get(i).move(arrayParticles.get(i).getXdirection(),arrayParticles.get(i).getYdirection());
// Redraw the canvas
invalidate();
}
}
}
I wanted to draw on the canvas with the code below with my custom brush, but as you can see in the picture, the background of my brush is black, albeit without color.
Although I specified the brush color as Color.TRANSPARENT or Color.parseColor ("# 00000000"), the brush background still turns black.
How can I make the background color of my brush transparent?
click to see the picture
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import androidx.annotation.ColorInt;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import android.util.AttributeSet;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
import java.util.Stack;
public class BrushDrawingView extends View {
static final float DEFAULT_BRUSH_SIZE = 50.0f;
static final float DEFAULT_ERASER_SIZE = 50.0f;
static final int DEFAULT_OPACITY = 255;
private float mBrushSize = DEFAULT_BRUSH_SIZE;
private float mBrushEraserSize = DEFAULT_ERASER_SIZE;
private int mOpacity = DEFAULT_OPACITY;
private final Stack<BrushLinePath> mDrawnPaths = new Stack<>();
private final Stack<BrushLinePath> mRedoPaths = new Stack<>();
private final Paint mDrawPaint = new Paint();
private Canvas mDrawCanvas;
private boolean mBrushDrawMode;
private Bitmap brushBitmap;
private Path mPath;
private float mTouchX, mTouchY;
private static final float TOUCH_TOLERANCE = 4;
private BrushViewChangeListener mBrushViewChangeListener;
public BrushDrawingView(Context context) {
this(context, null);
}
public BrushDrawingView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BrushDrawingView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setupBrushDrawing();
}
private void setupBrushDrawing() {
//Caution: This line is to disable hardware acceleration to make eraser feature work properly
setupPathAndPaint();
setVisibility(View.GONE);
}
private void setupPathAndPaint() {
mPath = new Path();
mDrawPaint.setAntiAlias(true);
mDrawPaint.setStyle(Paint.Style.STROKE);
mDrawPaint.setStrokeJoin(Paint.Join.ROUND);
mDrawPaint.setStrokeCap(Paint.Cap.ROUND);
mDrawPaint.setStrokeWidth(mBrushSize);
mDrawPaint.setAlpha(mOpacity);
}
private void refreshBrushDrawing() {
mBrushDrawMode = true;
setupPathAndPaint();
}
void brushEraser() {
mBrushDrawMode = true;
mDrawPaint.setStrokeWidth(mBrushEraserSize);
mDrawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
public void setBrushDrawingMode(boolean brushDrawMode) {
this.mBrushDrawMode = brushDrawMode;
if (brushDrawMode) {
this.setVisibility(View.VISIBLE);
refreshBrushDrawing();
}
}
public Bitmap getBrushBitmap() {
return brushBitmap;
}
public void setBrushBitmap(Bitmap brushBitmap) {
this.brushBitmap = brushBitmap;
}
public void setOpacity(#IntRange(from = 0, to = 255) int opacity) {
this.mOpacity = (int) (opacity * 2.55f);
setBrushDrawingMode(true);
}
public int getOpacity() {
return mOpacity;
}
boolean getBrushDrawingMode() {
return mBrushDrawMode;
}
public void setBrushSize(float size) {
mBrushSize = 5 + (int) (size);
setBrushDrawingMode(true);
}
void setBrushColor(#ColorInt int color) {
mDrawPaint.setColor(color);
setBrushDrawingMode(true);
}
void setBrushEraserSize(float brushEraserSize) {
this.mBrushEraserSize = brushEraserSize;
setBrushDrawingMode(true);
}
void setBrushEraserColor(#ColorInt int color) {
mDrawPaint.setColor(color);
setBrushDrawingMode(true);
}
float getEraserSize() {
return mBrushEraserSize;
}
public float getBrushSize() {
return mBrushSize;
}
int getBrushColor() {
return mDrawPaint.getColor();
}
public void clearAll() {
mDrawnPaths.clear();
mRedoPaths.clear();
if (mDrawCanvas != null) {
mDrawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
}
invalidate();
}
void setBrushViewChangeListener(BrushViewChangeListener brushViewChangeListener) {
mBrushViewChangeListener = brushViewChangeListener;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Bitmap canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mDrawCanvas = new Canvas(canvasBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
for (BrushLinePath linePath : mDrawnPaths) {
canvas.drawPath(linePath.getDrawPath(), linePath.getDrawPaint());
}
canvas.drawPath(mPath, mDrawPaint);
/////
final Bitmap scaledBitmap = getScaledBitmap();
final float centerX = scaledBitmap.getWidth() / 2;
final float centerY = scaledBitmap.getHeight() / 2;
final PathMeasure pathMeasure = new PathMeasure(mPath, false);
float distance = scaledBitmap.getWidth() / 2;
float[] position = new float[2];
float[] slope = new float[2];
float slopeDegree;
while (distance < pathMeasure.getLength())
{
pathMeasure.getPosTan(distance, position, slope);
slopeDegree = (float)((Math.atan2(slope[1], slope[0]) * 180f) / Math.PI);
canvas.save();
canvas.translate(position[0] - centerX, position[1] - centerY);
canvas.rotate(slopeDegree, centerX, centerY);
canvas.drawBitmap(scaledBitmap, 0, 0, mDrawPaint);
canvas.restore();
distance += scaledBitmap.getWidth() + 10;
}
}
/////
private Bitmap getScaledBitmap()
{
// width / height of the bitmap[
float width = brushBitmap.getWidth();
float height = brushBitmap.getHeight();
// ratio of the bitmap
float ratio = width / height;
// set the height of the bitmap to the width of the path (from the paint object).
float scaledHeight = mDrawPaint.getStrokeWidth();
// to maintain aspect ratio of the bitmap, use the height * ratio for the width.
float scaledWidth = scaledHeight * ratio;
// return the generated bitmap, scaled to the correct size.
return Bitmap.createScaledBitmap(brushBitmap, (int)scaledWidth, (int)scaledHeight, true);
}
/**
* Handle touch event to draw paint on canvas i.e brush drawing
*
* #param event points having touch info
* #return true if handling touch events
*/
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent(#NonNull MotionEvent event) {
if (mBrushDrawMode) {
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchStart(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
touchMove(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
touchUp();
break;
}
invalidate();
return true;
} else {
return false;
}
}
boolean undo() {
if (!mDrawnPaths.empty()) {
mRedoPaths.push(mDrawnPaths.pop());
invalidate();
}
if (mBrushViewChangeListener != null) {
mBrushViewChangeListener.onViewRemoved(this);
}
return !mDrawnPaths.empty();
}
boolean redo() {
if (!mRedoPaths.empty()) {
mDrawnPaths.push(mRedoPaths.pop());
invalidate();
}
if (mBrushViewChangeListener != null) {
mBrushViewChangeListener.onViewAdd(this);
}
return !mRedoPaths.empty();
}
private void touchStart(float x, float y) {
mRedoPaths.clear();
mPath.reset();
mPath.moveTo(x, y);
mTouchX = x;
mTouchY = y;
if (mBrushViewChangeListener != null) {
mBrushViewChangeListener.onStartDrawing();
}
}
private void touchMove(float x, float y) {
float dx = Math.abs(x - mTouchX);
float dy = Math.abs(y - mTouchY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mTouchX, mTouchY, (x + mTouchX) / 2, (y + mTouchY) / 2);
mTouchX = x;
mTouchY = y;
}
}
private void touchUp() {
mPath.lineTo(mTouchX, mTouchY);
// Commit the path to our offscreen
mDrawCanvas.drawPath(mPath, mDrawPaint);
// kill this so we don't double draw
mDrawnPaths.push(new BrushLinePath(mPath, mDrawPaint));
/////
final Bitmap scaledBitmap = getScaledBitmap();
final float centerX = scaledBitmap.getWidth() / 2;
final float centerY = scaledBitmap.getHeight() / 2;
final PathMeasure pathMeasure = new PathMeasure(mPath, false);
float distance = scaledBitmap.getWidth() / 2;
float[] position = new float[2];
float[] slope = new float[2];
float slopeDegree;
while (distance < pathMeasure.getLength())
{
pathMeasure.getPosTan(distance, position, slope);
slopeDegree = (float)((Math.atan2(slope[1], slope[0]) * 180f) / Math.PI);
mDrawCanvas.save();
mDrawCanvas.translate(position[0] - centerX, position[1] - centerY);
mDrawCanvas.rotate(slopeDegree, centerX, centerY);
mDrawCanvas.drawBitmap(scaledBitmap, 0, 0, mDrawPaint);
mDrawCanvas.restore();
distance += scaledBitmap.getWidth() + 10;
}
/////
mPath = new Path();
if (mBrushViewChangeListener != null) {
mBrushViewChangeListener.onStopDrawing();
mBrushViewChangeListener.onViewAdd(this);
}
}
#VisibleForTesting
Paint getDrawingPaint() {
return mDrawPaint;
}
#VisibleForTesting
Pair<Stack<BrushLinePath>, Stack<BrushLinePath>> getDrawingPath() {
return new Pair<>(mDrawnPaths, mRedoPaths);
}
}
public interface BrushViewChangeListener {
void onViewAdd(BrushDrawingView brushDrawingView);
void onViewRemoved(BrushDrawingView brushDrawingView);
void onStartDrawing();
void onStopDrawing();
}
class BrushLinePath {
private final Paint mDrawPaint;
private final Path mDrawPath;
BrushLinePath(final Path drawPath, final Paint drawPaints) {
mDrawPaint = new Paint(drawPaints);
mDrawPath = new Path(drawPath);
}
Paint getDrawPaint() {
return mDrawPaint;
}
Path getDrawPath() {
return mDrawPath;
}
}
The reason it happens is because Paint doesn't have an alpha composing mode set by default. Thus, when you're trying to paint a bitmap over your canvas it will replace the destination pixels with your brush pixels, which in your case is #00000000. And that will result in pixel being displayed as black. Have a look into this documentation: https://developer.android.com/reference/android/graphics/PorterDuff.Mode
By the first glance it seems you're looking for PorterDuff.Mode.SRC_OVER or PorterDuff.Mode.SRC_ATOP - this way transparent pixels from your source image (your brush) will not over-draw the pixels from your destination (canvas). In case your background is always non-transparent, you will see no difference between SRC_OVER and SRC_ATOP, but if it isn't - choose the one which fits your needs. Then you can modify setupPathAndPaint method by adding this line to its end:
mDrawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
I wanted to show profile status using a Progress bar just like Linkedin, I searched everywhere but didn't get any reference related to that.
My code:
public class ProgressDrawable extends Drawable {
private static final int NUM_SEGMENTS = 5;
private final int mForeground;
private final int mBackground;
private final Paint mPaint = new Paint();
private final RectF mSegment = new RectF();
public ProgressDrawable(int fgColor, int bgColor) {
mForeground = fgColor;
mBackground = bgColor;
}
#Override
protected boolean onLevelChange(int level) {
invalidateSelf();
return true;
}
#Override
public void draw(Canvas canvas) {
float level = getLevel() / 10000f;
Rect b = getBounds();
float gapWidth = b.height() / 10f;
float segmentWidth = (b.width() - (NUM_SEGMENTS - 1) * gapWidth) / NUM_SEGMENTS;
mSegment.set(0, 0, segmentWidth, b.height());
mPaint.setColor(mForeground);
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.drawRect(mSegment.left, mSegment.top, middle, mSegment.bottom, mPaint);
mPaint.setColor(mBackground);
canvas.drawRect(middle, mSegment.top, mSegment.right, mSegment.bottom, mPaint);
} else {
canvas.drawRect(mSegment, mPaint);
}
mSegment.offset(mSegment.width() + gapWidth, 0);
}
}
#Override
public void setAlpha(int alpha) {
}
#Override
public void setColorFilter(ColorFilter cf) {
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
In this code, all the blocks have same color, but as per requirement, all block colors should be different.
I want to simulate a collision between two balls, one controlled by the accelerometer and the other just moving randomly.
How do I implement these collisions? I've managed to set up the balls and the condition for collision, but beyond that, I have no idea how I can represent the collision vectors. An algorithm or a hint would be appreciated :) I have the x and y velocities and positions of the two balls stored in variables. I also managed to use some basic (yet wrong) collision mechanism, the random motion ball reverses its x and y velocities. But I'm having problems there too, if the balls are moving too fast, they overlap. What do I do?
package perseus.gfx.test;
import everything;
public class Ball extends View {
RectF lol;
Paint paint, lpaint;
Bitmap bitmap;
Canvas canvas;
private float ballx = 150;
private float bally = 140;
private double speedx = 0;
private double speedy = 0; //ignore
private double accx, accy=0;
private float rad = 15;
private float mult = 0.5f;
private float friction = -0.001f;
private double xv, yv, xS, yS;
private long ltm = -1;
int width, height;
int xmax, ymax;
int xmin, ymin;
public Ball(Context context) {
super(context);
lol = new RectF();
paint = new Paint();
paint.setColor(Color.CYAN);
lpaint = new Paint();
lpaint.setColor(Color.GRAY);
}
public double getSpeedX()
{
return this.speedx;
}
public double getSpeedY()
{
return this.speedy;
}
public void setSpeedX(double x)
{
this.speedx = x;
}
public void setSpeedY(double y)
{
this.speedy = y;
}
public void setColor(int c)
{
paint.setColor(c);
}
public float getRad()
{
return this.rad;
}
public void setRad(float rad)
{
this.rad = rad;
}
public void setAX(double accx)
{
this.accx = accx;
}
public void setAY(double accy)
{
this.accy = accy;
}
public float getX()
{
return this.ballx;
}
public void setX(float ballx)
{
this.ballx = ballx;
}
public float getY()
{
return this.bally;
}
public void setY(float bally)
{
this.bally = bally;
}
public void moveBall() {
xv = accx * mult;
yv = accy * mult;
ballx -= xv * mult;
bally -= yv * mult;
ballx +=speedx;
bally +=speedy;
/*ballx +=speedx;
bally +=speedy;*/
// Collision detection
if (ballx + rad > xmax) {
speedx = -speedx;
ballx = xmax-rad;
}
else if (ballx - rad < 0) {
speedx = -speedx;
ballx = rad;
}
if (bally + rad > 2*ymax/3) {
speedy = -speedy;
bally = 2*ymax/3 - rad;
}
else if (bally - rad < 0) {
speedy = -speedy;
bally = rad;
}
try {
Thread.sleep(20);
} catch(InterruptedException e) {}
invalidate();
}
#Override
public void onMeasure(int widthM, int heightM)
{
width = View.MeasureSpec.getSize(widthM);
height = View.MeasureSpec.getSize(heightM);
xmax = width-1;
ymax = height-1;
xmin = 0;
ymin = 0;
setMeasuredDimension(width, height);
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
}
#Override
public void onDraw(Canvas canvas)
{
canvas.drawBitmap(bitmap, 0, 0, paint);
lol.set(ballx - rad, bally-rad, ballx + rad, bally+rad);
canvas.drawLine(0, 2*height/3, width, 2*height/3, lpaint);
/*canvas.drawOval(lol, paint);*/
canvas.drawCircle(ballx, bally, rad, paint);
canvas.drawText(xv + " " + yv, 0, height/2, lpaint);
canvas.save();
moveBall();
canvas.restore();
}
}
This is my ball class, and my main activity would be:
package perseus.gfx.test;
import everything;
public class GfxActivity extends Activity implements OnSeekBarChangeListener, OnItemSelectedListener, SensorEventListener {
ViewGroup.LayoutParams vg = new ViewGroup.LayoutParams(-1, -1);
double velx, vely;
double x, y;
float radi;
double finx, finy;
float finrad;
long lastSensorUpdate = -1;
SensorManager sm;
static double ux, uy; //initial ball velocity
SeekBar velo, rad;
Spinner colour;
Ball ball, tester;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ball = new Ball(this);
tester = new Ball(this);
setContentView(R.layout.main);
addContentView(ball, vg);
addContentView(tester, vg);
sm = (SensorManager)getSystemService(SENSOR_SERVICE);
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_GAME);
colour = (Spinner)findViewById(R.id.color);
colour.setOnItemSelectedListener(this);
ArrayAdapter<CharSequence> aa = ArrayAdapter.createFromResource(this, R.array.colors, android.R.layout.simple_spinner_item);
aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
colour.setAdapter(aa);
velo = (SeekBar)findViewById(R.id.vel);
velo.setOnSeekBarChangeListener(this);
rad = (SeekBar)findViewById(R.id.rad);
rad.setOnSeekBarChangeListener(this);
ux = ball.getSpeedX();
uy = ball.getSpeedY();
radi = ball.getRad();
tester.setSpeedX(5);
tester.setSpeedY(3);
tester.setX(0);
tester.setY(0);
tester.setColor(Color.DKGRAY);
}
#Override
public void onProgressChanged(SeekBar seeker, int arg1, boolean arg2) {
switch(seeker.getId())
{
case R.id.vel:
x = ball.getSpeedX();
y = ball.getSpeedY();
if(x<0)
finx = -ux-arg1;
else if(x >= 0)
finx = ux+arg1;
if(y<0)
finy = -uy-arg1;
else if(finy>=0)
finy = uy+arg1;
ball.setSpeedX(finx);
ball.setSpeedY(finy);
break;
case R.id.rad:
finrad = radi + arg1;
ball.setRad(finrad);
break;
}
}
#Override
public void onStartTrackingTouch(SeekBar arg0) {
//nothing lol
}
#Override
public void onStopTrackingTouch(SeekBar arg0) {
//nothing lol
}
#Override
public void onItemSelected(AdapterView<?> parent, View v, int position,
long id) {
switch(position)
{
case 0:
ball.setColor(Color.CYAN);
break;
case 1:
ball.setColor(Color.RED);
break;
case 2:
ball.setColor(Color.BLUE);
break;
case 3:
ball.setColor(Color.GREEN);
break;
}
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent sensorevent) {
if(sensorevent.sensor.getType() == Sensor.TYPE_ORIENTATION)
{
ball.setAX(sensorevent.values[2]);
ball.setAY(sensorevent.values[1]);
}
if((Math.pow(ball.getX() - tester.getX(), 2) + Math.pow(ball.getY() - tester.getY(), 2)) <= (ball.getRad() + tester.getRad())*(ball.getRad() + tester.getRad()))
{
/*tester.setSpeedX(-1*tester.getSpeedX());
tester.setSpeedY(-1*tester.getSpeedY());*/
}
}
}
Ball and Tester are my two balls, Ball is controlled by the accelerometer. I'm aware that the code isn't very efficient, but I thought I'll work on implementing the collision first.
You'll need to consider a couple things before you can refine your collision algorithm - is the collision to be an elastic collision? Can you treat the two balls as point sources? Either way your momentum vectors will be conserved, so you can use Newton's P initial = P final to determine the new vectors.
The two balls are likely overlapping because the rate at which you are running your collision detection algorithm is slower than the rate at which you change the position of the balls.
If you post a code sample, we can help you better.
Considering you have xVel1, yVel1, xVel2, yVel2; xPos1, yPos1, xPos2, yPos2; mass1, mass2; after detecting the collision:
double theta = Math.atan2(yPos1-yPos2, xPos1-xPos2);
double c = Math.cos(theta);
double s = Math.sin(theta);
double xVel1prime = xVel1*c+yVel1*s;
double xVel2prime = xVel2*c+yVel2*s;
double yVel1prime = yVel1*c-xVel1*s;
double yVel2prime = yVel2*c-xVel2*s;
double P = (mass1*xVel1prime+mass2*xVel2prime);
double V = (xVel1prime-xVel2prime);
double v2f = (P+mass1*V)/(mass1+mass2);
double v1f = v2f-xVel1prime+xVel2prime;
xVel1prime = v1f;
xVel2prime = v2f;
xVel1 = xVel1prime*c-yVel1prime*s;
xVel2 = xVel2prime*c-yVel2prime*s;
yVel1 = yVel1prime*c+xVel1prime*s;
yVel2 = yVel2prime*c+xVel2prime*s;
//velocities updated
I am developing a simple 2d game. But im stuck at this point where i need to "spawn" unlimited with the same enemy when i click the screen.
So i think the best choose for something with unlimited is an array but i have no idea how to get a bitmapArray and then for each item in BitmapArray do canvas.draw
Someone please help me out!
//Simon
First of all, you will end up with a sort of limited array. Secondly, I'm recommending the Memory Pool pattern when using stuff like this, so you don't create new instances during runtime.
Back to your question, a first implementation would look something like this:
public class BitmapObject {
private Bitmap mBitmap;
private int mPositionX;
private int mPositionY;
private int mBitmapWidth;
private int mBitmapHeight;
private boolean mIsAlive;
public BitmapObject(Bitmap bitmap) {
mBitmap = bitmap;
mBitmapWidth = bitmap.getWidth();
mBitmapHeight = bitmap.getHeight();
mIsAlive = false;
}
public void draw(Canvas canvas) {
if (mIsAlive) {
canvas.drawBitmap(mBitmap, mPositionX, mPositionY, null);
}
}
public void setNewPosition(int touchX, int touchY) {
mPositionX = touchX - mBitmapWidth / 2;
mPositionY = touchY - mBitmapHeight / 2;
}
public void setIsAlive(boolean isAlive) { mIsAlive = isAlive; }
public boolean getIsAlive() { return mIsAlive; }
}
And use it like this in your SurfaceView class:
public class CanvasRenderer extends SurfaceView implements SurfaceHolder.Callback {
private static final int MAX_OBJECTS = 16;
private BitmapObject[] mBitmapObjectsArray;
public CanvasRenderer(Context context) {
super(context);
// Necessary SurfaceView initialization stuff.
Bitmap sprite = BitmapFactory.decodeResource(context.getResources(),
R.drawable.sprite);
mBitmapObjectsArray = new BitmapObject[MAX_OBJECTS];
for (int x = 0; x < MAX_OBJECTS; x++) {
mBitmapObjectsArray[x] = new BitmapObject(sprite);
}
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
for (int x = 0; x < MAX_OBJECTS; x++) {
mBitmapObjectsArray[x].draw(canvas);
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// Stuff.
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// Stuff.
}
#Override
public void onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
for (int x = 0; x < MAX_OBJECTS; x++) {
boolean isAlive = mBitmapObjectsArray[x].getIsAlive();
if (!isAlive) {
mBitmapObjectsArray[x].setNewPosition((int) event.getX(),
(int) event.getY());
mBitmapObjectsArray[x].setIsAlive(true);
break;
}
}
}
}
}
Ok, this is only the concept of drawing 2 bitmaps on a canvas. Actual implementation is much more serious.
Bitmap renderbmp1 = Bitmap.createBitmap( bitmapWidth,bitmapHeight,Bitmap.Config.RGB_565 );
Bitmap renderbmp2 = Bitmap.createBitmap( bitmapWidth,bitmapHeight,Bitmap.Config.RGB_565 );
Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
Canvas c = getHolder().lockCanvas(null);
c.drawBitmap(renderbmp1, left1, top1, paint);
c.drawBitmap(renderbmp2, left2, top2, paint);
getHolder().unlockCanvasAndPost(c);
renderbmp1.recycle();
renderbmp2.recycle();