android: the way to choose attributes randomly - java

I have a simple program to draw simple shapes by canvas.
private class MyViewCircle extends View {
public MyViewCircle(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
canvas.drawCircle(89, 150, 30, paint);
}
}
As you see, the attributes of the circle is
(Color.RED);
(89, 150, 30, paint);
I want to created another class includes a lot of other features(colors and coordinates) and select them randomly.
So, which way is better, array or arraylist or something else? Could someone gives me an example how to do that? Then how to randomly pick them and put them into the draw function? Cheers!

Try creating a simple Java object to contain all the attributes, then add them to a single list and choose an item at random:
class MyAttributes {
int color;
int x, y;
int radius;
public MyAttributes(int color, int x, int y, int radius) {
this.color = color;
this.x = x;
this.y = y;
this.radius = radius;
}
}
In your View class:
private List<MyAttributes> mAttributes;
private Random mRandom;
public MyViewCircle(Context context) {
mRandom = new Random();
mAttributes = new ArrayList<MyAttributes>();
mAttributes.add(new MyAttributes(Color.RED, 80, 70, 199));
mAttributes.add(new MyAttributes(Color.BLUE, 50, 170, 88));
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setAntiAlias(true);
int randomPosition = mRandom.nextInt(mAttributes.size());
MyAttributes randomAttr = mAttributes.get(randomPosition);
paint.setColor(randomAttr.color);
canvas.drawCircle(randomAttr.x, randomAttr.y, randomAttr.radius, paint);
}

Generally on Android I always aim to use an Array over using an ArrayList for performance.
To pick randomly you can use either the Math.random() method or the util.Random object. Using either of those you can generate an index value and read the data from the array with that index.
Should be pretty simple really so I won't write any code unless you really need that.

Related

Trying to populate the screen with objects

it seems I have a problem understanding classes. It would be great if someone could help.
I'm trying to populate my Smartphone screen (android) with 3 circles of different color.
My problem is that by using the code below I only get one (blue) circle.
I considered that the Problem is that the y-value isn't set correctly and the 3 circles are hiding each other (so that only the blue one is visible). But when I log the y-value of the 3 circle objects, the y-values seem to be correct (200,500,800)
Whats am I doing wrong?
Thanks for your help in advance.
public class MainActivity extends Activity {
public Circle circleR;
public Circle circleG;
public Circle circleB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
circleR = new Circle(this, 200, 255, 0, 0);
setContentView(circleR);
circleG = new Circle(this, 500, 0, 255, 0);
setContentView(circleG);
circleB = new Circle(this, 800, 0, 0, 255);
setContentView(circleB);
}
}
public class Circle extends View {
public Paint paint;
public int y;
public Circle(Context context,int y, int r, int g, int b){
super(context);
paint=new Paint();
paint.setColor(Color.rgb(r,g,b));
this.y=y;
}
#Override
protected void onDraw(Canvas canvas){
canvas.drawCircle(30, this.y,30, paint);
}
}
The problem lies in setting the content view multiple times. Only the view set as last (the one with a blue circle) will be visible. If you want multiple circles to be visible at the same time you should draw them on one canvas localized inside one view. I rearranged your code so that it does what you wanted:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CirclesView circlesView = new CirclesView(this);
setContentView(circlesView);
}
}
public class CirclesView extends View {
public Circle circleR;
public Circle circleG;
public Circle circleB;
public CirclesView(Context context) {
super(context);
circleR = new Circle(200, 255, 0, 0);
circleG = new Circle(500, 0, 255, 0);
circleB = new Circle(800, 0, 0, 255);
}
#Override
protected void onDraw(Canvas canvas){
circleR.draw(canvas);
circleG.draw(canvas);
circleB.draw(canvas);
}
}
public class Circle {
public Paint paint;
public int y;
public Circle(int y, int r, int g, int b) {
paint = new Paint();
paint.setColor(Color.rgb(r,g,b));
this.y=y;
}
public void draw(Canvas canvas) {
canvas.drawCircle(30, this.y,30, paint);
}
}
Circle knows how to draw itself on a canvas which will be provided to it by a view.

