emotionhero/app/src/main/java/com/rubenvandeven/emotionhero/GamingActivity.java

410 lines
14 KiB
Java

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.graphics.Typeface;
import android.media.AudioAttributes;
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;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;
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 java.util.HashMap;
import java.util.List;
/**
* An example full-screen activity that shows and hides the system UI (i.e.
* status bar and navigation/system bar) with user interaction.
*/
public class GamingActivity extends AppCompatActivity implements Detector.ImageListener, CameraDetector.CameraEventListener, Detector.FaceListener {
public final static String INTENT_EXTRA_SCENARIO = "com.rubenvandeven.emotionhero.LEVEL";
final static String LOG_TAG = "EmotionHero";
final int PERMISSIONS_REQUEST_CAMERA = 1;
private TextView mContentView;
private CameraDetector detector;
SurfaceView cameraPreview;
int previewWidth = 0;
int previewHeight = 0;
Scenario currentScenario;
ScenarioView scenarioView;
boolean has_camera_permission = false;
public SoundPool sound;
public HashMap<Integer, Integer> soundIds = new HashMap<>();
final static int SOUND_SCORE = 1;
final static int SOUND_BONUS = 2;
protected Player player;
protected boolean isStarted = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
if(getSupportActionBar() != null) {
getSupportActionBar().hide();
}
setContentView(R.layout.activity_gaming);
player = Player.getInstance(getApplicationContext());
Intent intent = getIntent();
// first level is the default to load, if none is given to intent
int scenarioLvlId = intent.getIntExtra(INTENT_EXTRA_SCENARIO, Scenario.SCENARIOS.get(0));
mContentView = (TextView) findViewById(R.id.fullscreen_content);
RelativeLayout videoLayout = (RelativeLayout) findViewById(R.id.video_layout);
TextView titleText = (TextView) findViewById(R.id.titleText);
//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 = GamingActivity.this.getWindow().getDecorView().getWidth();
int maxHeight = GamingActivity.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);
// setMeasuredDimension(1,1); // this DOES increase performance....
}
};
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);
videoLayout.addView(cameraPreview,0);
// currentScenario = new ScenarioAnger(this);
currentScenario = new Scenario(scenarioLvlId, this);
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));
soundIds.put(SOUND_BONUS, sound.load(this, R.raw.scorebonus, 1));
// StoryDialogFragment storyDialog = new StoryDialogFragment();
// storyDialog.show(getSupportFragmentManager(), "StoryDialog");
Typeface font = Typeface.createFromAsset(getAssets(), "unifont-9.0.02.ttf");
mContentView.setTypeface(font);
titleText.setText(currentScenario.toString());
titleText.setTypeface(font);
startGame();
}
public void startGame() {
isStarted = true;
startDetector();
}
@Override
protected void onResume() {
super.onResume();
if(isStarted)
startDetector();
// should resume 'on face detection started'
}
@Override
protected void onPause() {
super.onPause();
stopDetector();
currentScenario.pause();
}
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(true);
detector.setDetectAllEmojis(false);
detector.setDetectAllExpressions(true);
detector.setMaxProcessRate(12);
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<Face> list, Frame frame, float timestamp) {
// frame.getOriginalBitmapFrame()
// Log.e(LOG_TAG, "RESULT! faces: " + Integer.toString(list.size()) + " t: " + Float.toString(timestamp) + "s" );
// if(!currentScenario.isWithinTime(timestamp))
if(currentScenario.isFinished())
{
finishLevel();
return;
}
if (list == null)
return;
if (list.size() == 0) {
setText("No face found...");
// mContentView.setText("NO FACE FOUND"); // this happens in onFaceDetectionStopped
} else {
hideText(); // hide textView as we want as few elements as possible.
Face face = list.get(0);
currentScenario.setCurrentFace(face);
scenarioView.setCurrentAttributeScoresForFace(face);
currentScenario.currentFrame = (Frame.ByteArrayFrame) frame;
}
}
@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()
{
setText("START!");
if(isStarted)
currentScenario.start();
}
@Override
public void onFaceDetectionStopped()
{
currentScenario.pause();
}
public void setText(String text)
{
mContentView.setVisibility(View.VISIBLE);
mContentView.setText(text);
}
public void hideText()
{
mContentView.setVisibility(View.GONE);
}
// http://stackoverflow.com/a/27552576
protected void createSoundPool() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
createNewSoundPool();
} else {
createOldSoundPool();
}
}
// http://stackoverflow.com/a/27552576
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
protected void createNewSoundPool(){
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
sound = new SoundPool.Builder()
.setMaxStreams(6) // allow sounds to ring while another is started
.setAudioAttributes(attributes)
.build();
}
// http://stackoverflow.com/a/27552576
@SuppressWarnings("deprecation")
protected void createOldSoundPool(){
sound = new SoundPool(5, AudioManager.STREAM_MUSIC,0);
}
public void finishLevel() {
stopDetector();
PlayerInfo playerInfo = player.getPlayerInfo();
// ScoreList scores = playerInfo.getScoresForLevel(currentScenario.id);
// Score score = currentScenario.getScore();
//
// if(score.score == currentScenario.getMaxScore()) {
// // Maximum SCORE!!
// // You nailed it!
// } if(scores.isEmpty()) {
// // First play! Nice :-)
// }
// else if(scores.isHighest(score)) {
// // HIGHSCORE!!!!!
// } else {
// // Better luck next time
// }
// check whether this is the highest reached level by the player
// ... used by 'continue' button in main menu
if(currentScenario.minimumScore < currentScenario.game.score) {
if(currentScenario.isFinalLevel()) {
playerInfo.completedAll = true;
} else {
Scenario nextScenario = new Scenario(currentScenario.getNextLevelId(), this);
if(nextScenario.isHigherThen(playerInfo.reachedLevelId)) {
// allow player to continue to next level :-)
playerInfo.reachedLevelId = nextScenario.id;
}
}
}
// scores.add(score);
player.savePlayerInfo(playerInfo);
finish();
GameOpenHelper gameHelper = new GameOpenHelper(getApplicationContext());
gameHelper.insertGame(currentScenario.game);
Intent intent = new Intent(this, ReviewActivity.class);
intent.putExtra(ReviewActivity.INTENT_EXTRA_GAME_ID, currentScenario.game.id);
intent.putExtra(ReviewActivity.INTENT_EXTRA_FROM_GAME, true);
startActivity(intent);
}
}