I am trying to draw a cupola circles at random positions in an Android application.
I draw them on a bitmap and then draw that bitmap on the canvas. This is the function where a draw the circles:
private void drawRandomCircles(int numOfCircles) {
Canvas c = new Canvas(b);
Paint cPaint = new Paint;
cPaitn.setColor(Color.RED);
for(int i = 0; i < numOfCircles; i++) {
int x = Math.Random % 100;
int y = Math.Random % 100;
c.drawCircle(x, y, 20, cPaint)
}
}
The Bitmap b is global.
And after calling this function I just draw the bitmap in the onDraw method.
Now the problem is that I only get one circle drawn on the screen, no matter the size of numOfCircles.
Any clue what is happening here?
That code doesn't even compile. What is new Paint; for instance?
I suggest you log your arguments to drawCircle to make sure you draw them on different locations. If Math.Random for instance is a field, it would change in between reads, which would put the circles on top of each other.
If you intended to write Math.random() the error is that Math.random() returns a value between 0 and 1. You may want to use
Random r = new Random();
// your loop
int x = r.nextInt(100);
int y = r.nextInt(100);
Related
I'm new to android studio and I'm learning a lot right now. But I'm stuck now, I want to create something like a container for a 16x7 boardgame with individual fields. I think theres better ways to do this and I'm trying around since 2 hours, with no success. Right now I'm using a Grid View to display my String[] with an array adapter to a simple selectable list item, but it doesn't scale right and I need to scroll down to see all of the fields, which is bad for a videogame.
Tl,dr: I'd like to display an array of 112 elements like a boardgame, what container can I use to create those individual fields, maybe even set the amounts of rows(7) and columns(16), and display it simple like an actual boardgame?
I would render bitmap tiles to the Canvas. Below code is just an outline:
// You will set this frameBuffer to an ImageView in the app's main screen.
// You should set the ImageView's ScaleType properly.
Bitmap frameBuffer = Bitmap.createBitmap(
TILE_SIZE * 16, TILE_SIZE * 7, Bitmap.Config.ARGB_8888
);
Canvas canvas = new Canvas(frameBuffer);
Paint paint = new Paint();
for (int y = 0; y < 7; y++) {
for (int x = 0; x < 16; x++) {
// You are supposed to define bitmapTiles.get() method elsewhere.
canvas.drawBitmap(
bitmapTiles.get(x, y), TILE_SIZE * x, TILE_SIZE * y, paint
);
}
}
I am new to android programming and have run into a small problem. If you could help, that would be greatly appreciated.
I am making rectangles for a live wallpaper I am making using:
void drawFrame() {
final SurfaceHolder holder = getSurfaceHolder();
Canvas c = null;
try {
c = holder.lockCanvas();
if (c != null) {
Paint paint = new Paint();
paint.setColor(Color.CYAN);
Paint ypaint = new Paint();
ypaint.setColor(Color.RED);
Paint ppaint = new Paint();
ppaint.setColor(Color.GREEN);
drawVerStripes(c, ppaint, 0,20);
drawVerStripes(c, paint, 50,20);
drawVerStripes(c, ypaint,0,10);
}
} finally {
if (c != null)
holder.unlockCanvasAndPost(c);
}
The function:
Params:
width: width of the rectangle
space: the difference between last rect and this rect
int y=0;
int oldY=0;
private void drawVerStripes(Canvas c, Paint paint, int space, int width) {
y=oldY+space;
c.drawRect(y, 0, y+width,c.getHeight(), paint);
oldY=y;
}
The result is the rectangles moving to one side of screen really fast. I want them to stay on screen and not move.
In other words, is there a way that drawVerStripes is executed only once and not every frame.
Your drawFrame method is called with each frame. If your devices refresh rate is 70, then your method is called 70 times a second. If you increase x or y coordinate by 1, then you move 70 pixels in either x or y coordinates. You should do refresh rate independent movement.
1) Calculate delta time which is the time that passed since the last screen update.
2) Determine how many pixels you want your rectangle to move every second.
Let's say you want you rectangle to move 50 pixels in x.
Then do the following. x += deltaTime * 50.
long startTime = System.nanoTime(); // Execute before the first time your drawFrame executes
float deltaTime = (System.nanoTime()-startTime) / 1000000000.0f; // In drawFrame method calculate
long startTime = System.nanoTime(); // Execute after calculating delta time.
I believe that you need to set y and oldY to 0 again at the beginning of drawFrame.
I have an isometric map which I draw to the canvas. When I try and move the map around, these black lines flicker in between some of the tiles making the whole thing look rather shoddy.
Here is the relevant code from my updating thread
public void run() {
Canvas c;
while (isRunning){
c = null;
try {
c = cellMap.getHolder().lockCanvas(null);
synchronized (cellMap.getHolder()) {
cellMap.onDraw(c);
}
} finally {
if( c != null){
cellMap.getHolder().unlockCanvasAndPost(c);
}
}
}
}
and from my CellMap class (which extends SurfaceView):
public void onDraw(Canvas canvas){
canvas.drawColor(Color.BLACK);
int x = 0;
int y = 0;
for(int i = 0; i < mapSize; i++){
for(int j = 0; j < mapSize; j++){
x = (i-j) * 30 + xOffset;
y = (i+j) * 15 + yOffset;
mapCells[i][j].draw(canvas, paint, x, y);
}
}
mapCells[][] is an array of objects which contain the Bitmap image that needs to be drawn. The draw() function is only 1 line canvas.drawBitmap(bitmapImage, x, y, null)
I have discovered that removing the line Canvas.draw(Color.black) gets rid of the flicker. However, when I move the map the canvas is not cleared so I still see the image from the previous frames. I'd imagine it is because it is taking too long to draw the bitmaps? but the map is only very small at the moment.
I found the problem. When moving the map, the offset values were being changed. This lead to sections of the map being drawn temporarily with different offset values - creating the tearing. duh!
I solved this by copying the xOffset and yOffset values at the start of the onDraw() method, and using those values for the update.
I am developing an app which draws more or less a two-dimensional matrix of values to a canvas. The values of this matrix are scaled to Alpha levels to illustrate intensity, and the coordinates for the matrix are simply extrapolated from row and column indexes. Below is my onDraw routine.
public void onDraw(Canvas canvas, float [][] spectrum, float nsegs,int seglen) {
//canvas.translate(0,0);
//alpha = 0;
int canHeight = canvas.getHeight();
int canWidth = canvas.getWidth();
//float[] array = generateData(512);
float [] spec = new float[seglen];
final float bw = (float)(canWidth-2)/nsegs;
final float bh = (float)(canHeight-2)/(float) seglen;
for (int i = 0;i<seglen;i++){
spec[i] = spectrum[i][index]; // One column at a time
}
float max = maxVal(spec);
float min = minVal(spec);
xcoor = index;
for (int n = 0; n < seglen; n++){
//Scale value to alpha (0-255)
alpha =(int)Math.round((((spec[n] - min)/max)*255.0));
ycoor = n;
paint.setAlpha(alpha);
canvas.drawPoint(xcoor,ycoor, paint);
}
index = (int) (index +1);
if (index == nsegs-1){
index = 0;
}
}
Here paint configuration is pre-defined as:
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
paint.setStrokeWidth(2);
This program draws one pixel at a time, fills one column of pixels equal to the number of elements in a column of the matrix. Then it starts on the next column, where the previous column is still displayed and so forth. At this stage when all columns are full it stars from the first column again, drawing on top of previous elements.
The Problem: The tailing columns although already drawn appear to flicker and jump around, as does the Alpha. I have attempted to canvas.save() and canvas.restore() to capture the entire canvas and restore it after a column is printed. I have double checked all my row and column indexing and alpha vales to ensure the coordinates increment as per desired (and they do). This is very similar to the sample APIdemo DrawPoints.java, however there are three primary differences.
I am using DrawPoint not DrawPoints, and
I don't use "canvas.setColour" as it removes the tailing columns from the canvas.
This onDraw function is operating in a Thread which extends SurfaceView
Any idea's would be much appreciated, thank you for your time.
In the case above, I was using a SurfaceView instead of a View. Out of the Android dev docs
Note: On each pass you retrieve the Canvas from the SurfaceHolder, the previous state of the Canvas will be retained. In order to properly animate your graphics, you must re-paint the entire surface. For example, you can clear the previous state of the Canvas by filling in a color with drawColor() or setting a background image with drawBitmap(). Otherwise, you will see traces of the drawings you previously performed.
The Solution, re-draw the entire canvas each time to prevent the jitter.
I want to draw a signal waveform using the path.linTo method and a for loop as shown below.
public void drawSignal(Canvas c, PointF pos) // draws the signal onto the Canvas for each of the 12 channels
{
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStyle(Style.STROKE);
Path path = new Path();
for (int i=0; i<ECGFilereader.numChannels; i++){
path.moveTo(wavePos[i].x, wavePos[i].y);
for (int chan = 0; chan<ECGFilereader.numChannels; chan++)
for (int m = 0; m < ECGFilereader.numSamples; m++){
path.lineTo(m+wavePos[i].x, signal[chan][m]+wavePos[i].y);
}
}
c.drawPath(path, paint);
However I would like to scale the graph so that each movement in the x-axis is only 1/5 of that of the y-axis, so that the length of the signal is effectively squashed horrizontally. Is it possible to do this by simply using floats somehow I do I need to actually create a larger canvas and scale it there?
Thanks in advance for any help.
err, either multiply the y-components by 5 or divide the x-components by 5 in both path.moveTo and path.lineTo?