كيفية رسم الكثير من الصور النقطية على الشاشة في لعبة الروبوت من دون بطء الأداء

StackOverflow https://stackoverflow.com/questions/1430741

  •  07-07-2019
  •  | 
  •  

سؤال

وأريد أن لعبة تقوم البلاط لالروبوت. في هذه اللحظة أنا رسم كل البلاط كصورة نقطية مستقلة. لدي كبير للحلقة الذي يقرأ من سلسلة وتوجه البلاط مختلفة اعتمادا على ما يجده الطابع رسم المستوى.

ولقد سمح لي للمستخدم التمرير الشاشة باستخدام الإيماءات التمرير. لكن اللعبة بطيئة جدا. فإنه يأخذ وقتا طويلا لتحديث الشاشة بعد تمرير المستخدم. أفترض هذا هو لأنه يحتوي على رسم الصورة النقطية كل البلاط على حدة.

وماذا سيكون أسرع طريقة لرسم المستوى؟ كنت أفكر أتمكن من دمج كل البلاط إلى نقطية واحدة. لكني لا أعرف كيفية القيام بذلك. أي أفكار؟

وعلى أية حال هنا هو رمز بلادي حتى تتمكن من رؤية المشكلة:

package org.example.tutorial2d;

import android.app.Activity;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.GestureDetector.OnGestureListener;

import org.example.tutorial2d.Panel;

public class Tutorial2D extends Activity implements OnGestureListener {

GestureDetector gestureScanner;
Panel main;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    gestureScanner = new GestureDetector(this);

    //requestWindowFeature(Window.FEATURE_NO_TITLE);       
    main = new Panel(this);
    setContentView(main);       

}

