I have been researching and struggling with my code to get a textview to update the score when a "ghost" is touched.
This is my first Android application and so far as i can tell(i added Log.w() to the ontouch but a log is never posted as well as the score not being incremented or even appearing) the onTouch(View v, MotionEvent event) is never called. Below is my code.
package com.cs461.Ian;
//TODO:Add accelerometer support
//TODO:Add Clickable ghosts
//TODO:Add camera background
/*Completed:(As of 2:30am 4/16)
* Activity launches
* Ghost appears on screen
* Ghost will randomly move around the screen
*/
import java.util.Random;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.widget.TextView;
public class CameraActivity extends Activity{
Bitmap g;
Ghost a;
Ghost still;
SurfaceHolder mSurfaceHolder;
boolean firsttime=true;
int draw_x,draw_y,xSpeed,ySpeed,score=0;
TextView t;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game);
a = new Ghost(getApplicationContext());
still = new Ghost(getApplicationContext());
//requestWindowFeature(Window.FEATURE_NO_TITLE);
a.Initalize(BitmapFactory.decodeResource(getResources(), R.drawable.ghost), 20, 20);
still.Initalize(BitmapFactory.decodeResource(getResources(), R.drawable.ghost), 120, 120);
t = (TextView) findViewById(R.id.t);
t.setText("TEST SCORE TO SEE IF TEXTVIEW SHOWS UP");
a.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
score++;
t.setText("Score: "+score);
}
return true;
}
});
still.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
score++;
t.setText("Score: "+score);
Log.w("CLICKED","Clicked on ghost "+score+" times");
}
return true;
}
});
setContentView(new Panel(this));
}
class Panel extends View {
public Panel(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
//g.Initalise(BitmapFactory.decodeFile("/res/drawable-hdpi/ghost.png"), 200, 150, 5, 5);;
update(canvas);
invalidate();
}
/*Places ghost on screen and bounces it around in the screen. My phone is apparently only API level 4(the most up to date is 15) so i didn't code it
*for the accelerometer yet.
*/
public void update(Canvas canvas) {
Random rand = new Random();
if(firsttime){
draw_x = Math.round(System.currentTimeMillis() % (this.getWidth()*2)) ;
draw_y = Math.round(System.currentTimeMillis() % (this.getHeight()*2)) ;
xSpeed = rand.nextInt(10);
ySpeed = rand.nextInt(10);
firsttime=false;
}
draw_x+=xSpeed;
draw_y+=ySpeed;
draw_x = Math.round(System.currentTimeMillis() % (this.getWidth()*2)) ;
draw_y = Math.round(System.currentTimeMillis() % (this.getHeight()*2)) ;
if (draw_x>this.getWidth()){
draw_x = (this.getWidth()*2)-draw_x;
xSpeed = rand.nextInt(10);
if(xSpeed >=5)
xSpeed=-xSpeed;
}
if (draw_y>this.getHeight()){
draw_y = (this.getHeight()*2)-draw_y;
ySpeed = rand.nextInt(10);
if(ySpeed >=5)
ySpeed=-ySpeed;
}
g = BitmapFactory.decodeResource(getResources(), R.drawable.ghost);
canvas.drawBitmap(g, draw_x, draw_y, null);
still.draw(canvas);
a.update(canvas);
}
}
}
Forgot to add class Ghost:
package com.cs461.Ian;
import java.util.Random;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class Ghost extends View implements View.OnTouchListener{
public Ghost(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
private Bitmap mAnimation;
private int mXPos;
private int mYPos;
private Rect mSRectangle;
private int mSpriteHeight;
private int mSpriteWidth;
View v;
Rect dest;
int score = 0;
/*public Ghost() {
mSRectangle = new Rect(0,0,0,0);
mXPos = 80;
mYPos = 200;
}*/
public void Initalize(Bitmap theBitmap, int Height, int Width) {
mSRectangle = new Rect(0,0,0,0);
mXPos = 80;
mYPos = 200;
mAnimation = theBitmap;
mSpriteHeight = Height;
mSpriteWidth = Width;
mSRectangle.top = 0;
mSRectangle.bottom = mSpriteHeight;
mSRectangle.left = 0;
mSRectangle.right = mSpriteWidth;
dest = new Rect(mXPos, mYPos, mXPos + mSpriteWidth,
mYPos + mSpriteHeight);
}
public void draw(Canvas canvas) {
canvas.drawBitmap(mAnimation, mXPos, mYPos, null);
}
public void update(Canvas canvas) {
new Random();
mXPos = Math.round(System.currentTimeMillis() % (canvas.getWidth()*2)) ;
mYPos = Math.round(System.currentTimeMillis() % (canvas.getHeight()*2)) ;
if (mXPos>canvas.getWidth())
mXPos = (canvas.getWidth()*2)-mXPos;
if (mYPos>canvas.getHeight())
mYPos = (canvas.getHeight()*2)-mYPos;
draw(canvas);
}
public Rect getRect() {
return mSRectangle;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
score++;
//CameraActivity.t.setText("Score: "+CameraActivity.score);
Log.w("CLICKED","Clicked on ghost "+score+" times");
return true; //doesn't work if returns false either
}
}
Override dispatchTouchEvent(MotionEvent event) in your Activity to handle all the touch events that may occur. Return false to pass down the MotionEvent to the next view\layout in the hierachy if they they handle events.
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.
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.
I am making a game which requires the sprites to move towards the bottom of the screen. You can imagine it a bit like a rhythm game(guitar hero). However, I am having problems as the sprites are not moving at all even if the loop seems to work fine.
The GamePanel-
package com.jollygent.tapthepointer;
import java.util.ArrayList;
import java.util.Random;
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.view.SurfaceHolder;
import android.view.SurfaceView;
public class GamePanel extends SurfaceView{
SurfaceHolder holder;
GameLoopThread loop;
GamePanel game = this;
Random rand;
int y;
//ArrayList<Pointers> pointers = new ArrayList<Pointers>();
Pointers pointers;
public GamePanel(Context context) {
super(context);
holder = getHolder();
loop = new GameLoopThread(this);
rand = new Random();
pointers = new Pointers(rand.nextInt(4)+1,getWidth()/2,0,this);
//placeholder
this.setBackgroundColor(Color.WHITE);
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
loop.setRunning(false);
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
loop = new GameLoopThread(game);
if(!loop.isRunning()){
loop.setRunning(true);
loop.start();
}
else{
loop.setPause(false);
}
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stubn
}
});
}
public GameLoopThread getLoop(){
return loop;
}
public void update(){
}
public void draw(Canvas canvas){
pointers.draw(canvas);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStrokeWidth(20);
paint.setStyle(Paint.Style.STROKE);
canvas.drawLine(0,getHeight()/2 + 50,getWidth(),getHeight()/2 + 50, paint);
}
}
The Pointer class
package com.jollygent.tapthepointer;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
public class Pointers {
GamePanel game;
private int x,y;
Bitmap pointer;
Bitmap rotated_pointer;
Matrix matrix;
public Pointers(int type,int x,int y,GamePanel game){
this.game = game;
this.x = x;
this.y = y;
pointer = BitmapFactory.decodeResource(game.getResources(),R.drawable.pointer_xx);
matrix = new Matrix();
switch(type){
//points right
case 1:
matrix.postRotate(90);
break;
//points left
case 2:
matrix.postRotate(-90);
break;
//points up
case 3:
rotated_pointer = pointer;
break;
//points down
case 4:
matrix.postRotate(180);
break;
}
rotated_pointer = Bitmap.createBitmap(pointer,0,0,pointer.getHeight(),pointer.getWidth(), matrix,true);
}
public void update(){
/*if(y < game.getHeight()){
y += pointer.getHeight();
}*/
}
public int getHeight(){
return pointer.getHeight();
}
public void draw(Canvas canvas){
y++;//placeholder movement to see if the sprite actually moves. It doesn't.
canvas.drawBitmap(rotated_pointer,x,y,null);
}
}
Finally, I think it's necessary to post the GameLoopThread-
package com.jollygent.tapthepointer;
import android.graphics.Canvas;
public class GameLoopThread extends Thread{
GamePanel game;
boolean running = false;
boolean paused = false;
Canvas canvas;
static final int FPS = 10;
public GameLoopThread(GamePanel game){
this.game = game;
}
public boolean isRunning(){
return running;
}
public void setRunning(boolean b){
this.running = b;
}
public void setPause(boolean b){
this.paused = b;
}
#Override
public void run() {
// TODO Auto-generated method stub
long beginTime;
long ticks = 1000/FPS;
long sleepTime;
while(running){
if(!paused){
beginTime = System.currentTimeMillis();
canvas = null;
try{
canvas = game.holder.lockCanvas();
synchronized(game.getHolder()){
game.draw(canvas);
}
}finally{
if(canvas != null){
game.getHolder().unlockCanvasAndPost(canvas);
}
}
sleepTime = (System.currentTimeMillis() - beginTime)/ticks;
try{
if(sleepTime > 0)
Thread.sleep(sleepTime);
else
Thread.sleep(10);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}
I'm probably making a very stupid mistake, but no matter how much I scan into the code and change around few bits I can't seem to figure out how exactly to move the sprite. Also, how can I make it so the sprite is centered exactly in any device?
Thank you.
EDIT:
package com.jollygent.tapthepointer;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
public class GameActivity extends Activity {
GamePanel game;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
game = new GamePanel(this);
setContentView(game);
}
#Override
public void onPause(){
super.onPause();
game.getLoop().setPaused(true);
}
#Override
public void onResume(){
super.onResume();
game.getLoop().setPaused(false);
}
}
The problem is that the loop only runs once and once only. Perhaps the GameActivity is the problem?
First Of all I'm doing this on Eclipse.
1.I wish to draw a rectangle on reception of Touch event.
2.That rectangle should be persistent and on an another Touchevent should draw another rectangle.
3.I have managed to get it persistent for a single TouchEvent after which it shifts according to coordinates.
4.So basically I should have multiple rectangles due to different touch events.
I am thinking of iterating through arrays...
But I'm still confused pls help!
This one does not work... I'm asking for improvements...
Thanks! Also manifests and stuff is proper and permissions are taken properly!
code is somewhat like:
package code.e14.balldetector;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
public class MainActivity extends Activity implements CvCameraViewListener2, OnTouchListener {
private static final String TAG = "OCVBallTracker";
private CameraBridgeViewBase mOpenCvCameraView;
private boolean mIsJavaCamera = true;
private Mat mRgba;
int i=0;
private Double[] h=new Double[20];
private Double[] k=new Double[20];
private double x=0;
private double y=0;
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
#Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
mOpenCvCameraView.enableView();
mOpenCvCameraView.setOnTouchListener(MainActivity.this);
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
public MainActivity() {
Log.i(TAG, "Instantiated new " + this.getClass());
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "called onCreate");
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_main);
if (mIsJavaCamera)
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.java_surface_view);
else
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.native_surface_view);
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
mOpenCvCameraView.setCvCameraViewListener(this);
}
#Override
public void onPause()
{
super.onPause();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
#Override
public void onResume()
{
super.onResume();
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_5, this, mLoaderCallback);
}
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
Log.i(TAG, "called onCreateOptionsMenu");
return true;
}
public void onCameraViewStarted(int width, int height) {
mRgba = new Mat(height, width, CvType.CV_8UC4);
}
public void onCameraViewStopped() {
mRgba.release();
}
#Override
public boolean onTouch(View arg0,MotionEvent event) {
double cols = mRgba.cols();
double rows = mRgba.rows();
double xOffset = (mOpenCvCameraView.getWidth() - cols) / 2;
double yOffset = (mOpenCvCameraView.getHeight() - rows) / 2;
h[i] = (double)(event).getX() - xOffset;
k[i] = (double)(event).getY() - yOffset;
h[i]=x;
k[i]=y;
Log.i(TAG, "Touch image coordinates: (" + h[i] + ", " + k[i] + ")");
i++;
return false;// don't need subsequent touch events
}
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
mRgba=inputFrame.rgba();
Core.rectangle(mRgba, new Point(x-100,y-100),new Point(x+100,y+100),new Scalar( 0, 0, 255 ),0,8, 0 );
return mRgba;
}
}
It is quite easy to store the rectangles in a List. I have made some small adjustments that should work.
private List<Rect> ListOfRect = new ArrayList<Rect>();
#Override
public boolean onTouch(View arg0,MotionEvent event) {
double cols = mRgba.cols();
double rows = mRgba.rows();
double xOffset = (mOpenCvCameraView.getWidth() - cols) / 2;
double yOffset = (mOpenCvCameraView.getHeight() - rows) / 2;
h[i] = (double)(event).getX() - xOffset;
k[i] = (double)(event).getY() - yOffset;
h[i]=x;
k[i]=y;
ListOfRect.add(new Rect(x-100, y-100, x+100, y+100));
Log.i(TAG, "Touch image coordinates: (" + h[i] + ", " + k[i] + ")");
i++;
return false;// don't need subsequent touch events
}
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
mRgba=inputFrame.rgba();
for(int i=0; i<ListOfRect.size(); i++){
Core.rectangle(mRgba, ListOfRect.get(i).tl(), ListOfRect.get(i).br(),new Scalar( 0, 0, 255 ),0,8, 0 );}
return mRgba;
}
However keep in mind that you need to release and clear your list to free memory when you don't need the rectangles anymore. I hope it helped.