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.
Related
I'm writing a program to transform, rotate and scale a 2d square. I have the transformation and rotation working but I need help with the scaling. I can't seem to find any help on the internet to help since I have to use a math equation and I can't find the equation needed. Just so you know I don't want to use gl.glScaled(). I need to use a math equation but I can't figure it out.
package lab2;
public class Square {
public double [][] vertices = new double[4][2];
public Square(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
{
vertices[0][0]=x1;
vertices[0][1]=y1;
vertices[1][0]=x2;
vertices[1][1]=y2;
vertices[2][0]=x3;
vertices[2][1]=y3;
vertices[3][0]=x4;
vertices[3][1]=y4;
}
public double area()
{
return (vertices[1][0]-vertices[0][0])*(vertices[1][0]-vertices[0][0])+(vertices[1][1]-vertices[0][1])*(vertices[1][1]-vertices[0][1]);
}
public void translate(double tx, double ty)
{
for(int i=0;i<vertices.length;i++)
{
vertices[i][0]+=tx;
vertices[i][1]+=ty;
}
}
public void rotate(double theta)
{
//double x =0;
double x = (vertices[0][0]+vertices[2][0])/2;
double y = (vertices[0][1]+vertices[2][1])/2;
double oldX;
int i;
for(i = 0; i < 4; i++){
oldX = vertices[i][0];
vertices[i][0] = x + (vertices[i][0]-x)*Math.cos(theta*0.0174532925199)-(vertices[i][1]- y)*Math.sin(theta*0.0174532925199);
vertices[i][1] = y + (oldX-x)*Math.sin(theta*0.0174532925199)+(vertices[i][1]-y)*Math.cos(theta*0.0174532925199);
}
}
public void scale(double sx, double sy)
{
}
}
Then I also have this SquareControl.java so that I can control how I want it to work so for this program I'll be using key events
package lab2;
import java.awt.Frame;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.media.opengl.*;
import javax.media.opengl.awt.GLCanvas;
import com.sun.opengl.util.Animator;
import com.sun.opengl.util.FPSAnimator;
public class Square_Control implements GLEventListener, KeyListener {
Square square = new Square(100,100,200,100,200,200,100,200);
boolean rotating = false;
boolean scaling = false;
boolean enlarge = true;
double theta = 1;
double sx = 1.01, sy = 1.01;
GLProfile glp;
GLCapabilities caps;
GLCanvas canvas;
public Square_Control()
{
glp = GLProfile.getDefault();
caps = new GLCapabilities(glp);
canvas = new GLCanvas(caps);
Frame frame = new Frame("AWT Window Test");
frame.setSize(300, 300);
frame.add(canvas);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
canvas.addGLEventListener(this);
canvas.addKeyListener(this);
canvas.requestFocus();
Animator animator = new FPSAnimator(canvas,60);
animator.add(canvas);
animator.start();
}
public static void main(String[] args) {
Square_Control sqc = new Square_Control();
}
public void update()
{
if (rotating)
square.rotate(theta);
if (scaling)
{
square.scale(1, 1);
}
}
#Override
public void display(GLAutoDrawable drawable) {
update();
GL2 gl = drawable.getGL().getGL2();
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
gl.glColor3f(1, 0, 0);
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex2d(square.vertices[0][0], square.vertices[0][1]);
gl.glVertex2d(square.vertices[1][0], square.vertices[1][1]);
gl.glVertex2d(square.vertices[2][0], square.vertices[2][1]);
gl.glVertex2d(square.vertices[3][0], square.vertices[3][1]);
gl.glEnd();
}
#Override
public void dispose(GLAutoDrawable drawable) {
// TODO Auto-generated method stub
}
#Override
public void init(GLAutoDrawable drawable) {
// TODO Auto-generated method stub
GL2 gl = drawable.getGL().getGL2();
gl.glMatrixMode(gl.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(0, 300, 0, 300, -1, 1);
gl.glViewport(0, 0, 300, 300);
}
#Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent arg0) {
if (arg0.getKeyCode() == KeyEvent.VK_RIGHT)
square.translate(4, 0);
else if (arg0.getKeyCode() == KeyEvent.VK_LEFT)
square.translate(-4, 0);
else if (arg0.getKeyCode() == KeyEvent.VK_UP)
square.translate(0, 4);
else if (arg0.getKeyCode() == KeyEvent.VK_DOWN)
square.translate(0, -4);
//also add code to toggle rotation/scaling
if(arg0.getKeyCode() == KeyEvent.VK_R)
{
rotating = !rotating;
}
if(arg0.getKeyCode() == KeyEvent.VK_S)
{
scaling = !scaling;
}
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
To scale an object, you simply have to multiply each vertex by your scaling factor. A scaling factor of 1.0 will do nothing while a scaling factor of 2.0 will double de position of each vertex, hence scaling it AND probably translating it.
If you want the object to stay in place, you'll have to first translate it to your object's center, scale, then translate back to it's original position.
That is if you want to do the job software.
You should consider using Matrix functions. glRotatef, glTranslatef and glScalef.
I have very simple question. But i couldnt solve. I just want to draw a texture on the tilemap. With theese codes i can see the map and move, but i cant see texture.
Here is the screen:
package com.adsiz.areyoualive.screen;
import com.adsiz.areyoualive.game.Player;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.maps.tiled.*;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
public class PlayScreen implements Screen, InputProcessor{
public ScreenManager screenManager;
public static float speed = 32;
//tilemap & camera
TiledMap tiledMap;
OrthographicCamera camera;
TiledMapRenderer renderer;
//player
Player player;
//spritebatch
SpriteBatch spriteBatch;
public PlayScreen(){
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera = new OrthographicCamera();
camera.setToOrtho(false, w, h);
camera.update();
tiledMap = new TmxMapLoader().load("map/untitled.tmx");
renderer = new OrthogonalTiledMapRenderer(tiledMap);
spriteBatch = new SpriteBatch();
camera.position.set(0, 3200, 0);
Gdx.input.setInputProcessor(this);
player = new Player(0, 3200);
spriteBatch.setTransformMatrix(camera.combined);
}
#Override
public void render(float delta) {
Gdx.graphics.getGL20().glClearColor( 1, 1, 1, 1 );
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
Gdx.graphics.getGL20().glClear( GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT );
camera.update();
renderer.setView(camera);
renderer.render();
spriteBatch.setProjectionMatrix(camera.combined);
spriteBatch.begin();
player.draw(spriteBatch);
spriteBatch.end();
}
#Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
}
#Override
public void show() {
// TODO Auto-generated method stub
}
#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
}
#Override
public boolean keyDown(int keycode) {
switch (keycode) {
case Keys.DOWN:
camera.translate(0, -1*speed);
player.moveDown();
break;
case Keys.UP:
camera.translate(0, speed);
player.moveUp();
break;
case Keys.LEFT:
camera.translate(-1*speed, 0);
player.moveLeft();
break;
case Keys.RIGHT:
camera.translate(speed, 0);
player.moveRight();
break;
}
return false;
}
#Override
public boolean keyUp(int keycode) {
return false;
}
#Override
public boolean keyTyped(char character) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean mouseMoved(int screenX, int screenY) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean scrolled(int amount) {
// TODO Auto-generated method stub
return false;
}
}
and here is my player.draw function:
public void draw(SpriteBatch batch){
batch.draw(playerTexture, getPosX(), getPosY(), playerTexture.getWidth(), playerTexture.getHeight());
}
i just want to show a simple texture and move it on the screen. What is wrong above there? May you help me?
Regards Guys!
I solved my own problem, I just changed map renderer to OrthogonalTileMapRenderer, and changed SpriteBatch's with Batch of OrthogonalTileMapRenderer.
package com.adsiz.areyoualive.screen;
import com.adsiz.areyoualive.game.Player;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.maps.tiled.*;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
public class PlayScreen implements Screen, InputProcessor{
public ScreenManager screenManager;
public static float speed = 32;
//tilemap & camera
TiledMap tiledMap;
OrthographicCamera camera;
OrthogonalTiledMapRenderer renderer;
//player
Player player;
public PlayScreen(){
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera = new OrthographicCamera();
camera.setToOrtho(false, w, h);
camera.update();
tiledMap = new TmxMapLoader().load("map/untitled.tmx");
renderer = new OrthogonalTiledMapRenderer(tiledMap);
camera.position.set(0, 3200, 0);
Gdx.input.setInputProcessor(this);
player = new Player(0, 3200);
}
#Override
public void render(float delta) {
Gdx.graphics.getGL20().glClearColor( 1, 1, 1, 1 );
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
Gdx.graphics.getGL20().glClear( GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT );
camera.update();
renderer.setView(camera);
renderer.render();
renderer.getSpriteBatch().begin();
player.draw(renderer.getSpriteBatch());
renderer.getSpriteBatch().end();
}
I don't know what I'm doing wrong here
//This is the Bullet Class. Here All I need is the Y position (because the Bullet is going only Y. The image which is in my drawable hdpi folder contains the image of my bullet.
public class Bulletbun extends GameObject {
private int deltaY;
private android.media.Image img;
public Bulletbun(final int xPos, final int yPos, final Image img){
this.img= img;
this.xPos=xPos;
this.yPos=yPos;
}
public Bulletbun(float f, int i, int j, String string) {
// TODO Auto-generated constructor stub
}
#Override
public void draw(Graphics g){
g.drawImage (img, xPos, yPos, null);
}
#Override
void update() {
// TODO Auto-generated method stub
}
}
}
}
// Trying to make it fire from here... This is my OnClick. What I want is When I touch the button I made, an Image would shoot out on the Y position of the screen. Also If I were to hit it multiple time it would shoot more than one (5). But also destroy the ones that are off-screen to save memory.
#Override
public void onClick(View v) { //+sound
// TODO Auto-generated method stub //+sound
Bulletbun Bulletbunny= new Bulletbun(bunbutt.getX()+20, 4,4, "images/air_bunny.png");
if (barrelblast != 0)
sp.play(barrelblast, 1, 1, 0, 0, 1); //+sound
Vibrator vibe = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
vibe.vibrate(90);
smoke.setVisibility(View.VISIBLE);
Handler delayedAction = new Handler();
delayedAction.postDelayed(new Runnable() {
public void run() {
smoke.setVisibility(View.INVISIBLE);
//This is my GameObject Class
package com.ramy.fallingbarrels;
import com.badlogic.gdx.Graphics;
import android.media.Image;
public abstract class GameObject {
protected Image img;
protected int xPos;
protected int yPos;
abstract void draw (Graphics g);
abstract void update();
public Image getImg() {
return img;
}
public void setImg(Image img) {
this.img = img;
}
public int getxPos() {
return xPos;
}
public void setxPos(int xPos) {
this.xPos = xPos;
}
public int getYpos() {
return yPos;
}
public void setYpos(int ypos) {
this.yPos = ypos;
}
//I was trying to follow a tutorial. If I'm doing something wrong here please tell me. Also if there's a better way to do what I described please tell me.
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).
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.