why does this not work? it prints the locations as the should but it does not move the image on the screen? i am using an emulator.
i think the image should be moving around but it stays in the same place even though the x and y values are changing. i think the problem may be the canvas i am using when i call onDraw(canvas). what can i do to this canvas to make it work (if the canvas is the problem)?
if this is not enough detail please tell me. code below;
GameView.java
package com.example.game;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.View;
public class GameView extends View implements Runnable{
Thread gameLoop = new Thread(this);
boolean running = false;
int x = 10;
int y = 10;
Canvas canvas = new Canvas();
private Bitmap bmp;
public GameView(Context context) {
super(context);
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(bmp, x, y, null);
System.out.println(x);
if(x < 100) {
x+=10;
}
if(x >= 99 && y < 400) {
y+=10;
}
if(y > 350 && x >= 99) {
x = 10;
y = 10;
}
}
public void start() {
if(!running) {
running = true;
gameLoop.start();
}
}
public void stop() {
if(running) {
running = false;
}
}
#Override
public void run() {
while(running) {
try{
onDraw(canvas);
Thread.sleep(1000);
}catch(Exception exc) {System.err.println("error sleep interup");}
}
}
}
Main.java
package com.example.game;
import android.app.Activity;
import android.os.Bundle;
public class Main extends Activity {
GameView gv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gv = new GameView(this);
setContentView(gv);
gv.start();
}
}
You should put the object back on the canvas after you calculated the x and y coordinates.
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
System.out.println(x);
if(x < 100) {
x+=10;
}
if(x >= 99 && y < 400) {
y+=10;
}
if(y > 350 && x >= 99) {
x = 10;
y = 10;
}
canvas.drawBitmap(bmp, x, y, null);
}
Related
So i was trying to make a simple mobile game for a school project. I setted up a simple SurfaceView thing and builded it on my phone with Android 12 (Api 32), but it doesn't draw anything. It enters the draw function of the view, but i can't see an output. It only works on a old friend's tablet with Android 4.4.2.
MySurfaceView.java
package com.example.lyceumgame;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
Bitmap image;
Paint paint;
float iX, iY, tX = 0, tY = 0;
float dx = 0, dy = 0;
Resources res;
MyThread myThread;
float ws, hs;
float iw, ih;
boolean isFirstDraw = true;
public MySurfaceView(Context context) {
super(context);
getHolder().addCallback(this);
res = getResources();
iX = 100;
iY = 100;
paint = new Paint();
paint.setColor(Color.YELLOW);
paint.setStrokeWidth(5);
setAlpha(0);
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
myThread = new MyThread(surfaceHolder, this);
myThread.setRunning(true);
myThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
boolean retry = true;
myThread.setRunning(false);
while (retry) {
try {
myThread.join();
retry = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
setAlpha(0);
if (isFirstDraw){
ws = canvas.getWidth();
hs = canvas.getHeight();
isFirstDraw = false;
}
canvas.drawRGB(0,255,0);
canvas.drawLine(iX, iY, tX, tY, paint);
if(tX != 0)
delta();
iX += dx;
iY += dy;
checkScreen();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
tX = event.getX();
tY = event.getY();
delta();
return true;
}
void delta(){
double ro = Math.sqrt(Math.pow(tX-iX, 2)+Math.pow(tY-iY, 2));
double k = 10;
dx = (float) (k * (tX - iX)/ro);
dy = (float) (k * (tY - iY)/ro);
}
private void checkScreen(){
if(iY + ih >= hs && iY <= 0)
dy = -dy;
if(iX + iw >= ws && iX <= 0)
dx = -dx;
}
}
MyThread.java
package com.example.lyceumgame;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class MyThread extends Thread {
boolean isRunning = false;
SurfaceHolder surfaceHolder;
MySurfaceView mySurfaceView;
long prevTime, nowTime;
int FPS=60;
int c=1000;
int koeff=c/FPS;
public MyThread(SurfaceHolder holder, MySurfaceView surfaceView) {
surfaceHolder = holder;
mySurfaceView = surfaceView;
prevTime = System.currentTimeMillis();
}
#Override
public void run() {
Canvas canvas;
while (isRunning){
if(!surfaceHolder.getSurface().isValid())
continue;
canvas = null;
nowTime = System.currentTimeMillis();
long ellapsedTime = nowTime - prevTime;
if(ellapsedTime > koeff){
prevTime = nowTime;
canvas = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder){
mySurfaceView.draw(canvas);
}
if (canvas != null){
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
void setRunning(boolean f){
isRunning = f;
}
}
MainActivity.java
package com.example.lyceumgame;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MySurfaceView(this));
}
}
My SDK was in different location and code like this worked fine. I tried invalidating caches and moving SDK to previous location. It didn't work.
I am new to Android Studio and do not understand why the onSensorChanged() method does not give errors and warnings, but returns zero. I want to "roll the ball on the screen of the device." The graphic component works well. I see a ball with a constant speed of movement, and I want to adjust the speed by multiplying it by the angle of the screen and therefore my speed becomes - zero.
Please help me fix it.
I'm testing the application on a real device Xiaomi MI9 SE.
//MAIN ACTIVITY
package com.example.app_2;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class Gravity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_gravity);
setContentView(new MovementView(this));
}
}
//PHYSICS
package com.example.app_2;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MovementView extends SurfaceView implements SurfaceHolder.Callback {
public float xPos;
public float yPos;
public float xVel;
public float yVel;
public float width;
public float height;
private float circleRadius;
private Paint circlePaint;
UpdateThread updateThread;
public MovementView(Context context) {
super(context);
getHolder().addCallback(this);
circleRadius = 30;
circlePaint = new Paint();
circlePaint.setColor(Color.RED);
xVel = 2 ; // скорость движения
yVel = 2 ; // шарика
}
#Override
public void onDraw(Canvas c) {
c.drawColor(Color.WHITE);
c.drawCircle(xPos, yPos, circleRadius, circlePaint);
}
public void updatePhysics() {
float xz, zy;
xz = Acceleration.Accel(1);
zy = Acceleration.Accel(-1);
xPos += xVel - xz;
yPos += yVel - zy;
if (yPos - circleRadius < 0 || yPos + circleRadius > height) {
//В случае ударов о верх или низ холста
if (yPos - circleRadius < 0) {
//Удар о верхнюю грань
yPos = circleRadius;
}else{
//Удар о нижнюю грань
yPos = height - circleRadius;
}
//Меняем направление шарика
yVel *= -1;
}
if (xPos - circleRadius < 0 || xPos + circleRadius > width) {
//В случае столкновений с правой или левой стенками
if (xPos - circleRadius < 0) {
//В случае столкновений с левой стенкой
xPos = circleRadius;
} else {
//В случае столкновений с правой стенкой
xPos = width - circleRadius;
}
//Меняем x направление на обратное
xVel *= -1;
}
}
public void surfaceCreated(SurfaceHolder holder) {
Rect surfaceFrame = holder.getSurfaceFrame();
width = surfaceFrame.width();
height = surfaceFrame.height();
xPos = width / 2;
yPos = height / 2;
updateThread = new UpdateThread(this);
updateThread.setRunning(true);
updateThread.start();
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
updateThread.setRunning(false);
while (retry) {
try {
updateThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
}
//THREAD
package com.example.app_2;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class UpdateThread extends Thread{
private long time;
private final int fps = 5;
private boolean toRun = false;
private MovementView movementView;
private SurfaceHolder surfaceHolder;
UpdateThread(MovementView rMovementView) {
movementView = rMovementView;
surfaceHolder = movementView.getHolder();
}
void setRunning(boolean run) {
toRun = run;
}
#Override
public void run() {
Canvas c;
while (toRun) {
long cTime = System.currentTimeMillis();
//if ((cTime - time) <= (100000 / fps)) {
c = null;
try {
c = surfaceHolder.lockCanvas(null);
movementView.updatePhysics();
movementView.onDraw(c);
} finally {
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
//}
time = cTime;
}
}
}
//ACCELERATION
package com.example.app_2;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.IBinder;
import androidx.core.content.ContextCompat;
import static android.content.Context.SENSOR_SERVICE;
import static android.hardware.Sensor.TYPE_ROTATION_VECTOR;
import static androidx.core.content.ContextCompat.getSystemService;
public class Acceleration extends Service implements SensorEventListener {
public SensorManager sensorManager;
public static float xy_angle, xz_angle, zy_angle;
public Acceleration(Context pContext) {
sensorManager = (SensorManager) pContext.getSystemService(SENSOR_SERVICE);
assert sensorManager != null;
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(TYPE_ROTATION_VECTOR),
SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
assert sensorManager != null;
xy_angle = sensorEvent.values[0];
xz_angle = sensorEvent.values[1];
zy_angle = sensorEvent.values[2];
}
public static float Accel(int a){
float angle;
if (a > 0){
angle = xz_angle;
} else {
angle = zy_angle;
}
return angle;
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
I expect Acceleration.Accel(1) to return the value of the TYPE_ROTATION_VECTOR sensor at the time of the data request, but I always get zero.
What you need to do is pass your application's Context to your Acceleration class so that your SensorManager can get initialized. The way you had the SensorManager getting initialized inside the onSensorChanged() method meant that the SensorManager was never even getting setup because onSensorChanged() was never even getting called.
So in the revised Acceleration class below, I added a constructor which you will then need to call with your application's Context passed in as an argument:
public class Acceleration extends Service implements SensorEventListener {
public SensorManager sensorManager;
public static float xy_angle, xz_angle, zy_angle;
public Acceleration(Context pContext) {
sensorManager = (SensorManager) pContext.getSystemService(SENSOR_SERVICE);
assert sensorManager != null;
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(TYPE_ROTATION_VECTOR),
SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
xy_angle = sensorEvent.values[0];
xz_angle = sensorEvent.values[1];
zy_angle = sensorEvent.values[2];
}
public static float accel(int a) {
float angle;
if (a > 0) {
angle = xz_angle;
} else {
angle = zy_angle;
}
return angle;
}
}
In your Gravity class, just initialize an Acceleration object:
public class Gravity extends AppCompatActivity {
Acceleration acceleration;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MovementView(this));
acceleration = new Acceleration(this);
}
}
so i was following retro-chickens tutorial online on how to make a 2d game on android studio and i have run across a problem and i tried to figure it out but i just cant seemm to find a solution. The problem occured on his 2nd video (https://www.youtube.com/watch?v=Rliwg0sELJo) where he runs his code and rectangle appears on the screen which he can move around. For me the rectangle doesnt appear on the canvas for some reason, it is just a blank canvas even though i have the exact same code as him (i have gone back and checked).
At times my application sometimes doesnt even launch and gives me error like this (I have the latest sdk version and everything):
Cold swapped changes.
$ adb shell am start -n "com.example.ridhavraj.stardrifter/com.example.ridhavraj.stardrifter.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 3319 on device emulator-5554
W/System: ClassLoader referenced unknown path: /data/app/com.example.ridhavraj.stardrifter-2/lib/x86
I/InstantRun: Instant Run Runtime started. Android package is com.example.ridhavraj.stardrifter, real application class is null.
W/System: ClassLoader referenced unknown path: /data/app/com.example.ridhavraj.stardrifter-2/lib/x86
I/OpenGLRenderer: Initialized EGL, version 1.4
D/OpenGLRenderer: Swap behavior 1
[ 11-11 20:20:52.858 3319: 3343 D/ ]
HostConnection::get() New Host Connection established 0xaee13300, tid 3343
A/libc: Fatal signal 6 (SIGABRT), code -6 in tid 3343 (Thread-5)
[ 11-11 20:20:53.138 1214: 1214 W/ ]
debuggerd: handling request: pid=3319 uid=10072 gid=10072 tid=3343
Application terminated.
Here is the code that i have made from the video:
[GameObject Interface]
package com.example.ridhavraj.stardrifter;
import android.graphics.Canvas;
public interface GameObject {
public void draw(Canvas canvas);
public void update();
}
[MainActivity Class]
package com.example.ridhavraj.stardrifter;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
//setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new GamePanel(this));
}
}
[MainThread Class]
package com.example.ridhavraj.stardrifter;
import android.graphics.Canvas;
import android.provider.Settings;
import android.view.SurfaceHolder;
public class MainThread extends Thread{
public static final int MAX_FPS = 30;
private double averageFPS;
private SurfaceHolder surfaceHolder;
private GamePanel gamePanel;
private boolean running;
public static Canvas canvas;
public void setRunning(boolean running)
{
this.running = running;
}
public MainThread(SurfaceHolder surfaceHolder, GamePanel gamePanel)
{
super();
this.surfaceHolder = surfaceHolder;
this.gamePanel = gamePanel;
}
#Override
public void run()
{
long startTime;
long timeMillis = 1000/MAX_FPS;
long waitTime;
int frameCount = 0;
long totalTime = 0;
long targetTime = 1000/MAX_FPS;
while(running)
{
startTime = System.nanoTime();
canvas = null;
try
{
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder)
{
this.gamePanel.update();
this.gamePanel.draw(canvas);
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (canvas != null)
{
try
{
surfaceHolder.unlockCanvasAndPost(canvas);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
timeMillis = (System.nanoTime()-startTime)/1000000;
waitTime = targetTime - timeMillis;
try
{
if (waitTime > 0)
{
this.sleep(waitTime);
}
}
catch (Exception e)
{
e.printStackTrace();
}
totalTime += System.nanoTime() - startTime;
frameCount++;
if (frameCount == MAX_FPS)
{
averageFPS = 1000/((totalTime/frameCount)/1000000);
frameCount = 0;
totalTime = 0;
System.out.println(averageFPS);
}
}
}
}
[GamePanel Class]
package com.example.ridhavraj.stardrifter;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GamePanel extends SurfaceView implements SurfaceHolder.Callback {
private MainThread thread;
private Player player;
private Point playerPoint;
public GamePanel(Context context)
{
super(context);
getHolder().addCallback(this);
thread = new MainThread(getHolder(), this);
player = new Player(new Rect(100,100,200,200), Color.rgb(255,0,0));
playerPoint = new Point(150,150);
setFocusable(true);
}
#Override
public void surfaceChanged(SurfaceHolder Holder, int format, int width, int height)
{
}
#Override
public void surfaceCreated(SurfaceHolder holder)
{
thread = new MainThread(getHolder(), this);
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
boolean retry = true;
while(true)
{
try
{
thread.setRunning(false);
thread.join();
}
catch (Exception e)
{
e.printStackTrace();
}
retry = false;
}
}
public boolean onTouchEvent(MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
playerPoint.set((int)event.getX(), (int)event.getY());
}
return true;
//return super.onTouchEvent(event);
}
public void update()
{
player.update(playerPoint);
}
#Override
public void draw(Canvas canvas)
{
super.draw(canvas);
canvas.drawColor(Color.WHITE);
player.draw(canvas);
}
}
[Player Class]
package com.example.ridhavraj.stardrifter;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Canvas;
import android.graphics.Rect;
public class Player implements GameObject{
private Rect rectangle;
private int color;
public Player(Rect rectangle, int Color)
{
this.rectangle = rectangle;
this.color = color;
}
#Override
public void draw(Canvas canvas)
{
Paint paint = new Paint();
paint.setColor(color);
canvas.drawRect(rectangle, paint);
}
#Override
public void update()
{
}
public void update(Point point)
{
//l,t,r,b
rectangle.set(point.x-rectangle.width()/2, point.y-rectangle.height()/2, point.x+rectangle.width()/2, point.y+rectangle.height()/2);
}
}
I dont clue what i am doing wrong, any help would be greatly appreciated.
Well Turns out guys, i am retarded, there was a typo in the player class
private Rect rectangle;
private int color;
public Player(Rect rectangle, int Color [THIS SHOULD BE 'color' and not 'Color')
{
this.rectangle = rectangle;
this.color = color;
}
for 3D Rectangle(cube) copy whole code to your CustomView Class
Paste This into onDraw() method
drawCube(
fp.mX.toInt(), fp.mY.toInt(),
100 + (fp.mCx.toInt() - fp.mX.toInt()),
100 + fp.mCy.toInt() - fp.mY.toInt(),
mPaint, mCanvas!!
)
drawCube(
fp.mX.toInt(), fp.mY.toInt(),
100 + (fp.mCx.toInt() - fp.mX.toInt()),
100 + fp.mCy.toInt() - fp.mY.toInt(),
mStrokePaint, mCanvas!!
)
3D Cube Function Code
private fun drawCube(
x: Int,
y: Int,
width: Int,
height: Int,
paint: Paint,
canvas: Canvas
) {
val p1 = Point(x, y)
val p2 = Point(x, y + height)
val p3 = Point(x + width, y + height)
val p4 = Point(x + width, y)
val p5 = Point(x + width / 2, y - height / 2)
val p6 = Point(x + 3 * width / 2, y - height / 2)
val p7 = Point(x + 3 * width / 2, y + height / 2)
val path = Path()
path.fillType = Path.FillType.EVEN_ODD
path.moveTo(p1.x.toFloat(), p1.y.toFloat())
path.lineTo(p2.x.toFloat(), p2.y.toFloat())
path.lineTo(p3.x.toFloat(), p3.y.toFloat())
path.lineTo(p4.x.toFloat(), p4.y.toFloat())
path.lineTo(p1.x.toFloat(), p1.y.toFloat())
path.lineTo(p5.x.toFloat(), p5.y.toFloat())
path.lineTo(p6.x.toFloat(), p6.y.toFloat())
path.lineTo(p4.x.toFloat(), p4.y.toFloat())
path.moveTo(p3.x.toFloat(), p3.y.toFloat())
path.lineTo(p7.x.toFloat(), p7.y.toFloat())
path.lineTo(p6.x.toFloat(), p6.y.toFloat())
path.lineTo(p4.x.toFloat(), p4.y.toFloat())
path.close()
canvas.drawPath(path, paint)
}
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++;
}