Material para estudar

Cara, acho que to entendendo sobre e vetores até agora.
To tentando criar um movimento pra bola, porém me vem esse erro no LogCat:

05-10 16:17:55.773: E/AndroidRuntime(849): FATAL EXCEPTION: main
05-10 16:17:55.773: E/AndroidRuntime(849): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ball/com.example.ball.MainActivity}: java.lang.NullPointerException
05-10 16:17:55.773: E/AndroidRuntime(849): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
05-10 16:17:55.773: E/AndroidRuntime(849): 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
05-10 16:17:55.773: E/AndroidRuntime(849): 	at android.app.ActivityThread.access$600(ActivityThread.java:141)
05-10 16:17:55.773: E/AndroidRuntime(849): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
05-10 16:17:55.773: E/AndroidRuntime(849): 	at android.os.Handler.dispatchMessage(Handler.java:99)
05-10 16:17:55.773: E/AndroidRuntime(849): 	at android.os.Looper.loop(Looper.java:137)
05-10 16:17:55.773: E/AndroidRuntime(849): 	at android.app.ActivityThread.main(ActivityThread.java:5041)
05-10 16:17:55.773: E/AndroidRuntime(849): 	at java.lang.reflect.Method.invokeNative(Native Method)
05-10 16:17:55.773: E/AndroidRuntime(849): 	at java.lang.reflect.Method.invoke(Method.java:511)
05-10 16:17:55.773: E/AndroidRuntime(849): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
05-10 16:17:55.773: E/AndroidRuntime(849): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
05-10 16:17:55.773: E/AndroidRuntime(849): 	at dalvik.system.NativeStart.main(Native Method)
05-10 16:17:55.773: E/AndroidRuntime(849): Caused by: java.lang.NullPointerException
05-10 16:17:55.773: E/AndroidRuntime(849): 	at com.example.ball.MainActivity.onCreate(MainActivity.java:30)
05-10 16:17:55.773: E/AndroidRuntime(849): 	at android.app.Activity.performCreate(Activity.java:5104)
05-10 16:17:55.773: E/AndroidRuntime(849): 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
05-10 16:17:55.773: E/AndroidRuntime(849): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
05-10 16:17:55.773: E/AndroidRuntime(849): 	... 11 more

Pode me ajudar?

O que tem

at com.example.ball.MainActivity.onCreate(MainActivity.java:30) 

?

na linha 30

gameView.setCallbackHandler(guiRefresher);

As 3 classes:

MainActivity

package com.example.ball;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {
	
	private GameView gameView;
	Handler guiRefresher;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		gameView = (GameView) findViewById(R.id.action_settings);
		
		guiRefresher = new Handler() {
			public void handleMessage(Message msg) {
				if(msg.what == 10001) {
					gameView.invalidate();
			    }
				super.handleMessage(msg);
			}
		};
		
		gameView.setCallbackHandler(guiRefresher);
		
		Thread t = new Thread(gameView);
		t.setDaemon(true);
		t.start();
		
	
	}
}

GameView

package com.example.ball;

import java.util.Vector;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;

public class GameView extends View implements Runnable {
	int width = 600, height = 1024;
	Paint background;
	Handler handler;
	Ball ball;
	
	public GameView(Context context) {
		super(context);
	}
    
	public GameView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}
	
	public GameView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}
	
	public void init() {
		background = new Paint();
		background.setColor(Color.BLACK);
		
		
	}
	
	public void onDraw(Canvas canvas) {
		canvas.drawRect(0,0, getWidth(), getHeight(), background);
	}

	@Override
	public void run() {
		while(true) {
			try {
				ball.processAI();
				
				Message msg = new Message();
				msg.what = 10001;
				
				Thread.sleep(10);
			} catch (Exception e) {
			}
		}
		
	}
	
    public void setCallbackHandler(Handler guiRefresher) {
    	this.handler = guiRefresher;
    }
}

Ball

package com.example.ball;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import com.example.ball.Vector2D;

public class Ball {
    Paint paint;
    
    Vector2D pos;
    Vector2D dir;
    float speed;
    
    public Ball(Vector2D pos, Vector2D dir, float speed) {
    	this.pos = pos;
    	this.dir = dir;
    	this.speed = speed;
    	
    	paint = new Paint();
    	paint.setColor(Color.RED);
    }

