Make a sprite jump

2019-09-04 01:44发布

问题:

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)

回答1:

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.