How to add an OnClick event for an Android custom View - java

I have two images moving across the screen, one is a ball and one is a man.
What I want to happen is when the user touches the image of the man, the ball drops.
My problem is I cannot seem to add an onclick/ontouch event and get it to work.
I'm not implementing it properly, can anyone help please?
I have included the 3 classes below. Greg is the man and the ball is named ball :)
TestAnimationActivity.java
package com.test.firstAnimation;
import android.app.Activity;
import android.os.Bundle;
public class TestAnimationActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyAnimationView(this));
}
}
Sprite.java
package com.test.firstAnimation;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;
public class Sprite extends View implements OnClickListener{
private static int gregCoordX = 410; // the x coordinate at the canvas for greg
private Bitmap img; // the image of Greg
private Bitmap img2; // the image of pointer
private static int gregCoordY = 125; // the y coordinate at the canvas for greg
private static int pointCoordX = 10;
private static int pointCoordY = 10;
private static int count = 1;
private static int ballSpeed = 25;
private static boolean goingRight = false;
private static boolean goingLeft = true;
private static boolean pointerGoingRight = false;
private static boolean pointerGoingLeft = true;
public Sprite(Context context, int drawable) {
super(context);
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
img = BitmapFactory.decodeResource(context.getResources(), drawable);
img2 = (BitmapFactory.decodeResource(context.getResources(), drawable));
count++;
}
public static int getCount() {
return count;
}
void setX(int newValue) {
gregCoordX = newValue;
}
public static int getX() {
return gregCoordX;
}
public static int getY() {
return gregCoordY;
}
public static int getBX() {
return pointCoordX;
}
public static int getBY() {
return pointCoordY;
}
public Bitmap getBitmap() {
return img;
}
public Bitmap getImg2() {
return img2;
}
public static void dropBall()
{
pointCoordY++;
}
public static void moveBall(int x) {
// check the borders
//if more than ten go right
//if ten go left
//if more than 250 go left
if (x <= 10 && pointerGoingLeft)
{
pointCoordX = pointCoordX + ballSpeed;
pointerGoingRight = true;
pointerGoingLeft = false;
}
else if (x >= 410 && pointerGoingRight)
{
pointCoordX = pointCoordX - ballSpeed;
pointerGoingLeft = true;
pointerGoingRight = false;
}
else if (pointerGoingRight)
pointCoordX = pointCoordX + ballSpeed;
else
pointCoordX = pointCoordX - ballSpeed;
if(MyAnimationView.ballDropping == true)
{
while (pointCoordY<gregCoordY)
dropBall();
}
}
public static void moveGreg(int x) {
if (x <= 10 && goingLeft)
{
gregCoordX = gregCoordX + count;
goingRight = true;
goingLeft = false;
}
else if (x >= 410 && goingRight)
{
gregCoordX = gregCoordX - count;
goingLeft = true;
goingRight = false;
}
else if (goingRight)
gregCoordX = gregCoordX + count;
else
gregCoordX = gregCoordX - count;
}
#Override
public void onClick(View arg0) {
dropBall();
}
}
MyAnimationView.java
package com.test.firstAnimation;
import android.content.Context;
import android.graphics.Canvas;
import android.view.View;
public class MyAnimationView extends View{
private Sprite greg;
private Sprite ball;
private int xCoOr;
private int ballXCoOr;
public static boolean ballDropping;
public MyAnimationView(Context context) {
super(context);
ballDropping = false;
greg = new Sprite(context,R.drawable.greg);
ball = new Sprite(context, R.drawable.ball);
OnClickListener gregClicked = new OnClickListener() {
public void onClick(View v) {
ballDropping = true;
}
};
greg.setOnClickListener(gregClicked);
}
#Override protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFFFFFFF); //white background
ballXCoOr = Sprite.getBX();
xCoOr = Sprite.getX();
Sprite.moveGreg(xCoOr); //move ball left or right depending
Sprite.moveBall(ballXCoOr);
if(ballDropping == true)
{
Sprite.dropBall();
}
canvas.drawBitmap(greg.getBitmap(), xCoOr, Sprite.getY(), null);
canvas.drawBitmap(ball.getBitmap(), ballXCoOr, Sprite.getBY(), null);
invalidate();
}
}
Thanks in advance, I've been stuck for days!
Ben

float touched_x, touched_y;
boolean touched = false;
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
touchCounter++;
touched_x = event.getX();
touched_y = event.getY();
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
touched = true;
break;
case MotionEvent.ACTION_MOVE:
touched = true;
break;
case MotionEvent.ACTION_UP:
touched = false;
break;
case MotionEvent.ACTION_CANCEL:
touched = false;
break;
case MotionEvent.ACTION_OUTSIDE:
touched = false;
break;
default:
}
return true; // processed
}
Then;
if (touched) {
//control here
}
touched_x, touched_y are coordinates of the point that is clicked on the screen. You can compare Greg's coordinates and these coordinates. If same, then do what you wanna do.

