MainActivity.java
package edu.byuh.cis.cs203.hellocs203.sys; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { private LetiView lv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); lv = new LetiView(this); setContentView(lv); } @Override public void onDestroy() { super.onDestroy(); lv.saveDucks(); } }LetiView.java
package edu.byuh.cis.cs203.hellocs203.sys; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.Toast; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Scanner; import edu.byuh.cis.cs203.hellocs203.graphics.Duck; public class LetiView extends View { //private Duck donald; private List<Duck> flock; private boolean init; private Paint bluePaint; private Paint pinkPaint; private int howManyDucks; public /*static*/ class Timer extends Handler { public Timer() { sendMessageDelayed(obtainMessage(), 0); } @Override public void handleMessage(Message m) { //Log.d("CS203", "Hello, Altair!"); //donald.dance(); for (Duck d : flock) { d.dance(); } invalidate(); sendMessageDelayed(obtainMessage(), 100); } } public LetiView(Context c) { super(c); init = false; //donald = new Duck(getResources()); flock = new ArrayList<>(); loadDucks(); Toast t = Toast.makeText(c, "This is another factory example!", Toast.LENGTH_LONG); t.show(); bluePaint = new Paint(); bluePaint.setColor(Color.BLUE); bluePaint.setStyle(Paint.Style.FILL); bluePaint.setTextSize(60); bluePaint.setTextAlign(Paint.Align.CENTER); pinkPaint = new Paint(); pinkPaint.setColor(Color.rgb(255, 200, 200)); Timer tim = new Timer(); } private void makeDucks(int n) { for (int i=0; i<n; i++) { flock.add(new Duck(getResources())); } float w = getWidth(); float h = getHeight(); for (Duck d : flock) { d.resize(w); float x = (float)(Math.random()*(w-d.width())); float y = (float)(Math.random()*(h-d.height())); d.setPosition(x,y); } } @Override public void onDraw(Canvas c) { float w = c.getWidth(); float h = c.getHeight(); if (init == false) { //donald.resize(w); //donald.setPosition(w/2, h/2); makeDucks(howManyDucks); bluePaint.setStrokeWidth(w/50); init = true; } c.drawColor(Color.GREEN); c.drawRect(w/10, h/10, w*0.3f, h*0.4f, bluePaint); c.drawLine(w*0.8f, h*0.5f, w*0.5f, h*0.7f, bluePaint); c.drawCircle(w*0.3f, h*0.8f, w*0.1f, pinkPaint); c.drawText("General Conference was great!", w/2, h/2, bluePaint); //donald.draw(c); for (Duck d : flock) { d.draw(c); } } @Override public boolean onTouchEvent(MotionEvent m) { //this is a "local class"! //its scope is limited just to the onTouchEvent method. //it is invisible to all other methods in LetiView. /*class ClickOK implements DialogInterface.OnClickListener { @Override public void onClick(DialogInterface dialogInterface, int i) { makeDucks(5); } }*/ float x = m.getX(); float y = m.getY(); if (m.getAction() == MotionEvent.ACTION_DOWN) { //Log.d("CS203", "You just tapped at (" + x + "," + y + ")!"); List<Duck> doomed = new ArrayList<>(); for (Duck d : flock) { if (d.contains(x,y)) { //flock.remove(d); //break; doomed.add(d); } } for (Duck d : doomed) { flock.remove(d); } if (flock.isEmpty()) { //ClickOK ivan = new ClickOK(); AlertDialog.Builder ab = new AlertDialog.Builder(getContext()); ab.setTitle("Duck World 3000") .setMessage("Congratulations Captain! You have cleared the sector of all the ducks that were threatening our way of life. The federation is in need of a captain for a similar mission. Any volunteers?") .setCancelable(false) .setPositiveButton("Yes, sign me up!", (d, i) -> { howManyDucks += 5; makeDucks(howManyDucks); }) .setNegativeButton("No, I'm done.", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface d, int i) { Activity parent = (Activity)getContext(); parent.finish(); } }); AlertDialog box = ab.create(); box.show(); } } return true; } public void saveDucks() { try { FileOutputStream fos = getContext().openFileOutput("ducks.txt", Context.MODE_PRIVATE); String ivan = ""+howManyDucks; fos.write(ivan.getBytes()); fos.close(); } catch (IOException e) { //blissfully ignore } } private void loadDucks() { try { FileInputStream fis = getContext().openFileInput("ducks.txt"); Scanner s = new Scanner(fis); String lana = s.nextLine(); howManyDucks = Integer.parseInt(lana); s.close(); } catch (FileNotFoundException e) { howManyDucks = 5; } } }Duck.java
package edu.byuh.cis.cs203.hellocs203.graphics; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.RectF; import edu.byuh.cis.cs203.hellocs203.R; public class Duck { private Bitmap image; private RectF bounds; /** * Create a new duck * @param res the Android resources object */ public Duck(Resources res) { bounds = new RectF(); image = BitmapFactory.decodeResource(res, R.drawable.duck); } /** * scale the duck to its correct on-screen size * @param screenWidth the width of the screen in pixels */ public void resize(float screenWidth) { float duckSize = screenWidth * 0.2f; image = Bitmap.createScaledBitmap(image, (int)duckSize, (int)duckSize, true); bounds.set(0,0,duckSize, duckSize); } /** * Draw the duck at its predefined location * @param c the Android canvas object */ public void draw(Canvas c) { c.drawBitmap(image, bounds.left, bounds.top, null); } /** * Sets the center of the duck to (x,y) * @param x the new center x coordinate * @param y the new center y coordinate */ public void setPosition(float x, float y) { bounds.offsetTo(x,y); } public float width() { return bounds.width(); } public void dance() { float dx = 5-(float)(Math.random() * 10); float dy = 5-(float)(Math.random() * 10); bounds.offset(dx,dy); } public boolean contains(float x, float y) { return bounds.contains(x,y); } public float height() { return bounds.height(); } }