Vous êtes sur la page 1sur 9

package course.labs.

GraphicsLab; import import import import import import import import import import import import import import import import import import import import import import import java.util.Random; java.util.concurrent.Executors; java.util.concurrent.ScheduledExecutorService; java.util.concurrent.ScheduledFuture; java.util.concurrent.TimeUnit; android.app.Activity; android.content.Context; android.graphics.Bitmap; android.graphics.BitmapFactory; android.graphics.Canvas; android.graphics.Paint; android.media.AudioManager; android.media.SoundPool; android.media.SoundPool.OnLoadCompleteListener; android.os.Bundle; android.util.Log; android.view.GestureDetector; android.view.Menu; android.view.MenuItem; android.view.MotionEvent; android.view.View; android.view.ViewGroup; android.widget.RelativeLayout;

public class BubbleActivity extends Activity { // These variables are for testing purposes, do not modify private final static int RANDOM = 0; private final static int SINGLE = 1; private final static int STILL = 2; private static int speedMode = RANDOM; private static final int MENU_STILL = Menu.FIRST; private static final int MENU_SINGLE_SPEED = Menu.FIRST + 1; private static final int MENU_RANDOM_SPEED = Menu.FIRST + 2; private static final String TAG = "Lab-Graphics"; // Main view private RelativeLayout mFrame; // Bubble image private Bitmap mBitmap; // Display dimensions private int mDisplayWidth, mDisplayHeight; // Sound variables // AudioManager private AudioManager mAudioManager; // SoundPool private SoundPool mSoundPool; // ID for the bubble popping sound private int mSoundID; // Audio volume private float mStreamVolume;

// Gesture Detector private GestureDetector mGestureDetector; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Set up user interface mFrame = (RelativeLayout) findViewById(R.id.frame); // Load basic bubble Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawabl e.b64); } @Override protected void onResume() { super.onResume(); // Manage bubble popping sound // Use AudioManager.STREAM_MUSIC as stream type mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE); mStreamVolume = (float) mAudioManager .getStreamVolume(AudioManager.STREAM_MUSIC) / mAudioManager.getStreamMaxVolume(AudioManager. STREAM_MUSIC); // TODO2 - make a new SoundPool, allowing up to 10 streams mSoundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0); ; // TODO2 - set a SoundPool OnLoadCompletedListener that calls // setupGestureDetector() mSoundPool.setOnLoadCompleteListener(new OnLoadCompleteListener( ) { @Override public void onLoadComplete(SoundPool soundPool, int samp leId, int status) { setupGestureDetector(); } }); // TODO2 - load the sound from res/raw/bubble_pop.wav mSoundID = mSoundPool.load(this, R.raw.bubble_pop, 1); } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { // Get the size of the display so this view knows where borders are

mDisplayWidth = mFrame.getWidth(); mDisplayHeight = mFrame.getHeight(); } } // Set up GestureDetector private void setupGestureDetector() { mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() { // If a fling gesture starts on a BubbleView then change the // BubbleView's velocity @Override public boolean onFling(MotionEvent event1, MotionEvent e vent2, float velocityX, float velocityY) { // TODO2 - Implement onFling actions. // You can get all Views in mFrame using the // ViewGroup.getChildCount() method int numberOfBubbles = mFrame.getChildCount(); log("no of bubbles = " + numberOfBubbles); for (int i = 0; i < numberOfBubbles; i++) { BubbleView bubbleView = (BubbleView) mFr ame.getChildAt(i); if (bubbleView.intersects(event1.getRawX (), event1.getRawY())) { bubbleView.deflect(velocityX, ve locityY); return true; } } return false; } // If a single tap intersects a BubbleView, then pop the BubbleView // Otherwise, create a new BubbleView at the tap's locat ion and add // it to mFrame. You can get all views from mFrame with // ViewGroup.getChildAt() @Override public boolean onSingleTapConfirmed(MotionEvent event) { // TODO2 - Implement onSingleTapConfirmed action s. // You can get all Views in mFrame using the // ViewGroup.getChildCount() method for (int i = 0; i < mFrame.getChildCount(); i++) {

