سؤال

ما أريد فعله هو رسم خط يتبع إصبعي. لقد قمت بإنشاء عرض مخصص ، ولدي onTouchEvent() انه يعمل انها تعمل.

يمكنني رسم خط ثابت في onDraw() الطريقة دون الكثير من المتاعب.

لست متأكدًا حقًا من كيفية الحصول على الخط لرسم مع تحرك إصبعي.

  public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            Log.e(TAG, " - DOWN -");
            Log.e(TAG, " getX: " + event.getX());
            break;
        }
        case MotionEvent.ACTION_UP: {
            Log.e(TAG, " - UP -");
            Log.e(TAG, " getX: " + event.getX());
            break;
        }
        }
        return true;
    }

أي تلميحات يا رفاق الذين كانوا يفعلون ذلك بعض الوقت يمكن أن تعطي؟

هل أحتاج إلى تعيين إحداثيات على onTouchEvent() وإبطال العرض باستمرار بحيث ترسم شرائح الخط الصغير؟

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

هل كانت مفيدة؟

المحلول

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

Action_down: موقف المتجر.

ACTION_MOVE: إذا كان الموضع مختلفًا عن الموضع المخزن ، فقم برسم خط من الموضع المخزن إلى الموضع الحالي ، وتحديث الموضع المخزن إلى التيار.

Action_up: توقف.

في bit action_move ، قد يكون من الجيد التحقق مما إذا كان الموضع لا يقل عن 2 أو 3 بكسل بعيدًا عن الموضع المخزن. إذا كنت ستخزن جميع نقاط المؤامرة ، حتى تتمكن من القيام بشيء مع البيانات لاحقًا ، فربما تزيد من ذلك إلى 10 بكسل حتى لا ينتهي بك الأمر بمئات النقاط لخط بسيط.

نصائح أخرى

هذا ما انتهى بي الأمر. نأمل أن يساعد هذا بعض المبتدئين الآخرين في البدء.

لدي فئة Sprite التي تمثل الكائن الذي أريد تحريكه على الشاشة:

   public class Sprite {
    private final String TAG = "Sprite";
    private Drawable drawable;
    private int x; // the X coordinate
    private int y; // the Y coordinate
    private boolean touched; // if droid is touched/picked up
    private Speed speed; // the speed with its directions

    public Sprite(Drawable drawable, int x, int y) {
        this.drawable = drawable;
        this.x = x;
        this.y = y;
        this.speed = new Speed();
    }

    public void draw(Canvas canvas) {
        drawable.setBounds(new Rect(x, y, x+drawable.getIntrinsicWidth(), y+drawable.getIntrinsicHeight()));
        drawable.draw(canvas);
    }

    public void move() {
        if (!touched) {
            x += (speed.getXv() * speed.getxDirection());
            y += (speed.getYv() * speed.getyDirection());
        }
    }

    public void handleActionDown(int eventX, int eventY) {
        if (eventX >= (x - bitmap.getWidth() / 2) && (eventX <= (x + bitmap.getWidth() / 2))) {
            if (eventY >= (y - bitmap.getHeight() / 2) && (y <= (y + bitmap.getHeight() / 2))) {
                // droid touched
                setTouched(true);
            } else {
                setTouched(false);
            }
        } else {
            setTouched(false);
        }
    }
}

ثم لدي حلقة لعبة رئيسية. هذا الحلقات من خلال ودعوة أساليب عرض وتحديث MainPanel التي تبدو هكذا:

    public void render(Canvas canvas) {
    canvas.drawColor(Color.BLACK);
    sprite.draw(canvas);
}

public void update() {
    sprite.move();
}

يتم التعامل مع موقف المكان الذي ستتحرك فيه العفريت في التقاط حدث الحركة:

        if (event.getAction() == MotionEvent.ACTION_MOVE) {
        // the gestures
        if (sprite.isTouched()) {
            sprite.setX((int) event.getX());
            sprite.setY((int) event.getY());
        }
    }

نأمل أن يكون هذا مفيدًا. إذا قطعت الكثير وكان هناك شيء لا تخبرني به.

الخطوة التالية ، جعل الكائن يتبع السطر!

يرتبط حدث اللمس بقائمة من عدد المؤشرات القابلة للاستعادة مثل ما يلي:

     int p = event.getPointerCount();

يمكن أن يتسبب التكرار على هذه ونقاط الرسم في ظهور خط مستمر

