Hello I have a question with my code. As you can see below, I have r.getBlink() under OnDraw() method. Is there a function to determine if the "s" thread calls the OnDraw(). I mean I tried this.getClass().getBlink() but it displays as an error. help please.
public class main extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new BitmapView(this));
}
}
class BitmapView extends View implements OnTouchListener{
Circle r = new Circle();
Circle s = new Circle();
public BitmapView(Context context) {
super(context);
this.setOnTouchListener(this);
r.starter();
s.starter();
}
public void onDraw(Canvas canvas){
Paint paint = new Paint();
if (r.getBlink()==true){
paint.setColor(Color.YELLOW);
r.setBlink(false);
}
else{
paint.setColor(Color.BLACK);
r.setBlink(true);
}
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(r.getX(), r.getY(), 15, paint);
invalidate();
}
class Circle implements Runnable{
Random rnd=new Random();
int x=rnd.nextInt(200), y=rnd.nextInt(200);
boolean blink = false;
public int getX(){ return this.x; }
public int getY(){ return this.y; }
public boolean getBlink() { return this.blink; }
public void setBlink(boolean b) { this.blink=b; }
public void starter(){
Thread running=new Thread(this);
running.start();
x=rnd.nextInt(200);
y=rnd.nextInt(200);
}
public void run(){
while(true){
try {
Thread.sleep(rnd.nextInt(2000));
} catch (Exception ex) {ex.printStackTrace();}
}
}
}
Thread.currentThread().get Name();
-This method will give you the name of the currently executing thread object. I believe this is what you want.
Related
I know similar questions have been asked before but none of those solutions worked for me.
I'm trying to create a small 2D game for Android and I am having some problems using SurfaceView.
My main activity currently looks like this:
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private DrawingSurface drawingsurface;
private Game game;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate()");
setFullscreen();
game = new Game();
drawingsurface = new DrawingSurface(this, game);
setContentView(drawingsurface);
}
private void setFullscreen() {
// ...
}
}
As you can see, I set my activity to fullscreen, create a new SurfaceView (called drawingSurface) and create a new game instance.
My SurfaceView (called DrawingSurface) looks like this:
public class DrawingSurface extends SurfaceView implements SurfaceHolder.Callback {
private GameThread thread;
private static final String TAG = "DrawingSurface";
public DrawingSurface(Context context, Game game) {
super(context);
getHolder().addCallback(this);
setFocusable(true);
// create a new game rendering thread and pass it game so it can call the update() and render() functions of game:
thread = new GameThread(getHolder(), this, game);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Log.v(TAG, "surfaceCreated()");
// start the rendering thread:
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.v(TAG, "surfaceChanged()");
// do I need to do anything in here?
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// stop the rendering thread:
Log.v(TAG, "surfaceDestroyed()");
thread.setRunning(false);
boolean retry = true;
while (retry) {
try {
thread.join();
} catch (InterruptedException e) {
// try again shutting down the thread
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// pass the touch event to the Game instance (to keep everything in on place)
thread.game.onTouchEvent(event);
return super.onTouchEvent(event);
}
#Override
protected void onDraw(Canvas canvas) {
// I don't use onDraw(), instead I have my own update() and render() functions in my game thread
super.onDraw(canvas);
}
}
This is my game thread:
public class GameThread extends Thread {
private boolean running;
private SurfaceHolder surfaceHolder;
private DrawingSurface drawingSurface;
private static final String TAG = GameThread.class.getSimpleName();
protected Game game;
public GameThread(SurfaceHolder surfaceHolder, DrawingSurface drawingSurface, Game game) {
super();
this.surfaceHolder = surfaceHolder;
this.drawingSurface = drawingSurface;
this.game = game;
}
public void setRunning(boolean running) {
this.running = running;
}
#SuppressLint("WrongCall")
#Override
public void run() {
Log.d(TAG, "Starting game loop");
long now;
long dt;
long last = System.currentTimeMillis();
Canvas canvas;
while (running) {
Log.v(TAG, "GameThread running");
canvas = null;
/* try locking the canvas for exclusive
pixel editing in the surface */
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (this.surfaceHolder) {
now = System.currentTimeMillis();
dt = (now - last);
this.game.update(dt);
if(canvas != null)
this.game.render(canvas, dt);
last = now;
}
} finally {
/*in case of an exception the surface
is not left in an inconsistent state */
if (canvas != null) {
this.surfaceHolder.unlockCanvasAndPost(canvas);
}
}
if (dt < 16) {
try {
Thread.sleep(16 - dt);
} catch (InterruptedException e) {
}
}
}
}
}
And this is the Game class:
public class Game {
private static final String TAG = "Game";
private static int playerRefPosX = 40;
private int playerY = 0;
private int playerVelY = 1;
public Game() {
Log.v(TAG, "Game instance created");
}
public void update(long dt) {
playerY += playerVelY * dt;
if (playerY > 1800) {
playerVelY = -playerVelY;
}
if (playerY < 0) {
playerVelY = -playerVelY;
}
}
public void render(Canvas canvas, long dt) {
canvas.drawColor(Color.BLACK);
// draw Player
Paint paint = new Paint();
paint.setTextSize(100);
paint.setColor(new Color().rgb(255, 0, 0));
canvas.drawRect(playerRefPosX, playerY + 100, playerRefPosX + 200, playerY - 100, paint);
canvas.drawText(String.valueOf(1000/dt), canvas.getWidth()/2, canvas.getWidth()/2, paint);
}
public void onTouchEvent(MotionEvent event) {
Log.v(TAG, "received touch event..");
}
}
The problems I am have right now:
When I press the home button and reenter the app OR rotate my device it calls surfaceDestroyed() but doesn't recreate it afterwards (the canvas doesn't get repainted)
The game rendering thread never stops (as indicated by the log messages)
I am new to android graphics as far as custom views and such. I have the following program, but the SurfaceView for some reason will not draw a image from an object of another class. I continue to get a null pointer exception.
MAIN CLASS:
public class Main extends Activity {
MyView view;
TestObject test;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view = new MyView(this, this);
test = new TestObject(this);
setContentView(view);
}
public TestObject getTest() {
return test;
}
public void setTest(TestObject test) {
this.test = test;
}
}
VIEW CLASS:
public class MyView extends SurfaceView implements Runnable {
SurfaceHolder surfaceHolder;
Thread thread;
TestObject test;
public MyView(Context context, Main main) {
super(context);
this.test = main.getTest();
surfaceHolder = getHolder();
thread = new Thread(this);
thread.start();
}
#Override
public void run() {
while(true){
if(!surfaceHolder.getSurface().isValid())
continue;
Canvas canvas = surfaceHolder.lockCanvas();
canvas.drawBitmap(test.getImage(), test.getX(), test.getY(), null);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
OBJECT CLASS:
public class TestObject {
Main main;
Bitmap image;
int x,y;
DisplayMetrics dm;
public TestObject(Main main) {
this.main = main;
image = BitmapFactory.decodeResource(main.getResources(), R.drawable.ic_launcher);
dm = new DisplayMetrics();
x = dm.widthPixels / 2;
y = dm.heightPixels / 2;
}
public Bitmap getImage() {
return image;
}
public void setImage(Bitmap image) {
this.image = image;
}
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;
}
}
I get a null pointer exception at canvas.drawBitmap(test.getImage(), test.getX(), test.getY(), null); in the MyView class. Strangly, it will work if if was to say canvas.drawBitmap(BitmapFactory.decodeResource(main.getResources(), R.drawable.ic_launcher), 0, 0, null); (or any other x, y position).
Any help is appreciated!
You should override "onDraw" method of "MyView" instead of implementing Runnable.
I'm new to Java, so I hope it's not a silly question. I have a class called "Enemy".
I know how to multiply the class, I use the "for" loop. Now, the problem is that the variables x and y (the one's that move the bitmap) have the same values for every instance of the class. And I want them to be different in order to create some "randomness".
The main class:
public class MainActivity extends Activity{
Player ourView;
#SuppressLint("ClickableViewAccessibility") protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
ourView = new Player(this);
setContentView(ourView);
}
protected void onPause() {
super.onPause();
ourView.pause();
}
protected void onResume() {
super.onResume();
ourView.resume();
}
}
Here's the "Player" class:
public class Player extends SurfaceView implements Runnable {
Canvas canvas = new Canvas();
SurfaceHolder ourHolder;
Thread ourThread = null;
boolean isRunning = true;
public Player(Context context) {
super(context);
ourHolder = getHolder();
ourThread = new Thread(this);
ourThread.start();
}
public void pause() {
isRunning = false;
while(true){
try{
ourThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
ourThread = null;
}
public void resume() {
isRunning = true;
}
public void run() {
while(isRunning) {
if(!ourHolder.getSurface().isValid())
continue;
canvas = ourHolder.lockCanvas();
canvas.drawRGB(30, 30, 200);
Enemy[] enemy = new Enemy[3];
for(int i = 0; i<enemy.length; i++){
enemy[i] = new Enemy(null);
enemy[i].draw();
}
ourHolder.unlockCanvasAndPost(canvas);
}
}
}
And here's the "Enemy" class:
public class Enemy extends Player{
public Enemy(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
float x,y = (float) (Math.random()*200);
public void draw(){
Bitmap bitmap = (Bitmap) BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
canvas.drawBitmap(bitmap, x, y, null);
}
}
I've also tried to declare those variables inside the "Enemy" class, but they just don't work. The bitmap stays in (0,0).
NOTE: The "Player" and "Enemy" class are declared inside the "MainActivity" class.
Your Enemy class should not extend the Player class since they don't share any similarities except the canvas and the context.
A possible implementation of your Enemy could look like this:
public class Enemy {
private Bitmap bitmap;
private Canvas canvas;
private Context context;
private float x, y;
public Enemy(Canvas canvas, Context context) {
bitmap = BitmapFactory.decodeResource(
context.getResources(), R.drawable.ic_launcher);
x = (float) (Math.random() * 200);
y = (float) (Math.random() * 200);
}
public void draw() {
canvas.drawBitmap(bitmap, x, y, null);
}
public void printCoordinates() { // just used for printing
System.out.println("x = " + x + " / y = "+ y);
}
}
Your Player class just need a minor adjustment to create proper Enemy classes:
Enemy[] enemy = new Enemy[3];
for(int i = 0; i < enemy.length; i++){
enemy[i] = new Enemy(canvas, context);
enemy[i].printCoordinates(); // just used for printing the generated coordinates
enemy[i].draw();
}
You just have to provide proper canvas and context instances for the new Enemy instance. You may also drop the context instance since you (currently) don't use it anythere in that class.
This is an example print of above code:
x = 27.236885 / y = 7.8905525
x = 61.842735 / y = 158.4654
x = 186.16629 / y = 20.208426
If you really want to extend the Player class, then you can still do that. This won't change much in your Enemy class.
I want to make it so that pressing the screen moves my rectangle. The listener gives output to console but it doesn't invalidate the screen.
public class DrawView extends View{
Paint paint = new Paint();
static int x = 20;
static int y = 20;
public DrawView(Context context){
super(context);
paint.setColor(Color.GREEN);
}
#Override
public void onDraw(Canvas canvas){
canvas.drawRect(x,y,100,100,paint);
}
public void OTListener(){
setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View DrawView, MotionEvent e){
x = 100;
y = 100;
invalidate();
return false;
}
});
}
}
Try this. It should work if it is the top view in your view hierarchy.
You'll have to check out event.getAction() if you want to do more advanced stuff in onTouchEvent()...
public class DrawView extends View {
Paint paintRect = new Paint();
Paint paintClear = new Paint();
private Point touch = new Point();
public DrawView(Context context){
super(context);
paintClear.setColor(Color.BLACK);
paintRect.setColor(Color.GREEN);
}
#Override
public void onDraw(Canvas canvas){
canvas.drawPaint(paintClear);
canvas.drawRect(touch.x-50,touch.y-50,touch.x+50,touch.y+50,paintRect);
}
private void touch(int x, int y) {
touch.set(x,y);
invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
touch((int)event.getX(), (int)event.getY());
return true;
}
}
Using invalidate() in another method doesn't work. You need to use postinvalidate() if you want to refresh activity from another method.
How might I draw a graph of a function (for example, y = x^2 or y = (x +1)/(2*x +3)) on a Canvas in an Android app?
Here you have an example code ;D (plots the f(x)=x^3 function)
A sample thread that plots the function.
public class MainThread extends Thread {
private static final String TAG = MainThread.class.getSimpleName();
private SurfaceHolder surfaceHolder;
private MainGamePanel gamePanel;
private Paint paintRed;
private Paint paintBlue;
private boolean running;
public void setRunning(boolean running) {
this.running = running;
}
public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {
super();
this.paintRed = new Paint();
this.paintRed.setColor(Color.RED);
this.paintRed.setStrokeWidth(1);
this.paintBlue = new Paint();
this.paintBlue.setColor(Color.BLUE);
this.paintBlue.setStrokeWidth(1);
this.surfaceHolder = surfaceHolder;
this.gamePanel = gamePanel;
}
class MeasuredAxis {
public static final int X_GAP = 1;
public static final int Y_GAP = 1;
int _realHeight;
int _realWidth;
public MeasuredAxis(int width, int height) {
_realWidth = width;
_realHeight = height;
}
public int getXAxisNegLimit() {
return (_realWidth / 2)*(-1);
}
public int getXAxisLimit() {
return (_realWidth / 2);
}
public float getXMeasured(int x) {
return ((_realWidth / 2) + x);
}
public float getYMeasured(float y) {
return ((_realHeight / 2) - y);
}
}
private float function(float x) {
return new Double(Math.pow(x, 3)).floatValue();
}
#Override
public void run() {
long fps = 0L;
Log.d(TAG, "Starting game loop");
Canvas canvas = surfaceHolder.lockCanvas();
MeasuredAxis measured = new MeasuredAxis(canvas.getWidth(), canvas.getHeight());
synchronized (canvas) {
int x = measured.getXAxisNegLimit();
//from -x to +x evaluate and plot the function
while (x++ < measured.getXAxisLimit()) {
canvas.drawLine(
measured.getXMeasured(x),
measured.getYMeasured(function(x)),
measured.getXMeasured(x+MeasuredAxis.X_GAP),
measured.getYMeasured(function(x+MeasuredAxis.Y_GAP)),
paintRed);
}
canvas.save();
canvas.translate(0, 0);
canvas.scale(canvas.getWidth(), canvas.getHeight());
canvas.restore();
}
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
A sample surface view where the function is drawn.
public class MainGamePanel extends SurfaceView implements
SurfaceHolder.Callback {
private MainThread thread;
public MainGamePanel(Context context) {
super(context);
getHolder().addCallback(this);
// create the game loop thread
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) {
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
// try again shutting down the thread
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
#Override
protected void onDraw(Canvas canvas) {
}
}
And an example activity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(new MainGamePanel(this));
}
}
Hope this helps you!