Android Canvas weird shifting

I have a problem I was trying to solve for almost 2 days. (It ended up by switching to OpenGL :D)
Anyway... I have Canvas and I am trying to do a simple snake game. Just for this problem imagine our snake is made up from 5x5 pixels rectangles, he is leaving the trail (no clearing) and moving to the right from 0, 50 position... here is the code:
public class Snake extends AnimationWallpaper {
#Override
public Engine onCreateEngine() {
return new SnakeEngine();
}
class SnakeEngine extends AnimationEngine {
int i = 0;
Paint paint = new Paint();
#Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
// By default we don't get touch events, so enable them.
setTouchEventsEnabled(true);
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
}
#Override
public void onOffsetsChanged(float xOffset, float yOffset,
float xOffsetStep, float yOffsetStep, int xPixelOffset,
int yPixelOffset) {
super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep,
xPixelOffset, yPixelOffset);
}
#Override
public Bundle onCommand(String action, int x, int y, int z,
Bundle extras, boolean resultRequested) {
if ("android.wallpaper.tap".equals(action)) {
}
return super.onCommand(action, x, y, z, extras, resultRequested);
}
#Override
protected void drawFrame() {
SurfaceHolder holder = getSurfaceHolder();
Canvas c = null;
try {
c = holder.lockCanvas();
if (c != null) {
draw(c);
}
} finally {
if (c != null)
holder.unlockCanvasAndPost(c);
}
}
void draw(Canvas c) {
//c.save();
//c.drawColor(0xff000000);
paint.setAntiAlias(true);
// paint the fill
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
c.drawRect(i*5, 50, (i+1)*5, 55, paint);
//c.restore();
}
#Override
protected void iteration() {
i++;
super.iteration();
}
}
}
And here is output:
And that is not all, when it draws its kinda shifting... meaning what you see is shifted to the right side so it doesnt actualy stand in the same place...
If you have any idea why is it behave like that, please tell me!
In canvas, there's a reusability functionality which practically just add new drawings to whatever is in the canvas, hence if you are drawing 1 square at the time, the next time you will have whatever u had before +1, if you don't want that, and you want to fully manipulate every single draw from scratch, just add this line of code before to start drawing
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
It will clear anything you had in the previous state of the canvas, and you can start again drawing whatever you want...
Hope It Helps!
Regards!

Java 2D object repeatition