@Override
public boolean onTouchEvent(MotionEvent me)
{
 return gestureScanner.onTouchEvent(me);
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
{
 main.handleScroll(distanceX,distanceY);
 return true;
}

////////////////////
///////////////////
//////////////////
@Override
public boolean onDown(MotionEvent e)
{
 return true;
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
{
 return true;
}

@Override
public void onLongPress(MotionEvent e){    }

@Override
public void onShowPress(MotionEvent e) {   }    

@Override
public boolean onSingleTapUp(MotionEvent e)    
{
 return true;
}
////////////////////
///////////////////
//////////////////
}

والفئة التي يعمل كل عمل:

package org.example.tutorial2d;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.View;
import org.example.tutorial2d.Point;

public class Panel extends View {

private int scrollX = 0;
private int scrollY = 0;

public Panel(Context context)
{
    super(context);
}

@Override
public void onDraw(Canvas canvas)
{
    /*Bitmap scratch;
    //Drawable scratch;
    //scratch = getContext().getResources().getDrawable(
    //        R.drawable.icon);
    canvas.drawColor(Color.BLACK);
    //scratch.draw(canvas);
    int origin = 0;
    scratch = BitmapFactory.decodeResource(getResources(), R.drawable.horizontal5);
    canvas.drawBitmap(scratch, origin, origin, null);
    int width = scratch.getWidth();
    int height = scratch.getHeight();
    scratch = BitmapFactory.decodeResource(getResources(), R.drawable.room4entrynesw3x3);
    canvas.drawBitmap(scratch, origin + width, origin - 32, null);
    */

    String sucide_mission = 
"                  wwwww\n" +
"                  wfffw\n" +
"                  wfffw\n" +
"                  wfffw\n" + 
"                  wwfww\n" +
"                   wfw\n" + 
"                   wfw\n" +
"                   wfw\n" +
"             wwwwwwwfwwwwwfw\n" +
"             wfffffffffffffw\n" +
"             wfwwwwwfwwwwwfw\n" +
"     wwwww   wfw   wfw   wfw\n" +
"wwwwwwfffwwwwwfwwwwwfwwwwwfw\n" +
"fffffffffffffffffffffffffffw\n" +
"wwwwwwfffwwwwwwwwwwwfwwwwwfw\n" +
"     wwfww         wfw\n" +
"      wfw          wfw\n" +
"      wfw          wfw\n" +
"      wfw          wfw\n" +
"      wfw          wfw\n" +
"     wwfww         wfw\n" +
"     wfffwwfw      fff\n" +
"     wffffffw      www\n" +
"     wfffwwfw\n" +
"     wwwww";

    canvas.drawColor(Color.BLACK);
    int x = 0, y = 0;

    for (int i = 0; i < sucide_mission.length(); i++)
    {
        Bitmap tileImage;
        char tile = sucide_mission.charAt(i);

        Log.d("Draw tiles", Character.toString(tile) + " " + x + "," + y);

        switch (tile)
        {
            case 'w':
                if (x < tileImage = BitmapFactory.decodeResource(getResources(), R.drawable.walla);
                canvas.drawBitmap(tileImage, x - scrollX, y - scrollY, null);
                x += 32;
                break;
            case 'f':
                tileImage = BitmapFactory.decodeResource(getResources(), R.drawable.floore);
                canvas.drawBitmap(tileImage, x - scrollX, y - scrollY, null);
                x += 32;
                break;
            case ' ':
                x += 32;
                break;
            case '\n':
                y += 32;
                x = 0;
                break;
        }

    }

    //canvas.drawBitmap(adapt, 0, 0, paint);
    //canvas.drawBitmap(corner, origin -scrollX , origin -scrollY, paint);

}

 public void handleScroll(float distX, float distY)
 {
      // X-Axis ////////////////////////////////

      if(distX > 6.0)
      {
           if(scrollX < 460)
           {
                scrollX += 30;
           }
      }
      else if(distX < -6.0)
      {
           if(scrollX >= 30)
           {
                scrollX -= 30;
           }
      }
      ////////////////////////////////////////////

      // Y-AXIS //////////////////////////////////
      if(distY > 6.0)
      {
           if(scrollY < 100)
           {
                scrollY += 30;
           }
      }
      else if(distY < -6.0)
      {
           if(scrollY >= 30)
           {
                scrollY -= 30;
           }
      }              
      ////////////////////////////////////////////

      if((scrollX <= 480) && (scrollY <= 120))
      {
           //adapt = Bitmap.createBitmap(bmp, scrollX, scrollY, 320, 480);
           invalidate();
      }
 }
}
هل كانت مفيدة؟

المحلول

ويبدو أنك تقوم بإنشاء مثيل جديد من كل صورة نقطية لكل البلاط المقدمة. ربما بدلا من القيام بذلك، يمكنك إنشاء حالة واحدة لكل نوع البلاط؟ مثلا:

private Bitmap wallTile = BitmapFactory.decodeResource(getResources(), R.drawable.walla);
private Bitmap floorTile = BitmapFactory.decodeResource(getResources(), R.drawable.floore);

وثم إعادة استخدام نفس المثال البلاط في كل مرة يتم سحب البلاط. إذا لم تنجح هذه العملية، يجب عليك ان تضع في نوع من قياس الأداء لمعرفة ما هو الجزء من قانون يأخذ وقتا أطول، وتقليل كمية من المرات يتم تشغيل هذا الرمز، أو محاولة لتقليص عليه.

تنويه: أنا لست مبرمج الروبوت

نصائح أخرى

والمشكلة واضحة جدا. كنت مجرد تسريب الكثير الجحيم من الذاكرة. نلقي نظرة في LogCat وسترى ما أعنيه. 1. NEVER تخصيص سلاسل كل إطار. فهي غير قابلة للتغيير وذلك في كل عملية مع سلاسل يساوي تسرب الذاكرة. استخدام بدلا من ذلك شار بسيط [] الكائن الذي قمت بتعديل. 2. التوقف عن خلق الكائنات نقطية مرارا وتكرارا. أعتقد أن طريقة DecodeBitmap يخصص داخليا كائن نقطية لكل المكالمة. انها سيئة للقيام بذلك كل إطار.

وكقاعدة عامة من الإبهام -> تسرب الذاكرة وانها الصديق في GC والعمليات مكلفة جدا أن تجنبها عند رسم

.

ولقد مبرمجة أبدا لالروبوت من قبل، لذلك لست متأكدا 100٪ حول ما يحدث تحت الأغطية هناك، ولكن على افتراض أن:

BitmapFactory.decodeResource(getResources(), R.drawable.walla);

وهذا الشيء من التعليمات البرمجية يذهب وحمولة تصل نقطية في الذاكرة، يبدو أنك إعادة كل صورة نقطية كما كنت استدراجه.

وماذا فعلت عندما تطوير الألعاب الصغيرة في الماضي، عندما تذهب لتحميل المستوى، والعمل على كل الموارد التي ستحتاج ثم تحميلها ما يصل إلى الذاكرة مرة واحدة، ثم إعادة استخدامها.

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MapLoader extends SurfaceView implements SurfaceHolder.Callback,
    Runnable {

SurfaceHolder holder;
Thread thread;

Bitmap grass = BitmapFactory.decodeResource(getResources(),
        R.drawable.tilemapdemo);
boolean running = false;

int[][] grassCoords = new int[][] { { 0, 16, 32, 48, 64 },
        { 0, 16, 32, 48, 64 }, { 0, 16, 32, 48, 64 },
        { 0, 16, 32, 48, 64 }, { 0, 16, 32, 48, 64 } };

public MapLoader(Context context, int width, int height) {
    super(context);

    holder = getHolder();
    holder.addCallback(this);
}

public MapLoader(Context context, AttributeSet attrs) {
    super(context, attrs);

    holder = getHolder();
    holder.addCallback(this);
}

public MapLoader(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    holder = getHolder();
    holder.addCallback(this);
}

public void pause() {
    running = false;

    while (running) {
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        break;
    }
    thread = null;
}

public void resume() {
    running = true;
    thread = new Thread(this);
    thread.start();

}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {

    running = true;
    thread = new Thread(this);
    thread.start();

}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    Canvas c = holder.lockCanvas();
    draw(c);
    holder.unlockCanvasAndPost(c);

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {

}

@Override
public void run() {

    while (running == true) {

        // performs drawing to the canvas
        if (!holder.getSurface().isValid()) {

            continue;
        }

        Canvas c = holder.lockCanvas();

        int x = 0;
        int y = 0;

        for (x = 0; x < grassCoords.length; x += grass.getWidth()) {

            for (y = 0; y < grassCoords.length; y += grass.getHeight()) {

                c.drawBitmap(grass, x, y, null);
            }

        }

        holder.unlockCanvasAndPost(c);

    }

}

و}

وفكرة أخرى، من غير مبرمج، وربما إنشاء خلفية البلاط الكبيرة التي مخطوطات، وما إلى ذلك .. والطبقة العليا الثانية حيث يتم رسم العناصر المنقولة (لاعبين، مجلس الشعب، والبنود) على رأس الخلفية. لذا يجب أن يكون التمرير أسرع وأقل الشامل (إعادة) التقديم. أتصور أن هذا قد يكون أكثر الموارد مكثفة من الرجوع البلاط أصدرت بالفعل (كما ورد في اقتراح آخر أعلاه) .. ولكن قد لا يكون، عليك أن تقدم له رصاصة ونرى. : -)

وماذا عن تحريك منظر كامل عند تمرير المستخدم. عند التمرير في ويندوز، كنت في الواقع نقل الإطار في الاتجاه المعاكس أن تتصور. كنت انزل، والنوافذ يتحرك صعودا ..

وأنا واثق تماما هل يمكن جمع كل العناصر في طريقة عرض (الشبكة) ونقل رأي كامل .. تقديم الصور من الشاشة (أسرع) والانتقال بها حسب الحاجة ..

وهناك أمثلة المتاحة .. وأنا أعلم أنك يمكن أن تحصل على كل رمز الشاشة الرئيسية، ومخطوطات من اليسار إلى اليمين. قد يكون شيئا للنظر في. أنا متأكد تماما فعلوا ذلك التطبيق حق.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top