Why is my rectangle not updating in my canvas method?(android java) - java

So I made a painting class which has got an ontouchevent method where i set the xpos of my rectangle to the xpos of the touch event but the rectangle isnt moving! how can I correct that?
rectangle class:
public class myRectangle{
public int xpos;
public int ypos;
public int size;
private Paint paint;
public myRectangle(){
size = 40;
paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLUE);
}
public void drawRectangle(Canvas c,int x, int y){
c.drawRect(x, y, size, size, paint);
}
}
and my paint view:
public class Painting extends View {
myRectangle player;
float x;
float y;
public Painting(Context context) {
super(context);
player = new myRectangle();
// TODO Auto-generated constructor stub
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
x = event.getX();
y = event.getY();
String s = Float.toString(event.getX());
String c = Float.toString(event.getX());
Log.d(c, s);
return super.onTouchEvent(event);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
player.drawRectangle(canvas, (int)x, (int)y);
}
}
I can also post the main activity if needed

the only thing missing is the invalidate() call in your onTouchEvent. invalidate() schedule a draw

Related

only one color is displayed in time

I'm developing paint app the problem is when i choose color and paint and then pick different color the whole paint color changes to the new color can any one tell why this is happening and how to solve this ? and how to add eraser to this?
imageview DrawView here :
public class DrawView extends ImageView {
private ArrayList<Point> mTouches;
int paintColor;
public int setcolor(int a){
paintColor=a;
return paintColor;}
// Java constructor
public DrawView(Context context) {
super(context);
init();}
// XML constructor
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
init();}
private void init() {
mTouches = new ArrayList<Point>();}
#Override
public boolean onTouchEvent(MotionEvent event) {
// Capture a reference to each touch for drawing
float touchX = event.getX();
float touchY = event.getY();
mTouches.add(new Point(Math.round(touchX), Math.round(touchY)));
return super.onTouchEvent(event);}
#Override
protected void onDraw(Canvas c) {
// Let the image be drawn first
super.onDraw(c);
// Draw your custom points here
Paint paint = new Paint();
paint.setColor(paintColor);
paint.setAntiAlias(true);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
for (Point p : mTouches) {
c.drawCircle( p.x, p.y,15,paint);}} }
in my main:
im.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
DrawView mcustomImagview = (DrawView) v;
mcustomImagview.setcolor(color);
mcustomImagview.invalidate();
if (v.onTouchEvent(event)) {
// Do something with event.getX(), event.getY() }
return true;}})
Every time onDraw is called, the entire canvas is redraw. As you store only one paintColor in your custom class, only the last selected one is used.
You need to store the color together with the associated Point. Then when you loop throw your mTouches array, you change the color for the color of the current Point.
Btw the Paint object can be updated, so you don't need to create it every time as it's a bad practice to create new objects in onDraw.
EDIT
public class DrawView extends android.support.v7.widget.AppCompatImageView {
private ArrayList<ColouredPoint> mTouches;
// Current used colour
private int mCurrColour;
private Paint mPaint;
public void setColor(int colour) {
mCurrColour = colour;
}
public DrawView(Context context) {
super(context);
init();
}
// XML constructor
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mTouches = new ArrayList<>();
mPaint = new Paint();
mPaint.setColor(mCurrColour);
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(5);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// Capture a reference to each touch for drawing
float touchX = event.getX();
float touchY = event.getY();
mTouches.add(new ColouredPoint(Math.round(touchX), Math.round(touchY), mCurrColour));
return super.onTouchEvent(event);
}
#Override
protected void onDraw(Canvas c) {
// Let the image be drawn first
super.onDraw(c);
// Draw your custom points here
for (ColouredPoint p : mTouches) {
mPaint.setColor(p.colour);
c.drawCircle(p.x, p.y, 15, mPaint);
}
}
/**
* Class to store the coordinate and the colour of the point.
*/
private class ColouredPoint {
int x;
int y;
int colour;
public ColouredPoint(int x, int y, int colour) {
this.x = x;
this.y = y;
this.colour = colour;
}
}
}

How to send Canvas to object from onDraw function?