public class CustomView extends View implements OnClickListener {
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomView(Context context) {
super(context);
init();
}
private void init(){
setOnClickListener(this);
}
#Override
public void onClick(View v) {
// Do whatever you need to
}
}

Related

How to get bitmap from Surface View

I am attempting to get bitmap from my surface view. I've already seen many answers on this forum and on mostly all forums. I am using a custom class of ViewGroup in which i'm using a surface view to preview the camera image and the Graphic Overlay.
This is my CameraSourcePreview.class
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.SurfaceTexture;
import android.support.v7.util.AsyncListUtil;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.gms.common.images.Size;
import com.google.android.gms.vision.CameraSource;
import java.io.IOException;
public class CameraSourcePreview extends ViewGroup {
private static final String TAG = "CameraSourcePreview";
private Context mContext;
private SurfaceView mSurfaceView;
private boolean mStartRequested;
private boolean mSurfaceAvailable;
private CameraSource mCameraSource;
private GraphicOverlay mOverlay;
public CameraSourcePreview(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mStartRequested = false;
mSurfaceAvailable = false;
mSurfaceView = new SurfaceView(context);
mSurfaceView.getHolder().addCallback(new SurfaceCallback());
addView(mSurfaceView);
}
public void start(CameraSource cameraSource) throws IOException {
if (cameraSource == null) {
stop();
}
mCameraSource = cameraSource;
if (mCameraSource != null) {
mStartRequested = true;
startIfReady();
}
}
public void start(CameraSource cameraSource, GraphicOverlay overlay) throws IOException {
mOverlay = overlay;
start(cameraSource);
}
public void stop() {
if (mCameraSource != null) {
mCameraSource.stop();
}
}
public void release() {
if (mCameraSource != null) {
mCameraSource.release();
mCameraSource = null;
}
}
private void startIfReady() throws IOException {
if (mStartRequested && mSurfaceAvailable) {
mCameraSource.start(mSurfaceView.getHolder());
if (mOverlay != null) {
Size size = mCameraSource.getPreviewSize();
int min = Math.min(size.getWidth(), size.getHeight());
int max = Math.max(size.getWidth(), size.getHeight());
if (isPortraitMode()) {
// Swap width and height sizes when in portrait, since it will be rotated by
// 90 degrees
mOverlay.setCameraInfo(min, max, mCameraSource.getCameraFacing());
} else {
mOverlay.setCameraInfo(max, min, mCameraSource.getCameraFacing());
}
mOverlay.clear();
}
mStartRequested = false;
}
}
private class SurfaceCallback implements SurfaceHolder.Callback {
#Override
public void surfaceCreated(SurfaceHolder surface) {
mSurfaceAvailable = true;
try {
startIfReady();
} catch (IOException e) {
Log.e(TAG, "Could not start camera source.", e);
}
}
#Override
public void surfaceDestroyed(SurfaceHolder surface) {
mSurfaceAvailable = false;
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int width = 320;
int height = 240;
if (mCameraSource != null) {
Size size = mCameraSource.getPreviewSize();
if (size != null) {
width = size.getWidth();
height = size.getHeight();
}
}
// Swap width and height sizes when in portrait, since it will be rotated 90 degrees
if (isPortraitMode()) {
int tmp = width;
width = height;
height = tmp;
}
final int layoutWidth = right - left;
final int layoutHeight = bottom - top;
// Computes height and width for potentially doing fit width.
int childWidth = layoutWidth;
int childHeight = layoutHeight;
//(int)(((float) layoutWidth / (float) width) * height);
/*
// If height is too tall using fit width, does fit height instead.
if (childHeight > layoutHeight) {
childHeight = layoutHeight;
childWidth = (int)(((float) layoutHeight / (float) height) * width);
}*/
for (int i = 0; i < getChildCount(); ++i) {
getChildAt(i).layout(0, 0, childWidth, childHeight);
}
try {
startIfReady();
} catch (IOException e) {
Log.e(TAG, "Could not start camera source.", e);
}
}
private boolean isPortraitMode() {
int orientation = mContext.getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
return false;
}
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
return true;
}
Log.d(TAG, "isPortraitMode returning false by default");
return false;
}
}
Now when I capture the image from CameraSource it snapshots the image but not the graphic overlay which i'm inflating on the surface view. Neither does the surface view lets me take a bitmap from it. If i try to get screenshot of the root view then it captures only the Graphic Overlay not the surface view image.
My app is working on the logic of a face filter github project(link will be provided upon request)
I'm basically stuck because i want to capture both.
you have to take a particular view screenshot like convert any view into bitmap this way
How to convert Views to bitmaps?

How do you show where on the board the user has pressed for a mobile sudoku game?