    public void draw(Canvas canvas) {
    	canvas.save();
    	canvas.drawCircle(pos.getX(), dir.getY(), 10, paint);
    	canvas.restore();
    }
    
    public void move() {
    	pos.plusMe(dir.multiply(speed));
    }
    
    public void processAI() {
    	move();
    }
}

Cade activity_main.xml ?

Seu GameView tem id=action_settings?

O Handler seria um atualizador que apaga a bolinha e redesenha em outro lugar?
Uma coisa que eu não entendi no artigo, foi que o construtor da classe Ball
tem os parâmetros :

public Ball(Vector2D pos, Vector2D dir, float speed)

Mas na classe GameView, os parâmetros do objeto da classe Ball, são:

ball = new Ball(new Vector2D(20, 20), new Vector(1,1), 1.2)

Por que Vector ao invés de Vector2D? E o parâmetro da variável speed devia ser um
float, e não um double… ou não? kk

Eu coloquei:

Rodou, a bolinha se mexe, mas só uma vez, depois para.

O Handler (assim como descrito no artigo se bem me lembro) serve para sincronizar a tela com a Thread secundaria que está rodando o loop do jogo.

Talvez foi erro meu antes de formatar o codigo para o artigo remover o 2D do parametro, e auto-castings funcionam sem f também.

Ahh… a bola não está se mechendo por que falta enviar a mensagem no seu método run (dentro do while) para o Handler.

 @Override  
    public void run() {  
        while(true) {  
            try {  
                ball.processAI();  
                  
                Message msg = new Message();  
                msg.what = 10001;  
                  
handler.sendMessage(msg);
                Thread.sleep(10);  
            } catch (Exception e) {  
            }  
        }  
          
    }  

Valeu Mark.
Consegui fazer o movimento.
Agora eu tava querendo fazer uma troca de imagens simples,
ao toque de um botão.

MainActivity:

[code]package com.example.animar;

import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Canvas;
import android.view.Menu;
import android.view.View;
import android.widget.Button;

@SuppressLint(“WrongCall”)
public class MainActivity extends Activity implements Runnable {

GV gv;
Canvas canvas;
Button bt;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Button bt = (Button) findViewById(R.id.button);
    gv = new GV(this);
    setContentView(R.layout.activity_main);
}

@Override
public void run() {
	while(true) {
		gv.onDraw(canvas);
		try {
			Thread.sleep(1000/30);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
}

public void move() {
	bt.setOnClickListener(new View.OnClickListener() {
		
		@Override
		public void onClick(View arg0) {
			gv.animar();
		}
	});
}

}
[/code]

GameView

package com.example.animar;

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.util.AttributeSet;
import android.view.View;

public class GV extends View {
	Paint paint;
	Bitmap[] image = new Bitmap[2];
	Canvas canvas;
	
	int n = 0;
	
	public GV(Context context) {
		super(context);
		init();
	}
	
	public GV(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}
	
	public GV(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}
	
	public void init() {
		paint = new Paint();
		paint.setColor(Color.BLACK);
		
		image[0] = BitmapFactory.decodeResource(getResources(), R.drawable.ball);
		image[1] = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
	}
	
	public void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		
		canvas.save();
        canvas.drawRect(0, 0, 600, 1024, paint);
        canvas.drawBitmap(image[n], 0, 0, paint);
		canvas.restore();
	}
	
	public void animar() {
		n++;
	}
}

Eu queria fazer que quando eu clicasse
no botão, a int n (numero do array) fosse para 1 e o array 1 é uma outra imagem,
e com isso, aparecer outra imagem na tela.
Mas até agora não consegui nada.
Na verdade não sei se da pra fazer desse jeito
pra android. Com Java pra desktop eu conseguia.
Desde já obrigado.

Nesse caso, a GameView é uma View, voce precisaria de um componente fora desse layout para modificar o valor que voce quer.

Isso é possivel sim, mas o ideal é lidar com mudanças de frames do sprite num método proccessLogics, se voce seguir o artigo adiante essa lógica vai ser extraida para um método desses e voce pode modificar lá.

Blz, vlw!
Vou até o final do artigo agora :smiley: