I am trying to edit this game code and call a second activity in //Show Result in order to go to another screen when the game is over.
There's an error "cannot resolve contructor".
enter image description here
I think the problem is with the intent but I am not really sure about where I can put it.
Can you help me?
Thank you
This is the GameView code
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.content.Intent;
public class GameView extends View {
// Canvas
private int canvasWidth;
private int canvasHeight;
// J
//private Bitmap j;
private Bitmap j[] = new Bitmap[2];
private int jX = 10;
private int jY;
private int jSpeed;
// Blue Ball
private int blueX;
private int blueY;
private int blueSpeed = 15;
private Paint bluePaint = new Paint();
// Black Ball
private int blackX;
private int blackY;
private int blackSpeed = 20;
private Paint blackPaint = new Paint();
// Background
private Bitmap bgImage;
// Score
private Paint scorePaint = new Paint();
private int score;
// Level
private Paint levelPaint = new Paint();
// Life
private Bitmap life[] = new Bitmap[2];
private int life_count;
// Status Check
private boolean touch_flg = false;
public GameView(Context context) {
super(context);
j[0] = BitmapFactory.decodeResource(getResources(), R.drawable.jun1);
j[1] = BitmapFactory.decodeResource(getResources(), R.drawable.jun2);
bgImage = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
bluePaint.setColor(Color.BLUE);
bluePaint.setAntiAlias(false);
blackPaint.setColor(Color.BLACK);
blackPaint.setAntiAlias(false);
scorePaint.setColor(Color.BLACK);
scorePaint.setTextSize(32);
scorePaint.setTypeface(Typeface.DEFAULT_BOLD);
scorePaint.setAntiAlias(true);
levelPaint.setColor(Color.DKGRAY);
levelPaint.setTextSize(32);
levelPaint.setTypeface(Typeface.DEFAULT_BOLD);
levelPaint.setTextAlign(Paint.Align.CENTER);
levelPaint.setAntiAlias(true);
life[0] = BitmapFactory.decodeResource(getResources(), R.drawable.heart);
life[1] = BitmapFactory.decodeResource(getResources(), R.drawable.heart_g);
// First position.
jY = 500;
score = 0;
life_count = 3;
}
#Override
protected void onDraw(Canvas canvas) {
canvasWidth = canvas.getWidth();
canvasHeight = canvas.getHeight();
canvas.drawBitmap(bgImage, 0, 0, null);
// Bird
int minBirdY = j[0].getHeight();
int maxBirdY = canvasHeight - j[0].getHeight() * 3;
jY += jSpeed;
if (jY < minBirdY) jY = minBirdY;
if (jY > maxBirdY) jY = maxBirdY;
jSpeed += 2;
if (touch_flg) {
// Flap wings.
canvas.drawBitmap(j[1], jX, jY, null);
touch_flg = false;
} else {
canvas.drawBitmap(j[0], jX, jY, null);
}
// Blue
blueX -= blueSpeed;
if (hitCheck(blueX, blueY)) {
score += 10;
blueX = -100;
}
if (blueX < 0) {
blueX = canvasWidth + 20;
blueY = (int) Math.floor(Math.random() * (maxBirdY - minBirdY)) + minBirdY;
}
canvas.drawCircle(blueX, blueY, 10, bluePaint);
// Black
blackX -= blackSpeed;
if (hitCheck(blackX, blackY)) {
blackX = -100;
life_count--;
if (life_count == 0) {
// Show Result
Intent i = new Intent(this, result.class);
i.putExtra("SCORE", score);
}
}
if (blackX < 0) {
blackX = canvasWidth + 200;
blackY = (int) Math.floor(Math.random() * (maxBirdY - minBirdY)) + minBirdY;
}
canvas.drawCircle(blackX, blackY, 20, blackPaint);
// Score
canvas.drawText("Score : " + score, 20, 60, scorePaint);
// Level
canvas.drawText("Lv.1", canvasWidth / 2, 60, levelPaint);
// Life
for (int i = 0; i < 3; i++) {
int x = (int) (560 + life[0].getWidth() * 1.5 * i);
int y = 30;
if (i < life_count) {
canvas.drawBitmap(life[0], x, y, null);
} else {
canvas.drawBitmap(life[1], x, y, null);
}
}
}
public boolean hitCheck(int x, int y) {
if (jX < x && x < (jX + j[0].getWidth()) &&
jY < y && y < (jY + j[0].getHeight())) {
return true;
}
return false;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
touch_flg = true;
jSpeed = -20;
}
return true;
}
}
View doesn't extend the Context class, which Intent's constructor needs for what you're doing.
Use
Intent i = new Intent(getContext(), result.class);
in your View class.
Related
I am trying to use one MainActivity.java class in Android Studio to control an RC car, I am still in the works as this is an early prototype code.
I am currently struggling on why my surfaceHolder.getSurface().isValid() is returning false every time. I cannot find any help besides implementing a Callback class, however, previously I have been able to use precisely the same lines of code mimicking my surfaceHolder and never needed a Callback class, the only exception was the class extended SurfaceView which this one does not because I can only extend one class. Below is my code:
package com.example.hughman.cccontrol;
import android.graphics.Point;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.SurfaceView;
import android.view.SurfaceHolder;
import android.widget.ImageButton;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
public class MainActivity extends AppCompatActivity implements View.OnClickListener, Runnable{
private ImageButton breakButton, connectButton;
private Bitmap left_thumb, left_thumb_resized, right_thumb_resized;
private Context context;
private int screenW, screenH, thumb_x, thumb_y, drag_x, drag_y, current_thumb = -1;
private Canvas canvas;
private Paint paint = new Paint();
private SurfaceHolder surfaceHolder;
private Thread thread;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
SurfaceView surfaceView = new SurfaceView(this);
paint.setAntiAlias(true);
//puts the app in full screen mode
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
surfaceHolder = surfaceView.getHolder();
//initalize screen size
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
screenH = size.x;
screenW = size.x;
//initialize buttons
breakButton = findViewById(R.id.breakbutton);
connectButton = findViewById(R.id.connectbutton);
breakButton.setOnClickListener(this);
connectButton.setOnClickListener(this);
left_thumb = BitmapFactory.decodeResource(this.getResources(), R.drawable.thumbstick);
left_thumb_resized = Bitmap.createScaledBitmap(left_thumb, 500, 500, false);
right_thumb_resized = Bitmap.createScaledBitmap(left_thumb, 500, 500, false);
thread = new Thread(this);
thread.start();
}
#Override
public void run() {
if(current_thumb == -1) {
drawInitialBitmap();
}
else
{
reDraw(drag_x, drag_y);
}
System.out.println("Run Test");
setFPS();
}
public void drawInitialBitmap()
{
thumb_x = 800;
thumb_y = (screenH / 2) + 250;
if (surfaceHolder.getSurface().isValid()) {
System.out.println("Hello");
canvas = surfaceHolder.lockCanvas();
canvas.drawBitmap(left_thumb_resized, thumb_x, thumb_y, paint);
canvas.drawBitmap(right_thumb_resized, thumb_x * 2, thumb_y, paint);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
public void reDraw(int x, int y)
{
if (surfaceHolder.getSurface().isValid()) {
canvas = surfaceHolder.lockCanvas();
if (current_thumb == 1) {
canvas.drawBitmap(left_thumb_resized, x, y, paint);
} else if (current_thumb == 2) {
canvas.drawBitmap(right_thumb_resized, x, y, paint);
}
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
//method for when user selects an xml button
public void onClick(View v) {
if (v == connectButton) {
//prompts to connect to Bluetooth
System.out.println("ConectButton");
}
else if(v == breakButton)
{
System.out.println("BreakButton");
//halt all motors
}
}
public boolean onTouchEvent(MotionEvent event){
int action = event.getAction();
int drag_x = (int) event.getX(); // or getRawX();
int drag_y = (int) event.getY();
switch(action){
case MotionEvent.ACTION_DOWN:
if (drag_x >= thumb_x && drag_x < (thumb_x + left_thumb_resized.getWidth())
&& drag_y >= thumb_y && drag_y < (thumb_y + left_thumb_resized.getHeight())) {
current_thumb = 1;
return true;
}
else if (drag_x >= thumb_x * 2 && drag_x < ((thumb_x * 2) + right_thumb_resized.getWidth())
&& drag_y >= thumb_y && drag_y < (thumb_y + right_thumb_resized.getHeight())) {
current_thumb = 2;
return true;
}
break;
case MotionEvent.ACTION_MOVE:
if(current_thumb != -1)
{
System.out.println(Math.sqrt(Math.pow(drag_x - thumb_x, 2) + Math.pow(drag_y - thumb_y, 2)));
System.out.println(Math.sqrt(Math.pow(drag_x - (thumb_x * 2), 2) + Math.pow(drag_y - thumb_y, 2)));
//move left thumb
return true;
}
break;
case MotionEvent.ACTION_UP:
current_thumb = -1;
drawInitialBitmap();
break;
default:
}
return false;
}
public void setFPS() {
try {
thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Everything runs fine and builds properly, but neither thumb sticks are being drawn. I haven't restricted the movement of the thumb sticks, but later on I will add that. As for now, I want to be able to drag them in the direction I want to move, using the distance function to simply figure out how far I ideally want to be able to drag them.
Is it possible to do this without extending SufaceView? Or making a Callback class? Why? Below I will add the code from my previous project where I did not use a Callback class, keep in mind the code is messy as we had multiple people working on the project and it had a required deadline of 24 hours.
package com.example.michael.doyouknowdeway;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageButton;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.media.MediaPlayer;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* Created by michael on 1/27/18.
* The big class that does most of the work for the code, sets the overall view of the game, getting
* the character, tiles, and player motions all together for a working game. Took us the most time
* to work on with many bugs occuring along de wae.
*/
public class GameView extends SurfaceView implements Runnable{
//
volatile boolean isPlaying = true, init = true, isPassOver = true;
private Thread gameThread = null;
private SurfaceHolder surfaceHolder;
private Canvas canvas;
private Context context;
private Activity activity;
private int screenWidth = 0, screenHeight = 0, move_const = 1;
private Player player;
private MediaPlayer jumpNoise, eatNoise;
private Bitmap backgroundImage;
private MediaPlayer backgroundMusic;
private MediaPlayer endGameSound;
private Bitmap backgroundImageResized;
Tile currentTile, nextTile;
private ScheduledExecutorService executorService;
private Paint paint = new Paint();
private Paint textPaint = new Paint();
private FireBall fireball;
private int scoreCount = 0, passOver;
private Bitmap endImage;
private Bitmap endImageResized;
private Bitmap run1, podCount;
private Bitmap run1Resized, podCountResized;
private Bitmap run2;
private Bitmap playerJumpImage;
private boolean isRun1 = false;
private ImageButton redoButton;
//starts of the program, creating the background for the game based on the dimensions of the
//phone being used
public GameView(Context context, int screenX, int screenY) {
super(context);
//load images into game
backgroundImage = BitmapFactory.decodeResource(context.getResources(), R.drawable.background_sky);
backgroundImageResized = Bitmap.createScaledBitmap(backgroundImage, screenX, screenY, false);
podCount = BitmapFactory.decodeResource(context.getResources(), R.drawable.detergent_pod);
run1 = BitmapFactory.decodeResource(context.getResources(), R.drawable.knuckles_run);
run1Resized = Bitmap.createScaledBitmap(run1, 200, 200, false);
podCountResized = Bitmap.createScaledBitmap(podCount, 100, 100, false);
run2 = BitmapFactory.decodeResource(context.getResources(), R.drawable.ugandan_knuckle);
playerJumpImage = BitmapFactory.decodeResource(context.getResources(), R.drawable.knucklesjump);
//load sounds into game
jumpNoise = MediaPlayer.create(context, R.raw.jump_takeoff);
eatNoise = MediaPlayer.create(context, R.raw.eat_1);
backgroundMusic = MediaPlayer.create(context, R.raw.music_baby);
endGameSound = MediaPlayer.create(context, R.raw.end_game);
//initialize other important stuff
textPaint.setColor(Color.WHITE);
textPaint.setTextSize(72);
textPaint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
screenWidth = screenX;
screenHeight = screenY;
activity = (Activity) context;
backgroundMusic.start();
this.context = context;
player = new Player(context, screenX, screenY);
fireball = new FireBall(context, screenX, screenY);
currentTile = new Tile(context, 3, screenWidth + 400, screenHeight);
currentTile.fillTile();
surfaceHolder = getHolder();
//controls "running" animation
executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
if(!player.isJumping) {
if (!isRun1) {
run1Resized = Bitmap.createScaledBitmap(run1, 200, 200, false);
isRun1 = true;
} else {
run1Resized = Bitmap.createScaledBitmap(run2, 200, 200, false);
isRun1 = false;
}
}
}
}, 0, 200, TimeUnit.MILLISECONDS); //can change "speed" of run by altering the second param
}
/**
* Main game loop
*/
public void run() {
while (isPlaying) {
update();
draw();
setFPS();
}
}
/**
* Redraws the screen in the new positions, creating continuous movement for the game
*/
public void draw() {
if (surfaceHolder.getSurface().isValid()) {
canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(backgroundImageResized, 0, 0, paint);
canvas.drawBitmap(podCountResized, 0, 0, paint);
String scoreCountStr = Integer.toString(scoreCount);
if(0 >= (currentTile.getLength() * 100) - move_const)
{
currentTile = new Tile(nextTile);
isPassOver = true;
nextTile = null;
move_const = 0;
}
if(init) {
init = false;
for (int i = 0; i < currentTile.getLength(); i++) {
for (int j = currentTile.getHeight() - 1; j >= 0; j--) {
if (currentTile.getBlock(i, j) != null) {
canvas.drawBitmap(currentTile.getBlock(i, j).getImage(), (i * 100), (j * 100) + 10, paint);
}
}
}
}
else
{
for (int i = 0; i < currentTile.getLength(); i++) {
for (int j = currentTile.getHeight() - 1; j >= 0; j--) {
if (currentTile.getBlock(i, j) != null) {
canvas.drawBitmap(currentTile.getBlock(i, j).getImage(), (i * 100) - move_const, (j * 100) + 10, paint);
}
if (nextTile != null) {
if (i < nextTile.getLength() && j < nextTile.getHeight()) {
if (nextTile.getBlock(i, j) != null) {
canvas.drawBitmap(nextTile.getBlock(i, j).getImage(), ((i + currentTile.getLength()) * 100) - move_const, (j * 100) + 10, paint);
}
}
}
}
}
move_const += 10;
}
if(fireball.isShooting) {
canvas.drawBitmap(fireball.getImage(), fireball.getXVal(), fireball.getYVal(), paint);
}
canvas.drawBitmap(run1Resized,player.getXVal(), player.getYVal(), paint);
canvas.drawText(scoreCountStr, 120, 80, textPaint);
//releases the canvas to be redrawn again
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
/**
* updates the positions of everything on the screen if needed
*/
public void update() {
player.update();
if(fireball.isShooting) {
fireball.update(player);
}
if((((currentTile.getLength() - (screenWidth/100) )* 100) - move_const <= 200) && nextTile == null){
nextTile = currentTile.getNextTile();
}
if(player.getYVal() >= screenHeight || player.getXVal() <= 0){
gameOver();
}
detectCollisions();
}
//initially sets player to not be colliding - changed almost instantly
static boolean isColliding = false;
//
/**
* Detects collisions so the player can collect tide pods and jump off of surfaces.
*/
public void detectCollisions(){
int highestY = 9;
int currentX = (250 + move_const)/100;
if(currentX >= currentTile.getLength() && isPassOver)
{
passOver = -10;
isPassOver = false;
}
else
{
passOver= -25; //arbitrary
}
for(int i = 0; i < currentTile.getHeight(); i++)
{
if(currentX >= currentTile.getLength())
{
passOver += 10;
if(nextTile.getBlock(passOver/100, i) != null)
{
if(!nextTile.getBlock(passOver/100, i).isPod())
{
highestY = i;
break;
}
}
}
else if(currentTile.getBlock(currentX, i) != null)
{
if(!currentTile.getBlock(currentX, i).isPod())
{
highestY = i;
break;
}
}
else
{
highestY = -1;
}
}
checkGroundCollision(highestY);
checkTidePodCollision(currentTile, nextTile);
checkForwardCollision(nextTile, currentX, highestY, passOver);
}
/**
* Method used to check if the player has hit a wall in front of them.
* #param next - the next tile
* #param x - player x position
* #param y - player y position
* #param passOver - the location being passed over.
*/
public void checkForwardCollision(Tile next, int x, int y, int passOver)
{
boolean collision = false;
Rect rect = new Rect();
if(next != null && passOver >= 0)
{
rect.top = y * 100;
rect.bottom = screenHeight;
rect.left = passOver + (player.getBitmap().getWidth() / 2);
rect.right = passOver + (player.getBitmap().getWidth() / 2) + 100;
collision = Rect.intersects(player.getHitBox(), rect);
}
else
{
rect.top = y * 100;
rect.bottom = screenHeight;
rect.left = (x+1)* 100;
rect.right = (x+2) * 100;
collision = Rect.intersects(player.getHitBox(), rect);
}
//if collision is true, half player movement until its not true
}
/**
* Method that checks if a player has hit a tidepod, if so, adds to score count
* #param current - the current tile
* #param next - the next tile
*/
public void checkTidePodCollision(Tile current, Tile next)
{
if(next != null && !isPassOver)
{
for(double iter: next.getTidePods())
{
int x = (int) iter;
int y = (int) (iter - x)*10;
boolean hit = podCollision(x, y);
if(hit)
{
eatNoise.start();
scoreCount += 10;
System.out.println("Cur Next: " + x + " || " + y);
nextTile.setNullBlock(x, y);
return;
}
}
}
else
{
for(double iter: current.getTidePods())
{
int x = (int) iter;
double temp = x;
int y = (int) ((iter - temp)*10.00);
boolean hit = podCollision(x, y);
if(hit)
{
eatNoise.start();
scoreCount += 10;
System.out.println("Current: " + x + " || " + y);
currentTile.setNullBlock(x, y);
return;
}
}
}
}
//compliment to the previous method
private boolean podCollision(int x, int y) {
Rect tideRect = new Rect();
if(isPassOver && x < 3)
{
System.out.println("TEST: " + x + " || " + y);
tideRect.top = (y * 100);
tideRect.left = x * 100 + passOver + 10;
tideRect.right = (x + 2) * 100 + passOver;
tideRect.bottom = (y + 2) * 100 + 10;
}
else {
tideRect.top = y * 100;
tideRect.left = x * 100 - move_const + 10;
tideRect.right = (x + 2) * 100 - move_const;
tideRect.bottom = (y + 2) * 100 + 10;
}
return Rect.intersects(player.getHitBox(), tideRect);
}
/**
* Method used for jumping off of the ground.
* #param highestY
*/
private void checkGroundCollision(int highestY) {
Rect blockRect = new Rect();
boolean GroundCollision;
if(highestY >= 0) {
blockRect.top = (highestY) * 100 - 25;
blockRect.left = 200;
blockRect.right = 300;
//changed this valued -- this is to remind myself
blockRect.bottom = highestY * 100 + 25; //still needs work //make player hitbox just his feet
GroundCollision = Rect.intersects(player.getFeetBox(), blockRect);
System.out.println("WWWWWW : " + GroundCollision);
}
else
{
GroundCollision = false;
}
if(GroundCollision){
isColliding = true;
} else {
player.isFalling = true;
isColliding = false;
}
}
/**
* Sets the FPS to roughly 60 fps
*/
public void setFPS() {
try {
gameThread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* Method that
*/
public void gameOver() {
//end image is not currently working
endImage = BitmapFactory.decodeResource(context.getResources(), R.drawable.end_game);
endImageResized = Bitmap.createScaledBitmap(endImage, 100, 200, false);
canvas.drawBitmap(endImageResized, screenWidth/2, screenHeight/2, paint);
//free up memory from bitmaps
backgroundImage.recycle();
backgroundImage = null;
backgroundImageResized.recycle();
backgroundImageResized = null;
podCount.recycle();
podCount = null;
podCountResized.recycle();
podCountResized = null;
backgroundImage.recycle();
backgroundImage = null;
run1.recycle();
run1 = null;
run1Resized.recycle();
run1Resized = null;
run2.recycle();
run2 = null;
playerJumpImage.recycle();
playerJumpImage = null;
backgroundMusic.stop();
Runtime.getRuntime().gc(); //manually run garbage collector
endGameSound.start();
context.startActivity(new Intent(context,MainActivity.class));
}
/**
* Method used to dictate what to do when the android screen is touched.
* #param event - the type of touch on the screen
* #return - true when screen is touched
*/
public boolean onTouchEvent(MotionEvent event){
int touchAction = event.getAction();
if(touchAction == MotionEvent.ACTION_DOWN){
if(event.getX() < (screenWidth / 2)) {
jumpNoise.start();
if(!player.isJumping && !player.isFalling) {
player.setYval(player.getYVal());
player.isJumping = true;
run1Resized = Bitmap.createScaledBitmap(playerJumpImage, 200, 200, false);
}
else if(player.getJumpCount() < 1)
{
player.setYval(player.getYVal());
player.incrJump();
player.isJumping = true;
run1Resized = Bitmap.createScaledBitmap(playerJumpImage, 200, 200, false);
}
} else {
fireball.setOnScreen(true);
}
}
return true;
}
/**
* Method that pauses the game when necessary (i.e when home button is pressed)
*/
public void pause() {
isPlaying = false;
backgroundMusic.pause();
try {
gameThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* Resumes the game after a pause
*/
public void resume() {
isPlaying = true;
backgroundMusic.start();
gameThread = new Thread(this);
gameThread.start();
}
}
Thank you for your time & any help is appreciated!
EDIT: Also using bitmaps to redraw etc. as that is what I am used to.
Okay, so I need to start another activity on collision detection, I am a beginner trying to make this simple game and I just cannot figure this out ... It is marked by //This is the place I am trying to start another activity, where I want to start it, the current code gives me error
GameView.java file where I need to start the activity
package fi.itsn.jetfighter;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.ArrayList;
import static android.support.v4.app.ActivityCompat.startActivity;
/**
* Created by h on 21.9.2016.
*/
public class GameView extends SurfaceView implements Runnable {
volatile boolean playing;
private Thread gameThread = null;
private Player player;
private Paint paint;
private Canvas canvas;
private SurfaceHolder surfaceHolder;
private Enemy[] enemies;
private Broccoli[] broccolis;
private int enemyCount = 3;
private int broccoliCount = 1;
private ArrayList<Star> stars = new
ArrayList<Star>();
//defining a boom object to display blast
private Boom boom;
public GameView(Context context, int screenX, int screenY) {
super(context);
player = new Player(context, screenX, screenY);
surfaceHolder = getHolder();
paint = new Paint();
int starNums = 100;
for (int i = 0; i < starNums; i++) {
Star s = new Star(screenX, screenY);
stars.add(s);
}
enemies = new Enemy[enemyCount];
for (int i = 0; i < enemyCount; i++) {
enemies[i] = new Enemy(context, screenX, screenY);
}
//initializing boom object
boom = new Boom(context);
broccolis = new Broccoli[broccoliCount];
for (int i = 0; i < broccoliCount; i++) {
broccolis[i] = new Broccoli(context, screenX, screenY);
}
}
#Override
public void run() {
while (playing) {
update();
draw();
control();
}
}
private void update() {
player.update();
//setting boom outside the screen
boom.setX(-250);
boom.setY(-250);
for (Star s : stars) {
s.update(player.getSpeed());
}
for (int i = 0; i < enemyCount; i++) {
enemies[i].update(player.getSpeed());
//if collision occurrs with player
if (Rect.intersects(player.getDetectCollision(), enemies[i].getDetectCollision())) {
//displaying boom at that location
boom.setX(enemies[i].getX());
boom.setY(enemies[i].getY());
enemies[i].setX(-200);
}
}
for (int i = 0; i < broccoliCount; i++) {
broccolis[i].update(player.getSpeed());
if (Rect.intersects(player.getDetectCollision(), broccolis[i].getDetectCollision())) {
startActivity(new Intent(this, end.class));
//This is the place I am trying to start another activity
}
}
}
private void draw() {
if (surfaceHolder.getSurface().isValid()) {
canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.BLUE);
paint.setColor(Color.WHITE);
for (Star s : stars) {
paint.setStrokeWidth(s.getStarWidth());
canvas.drawPoint(s.getX(), s.getY(), paint);
}
canvas.drawBitmap(
player.getBitmap(),
player.getX(),
player.getY(),
paint);
for (int i = 0; i < enemyCount; i++) {
canvas.drawBitmap(
enemies[i].getBitmap(),
enemies[i].getX(),
enemies[i].getY(),
paint
);
}
for (int i = 0; i < broccoliCount; i++) {
canvas.drawBitmap(
broccolis[i].getBitmap(),
broccolis[i].getX(),
broccolis[i].getY(),
paint
);
}
//drawing boom image
canvas.drawBitmap(
boom.getBitmap(),
boom.getX(),
boom.getY(),
paint
);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
private void control() {
try {
gameThread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void pause() {
playing = false;
try {
gameThread.join();
} catch (InterruptedException e) {
}
}
public void resume() {
playing = true;
gameThread = new Thread(this);
gameThread.start();
}
#Override
public boolean onTouchEvent(MotionEvent motionEvent) {
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_UP:
player.stopBoosting();
break;
case MotionEvent.ACTION_DOWN:
player.setBoosting();
break;
}
return true;
}
}
And here is the Broccoli.java file
package fi.itsn.jetfighter;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import java.util.Random;
/**
* Created by h on 22.9.2016.
*/
public class Broccoli {
//bitmap for the enemy
//we have already pasted the bitmap in the drawable folder
private Bitmap bitmap;
private int x;
private int y;
private int speed = 1;
private int maxX;
private int minX;
private int maxY;
private int minY;
//creating a rect object
private Rect detectCollision;
public Broccoli(Context context, int screenX, int screenY) {
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.broccoli);
maxX = screenX;
maxY = screenY;
minX = 0;
minY = 0;
Random generator = new Random();
speed = generator.nextInt(6) + 10;
x = screenX;
y = generator.nextInt(maxY) - bitmap.getHeight();
//initializing rect object
detectCollision = new Rect(x, y, bitmap.getWidth(), bitmap.getHeight());
}
public void update(int playerSpeed) {
x -= playerSpeed;
x -= speed;
if (x < minX - bitmap.getWidth()) {
Random generator = new Random();
speed = generator.nextInt(10) + 10;
x = maxX;
y = generator.nextInt(maxY) - bitmap.getHeight();
}
//Adding the top, left, bottom and right to the rect object
detectCollision.left = x;
detectCollision.top = y;
detectCollision.right = x + bitmap.getWidth();
detectCollision.bottom = y + bitmap.getHeight();
}
//adding a setter to x coordinate so that we can change it after collision
public void setX(int x){
this.x = x;
}
//one more getter for getting the rect object
public Rect getDetectCollision() {
return detectCollision;
}
//getters
public Bitmap getBitmap() {
return bitmap;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getSpeed() {
return speed;
}
}
Try with
startActivity(new Intent(getContext(), end.class));
You need to pass context not this. Here you are extending a class with SurfaceView not Activity so this won't give you context like it gives in Activity
OR
Because you are passing context in constructor so you can also do it like
public GameView(Context context, int screenX, int screenY) {{
super(context);
this.mContext = context;
}
and pass this mContext in Intent
startActivity(new Intent(mContext, end.class));
I have a rectangle I want to move up the screen at a constant rate and am confused as to why my code isn't working. Below is the code:
package com.ashmore.MyGame;
import java.util.ArrayList;
import java.util.List;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;
import com.ashmore.framework.Game;
import com.ashmore.framework.Graphics;
import com.ashmore.framework.Image;
import com.ashmore.framework.Screen;
import com.ashmore.framework.Input.TouchEvent;
public class GameScreen extends Screen {
enum GameState {
Ready, Running, Paused
}
GameState state = GameState.Ready;
boolean BarisMoving = false;
private ArrayList<Rect> rectangles = new ArrayList<Rect>();
int bar_x = 32;
int bar_y = 653;
int bar_width = 183;
int bar_height = 648;
Rect bar;
Paint paint;
public GameScreen(Game game) {
super(game);
// Initialize game objects here
bar = new Rect();
bar.set(bar_x, bar_y, bar_width, bar_height);
// Defining a paint object
paint = new Paint();
paint.setTextSize(30);
paint.setTextAlign(Paint.Align.CENTER);
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
}
private void updateRunning(List<TouchEvent> touchEvents, float deltaTime) {
// 1. All touch input is handled here:
int len = touchEvents.size();
for (int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
BarisMoving = true;
if (event.type == TouchEvent.TOUCH_UP) {
if (ScalesScreen.scaleType.equals("C")) {
rectangles.add(new Rect(56, 400, 80, 435));
//rectangles.get(0);
break;
}
if (BarisMoving) {
bar_y = bar_y -= 10;
}
for (Rect rect : rectangles) {
if(bar.intersect(rect)) {
checkButtons();
}
}
}
}
private void checkButtons() {
Log.d("GameScreen","Note and Bar Intersected");
}
#Override
public void paint(float deltaTime) {
Graphics g = game.getGraphics();
Paint paint = new Paint();
Paint paint2 = new Paint();
paint.setColor(Color.RED);
paint2.setColor(Color.RED);
for (Rect rect : rectangles) {
g.drawRect(rect, paint);
}
g.drawRect(bar, paint2);
}
private boolean inBounds(TouchEvent event, int x, int y, int width,
int height) {
if (event.x > x && event.x < x + width - 1 && event.y > y
&& event.y < y + height - 1)
return true;
else
return false;
}
}
I am probably missing something really basic. However, I can't seem to find the issue. Any help is appreciated!
I have figured out my problem. The problem was where my code was placed in the updateRunning() method. In my question, the setting of the boolean BarisMoving was set equal to "true" when there was a touch event:
int len = touchEvents.size();
for (int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
BarisMoving = true;
The boolean had to be moved outside of this (above int len = touchEvents.size();) and outside of the whole touch event area to work the way I wanted (outside of the for () { and the ending bracket }).
I'm making an android app, and I want to be able to record some audio that's played on an AudioTrack to a music file, It seems like a good idea to me to make an ArrayList of the samples that are played, adding each sample as it's played. I've made something I'd expect to work, but nothing shows up under "Music" app afterwards. Please take a look at my code and tell me if this is the right sort of thing to save to music, and what I need to do to make it work. Look especially at the startRecord() and stopRecording().
package com.example.test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
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.graphics.Point;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
public class Afspl extends Activity {
public DrawView vi;
private Point size;
Display disp;
public int wide, high, cx, cy;
boolean doPlay = false;
Thread soundPlayer;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
disp = getWindowManager().getDefaultDisplay();
try{
disp.getSize(size);
wide = size.x;
high = size.y;
}catch(Exception e){
wide = disp.getWidth();
high = disp.getHeight();
}
cx = 0; //tracks mouse x
cy = 0; //tracks mouse y
vi = new DrawView(getApplicationContext());
setContentView(vi);
soundPlayer = new Thread(new Runnable(){
public void run(){
int count = 0;
while(true){
try{
Thread.sleep((long)(duration * 10));
}catch(Exception e){}
if(!doPlay){
if(count==1)track.stop();
continue;
}
int note = cy * 12 / high;
if(cx > wide/2)note+=12;
int freq = (int)(440 * Math.pow(1.059463, note));
System.out.println(note + ", " + freq);
genTone(freq);
if(count==0){
handler.post(new Runnable(){
public void run(){
playSound();
}
});
count++;
}else{
handler.post(new Runnable(){
public void run(){
track.release();
playSound();
}
});
}
}
}
});
soundPlayer.start();
}
class DrawView extends View{
Paint paint = new Paint();
public DrawView(Context context){
super(context);
}
public void onDraw(Canvas c){
int red = 256;
int green = 0;
int blue = 0;
int curInc = 0;
for(int i=0; i<24; i++){
if(curInc==0){
green += 256/2;
if(green>=256){
curInc = 1;
}
}
else if(curInc == 1){
red -= 256/2;
if(red<=0){
curInc = 2;
}
}
else if(curInc == 2){
blue += 256/2;
if(blue >= 256){
curInc = 3;
}
}
else if(curInc == 3){
green -= 256/2;
if(green<=0){
curInc = 4;
}
}
else if(curInc == 4){
red += 256/2;
if(red>=256){
curInc = 5;
}
}else if(curInc == 5){
blue -= 256/2;
}
int width = wide;
int start = 0;
if(i<12){
width/=2;
}
else{
start = width/2;
if(red==0){
red = 128;
}
if(green == 0){
green = 128;
}
if(blue == 0){
blue = 128;
}
}
paint.setColor(getColor(red, blue, green));
int height = high / 12;
int starty = i * height;
int endy = (i+1) * height;
if(i>=12){
starty = (i-12) * height;
endy = (i-11) * height;
}
c.drawRect(start, starty, width, endy, paint);
}
paint.setColor(Color.WHITE);
c.drawRect(wide-100, high-100, wide, high, paint);
}
public int getColor(int r, int g, int b){
System.out.println(r + "," + g + "," + b);
int red = (r << 16) & 0x00ff0000;
int green = (g << 8) & 0x0000ff00;
int blue = b & 0x000000ff;
return 0xff000000 | red | green | blue;
}
}
public boolean onTouchEvent(MotionEvent me){
int type = me.getActionMasked();
switch(type){
case MotionEvent.ACTION_DOWN:
cx = (int)me.getX();
cy = (int)me.getY();
doPlay = true;
return true;
case MotionEvent.ACTION_UP:
doPlay = false;
if(cx > wide-50 && cy > high-50){
if(!isRecording)startRecord();
else stopRecording();
}
return true;
case MotionEvent.ACTION_MOVE:
cx = (int)me.getX();
cy = (int)me.getY();
return true;
default:
return super.onTouchEvent(me);
}
}
public double duration = 1;
public int sampleRate = 8000;
public int numSamples = (int)duration * sampleRate;
public final double[] samples = new double[numSamples];
public final byte[] generatedSnd = new byte[numSamples * 2];
public Handler handler = new Handler();
AudioTrack track;
public void genTone(int freq){
for(int i = 0; i<numSamples; i++){
samples[i] = Math.pow(-1, (float)(i / (sampleRate/freq)));
}
int idx = 0;
int volume = 32767 * cx/wide;
for (final double dVal : samples) {
final short val = (short) ((dVal+1) * volume);
generatedSnd[idx++] = (byte) (val & 0x00ff);
generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
if(isRecording){
toRec.add((byte)(val & 0x00ff));
toRec.add((byte)((val & 0xff00) >>> 8));
}
}
}
public void playSound(){
track = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length, AudioTrack.MODE_STATIC);
track.write(generatedSnd, 0, generatedSnd.length);
track.play();
}
public List<Byte> toRec = new ArrayList<Byte>();
boolean isRecording = false;
public void startRecord(){
isRecording = true;
toRec.clear();
}
String name;
public void setName(String str){
name=str;
}
public void stopRecording(){
Byte[] samplesNew = toRec.toArray(new Byte[toRec.size()]);
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Song Name");
alert.setMessage("Enter Song Title");
final EditText input = new EditText(this);
alert.setView(input);
final String name = "";
alert.setPositiveButton("OK", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int inter){
setName(input.getText().toString());
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int inter){
}
});
alert.show();
setName(name + ".mp3");
File writeTo = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC), "name");
if(!writeTo.mkdirs()){
System.out.println("Dir not created");
}
FileOutputStream stream = null;
try {
stream = new FileOutputStream(writeTo);
for(Byte b : samplesNew){
stream.write(b);
}
stream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The dialog comes up to enter a name when I click the box twice, but nothing appears under "Music" afterwards.
Please help with the following code - I need a dialog box with a button to appear when the game puzzle is completed. Thank you!
Here's the code:
Sudoku.java
package org.example.sudoku;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
public class Sudoku extends Activity implements OnClickListener {
private static final String TAG = "Sudoku";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Set up click listeners for all the buttons
View continueButton = findViewById(R.id.continue_button);
continueButton.setOnClickListener(this);
View newButton = findViewById(R.id.new_button);
newButton.setOnClickListener(this);
View aboutButton = findViewById(R.id.about_button);
aboutButton.setOnClickListener(this);
View exitButton = findViewById(R.id.exit_button);
exitButton.setOnClickListener(this);
}
#Override
protected void onResume() {
super.onResume();
Music.play(this, R.raw.main);
}
#Override
protected void onPause() {
super.onPause();
Music.stop(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.continue_button:
startGame(Game.DIFFICULTY_CONTINUE);
break;
// ...
case R.id.about_button:
Intent i = new Intent(this, About.class);
startActivity(i);
break;
// More buttons go here (if any) ...
case R.id.new_button:
openNewGameDialog();
break;
case R.id.exit_button:
finish();
break;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.settings:
startActivity(new Intent(this, Prefs.class));
return true;
// More items go here (if any) ...
}
return false;
}
/** Ask the user what difficulty level they want */
private void openNewGameDialog() {
new AlertDialog.Builder(this)
.setTitle(R.string.new_game_title)
.setItems(R.array.difficulty,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialoginterface,
int i) {
startGame(i);
}
})
.show();
}
/** Start a new game with the given difficulty level */
private void startGame(int i) {
Log.d(TAG, "clicked on " + i);
Intent intent = new Intent(Sudoku.this, Game.class);
intent.putExtra(Game.KEY_DIFFICULTY, i);
startActivity(intent);
}
}
Game.Java
package org.example.sudoku;
import android.app.Activity;
import android.app.Dialog;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.widget.Toast;
public class Game extends Activity {
private static final String TAG = "Sudoku";
public static final String KEY_DIFFICULTY =
"org.example.sudoku.difficulty";
private static final String PREF_PUZZLE = "puzzle" ;
public static final int DIFFICULTY_EASY = 0;
public static final int DIFFICULTY_MEDIUM = 1;
public static final int DIFFICULTY_HARD = 2;
protected static final int DIFFICULTY_CONTINUE = -1;
private int puzzle[] = new int[9 * 9];
private final String easyPuzzle =
"360000000004230800000004200" +
"070460003820000014500013020" +
"001900000007048300000000045";
private final String mediumPuzzle =
"650000070000506000014000005" +
"007009000002314700000700800" +
"500000630000201000030000097";
private final String hardPuzzle =
"009000000080605020501078000" +
"000000700706040102004000000" +
"000720903090301080000000600";
private PuzzleView puzzleView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
int diff = getIntent().getIntExtra(KEY_DIFFICULTY,
DIFFICULTY_EASY);
puzzle = getPuzzle(diff);
calculateUsedTiles();
puzzleView = new PuzzleView(this);
setContentView(puzzleView);
puzzleView.requestFocus();
// ...
// If the activity is restarted, do a continue next time
getIntent().putExtra(KEY_DIFFICULTY, DIFFICULTY_CONTINUE);
}
#Override
protected void onResume() {
super.onResume();
Music.play(this, R.raw.game);
}
#Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause");
Music.stop(this);
// Save the current puzzle
getPreferences(MODE_PRIVATE).edit().putString(PREF_PUZZLE,
toPuzzleString(puzzle)).commit();
}
/** Given a difficulty level, come up with a new puzzle */
private int[] getPuzzle(int diff) {
String puz;
switch (diff) {
case DIFFICULTY_CONTINUE:
puz = getPreferences(MODE_PRIVATE).getString(PREF_PUZZLE,
easyPuzzle);
break;
// ...
case DIFFICULTY_HARD:
puz = hardPuzzle;
break;
case DIFFICULTY_MEDIUM:
puz = mediumPuzzle;
break;
case DIFFICULTY_EASY:
default:
puz = easyPuzzle;
break;
}
return fromPuzzleString(puz);
}
/** Convert an array into a puzzle string */
static private String toPuzzleString(int[] puz) {
StringBuilder buf = new StringBuilder();
for (int element : puz) {
buf.append(element);
}
return buf.toString();
}
/** Convert a puzzle string into an array */
static protected int[] fromPuzzleString(String string) {
int[] puz = new int[string.length()];
for (int i = 0; i < puz.length; i++) {
puz[i] = string.charAt(i) - '0';
}
return puz;
}
/** Return the tile at the given coordinates */
private int getTile(int x, int y) {
return puzzle[y * 9 + x];
}
/** Change the tile at the given coordinates */
private void setTile(int x, int y, int value) {
puzzle[y * 9 + x] = value;
}
/** Return a string for the tile at the given coordinates */
protected String getTileString(int x, int y) {
int v = getTile(x, y);
if (v == 0)
return "";
else
return String.valueOf(v);
}
/** Change the tile only if it's a valid move */
protected boolean setTileIfValid(int x, int y, int value) {
int tiles[] = getUsedTiles(x, y);
if (value != 0) {
for (int tile : tiles) {
if (tile == value)
return false;
}
}
setTile(x, y, value);
calculateUsedTiles();
return true;
}
/** Open the keypad if there are any valid moves */
protected void showKeypadOrError(int x, int y) {
int tiles[] = getUsedTiles(x, y);
if (tiles.length == 9) {
Toast toast = Toast.makeText(this,
R.string.no_moves_label, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
} else {
Log.d(TAG, "showKeypad: used=" + toPuzzleString(tiles));
Dialog v = new Keypad(this, tiles, puzzleView);
v.show();
}
}
/** Cache of used tiles */
private final int used[][][] = new int[9][9][];
/** Return cached used tiles visible from the given coords */
protected int[] getUsedTiles(int x, int y) {
return used[x][y];
}
/** Compute the two dimensional array of used tiles */
private void calculateUsedTiles() {
for (int x = 0; x < 9; x++) {
for (int y = 0; y < 9; y++) {
used[x][y] = calculateUsedTiles(x, y);
// Log.d(TAG, "used[" + x + "][" + y + "] = "
// + toPuzzleString(used[x][y]));
}
}
}
/** Compute the used tiles visible from this position */
private int[] calculateUsedTiles(int x, int y) {
int c[] = new int[9];
// horizontal
for (int i = 0; i < 9; i++) {
if (i == y)
continue;
int t = getTile(x, i);
if (t != 0)
c[t - 1] = t;
}
// vertical
for (int i = 0; i < 9; i++) {
if (i == x)
continue;
int t = getTile(i, y);
if (t != 0)
c[t - 1] = t;
}
// same cell block
int startx = (x / 3) * 3;
int starty = (y / 3) * 3;
for (int i = startx; i < startx + 3; i++) {
for (int j = starty; j < starty + 3; j++) {
if (i == x && j == y)
continue;
int t = getTile(i, j);
if (t != 0)
c[t - 1] = t;
}
}
// compress
int nused = 0;
for (int t : c) {
if (t != 0)
nused++;
}
int c1[] = new int[nused];
nused = 0;
for (int t : c) {
if (t != 0)
c1[nused++] = t;
}
return c1;
}
}
PuzzleView.java
package org.example.sudoku;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;
public class PuzzleView extends View {
private static final String TAG = "Sudoku";
private static final String SELX = "selX";
private static final String SELY = "selY";
private static final String VIEW_STATE = "viewState";
private static final int ID = 42;
private float width; // width of one tile
private float height; // height of one tile
private int selX; // X index of selection
private int selY; // Y index of selection
private final Rect selRect = new Rect();
private final Game game;
public PuzzleView(Context context) {
super(context);
this.game = (Game) context;
setFocusable(true);
setFocusableInTouchMode(true);
// ...
setId(ID);
}
#Override
protected Parcelable onSaveInstanceState() {
Parcelable p = super.onSaveInstanceState();
Log.d(TAG, "onSaveInstanceState");
Bundle bundle = new Bundle();
bundle.putInt(SELX, selX);
bundle.putInt(SELY, selY);
bundle.putParcelable(VIEW_STATE, p);
return bundle;
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
Log.d(TAG, "onRestoreInstanceState");
Bundle bundle = (Bundle) state;
select(bundle.getInt(SELX), bundle.getInt(SELY));
super.onRestoreInstanceState(bundle.getParcelable(VIEW_STATE));
return;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
width = w / 9f;
height = h / 9f;
getRect(selX, selY, selRect);
Log.d(TAG, "onSizeChanged: width " + width + ", height "
+ height);
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
// Draw the background...
Paint background = new Paint();
background.setColor(getResources().getColor(
R.color.puzzle_background));
canvas.drawRect(0, 0, getWidth(), getHeight(), background);
// Draw the board...
// Define colors for the grid lines
Paint dark = new Paint();
dark.setColor(getResources().getColor(R.color.puzzle_dark));
Paint hilite = new Paint();
hilite.setColor(getResources().getColor(R.color.puzzle_hilite));
Paint light = new Paint();
light.setColor(getResources().getColor(R.color.puzzle_light));
// Draw the minor grid lines
for (int i = 0; i < 9; i++) {
canvas.drawLine(0, i * height, getWidth(), i * height,
light);
canvas.drawLine(0, i * height + 1, getWidth(), i * height
+ 1, hilite);
canvas.drawLine(i * width, 0, i * width, getHeight(),
light);
canvas.drawLine(i * width + 1, 0, i * width + 1,
getHeight(), hilite);
}
// Draw the major grid lines
for (int i = 0; i < 9; i++) {
if (i % 3 != 0)
continue;
canvas.drawLine(0, i * height, getWidth(), i * height,
dark);
canvas.drawLine(0, i * height + 1, getWidth(), i * height
+ 1, hilite);
canvas.drawLine(i * width, 0, i * width, getHeight(), dark);
canvas.drawLine(i * width + 1, 0, i * width + 1,
getHeight(), hilite);
}
// Draw the numbers...
// Define color and style for numbers
Paint foreground = new Paint(Paint.ANTI_ALIAS_FLAG);
foreground.setColor(getResources().getColor(
R.color.puzzle_foreground));
foreground.setStyle(Style.FILL);
foreground.setTextSize(height * 0.75f);
foreground.setTextScaleX(width / height);
foreground.setTextAlign(Paint.Align.CENTER);
// Draw the number in the center of the tile
FontMetrics fm = foreground.getFontMetrics();
// Centering in X: use alignment (and X at midpoint)
float x = width / 2;
// Centering in Y: measure ascent/descent first
float y = height / 2 - (fm.ascent + fm.descent) / 2;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
canvas.drawText(this.game.getTileString(i, j), i
* width + x, j * height + y, foreground);
}
}
if (Prefs.getHints(getContext())) {
// Draw the hints...
// Pick a hint color based on #moves left
Paint hint = new Paint();
int c[] = { getResources().getColor(R.color.puzzle_hint_0),
getResources().getColor(R.color.puzzle_hint_1),
getResources().getColor(R.color.puzzle_hint_2), };
Rect r = new Rect();
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
int movesleft = 9 - game.getUsedTiles(i, j).length;
if (movesleft < c.length) {
getRect(i, j, r);
hint.setColor(c[movesleft]);
canvas.drawRect(r, hint);
}
}
}
}
// Draw the selection...
Log.d(TAG, "selRect=" + selRect);
Paint selected = new Paint();
selected.setColor(getResources().getColor(
R.color.puzzle_selected));
canvas.drawRect(selRect, selected);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() != MotionEvent.ACTION_DOWN)
return super.onTouchEvent(event);
select((int) (event.getX() / width),
(int) (event.getY() / height));
game.showKeypadOrError(selX, selY);
Log.d(TAG, "onTouchEvent: x " + selX + ", y " + selY);
return true;
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
Log.d(TAG, "onKeyDown: keycode=" + keyCode + ", event="
+ event);
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
select(selX, selY - 1);
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
select(selX, selY + 1);
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
select(selX - 1, selY);
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
select(selX + 1, selY);
break;
case KeyEvent.KEYCODE_0:
case KeyEvent.KEYCODE_SPACE: setSelectedTile(0); break;
case KeyEvent.KEYCODE_1: setSelectedTile(1); break;
case KeyEvent.KEYCODE_2: setSelectedTile(2); break;
case KeyEvent.KEYCODE_3: setSelectedTile(3); break;
case KeyEvent.KEYCODE_4: setSelectedTile(4); break;
case KeyEvent.KEYCODE_5: setSelectedTile(5); break;
case KeyEvent.KEYCODE_6: setSelectedTile(6); break;
case KeyEvent.KEYCODE_7: setSelectedTile(7); break;
case KeyEvent.KEYCODE_8: setSelectedTile(8); break;
case KeyEvent.KEYCODE_9: setSelectedTile(9); break;
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_DPAD_CENTER:
game.showKeypadOrError(selX, selY);
break;
default:
return super.onKeyDown(keyCode, event);
}
return true;
}
public void setSelectedTile(int tile) {
if (game.setTileIfValid(selX, selY, tile)) {
invalidate();// may change hints
} else {
// Number is not valid for this tile
Log.d(TAG, "setSelectedTile: invalid: " + tile);
startAnimation(AnimationUtils.loadAnimation(game,
R.anim.shake));
}
}
private void select(int x, int y) {
invalidate(selRect);
selX = Math.min(Math.max(x, 0), 8);
selY = Math.min(Math.max(y, 0), 8);
getRect(selX, selY, selRect);
invalidate(selRect);
}
private void getRect(int x, int y, Rect rect) {
rect.set((int) (x * width), (int) (y * height), (int) (x
* width + width), (int) (y * height + height));
}
// ...
}
Maybe an AlertDialog?http://developer.android.com/guide/topics/ui/dialogs.html#AlertDialog