I am trying to animate my object. For drawing an object I need to use a canvas. I can send canvas to the object constructor only from onDraw function. But doing that, a new object is creating on every step of animation.
public class DrawView extends View {
public static Paint paint;
public DrawView(Context context) {
super(context);
paint = new Paint();
paint.setColor(Color.BLACK);
}
#Override
public void onDraw(Canvas canvas) {
Line s = new Line(10, 10, canvas);
super.onDraw(canvas);
s.move();
invalidate();
}
}
class Line{
private float x, y;
private Canvas canvas;
public Line(float x, float y, Canvas canvas) {
this.x = x;
this.y = y;
this.canvas = canvas;
}
public void move(){
draw();
x++;
y++;
}
public void draw(){
canvas.drawLine(x, y, x + 5, y + 5, DrawView.paint);
}
}
You mean this???
public void move(Canvas canvas){
draw(Canvas canvas);
x++;
y++;
}
public void draw(Canvas canvas){
canvas.drawLine(x, y, x + 5, y + 5, DrawView.paint);
}

How to create Enemies at specific time in libgdx

I am a newbie in libgdx. I am working on a game which has a player body and I have given controls but I want to create enemies at specific time in my game. I have tried creating it but only the player body is been created and but not enemy body.
This is my code
public class Player
implements Screen, InputProcessor {
private Body polybody;
private Player player;
private World world;
private Body enemybody;
private Sprite polysprite;
public final float width, height;
private Vector2 movement = new Vector2();
private float speed = 580;
public Player(World world, float x, float y, float width) {
this.width = width; //IMP
height = width * 2;
BodyDef polygon = new BodyDef();
polygon.type = BodyType.DynamicBody;
polygon.position.set(x, y); //
PolygonShape poly = new PolygonShape();
poly.setAsBox(width / 2, height / 2); //
//fixture defn
FixtureDef polyfixture = new FixtureDef();
polyfixture.shape = poly;
polyfixture.friction = 0.8f; //
polyfixture.restitution = 0.1f; //
polyfixture.density = 3; //
//creating actual body
polybody = world.createBody(polygon);
polybody.createFixture(polyfixture);
// polybody.applyAngularImpulse(52, true);
polysprite = new Sprite(new Texture("img/car.jpg"));
polysprite.setSize(0.5f, 1); //size of mario
polysprite.setOrigin(polysprite.getWidth() / 2, polysprite.getHeight() / 2);
polybody.setUserData(polysprite);
poly.dispose();
}
public void update() {
polybody.applyForceToCenter(movement, true);
}
public Body getBody() {
return polybody;
}
#Override
public void show() {
// TODO Auto-generated method stub
}
final float step = 0.1f;
float timeElapsed = 0f;
#Override
public void render(float delta) {
timeElapsed += delta;
while (timeElapsed > step) {
timeElapsed -= step;
Enemy();
}
}
public void Enemy() {
BodyDef enemy = new BodyDef();
enemy.type = BodyType.DynamicBody;
enemy.position.set(6, 3);
PolygonShape enemypoly = new PolygonShape();
enemypoly.setAsBox(2, 2);
FixtureDef enemyfixture = new FixtureDef();
enemyfixture.shape = enemypoly;
enemyfixture.friction = 0.75f;
enemyfixture.restitution = 0.1f;
enemyfixture.density = 5;
enemybody = world.createBody(enemy);
enemybody.createFixture(enemyfixture);
enemypoly.dispose();
}
#Override
public void resize(int width, int height) {
// 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 hide() {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
// TODO Auto-generated method stub
}
#Override
public boolean keyDown(int keycode) {
// TODO Auto-generated method stub
switch (keycode) {
case Keys.W:
movement.y = speed;
break;
case Keys.S:
movement.y = -speed;
break;
case Keys.D:
movement.x = speed;
break;
case Keys.A:
movement.x = -speed;
}
return true;
}
#Override
public boolean keyUp(int keycode) {
// TODO Auto-generated method stub
switch (keycode) {
case Keys.W:
movement.y = 0;
break;
case Keys.S:
movement.y = 0;
break;
case Keys.D:
movement.x = 0;
break;
case Keys.A:
movement.x = 0;
}
return true;
}
#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
movement.x = speed;
Gdx.app.log("Example", "touch done ");
return true;
}
}
This is the player class that gets called first and after this on render method the enemy method gets called. The player body is working fine but I couldn't see any enemy body. Please help .Thanks in advance !!
Apparently, your Player class is responsible for:
Handling inputs for controlling the game
the construction of enemy objects
rendering the entire world (handling time) and displaying the world and all objects
creating Textures (that is supposed to be created only once, not every time you make a Sprite!)
Aaaand you don't have any other class.
I think you should fix this problem.
Also, I'm a bit weary of that you're calling dispose() each time after you create an object.
By the way, the render() method only gets called if you set the active screen for the Game, so
public class MyGame extends Game {
...
MyScreen myScreen = new MyScreen();
...
public void goToMyScreen() {
this.setScreen(myScreen);
}
}
Something like that is necessary for render() to work.
And please check How to track time in Libgdx(android) on how to handle elapsed time.
I suggest a refactoring of your application. That class Player doesn't look like the right place for creating enemies (which you seem to do in every step). Instead you should create the Enemy in the same place where you create your Player and give your Enemy an own class.
Furthermore you could write debug messages to the console or use your IDE's debugger to check what your code is actually doing.

