I have Mat difference which has some black pixels(or really nearly black pixels -> if earhquake occurs, buliding will move etc.) in it and the Mat current which consists real image with natural colors. I would like to replace pixels in Mat current with these black pixels in Mat difference. If I do it manually like this:
for(int i = 0; i < difference.rows(); i++){
for(int j = 0; j < difference.cols(); j++){
subtractedPixel = difference.get(i, j);
if(subtractedPixel[0] < 10 && subtractedPixel[1] < 10 && subtractedPixel[2] < 10){
originalPixel = current.get(i, j);
difference.put(i, j, originalPixel);
}
}
it is extremely slow.
Full code(running):
package com.example.szpieg2;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Range;
import org.opencv.core.Size;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.Window;
import android.view.WindowManager;
public class TrackActivity extends Activity implements CvCameraViewListener {
private Mat current;
private CameraBridgeViewBase cameraView;
private Mat previous;
private Mat difference;//difference between previous and current
private boolean first = true;
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
#Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS: {
Log.i("Co sie dzieje?", "OpenCV loaded successfully");
cameraView.enableView();
// cameraView.setOnTouchListener(ColorBlobDetectionActivity.this);
}
break;
default: {
super.onManagerConnected(status);
}
break;
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
setContentView(R.layout.activity_track);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
cameraView = (CameraBridgeViewBase) findViewById(R.id.surface_view);
cameraView.setCvCameraViewListener(this);
}
// --------Activity Actions---------
#Override
public void onPause() {
if (cameraView != null)
cameraView.disableView();
super.onPause();
}
#Override
public void onResume() {
super.onResume();
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this,
mLoaderCallback);
}
public void onDestroy() {
super.onDestroy();
if (cameraView != null)
cameraView.disableView();
}
// --------/Activity Actions/---------
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_track, menu);
return true;
}
// --------listener method implementation-------------
#Override
public void onCameraViewStarted(int width, int height) {
/*current = new Mat(width, height, CvType.CV_64FC4);
previous = new Mat(width, height, CvType.CV_64FC4);
difference = new Mat(width, height, CvType.CV_64FC4);*/
current = new Mat(width, height, CvType.CV_8UC4);
previous = new Mat(width, height, CvType.CV_8UC4);
difference = new Mat(width, height, CvType.CV_8UC4);//RGBA 0..255
}
#Override
public void onCameraViewStopped() {
current.release();
}
#Override
public Mat onCameraFrame(Mat inputFrame) {
inputFrame.copyTo(current);
if(first){//first is true at the first time
inputFrame.copyTo(previous);
first = false;
Log.i("First processing", "Pierwszy przebieg");
}
Core.absdiff(current, previous, difference);
// Core.absdiff( previous,current, difference);
//I leave black pixels and load original colors
double[] subtractedPixel, originalPixel;
String s = "";
for(int i = 0; i < difference.rows(); i++){
for(int j = 0; j < difference.cols(); j++){
subtractedPixel = difference.get(i, j);
if(subtractedPixel[0] < 10 && subtractedPixel[1] < 10 && subtractedPixel[2] < 10){
originalPixel = previous.get(i, j);
difference.put(i, j, originalPixel);
}
}
// s+="\n";
}
// Log.i("mat ", s);
// Log.i("mat ", difference.get(44,444)[0] + "");
//---------------------------------------------
inputFrame.copyTo(previous);
return difference;//UNREAL COLORS
}
}
You can do the following.
Threshold your image using inRange().
Mat mask;
void inRange(difference, Scalar(0,0,0), Scalar(9,9,9), mask)
The output mask will be a binary mask where its pixel is set to 255 if its under threshold cv::Scalar(9,9,9);
Copy difference image into current image through mask using copyTo().
difference.copyTo(current, mask);
Related
Is it possible to connect your phone to your computer via USB cable and use it as webcam? I know there are plenty of software that allows it (at least for wireless), but how to use it in opencv (I am using Java)?
I think it's possible, however I did not test it. First download such an application that allows to use your phone as a webcam and then connect to it via VideoCapture(0) if it's the only webcam attached to your system. This code should be good for testing, if everything works you should see the video in a JFrame:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.WritableRaster;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.opencv.core.*;
import org.opencv.highgui.Highgui;
import org.opencv.highgui.VideoCapture;
public class JPanelOpenCV extends JPanel{
BufferedImage image;
public static void main (String args[]) throws InterruptedException{
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
JPanelOpenCV t = new JPanelOpenCV();
VideoCapture camera = new VideoCapture(0);
Mat frame = new Mat();
camera.read(frame);
if(!camera.isOpened()){
System.out.println("Error");
}
else {
while(true){
if (camera.read(frame)){
BufferedImage image = t.MatToBufferedImage(frame);
t.window(image, "Original Image", 0, 0);
t.window(t.grayscale(image), "Processed Image", 40, 60);
//t.window(t.loadImage("ImageName"), "Image loaded", 0, 0);
break;
}
}
}
camera.release();
}
#Override
public void paint(Graphics g) {
g.drawImage(image, 0, 0, this);
}
public JPanelOpenCV() {
}
public JPanelOpenCV(BufferedImage img) {
image = img;
}
//Show image on window
public void window(BufferedImage img, String text, int x, int y) {
JFrame frame0 = new JFrame();
frame0.getContentPane().add(new JPanelOpenCV(img));
frame0.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame0.setTitle(text);
frame0.setSize(img.getWidth(), img.getHeight() + 30);
frame0.setLocation(x, y);
frame0.setVisible(true);
}
//Load an image
public BufferedImage loadImage(String file) {
BufferedImage img;
try {
File input = new File(file);
img = ImageIO.read(input);
return img;
} catch (Exception e) {
System.out.println("erro");
}
return null;
}
//Save an image
public void saveImage(BufferedImage img) {
try {
File outputfile = new File("Images/new.png");
ImageIO.write(img, "png", outputfile);
} catch (Exception e) {
System.out.println("error");
}
}
//Grayscale filter
public BufferedImage grayscale(BufferedImage img) {
for (int i = 0; i < img.getHeight(); i++) {
for (int j = 0; j < img.getWidth(); j++) {
Color c = new Color(img.getRGB(j, i));
int red = (int) (c.getRed() * 0.299);
int green = (int) (c.getGreen() * 0.587);
int blue = (int) (c.getBlue() * 0.114);
Color newColor =
new Color(
red + green + blue,
red + green + blue,
red + green + blue);
img.setRGB(j, i, newColor.getRGB());
}
}
return img;
}
public BufferedImage MatToBufferedImage(Mat frame) {
//Mat() to BufferedImage
int type = 0;
if (frame.channels() == 1) {
type = BufferedImage.TYPE_BYTE_GRAY;
} else if (frame.channels() == 3) {
type = BufferedImage.TYPE_3BYTE_BGR;
}
BufferedImage image = new BufferedImage(frame.width(), frame.height(), type);
WritableRaster raster = image.getRaster();
DataBufferByte dataBuffer = (DataBufferByte) raster.getDataBuffer();
byte[] data = dataBuffer.getData();
frame.get(0, 0, data);
return image;
}
}
P.S. I do think your question is off-topic, too.
You can simply create camera activity and write code given
package com.techamongus.opencvcamera;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.hardware.Camera;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.JavaCameraView;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import java.io.File;
import java.util.List;
public class CameraActivity extends Activity implements CameraBridgeViewBase.CvCameraViewListener2 {
// A tag for log output.
private static final String TAG =
CameraActivity.class.getSimpleName();
// A key for storing the index of the active camera.
private static final String STATE_CAMERA_INDEX = "cameraIndex";
// A key for storing the index of the active image size.
private static final String STATE_IMAGE_SIZE_INDEX =
"imageSizeIndex";
// An ID for items in the image size submenu.
private static final int MENU_GROUP_ID_SIZE = 2;
// The index of the active camera.
private int mCameraIndex;
// The index of the active image size.
private int mImageSizeIndex;
// Whether the active camera is front-facing.
// If so, the camera view should be mirrored.
private boolean mIsCameraFrontFacing;
// The number of cameras on the device.
private int mNumCameras;
// The camera view.
private CameraBridgeViewBase mCameraView;
// The image sizes supported by the active camera.
private List<Camera.Size> mSupportedImageSizes;
// Whether the next camera frame should be saved as a photo.
private boolean mIsPhotoPending;
// A matrix that is used when saving photos.
private Mat mBgr;
// Whether an asynchronous menu action is in progress.
// If so, menu interaction should be disabled.
private boolean mIsMenuLocked;
// The OpenCV loader callback.
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
#Override
public void onManagerConnected(final int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
Log.d(TAG, "OpenCV loaded successfully");
mCameraView.enableView();
mBgr = new Mat();
break;
default:
super.onManagerConnected(status);
break;
}
}
};
#SuppressLint("NewApi")
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Window window = getWindow();
window.addFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
if (savedInstanceState != null) {
mCameraIndex = savedInstanceState.getInt(
STATE_CAMERA_INDEX, 0);
mImageSizeIndex = savedInstanceState.getInt(
STATE_IMAGE_SIZE_INDEX, 0);
} else {
mCameraIndex = 0;
mImageSizeIndex = 0;
}
final Camera camera;
if (Build.VERSION.SDK_INT >=
Build.VERSION_CODES.GINGERBREAD) {
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(mCameraIndex, cameraInfo);
mIsCameraFrontFacing =
(cameraInfo.facing ==
Camera.CameraInfo.CAMERA_FACING_FRONT);
mNumCameras = Camera.getNumberOfCameras();
camera = Camera.open(mCameraIndex);
} else { // pre-Gingerbread
// Assume there is only 1 camera and it is rear-facing.
mIsCameraFrontFacing = false;
mNumCameras = 1;
camera = Camera.open();
}
final Camera.Parameters parameters = camera.getParameters();
camera.release();
mSupportedImageSizes =
parameters.getSupportedPreviewSizes();
final Camera.Size size = mSupportedImageSizes.get(mImageSizeIndex);
mCameraView = new JavaCameraView(this, mCameraIndex);
mCameraView.setMaxFrameSize(size.width, size.height);
mCameraView.setCvCameraViewListener(this);
setContentView(mCameraView);
}
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the current camera index.
savedInstanceState.putInt(STATE_CAMERA_INDEX, mCameraIndex);
// Save the current image size index.
savedInstanceState.putInt(STATE_IMAGE_SIZE_INDEX,
mImageSizeIndex);
super.onSaveInstanceState(savedInstanceState);
}
#SuppressLint("NewApi")
#Override
public void recreate() {
if (Build.VERSION.SDK_INT >=
Build.VERSION_CODES.HONEYCOMB) {
super.recreate();
} else {
finish();
startActivity(getIntent());
}
}
#Override
public void onPause() {
if (mCameraView != null) {
mCameraView.disableView();
}
super.onPause();
}
#Override
public void onResume() {
super.onResume();
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_2_0,
this, mLoaderCallback);
mIsMenuLocked = false;
}
#Override
public void onDestroy() {
if (mCameraView != null) {
mCameraView.disableView();
}
super.onDestroy();
}
public Mat onCameraFrame(final CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
final Mat rgba = inputFrame.rgba();
if (mIsPhotoPending) {
mIsPhotoPending = false;
//takePhoto(rgba);
}
if (mIsCameraFrontFacing) {
// Mirror (horizontally flip) the preview.
Core.flip(rgba, rgba, 1);
}
return rgba;
}
Disclaimer:Check my blog link
http://www.techamongus.com/2017/03/android-camera-in-opencv.html
I want to make a sprite\bitmap jump using only android (no game engines). I wasn't able to find tutorials on how to do so in android using only canvas and views, but I did find a tutorial for xna(http://www.xnadevelopment.com/tutorials/thewizardjumping/thewizardjumping.shtml), and I tried to recreate it with the tools android offers. I was able to make the character move left and right using the tutorial code but making it jump just won't work.
this is my sprite class:
package com.example.spiceup;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Point;
import android.view.KeyEvent;
import android.widget.Toast;
public class Sprite {
enum State
{
Walking, Standing, Jumping
}
State mCurrentState = State.Standing;
Point mDirection;
int mSpeed = 0;
Context cc;
int mPreviousKeyboardState;
private String spriteName;
Bitmap sprite;
private int rows;
private int rows2;
int START_POSITION_X = 125;
int START_POSITION_Y = 245;
int SPRITE_SPEED = 6;
int MOVE_UP = -1;
int MOVE_DOWN = 1;
int MOVE_LEFT = -1;
int MOVE_RIGHT = 1;
Point mStartingPosition;
int aCurrentKeyboardState;
private float mScale = 1.0f;
Point Position;
public Sprite(String name,Bitmap sprite) {
this.sprite=sprite;
this.spriteName=name;
Position=new Point(150,150);
mStartingPosition=new Point(150,150);
mDirection=new Point(0,0);
}
public void Update()
{
UpdateMovement(aCurrentKeyboardState);
UpdateJump(aCurrentKeyboardState);
}
public void setkeyboard(int keyboard){
aCurrentKeyboardState = keyboard;
}
public void setLastKeyboard(int keyboard){
mPreviousKeyboardState = keyboard;
}
private void UpdateMovement(int aCurrentKeyboardState)
{
if (mCurrentState == State.Walking)
{
mSpeed = 0;
mDirection.x = 0;
if (aCurrentKeyboardState==KeyEvent.KEYCODE_A)
{
mSpeed = SPRITE_SPEED;
mDirection.x = MOVE_LEFT;
}
else if(aCurrentKeyboardState==KeyEvent.KEYCODE_D)
{
mSpeed = SPRITE_SPEED;
mDirection.x= MOVE_RIGHT;
}
Position.x += mDirection.x * mSpeed;
}
}
private void UpdateJump(int aCurrentKeyboardState)
{
if (mCurrentState == State.Walking)
{
if (aCurrentKeyboardState==KeyEvent.KEYCODE_SPACE && mPreviousKeyboardState!=KeyEvent.KEYCODE_SPACE)
{
Jump();
}
}
if (mCurrentState == State.Jumping)
{
if (mStartingPosition.y - Position.y> 150)
{
Position.y += mDirection.y * mSpeed;
mDirection.y = MOVE_DOWN;
}
if (Position.y > mStartingPosition.y)
{
Position.y = mStartingPosition.y;
mCurrentState = State.Walking;
}
}
}
private void Jump()
{
if (mCurrentState != State.Jumping)
{
mCurrentState = State.Jumping;
mStartingPosition = Position;
mDirection.y = MOVE_UP;
mSpeed = 6;
Position.y += mDirection.y * mSpeed;
}
}
public void Draw(Canvas c)
{
c.drawBitmap(sprite, Position.x,Position.y, null);
}
public void setmCurrentState(State mCurrentState) {
this.mCurrentState = mCurrentState;
}
}
this is the surfaceview:
import com.example.spiceup.Sprite.State;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameView extends SurfaceView {
Context cc;
Bitmap Sprite;
Sprite sprite2;
Handler handlerAnimation100;
private GameLoopThread gameLoopThread;
private SurfaceHolder holder;
public GameView(Context c) {
// TODO Auto-generated constructor stub
super(c);
gameLoopThread = new GameLoopThread(this);
this.cc=c;
this.Sprite=BitmapFactory.decodeResource(getResources(), R.drawable.walk1);
this.Sprite=Bitmap.createScaledBitmap(Sprite, Sprite.getWidth()*2, Sprite.getHeight()*2, false);
sprite2=new Sprite("Spicy",Sprite);
this.requestFocus();
this.setFocusableInTouchMode(true);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
gameLoopThread.setRunning(false);
while (retry) {
try {
gameLoopThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLACK);
sprite2.Update();
sprite2.Draw(canvas);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
sprite2.setkeyboard(keyCode);
sprite2.setmCurrentState(State.Walking);
return false;
}
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
sprite2.setmCurrentState(State.Standing);
sprite2.setLastKeyboard(keyCode);
return false;
}
}
if anyone knows where is my error or has a better code to show me I'll be happy, all I'm trying to do is to create a bitmap that moves around and can jump (but also jump while walking)
So I think what is happening in your code is that it's hitting the max height in the game loop and adding back to the y of the sprite. Second game loop run it is no longer above or near the max height distance therefore you stop going down and your start position becomes that position in the air. On a third loop through you hit spacebar again and your sprite starts the whole jumping processes over and the same thing happens on the next to loops through or however many it takes to trigger that if statement to get the sprite to start falling.
Good place to start is have a persistent boolean that determines whether or not the sprite is actually done climbing and jumping state should stay true while climbing and falling. See below.
boolean maxJumpAchieved = false;
if (mCurrentState == State.Jumping)
{
if (mStartingPosition.y - Position.y> 150)
{
maxJumpAchieved = true;
}
if (maxJumpAchieved) {
mDirection.y = MOVE_DOWN;
Position.y += mDirection.y * mSpeed;
}
if (Position.y > mStartingPosition.y)
{
maxJumpAchieved = false;
Position.y = mStartingPosition.y;
mCurrentState = State.Walking;
}
}
I think this should get you in the right direction but if you have issues let me know and I can edit my answer.
Another thing to note is don't set the mCurrentState to State.Walking until you know for sure you're on the ground otherwise you could double jump for days.
OK, So Im drawing a bitmap beneath everything else for my background. Whenever the player moves it moves the enemy array 1 px and its supposed to do the same for the background. But whenever I move the background goes way faster and farther than everything else in the game. Can anyone tell me whats causing this? Heres the code. The code that moves everything is at the bottom in the set direction method.
package com.gametest;
import java.util.concurrent.CopyOnWriteArrayList;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
public class GameSurfaceView extends Activity implements OnTouchListener {
double ran;
int touchX, touchY, screenWidth, screenHeight, objX, objY;
static int bgx, bgy, bgW, bgH, enemyCount, score, playerHealth;
static boolean canUpdate;
static MyView v;
static Bitmap orb, orb2, explosion, bg;
static CopyOnWriteArrayList<Sprite> copy = new CopyOnWriteArrayList<Sprite>();
static String hpString;
static Player player;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
v = new MyView(this);
v.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent me) {
switch (me.getAction()) {
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_MOVE:
return true;
case MotionEvent.ACTION_UP:
touchX = (int) me.getX();
touchY = (int) me.getY();
for (Sprite sprite : copy) {
sprite.checkTouch(touchX, touchY);
return true;
}
}
return true;
}
});
canUpdate = true;
screenWidth = v.getWidth();
screenHeight = v.getHeight();
playerHealth = 250;
hpString = "Health " + playerHealth;
ran = 0;
score = 0;
orb = BitmapFactory.decodeResource(getResources(), R.drawable.blue_orb);
orb2 = BitmapFactory.decodeResource(getResources(), R.drawable.red_orb);
bg = BitmapFactory.decodeResource(getResources(), R.drawable.bg1);
bgx = bg.getHeight()/2;
bgy = bg.getHeight()/2;
bgH = bg.getHeight();
bgW = bg.getWidth();
explosion = BitmapFactory.decodeResource(getResources(), R.drawable.explosion);
player = new Player(v, orb2, explosion, screenWidth, screenHeight);
createEnemies();
setContentView(v);
}
private void createEnemies() {
if (enemyCount < 5) {
screenWidth = v.getWidth();
screenHeight = v.getHeight();
copy.add(new Sprite(v, orb, explosion, screenWidth, screenHeight, copy.size()));
enemyCount++;
}
}
public static void checkECount(int id) {
canUpdate = false;
copy.remove(id);
enemyCount--;
CopyOnWriteArrayList<Sprite> c = new CopyOnWriteArrayList<Sprite>();
int index = 0;
for (Sprite s : copy) {
s.ID = index;
c.add(s);
index++;
}
score = score + 10;
copy = c;
canUpdate = true;
}
#Override
protected void onPause() {
super.onPause();
v.pause();
}
#Override
protected void onResume() {
super.onResume();
v.resume();
}
public class MyView extends SurfaceView implements Runnable {
Thread t = null;
SurfaceHolder holder;
boolean isItOk = false;
public MyView(Context context) {
super(context);
holder = getHolder();
}
#Override
public void run() {
while (isItOk == true) {
if (!holder.getSurface().isValid()) {
continue;
}
Canvas c = holder.lockCanvas();
if (canUpdate) {
canvas_draw(c);
}
holder.unlockCanvasAndPost(c);
try {
t.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
protected void canvas_draw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
Rect bgRec = new Rect(bgx, bgy, bgx+bgW, bgy+bgH);
canvas.drawBitmap(bg, null, bgRec, null);
ran = Math.random() * 5;
if (ran > 4.5) {
createEnemies();
}
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(15);
canvas.drawText(hpString, 10, 25, paint);
for (Sprite sprite : copy) {
sprite.sprite_draw(canvas);
}
Player.sprite_draw(canvas, copy);
}
public void pause() {
isItOk = false;
while (true) {
try {
t.join();
} catch (InterruptedException e) {
}
break;
}
t = null;
}
public void resume() {
isItOk = true;
t = new Thread(this);
t.start();
}
}
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
return false;
}
public static void damagePlayer() {
hpString = "Health " + playerHealth;
playerHealth = playerHealth - 5;
if (playerHealth < 0) {
hpString = "game over";
}
}
public static void setDirection(int i, int j) {
if (i == 0 && j == -1) {
for (Sprite s : copy) {
s.y++;
bgy++;
}
}
if (i == 0 && j == 1) {
for (Sprite s : copy) {
s.y--;
bgy--;
}
}
if (i == -1 && j == 0) {
for (Sprite s : copy) {
s.x++;
bgx++;
}
}
if (i == 1 && j == 0) {
for (Sprite s : copy) {
s.x--;
bgx--;
}
}
}
}
You are changing bgx based on the number of sprites you have in your copy Iterable. in your setDirection method, please move the bgy, bgx outside of the enhanced for loops, like in:
if (i == 0 && j == -1) {
for (Sprite s : copy) {
s.y++;
}
bgy++;
}
First Of all I'm doing this on Eclipse.
1.I wish to draw a rectangle on reception of Touch event.
2.That rectangle should be persistent and on an another Touchevent should draw another rectangle.
3.I have managed to get it persistent for a single TouchEvent after which it shifts according to coordinates.
4.So basically I should have multiple rectangles due to different touch events.
I am thinking of iterating through arrays...
But I'm still confused pls help!
This one does not work... I'm asking for improvements...
Thanks! Also manifests and stuff is proper and permissions are taken properly!
code is somewhat like:
package code.e14.balldetector;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
public class MainActivity extends Activity implements CvCameraViewListener2, OnTouchListener {
private static final String TAG = "OCVBallTracker";
private CameraBridgeViewBase mOpenCvCameraView;
private boolean mIsJavaCamera = true;
private Mat mRgba;
int i=0;
private Double[] h=new Double[20];
private Double[] k=new Double[20];
private double x=0;
private double y=0;
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
#Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
mOpenCvCameraView.enableView();
mOpenCvCameraView.setOnTouchListener(MainActivity.this);
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
public MainActivity() {
Log.i(TAG, "Instantiated new " + this.getClass());
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "called onCreate");
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_main);
if (mIsJavaCamera)
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.java_surface_view);
else
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.native_surface_view);
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
mOpenCvCameraView.setCvCameraViewListener(this);
}
#Override
public void onPause()
{
super.onPause();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
#Override
public void onResume()
{
super.onResume();
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_5, this, mLoaderCallback);
}
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
Log.i(TAG, "called onCreateOptionsMenu");
return true;
}
public void onCameraViewStarted(int width, int height) {
mRgba = new Mat(height, width, CvType.CV_8UC4);
}
public void onCameraViewStopped() {
mRgba.release();
}
#Override
public boolean onTouch(View arg0,MotionEvent event) {
double cols = mRgba.cols();
double rows = mRgba.rows();
double xOffset = (mOpenCvCameraView.getWidth() - cols) / 2;
double yOffset = (mOpenCvCameraView.getHeight() - rows) / 2;
h[i] = (double)(event).getX() - xOffset;
k[i] = (double)(event).getY() - yOffset;
h[i]=x;
k[i]=y;
Log.i(TAG, "Touch image coordinates: (" + h[i] + ", " + k[i] + ")");
i++;
return false;// don't need subsequent touch events
}
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
mRgba=inputFrame.rgba();
Core.rectangle(mRgba, new Point(x-100,y-100),new Point(x+100,y+100),new Scalar( 0, 0, 255 ),0,8, 0 );
return mRgba;
}
}
It is quite easy to store the rectangles in a List. I have made some small adjustments that should work.
private List<Rect> ListOfRect = new ArrayList<Rect>();
#Override
public boolean onTouch(View arg0,MotionEvent event) {
double cols = mRgba.cols();
double rows = mRgba.rows();
double xOffset = (mOpenCvCameraView.getWidth() - cols) / 2;
double yOffset = (mOpenCvCameraView.getHeight() - rows) / 2;
h[i] = (double)(event).getX() - xOffset;
k[i] = (double)(event).getY() - yOffset;
h[i]=x;
k[i]=y;
ListOfRect.add(new Rect(x-100, y-100, x+100, y+100));
Log.i(TAG, "Touch image coordinates: (" + h[i] + ", " + k[i] + ")");
i++;
return false;// don't need subsequent touch events
}
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
mRgba=inputFrame.rgba();
for(int i=0; i<ListOfRect.size(); i++){
Core.rectangle(mRgba, ListOfRect.get(i).tl(), ListOfRect.get(i).br(),new Scalar( 0, 0, 255 ),0,8, 0 );}
return mRgba;
}
However keep in mind that you need to release and clear your list to free memory when you don't need the rectangles anymore. I hope it helped.
I have been researching and struggling with my code to get a textview to update the score when a "ghost" is touched.
This is my first Android application and so far as i can tell(i added Log.w() to the ontouch but a log is never posted as well as the score not being incremented or even appearing) the onTouch(View v, MotionEvent event) is never called. Below is my code.
package com.cs461.Ian;
//TODO:Add accelerometer support
//TODO:Add Clickable ghosts
//TODO:Add camera background
/*Completed:(As of 2:30am 4/16)
* Activity launches
* Ghost appears on screen
* Ghost will randomly move around the screen
*/
import java.util.Random;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.widget.TextView;
public class CameraActivity extends Activity{
Bitmap g;
Ghost a;
Ghost still;
SurfaceHolder mSurfaceHolder;
boolean firsttime=true;
int draw_x,draw_y,xSpeed,ySpeed,score=0;
TextView t;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game);
a = new Ghost(getApplicationContext());
still = new Ghost(getApplicationContext());
//requestWindowFeature(Window.FEATURE_NO_TITLE);
a.Initalize(BitmapFactory.decodeResource(getResources(), R.drawable.ghost), 20, 20);
still.Initalize(BitmapFactory.decodeResource(getResources(), R.drawable.ghost), 120, 120);
t = (TextView) findViewById(R.id.t);
t.setText("TEST SCORE TO SEE IF TEXTVIEW SHOWS UP");
a.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
score++;
t.setText("Score: "+score);
}
return true;
}
});
still.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
score++;
t.setText("Score: "+score);
Log.w("CLICKED","Clicked on ghost "+score+" times");
}
return true;
}
});
setContentView(new Panel(this));
}
class Panel extends View {
public Panel(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
//g.Initalise(BitmapFactory.decodeFile("/res/drawable-hdpi/ghost.png"), 200, 150, 5, 5);;
update(canvas);
invalidate();
}
/*Places ghost on screen and bounces it around in the screen. My phone is apparently only API level 4(the most up to date is 15) so i didn't code it
*for the accelerometer yet.
*/
public void update(Canvas canvas) {
Random rand = new Random();
if(firsttime){
draw_x = Math.round(System.currentTimeMillis() % (this.getWidth()*2)) ;
draw_y = Math.round(System.currentTimeMillis() % (this.getHeight()*2)) ;
xSpeed = rand.nextInt(10);
ySpeed = rand.nextInt(10);
firsttime=false;
}
draw_x+=xSpeed;
draw_y+=ySpeed;
draw_x = Math.round(System.currentTimeMillis() % (this.getWidth()*2)) ;
draw_y = Math.round(System.currentTimeMillis() % (this.getHeight()*2)) ;
if (draw_x>this.getWidth()){
draw_x = (this.getWidth()*2)-draw_x;
xSpeed = rand.nextInt(10);
if(xSpeed >=5)
xSpeed=-xSpeed;
}
if (draw_y>this.getHeight()){
draw_y = (this.getHeight()*2)-draw_y;
ySpeed = rand.nextInt(10);
if(ySpeed >=5)
ySpeed=-ySpeed;
}
g = BitmapFactory.decodeResource(getResources(), R.drawable.ghost);
canvas.drawBitmap(g, draw_x, draw_y, null);
still.draw(canvas);
a.update(canvas);
}
}
}
Forgot to add class Ghost:
package com.cs461.Ian;
import java.util.Random;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class Ghost extends View implements View.OnTouchListener{
public Ghost(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
private Bitmap mAnimation;
private int mXPos;
private int mYPos;
private Rect mSRectangle;
private int mSpriteHeight;
private int mSpriteWidth;
View v;
Rect dest;
int score = 0;
/*public Ghost() {
mSRectangle = new Rect(0,0,0,0);
mXPos = 80;
mYPos = 200;
}*/
public void Initalize(Bitmap theBitmap, int Height, int Width) {
mSRectangle = new Rect(0,0,0,0);
mXPos = 80;
mYPos = 200;
mAnimation = theBitmap;
mSpriteHeight = Height;
mSpriteWidth = Width;
mSRectangle.top = 0;
mSRectangle.bottom = mSpriteHeight;
mSRectangle.left = 0;
mSRectangle.right = mSpriteWidth;
dest = new Rect(mXPos, mYPos, mXPos + mSpriteWidth,
mYPos + mSpriteHeight);
}
public void draw(Canvas canvas) {
canvas.drawBitmap(mAnimation, mXPos, mYPos, null);
}
public void update(Canvas canvas) {
new Random();
mXPos = Math.round(System.currentTimeMillis() % (canvas.getWidth()*2)) ;
mYPos = Math.round(System.currentTimeMillis() % (canvas.getHeight()*2)) ;
if (mXPos>canvas.getWidth())
mXPos = (canvas.getWidth()*2)-mXPos;
if (mYPos>canvas.getHeight())
mYPos = (canvas.getHeight()*2)-mYPos;
draw(canvas);
}
public Rect getRect() {
return mSRectangle;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
score++;
//CameraActivity.t.setText("Score: "+CameraActivity.score);
Log.w("CLICKED","Clicked on ghost "+score+" times");
return true; //doesn't work if returns false either
}
}
Override dispatchTouchEvent(MotionEvent event) in your Activity to handle all the touch events that may occur. Return false to pass down the MotionEvent to the next view\layout in the hierachy if they they handle events.