From d711a93fbf69b8de11459ded1e4e0f5e689f6078 Mon Sep 17 00:00:00 2001 From: Ruben Date: Wed, 7 Sep 2016 23:32:28 +0100 Subject: [PATCH] Score bar, level introductions and new interactive menu --- .idea/misc.xml | 2 +- app/src/main/AndroidManifest.xml | 7 +- .../emotionhero/GamingActivity.java | 44 ++- .../emotionhero/IntroActivity.java | 2 +- .../emotionhero/MenuActivity.java | 2 +- .../emotionhero/MirrorMenuActivity.java | 329 ++++++++++++++++++ .../rubenvandeven/emotionhero/Scenario.java | 20 ++ .../emotionhero/ScenarioView.java | 88 +++-- .../emotionhero/StoryDialogFragment.java | 54 +++ .../main/res/layout/activity_mirror_menu.xml | 102 ++++++ app/src/main/res/values/strings.xml | 2 +- 11 files changed, 612 insertions(+), 40 deletions(-) create mode 100644 app/src/main/java/com/rubenvandeven/emotionhero/MirrorMenuActivity.java create mode 100644 app/src/main/java/com/rubenvandeven/emotionhero/StoryDialogFragment.java create mode 100644 app/src/main/res/layout/activity_mirror_menu.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index 1b77328..bd04605 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -37,7 +37,7 @@ - + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a13252b..c66d819 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -51,9 +51,10 @@ - - + + \ No newline at end of file diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/GamingActivity.java b/app/src/main/java/com/rubenvandeven/emotionhero/GamingActivity.java index a52374f..393860f 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/GamingActivity.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/GamingActivity.java @@ -2,6 +2,8 @@ package com.rubenvandeven.emotionhero; import android.Manifest; import android.annotation.TargetApi; +import android.app.Dialog; +import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.media.AudioAttributes; @@ -9,6 +11,8 @@ import android.media.AudioManager; import android.media.SoundPool; import android.os.Build; import android.support.v4.app.ActivityCompat; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; @@ -63,6 +67,8 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL protected Player player; + protected boolean isStarted = false; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -88,6 +94,8 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL public void onMeasure(int widthSpec, int heightSpec) { int measureWidth = MeasureSpec.getSize(widthSpec); int measureHeight = MeasureSpec.getSize(heightSpec); + int maxWidth = GamingActivity.this.getWindow().getDecorView().getWidth(); + int maxHeight = GamingActivity.this.getWindow().getDecorView().getHeight(); int width; int height; if (previewHeight == 0 || previewWidth == 0) { @@ -105,6 +113,18 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL height = measureHeight; } } + + // make sure we fill the screen! + if(width < maxWidth) { + float ratio = (float)maxWidth/width; + width = maxWidth; + height = (int) (ratio * height); + } + if(height < maxHeight) { + float ratio = (float)maxHeight/height; + width = (int) (ratio * width); + height = maxHeight; + } setMeasuredDimension(width,height); // setMeasuredDimension(1,1); // this DOES increase performance.... } @@ -113,8 +133,8 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL // RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(1,1); params.addRule(RelativeLayout.CENTER_IN_PARENT,RelativeLayout.TRUE); // 10% margin: - params.leftMargin = (int) 120; - params.rightMargin = params.leftMargin; +// params.leftMargin = (int) 120; +// params.rightMargin = params.leftMargin; cameraPreview.setLayoutParams(params); videoLayout.addView(cameraPreview,0); @@ -125,18 +145,28 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL currentScenario.init(); // "start the clock"... scenarioView = new ScenarioView(this, currentScenario); + scenarioView.drawOverlay = true; RelativeLayout.LayoutParams scenarioViewParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); videoLayout.addView(scenarioView, 1, scenarioViewParams); createSoundPool(); // instantiate SoundPool in sound soundIds.put(SOUND_SCORE, sound.load(this, R.raw.score2, 1)); + StoryDialogFragment storyDialog = new StoryDialogFragment(); + storyDialog.show(getSupportFragmentManager(), "StoryDialog"); + + } + + public void startGame() { + isStarted = true; + startDetector(); } @Override protected void onResume() { super.onResume(); - startDetector(); + if(isStarted) + startDetector(); // should resume 'on face detection started' } @@ -172,10 +202,10 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL detector.setLicensePath("emotionhero_dev.license"); detector.setDetectAllEmotions(true); - detector.setDetectAllAppearances(false); + detector.setDetectAllAppearances(true); detector.setDetectAllEmojis(false); detector.setDetectAllExpressions(true); - detector.setMaxProcessRate(20); + detector.setMaxProcessRate(12); detector.setImageListener(this); detector.setOnCameraEventListener(this); @@ -264,7 +294,9 @@ public class GamingActivity extends AppCompatActivity implements Detector.ImageL public void onFaceDetectionStarted() { setText("START!"); - currentScenario.start(); + + if(isStarted) + currentScenario.start(); } @Override diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/IntroActivity.java b/app/src/main/java/com/rubenvandeven/emotionhero/IntroActivity.java index 605a342..0b448e7 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/IntroActivity.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/IntroActivity.java @@ -89,7 +89,7 @@ public class IntroActivity extends AppCompatActivity { public void continueToMenu() { continueHandler.removeCallbacks(continueRunnable); - Intent intent = new Intent(this, MenuActivity.class); + Intent intent = new Intent(this, MirrorMenuActivity.class); finish(); startActivity(intent); //disable distracting transition when going to menu diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/MenuActivity.java b/app/src/main/java/com/rubenvandeven/emotionhero/MenuActivity.java index d17df2c..3863b41 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/MenuActivity.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/MenuActivity.java @@ -87,7 +87,7 @@ public class MenuActivity extends AppCompatActivity { public void onClick(View v) { loadGameDialog = ProgressDialog.show(MenuActivity.this, "", MenuActivity.this.getResources().getString(R.string.load_game_activity), true); - Intent intent = new Intent(MenuActivity.this, GamingActivity.class); + Intent intent = new Intent(MenuActivity.this, MirrorMenuActivity.class); startActivity(intent); } diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/MirrorMenuActivity.java b/app/src/main/java/com/rubenvandeven/emotionhero/MirrorMenuActivity.java new file mode 100644 index 0000000..a08c532 --- /dev/null +++ b/app/src/main/java/com/rubenvandeven/emotionhero/MirrorMenuActivity.java @@ -0,0 +1,329 @@ +package com.rubenvandeven.emotionhero; + +import android.Manifest; +import android.animation.ArgbEvaluator; +import android.animation.ValueAnimator; +import android.app.ProgressDialog; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Color; +import android.graphics.Typeface; +import android.support.v4.app.ActivityCompat; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.util.Log; +import android.view.SurfaceView; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.affectiva.android.affdex.sdk.Frame; +import com.affectiva.android.affdex.sdk.detector.CameraDetector; +import com.affectiva.android.affdex.sdk.detector.Detector; +import com.affectiva.android.affdex.sdk.detector.Face; + +import org.w3c.dom.Text; + +import java.util.List; + +public class MirrorMenuActivity extends AppCompatActivity implements Detector.ImageListener, CameraDetector.CameraEventListener, Detector.FaceListener { + + final static String LOG_TAG = "EmotionHero-Mirror"; + + private CameraDetector detector; + + + final int PERMISSIONS_REQUEST_CAMERA = 1; + + int previewWidth = 0; + int previewHeight = 0; + + SurfaceView cameraPreview; + ScenarioView scenarioView; + TextView messageText; + + boolean has_camera_permission = false; + + ProgressDialog loadGameDialog; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + if(getSupportActionBar() != null) { + getSupportActionBar().hide(); + } + setContentView(R.layout.activity_mirror_menu); + + RelativeLayout videoContentLayout = (RelativeLayout) findViewById(R.id.videoContent); + ImageView logoEmotionHero = (ImageView) findViewById(R.id.logoEmotionHero); + messageText = (TextView) findViewById(R.id.messageText); + final TextView startButton = (TextView) findViewById(R.id.startButton); + TextView highscoresButton = (TextView) findViewById(R.id.highscoresButton); + TextView creditsButton = (TextView) findViewById(R.id.creditsButton); + + Typeface font = Typeface.createFromAsset(getAssets(), "unifont-9.0.02.ttf"); + startButton .setTypeface(font); + highscoresButton .setTypeface(font); + creditsButton .setTypeface(font); + + //We create a custom SurfaceView that resizes itself to match the aspect ratio of the incoming camera frames + cameraPreview = new SurfaceView(this) { + @Override + public void onMeasure(int widthSpec, int heightSpec) { + int measureWidth = MeasureSpec.getSize(widthSpec); + int measureHeight = MeasureSpec.getSize(heightSpec); + int maxWidth = MirrorMenuActivity.this.getWindow().getDecorView().getWidth(); + int maxHeight = MirrorMenuActivity.this.getWindow().getDecorView().getHeight(); + int width; + int height; + if (previewHeight == 0 || previewWidth == 0) { + width = measureWidth; + height = measureHeight; + } else { + float viewAspectRatio = (float)measureWidth/measureHeight; + float cameraPreviewAspectRatio = (float) previewWidth/previewHeight; + + if (cameraPreviewAspectRatio > viewAspectRatio) { + width = measureWidth; + height =(int) (measureWidth / cameraPreviewAspectRatio); + } else { + width = (int) (measureHeight * cameraPreviewAspectRatio); + height = measureHeight; + } + } + + // make sure we fill the screen! + if(width < maxWidth) { + float ratio = (float)maxWidth/width; + width = maxWidth; + height = (int) (ratio * height); + } + if(height < maxHeight) { + float ratio = (float)maxHeight/height; + width = (int) (ratio * width); + height = maxHeight; + } + + setMeasuredDimension(width,height); + } + }; + RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); +// RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(1,1); + params.addRule(RelativeLayout.CENTER_IN_PARENT,RelativeLayout.TRUE); + // 10% margin: +// params.leftMargin = (int) 120; +// params.rightMargin = params.leftMargin; + cameraPreview.setLayoutParams(params); + videoContentLayout.addView(cameraPreview,0); + + scenarioView = new ScenarioView(this, null); + RelativeLayout.LayoutParams scenarioViewParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + videoContentLayout.addView(scenarioView, 1, scenarioViewParams); + + scenarioView.drawOverlay = true; + scenarioView.noFace = true; + + Animation anim = new AlphaAnimation(0.0f, 1.0f); + anim.setDuration(1000); //You can manage the blinking time with this parameter + anim.setStartOffset(20); + anim.setRepeatMode(Animation.REVERSE); + anim.setRepeatCount(Animation.INFINITE); + logoEmotionHero.startAnimation(anim); + + Integer colorFrom = getResources().getColor(R.color.textPrimary); + Integer colorTo = getResources().getColor(R.color.textHighlight); + ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); + colorAnimation.setDuration(1000); + colorAnimation.setRepeatCount(ValueAnimator.INFINITE); + colorAnimation.setRepeatMode(ValueAnimator.REVERSE); + colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + + @Override + public void onAnimationUpdate(ValueAnimator animator) { + startButton.setTextColor((Integer)animator.getAnimatedValue()); + } + + }); + colorAnimation.start(); + + + startButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + loadGameDialog = ProgressDialog.show(MirrorMenuActivity.this, "", + MirrorMenuActivity.this.getResources().getString(R.string.load_game_activity), true); + Intent intent = new Intent(MirrorMenuActivity.this, GamingActivity.class); + startActivity(intent); + detector.stop(); + detector = null; + + } + }); + + highscoresButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(MirrorMenuActivity.this, HighscoreActivity.class); +// intent.putExtra(HighscoreActivity.INTENT_EXTRA_LEVEL, player.getPlayerInfo().reachedLevelId); + startActivity(intent); + } + }); + + creditsButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(MirrorMenuActivity.this, CreditsActivity.class); + startActivity(intent); + } + }); + } + + @Override + protected void onResume() { + super.onResume(); + startDetector(); + + if(loadGameDialog != null) + loadGameDialog.dismiss(); + } + + @Override + protected void onPause() { + super.onPause(); + stopDetector(); + } + + void startDetector() { + if (detector == null || !detector.isRunning()) { + // check permission + String permission = "android.permission.CAMERA"; + int res = getApplicationContext().checkCallingOrSelfPermission(permission); + if (res == PackageManager.PERMISSION_GRANTED) { + Log.i(LOG_TAG, "Has camera permission"); + has_camera_permission = true; + } else { + Log.i(LOG_TAG, "No camera permission"); + ActivityCompat.requestPermissions(this, + new String[]{Manifest.permission.CAMERA}, + PERMISSIONS_REQUEST_CAMERA); + } + + if(has_camera_permission) + { + if(detector == null) + { +// SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView); + + detector = new CameraDetector(this, CameraDetector.CameraType.CAMERA_FRONT, cameraPreview, 1, Detector.FaceDetectorMode.LARGE_FACES); + detector.setLicensePath("emotionhero_dev.license"); + + detector.setDetectAllEmotions(true); + detector.setDetectAllAppearances(false); + detector.setDetectAllEmojis(false); + detector.setDetectAllExpressions(true); + detector.setMaxProcessRate(20); + + detector.setImageListener(this); + detector.setOnCameraEventListener(this); + detector.setFaceListener(this); + } + + detector.start(); + setText("STARTING..."); + Log.d(LOG_TAG, Boolean.toString(detector.isRunning())); + } + } + } + + void stopDetector() { + if (detector != null && detector.isRunning()) { + detector.stop(); + } + } + + @Override + /** + * Detector callback gives the faces found so we can match their hits to the given scenario. + */ + public void onImageResults(List list, Frame frame, float timestamp) {if (list == null) + return; + if (list.size() == 0) { + setText("Show me your face"); + } else { + hideText(); + Face face = list.get(0); + scenarioView.setCurrentAttributeScoresForFace(face); + } + } + + @Override + /** + * For CameraDetector.CameraEventListener + * Used to scale video preview output + */ + public void onCameraSizeSelected(int width, int height, Frame.ROTATE rotate) { + if (rotate == Frame.ROTATE.BY_90_CCW || rotate == Frame.ROTATE.BY_90_CW) { + previewWidth = height; + previewHeight = width; + } else { + previewHeight = height; + previewWidth = width; + } + cameraPreview.requestLayout(); + } + + @Override + public void onRequestPermissionsResult(int requestCode, + String permissions[], int[] grantResults) { + switch (requestCode) { + case PERMISSIONS_REQUEST_CAMERA: { + // If request is cancelled, the result arrays are empty. + if (grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + has_camera_permission = true; + startDetector(); + } else { + has_camera_permission = false; + Toast errorMsg = Toast.makeText(this, R.string.camera_required, Toast.LENGTH_LONG); + errorMsg.show(); + } + return; + } + + // other 'case' lines to check for other + // permissions this app might request + } + } + + @Override + public void onFaceDetectionStarted() + { + hideText(); + scenarioView.noFace = false; + } + + @Override + public void onFaceDetectionStopped() + { + scenarioView.noFace = true; + } + + public void setText(String text) + { + messageText.setVisibility(View.VISIBLE); + messageText.setText(text); + } + + public void hideText() + { + messageText.setVisibility(View.GONE); + } + +} diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/Scenario.java b/app/src/main/java/com/rubenvandeven/emotionhero/Scenario.java index 28b18b2..e7c7e63 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/Scenario.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/Scenario.java @@ -70,6 +70,8 @@ public class Scenario { private GamingActivity _activity; + int maxScore = 0; + /** * The scorres in this moment, as to draw them on the screen. * Indexes are Emotion ordinals @@ -177,6 +179,7 @@ public class Scenario { target.emotion = emotion; target.index = targets.size() + 1; targets.add(target); + maxScore = getMaxScore(); } /** @@ -205,6 +208,23 @@ public class Scenario { return value; } + public float getHitTotalMisValue() + { + float value = 0; + for (Hit hit : game.hits.values()) { + value += 100-hit.score; + } + return value; + } + + public float getHitPercentage() { + return (getHitTotalValue()/maxScore) * 100; + } + + public float getMissedPercentage() { + return (getHitTotalMisValue()/maxScore) * 100; + } + /** * Check whether given timestamp is within duration of the scenario * @param timestamp diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/ScenarioView.java b/app/src/main/java/com/rubenvandeven/emotionhero/ScenarioView.java index 3e328db..1674c0b 100644 --- a/app/src/main/java/com/rubenvandeven/emotionhero/ScenarioView.java +++ b/app/src/main/java/com/rubenvandeven/emotionhero/ScenarioView.java @@ -8,6 +8,7 @@ import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.Typeface; +import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; @@ -38,10 +39,15 @@ public class ScenarioView extends SurfaceView implements SurfaceHolder.Callback private Map emoScoredPaints = new HashMap<>(); private Paint mainPaint = new Paint(); private Paint attrScorePaint = new Paint(); + private Paint attrScoreLinePaint = new Paint(); private Paint linePaint = new Paint(); private Paint scorePaint = new Paint(); private Paint scoreFinishedPaint = new Paint(); + public boolean drawOverlay = false; + + public boolean noFace = false; + // see: http://blog.danielnadeau.io/2012/01/android-canvas-beginners-tutorial.html class PanelThread extends Thread { private SurfaceHolder _surfaceHolder; @@ -103,6 +109,9 @@ public class ScenarioView extends SurfaceView implements SurfaceHolder.Callback linePaint.setStrokeWidth(5); attrScorePaint.setColor(Color.DKGRAY); + attrScoreLinePaint.setColor(Color.DKGRAY); + attrScoreLinePaint.setStrokeWidth(2); + for(Emotion emotion: Emotion.values()) { Paint emoPaint = new Paint(); emoPaint.setTextSize(22); @@ -135,9 +144,14 @@ public class ScenarioView extends SurfaceView implements SurfaceHolder.Callback @Override public void onDraw(Canvas canvas) { -// canvas.drawColor(0x00AAAAAA); + if(drawOverlay) { + canvas.drawColor(0x990000FF); + } //do drawing stuff here. + if (noFace) + return; + float height = canvas.getHeight(); float width = canvas.getWidth(); @@ -187,42 +201,62 @@ public class ScenarioView extends SurfaceView implements SurfaceHolder.Callback // Draw targets: float sec_height = height * (float) 0.2; // each second is 20% of canvas height // current moved position - float diff_y = sec_height * _scenario.getTime(); + if(_scenario != null) { - for(Scenario.Target target: _scenario.getTargets()) { -// Paint targetPaint = (target.hit == null) ? emoPaints.get(target.emotion) : emoScoredPaints.get(target.emotion); - float cy = bottomline_height - (target.timestamp * sec_height) + diff_y; + float diff_y = sec_height * _scenario.getTime(); - float cx = padding_left + (step_y * target.emotion.ordinal() + step_y / 2); + for(Scenario.Target target: _scenario.getTargets()) { - canvas.drawCircle(cx, cy, max_ball_radius * target.value/100, emoPaints.get(target.emotion)); + // don't draw hit targets + if(target.isHit){ + continue; + } - if(target.isHit) { - Hit hit = _scenario.getHitForTarget(target); - canvas.drawText(Integer.toString(Math.round(hit.score)), cx, cy, emoPaints.get(target.emotion)); - canvas.drawCircle(cx, cy, max_ball_radius * hit.score/100, emoScoredPaints.get(target.emotion)); + // Paint targetPaint = (target.hit == null) ? emoPaints.get(target.emotion) : emoScoredPaints.get(target.emotion); + float cy = bottomline_height - (target.timestamp * sec_height) + diff_y; -// TODO: Use target.hit.face to set Rect src. -// if(target.hit.image != null) { -// Rect rect = new Rect((int) cx-10, (int) cy-10, (int) cx+10, (int) cy+10); -// canvas.drawBitmap(target.hit.image, null, rect, null); -// } + float cx = padding_left + (step_y * target.emotion.ordinal() + step_y / 2); + + canvas.drawCircle(cx, cy, max_ball_radius * target.value/100, emoPaints.get(target.emotion)); + + if(target.isHit) { + Hit hit = _scenario.getHitForTarget(target); + canvas.drawText(Integer.toString(Math.round(hit.score)), cx, cy, emoPaints.get(target.emotion)); + canvas.drawCircle(cx, cy, max_ball_radius * hit.score/100, emoScoredPaints.get(target.emotion)); + } + + + // String target_text = target.emotion.toString() + " " + target.value + "%"; + // canvas.drawText(target_text, cx, y_pos + diff_y , emoPaint); } + // draw the hit middle bottom; +// Paint usedScorePaint = _scenario.isFinished() ? scoreFinishedPaint : scorePaint; +// String scoreText = String.format("Total: %1$.0f", _scenario.getHitTotalValue()); +// Rect scoreTextBounds = new Rect(); +// usedScorePaint.getTextBounds(scoreText, 0, scoreText.length(), scoreTextBounds); + +// canvas.drawText(scoreText, (width - scoreTextBounds.width()) / 2, height - 10, usedScorePaint); + + + float hitWidth = width*(_scenario.getHitPercentage()/100); + float misWidth = width*(_scenario.getMissedPercentage()/100); + + String scoreText = String.format("%1$.0f", _scenario.getHitTotalValue()); + Rect scoreTextBounds = new Rect(); + scorePaint.getTextBounds(scoreText, 0, scoreText.length(), scoreTextBounds); + canvas.drawText(scoreText, hitWidth, height*0.95f-scoreTextBounds.height()-5, scorePaint); + + canvas.drawRect(0, height*0.95f, width, height, mainPaint); + float stepSize = width / _scenario.targets.size(); + for(int i = _scenario.targets.size(); i > 0; i--) { + canvas.drawLine(stepSize*i, height*0.95f, stepSize*i, height, attrScoreLinePaint); + } + canvas.drawRect(0, height*0.95f, hitWidth, height, emoPaints.get(Emotion.JOY)); + canvas.drawRect(hitWidth, height*0.95f, hitWidth+misWidth, height, attrScorePaint); -// String target_text = target.emotion.toString() + " " + target.value + "%"; -// canvas.drawText(target_text, cx, y_pos + diff_y , emoPaint); } - // draw the hit middle bottom; - Paint usedScorePaint = _scenario.isFinished() ? scoreFinishedPaint : scorePaint; - String scoreText = String.format("Total: %1$.0f", _scenario.getHitTotalValue()); - Rect scoreTextBounds = new Rect(); - usedScorePaint.getTextBounds(scoreText, 0, scoreText.length(), scoreTextBounds); - - canvas.drawText(scoreText, (width - scoreTextBounds.width()) / 2, height - 10, usedScorePaint); - - } diff --git a/app/src/main/java/com/rubenvandeven/emotionhero/StoryDialogFragment.java b/app/src/main/java/com/rubenvandeven/emotionhero/StoryDialogFragment.java new file mode 100644 index 0000000..9f708d8 --- /dev/null +++ b/app/src/main/java/com/rubenvandeven/emotionhero/StoryDialogFragment.java @@ -0,0 +1,54 @@ +package com.rubenvandeven.emotionhero; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatDialogFragment; + +/** + * Created by ruben on 07/09/16. + */ + +public class StoryDialogFragment extends AppCompatDialogFragment { + + GamingActivity activity; + + // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + // Verify that the host activity implements the callback interface + try { + // Instantiate the NoticeDialogListener so we can send events to the host + this.activity = (GamingActivity) activity; + } catch (ClassCastException e) { + // The activity doesn't implement the interface, throw exception + throw new ClassCastException(activity.toString() + + " must implement StoryDialogFragmentListener"); + } + } + + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + // Use the Builder class for convenient dialog construction + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setMessage(activity.currentScenario.getDescription()).setTitle(activity.currentScenario.toString()) + .setNeutralButton("Start!", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + activity.startGame(); + } + }).setCancelable(false).setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + activity.startGame(); + } + }); + // Create the AlertDialog object and return it + return builder.create(); + } +} diff --git a/app/src/main/res/layout/activity_mirror_menu.xml b/app/src/main/res/layout/activity_mirror_menu.xml new file mode 100644 index 0000000..4d27921 --- /dev/null +++ b/app/src/main/res/layout/activity_mirror_menu.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8b5f74d..77b04b5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -8,7 +8,7 @@ Next Level! Start Continue - Levels + Progress Credits HighscoreActivity Settings