I built a Java 2d circle using the Java g.drawstring() methods and using the Breseham's Circle algorithm and I used it to draw a smiley but when I move the smiley it repeats all over the screen I know for sure that the PaintComponent(Graphics g) Method keeps re-drawing the simley at different location specified but how to correct this logic error is my problem. Here are the codes i wrote.
public class Midsemester extends JPanel implements ActionListener {
// objects class
static Movement move = new Movement();
public int x = 0, y = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0, x3 = 0, y3 = 0, x4 = 0, y4 = 0;
private int inix = 0, iniy = 0;
static String[] st = {"xy","x1y1","x2y2","x3y3","x4y4"};
static shapes shaper = new shapes();//object class contain the algorithms used to draw the circles using the Breseham's Circle algorithm
public Midsemester()
{
}
/****/
#Override
public void paintComponent(Graphics g)
{
super.paintComponents(g);
x = (int)move.x;
y = (int)move.y;
x1 = (int)move.x1;
y1 = (int)move.y1;
x2 = (int)move.x2;
y2 = (int)move.y2;
x3 = (int)move.x3;
y3 = (int)move.y3;
x4 = (int)move.x4;
y4 = (int)move.y4;
shaper.draw_floor(100, 350, 1350, g);
shaper.draw_wall(100, 0, 350, g);
shaper.create(x,y,50,g, Color.yellow);//creates the smileys in there different colors
shaper.create(x1,y1,50,g, Color.BLUE);
shaper.create(x2,y2,50,g, Color.pink);
shaper.create(x3,y3,50,g, Color.magenta);
shaper.create(x4,y4,50,g, Color.orange);
repaint();
}
#Override
public void actionPerformed(ActionEvent ae)
{
float[] values = move.firstscenemovement(500,200,st[0]);
repaint();
System.out.println("x:"+values[0] + "\ny:" + values[1]);
}
}
The image repeats or trails as it moves would have posted an image but i need a 10 reputation to do.
How can I correct this error? Thanks in advance.
I think The repaint() in your paintComponent() code causes an endless recursion.
repaint --> paintComponent --> repaint -->...
This is messing up the Graphics object.
edit:
There is another error in your code, your calling super.paintComponent s (g) instead of super.paintComponent(g). Try to use the method without the s.
Here is a simple example of a class that moves the string according to the position of the last click:
public class Test extends JPanel implements MouseListener {
private int x = 100;
private int y = 100;
public static void main(String[] args) {
JFrame jFrame = new JFrame();
Test test = new Test();
jFrame.add(test);
jFrame.setBounds(0, 0, 800, 600);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setVisible(true);
jFrame.addMouseListener(test);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("blub", x, y);
}
#Override
public void mouseClicked(MouseEvent e) {
this.x = e.getX();
this.y = e.getY();
repaint();
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
}
You are the first questioner i have found who is calling super.paintComponent(g) in the overridden paintComponent(Graphics g) function in their first posted question. Well,
calling repaint() will actually submit a new paint request resulting another invocation of paintComponenr(Graphics g) function and putting repaint() inside the paintComponent function is going to create a cycle, calling painting functions one after another increasing the rendering stack. So remove the repaint() call from the paintComponent function.
Check out the tutorial: Performing custom painting

Some questions on using the canvas in Java to draw shapes and paths for Android?

How do I find the coordinates of the screen? I know e.g. a phone would have say a 960 x 540 resolution, but in the emulators some of the edges are not filled if I draw a shape to that resolution. Is there a way around this?
For the colour of the rectangle, it is seen there are two rectangles, and two of them have the same colour despite giving two separate colours for drawPaint. Just setting a new variable e.g. drawPaint2 returns errors. How to change the colour of both?
How to use the path function in the canvas. E.g. to draw a triangle? I have included my attempt in the code but it doesn't display a triangle.
public class DrawView extends View implements OnTouchListener
{
private Paint backgroundPaint = new Paint();
private Paint drawPaint = new Paint();
private Paint circlePaint = new Paint();
private Paint textPaint = new Paint();
private Paint path = new Paint();
private float sx, sy;
public DrawView(Context context)
{
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
backgroundPaint.setColor(Color.CYAN);
backgroundPaint.setAntiAlias(true);
backgroundPaint.setStyle(Style.FILL);
drawPaint.setColor(Color.WHITE);
drawPaint.setStyle(Style.FILL);
circlePaint.setColor(Color.DKGRAY);
circlePaint.setStyle(Style.FILL);
textPaint.setColor(Color.WHITE);
textPaint.setStyle(Style.FILL);
drawPaint.setColor(Color.GREEN);
drawPaint.setStyle(Style.FILL);
circlePaint.setColor(Color.RED);
circlePaint.setStyle(Style.FILL);
path.setColor(android.graphics.Color.RED);
path.setStyle(Paint.Style.FILL);
Path path = new Path();
path.moveTo(1, 1);
path.lineTo(20, 50);
path.moveTo(20, 50);
path.lineTo(100, 100);
path.moveTo(100, 100);
path.lineTo(1, 1);
path.close();
this.setOnTouchListener(this);
}
#Override
public void onDraw(Canvas canvas)
{
//canvas.drawPath(path, paint); <-- error
// to draw background
canvas.drawRect(this.getLeft(), this.getTop(), this.getRight(), this.getBottom(), backgroundPaint);
//to draw two rectangle with blue and green paint
canvas.drawRect(100,100, 340,540, drawPaint);
canvas.drawRect(00,00, 120,80, drawPaint);
//draw text with paint
canvas.drawText("Hello Dear Leader!", 110, 160, textPaint);
//draw a circle with green paint with the touch coordinates
canvas.drawCircle(sx-30,sy-30, 30, circlePaint);
//draw a circle with red paint with the touch coordinates
canvas.drawCircle(sx-80, sy-80, 10, circlePaint);
}
public boolean onTouch(View v, MotionEvent event)
{
//update the coordinates for the OnDraw method above, with wherever we touch
sx = event.getX();
sy = event.getY();
invalidate();
return true;
}
}
for the size you can easily call canvas.getWidth() and canvas.getHeight() and do all your values a percentage of those. Do never assume a constant!
You need to use two separate Paints to use two different colors. And remember that each paint is an object that needs initialisation.
// objects
private Paint drawPaint_WH = new Paint();
private Paint drawPaint_GR = new Paint();
// during construction
drawPaint_WH.setColor(Color.WHITE);
drawPaint_WH.setStyle(Style.FILL);
drawPaint_GR.setColor(Color. GREEN);
drawPaint_GR.setStyle(Style.FILL);
// and then during draw()
canvas.drawRect(100,100, 340,540, drawPaint_WH);
canvas.drawRect(0,0, 120,80, drawPaint_GR);
and then to make a triangle:
// object
private Path trianglePath;
// during construction
trianglePath = new Path();
trianglePath.moveTo(10, 10); // starting point
trianglePath.lineTo(10, 50); // 1st vertix
trianglePath.lineTo(50, 10); // 2nd vertix
trianglePath.lineTo(10, 10); // 3rd vertix and close
// then during draw()
canvas.drawPath(trianglePath, drawPaint_GR) // or whatever paint you want
ps.: do color the background it's easier to call canvas.drawColor(int colorVal);

draw a custom drawable without any size in Android

I'm trying to draw a drawable background with a path. But i getting to one point where i can't draw because i need the size of the object that will receive the background. Is there a function to find the size of the specific view that i will draw on ?
public class CustomDrawableEditText extends Drawable{
private Context context;
public CustomDrawableEditText(Context context) {
// TODO Auto-generated constructor stub
this.context = context;
}
#Override
public void draw(Canvas canvas) {
// TODO Auto-generated method stub
Path path = new Path();
Paint paint = new Paint();
path.moveTo(0, 0);
path.lineTo(10, 0);
path.moveTo(0, 0);
path.lineTo(0, Y);
path.lineTo(10, Y);
path.moveTo( X, 0);
path.lineTo( X-10, 0);
path.moveTo( X, 0);
path.lineTo( X, X);
path.lineTo( X-10, X);
paint.setColor(context.getResources().getColor(R.color.orange));
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.STROKE);
canvas.drawPath(path, paint);
}
private int getY() {
final Resources res = context.getResources();
final float scale = res.getDisplayMetrics().density;
return (int) (res.getDimension(R.dimen.dim4) * scale + 0.5f);
}
#Override
public int getOpacity() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void setAlpha(int alpha) {
// TODO Auto-generated method stub
}
#Override
public void setColorFilter(ColorFilter cf) {
// TODO Auto-generated method stub
}
}
To get the size of a View you can invoke getWidth() and getHeight(). Note that you might be interested in getMeasuredWidth() and getMeasuredHeight() as well.
Make sure these methods are called after the layout process of your view.
Call the Drawable.getBounds() or Drawable.copyBounds(Rect rect) methods.
These two methods should return the View's bounds (when a View's size changes, it calls (should call) the Drawable.setBounds method on each Drawable it has with the appropriate parameter values) in which the View wants your Drawable to be drawn. Your own custom-Drawable can then retrieve this value by calling Drawable.getBounds() or Drawable.copyBounds(Rect rect).

Categories

Resources