I am making a sudoku game in java - Intellij. I want to show the user where they have pressed and I do not know how to do so.
If you need the whole file its on the github:
https://github.com/SamirSydykov03/Sudoku-Varients-for-mobile-phones
Here is my Game.java
import com.example.sudokuvarients.normalsudoku9x9.SudokuGrid.GameGrid;
public class Game {
private static Game instance;
private GameGrid grid = null;
private int selectedX = -1;
private int selectedY = -1;
private Game(){}
public static Game getInstance(){
if(instance == null){
instance = new Game();
}
return instance;
}
public void createGrid(Context context){
int[][] Sudoku = SudokuGenerator.getInstance().generateGrid();
Sudoku = SudokuGenerator.getInstance().removal(Sudoku);
grid = new GameGrid(context);
grid.setGrid(Sudoku);
}
public GameGrid getGrid(){
return grid;
}
public void setSelectedPos(int x, int y){
setSelectedItem();
selectedX = x;
selectedY = y;
}
public void setSelectedItem(){
grid.getItem(-1,-1);
}
public void setNumber(int number){
if(selectedY != -1 && selectedX != -1){
grid.setItem(selectedX,selectedY,number);
}
grid.checkGame();
}
Here is my BaseSudokoCell.java
package com.example.sudokuvarients.normalsudoku9x9.SudokuGrid;
import android.content.Context;
import android.view.View;
public class BaseSudokuCell extends View {
private boolean modify = true;
private int value;
private boolean selected;
public BaseSudokuCell(Context context) {
super(context);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
public void setNotModify(){
modify = false;
}
public void setInitialValue(int value){
this.value = value;
invalidate();
}
public void setValue(int value){
if(modify){
this.value = value;
}
invalidate();
}
public boolean getSelect(){
return selected;
}
public int getValue(){
return value;
}
}
Here is my SudokuCell.java - It does draw a tile, but it does not hide and it is drawn in all the cells. It does not do anything when clicked.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;
public class SudokuCell extends BaseSudokuCell{
private Paint mPaint;
public SudokuCell(Context context){
super(context);
mPaint =new Paint();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawNumber(canvas);
drawLines(canvas);
drawRectangle(canvas);
}
private void drawLines(Canvas canvas) {
mPaint.setColor(Color.MAGENTA);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
canvas.drawRect(0,0,getWidth(), getHeight(), mPaint);
}
private void drawNumber(Canvas canvas) {
mPaint.setColor(Color.CYAN);
mPaint.setTextSize(60);
mPaint.setStyle(Paint.Style.FILL);
Rect bounds = new Rect();
mPaint.getTextBounds(String.valueOf(getValue()), 0, String.valueOf(getValue()).length(), bounds);
if (getValue() != 0) {
canvas.drawText(String.valueOf(getValue()), (getWidth() - bounds.width()) / 2, (getHeight() + bounds.height()) / 2, mPaint);
}
}
private void drawRectangle(Canvas canvas){
Rect ourRect = new Rect();
ourRect.set(0,0,canvas.getWidth()-5,canvas.getHeight()-5);
Paint grey = new Paint();
grey.setColor(Color.GRAY);
grey.setStyle(Paint.Style.FILL);
canvas.drawRect(ourRect,grey);
}
}

Player Character Movement Error LibGDX RPG

I am making an RPG game, however, I have an error at the moment. The player's character can move in all four cardinal directions, but the player becomes stuck if you move right, up or down.
Also, the error seems to have some logic to it:
if moving down, the character is stuck in a loop moving down
unless the up arrow is pressed, then the player will begin a new infinite loop for up
unless the right arrow is pressed, then the player will begin a new infinite loop for right
So right seems to take precedence over up which takes precedence over down.
Strangely, the leftward movement works perfectly. Even when the character is stuck in an infinite loop, the left arrow key will always cause the player to move left in the correct way.
I don't understand where the error is in my code. I don't know why the leftward movement works while the other three directions do not. I don't understand why there seems to be some sort of priority ordering between the other three directions as well.
I have looked through the program and I don't think I treat leftward movement differently to any other direction. However, I might be wrong, considering this error.
Due to the 30k word limit, I do not have enough space to include all the code here. Therefore, I have included a link to my github, so you can see the code there instead.
https://github.com/davey67/bludbourne
I think these classes are probably the most important classes though:
package com.bludbourne.game.desktop;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.bludbourne.game.BludBourne;
public class DesktopLauncher {
public static void main (String[] arg) {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.title="BludBourne";
config.useGL30=false;
config.width =480;
config.height=480;
Application app = new LwjglApplication(new BludBourne(),config);
Gdx.app=app;
Gdx.app.setLogLevel(Application.LOG_DEBUG);
}
}
/
package com.bludbourne.game;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.bludbourne.game.screens.MainGameScreen;
import com.badlogic.gdx.Game;
public class BludBourne extends Game {
public static final MainGameScreen _mainGameScreen = new MainGameScreen();
#Override
public void create () {
setScreen(_mainGameScreen);
}
#Override
public void dispose () {
_mainGameScreen.dispose();
}
}
/
package com.bludbourne.game;
import java.util.HashMap;
import java.util.Map;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.math.Vector3;
public class PlayerController implements InputProcessor
{
private final static String TAG = PlayerController.class.getSimpleName();
enum Keys{
LEFT,RIGHT,UP,DOWN,QUIT
}
enum Mouse{
SELECT,DOACTION
}
private static Map<Keys,Boolean> keys=new HashMap<PlayerController.Keys,Boolean>();
private static Map<Mouse,Boolean> mouseButtons = new HashMap<PlayerController.Mouse,Boolean>();
private Vector3 lastMouseCoordinates;
static {
keys.put(Keys.LEFT,false);
keys.put(Keys.RIGHT,false);
keys.put(Keys.UP,false);
keys.put(Keys.DOWN, false);
keys.put(Keys.QUIT, false);
}
static {
mouseButtons.put(Mouse.SELECT, false);
mouseButtons.put(Mouse.DOACTION, false);
}
private Entity _player;
public PlayerController(Entity player) {
this.lastMouseCoordinates=new Vector3();
this._player=player;
}
#Override
public boolean keyDown(int keycode)
{
if(keycode ==Input.Keys.LEFT||keycode==Input.Keys.A) {
this.leftPressed();
}
if(keycode ==Input.Keys.RIGHT||keycode==Input.Keys.D) {
this.rightPressed();
}
if(keycode ==Input.Keys.UP||keycode==Input.Keys.W) {
this.upPressed();
}
if(keycode ==Input.Keys.DOWN||keycode==Input.Keys.S) {
this.downPressed();
}
if(keycode==Input.Keys.Q) {
this.quitPressed();
}
return true;
}
#Override
public boolean keyUp(int keycode)
{
if(keycode ==Input.Keys.LEFT||keycode==Input.Keys.A) {
this.leftReleased();
}
if(keycode ==Input.Keys.RIGHT||keycode==Input.Keys.D) {
this.rightReleased();
}
if(keycode ==Input.Keys.UP||keycode==Input.Keys.W) {
this.upReleased();
}
if(keycode ==Input.Keys.DOWN||keycode==Input.Keys.S) {
this.downReleased();
}
if(keycode==Input.Keys.Q) {
this.quitReleased();
}
return true;
}
#Override
public boolean keyTyped(char character)
{
// TODO Auto-generated method stub
return false;
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button)
{
if(button==Input.Buttons.LEFT||button==Input.Buttons.RIGHT) {
this.setClickedMouseCoordinates(screenX,screenY);
}
if(button==Input.Buttons.LEFT) {
this.selectMouseButtonPressed(screenX,screenY);
}
if(button==Input.Buttons.RIGHT) {
this.doActionMouseButtonPressed(screenX,screenY);
}
return true;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button)
{
if(button==Input.Buttons.LEFT) {
this.selectMouseButtonReleased(screenX,screenY);
}
if(button==Input.Buttons.RIGHT) {
this.doActionMouseButtonReleased(screenX,screenY);
}
return true;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer)
{
// TODO Auto-generated method stub
return false;
}
#Override
public boolean mouseMoved(int screenX, int screenY)
{
// TODO Auto-generated method stub
return false;
}
#Override
public boolean scrolled(int amount)
{
// TODO Auto-generated method stub
return false;
}
public void dispose() {
}
public void leftPressed() {
keys.put(Keys.LEFT,true);
}
public void rightPressed() {
keys.put(Keys.RIGHT,true);
}
public void upPressed() {
keys.put(Keys.UP,true);
}
public void downPressed() {
keys.put(Keys.DOWN,true);
}
public void quitPressed() {
keys.put(Keys.QUIT, true);
}
public void setClickedMouseCoordinates(int x,int y) {
lastMouseCoordinates.set(x,y,0);
}
public void selectMouseButtonPressed(int x,int y) {
mouseButtons.put(Mouse.SELECT,true);
}
public void doActionMouseButtonPressed(int x,int y) {
mouseButtons.put(Mouse.DOACTION, true);
}
public void leftReleased() {
keys.put(Keys.LEFT,false);
}
public void rightReleased() {
keys.put(Keys.RIGHT,true);
}
public void upReleased() {
keys.put(Keys.UP,true);
}
public void downReleased() {
keys.put(Keys.DOWN,true);
}
public void quitReleased() {
keys.put(Keys.QUIT, true);
}
public void selectMouseButtonReleased(int x,int y) {
mouseButtons.put(Mouse.SELECT, false);
}
public void doActionMouseButtonReleased(int x ,int y) {
mouseButtons.put(Mouse.DOACTION, false);
}
public void update(float delta) {
processInput(delta);
}
public static void hide() {
keys.put(Keys.LEFT, false);
keys.put(Keys.RIGHT, false);
keys.put(Keys.UP, false);
keys.put(Keys.DOWN, false);
keys.put(Keys.QUIT, false);
}
private void processInput(float delta) {
if(keys.get(Keys.LEFT)) {
_player.calculateNextPosition(Entity.Direction.LEFT,delta);
_player.setState(Entity.State.WALKING);
_player.setDirection(Entity.Direction.LEFT,delta);
}
else if(keys.get(Keys.RIGHT)) {
_player.calculateNextPosition(Entity.Direction.RIGHT,delta);
_player.setState(Entity.State.WALKING);
_player.setDirection(Entity.Direction.RIGHT,delta);
}
else if(keys.get(Keys.UP)) {
_player.calculateNextPosition(Entity.Direction.UP,delta);
_player.setState(Entity.State.WALKING);
_player.setDirection(Entity.Direction.UP,delta);
}
else if(keys.get(Keys.DOWN)) {
_player.calculateNextPosition(Entity.Direction.DOWN,delta);
_player.setState(Entity.State.WALKING);
_player.setDirection(Entity.Direction.DOWN,delta);
}
else if(keys.get(Keys.QUIT)) {
Gdx.app.exit();
}
else {
_player.setState(Entity.State.IDLE);
}
if(mouseButtons.get(Mouse.SELECT)) {
mouseButtons.put(Mouse.SELECT, false);
}
}
}
/
package com.bludbourne.game;
import java.util.UUID;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
public class Entity
{
private static final String TAG = Entity.class.getSimpleName();
private static final String _defaultSpritePath = "sprites/characters/Warrior.png";
private Vector2 _velocity;
private String _entityID;
private Direction _currentDirection = Direction.LEFT;
private Direction _previousDirection = Direction.UP;
private Animation _walkLeftAnimation;
private Animation _walkRightAnimation;
private Animation _walkUpAnimation;
private Animation _walkDownAnimation;
private Array<TextureRegion> _walkLeftFrames;
private Array<TextureRegion> _walkRightFrames;
private Array<TextureRegion> _walkUpFrames;
private Array<TextureRegion> _walkDownFrames;
protected Vector2 _nextPlayerPosition;
protected Vector2 _currentPlayerPosition;
protected State _state = State.IDLE;
protected float _frameTime = 0f;
protected Sprite _frameSprite = null;
protected TextureRegion _currentFrame = null;
public final int FRAME_WIDTH = 16;
public final int FRAME_HEIGHT = 16;
public static Rectangle boundingBox;
public enum State
{
IDLE, WALKING
}
public enum Direction
{
UP, RIGHT, DOWN, LEFT
}
public Entity() {
initEntity();
}
public void initEntity()
{
this._entityID = UUID.randomUUID().toString();
this._nextPlayerPosition = new Vector2();
this._currentPlayerPosition = new Vector2();
this.boundingBox = new Rectangle();
this._velocity = new Vector2(2f, 2f);
Utility.loadTextureAsset(_defaultSpritePath);
loadDefaultSprite();
loadAllAnimations();
}
public void update(float delta)
{
_frameTime = (_frameTime + delta) % 5;
setBoundingBoxSize(0f, 0.5f);
}
public void init(float startX, float startY)
{
this._currentPlayerPosition.x = startX;
this._currentPlayerPosition.y = startY;
this._nextPlayerPosition.x = startX;
this._nextPlayerPosition.y = startY;
}
public void setBoundingBoxSize(float percentageWidthReduced, float percentageHeightReduced)
{
float width;
float height;
float widthReductionAmount = 1.0f - percentageWidthReduced;
float heightReductionAmount = 1.0f - percentageHeightReduced;
if (widthReductionAmount > 0 && widthReductionAmount < 1)
{
width = FRAME_WIDTH * widthReductionAmount;
}
else
{
width = FRAME_WIDTH;
}
if (heightReductionAmount > 0 && heightReductionAmount < 1)
{
height = FRAME_HEIGHT * heightReductionAmount;
}
else
{
height = FRAME_HEIGHT;
}
if (width == 0 || height == 0)
{
Gdx.app.debug(TAG, "Width and Height are 0!! " + width + ":" + height);
}
float minX;
float minY;
if (MapManager.UNIT_SCALE > 0)
{
minX = _nextPlayerPosition.x / MapManager.UNIT_SCALE;
minY = _nextPlayerPosition.y / MapManager.UNIT_SCALE;
}
else
{
minX = _nextPlayerPosition.x;
minY = _nextPlayerPosition.y;
}
boundingBox.set(minX, minY, width, height);
}
private void loadDefaultSprite()
{
Texture texture = Utility.getTextureAsset(_defaultSpritePath);
TextureRegion[][] textureFrames = TextureRegion.split(texture, FRAME_WIDTH, FRAME_HEIGHT);
_frameSprite = new Sprite(textureFrames[0][0].getTexture(), 0, 0, FRAME_WIDTH, FRAME_HEIGHT);
_currentFrame = textureFrames[0][0];
}
public void loadAllAnimations()
{
Texture texture = Utility.getTextureAsset(_defaultSpritePath);
TextureRegion[][] textureFrames = TextureRegion.split(texture, FRAME_WIDTH, FRAME_HEIGHT);
_walkDownFrames = new Array<TextureRegion>(4);
_walkLeftFrames = new Array<TextureRegion>(4);
_walkRightFrames = new Array<TextureRegion>(4);
_walkUpFrames = new Array<TextureRegion>(4);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
TextureRegion region=textureFrames[i][j];
if(region==null) {
Gdx.app.debug(TAG, "Got null animation frame "+i+","+j);
}
switch(i) {
case 0:
_walkDownFrames.insert(j,region);
break;
case 1:
_walkLeftFrames.insert(j,region);
break;
case 2:
_walkRightFrames.insert(j,region);
break;
case 3:
_walkUpFrames.insert(j,region);
break;
}
}
}
_walkDownAnimation = new Animation(0.25f,_walkDownFrames,Animation.PlayMode.LOOP);
_walkLeftAnimation = new Animation(0.25f,_walkLeftFrames,Animation.PlayMode.LOOP);
_walkRightAnimation = new Animation(0.25f,_walkRightFrames,Animation.PlayMode.LOOP);
_walkUpAnimation = new Animation(0.25f,_walkUpFrames,Animation.PlayMode.LOOP);
}
public void dispose() {
Utility.unloadAsset(_defaultSpritePath);
}
public void setState(State state) {
this._state = state;
}
public Sprite getFrameSprite() {
return _frameSprite;
}
public TextureRegion getFrame() {
return _currentFrame;
}
public Vector2 getCurrentPosition() {
return _currentPlayerPosition;
}
public void setCurrentPosition(float currentPositionX,float currentPositionY) {
_frameSprite.setX(currentPositionX);
_frameSprite.setY(currentPositionY);
this._currentPlayerPosition.x=currentPositionX;
this._currentPlayerPosition.y=currentPositionY;
}
public void setDirection(Direction direction,float deltaTime) {
this._previousDirection=this._currentDirection;
this._currentDirection=direction;
switch(_currentDirection) {
//not sure about this
case DOWN:
_currentFrame=(TextureRegion) _walkDownAnimation.getKeyFrame(_frameTime);
break;
case LEFT:
_currentFrame=(TextureRegion) _walkLeftAnimation.getKeyFrame(_frameTime);
break;
case RIGHT:
_currentFrame=(TextureRegion) _walkRightAnimation.getKeyFrame(_frameTime);
break;
case UP:
_currentFrame=(TextureRegion) _walkUpAnimation.getKeyFrame(_frameTime);
break;
default:
break;
}
}
public void setNextPositionToCurrent() {
setCurrentPosition(_nextPlayerPosition.x,_nextPlayerPosition.y);
}
public void calculateNextPosition(Direction currentDirection,float deltaTime) {
float testX=_currentPlayerPosition.x;
float testY=_currentPlayerPosition.y;
_velocity.scl(deltaTime);
switch(currentDirection) {
case LEFT:
testX-=_velocity.x;
break;
case RIGHT:
testX+=_velocity.x;
break;
case UP:
testY+=_velocity.y;
break;
case DOWN:
testY-=_velocity.y;
break;
default:
break;
}
_nextPlayerPosition.x=testX;
_nextPlayerPosition.y=testY;
_velocity.scl(1/deltaTime);
}
}
I feel that I am probably missing something obvious, however, I still cannot see the error. Help is much appreciated. Thank you.
My github also contains the sprite sheet and the three maps, all of which would be stored in the asset folder of my project.
May I draw your attention to these four methods in PlayerInput
public void leftReleased() {
keys.put(Keys.LEFT,false);
}
public void rightReleased() {
keys.put(Keys.RIGHT,true);
}
public void upReleased() {
keys.put(Keys.UP,true);
}
public void downReleased() {
keys.put(Keys.DOWN,true);
}
I believe it should be false, not true when the key is released. I've verified that this prevents the infinite loop.
The priority order of right, up, then down is due to the order in which the keys are checked in processInput.

