Firstly I am adding my cards to a list like that:
private void initCards() {
for (int i = 0; i < 20; i++) {
Bitmap tempBitmap = BitmapFactory.decodeResource(myContext.getResources(),R.drawable.ic_launcher);
scaledCardW = (int) (screenW/10);
scaledCardH = (int) (scaledCardW*1.28);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(tempBitmap,scaledCardW, scaledCardH, false);
deck.add(scaledBitmap);
}
But when it came to on draw method,my program is transforming a thing like an animation.
My onDraw method is here:
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
int left=newInteger.nextInt(screenW);
int right=newInteger.nextInt(screenH);
for(int i=0 ; i<k ;i++){
canvas.drawBitmap(deck.get(i), left, right, null);
}
}
These bitmaps must have random location and if I change the k from our main Activity different numbers of bitmaps must be drawen.Because of that,ı cannot remove the invalite() function.
Can anybody help me?Unfortunately,another topics about this problem are not providing my request.
Your bitmaps keep moving because you are randomizing their position every time you draw. Try moving these lines:
left = newInteger.nextInt(screenW);
right = newInteger.nextInt(screenH);
into the same function that changes the value of k.
Related
XML is not the factor in this case. I'm overriding the canvas with the onDraw function and providing the entire screen as a canvas.
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
int gemID=0;
for(int c=0;c<5;c++){
for(int r=0;r<5;r++){
gemID= GemField[c][r];
canvas.drawBitmap(bmps.get(gemID),c,r,null);
}
}
Upon creating the canvas to draw on I create the matrix, and then I fill the matrix as seen in the following bits of code.
private void createGemField() {
Random rnd= new Random();
for(int col=0;col<5;col++){
for(int row=0;row<5;row++){
int gemNum = rnd.nextInt(4-0);
GemField[col][row]=gemNum;
}
}
}
private void drawGems(){
int gemID=0;
for(int col=0;col<5;col++){
for(int row=0;row<5;row++){
gemID=GemField[col][row];
canvas.drawBitmap(bmps.get(gemID),col,row,null);
}
}
}
Unfortunately the image I get is square in the top left of the screen with multiple objects that seem like they're scaled over each other. More like a snakes scale or shingles, the objects overlap but not completely. The further from the starting place holder in the matrix the less they overlap. Any idea why this may be happening?
canvas.drawBitmap(bmps.get(gemID),c,r,null);
Here, c and r are the x and y components of the point on the canvas where the bitmap is drawn. I assume your bitmaps are larger than 1px, so you should change this into:
canvas.drawBitmap(bmps.get(gemID), 50 * c, 50 * r, null); or something like this; between the bitmaps is now 50px space.
I use followed example (described here) to animate my sprite sheet.
from example I wrote my Object:
public class Sprite {
private int x, y;
private int width, height;
private Bitmap b;
MainGamePanel ov;
int currentFrame = 0;
public Sprite(MainGamePanel mainGamePanel, Bitmap blob) {
this.ov = mainGamePanel;
this.b = blob;
// 1x12
height = b.getHeight();
width = b.getWidth()/12;
x = y = 50;
}
private void update(int dist) {
currentFrame = ++currentFrame % 12;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//return _b;
}
public void draw(int shift, Canvas canvas, int dist) {
update(dist);
int srcX = currentFrame * width;
Rect src = new Rect(srcX, 0, srcX+width, height);
Rect dst = new Rect(x, y+shift, x+width, y+height+shift);
canvas.drawBitmap(b, src, dst, null);
}
Here every 100 msec I take different part from image (Bitmap) and show it.
1 -> 2 -> 3 -> 4 -> ... -> 12
So my creature flies and moves with wings.
If I show only 1 object, it seems good but when I try to run 20 creatures in loop:
Bitmap blob = BitmapFactory.decodeResource(getResources(), R.drawable.sprite3);
for(int i=0; i<20; i++){
spriteList.add(new Sprite(this, blob));
}
....
for(int i=0; i<spriteList.size(); i++){
sprite = spriteList.get(0);
sprite.draw(canvas, dist);
}
My objects start to be slow according to drawn object count.
It happens I think because of Thread.sleep(100);.
I don't see any performance problem.
Sounds like each object sleep pauses all objects.
For 20 objects this sleep grows to 2 sec.
For sure I use workaround like:
int sleep = 100/spriteList.size();
Thread.sleep(sleep);
But code looks messy.
Can anyone help me how to fix it?
Here is sprite3 image:
[EDIT]
Maybe I need create each object in separate Thread?
You should definitely not sleep while rendering; it greatly reduces the performance, especially, as you add new Animation Clips, etc. Also, don't create objects within your onDraw method and do try to reuse the Rect objects. Creating objects during rendering is very expensive.
Hello All first post on Stack overflow!!
I am attempting to draw multiple lines on a canvas but using different colours. My problem is that the line colours are always the same as the last line in the array. I am drawing vertical lines progressively across the screen at 30Hz, similar to a bar chart without any spacing. I am calling view. Invalidate() for the view onDraw() to run and draw the lines.
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
if (plotInfo == null)
return;
for (int i = 0; i < plotInfo.length; i++) {
//paintlineinfo = String.valueOf( plotInfo[i].paintOfLine.getColor());
canvas.drawLine(i, mDisplay.getHeight(), i, mDisplay.getHeight()-plotInfo[i].linePositionY, plotInfo[i].paintOfLine);
}
}
I believe I may to use Open GL but I am trying to avoid it for the moment unless anyone can point me in the right direction for a good article that may help me.
At some point i would like to make the lines multiple colours.
Any help would be greatly appreciated...
I don't know from there you ge the colour, try:
#Override
protected void onDraw(Canvas canvas)
{
// TODO Auto-generated method stub
super.onDraw(canvas);
if (plotInfo == null)
return;
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
for (int i = 0; i < plotInfo.length; i++) {
paint.setColor( yourArrayOfColours.get(i) );
canvas.drawLine(i, mDisplay.getHeight(), i, mDisplay.getHeight()-plotInfo[i].linePositionY, paint);
}
}
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.
In my Android app, I am trying to show letters one by one with a short delay between each, while also playing a sound for each letter. I have everything working, and the sounds play with the correct delay, but the text always prints to the screen far too fast. The canvas seems to be updated even when i am not specifically invalidating the view.
Here is what I have so far - I also tried a variant of this based on the "snake" example and had the same results... any help would be appreciated!
public class SpellingView extends View {
private static final String WORD = "TRUCK";
int width;
int height;
String textToPrint;
float textspace;
int j=0;
private final Path arc;
private final Paint tPaint;
//constructor for SpellingView
public SpellingView(Context context) {
super(context);
arc = new Path();
tPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
displayLetterLoop();
}
public void displayLetterLoop(){
for (int i = 0; i < WORD.length(); i++){
final Runnable mUpdateUITimerTask = new Runnable() {
public void run() {
Spelling.mp.start();
}
};
final Handler mHandler = new Handler();
mHandler.postDelayed(mUpdateUITimerTask, i*1500);
}
}
#Override
protected void onDraw(Canvas canvas) {
int k;
// Drawing commands go here
width = canvas.getWidth();
height = canvas.getHeight();
arc.addArc(new RectF((width*.15f), (height*.15f), (width*.85f), (height*.4f)), 180,180);
tPaint.setStyle(Paint.Style.FILL_AND_STROKE);
tPaint.setColor(Color.RED);
tPaint.setTextSize(height * 0.1f);
tPaint.setTextAlign(Paint.Align.LEFT);
setBackgroundColor(Color.BLACK);
for (k = 0; k < j; k++){
char c = WORD.charAt(k);
String cs = Character.toString(c);
textToPrint+= cs;
textspace =(float) (k*(width/WORD.length())*.9);
canvas.drawTextOnPath(cs, arc, textspace , 0, tPaint);
}
if(j<WORD.length()){
j++;
}
}
}
Custom view will invalidate itself when is a part of a layout which for some reason redraw itself. Therefore you could envelop your code in onDraw() with a condition and a flag so that it draws your stuff only when the timer sets the flag and calls invalidate. After one letter is drawn then the flag shoud be set on false like:
if (drawLetter){
drawLetter = false;
/code...
}
However this also may need to be a sychronized block.
OnDraw should happen 60 times a second and not only when you are invalidating.
So maybe you need to update some class variables (when you are invalidating) and use those for your draw logic # OnDraw.