Libgdx screen render function being called but not drawing

I have been having a problem with the rendering in my screens.
Basically I have an overall class that extends Game and I have created a few other classes for the various pages for my game such as the Main Menu, the actual game etc. When I call setScreen(screen) on one of these classes the rendering loop of that screen is called, but I cant seem to draw anything.
What I have done is that I created the orthographic camera and spritebatch in the overall game class and passed it to the screens through their constructor method. However, I don't seem to be able to draw anything. The screen still clears the background.
Sorry I don't have my source code at the moment but here is roughly what it looks like:
This is my overall game class:
public class MyGdxGame extends Game {
public OrthographicCamera camera;
public SpriteBatch batch;
public ResourceManager Rm;
public StartScreen MainMenu;
public GameScreen CellTD;
public InstructionsScreen Instructions;
public PauseScreen Pause;
#Override
public void create() {
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
Rm = new ResourceManager();
camera = new OrthographicCamera(1.0f, h/w);
batch = new SpriteBatch();
Rm.LoadTexture("Cell.png");
MainMenu = new StartScreen(camera, batch, Rm, this);
CellTD = new GameScreen(camera, batch, Rm, this);
Instructions = new InstructionsScreen(camera, batch, Rm, this);
Pause = new PauseScreen(camera, batch, Rm, this);
setScreen(MainMenu);
}
#Override
public void dispose() {
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}
This is one of my screen classes:
public class StartScreen implements Screen{
private OrthographicCamera camera;
private SpriteBatch batch;
private ResourceManager Rm;
private int SCREEN_W, SCREEN_H;
public MyGdxGame Parent;
private Label Title;
private Sprite s;
StartScreen(OrthographicCamera c, SpriteBatch b, ResourceManager r, MyGdxGame g)
{
camera = c;
batch = b;
Rm = r;
SCREEN_W = Gdx.graphics.getWidth();
SCREEN_H = Gdx.graphics.getHeight();
Parent = g;
camera.setToOrtho(false,1.0f,SCREEN_H/SCREEN_W);
camera.update();
Title = new Label("Cell TD",new Label.LabelStyle(new BitmapFont(Gdx.files.internal("data/CellTDFont.fnt"),false) ,new Color(1.0f,1.0f,1.0f,1.0f)));
Title.setText("Cell TD");
Title.setSize(1.0f, SCREEN_H/SCREEN_W);
Title.setOrigin(Title.getWidth()/2, Title.getHeight()/2);
Title.setPosition(0, 0);
s = new Sprite(Rm.GetTexture("Cell.png"));
s.setSize(1.0f, SCREEN_H/SCREEN_W);
s.setOrigin(s.getWidth()/2, s.getHeight()/2);
s.setPosition(-0.5f, -SCREEN_H/SCREEN_W/2);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0.9f, 0.9f, 0);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
//Title.draw(batch,1);
s.draw(batch);
batch.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
}
}
Its an easy bug.
Your camera is not correct i guess.
c = new OrthographicCamera(1.0f,h/w);
this means that the camera is 1px width and h/w height... and your sprite is like 100x200 for example. So the only thing you will see is around 1px of the sprite.
Do change the constructor of it to something liket this:
float w = Gdx.graphics.getWidth(); //the width of the window
float h = Gdx.graphics.getHeight();//the height of the window
camera = new OrthographicCamera(w, h);
Dont forget to resize the camera inside of the resize.
maybe take a look at the new libgdx wiki here:
Orthographic camera
Spritebatch, textureregions, and sprite