Handling TouchEvents concurrentModificationException android

I was trying to draw some balloons on screeen using canvas in SurfaceView class, I was successfully able to draw Multiple balloons on canvas and animate them by swapping different images. The problem is When I try touching on Oneballoon I need to remove it from screen .Here I get this exception and I am stuck
Code:
MainActivity:
package com.pradhul.game.touchball;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new GameView(this));
/*TODO Hide the bottom navigation bar */
}
}
GameView.java
package com.pradhul.game.touchball;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class GameView extends SurfaceView implements SurfaceHolder.Callback, View.OnTouchListener {
private static final int NUM_OF_BALLOONS = 5; //TODO for more than one balloons animations dont work(?)
/*use SurfaceView because we want complete control over the screen.
* unlike extending View class the oDraw() Method will not be called automatically
* from the method onSurfaceCreated() we have to call it Manually and pass a canvas object into it
* */
private final SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private List<Balloon> balloons = new ArrayList<>();
public GameView(Context context) {
super(context);
gameLoopThread = new GameLoopThread(this);
holder = getHolder();
holder.addCallback(this);
createBalloons(NUM_OF_BALLOONS);
this.setOnTouchListener(this);
}
private void createBalloons(int count) {
for(int i=0 ; i< count ;i++){
balloons.add(createBalloon());
}
}
#Override
protected void onDraw(Canvas canvas) {
if(canvas != null) {
canvas.drawColor(Color.WHITE);
for(Balloon balloon : balloons){
try {
gameLoopThread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
balloon.onDraw(canvas);
}
}
}
#SuppressLint("WrongCall")
#Override
public void surfaceCreated(SurfaceHolder holder) {
/*this is called when the view is created*/
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
/*pausing game Thread*/
gameLoopThread.setRunning(false);
while (true){
try {
gameLoopThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private Balloon createBalloon(){
return new Balloon(this);
}
#Override
public synchronized boolean onTouch(View v, MotionEvent event) {
Log.d("OnTouch real -", "x: " + event.getX() + ", Y: " + event.getY());
/* for (int i = balloons.size()-1; i >= 0; i--) {
Balloon balloon = balloons.get(i);
Log.d("OnTouch collision -", !balloon.isCollision(event.getX(), event.getY())+"");
if (!balloon.isCollision(event.getX(), event.getY())) {
balloons.remove(0);
break;
}
}*/
Iterator<Balloon> balloonIterator = balloons.iterator();
while(balloonIterator.hasNext()){
Balloon balloon = balloonIterator.next();
balloons.remove(0);
}
return true;
}
}
GameLoopThread.java
package com.pradhul.game.touchball;
import android.annotation.SuppressLint;
import android.graphics.Canvas;
public class GameLoopThread extends Thread {
private GameView view;
private boolean running = false;
public GameLoopThread(GameView view){
this.view = view;
}
public void setRunning(boolean run){
running = run;
}
#SuppressLint("WrongCall")
public void run(){
while (running){
Canvas canvas = null;
try{
canvas = view.getHolder().lockCanvas();
synchronized (view.getHolder()){
view.onDraw(canvas);
}
}finally{
if(canvas != null) {
view.getHolder().unlockCanvasAndPost(canvas);
}
}
}
}
}
Balloon.java
package com.pradhul.game.touchball;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.Log;
import java.util.Random;
public class Balloon {
private static final int BALLOON_SPEED = 10;
private int y = 0;
private int x = 0;
private int speed = 1;
private GameView gameView;
private Bitmap balloon;
public Bitmap[] normalBalloons;
private int balloonIndex = 0;
private int normalImages[] = {R.drawable.normal_01,R.drawable.normal_02,R.drawable.normal_03,
R.drawable.normal_04,R.drawable.normal_05,R.drawable.normal_06,R.drawable.normal_07,
R.drawable.normal_08,
};
private int crackingImages[] = {R.drawable.crack_01,R.drawable.crack_02,R.drawable.crack_03,
R.drawable.crack_04, R.drawable.crack_05,R.drawable.crack_04,R.drawable.crack_03,
R.drawable.crack_02
};
private boolean reverseSwap = false;
public Balloon(GameView gameView){
this.gameView = gameView;
normalBalloons = new Bitmap[8];
setUpImages();
}
public void onDraw(Canvas canvas){
/*draws the balloon in canvas */
animateBalloon();
update(canvas.getWidth());
canvas.drawBitmap(balloon, x, y, null);
}
public boolean isCollision(float x2, float y2) {
return x2 > x && x2 < x + balloon.getWidth() && y2 > y && y2 < y + balloon.getHeight();
}
private int getRandomX(int maxVal) {
Random rand = new Random();
return rand.nextInt(maxVal);
}
private void animateBalloon() {
/*Animates the balloon by swapping resource image at each call*/
this.balloon = getBalloons();
Log.d("Balloon",balloonIndex % normalBalloons.length + "");
}
private void update(int canvasWidth) {
/*updates the y position for moving the balloon*/
if (y <= 0){
/*so that the balloon starts from bottom
* gameView will return a height only after the View is ready
* getting 0 in constructor of this class*/
y = gameView.getHeight();
/*x is assigned a random between the width od the canvas
* so that the balloons will appear random positions from below*/
x = getRandomX(canvasWidth - balloon.getWidth());
}
if (y > gameView.getHeight() - balloon.getHeight() - speed) {
speed = -BALLOON_SPEED;
}
y = y + speed;
Log.d("Balloon","Positions:"+x+","+y);
}
private Bitmap getBalloons() {
if(balloonIndex == normalBalloons.length-1) {
reverseSwap = true;
}
if(balloonIndex == 0){
reverseSwap = false;
}
balloonIndex = reverseSwap?balloonIndex-1:balloonIndex+1;
return normalBalloons[balloonIndex];
}
private void setUpImages() {
/*setting up resources array*/
for(int count =0; count < normalImages.length; count++){
Bitmap balloon = BitmapFactory.decodeResource(gameView.getResources(), normalImages[count]);
normalBalloons[count] = balloon;
}
}
}
I am confused that why it causes an error like this , Can anybody can take look at it and suggest me a solution, is this the right way to remove ?
please share any suggestion
Thanks
It's the wrong way to remove.
If you iterate over a Collection / List, and want to remove the current element, you must use Iterator.remove() method.
In your case, simply call balloonIterator.remove() instead of balloons.remove(0)
Even simpler, since you want to remove all elements from the list - you should simply call balloons.clear() and remove the loop completely.
This exception is due to concurrent modification of list balloons.
As soon as you touch surface view onDraw() gets invoked with onTouch(), in which you are working on list balloons.
I think you should add touch listener to balloon instead of GameView.
okay ,
I need to wrap all my code inside a synchronized holder inorder this to work
(don't know much about it)
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("OnTouch","x:"+event.getX()+"Y:"+event.getY());
synchronized (getHolder()){
for (int i=0 ;i<balloons.size();i++){
balloons.remove(0);
break;
}
}
return true;
}

Dragging images after touch cordinates in android

I am making an android game that should drag an image after my touch cordinates in onTouchEvent(MotionEvent event) method. So far i have managed to move it by clicking, but not by dragging, how can i do this? Please help me and thanks so much in advance! Check out my onTouchEvent(MotionEvent event) method in this code:
package com.mysoftwaremobileapps.TriangleUnlocker;
import java.util.ArrayList;
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.media.MediaPlayer;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;
import android.widget.Toast;
public class GameScreenActivity extends SurfaceView implements SurfaceHolder.Callback
{
class ExampleThread extends Thread
{
private ArrayList<Triangle> triangles;
private Bitmap TriangleImage;
private Paint black;
private boolean running;
private SurfaceHolder mSurfaceHolder;
private Context mContext;
private Context mContext1;
private Handler mHandler;
private Handler mHandler1;
private TriangleUnlockerActivity mActivity;
private long frameRate;
private boolean loading;
public float x;
public float y;
public float x1;
public float y1;
public MediaPlayer mp1;
public int parachuterIndexToResetAndDelete;
public int canvasGetWidth;
public int livesLeftValue;
public ExampleThread(SurfaceHolder sHolder, Context context, Handler handler)
{
mSurfaceHolder = sHolder;
mHandler = handler;
mHandler1 = handler;
mContext = context;
mActivity = (TriangleUnlockerActivity) context;
triangles = new ArrayList<Triangle>();
TriangleImage = BitmapFactory.decodeResource(getResources(), R.drawable.triangle);
black = new Paint();
black.setStyle(Paint.Style.FILL);
black.setColor(Color.GRAY);
running = true;
// This equates to 26 frames per second.
frameRate = (long) (1000 / 26);
loading = true;
}
#Override
public void run()
{
while (running)
{
Canvas c = null;
try
{
c = mSurfaceHolder.lockCanvas();
synchronized (mSurfaceHolder)
{
long start = System.currentTimeMillis();
doDraw(c);
long diff = System.currentTimeMillis() - start;
if (diff < frameRate)
Thread.sleep(frameRate - diff);
}
} catch (InterruptedException e)
{
}
finally
{
if (c != null)
{
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
protected void doDraw(Canvas canvas)
{
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), black);
canvasGetWidth = canvas.getWidth();
//Draw
for (int i = 0; i < triangles.size(); i++)
{
canvas.drawBitmap(TriangleImage, triangles.get(i).getX(), triangles.get(i).getY(), null);
}
}
public boolean onTouchEvent(MotionEvent event)
{
if (event.getAction() != MotionEvent.ACTION_DOWN)
Toast.makeText(getContext(), "onTouchEvent invoked. X= " + event.getX() + " Y= " + event.getY(), 15).show();
x1 = event.getX();
y1 = event.getY();
for (Triangle p: triangles) {
Toast.makeText(getContext(), "Moving the triangle after touch cordinates", 25).show();
p.posX = event.getX();
p.posY = event.getY();
return false;
}
return loading;
}
public void displayTriangles()
{
//Parachuter nr.1
x = 14;
y = 28;
Triangle p = new Triangle(x, y);
triangles.add(p);
}
public void setRunning(boolean bRun)
{
running = bRun;
}
public boolean getRunning()
{
return running;
}
}
/** Handle to the application context, used to e.g. fetch Drawables. */
private Context mContext;
/** Pointer to the text view to display "Paused.." etc. */
private TextView mStatusText;
/** The thread that actually draws the animation */
private ExampleThread eThread;
public GameScreenActivity(Context context)
{
super(context);
// register our interest in hearing about changes to our surface
SurfaceHolder holder = getHolder();
holder.addCallback(this);
// create thread only; it's started in surfaceCreated()
eThread = new ExampleThread(holder, context, new Handler()
{
#Override
public void handleMessage(Message m)
{
// mStatusText.setVisibility(m.getData().getInt("viz"));
// mStatusText.setText(m.getData().getString("text"));
}
});
setFocusable(true);
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
return eThread.onTouchEvent(event);
}
public ExampleThread getThread()
{
return eThread;
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
{
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder)
{
if (eThread.getState() == Thread.State.TERMINATED)
{
eThread = new ExampleThread(getHolder(), getContext(), getHandler());
eThread.start();
}
else
{
eThread.start();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
boolean retry = true;
eThread.setRunning(false);
while (retry)
{
try
{
eThread.join();
retry = false;
}
catch (InterruptedException e)
{
}
}
}
}
if (event.getAction() == MotionEvent.ACTION_DOWN)
//set the x and y of your object here when action down
p.posX = event.getX();
p.posY = event.getY();
}
you can listen to the ACTION_MOVE event with GestureDetector http://developer.android.com/reference/android/view/GestureDetector.html

Categories