if (event.getAction() == MotionEvent.ACTION_MOVE
    || event.getAction() == MotionEvent.ACTION_DOWN) {

  int p = event.getPointerCount();
     for (int i = 0; i < p; i++) { 
       c.drawPoint(event.getX(i), event.getY(i), paint);
     }
}

على افتراض paint تم تعيينه بالفعل و c هو القماش ، الذي قد يحتاج إلى قفل (على سبيل المثال- في تطبيق متعدد القدامات) ، قبل الرسم عليه.

بالنسبة للمبتدئين ، سيساعدك هذا الرمز على إنشاء صورة رسومات الشعار المبتكرة وتصديرها إلى صورة PNG هنا هي رمز كامل وهذا فئة النشاط مع فئة عرض أيضا ..

public class MainActivity extends Activity {
    private Bitmap DrawBitmap;
    private Canvas mCanvas;
    private Path mPath;
    private Paint DrawBitmapPaint;
    RelativeLayout Rl;
    CustomView View;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        View = new CustomView(this);
        Rl = (RelativeLayout) findViewById(R.id.Rel);
        Rl.addView(View);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(getResources()
                .getColor(android.R.color.holo_green_dark));
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(20);

    }

    private Paint mPaint;

    public class CustomView extends View {

        @SuppressWarnings("deprecation")
        public CustomView(Context c) {

            super(c);
            Display Disp = getWindowManager().getDefaultDisplay();
            DrawBitmap = Bitmap.createBitmap(Disp.getWidth(), Disp.getHeight(),
                    Bitmap.Config.ARGB_4444);

            mCanvas = new Canvas(DrawBitmap);

            mPath = new Path();
            DrawBitmapPaint = new Paint(Paint.DITHER_FLAG);
        }

        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            setDrawingCacheEnabled(true);
            canvas.drawBitmap(DrawBitmap, 0, 0, DrawBitmapPaint);
            canvas.drawPath(mPath, mPaint);
            canvas.drawRect(mY, 0, mY, 0, DrawBitmapPaint);
        }

        private float mX, mY;
        private static final float TOUCH_TOLERANCE = 4;

        private void touch_start(float x, float y) {
            mPath.reset();
            mPath.moveTo(x, y);
            mX = x;
            mY = y;
        }

        private void touch_move(float x, float y) {
            float dx = Math.abs(x - mX);
            float dy = Math.abs(y - mY);
            if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
                mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
                mX = x;
                mY = y;
            }
        }

        private void touch_up() {
            mPath.lineTo(mX, mY);

            mCanvas.drawPath(mPath, mPaint);

            mPath.reset();
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX();
            float y = event.getY();

            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touch_start(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                touch_move(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                touch_up();
                invalidate();
                break;
            }
            return true;
        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        mPaint.setXfermode(null);
        switch (item.getItemId()) {
        case R.id.erase: 
               mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
               break;
        case R.id.DELETE: 
             View =  new CustomView(this);
               break;
        case R.id.draw: 
               mPaint.setXfermode(null);

               break;
        case R.id.Save:
            String pattern = "mm ss";
            SimpleDateFormat formatter = new SimpleDateFormat(pattern);
            String time = formatter.format(new Date());
            String path = ("/d-codepages" + time + ".png");

            File file = new File(Environment.getExternalStorageDirectory()
                    + path);

            try {
                DrawBitmap.compress(Bitmap.CompressFormat.PNG, 100,
                        new FileOutputStream(file));
                Toast.makeText(this, "File Saved ::" + path, Toast.LENGTH_SHORT)
                        .show();
            } catch (Exception e) {
                Toast.makeText(this, "ERROR" + e.toString(), Toast.LENGTH_SHORT)
                        .show();
            }

        }
        return super.onOptionsItemSelected(item);
    }

}

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

لقد مر بعض الوقت ولكن هذا المنشور لا يزال يحصل على بعض المشاهدات ، لذلك اعتقدت أنني سأقوم بنشر بعض الأشياء المفيدة:

البرنامج التعليمي حول كيفية جعل كائن اتبع الخط:http://www.rengelbert.com/tutorial.php؟id=182

هذا محرك لعبة مجاني جيد يستخدمه البرنامج التعليمي أعلاه أيضًا:http://libgdx.badlogicgames.com/

آمل أن يساعد هذا شخص ما!

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