I have this screen with two bird animatons using Bitmap. I want the bitmaps to be clickable but I am unable to figure out how. I can easily make the entire screen clickable by setting view.OnClickListener but that is not what I want, I want separate things to happen depending on which bird the user clicks on.
Also, how and where would I create a local variable for my bitmaps, for now I can only access them inside of the draw() method.
The run() method is for the animation and works fine.
I am new to all of this and appreciate any help!
Code
public class PlayActivity extends AppCompatActivity {
surfaceView view;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view = new surfaceView(this);
setContentView(view);
}
public class surfaceView extends SurfaceView {
public surfaceView(Context context) {
super(context);
new Anim().start();
}
private class Anim extends Thread {
int counter = 0;
int counter2 = 0;
#Override
public void run() {
long last_updated_time = 0;
long delay = 150;
int[] purple_bird = {
R.drawable.bird1,
R.drawable.bird2
};
int[] red_bird = {
R.drawable.red1,
R.drawable.red2,
R.drawable.red3,
R.drawable.red4,
R.drawable.red5,
R.drawable.red6,
R.drawable.red7,
R.drawable.red8,
R.drawable.red9,
R.drawable.red10
};
while (true) {
boolean playing = true;
if (playing) {
long current_time = System.currentTimeMillis();
if (current_time > last_updated_time + delay) {
if (counter >= 2) {
counter = 0;
}
if (counter2 >= 4) {
counter2 = 0;
}
draw(purple_bird[counter], red_bird[counter2]);
last_updated_time = current_time;
counter++;
counter2++;
}
}
}
}
private void draw(int red_bird, int purple_bird) {
SurfaceHolder holder = getHolder();
Canvas canvas = holder.lockCanvas();
if (canvas != null) {
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
Bitmap purpleBird = BitmapFactory.decodeResource(getContext().getResources(), purple_bird);
Bitmap redBird = BitmapFactory.decodeResource(getContext().getResources(), red_bird);
Bitmap resizedRedBird = Bitmap.createScaledBitmap(redBird, (int) (redBird.getWidth() * 0.1), (int) (redBird.getHeight() * 0.1), true);
Bitmap resizedPurpleBird = Bitmap.createScaledBitmap(purpleBird, (int) (purpleBird.getWidth() * 0.8), (int) (purpleBird.getHeight() * 0.8), true);
canvas.drawBitmap(resizedRedBird, 100, 100, paint);
canvas.drawBitmap(resizedPurpleBird, 100, 600, paint);
holder.unlockCanvasAndPost(canvas);
}
}
}
}
}
Related
My code does not work correctly. SurfaceView shows a black screen instead of Bitmaps. I make a game loop that doesn't depend on CPU, like Fix Your Timestep!, but I can't get it to work.
public class DrawView extends SurfaceView implements SurfaceHolder.Callback {
private DrawThreat drawThread;
public Background background;
private int height;
private int width;
public DrawView(Context context) {
super(context);
getHolder().addCallback(this);
drawThread = new DrawThreat(getHolder(), this);
setFocusable(true);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Rect surface = getHolder().getSurfaceFrame();
this.width = surface.width();
this.height = surface.height();
Bitmap back= BitmapFactory.decodeResource(App.getContext().getResources(), R.drawable.fon);
back = Bitmap.createScaledBitmap(back, width, height, false);
background = new Background(back, back, 0, 0, 0, -height);
drawThread = new DrawThreat(getHolder(), this);
drawThread.start();
}
public class DrawThreat extends Thread {
private final DrawView drawView;
private SurfaceHolder surfaceHolder;
private boolean running=true;
private static final int UPDATES_PER_SECOND = 25;
private static final int UPDATE_INTERVAL = 1000 / UPDATES_PER_SECOND * 1000000;
private static final int MAX_FRAMESKIP = 5;
private long nextUpdate = System.nanoTime();
public DrawThreat(SurfaceHolder surfaceHolder, DrawView drawView){
super();
this.surfaceHolder = surfaceHolder;
this.drawView = drawView;
}
I tried to implement a game loop, but only a black screen is displayed
#Override
public void run(){
while (running){
Canvas canvas = surfaceHolder.lockCanvas();
int skippedFrames = 0;
while (System.nanoTime() > this.nextUpdate && skippedFrames < MAX_FRAMESKIP) {
long delta = UPDATE_INTERVAL;
this.drawView.update(delta);
this.nextUpdate += UPDATE_INTERVAL;
skippedFrames++;
}
double interpolation = (System.nanoTime() + UPDATE_INTERVAL - this.nextUpdate) / (double) UPDATE_INTERVAL;
this.drawView.draw(canvas);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
Please point out the errors and tell me the right way to implement the idea.
Im using the MLKit combined with the CameraX Image-Analysis Use Case to build an App, that lets you control a cursor, which gets drawn onto an overlay based on the position of the face (head based pointing essentially).
I have two activities:
Activity 1 previews the camera feed and draws the facial landmarks (in my case, just the nosetip) onto the overlay as well as the cursor. As I said before, the cursor position is being calculated based on the nosetip position in the image -> No problems here
Activity 2 runs a very simplistic game in a separate thread, which spawns obstacles that need to be avoided with the cursor. No live camera feed, "just" the face detection, the face -> cursor screen mapping, a custom gameView and the overlay for the cursor ontop.
My problem:
After some time, the face detector just stops detecting faces (thus the cursor gets "stuck") without any errors and oddly enough, the game incrementally speeds up (but still registers collision with the cursor).
I already followed the instructions for optimizing face detection in real-time by only enabling landmark-mode, enabled tracking and setting the performance mode to fast.
My guess was that running the face detection, mapping the cursor to a point on the screen, drawing onto the overlay for the cursor and having a game running at the same time might be just too much work, but I read somewhere that MLKit runs its detection on its own thread.
It must have something to do with my game, because as already mentioned above, in Activity 1 (Live camera preview + calculating cursor position + drawing landmarks & cursor on the overlay canvas) I never faced (no pun intended) a crash.
My custom GameView:
public class GameView extends SurfaceView implements SurfaceHolder.Callback{
private final int difficultyTime = 5;
private GameThread thread;
private long startTime;
private long timer;
private long difficultyTimer;
private long lastSpawned = 0;
private Paint textPaint;
private Random random;
private Pointer pointer;
private GameManager game;
public GameView(Context context) {
super(context);
init();
}
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public GameView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public void init() {
getHolder().addCallback(this);
thread = new GameThread(getHolder(), this);
game = new GameManager();
setFocusable(true);
textPaint = new Paint();
textPaint.setColor(Color.RED);
textPaint.setTextSize(70);
Paint collisionPaint = new Paint();
collisionPaint.setColor(Color.BLUE);
Paint pointerPaint = new Paint();
pointerPaint.setColor(Color.GREEN);
startTime = System.currentTimeMillis();
lastSpawned = System.currentTimeMillis();
difficultyTimer = System.currentTimeMillis() + difficultyTime * 1000;
random = new Random();
}
public void update() {
timer = (System.currentTimeMillis() - startTime) / 1000;
long currentTimeMS = System.currentTimeMillis();
if(currentTimeMS > lastSpawned + (game.getCooldown() * 1000L)) {
lastSpawned = System.currentTimeMillis();
game.setMayDraw(true);
}
if(checkCollision()) {
gameover();
}
// Raise difficulty
if(difficultyTimer <= System.currentTimeMillis()) {
difficultyTimer = System.currentTimeMillis() + difficultyTime * 1000;
game.advanceDifficulty();
}
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
int bgColor = Color.WHITE;
canvas.drawColor(bgColor);
// Spawn elements
if(game.getMayDraw()) {
game.setMayDraw(false);
spawnObstacles(canvas);
}
// Update existing elements
game.updateObstacles(canvas);
// Draw the timer
drawTimer(canvas);
// Draw difficulty text
drawDifficulty(canvas);
}
private void drawTimer(Canvas canvas) {
canvas.drawText(Long.toString(timer), (getWidth() / 2), 80, textPaint);
invalidate();
}
private void drawDifficulty(Canvas canvas) {
canvas.drawText("Difficulty: " + game.getCurrentDifficultyIndex(), (getWidth() / 2) + 250, 80, textPaint);
}
private void spawnObstacles(Canvas canvas) {
int random_number;
int last_random = 0;
for(int i = 0; i < game.getMAX_SPAWN(); i++) {
do {
random_number = random.nextInt(4) + 1;
}while(random_number == last_random);
switch(random_number) {
case 1:
game.spawnTop(canvas);
break;
case 2:
game.spawnBottom(canvas);
break;
case 3:
game.spawnLeft(canvas);
break;
case 4:
game.spawnRight(canvas);
break;
}
last_random = random_number;
}
}
public void gameover() {
startTime = System.currentTimeMillis();
game.getObstacles().clear();
game.resetDifficulty();
difficultyTimer = System.currentTimeMillis() + difficultyTime * 1000;
}
public boolean checkCollision() {
List<Pair<GameManager.Direction, Rect>> collidables = game.getObstacles();
for (Pair<GameManager.Direction, Rect> r : collidables) {
if(intersects(r.second, pointer.getCollisionRect()) || intersects(pointer.getCollisionRect(), r.second)) {
return true;
}
}
return false;
}
public static boolean intersects(Rect rect, Rect otherRect) {
return rect.left <= otherRect.right && otherRect.left <= rect.right
&& rect.top <= otherRect.bottom && otherRect.top <= rect.bottom;
}
#Override
public void surfaceCreated(#NonNull SurfaceHolder surfaceHolder) {
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceChanged(#NonNull SurfaceHolder surfaceHolder, int format, int width, int height) {
System.out.println("Surface changed - Format: " + format + " W/H: ("+width +"/" +height+")");
}
#Override
public void surfaceDestroyed(#NonNull SurfaceHolder surfaceHolder) {
boolean retry = true;
while (retry) {
try {
thread.setRunning(false);
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
retry = false;
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
GameThread:
public class GameThread extends Thread{
private final SurfaceHolder surfaceHolder;
private final GameView gameView;
private boolean running;
public static Canvas canvas;
public GameThread(SurfaceHolder surfaceHolder, GameView gameView) {
super();
this.surfaceHolder = surfaceHolder;
this.gameView = gameView;
}
#Override
public void run() {
long startTime;
long timeMillis;
long waitTime;
long totalTime = 0;
int frameCount = 0;
int targetFPS = 15;
long targetTime = 1000 / targetFPS;
while (running) {
startTime = System.nanoTime();
canvas = null;
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized(surfaceHolder) {
this.gameView.update();
this.gameView.draw(canvas);
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
if (canvas != null) {
try {
surfaceHolder.unlockCanvasAndPost(canvas);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
timeMillis = (System.nanoTime() - startTime) / 1000000;
waitTime = targetTime - timeMillis;
try {
if(waitTime > 0) {
this.sleep(waitTime);
}
} catch (Exception e) {
e.printStackTrace();
}
totalTime += System.nanoTime() - startTime;
frameCount++;
if (frameCount == targetFPS) {
double averageFPS = 1000 / ((totalTime / frameCount) / 1000000);
frameCount = 0;
totalTime = 0;
Log.d("GameFPS", "" + averageFPS);
}
}
}
public void setRunning(boolean isRunning) {
running = isRunning;
}
FaceDetector:
public class Detector {
private final FaceDetector faceDetector;
private final GraphicOverlay overlay;
private final Pointer pointer;
private final ClickHandler clickHandler;
private final boolean drawFaces;
public Detector(GraphicOverlay overlay, Context context, boolean drawFaces) {
this.overlay = overlay;
this.drawFaces = drawFaces;
pointer = new Pointer(overlay, context);
clickHandler = new ClickHandler(context, this.pointer);
FaceDetectorOptions options =
new FaceDetectorOptions.Builder()
//.setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL)
.setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL)
/* disable for better performance *///.setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL)
.enableTracking()
.setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_FAST)
.build();
faceDetector = FaceDetection.getClient(options);
}
public void detectFace(ImageProxy image) {
if(image == null) {
return;
}
InputImage inputImage = getInputImage(image);
int rotationDegrees = image.getImageInfo().getRotationDegrees();
if(rotationDegrees == 0 || rotationDegrees == 180) {
overlay.setImageSourceInfo(image.getWidth(), image.getHeight(), true);
}else{
overlay.setImageSourceInfo(image.getHeight(), image.getWidth(), true);
}
if(inputImage == null) {
return;
}
Task<List<Face>> result =
this.faceDetector.process(inputImage)
// When detection succeeded
.addOnSuccessListener(
faces -> {
overlay.clear();
if(faces.size() > 0) {
for(Face face: faces) {
if(drawFaces) {
// Adding faces to overlay
FaceGraphic g = new FaceGraphic(overlay, face);
overlay.add(g);
}
// Update Pointer/Cursor
pointer.update(face);
}
}
})
// When detection failed
.addOnFailureListener(
e -> Log.d("Processing failed", e.getMessage()))
// When detection is completed
.addOnCompleteListener(
task -> image.close()
);
}
#SuppressLint("UnsafeOptInUsageError")
private InputImage getInputImage(ImageProxy image) {
int rotation = image.getImageInfo().getRotationDegrees();
Image mediaImage = image.getImage();
if(mediaImage != null) {
return InputImage.fromMediaImage(mediaImage, rotation);
}else{
return null;
}
}
GameActivity:
public class GameActivity extends AppCompatActivity {
private GraphicOverlay mOverlay;
private GameView gameView;
private Camera camera;
private Pointer pointer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_game);
gameView = findViewById(R.id.gameView);
mOverlay = findViewById(overlay_game);
initCamera();
}
private void initCamera() {
camera = new Camera(this, mOverlay);
camera.setDrawFaces(false);
camera.setAnalysisUseCase();
camera.setAnalyzer();
camera.build();
pointer = camera.getDetector().getPointer();
gameView.setPointer(pointer);
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
}
The face detection "crash" can occur anywhere from 1 second to 5 minutes playing the game. I would gladly appreciate any hints or suggestions. Also im fairly new to java and mobile-app development, so please excuse my bad code.
If you need any further information/code i'll happily provide it.
Thanks in advance
I am trying to save bitmaps in an ArrayList. I generate 2 types of bitmaps, they are basically identical - drawn with a finger by the user.
The first bitmap is fully visible in activity
The second is stored dynamically in the ArrayList - it is a slice of the last x milliseconds from the visible bitmap - It will be further converting and sending by BT.
The problem is that the last bitmap in the ArrayList is well saved, while each previous bitmap turns into a black rectangle when you add another one.
Relevant code snippets:
private ArrayList<Bitmap> bitmapsListToSend = new ArrayList<>();
private ArrayList<Canvas> canvasListToSend = new ArrayList<>();
mBitmapToShow = Bitmap.createBitmap(drawingWidth,drawingHeight,Bitmap.Config.RGB_565);
mCanvasToShow = new Canvas(mBitmapToShow);
bitmapsListToSend.add(Bitmap.createBitmap(drawingWidth,drawingHeight,Bitmap.Config.RGB_565))
//mCanvasToSend = new Canvas(bitmapsListToSend.get(bitmapsListToSend.size()-1));
canvasListToSend.add(new Canvas(bitmapsListToSend.get(bitmapsListToSend.size()-1)));;
I tried to make separate Canvas to each bitmap without success
public class PaintView extends View {
private final Paint mPaintToShow = new Paint();
private Bitmap mBitmapToShow;
private Canvas mCanvasToShow;
private final Paint mPaintToSend = new Paint();
//private Canvas mCanvasToSend;
private TouchPoint startPoint;
#Nullable
private ArrayList<Bitmap> bitmapsListToSend = new ArrayList<>();
private ArrayList<Canvas> canvasListToSend = new ArrayList<>();
private int bitmapCounter = 0;
private int alpha = 1;
/* debug */
Stopwatch watch = Stopwatch.createUnstarted();
public PaintView(Context c) {
super(c);
setFocusable(true);
mPaintToShow.setAntiAlias(true);
mPaintToShow.setColor(BLACK);
mPaintToShow.setAlpha(alpha);
mPaintToShow.setStrokeJoin(Paint.Join.ROUND);
mPaintToShow.setStrokeCap(Paint.Cap.ROUND);
mPaintToSend.setAntiAlias(true);
mPaintToSend.setColor(BLACK);
mPaintToSend.setStrokeJoin(Paint.Join.ROUND);
mPaintToSend.setStrokeCap(Paint.Cap.ROUND);
mBitmapToShow = Bitmap.createBitmap(drawingWidth,drawingHeight,Bitmap.Config.RGB_565);
mCanvasToShow = new Canvas(mBitmapToShow);
bitmapsListToSend.add(Bitmap.createBitmap(drawingWidth,drawingHeight,Bitmap.Config.RGB_565));
//mCanvasToSend = new Canvas(bitmapsListToSend.get(bitmapsListToSend.size()-1));
canvasListToSend.add(new Canvas(bitmapsListToSend.get(bitmapsListToSend.size()-1)));
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mCanvasToShow.drawColor(Color.WHITE);
//mCanvasToSend.drawColor(Color.WHITE);
canvasListToSend.get(canvasListToSend.size()-1).drawColor(WHITE);
}
public void clear() {
if (mCanvasToShow != null) {
mPaintToShow.setColor(Color.WHITE);
mCanvasToShow.drawPaint(mPaintToShow);
//mCanvasToSend.drawPaint(mPaintToShow);
bitmapCounter=0;
alpha=1;
bitmapsListToSend.clear();
canvasListToSend.clear();
mPaintToShow.setColor(BLACK);
watch.reset();
invalidate();
}
}
#Override
protected void onDraw(Canvas canvas) {
if (mBitmapToShow != null) {
canvas.drawBitmap(mBitmapToShow, 0, 0, null);
//mCanvasToSend.drawBitmap(bitmapsListToSend.get(bitmapsListToSend.size()-1), 0, 0, null);
}
}
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent(MotionEvent event) {
return onTouchOrHoverEvent(event, true /*isTouch*/);
}
private boolean onTouchOrHoverEvent(MotionEvent event, boolean isTouch) {
/*if (SENDING_NOW)
return true;*/
final int action = event.getActionMasked();
mPaintToShow.setStrokeWidth((float) ( getBrushSize() ));
if (action == MotionEvent.ACTION_DOWN) {
startPoint = new TouchPoint(event, 0);
runnableSaveBitmaps.run();
runnableChangeAlpha.run();
watch.start();
}else if(action == MotionEvent.ACTION_MOVE){
runnableChangeAlpha.run();
}else if (action == MotionEvent.ACTION_UP) {
startPoint = new TouchPoint(event, 0);
handlerSaveBitmaps.removeCallbacks(runnableSaveBitmaps);
handlerChangeAlpha.removeCallbacks(runnableChangeAlpha);
watch.stop();
}
//make drawings//
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
paintLines(mTouchPoints);
break;
case MotionEvent.ACTION_DOWN:
mCanvasToShow.drawCircle(startPoint.x, startPoint.y, getBrushSize()/2f, mPaintToShow);
//mCanvasToSend.drawCircle(startPoint.x, startPoint.y, getBrushSize()/2f, mPaintToSend);
canvasListToSend.get(canvasListToSend.size()-1).drawCircle(startPoint.x, startPoint.y, getBrushSize()/2f, mPaintToSend);
break;
}
invalidate();
}
return true;
}
//drawing methods//
Handler handlerSaveBitmaps = new Handler();
Runnable runnableSaveBitmaps = new Runnable() {
public void run() {
handlerSaveBitmaps.postDelayed(runnableSaveBitmaps, 10);
Log.v("B", "Bitmap added " + bitmapCounter + " " + (watch.toString()));
bitmapsListToSend.add(bitmapCounter, Bitmap.createBitmap(drawingWidth,drawingHeight,Bitmap.Config.RGB_565));
canvasListToSend.add(bitmapCounter++, new Canvas(bitmapsListToSend.get(bitmapsListToSend.size()-1)));
}
};
Handler handlerChangeAlpha = new Handler();
Runnable runnableChangeAlpha = new Runnable() {
#Override
public void run() {
handlerChangeAlpha.postDelayed(runnableChangeAlpha, 635);
if(alpha < 255)
mPaintToShow.setAlpha(alpha++);
else {
handlerChangeAlpha.removeCallbacks(runnableChangeAlpha);
Log.v("A", "ALPHA MAX" + (watch.toString()));
}
}
};
}
If Runnable saves 100 bitmaps - 99 will be black, the last one will be ok
//Bitmap.copy() fixed it
My intersect method keeps returning true and setting my "score text" to intersect detected when my images do not collide, instead it changes the text as soon as the emulator starts. Please notify me if more code is needed and check back within 10 minutes. Thanks! -this is all my code and collision code starts at line 163, something is wrong with my collision code because collision isn't being detected, what should I do to fix my collision code.
here is my code:
public class MainActivity extends AppCompatActivity {
//Layout
private RelativeLayout myLayout = null;
//Screen Size
private int screenWidth;
private int screenHeight;
//Position
private float ballDownY;
private float ballDownX;
//Initialize Class
private Handler handler = new Handler();
private Timer timer = new Timer();
//Images
private ImageView net = null;
private ImageView ball = null;
//for net movement along x-axis
float x;
float y;
//points
private int points = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myLayout = (RelativeLayout) findViewById(R.id.myLayout);
//score
TextView score = (TextView) findViewById(R.id.score);
//imageviews
net = (ImageView) findViewById(R.id.net);
ball = (ImageView) findViewById(R.id.ball);
//retrieving screen size
WindowManager wm = getWindowManager();
Display disp = wm.getDefaultDisplay();
Point size = new Point();
disp.getSize(size);
screenWidth = size.x;
screenHeight = size.y;
//move to out of screen
ball.setX(-80.0f);
ball.setY(screenHeight + 80.0f);
//start timer
timer.schedule(new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
changePos();
}
});
}
}, 0, 20);
}
public void changePos() {
//down
ballDownY += 10;
if (ball.getY() > screenHeight) {
ballDownX = (float) Math.floor((Math.random() * (screenWidth -
ball.getWidth())));
ballDownY = -100.0f;
}
ball.setY(ballDownY);
ball.setX(ballDownX);
/*INTERSECT METHOD
Rect rc1 = new Rect();
net.getDrawingRect(rc1);
Rect rc2 = new Rect();
ball.getDrawingRect(rc2);
if (Rect.intersects(rc1, rc2)) {
TextView score = (TextView) findViewById(R.id.score);
score.setText("INTERSECT DETECTED");
}*/
//make net follow finger
myLayout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
MainActivity.this.x = event.getX();
y = event.getY();
if (event.getAction() == MotionEvent.ACTION_MOVE) {
net.setX(MainActivity.this.x);
net.setY(y);
}
return true;
}
});
}
public boolean Collision(ImageView net, ImageView ball)
{
Rect AR = new Rect();
net.getHitRect(AR);
Rect BR = new Rect();
ball.getHitRect(BR);
Render();
return AR.intersect(BR) || AR.contains(BR) || BR.contains(AR);
}
public void Render()
{
if(Collision(net, ball))
{
points++;
TextView score = (TextView)findViewById(R.id.score);
score.setText("Score:" + points);
}
}
}
I have reformed your code, try now
public class MainActivity extends AppCompatActivity
{
//Layout
private RelativeLayout myLayout = null;
//Screen Size
private int screenWidth;
private int screenHeight;
//Position
private float ballDownY;
private float ballDownX;
//Initialize Class
private Handler handler = new Handler();
private Timer timer = new Timer();
//Images
private ImageView net = null;
private ImageView ball = null;
//score
private TextView score = null;
//for net movement along x-axis
public float x = 0;
public float y = 0;
//points
private int points = 0;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_main);
this.myLayout = (RelativeLayout) findViewById(R.id.myLayout);
this.score = (TextView) findViewById(R.id.score);
this.net = (ImageView) findViewById(R.id.net);
this.ball = (ImageView) findViewById(R.id.ball);
//retrieving screen size
WindowManager wm = getWindowManager();
Display disp = wm.getDefaultDisplay();
Point size = new Point();
disp.getSize(size);
screenWidth = size.x;
screenHeight = size.y;
//move to out of screen
this.ball.setX(-80.0f);
this.ball.setY(screenHeight + 80.0f);
//Error here
/*//Run constantly
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
Render();
}
}, 100); //100 is miliseconds interval than sleep this process, 1000 miliseconds is 1 second*/
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(100);
runOnUiThread(new Runnable() {
#Override
public void run(){Render();}});}
}catch (InterruptedException e) {}}};
t.start();
}
public void Render()
{
changePos();
if(Collision(net, ball))
{
points++; //You dont need findView Textview score for that exists in OnCreate Method
this.score.setText("Score:" + points);
}
}
public void changePos()
{
//down
ballDownY += 10;
if (ball.getY() > screenHeight) {
ballDownX = (float) Math.floor((Math.random() * (screenWidth - ball.getWidth())));
ballDownY = -100.0f;
}
ball.setY(ballDownY);
ball.setX(ballDownX);
//make net follow finger
myLayout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
x = event.getX();
y = event.getY();
if (event.getAction() == MotionEvent.ACTION_MOVE) {
net.setX(x);
net.setY(y);
}
return true;
}
});
public boolean Collision(ImageView net, ImageView ball)
{
Rect BallRect = new Rect();
ball.getHitRect(BallRect);
Rect NetRect = new Rect();
net.getHitRect(NetRect);
return BallRect.intersect(NetRect);
}
}
Something like this:
boolean collision = net.getRect().intersect(ball.getRect());
Collision is a boolean
if(boolean) //Action
Then
if(collision) score.setText("INTERSECT DETECTED");
OR
public boolean Collision(ImageView a, ImageView b)
{
Rect AR = new Rect();
a.getHitRect(myViewRect);
Rect BR = new Rect();
b.getHitRect(otherViewRect1);
return Rect.intersects(AR, BR);
}
--
if(Collision(net, ball))
{
//Do action
}
--
ImageView ball = (ImageView) findViewById(R.id.Ball);
ImageView net = (ImageView) findViewById(R.id.Net);
if(Collision(net, ball))
{
//Collision detected
}
--
import android.graphics.Rect;
public boolean Collision(ImageView ball, ImageView net)
{
Rect ballRect = new Rect();
ball.getDrawingRect(ballRect);
Rect netRect = new Rect();
net.getDrawingRect(netRect);
return Rect.intersects(ballRect, netRect);
}
Check this post how to detect when a ImageView is in collision with another ImageView?
I have a gif , running by Movie Class over a canvas. How can I change the size of the movie in proportion to the Screen's size? I tried to change it with canvas.scale() but the gif disappeard if I changed the height to a value bigger than 1.1 ..
Here is the code:
public class OurView extends SurfaceView implements Runnable {
private Movie mMovie;
InputStream mStream;
public OurView(Context context, InputStream stream) {
super(context);
holder = getHolder();
mStream = stream;
mMovie = Movie.decodeStream(mStream);
}
private long mMoviestart = 0;
Thread t = null;
SurfaceHolder holder;
boolean isItOK = false;
public OurView(Context c) {
super(c);
holder = getHolder();
}
public void run() {
while (isItOK) {
if (!holder.getSurface().isValid()) {
continue;
}
Canvas c = holder.lockCanvas();
try {
t.sleep(90);
} catch (InterruptedException e) {
e.printStackTrace();
}
x -= 10;
if (x + screenWidth <= 0) {
x = 0;
}
c.drawARGB(255, 150, 150, 10);
c.drawBitmap(map, 0, 0, null);
c.drawBitmap(grass, x, this.getHeight() - grassHeight, null);
c.drawBitmap(grass, (x + screenWidth), this.getHeight() - grassHeight, null);
final long now = SystemClock.uptimeMillis();
if (mMoviestart == 0) {
mMoviestart = now;
}
final int relTime = (int) ((now - mMoviestart) % mMovie.duration());
mMovie.setTime(relTime);
mMovie.draw(c, screenWidth / 7, this.getHeight() - (grassHeight + 30));
holder.unlockCanvasAndPost(c);
}
}
}
Thanks for any suggestions.
You can use:
canvas.scale(
(float)getMesuredWidth()/movie.width(),
(float)getMesuredHeight()/movie.height()
);
It worked for me
I use canvas.scale() and it works.