|
Android example source code file (GameView.java)
The GameView.java Android example source code/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.clickin2dabeat; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Typeface; import android.media.AudioManager; import android.media.SoundPool; import android.os.Vibrator; import android.view.MotionEvent; import android.view.View; import java.util.ArrayList; /** * Draws the beat targets and takes user input. * This view is used as the foreground; the background is the video * being played. */ public class GameView extends View { private static final long[] VIBE_PATTERN = {0, 1, 40, 41}; private static final int INTERVAL = 10; // in ms private static final int PRE_THRESHOLD = 1000; // in ms private static final int POST_THRESHOLD = 500; // in ms private static final int TOLERANCE = 100; // in ms private static final int POINTS_FOR_PERFECT = 100; private static final double PENALTY_FACTOR = .25; private static final double COMBO_FACTOR = .1; private static final float TARGET_RADIUS = 50; public static final String LAST_RATING_OK = "(^_')"; public static final String LAST_RATING_PERFECT = "(^_^)/"; public static final String LAST_RATING_MISS = "(X_X)"; private C2B parent; private Vibrator vibe; private SoundPool snd; private int hitOkSfx; private int hitPerfectSfx; private int missSfx; public int comboCount; public int longestCombo; public String lastRating; Paint innerPaint; Paint borderPaint; Paint haloPaint; private ArrayList<Target> drawnTargets; private int lastTarget; public ArrayList<Target> recordedTargets; private int score; public GameView(Context context) { super(context); parent = (C2B) context; lastTarget = 0; score = 0; comboCount = 0; longestCombo = 0; lastRating = ""; drawnTargets = new ArrayList<Target>(); recordedTargets = new ArrayList<Target>(); vibe = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); snd = new SoundPool(10, AudioManager.STREAM_SYSTEM, 0); missSfx = snd.load(context, R.raw.miss, 0); hitOkSfx = snd.load(context, R.raw.ok, 0); hitPerfectSfx = snd.load(context, R.raw.perfect, 0); innerPaint = new Paint(); innerPaint.setColor(Color.argb(127, 0, 0, 0)); innerPaint.setStyle(Paint.Style.FILL); borderPaint = new Paint(); borderPaint.setStyle(Paint.Style.STROKE); borderPaint.setAntiAlias(true); borderPaint.setStrokeWidth(2); haloPaint = new Paint(); haloPaint.setStyle(Paint.Style.STROKE); haloPaint.setAntiAlias(true); haloPaint.setStrokeWidth(4); Thread monitorThread = (new Thread(new Monitor())); monitorThread.setPriority(Thread.MIN_PRIORITY); monitorThread.start(); } private void updateTargets() { int i = lastTarget; int currentTime = parent.getCurrentTime(); // Add any targets that are within the pre-threshold to the list of // drawnTargets boolean cont = true; while (cont && (i < parent.targets.size())) { if (parent.targets.get(i).time < currentTime + PRE_THRESHOLD) { drawnTargets.add(parent.targets.get(i)); i++; } else { cont = false; } } lastTarget = i; // Move any expired targets out of drawn targets for (int j = 0; j < drawnTargets.size(); j++) { Target t = drawnTargets.get(j); if (t == null) { // Do nothing - this is a concurrency issue where // the target is already gone, so just ignore it } else if (t.time + POST_THRESHOLD < currentTime) { try { drawnTargets.remove(j); } catch (IndexOutOfBoundsException e){ // Do nothing here, j is already gone } if (longestCombo < comboCount) { longestCombo = comboCount; } comboCount = 0; lastRating = LAST_RATING_MISS; } } } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { int currentTime = parent.getCurrentTime(); float x = event.getX(); float y = event.getY(); boolean hadHit = false; if (parent.mode == C2B.ONEPASS_MODE) { // Record this point as a target hadHit = true; snd.play(hitPerfectSfx, 1, 1, 0, 0, 1); Target targ = new Target(currentTime, (int) x, (int) y, ""); recordedTargets.add(targ); } else if (parent.mode == C2B.TWOPASS_MODE) { hadHit = true; parent.beatTimes.add(currentTime); } else { // Play the game normally for (int i = 0; i < drawnTargets.size(); i++) { if (hitTarget(x, y, drawnTargets.get(i))) { Target t = drawnTargets.get(i); int points; double timeDiff = Math.abs(currentTime - t.time); if (timeDiff < TOLERANCE) { points = POINTS_FOR_PERFECT; snd.play(hitPerfectSfx, 1, 1, 0, 0, 1); lastRating = LAST_RATING_PERFECT; } else { points = (int) (POINTS_FOR_PERFECT - (timeDiff * PENALTY_FACTOR)); points = points + (int) (points * (comboCount * COMBO_FACTOR)); snd.play(hitOkSfx, 1, 1, 0, 0, 1); lastRating = LAST_RATING_OK; } if (points > 0) { score = score + points; hadHit = true; } drawnTargets.remove(i); break; } } } if (hadHit) { comboCount++; } else { if (longestCombo < comboCount) { longestCombo = comboCount; } comboCount = 0; snd.play(missSfx, 1, 1, 0, 0, 1); lastRating = LAST_RATING_MISS; } vibe.vibrate(VIBE_PATTERN, -1); } return true; } private boolean hitTarget(float x, float y, Target t) { if (t == null) { return false; } // Use the pythagorean theorem to solve this. float xSquared = (t.x - x) * (t.x - x); float ySquared = (t.y - y) * (t.y - y); if ((xSquared + ySquared) < (TARGET_RADIUS * TARGET_RADIUS)) { return true; } return false; } @Override public void onDraw(Canvas canvas) { if (parent.mode != C2B.GAME_MODE) { return; } int currentTime = parent.getCurrentTime(); // Draw the circles for (int i = 0; i < drawnTargets.size(); i++) { Target t = drawnTargets.get(i); if (t == null) { break; } // Insides should be semi-transparent canvas.drawCircle(t.x, t.y, TARGET_RADIUS, innerPaint); // Set colors for the target borderPaint.setColor(t.color); haloPaint.setColor(t.color); // Perfect timing == hitting the halo inside the borders canvas.drawCircle(t.x, t.y, TARGET_RADIUS - 5, borderPaint); canvas.drawCircle(t.x, t.y, TARGET_RADIUS, borderPaint); // Draw timing halos - may need to change the formula here float percentageOff = ((float) (t.time - currentTime)) / PRE_THRESHOLD; int haloSize = (int) (TARGET_RADIUS + (percentageOff * TARGET_RADIUS)); canvas.drawCircle(t.x, t.y, haloSize, haloPaint); } // Score and Combo info String scoreText = "Score: " + Integer.toString(score); int x = getWidth() - 100; // Fudge factor for making it on the top right // corner int y = 30; Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(Color.RED); paint.setTextAlign(Paint.Align.CENTER); paint.setTextSize(24); paint.setTypeface(Typeface.DEFAULT_BOLD); y -= paint.ascent() / 2; canvas.drawText(scoreText, x, y, paint); x = getWidth() / 2; canvas.drawText(lastRating, x, y, paint); String comboText = "Combo: " + Integer.toString(comboCount); x = 60; canvas.drawText(comboText, x, y, paint); } private class Monitor implements Runnable { public void run() { while (true) { try { Thread.sleep(INTERVAL); } catch (InterruptedException e) { // This should not be interrupted. If it is, just dump the stack // trace. e.printStackTrace(); } updateTargets(); postInvalidate(); } } } } Other Android examples (source code examples)Here is a short list of links related to this Android GameView.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.