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();
}
}
}
Related
This is my first time working with android, and I'm having some trouble drawing on a canvas repeatedly inside a thread. It seems that it only gets drawn once, although the thread is running which I made sure using a toast that popped up each time the thread executed (I've removed it because it was bothering me) but the thread is running and the code inside gets executed, it just sort of doesn't redraw...
public class GameActivity extends Activity implements Runnable{
ImageView gameView;
public int screenWidth, screenHeight, objectSize;
private static int FPS = 30;
private boolean rightPressed = false, leftPressed = false;
private Player player;
private Thread thread;
private Canvas canvas;
private Bitmap blankBitmap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
screenWidth = size.x;
screenHeight = size.y;
objectSize = screenWidth/8;
player = new Player(objectSize, screenWidth/2 - objectSize/2, screenHeight - (objectSize+10));
blankBitmap = Bitmap.createBitmap(screenWidth,screenHeight,Bitmap.Config.ARGB_8888);
canvas = new Canvas(blankBitmap);
gameView = new ImageView(this);
gameView.setImageBitmap(blankBitmap);
draw();
setContentView(gameView);
thread = new Thread(this);
thread.start();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
leftPressed = true;
if((int)event.getX()<=screenWidth/2){
leftPressed = true;
rightPressed = false;
Toast.makeText(this, "left", Toast.LENGTH_SHORT).show();
}
if((int)event.getX()>screenWidth/2){
rightPressed = true;
leftPressed = false;
Toast.makeText(this, "right", Toast.LENGTH_SHORT).show();
}
}
if(event.getAction() == MotionEvent.ACTION_UP) {
rightPressed = false;
leftPressed = false;
Toast.makeText(this, "released", Toast.LENGTH_SHORT).show();
}
return super.onTouchEvent(event);
}
public void draw(){
canvas.drawColor(Color.argb(255, 255, 255, 255));
player.draw(canvas);
}
#Override
public void run() {
while (!player.shouldDie()) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (!rightPressed && !leftPressed) player.setDx(0);
if(rightPressed) player.setDx(player.getSpeed());
if(leftPressed) player.setDx(-player.getSpeed());
player.update();
draw();
}
});
Thread.sleep(1000/FPS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
I also checked that the x of the player does actually change, and if I manually set the dx to like 100 it does actually move the first time it is executed, but not later even though the thread is still running
anyway, here's the Player.class
public class Player {
private int health, size, x, y;
private double dx, speed;
private Paint paint;
public Player(int size, int x, int y){
health = 3;
speed = 1;
dx = 0;
this.size = size;
this.x = x;
this.y = y;
paint = new Paint();
paint.setColor(Color.argb(255, 26, 128, 182));
}
public void draw(Canvas canvas){
canvas.drawRect(x, y, x+size, y+size, paint);
}
public void update(){
x += dx;
}
public void hurt(){
health--;
}
public boolean shouldDie(){
if(health<=0)return true;
return false;
}
public void posToast(Context context){
Toast.makeText(context, "X: " + x, Toast.LENGTH_SHORT).show();
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public Paint getPaint() {
return paint;
}
public double getSpeed() {
return speed;
}
public void setSpeed(double speed) {
this.speed = speed;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public double getDx() {
return dx;
}
public void setDx(double dx) {
this.dx = dx;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
If anyone sees anything wrong in here I'd appreciate some help as I'm really confused as to why this doesn't work, especially since this is my first time working with android.
Seems you forgot to call rePaint() method. In Android, you have something called inValidate() which does redraw your canvas. You can either add in player draw method or activity draw method. That should do the trick.
I am new to programing. I am trying to move a circle by using the OnTouchListener, but I don't know how to call it within the onTouch event as I have a Class for Circle with x and y and a class called Drawing (d) which draws it on the canvas. I have highlighted bellow the lines which I find problematic. Thank you.
``
public class FirstPicture extends Activity implements OnTouchListener {
Drawing d;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
d=new Drawing(this);
setContentView(d);
d.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
**d.c1.getX() = event.getX();
d.c1.getY()= event.getY();**
d.invalidate();
return true;
}
}
public class Drawing extends View{
Context ctx;
Circle c1;
public Drawing(Context context) {
super(context);
this.ctx = context;
c1 = new Circle (165, 350, 33);
}
protected void onDraw (android.graphics.Canvas canvas){
Paint p = new Paint();
Paint p1 = new Paint ();
Paint p2 = new Paint ();
Paint p3= new Paint();
Paint p4 = new Paint();
p2.setColor(Color.WHITE);
p.setColor(Color.GREEN);
p3.setColor(Color.RED);
p1.setColor(Color.BLACK);
p4.setColor(Color.BLUE);
p1.setStyle(Style.FILL);
p1.setStyle(Style.FILL_AND_STROKE);
p1.setTextSize(19);
canvas.drawCircle(c1.getX(), c1.getY(), c1.getR(), p4);
canvas.drawText("100", c1.getX()-15, c1.getY()+5, p1);
}
}
public class Circle {
private float x;
private float y;
private float r;
public Circle(float x, float y, float r) {
super();
this.x = x;
this.y = y;
this.r = r;
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
public float getR() {
return r;
}
public void setR(float r) {
this.r = r;
}
}
You're trying to assign to a getter:
d.c1.getX() = event.getX()
How about exposing an update method on your Drawing view.
private int circleCenterX;
private int circleCenterY;
public void update(int x, int y) {
this.circleCenterX = x;
this.circleCenterY = y;
}
#Override
protected void draw(Canvas canvas) {
canvas.drawCircle(circleCenterX, circleCenterY, c1.getR(), p4);
canvas.drawText("100", c1.getX() - 15, c1.getY() + 5, p1);
}
Then your onTouch becomes:
#Override
public boolean onTouch(View v, MotionEvent event) {
d.update(event.getX(), event.getY());
return true;
}
Instantiate all your Paint objects outside of the draw method - perhaps in your constructor where you instantiate the circle. Instantiating objects is a relatively heavy operation and you don't want to do it while draw() is happening, especially as it happens 60x a second.
I'm semi-sure the draw() method on the view will automatically be called so there's no need to invalidate the view (but even if you do, it won't redraw the view until the next frame anyway - take this bullet point and this bit inside parentheses with a pinch of salt!)
I am in need of a good resource like a tutorial or sample code that would draw an expanding circle of different thickness. To be exact, a small full circle that would expand and shrink over time like a few seconds.
Thanks for the help.
I am relatively new on this and so I would like to ask for help on this.
Thanks.
This class will help:
public class BallView extends View {
public float x;
public float y;
private final int r;
public int color;
public void setColor(int color) {
mPaint.setColor(color);
}
#Override
public float getX() {
return x;
}
#Override
public void setX(float x) {
this.x = x;
}
#Override
public float getY() {
return y;
}
#Override
public void setY(float y) {
this.y = y;
}
public int getR() {
return r;
}
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//construct new ball object
public BallView(Context context, float x, float y, int r) {
super(context);
//color hex is [transparncy][red][green][blue]
mPaint.setColor(0xFF15FFD4); //not transparent. color is white
this.x = x;
this.y = y;
this.r = r; //radius
}
//qcalled by invalidate()
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(x, y, r, mPaint);
}
}
You can use it to draw a ball in your main activity using mainView.addView(mBallView) to add it to the view and BallView.invalidate to actually draw it and according to whatever mechanisms you want to achieve you can use the setter method to set the radius of the circle as time increases or whatever you'd like. Make sure to use a Timer that calls RedrawHandler.post() within it and redraws the view within there with the updated radius values.
Hey I am trying to make a new icon every 800 milliseconds, and position their x values randomly, and their y below the android screen. I want to get these icon to move across the screen vertically, but instead getting to work I keep getting multiple icons stacked on top of each other. Any Help is appreciated.
public class GameView extends SurfaceView{
Bitmap icon;
LinkedList<Sprite> balloonList;
Timer spawnTimer;
TimerTask spawnTask;
Random rand;
SurfaceHolder holder;
int spawnTime;
final int SPAWN_DIFFERENCE = 10;
public GameView(Context context){
super(context);
icon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
holder = getHolder();
balloonList = new LinkedList<Sprite>();
rand = new Random();
spawnTime = 1;
spawnTimer = new Timer();
spawnTask = new TimerTask() {
#Override
public void run() {
spawnNewBalloon();
}
};
spawnTimer.scheduleAtFixedRate(spawnTask, 800, 800);
}
private void spawnNewBalloon(){
Canvas canvas = holder.lockCanvas();
if(spawnTime == 0){
balloonList.insertTail(new Sprite(icon, rand.nextInt(getWidth() - icon.getWidth() / 2), getHeight()));
balloonList.getTailData().draw(canvas);
spawnTime = SPAWN_DIFFERENCE;
}
else spawnTime--;
if(balloonList.length() == 0){
for(int i = 0; i < balloonList.length(); i++) {
balloonList.getData(i).update(canvas);
}
}
holder.unlockCanvasAndPost(canvas);
}
}
class Sprite{
public Bitmap image;
public int x, y;
public Sprite(Bitmap image, int x, int y){
this.image = image;
this.x = x;
this.y = y;
}
public void draw(Canvas canvas){
canvas.drawBitmap(image, x, y, null);
}
public void update(Canvas canvas){
if(y > 0) y -= 15;
draw(canvas);
}
}
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);