BubbleView b = (BubbleView) mFrame.getCh ildAt(i); if (b.intersects(event.getX(), event.get Y())) { b.stop(true); return true; } else { BubbleView newBubble = new Bubbl eView( BubbleActivity.t his, event.getX(), event.getY()); mFrame.addView(newBubble); } } return false; } }); } @Override public boolean onTouchEvent(MotionEvent event) { // TODO2 - delegate the touch to the gestureDetector mGestureDetector.onTouchEvent(event); return false; } @Override protected void onPause() { // TODO2 - Release all SoundPool resources mSoundPool.unload(mSoundID); mSoundPool.release(); mSoundPool = null; super.onPause(); } // BubbleView is a View that displays a bubble. // This class handles animating, drawing, popping amongst other actions. // A new BubbleView is created for each bubble on the display private class BubbleView extends View { private private private private private private static final int BITMAP_SIZE = 64; static final int REFRESH_RATE = 40; final Paint mPainter = new Paint(); ScheduledFuture<?> mMoverFuture; int mScaledBitmapWidth; Bitmap mScaledBitmap;

// location, speed and direction of the bubble private float mXPos, mYPos, mDx, mDy; private long mRotate, mDRotate;

public BubbleView(Context context, float x, float y) { super(context); log("Creating Bubble at: x:" + x + " y:" + y); // Create a new random number generator to // randomize size, rotation, speed and direction Random r = new Random(); // Creates the bubble bitmap for this BubbleView createScaledBitmap(r); // Adjust position to center the bubble under user's fin ger mXPos = x - mScaledBitmapWidth / 2; mYPos = y - mScaledBitmapWidth / 2; // Set the BubbleView's speed and direction setSpeedAndDirection(r); // Set the BubbleView's rotation setRotation(r); mPainter.setAntiAlias(true); } private void setRotation(Random r) { if (speedMode == RANDOM) { // TODO2 - set rotation in range [1..3] mDRotate = 1 + r.nextInt(3 - 1 + 1); } else { mDRotate = 0; } } private void setSpeedAndDirection(Random r) { // Used by test cases switch (speedMode) { case SINGLE: // Fixed speed mDx = 10; mDy = 10; break; case STILL: // No speed mDx = 0; mDy = 0; break; default:

// TODO2 - Set movement direction and speed // Limit movement speed in the x and y // direction to [-3..3]. mDx = -3 + r.nextInt(3 - (-3) + 1); mDy = -3 + r.nextInt(3 - (-3) + 1); break; } } private void createScaledBitmap(Random r) { if (speedMode != RANDOM) { mScaledBitmapWidth = BITMAP_SIZE * 3; } else { // TODO2 - set scaled bitmap size in range [1..3 ] * BITMAP_SIZE mScaledBitmapWidth = (1 + r.nextInt(3 - 1 + 1)) * BITMAP_SIZE; } // TODO2 - create the scaled bitmap using size set above mScaledBitmap = Bitmap.createScaledBitmap(mBitmap, mScaledBitmapWidth, mScaledBitmapWidth, false); } // Start moving the BubbleView & updating the display private void start() { // Creates a WorkerThread ScheduledExecutorService executor = Executors .newScheduledThreadPool(1); // Execute the run() in Worker Thread every REFRESH_RATE // milliseconds // Save reference to this job in mMoverFuture mMoverFuture = executor.scheduleWithFixedDelay(new Runna ble() { @Override public void run() { // TODO2 - implement movement logic. // Each time this method is run the Bubb leView should // move one step. If the BubbleView exit s the display, // stop the BubbleView's Worker Thread. // Otherwise, request that the BubbleVie w be redrawn. System.out.println("inside start()"); if (moveWhileOnScreen()) { System.out.println("inside moveW hileOnScreen()"); BubbleView.this.postInvalidate() ;

} else { System.out.println("inside ELSE [moveWhileOnScreen()]"); BubbleView.this.stop(false); } } }, 0, REFRESH_RATE, TimeUnit.MILLISECONDS); } private synchronized boolean intersects(float x, float y) { // TODO2 - Return true if the BubbleView intersects posi tion (x,y) return (((mXPos <= x) && (x <= mXPos + mScaledBitmapWidt h)) && ((mYPos <= y) && (y <= mYPos + mScaledBitmapWidth))); } // Cancel the Bubble's movement // Remove Bubble from mFrame // Play pop sound if the BubbleView was popped private void stop(final boolean popped) { if (null != mMoverFuture && mMoverFuture.cancel(true)) { // This work will be performed on the UI Thread mFrame.post(new Runnable() { @Override public void run() { // TODO2 - Remove the BubbleView from mFrame mFrame.removeView(BubbleView.thi s); if (popped) { log("Pop!"); // TODO2 - If the bubble was popped by user, // play the popping soun d mSoundPool.play(mSoundID , mStreamVolume, mStreamV olume, 1, 0, 1.0f); } log("Bubble removed from view!") ; } }); } } // Change the Bubble's speed and direction private synchronized void deflect(float velocityX, float velocit

yY) { log("velocity X:" + velocityX + " velocity Y:" + velocit yY); // TODO2 - set mDx and mDy to be the new velocities divi ded by the // REFRESH_RATE mDx = velocityX / REFRESH_RATE; mDy = velocityY / REFRESH_RATE; } // Draw the Bubble at its current location @Override protected synchronized void onDraw(Canvas canvas) { // TODO2 - save the canvas canvas.save(); // TODO2 - increase the rotation of the original image b y mDRotate mRotate += mDRotate; // TODO2 Rotate the canvas by current rotation canvas.rotate(mRotate); // TODO2 - draw the bitmap at it's new location canvas.rotate(mRotate, mXPos + mScaledBitmapWidth / 2, m YPos + mScaledBitmapWidth / 2); canvas.drawBitmap(mScaledBitmap, mXPos, mYPos, mPainter) ; // TODO2 - restore the canvas canvas.restore(); } private synchronized boolean moveWhileOnScreen() { // TODO2 - Move the BubbleView // Returns true if the BubbleView has exited the screen mXPos += mDx; mYPos += mDy; return isOutOfView(); } private boolean isOutOfView() { // TODO2 - Return true if the BubbleView has exited the screen if (mXPos > mDisplayWidth || mYPos > mDisplayHeight || mXPos + mScaledBitmapWidth < 0 || mYPos + mScaledBitmapWidth < 0) { return true; } else { return false;

} } } // Do not modify below here @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); menu.add(Menu.NONE, MENU_STILL, Menu.NONE, "Still Mode"); menu.add(Menu.NONE, MENU_SINGLE_SPEED, Menu.NONE, "Single Speed Mode"); menu.add(Menu.NONE, MENU_RANDOM_SPEED, Menu.NONE, "Random Speed Mode"); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case MENU_STILL: speedMode = STILL; return true; case MENU_SINGLE_SPEED: speedMode = SINGLE; return true; case MENU_RANDOM_SPEED: speedMode = RANDOM; return true; default: return super.onOptionsItemSelected(item); } } private static void log(String message) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } Log.i(TAG, message); } }

Vous aimerez peut-être aussi