Федеральное агентство связи РФ Федеральное государственное бюджетное образовательное учреждение высшего образования «Сибирский государственный университет телекоммуникаций и информатики» (СибГУТИ) Лабораторная работа №3 по дисциплине «Программирование мобильных устройств» Выполнил: Группа: Последняя цифра пароля: 5 Вариант: 3 Проверил: Новосибирск, 2019 Задание Реализуйте прыгающий <объект>. Начальная позиция появления объекта определяется нажатием пальца по экрану. Объект падает с ускорением вниз, отражаясь от нижней границы экрана, и с незначительным смешением вправо. С каждым разом высота отскока объекта уменьшается, и когда объект практически остановится, он пропадает с экрана. Объектов может быть несколько, поэтому каждый должен обрабатываться в отдельном потоке приложения. (<объект> - Буква Вашей фамилии, после каждого нажития буква меняется на следующую, по окончанию Вы опять возвращаетесь на первую букву). Для примера <объект> - цифра восемь, направление падения схематично показано красным. Описание программы BounceItem BounceThread BounceView MainActivity Класс, определяющий объект одного символа, участвующего в анимации. Поток процесса отрисовки. Основное вью приложения, наследуется от SurfaceView. Основной активити. 2 Исходный код MainActivity.java package com.example.user.lab3_bounce; import import import import import import import android.content.DialogInterface; android.content.Intent; android.os.Bundle; android.app.Activity; android.support.v7.app.AlertDialog; android.util.Log; android.view.MenuItem; import java.text.DateFormat; import java.util.Date; public class MainActivity extends Activity { BounceView bounceView; private Boolean processStarted; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); processStarted = false; bounceView = new BounceView(this); setContentView(bounceView); processStarted = true; } @Override public boolean onOptionsItemSelected(MenuItem item) { try { switch (item.getItemId()) { case android.R.id.home: onBackPressed(); return true; default: return super.onOptionsItemSelected(item); } } catch (Exception ex) { Log.v(ex.getMessage(), "error"); } return super.onOptionsItemSelected(item); } @Override public void onStop() { try { super.onStop(); } catch (Exception ex) { Log.v(ex.getMessage(), "error"); } } @Override public void onBackPressed() { try { bounceView.pause(); } catch (Exception ex) { 3 Log.v(ex.getMessage(), "error"); } } @Override protected void onPause() { try { super.onPause(); if (processStarted) { bounceView.pause(); } } catch (Exception ex) { Log.v(ex.getMessage(), "error"); } } @Override protected void onResume() { try { super.onResume(); if (processStarted) { bounceView.resume(); } } catch (Exception ex) { Log.v(ex.getMessage(), "error"); } } @Override public void onDestroy() { try { super.onDestroy(); if (processStarted) { bounceView.pause(); } } catch (Exception ex) { Log.v(ex.getMessage(), "error"); } } } BounceView.java package com.example.user.lab3_bounce; import import import import import import import import import import android.annotation.SuppressLint; android.content.Context; android.graphics.Bitmap; android.graphics.BitmapFactory; android.graphics.Canvas; android.graphics.Color; android.util.Log; android.view.MotionEvent; android.view.SurfaceHolder; android.view.SurfaceView; import java.util.ArrayList; import java.util.List; public class BounceView extends SurfaceView { private long lastClick; 4 private private private private List<BounceItem> items = new ArrayList<>(); List<Integer> resources = new ArrayList<>(); Integer lastUsedResourceIndex; BounceThread bounceThread; public BounceView(Context context) { super(context); resources.add(R.drawable.i); resources.add(R.drawable.v); resources.add(R.drawable.a); resources.add(R.drawable.n); resources.add(R.drawable.o); resources.add(R.drawable.v); lastUsedResourceIndex = 0; try { bounceThread = new BounceThread(this); getHolder().addCallback(new SurfaceHolder.Callback() { @Override public void surfaceDestroyed(SurfaceHolder holder) { boolean retry = true; bounceThread.setRunning(false); while (retry) { try { bounceThread.join(); retry = false; } catch (InterruptedException e) { Log.v(e.getMessage(), "error"); } } } @Override public void surfaceCreated(SurfaceHolder holder) { bounceThread.setRunning(true); bounceThread.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } }); } catch (Exception ex) { Log.v(ex.getMessage(), "error"); } } @Override public void onDraw(Canvas canvas) { try { canvas.drawColor(Color.WHITE); @SuppressLint("DrawAllocation") List<BounceItem> bounceItemIdsToRemove = new ArrayList<>(); canvas.save(); for (int i = items.size() - 1; i >= 0; i--) { BounceItem item = items.get(i); 5 int screenH = getHeight() - item.ball.getHeight(); int screenW = getWidth() - item.ball.getWidth(); if ((item.Y != screenH) || (item.lastY != screenH)) { item.lastY = item.Y; if (item.Y == screenH) item.speed = -0.9f * item.speed; item.speed = item.speed + item.grav; float part1 = (item.speed * item.accel); float part2 = (item.grav * item.accel * item.accel / 2); item.Y = item.Y - part1 - part2; if (item.Y > screenH) item.Y = screenH; if (item.toRight) { item.X += 2; } else { item.X -= 2; } if (item.X >= screenW) { item.toRight = false; item.X = screenW; } if (item.X <= 0) { item.toRight = true; item.X = 0; } canvas.drawBitmap(item.ball, item.X, item.Y, null); } else { if (item.liveCounter >= 15) { bounceItemIdsToRemove.add(item); } else { item.liveCounter++; canvas.drawBitmap(item.ball, item.X, item.Y, null); } } } if (bounceItemIdsToRemove.size() > 0) { for (BounceItem item : bounceItemIdsToRemove) { items.remove(item); } } canvas.restore(); invalidate(); } catch (Exception ex) { Log.v(ex.getMessage(), "error"); } } private BounceItem createBounceItem(float x, float y, Bitmap ball) { BounceItem bounceItem = new BounceItem(); bounceItem.X = x; bounceItem.Y = y; bounceItem.lastY = y; bounceItem.ball = ball; bounceItem.accel = 0.1f; bounceItem.grav = -500f * 0.1f; 6 bounceItem.speed = 10f; bounceItem.toRight = true; return bounceItem; } @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { if (System.currentTimeMillis() - lastClick > 300) { lastClick = System.currentTimeMillis(); float x = event.getX(); float y = event.getY(); Integer lastUsedResource = resources.get(lastUsedResourceIndex); synchronized (getHolder()) { Bitmap ball = BitmapFactory.decodeResource(getResources(), lastUsedResource); BounceItem bounceItem = createBounceItem(x, y, ball); items.add(bounceItem); } Integer charsCount = resources.size(); if (lastUsedResourceIndex + 1 == charsCount) { lastUsedResourceIndex = 0; lastUsedResource = resources.get(lastUsedResourceIndex); } else { lastUsedResourceIndex++; lastUsedResource = resources.get(lastUsedResourceIndex); } } return true; } public void resume() { try { if (bounceThread != null) { bounceThread.setRunning(true); } } catch (Exception ex) { Log.v(ex.getMessage(), "error"); } } public void pause() { try { bounceThread.setRunning(false); boolean retry = true; while (retry) { try { bounceThread.join(); retry = false; } catch (InterruptedException e) { Log.v(e.getMessage(), "error"); } } } catch (Exception ex) { Log.v(ex.getMessage(), "error"); } } } 7 BounceThread.java package com.example.user.lab3_bounce; import import import import android.annotation.SuppressLint; android.graphics.Canvas; android.util.Log; android.view.SurfaceHolder; public class BounceThread extends Thread { private static final long FPS = 15; private BounceView view; private boolean running = false; BounceThread(BounceView view) { this.view = view; } public void setRunning(boolean run) { running = run; } @SuppressLint("WrongCall") @Override public void run() { long ticksPS = 1000 / FPS; long startTime; long sleepTime; while (running) { Canvas c = null; startTime = System.currentTimeMillis(); SurfaceHolder holder = view.getHolder(); try { c = holder.lockCanvas(); synchronized (view.getHolder()) { view.onDraw(c); } } finally { if (c != null) { holder.unlockCanvasAndPost(c); } } sleepTime = ticksPS - (System.currentTimeMillis() - startTime); try { if (sleepTime > 0) sleep(sleepTime); else sleep(10); } catch (Exception e) { Log.v(e.getMessage(), "error"); } } } } 8 Результаты работы программы 9