How to clear drawing on a canvas in Android

I have already set up the canvas for the drawing. My problem now is how to clear the drawing.
Tried doing this to no avail.
public void clear()
{
circlePath.reset();
mPath.reset();
// Calls the onDraw() method
//invalidate();
}
Please take a look at the whole code here:
https://gist.github.com/akosijiji/a29cca90bead2e5e35ad
Any help is truly appreciated.
On button click
b1.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
dv.clear(); // call clear method using in your custom view
}
});
Define a clear method in your custom view
public void clear()
{
mBitmap = Bitmap.createBitmap(width,height ,
Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
//Added later..
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.GREEN);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
invalidate();
}
Reset all drawing tools and call invalidate to refresh the view.
Complete working code
public class MainActivity extends Activity implements ColorPickerDialog.OnColorChangedListener {
DrawingView dv ;
RelativeLayout rl;
private Paint mPaint;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dv = new DrawingView(this);
setContentView(R.layout.activity_main);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.GREEN);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
rl = (RelativeLayout) findViewById(R.id.rl);
rl.addView(dv);
Button b = (Button) findViewById(R.id.button1);
//b.setText(R.string.France);
Button b1 = (Button) findViewById(R.id.button2);
rl.setDrawingCacheEnabled(true);
b.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
// dv.clear();
new ColorPickerDialog(MainActivity.this, MainActivity.this, mPaint.getColor()).show();
}
});
b1.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
dv.clear();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public class DrawingView extends View {
private int width;
private int height;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
Context context;
private Paint circlePaint;
private Path circlePath;
public DrawingView(Context c) {
super(c);
context=c;
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
circlePaint = new Paint();
circlePath = new Path();
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.BLUE);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(4f);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width =w;
height =h;
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
public void clear()
{
mBitmap = Bitmap.createBitmap(width,height ,
Bitmap.Config.ARGB_8888);
//Log.d("BITMAP","Restoring...");
//mBitmap=BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
mCanvas = new Canvas(mBitmap);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
//Added later..
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.GREEN);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
canvas.drawPath(circlePath, circlePaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
mX = x;
mY = y;
circlePath.reset();
circlePath.addCircle(mX, mY, 30, Path.Direction.CW);
// invalidate();
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
circlePath.reset();
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath.reset();
// mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));//.Mode.SCREEN));
mPaint.setMaskFilter(null);
mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SCREEN);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
}
#Override
public void colorChanged(int color) {
// TODO Auto-generated method stub
mPaint.setColor(color);
}
}
The above works but it is not good design coz everytime you need to clear you will be creating objects like paint object.
You can create singleton class and have your tools reset and then call invalidate
public class DrawingManager {
private static DrawingManager mInstance=null;
public DrawingTools mDrawingUtilities=null;
public int mThemeIndex;
public Canvas mCanvas;
public Path mPath;
public Paint mBitmapPaint;
public Bitmap mBitmap;
public Paint mPaint;
private DrawingManager()
{
resetDrawingTools();
}
public static DrawingManager getInstance()
{
if(mInstance==null)
{
mInstance=new DrawingManager();
}
return mInstance;
}
public void resetDrawingTools()
{
mBitmap = Bitmap.createBitmap(screenwidth,screenheight ,
Bitmap.Config.ARGB_8888)
mCanvas = new Canvas(mBitmap);
Path = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
//Added later..
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.Green);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
}
/**
* Clears the drawing board.
*/
public static void clearDrawingBoard()
{
mInstance=null;
}
public void resetBitmapCanvasAndPath() {
// TODO Auto-generated method stub
mBitmap = Bitmap.createBitmap(screenwidth,screenheight ,
Bitmap.Config.ARGB_8888);
//Log.d("BITMAP","Restoring...");
//mBitmap=BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
mCanvas = new Canvas(.mBitmap);
mPath = new Path();
}
}
In your painting class
private DrawingManager mDrawingManager=null;
mDrawingManager=DrawingManager.getInstance();// initialize drawing tools once
Then on button click to clear draw
mDrawingManager.resetBitmapCanvasAndPath();
invalidate();
you should use yourpaintlayout.removeallviews();
you would have added one layout to your drawing canvas class. You will have option to remove all views from your drawing layout. hope this will help you.

Categories