I just want to say I am very new to java app development.
So I have this image floating around the screen and when I touch the screen I want the image to change colors (switch from image to image1)
I got this working but the image gets moved to starting point, I want the transition to be smooth and to take place where the image is at certain point.
I have this code in my GameView.java class
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
private MainThread thread;
private CharacterSprite characterSprite;
private int col = 0;
public GameView(Context context){
super(context);
getHolder().addCallback(this);
thread = new MainThread(getHolder(),this);
setFocusable(true);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder){
characterSprite = new CharacterSprite(BitmapFactory.decodeResource(getResources(),R.drawable.avdgreen), 100, 100);
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder){
boolean retry = true;
while(retry){
try{
thread.setRunning(false);
thread.join();
}catch(InterruptedException e){
e.printStackTrace();
}
retry = false;
}
}
public void update(){
characterSprite.update();
}
public boolean onTouchEvent(MotionEvent event) {
int X = (int) event.getX();
int Y = (int) event.getY();
int eventaction = event.getAction();
switch (eventaction) {
case MotionEvent.ACTION_DOWN:
if(col == 0){
int ox = characterSprite.getX();
int oy = characterSprite.getY();
characterSprite.setX(ox);
characterSprite.setX(oy);
characterSprite = new CharacterSprite(BitmapFactory.decodeResource(getResources(),R.drawable.avdgreen1), ox, oy);
Toast.makeText(getContext(), "ACTION_UP "+"X: "+ox+" Y: "+oy, Toast.LENGTH_LONG).show();
col = 1;
}else{
int ox = characterSprite.getX();
int oy = characterSprite.getY();
characterSprite.setX(ox);
characterSprite.setX(oy);
characterSprite = new CharacterSprite(BitmapFactory.decodeResource(getResources(),R.drawable.avdgreen), ox, oy);
Toast.makeText(getContext(), "ACTION_UP "+"X: "+ox+" Y: "+oy, Toast.LENGTH_LONG).show();
col = 0;
}
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
#Override
public void draw(Canvas canvas){
super.draw(canvas);
if(canvas!=null){
characterSprite.draw(canvas);
}
}
This is where most of work is taking place, I also have CharacterSprite.java class which basicly creates the 'image' and makes it float around the screen:
public class CharacterSprite {
private Bitmap image;
private int x,y;
private int xVelocity = 10;
private int yVelocity = 5;
private int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
private int screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels;
public CharacterSprite(Bitmap bmp, int x, int y){
image = bmp;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public void setX(int nx){
x = nx;
}
public void setY(int ny){
y = ny;
}
public void draw(Canvas canvas){
canvas.drawBitmap(image,x,y,null);
}
public void update(){
if(x < 0 && y < 0){
x = screenWidth / 2;
y = screenHeight / 2;
}else{
x += xVelocity;
y += yVelocity;
if((x > screenWidth - image.getWidth()) || (x < 0)){
xVelocity = xVelocity*-1;
}
if((y > screenHeight - image.getHeight()) || (y < 0)){
yVelocity = yVelocity*-1;
}
}
}
as You can see I tried to get current x and y and set it back when creating new character, but that did not work, my guess is that this is happening because for a second the image is not on the screen and the whole thing reset but 1. I am not sure if thats right 2. I have no idea how I could fix that.
If anyone could point me where I should search that would be awesome.
#edit:
I changed to this Toast.makeText(getContext(), "ACTION_UP "+"X: "+characterSprite.getX()+" Y: "+characterSprite.getY(), Toast.LENGTH_LONG).show();
To debug and the output I am getting is ACTION_UP X: 0 Y: 0
ANSWER
Added
public void updateD(Canvas canvas){
canvas.drawBitmap(image,x,y,null);
}
To CharacterSprite.java and changed:
if(col == 0){
int ox = 550; //characterSprite.getX();
int oy = 550;//characterSprite.getY();
// characterSprite.setX(ox);
//characterSprite.setX(oy);
characterSprite = new CharacterSprite(BitmapFactory.decodeResource(getResources(),R.drawable.avdgreen1));
Toast.makeText(getContext(), "ACTION_UP "+"X: "+characterSprite.getX()+" Y: "+characterSprite.getY(), Toast.LENGTH_LONG).show();
col = 1;
}
To:
if(col == 0){
characterSprite.setImg(BitmapFactory.decodeResource(getResources(),R.drawable.avdgreen1));
Toast.makeText(getContext(), "ACTION_UP "+"X: "+characterSprite.getX()+" Y: "+characterSprite.getY(), Toast.LENGTH_LONG).show();
col = 1;
}
Related
I'm drawing a rectangle on a Canvas in Android. How do I drag it around on the screen? I have an onTouchEvent() method in my class that listens to MotionEvent(s). How do I use this to drag my rectangle around while preserving it's size.
My code is as follows:
public class CustomSquareView3 extends View {
private Rect rect;
private Paint paint;
public static int rotation = 45;
Canvas canvas;
int x1 = 200;
int x2 = 400;
int y1 = 200;
int y2 = 400;
public CustomSquareView3(Context context){
super(context);
int x = 50;
int y = 50;
int sideLength = 200;
rect = new Rect(x1,y1, x2, y2);
paint = new Paint();
paint.setColor(Color.GRAY);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
canvas.save();
canvas.rotate(rotation, (x1+x2)/2, (y1+y2)/2);
canvas.drawRect(rect, paint);
Paint paint2 = new Paint();
paint2.setColor(Color.WHITE);
paint2.setTextSize(50);
canvas.drawText("Hi", (x1+x2)/2, (y1+y2)/2, paint2);
canvas.restore();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int motionEvent = event.getAction();
float xMove = event.getX();
float yMove = event.getY();
switch (motionEvent){
case MotionEvent.ACTION_DOWN : {
x1 = (int) event.getX();
y1 = (int) event.getY();
rect = new Rect(x1, y1, x2, y2);
break;
}
case MotionEvent.ACTION_MOVE : {
x1 = (int) event.getX();
y1 = (int) event.getY();
rect = new Rect(x1, y1, x2, y2);
break;
}
case MotionEvent.ACTION_UP : {
x1 = (int) event.getX();
y1 = (int) event.getY();
rect = new Rect(x1, y1, x2, y2);
break;
}
default:
return false;
}
invalidate();
return true;
}
}
The above code resizes the rectangle every time I touch the screen. How do I get a smooth drag gesture in the code such that the size of the rectangle is maintained when it is dragged around the screen?
See this example:
class ViewPort extends View {
List<Layer> layers = new LinkedList<Layer>();
int[] ids = {R.drawable.layer0, R.drawable.layer1, R.drawable.layer2};
public ViewPort(Context context) {
super(context);
Resources res = getResources();
for (int i = 0; i < ids.length; i++) {
Layer l = new Layer(context, this, BitmapFactory.decodeResource(res, ids[i]));
layers.add(l);
}
}
#Override
protected void onDraw(Canvas canvas) {
for (Layer l : layers) {
l.draw(canvas);
}
}
private Layer target;
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
target = null;
for (int i = layers.size() - 1; i >= 0; i--) {
Layer l = layers.get(i);
if (l.contains(event)) {
target = l;
layers.remove(l);
layers.add(l);
invalidate();
break;
}
}
}
if (target == null) {
return false;
}
return target.onTouchEvent(event);
}
}
class Layer implements MatrixGestureDetector.OnMatrixChangeListener {
Matrix matrix = new Matrix();
Matrix inverse = new Matrix();
RectF bounds;
View parent;
Bitmap bitmap;
MatrixGestureDetector mgd = new MatrixGestureDetector(matrix, this);
public Layer(Context ctx, View p, Bitmap b) {
parent = p;
bitmap = b;
bounds = new RectF(0, 0, b.getWidth(), b.getHeight());
matrix.postTranslate(50 + (float) Math.random() * 50, 50 + (float) Math.random() * 50);
}
public boolean contains(MotionEvent event) {
matrix.invert(inverse);
float[] pts = {event.getX(), event.getY()};
inverse.mapPoints(pts);
if (!bounds.contains(pts[0], pts[1])) {
return false;
}
return Color.alpha(bitmap.getPixel((int) pts[0], (int) pts[1])) != 0;
}
public boolean onTouchEvent(MotionEvent event) {
mgd.onTouchEvent(event);
return true;
}
#Override
public void onChange(Matrix matrix) {
parent.invalidate();
}
public void draw(Canvas canvas) {
canvas.drawBitmap(bitmap, matrix, null);
}
}
class MatrixGestureDetector {
private static final String TAG = "MatrixGestureDetector";
private int ptpIdx = 0;
private Matrix mTempMatrix = new Matrix();
private Matrix mMatrix;
private OnMatrixChangeListener mListener;
private float[] mSrc = new float[4];
private float[] mDst = new float[4];
private int mCount;
interface OnMatrixChangeListener {
void onChange(Matrix matrix);
}
public MatrixGestureDetector(Matrix matrix, MatrixGestureDetector.OnMatrixChangeListener listener) {
this.mMatrix = matrix;
this.mListener = listener;
}
public void onTouchEvent(MotionEvent event) {
if (event.getPointerCount() > 2) {
return;
}
int action = event.getActionMasked();
int index = event.getActionIndex();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
int idx = index * 2;
mSrc[idx] = event.getX(index);
mSrc[idx + 1] = event.getY(index);
mCount++;
ptpIdx = 0;
break;
case MotionEvent.ACTION_MOVE:
for (int i = 0; i < mCount; i++) {
idx = ptpIdx + i * 2;
mDst[idx] = event.getX(i);
mDst[idx + 1] = event.getY(i);
}
mTempMatrix.setPolyToPoly(mSrc, ptpIdx, mDst, ptpIdx, mCount);
mMatrix.postConcat(mTempMatrix);
if(mListener != null) {
mListener.onChange(mMatrix);
}
System.arraycopy(mDst, 0, mSrc, 0, mDst.length);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
if (event.getPointerId(index) == 0) ptpIdx = 2;
mCount--;
break;
}
}
}
You have to redo it a little. Use your rectangle instead of bitmaps.
My app has 2 activities a main menu and a game play activity. you click play to start the game play and when you die you can click back to go to the main menu. For some reason when i click play for the third time (meaning ive died and went back to the main menu twice) the game crashes with this error.
FATAL EXCEPTION: main
Process: com.example.jordanschanzenbach.myapplication, PID: 1875
java.lang.OutOfMemoryError: Failed to allocate a 360012 byte allocation with 79976 free bytes and 78KB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:700)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:535)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:558)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:588)
at com.example.jordanschanzenbach.myapplication.Obstacle.<init>(Obstacle.java:44)
at com.example.jordanschanzenbach.myapplication.ObstacleManager.populateObstacles(ObstacleManager.java:57)
at com.example.jordanschanzenbach.myapplication.ObstacleManager.<init>(ObstacleManager.java:38)
at com.example.jordanschanzenbach.myapplication.GamePlayScene.<init>(GamePlayScene.java:41)
at com.example.jordanschanzenbach.myapplication.GamePanel.<init>(GamePanel.java:29)
at com.example.jordanschanzenbach.myapplication.MainActivity.onCreate(MainActivity.java:27)
that's not the entire error message but i think i gave you what you needed. Now i tried to make an animation for the obstacles to be spikes instead of just black rectangles but for some reason the spikes will not display and i think it might correspond with the error i receive. But i don't understand why the spikes wont display as i used the same code for the animation for my player.
here is the code for my obstacle
public class Obstacle implements GameObject
{
private Rect rectangle;
private Rect rectangle2;
private int color;
private Animation falling;
private Animation fallingStill;
private Animation fallingAgain;
private AnimationManagerObstacle animationManagerObstacle;
public Rect getRectangle()
{
return rectangle;
}
public void IncrementY(float y )
{
rectangle.top += y;
rectangle.bottom += y;
rectangle2.top += y;
rectangle2.bottom += y;
}
public Obstacle(int rectHeight, int color, int startX, int startY, int playerGap)
{
this.color = color;
BitmapFactory bitfac = new BitmapFactory();
Bitmap fallings = bitfac.decodeResource(GlobalVariables.CURRENT_CONTEXT.getResources(), R.drawable.spikesupsidedown);
Bitmap fallingStills = bitfac.decodeResource(GlobalVariables.CURRENT_CONTEXT.getResources(), R.drawable.spikesupsidedown);
Bitmap fallingAgains = bitfac.decodeResource(GlobalVariables.CURRENT_CONTEXT.getResources(), R.drawable.spikesupsidedown);
falling = new Animation(new Bitmap[]{fallings}, 2);
fallingStill = new Animation(new Bitmap[]{fallings, fallingStills}, 0.5f);
fallingAgain = new Animation(new Bitmap[]{fallings, fallingAgains}, 0.5f);
animationManagerObstacle = new AnimationManagerObstacle(new Animation[]{falling, fallingStill, fallingAgain});
rectangle = new Rect(0, startY, startX, startY + rectHeight);
rectangle2 = new Rect(startX + playerGap, startY, GlobalVariables.SCREEN_WIDTH, startY + rectHeight);
}
public boolean playerCollide(RectPlayer player)
{
return Rect.intersects(rectangle, player.getRectangle()) || Rect.intersects(rectangle2, player.getRectangle());
}
#Override
public void draw(Canvas canvas)
{
Paint paint = new Paint();
paint.setColor(color);
animationManagerObstacle.draw(canvas, rectangle);
canvas.drawRect(rectangle, paint);
canvas.drawRect(rectangle2, paint);
}
#Override
public void update()
{
animationManagerObstacle.update();
}
public void update(Point point)
{
float oldTop = rectangle.top;
rectangle.set(point.x - rectangle.width() / 2,
point.y - rectangle.height() / 2,
point.x + rectangle.width() / 2,
point.y + rectangle.height() / 2);
int state = 0;
if (rectangle.left - oldTop > 1)
{
state = 1;
}
else if (rectangle.left - oldTop < 2)
{
state = 2;
}
animationManagerObstacle.playAnim(state);
animationManagerObstacle.update();
}
}
this is the line that the error message points to
Bitmap fallings = bitfac.decodeResource(GlobalVariables.CURRENT_CONTEXT.getResources(), R.drawable.spikesupsidedown);
here is my obstacle manager where i add and display the obstacles
public class ObstacleManager
{
private ArrayList<Obstacle> obstacles;
private int playerGap;
private int obstacleGap;
private int obstacleHeight;
private int color;
private long startTime;
private long initTime;
private int score = 0;
public ObstacleManager(int playerGap, int obstacleGap, int obstacleHeight, int color)
{
this.playerGap = playerGap;
this.obstacleGap = obstacleGap;
this.obstacleHeight = obstacleHeight;
this.color = color;
startTime = initTime = System.currentTimeMillis();
obstacles = new ArrayList<>();
populateObstacles();
}
public boolean playerCollide(RectPlayer player)
{
for(Obstacle ob : obstacles)
{
if(ob.playerCollide(player))
return true;
}
return false;
}
private void populateObstacles()
{
int currY = -5 * GlobalVariables.SCREEN_HEIGHT / 4;
while(currY < 0)
{
int xStart = (int)(Math.random()*(GlobalVariables.SCREEN_WIDTH - playerGap));
obstacles.add(new Obstacle(obstacleHeight, color, xStart, currY, playerGap));
currY += obstacleHeight + obstacleGap;
}
}
public void update()
{
if (GlobalVariables.GAMEOVER)
{
for (int i = 0; i < 3; i++)
{
obstacles.remove(obstacles.size() - 2);
}
}
int elapsedTime = (int)(System.currentTimeMillis() - startTime);
startTime = System.currentTimeMillis();
float speed = (float)(Math.sqrt((1 + startTime - initTime) / 1750.0)) * GlobalVariables.SCREEN_HEIGHT /17500.0f;
for(Obstacle ob : obstacles)
{
ob.IncrementY(speed * elapsedTime);
}
if(obstacles.get(obstacles.size() - 1).getRectangle().top >= GlobalVariables.SCREEN_HEIGHT * 3/4)
{
int xStart = (int)(Math.random()*(GlobalVariables.SCREEN_WIDTH - playerGap));
obstacles.add(0, new Obstacle(obstacleHeight, color, xStart,
obstacles.get(0).getRectangle().top - obstacleHeight - obstacleGap, playerGap));
obstacles.remove(obstacles.size() - 1);
score++;
if (score > GlobalVariables.HIGHSCORE)
GlobalVariables.HIGHSCORE = score;
}
}
public void draw(Canvas canvas)
{
for(Obstacle ob : obstacles)
ob.draw(canvas);
Paint paint = new Paint();
paint.setTextSize(100);
paint.setColor(Color.RED);
canvas.drawText("" + score, 50, 50 + paint.descent() - paint.ascent(), paint);
canvas.drawText("HighScore: " + GlobalVariables.HIGHSCORE, GlobalVariables.SCREEN_WIDTH / 2 + 50, 50 + paint.descent() - paint.ascent(), paint);
}
}
here is my animation manager
public class AnimationManager
{
private Animation[] animations;
private int animationsIndex = 0;
public AnimationManager(Animation[] animations)
{
this.animations = animations;
}
public void playAnim(int index)
{
for (int i = 0; i < animations.length; i++)
{
if (i == index)
{
if (!animations[index].isPlaying())
{
animations[i].play();
}
}
else
{
animations[i].stop();
}
}
animationsIndex = index;
}
public void draw(Canvas canvas, Rect rect)
{
if (animations[animationsIndex].isPlaying())
{
animations[animationsIndex].draw(canvas, rect);
}
}
public void update()
{
if (animations[animationsIndex].isPlaying())
{
animations[animationsIndex].update();
}
}
}
and finally my animation class
public class Animation
{
private Bitmap[] frames;
private int frameIndex;
private boolean isPlaying = false;
public boolean isPlaying()
{
return isPlaying;
}
public void play()
{
isPlaying = true;
frameIndex = 0;
lastFrame = System.currentTimeMillis();
}
public void stop()
{
isPlaying = false;
}
private float frameTime;
private long lastFrame;
public Animation(Bitmap[] frames, float animTime)
{
this.frames = frames;
frameIndex = 0;
frameTime = animTime / frames.length;
lastFrame = System.currentTimeMillis();
}
public void draw(Canvas canvas, Rect destination)
{
if (!isPlaying)
return;
scaleRect(destination);
canvas.drawBitmap(frames[frameIndex], null, destination, new Paint());
}
private void scaleRect(Rect rect)
{
float whRatio = (float)(frames[frameIndex].getWidth() / frames[frameIndex].getHeight());
if (rect.width() > rect.height())
{
rect.left = rect.right - (int)(rect.height() * whRatio);
}
else
{
rect.top = rect.bottom - (int)(rect.width() * (1 / whRatio));
}
}
public void update()
{
if (!isPlaying)
return;
if (System.currentTimeMillis() - lastFrame > frameTime * 1000)
{
frameIndex++;
if (frameIndex >= frames.length)
frameIndex = 0;
lastFrame = System.currentTimeMillis();
}
}
}
i dont think you necessarily needed all that but just in case :). thanks for any comments to improve or help.
OutOfMemoryError basically means that you tried to use more memory than you can. In this specific example you (bitmap) tried to allocate 360KB though you could only allocate 78KB more. You might have a memory leak somewhere or your bitmap might be too big. I think your Bitmaps might be leaking memory. I'm not an Android expert though.
I'd recommend you to create a method in Obstacle like recycle or something along this way. Then every time you remove Obstacle from obstacles in ObstacleManager call that method. In that method you should aim to recycle all no longer used bitmaps. I'd do it by calling either Animation#recycle on every of your animations or calling AnimationManagerObstacle#recycle. (Animation#recycle would be meant to call recycle on every one of your frames.)
Following: https://developer.android.com/training/gestures/movement.html
for handling movement in an onTouchEvent. My problem is though that it seems the touch is never registered, even when following the tutorial linked.
Code:
public class Sprite extends Activity {
private static final int BMP_ROWS = 4;
private static final int BMP_COL = 3;
private int x, y = 0;
private int speedx, speedy = 5;
private int currentFrame = 0;
private int width, height;
private float xTouch, yTouch;
private VelocityTracker mVelocityTracker = null;
private GameView gameView;
private Bitmap bmp;
int [] DIRECTION_TO_ANIMATE_MAP = {3, 1, 0, 2};
public Sprite(GameView gameView, Bitmap bmp) {
this.gameView = gameView;
this.bmp = bmp;
this.width = bmp.getWidth() / BMP_COL;
this.height = bmp.getHeight() / BMP_ROWS;
}
private void Update() {
if (x >= gameView.getWidth() - width - speedx|| x + speedx <= 0) {
}
if (y >= gameView.getHeight() - height - speedy || y + speedy <= 0) {
}
currentFrame = ++currentFrame % BMP_COL;
}
public boolean onTouchEvent(MotionEvent event) {
int index = event.getActionIndex();
int action = event.getActionMasked();
int pointerId = event.getPointerId(index);
synchronized (gameView.getHolder()) {
if (this.isCollition(event.getX(), event.getY())) {
Log.d("", "Sprite touched!");
}
switch (action) {
case MotionEvent.ACTION_DOWN:
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
} else {
mVelocityTracker.clear();
}
xTouch = event.getX();
yTouch = event.getY();
Log.d("", "You clicked: " + Float.toString(xTouch) + "," + Float.toString(yTouch));
mVelocityTracker.addMovement(event);
break;
case MotionEvent.ACTION_MOVE:
mVelocityTracker.addMovement(event);
mVelocityTracker.computeCurrentVelocity(1000);
Log.d("", "X velocity: " + VelocityTrackerCompat.getXVelocity(mVelocityTracker, pointerId));
Log.d("", "Y velocity: " + VelocityTrackerCompat.getYVelocity(mVelocityTracker, pointerId));
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mVelocityTracker.recycle();
break;
}
}
boolean ret = super.onTouchEvent(event);
return ret;
}
public void onDraw(Canvas canvas) {
MotionEvent event = null;
Update();
int srcX = 1 * width;
int srcY = 0 * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
public boolean isCollition(float x2, float y2) {
return x2 > x && x2 < x + width && y2 > y && y2 < y + height;
}
}
I get a logcat message each time I touch the sprite but whenever i touch the screen or swipe I get nothing. I realise that the most possible reason is me not utilizing onTouchEvent properly but I've tried implementing some of the things suggested in other questions but without luck.
EDIT:
It was as suggested below my game logic that was wrong here. I had the onTouchEvent in a wrong class. When I changed it into the view class it works perfectly:
public class GameView extends SurfaceView {
private Bitmap bmp;
private SurfaceHolder holder;
private GameLoop gameLoop;
private Sprite sprite;
private int x = 0;
private long lastClick;
private VelocityTracker mVelocityTracker;
private float xTouch;
private float yTouch;
public GameView(Context context) {
super(context);
gameLoop = new GameLoop(this);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#SuppressLint("WrongCall")
#Override
public void surfaceCreated(SurfaceHolder holder) {
gameLoop.setRunning(true);
gameLoop.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
});
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.image);
sprite = new Sprite(this, bmp);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
sprite.onDraw(canvas);
}
public boolean onTouchEvent(MotionEvent event) {
int index = event.getActionIndex();
int action = event.getActionMasked();
int pointerId = event.getPointerId(index);
synchronized (getHolder()) {
if (sprite.isCollition(event.getX(), event.getY())) {
Log.d("", "Sprite touched!");
}
switch (action) {
case MotionEvent.ACTION_DOWN:
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
} else {
mVelocityTracker.clear();
}
xTouch = event.getX();
yTouch = event.getY();
Log.d("", "You clicked: " + Float.toString(xTouch) + "," + Float.toString(yTouch));
mVelocityTracker.addMovement(event);
break;
case MotionEvent.ACTION_MOVE:
mVelocityTracker.addMovement(event);
mVelocityTracker.computeCurrentVelocity(1000);
Log.d("", "X velocity: " + VelocityTrackerCompat.getXVelocity(mVelocityTracker, pointerId));
Log.d("", "Y velocity: " + VelocityTrackerCompat.getYVelocity(mVelocityTracker, pointerId));
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mVelocityTracker.recycle();
break;
}
}
boolean ret = super.onTouchEvent(event);
return ret;
}
}
check your game logic again and handle return value manually, instead of super.onTouchEvent(event);
I have created a 10x10 grid, and now would like to place an image of the player inside one of the grid squares. to do this I think i have to use bitmap? I will put all my code below. to try and do this anyway I created a game class which sets and gets the x position of the player image. I then created a player class, which is where I try to add the image, using Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sokobanplayer1);
i keep getting an error under getResources so i created a get resources method in game, but it didnt fix the problem. could someone please show me how to do this, my code is below.
//DRAW CLASS
public class Draw extends View {
Paint red = new Paint();
Paint green = new Paint();
int rectSide = 1000;
public Draw(Context context) {
super(context);
red.setColor(Color.RED);
green.setColor(Color.GREEN);
red.setStrokeWidth(8);
green.setStrokeWidth(8);
}
public void drawGrid(Canvas canvas) {
int width = canvas.getWidth();
int height = canvas.getHeight();
float startX = (width / 2) - (rectSide / 2);
float stopX = (width / 2) + (rectSide / 2);
float startY = (height / 2) - (rectSide / 2);
float stopY = (height / 2) + (rectSide / 2);
for (int i = 0; i < 1100; i += 100) {
float newY = startY + i;
canvas.drawLine(startX, newY, stopX, newY, green);
}
for (int i = 0; i < 1100; i += 100) {
float newX = startX + i;
canvas.drawLine(newX, startY, newX, stopY, green);
}
}
#Override
public void onDraw(Canvas canvas) {
drawGrid(canvas);
}
}
//GAME CLASS
public class Game {
Bitmap image;
int x;
int y;
int height;
int width;
public void setX(int x){
this.x = x;
}
public void setY(int y){
this.y = y;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public int getHeight(){
return height;
}
public int getWidth(){
return width;
}
public Bitmap getResources(){
return image;
}
}
//PLAYER CLASS
public class Player extends Game {
public Player(Bitmap res, int w, int h){
image = res;
x = 300;
y = 300;
height = h;
width = w;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sokobanplayer1);
}
}
//MAIN ACTIVITY
public class MainActivity extends Activity {
Draw draw;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
draw = new Draw(this);
draw.setBackgroundColor(Color.BLUE);
setContentView(draw);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Replace your Player class with this:
//PLAYER CLASS
class Player extends Game {
public Player(Context context, int w, int h){
x = 300;
y = 300;
height = h;
width = w;
image = BitmapFactory.decodeResource(context.getResources(), R.drawable.sokobanplayer1);
}
}
I am creating an android app and I am creating a game and the droid has to be able to bounce off the walls and the edge of the screen. Here is my update method in my MainGamePanel.java file where I call the collision detection.
It works when it just has to bounce off the edge of the screen. However when I try to get it bounce off the wall objects it sometimes works. When it doesn't, it goes through the wall sometimes, although this only happens when it moves up and down. It also sometimes gets stuck in the wall. How would I modify the collision detection so I won't have these issues. Any help would be much appreciated.
public void update()
{
// check collision with right wall if heading right
if (droid.getSpeed().getxDirection() == Speed.DIRECTION_RIGHT
&& droid.getX() + droid.getBitmap().getWidth() / 2 >= getWidth()) {
droid.getSpeed().toggleXDirection();
}
// check collision with left wall if heading left
else if (droid.getSpeed().getxDirection() == Speed.DIRECTION_LEFT
&& droid.getX() - droid.getBitmap().getWidth() / 2 <= 0) {
droid.getSpeed().toggleXDirection();
droid.getSpeed().setYv(0);
}
// check collision with bottom wall if heading down
else if (droid.getSpeed().getyDirection() == Speed.DIRECTION_DOWN
&& droid.getY() + droid.getBitmap().getHeight() / 2 >= getHeight()) {
droid.getSpeed().toggleYDirection();
droid.getSpeed().setXv(0);
}
// check collision with top wall if heading up
else if (droid.getSpeed().getyDirection() == Speed.DIRECTION_UP
&& droid.getY() - droid.getBitmap().getHeight() / 2 <= 0) {
droid.getSpeed().toggleYDirection();
droid.getSpeed().setXv(0);
}
for (int i = 0 ; i < listOfWs.length ; i++)
{
if (droid.getX() +(droid.getBitmap().getWidth()/2)+1 > listOfWs [i].giveLeft ()
&& droid.getX()-(droid.getBitmap().getWidth()/2)-1 < listOfWs [i].giveRight ()
&& droid.getY()+(droid.getBitmap().getHeight()/2)+1 > listOfWs [i].giveTop ()
&& droid.getY()-(droid.getBitmap().getHeight()/2)-1 < listOfWs [i].giveBottom () )
{
if(droid.getSpeed().getYv()==0){
droid.getSpeed().toggleXDirection();//Takes the speed and multiplies it by -1 so it changes direction
}
else{
droid.getSpeed().toggleYDirection();
}
}
}
// Update the lone droid
droid.update();
}
Here is my droid.java file that I used.
public class Droid {
private Bitmap bitmap; // the actual bitmap
private int x; // the X coordinate
private int y; // the Y coordinate
public Speed speed;
public Droid(Bitmap bitmap, int x, int y) {
this.bitmap = bitmap;
this.x = x;
this.y = y;
speed= new Speed();
}
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void draw(Canvas canvas) {
canvas.drawBitmap(bitmap, x - (bitmap.getWidth() /2), y - (bitmap.getHeight() / 2), null);
}
public void update() {
x += (int)(speed.getXv() * speed.getxDirection());
y += (int)(speed.getYv() * speed.getyDirection());
}
public Speed getSpeed(){
return speed;
}
}
This is the speed.java file.
public class Speed {
public static final int DIRECTION_RIGHT = 4;
public static final int DIRECTION_LEFT = -4;
public static final int DIRECTION_UP = -4;
public static final int DIRECTION_DOWN = 4;
private float xv = 1; // velocity value on the X axis
private float yv = 1; // velocity value on the Y axis
private int xDirection = DIRECTION_RIGHT;
private int yDirection = DIRECTION_DOWN;
public Speed() {
this.xv = 1;
this.yv = 1;
}
public Speed(float xv, float yv) {
this.xv = xv;
this.yv = yv;
}
public float getXv() {
return xv;
}
public void setXv(float xv) {
this.xv = xv;
}
public float getYv() {
return yv;
}
public void setYv(float yv) {
this.yv = yv;
}
public int getxDirection() {
return xDirection;
}
public void setxDirection(int xDirection) {
this.xDirection = xDirection;
}
public void setRight() {
xDirection = DIRECTION_RIGHT;
}
public void setLeft() {
xDirection = DIRECTION_LEFT;
}
public void setUp() {
yDirection = DIRECTION_UP;
}
public void setDown() {
yDirection = DIRECTION_DOWN;
}
public int getyDirection() {
return yDirection;
}
public void setyDirection(int yDirection) {
this.yDirection = yDirection;
}
// changes the direction on the X axis
public void toggleXDirection() {
xDirection = xDirection * -1;
}
// changes the direction on the Y axis
public void toggleYDirection() {
yDirection = yDirection * -1;
}
}
in the update method, in for circulation, it seems you make your logical operation there, would you make it more specific?