I'm trying to draw a drawable background with a path. But i getting to one point where i can't draw because i need the size of the object that will receive the background. Is there a function to find the size of the specific view that i will draw on ?
public class CustomDrawableEditText extends Drawable{
private Context context;
public CustomDrawableEditText(Context context) {
// TODO Auto-generated constructor stub
this.context = context;
}
#Override
public void draw(Canvas canvas) {
// TODO Auto-generated method stub
Path path = new Path();
Paint paint = new Paint();
path.moveTo(0, 0);
path.lineTo(10, 0);
path.moveTo(0, 0);
path.lineTo(0, Y);
path.lineTo(10, Y);
path.moveTo( X, 0);
path.lineTo( X-10, 0);
path.moveTo( X, 0);
path.lineTo( X, X);
path.lineTo( X-10, X);
paint.setColor(context.getResources().getColor(R.color.orange));
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.STROKE);
canvas.drawPath(path, paint);
}
private int getY() {
final Resources res = context.getResources();
final float scale = res.getDisplayMetrics().density;
return (int) (res.getDimension(R.dimen.dim4) * scale + 0.5f);
}
#Override
public int getOpacity() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void setAlpha(int alpha) {
// TODO Auto-generated method stub
}
#Override
public void setColorFilter(ColorFilter cf) {
// TODO Auto-generated method stub
}
}
To get the size of a View you can invoke getWidth() and getHeight(). Note that you might be interested in getMeasuredWidth() and getMeasuredHeight() as well.
Make sure these methods are called after the layout process of your view.
Call the Drawable.getBounds() or Drawable.copyBounds(Rect rect) methods.
These two methods should return the View's bounds (when a View's size changes, it calls (should call) the Drawable.setBounds method on each Drawable it has with the appropriate parameter values) in which the View wants your Drawable to be drawn. Your own custom-Drawable can then retrieve this value by calling Drawable.getBounds() or Drawable.copyBounds(Rect rect).
Related
I'm working on an Android game and so far the way I draw game objects is I initialise them in Game then put them in an array list of GameObject (every object extends this abstract class; player, flag, coin). This array list gets passed into Renderer which then draws the objects using a for loop (that iterates over the array list).
I am trying to add a new GameObject called Coin. Unlike other objects I want this one to be animated, and already have 8 pictures representing each frame of the animation. Here's my code (using the libgdx Animation class):
public class Coin extends GameObject implements Screen {
private SpriteBatch batch;
private Animation animation;
private float time;
public Coin(Sprite spr, float xPos, float yPos,
float radius) {
super(spr, xPos, yPos, radius);
setxPos(xPos);
setyPos(yPos);
batch = new SpriteBatch();
time = 0;
}
public void render(float delta) {
// TODO Auto-generated method stub
batch.begin();
batch.draw(animation.getKeyFrame(time += delta), getxPos(), getyPos());
batch.end();
}
#Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
}
#Override
public void show() {
// TODO Auto-generated method stub
//batch = new SpriteBatch();
animation = new Animation(1 / 3f,
new TextureRegion(new Texture("coin1.png")),
new TextureRegion(new Texture("coin2.png")),
new TextureRegion(new Texture("coin3.png")),
new TextureRegion(new Texture("coin4.png")),
new TextureRegion(new Texture("coin5.png")),
new TextureRegion(new Texture("coin6.png")),
new TextureRegion(new Texture("coin7.png")),
new TextureRegion(new Texture("coin8.png")));
animation.setPlayMode(Animation.PlayMode.LOOP);
}
#Override
public void hide() {
// TODO Auto-generated method stub
}
#Override
public void pause() {
// TODO Auto-generated method stub
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
// TODO Auto-generated method stub
batch.dispose();
}
}
The error I get from the LogCAT is a NullPointerException # batch.draw(animation.getKeyFrame(time += delta), getxPos(), getyPos());
Does anyone know how to fix this? Any insight would be highly appreciated
Write this code:
public Coin(Sprite spr, float xPos, float yPos,
float radius) {
super(spr, xPos, yPos, radius);
setxPos(xPos);
setyPos(yPos);
batch = new SpriteBatch();
time = 0;
loadAnimation();
}
public void loadAnimation() {
// TODO Auto-generated method stub
//batch = new SpriteBatch();
animation = new Animation(1 / 3f,
new TextureRegion(new Texture("coin1.png")),
new TextureRegion(new Texture("coin2.png")),
new TextureRegion(new Texture("coin3.png")),
new TextureRegion(new Texture("coin4.png")),
new TextureRegion(new Texture("coin5.png")),
new TextureRegion(new Texture("coin6.png")),
new TextureRegion(new Texture("coin7.png")),
new TextureRegion(new Texture("coin8.png")));
animation.setPlayMode(Animation.PlayMode.LOOP);
}
I have a problem with the method sprite.setSize(float x, float y) in Libgdx. It does not affect the size or the dimensions of the sprite. They remains fixed whatever I pass to the setSize() method.
here is my code:
public class GameScreen implements Screen {
OrthographicCamera camera;
SpriteBatch batch;
Texture carTexture;
Sprite carSprite;
public GameScreen()
{
}
#Override
public void render(float delta) {
// TODO Auto-generated method stub
Gdx.gl.glClearColor(0,0,0,0);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.begin();
carSprite.setSize(16, 32);
batch.draw(carSprite, 0 , 0);
batch.end();
camera.update();
}
#Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
camera.viewportWidth=width;
camera.viewportHeight=height;
camera.update();
}
#Override
public void show() {
// TODO Auto-generated method stub
camera = new OrthographicCamera();
batch = new SpriteBatch();
carTexture = new Texture(Gdx.files.internal("NetRace.png"));
carTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
carSprite = new Sprite(carTexture);
}
#Override
public void hide() {
// TODO Auto-generated method stub
}
#Override
public void pause() {
// TODO Auto-generated method stub
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
// TODO Auto-generated method stub
}
}
could you please find my mistake?
The problem was solved.
I had to use sprite.draw(batch); instead of using Batch.draw(Sprite sp, float x, float y); since the Batch.draw(...) method takes the texture from the passed sprite and uses the texture in the drawing process which has a fixed width and a fixed height.
Another way to solve this problem is to use the batch.draw(Sprite, float x, float y, float width, float height); method in the SpriteBatch class.
I have a simple program to draw simple shapes by canvas.
private class MyViewCircle extends View {
public MyViewCircle(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
canvas.drawCircle(89, 150, 30, paint);
}
}
As you see, the attributes of the circle is
(Color.RED);
(89, 150, 30, paint);
I want to created another class includes a lot of other features(colors and coordinates) and select them randomly.
So, which way is better, array or arraylist or something else? Could someone gives me an example how to do that? Then how to randomly pick them and put them into the draw function? Cheers!
Try creating a simple Java object to contain all the attributes, then add them to a single list and choose an item at random:
class MyAttributes {
int color;
int x, y;
int radius;
public MyAttributes(int color, int x, int y, int radius) {
this.color = color;
this.x = x;
this.y = y;
this.radius = radius;
}
}
In your View class:
private List<MyAttributes> mAttributes;
private Random mRandom;
public MyViewCircle(Context context) {
mRandom = new Random();
mAttributes = new ArrayList<MyAttributes>();
mAttributes.add(new MyAttributes(Color.RED, 80, 70, 199));
mAttributes.add(new MyAttributes(Color.BLUE, 50, 170, 88));
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setAntiAlias(true);
int randomPosition = mRandom.nextInt(mAttributes.size());
MyAttributes randomAttr = mAttributes.get(randomPosition);
paint.setColor(randomAttr.color);
canvas.drawCircle(randomAttr.x, randomAttr.y, randomAttr.radius, paint);
}
Generally on Android I always aim to use an Array over using an ArrayList for performance.
To pick randomly you can use either the Math.random() method or the util.Random object. Using either of those you can generate an index value and read the data from the array with that index.
Should be pretty simple really so I won't write any code unless you really need that.
I am experiencing an unusual error using ItemizedOverlay in Android.
I am creating a GPS tracking device that plots a route between waypoints stored in a database.
When I provide the first two sets of longitude and latitude points through the emulator in Eclipse, it draws a red line just how I want it, but if I send another GPS point, it animates to the point, but does not draw a line from the last point.
public class MyOverlay extends ItemizedOverlay<OverlayItem>
{
// private Projection projection;
private Paint linePaint;
private Vector<GeoPoint> points;
public MyOverlay(Drawable defaultMarker) {
super(defaultMarker);
points = new Vector<GeoPoint>();
//set colour, stroke width etc.
linePaint = new Paint();
linePaint.setARGB(255, 255, 0, 0);
linePaint.setStrokeWidth(3);
linePaint.setDither(true);
linePaint.setStyle(Style.FILL);
linePaint.setAntiAlias(true);
linePaint.setStrokeJoin(Paint.Join.ROUND);
linePaint.setStrokeCap(Paint.Cap.ROUND);
}
public void addPoint(GeoPoint point) {
points.addElement(point);
}
public void draw(Canvas canvas, MapView view, boolean shadow) {
int size = points.size();
Point lastPoint = new Point();
if(size == 0) return;
view.getProjection().toPixels(points.get(0), lastPoint);
Point point = new Point();
for(int i = 1; i<size; i++){
view.getProjection().toPixels(points.get(i), point);
canvas.drawLine(lastPoint.x, lastPoint.y, point.x, point.y, linePaint);
lastPoint = point;
}
}
#Override
protected OverlayItem createItem(int arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int size() {
// TODO Auto-generated method stub
return 0;
}
}
In your code the draw() methhod is called only once and then it is never recalled. The populate method will repopulate all the overlayes points which is there in your list each time. So it will again call the draw method which will draw a line for you.
package com.example.mymap;
import java.util.ArrayList;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;
public class ItemOverLay extends ItemizedOverlay<OverlayItem> {
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
GeoPoint prePoint=null,currentPoint=null;
MapView mapView=null;
Paint paint=new Paint();
public ItemOverLay(GeoPoint prePoint,GeoPoint currentPoint, Drawable defaultMarker,MapView mapview) {
super(boundCenterBottom(defaultMarker));
this.currentPoint=currentPoint;
this.prePoint = prePoint;
mapView=mapview;
// TODO Auto-generated constructor stub
}
public ItemOverLay(Drawable defaultMarker) {
super(defaultMarker);
// TODO Auto-generated constructor stub
}
public void addOverlay(OverlayItem item){
mOverlays.add(item);
populate();
}
#Override
protected OverlayItem createItem(int i) {
// TODO Auto-generated method stub
return mOverlays.get(i);
}
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
super.draw(canvas, mapView, shadow);
Paint paint=new Paint();
Point screenCoords=new Point();
Point screenCoords1=new Point();
mapView.getProjection().toPixels(prePoint, screenCoords);
int x1=screenCoords.x;
int y1=screenCoords.y;
mapView.getProjection().toPixels(currentPoint, screenCoords1);
int x2=screenCoords1.x;
int y2=screenCoords1.y;
paint.setStrokeWidth(1);
canvas.drawLine(x1, y1, x2, y2, paint);
}
#Override
public int size() {
// TODO Auto-generated method stub
return mOverlays.size();
}
}
Change this line
view.getProjection().toPixels(points.get(i), point);
to
point = view.getProjection().toPixels(points.get(i), null);
then it should work.
I am building an application which stores GPS locations in a SQLite database and then outputs the data onto a MapView using an Overlay by drawing a red line between the points.
I want to be able to show graphical markers (images) for each of these points as well as the red line. My code is as follows:
public class MyOverlay extends ItemizedOverlay<OverlayItem> {
// private Projection projection;
private Paint linePaint;
private Vector<GeoPoint> points;
public MyOverlay(Drawable defaultMarker) {
super(defaultMarker);
points = new Vector<GeoPoint>();
//set colour, stroke width etc.
linePaint = new Paint();
linePaint.setARGB(255, 255, 0, 0);
linePaint.setStrokeWidth(3);
linePaint.setDither(true);
linePaint.setStyle(Style.FILL);
linePaint.setAntiAlias(true);
linePaint.setStrokeJoin(Paint.Join.ROUND);
linePaint.setStrokeCap(Paint.Cap.ROUND);
}
public void addPoint(GeoPoint point) {
populate();
points.addElement(point);
}
//public void setProjection(Projection projection) {
// this.projection = projection;
// }
public void draw(Canvas canvas, MapView view, boolean shadow) {
populate();
int size = points.size();
Point lastPoint = new Point();
if(size == 0) return;
view.getProjection().toPixels(points.get(0), lastPoint);
Point point = new Point();
for(int i = 1; i<size; i++){
view.getProjection().toPixels(points.get(i), point);
canvas.drawLine(lastPoint.x, lastPoint.y, point.x, point.y, linePaint);
lastPoint = point;
}
}
#Override
protected OverlayItem createItem(int arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int size() {
// TODO Auto-generated method stub
return 0;
}
}
What would be the easiest way to implement adding markers for each GeoPoint?
Take a look at http://www.vtgroup.com/index.html#MapLocation and see if it answers your question.