I try to use setRotation() on my GLSurfaceView, but the view seems not rotate around the pivot which is the center of the screen. the code like below:
class MyGLSurfaceView extends GLSurfaceView {
private float mCurRotation = 0.0f;
#Override
public boolean onTouchEvent(MotionEvent e) {
mCurRotation = mCurRotation + 10;
setRotation(mCurRotation);
}
}
Is there any body know the reason and teach me how to rotate my GLSurfaceView?
Contrary to your expectation, methods of View doesn't work well.
GLSurfaceView punches a hole to display underneath surface. Actually it has only transparent pixels.
If you want to rotate your image, you have to use OpenGL operations.
Related
I am trying to follow the tutorial from https://www.youtube.com/watch?v=X2ls3FTPOAc in order to zoom into my drawable which lies inside an imageview.
I see here that the scaleListener object is called since the Log outputs that it's being called. However, when I use the ImageView.ScaleType.MATRIX scale type for the image-view it doesn't seem to work. I've also added a slight modification in the onScale method. Here's my code:
view1.setScaleType(ImageView.ScaleType.MATRIX); //using CENTER works
Matrix matrix = new Matrix();
view1.setImageMatrix(matrix);
DummyDraw drawD = new DummyDraw(this);
view1.setImageDrawable(drawD);
scaleGestureDetector = new ScaleGestureDetector(this, new ScaleListener());
a few methods down I have:
public boolean onTouchEvent(MotionEvent event){
scaleGestureDetector.onTouchEvent(event);
return true; }
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener{
public boolean onScale(ScaleGestureDetector detector) {
Log.d("inside1044","inside scale listener onSscale method ");
float scaleFactor = detector.getScaleFactor();
scaleFactor = Math.max(0.1f, Math.min(scaleFactor,5.0f));
scaleFactor2 = scaleFactor;//a modification I made
matrix.setScale(scaleFactor,scaleFactor);
view1.invalidateDrawable(view1.getDrawable());//this is the modification I made
return true;}
}
Now, the DummyDraw class extends Drawable which just draws a pink background and a circle in the middle of the canvas. the variable scaleFactor2 is static and defined in the MainActivity, so everytime the user touches the view the method onScale is called updating the new value for scaleFactor2. I use this scaleFactor2 value somehow to try to scale the canvas of my drawable object. Here's what the code looks like inside the drawable object, inside the onDraw():
//define some variables to get the center of the canvas
canvas.save();
canvas.scale(MainActivity.scaleFactor2,MainActivity.scaleFactor2);
//draw the circle to the screen
canvas.restore();
When I place both fingers on the screen and bring them closer together the circle jumps and moves slightly, however when I move the fingers apart nothing happens. Remember, that this works only when the ImageView.ScaleType is set to CENTER not to MATRIX.
I am trying to accomplish a smooth zoom in and out of the view.
Any ideas would be appreciated.
I have a class which is extended from ImageView (lets call it 'surface'). On onDraw method, a little dot is drawing on canvas. When I click a button I try to move this dot to another location. You can consider like manual version of translate animation. It works but now I try to figured out speed of this moving. I mean I want dot moving faster.
Relevant part of surface :
private float actual_x=100,actual_y=100; // Dot is drawn on 100,100 at beginning
private float increase_x,increase_y;
private boolean isMovingResume=false;
private int moving_counter;
public void changeLocation(float x,float y){
isMovingResume=true;
moving_counter=0;
increase_x=(x-actual_x)/50;
increase_y=(y-actual_y)/50;
invalidate(); // This trigger onDraw method
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(actual_x,actual_y,15,fill_paint);
if(isMovingResume){
actual_x=actual_x+increase_x;
actual_y=actual_y+increase_y;
if(moving_counter==49){ // Moving will end after 50 redraw
isMovingResume=false;
}
else{
moving_counter++;
}
invalidate(); //redraw
}
}
And my button click :
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
surface.changeLocation(200,200);
}
});
Like I said, it works but I want it more faster. For example, in this case moving time is 2 second, How can I make it 0,5 second ?
Thanks for all replies.
You need to switch to surfaceview or even faster textureview, both use a canvas as well, and have better performance. Textureview especially as it is hardware accelerated and I also feel it behaves better than surfaceview. That or even consider going to GLSurfaceView.
You can see some example code of surfaceview and textureview: Here
I want the game screen on the Android device to change to a screen that displays "LEVEL COMPLETE". I made a .png file with this message in the middle and want to basically load it on top of the current screen (like a Fragment i guess?) when Player collides with Flag (both are modelled as rectangles for the sake of collision detection). This is my Flag class
public class Flag extends GameObject {
private Sprite spr;
private Rectangle playerRect;
private boolean isOverlapping;
Player player;
private Rectangle flagRect;
public Flag(Sprite spr, float xPos, float yPos) {
super(spr, xPos, yPos);
player = Player.getInstance(null);
setxPos(xPos);
setyPos(yPos);
flagRect = new Rectangle(getxPos(), getyPos(), getSprite().getWidth(),
getSprite().getHeight());
}
public void update() {
playerRect = new Rectangle(player.getxPos(), player.getyPos(), player
.getSprite().getWidth(), player.getSprite().getHeight());
isOverlapping = playerRect.overlaps(flagRect);
if(isOverlapping) {
...
}
}
}
I put levelComplete.png in my assets folder and am a little unsure where to go from here. Any suggestions? Would be highly appreciated
All you need to do is make a Texture from your image and draw it on your screen using SpriteBatch. This can be achieved with something like this:
public Texture levelComplete = new Texture(Gdx.files.internal("assets/imageName.png"));
public SpriteBatch batch = new SpriteBatch();
public render(){
batch.begin();
if(isOverlapping){
batch.draw(levelComplete, x, y);
}else{
// render game
}
batch.end();
}
Note that you might want to put some timer and stop drawing the Texture after like 5 seconds or put some sort of "ok" button. Otherwise you will be stuck with the same Texture.
Instead of creating an image that contain your text "Level Complete " you can use BitmapFont to write it down on your screen with any font you like
first choose your font (you can generate any font you want using tools like Hiero)
put them on assets file and load them using this line of code
textFont = new BitmapFont(Gdx.files.internal("nameFont.fnt"), gdx.files.internal("nameFont.png"), false);
then you have just to write your text in the position you want
textFont.draw(spritebatch, "Level Complete", x, y)
hope it will help !
I have drawn a bitmap image over a canvas.
Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.sq);
canvas.drawColor(color.black);
Rect dstRectForRender = new Rect(0,0,320,450);
canvas.drawBitmap(image, null,dstRectForRender,null);
The image gets displayed based on my screnn on a cnavs.
On my touch input, I need to pass the x and y co-ordinate position of the image and fill that pixel with a color to show that the image is painted on a drag event.
How can I pass the x and y coo-ordinate parameters? Which functions should I use to plot the pixels on the image?
I appreciate your help and sweet time.
I'm not sure if this is the best way to do this, but it would be much easier to do this if you defined your own subclass of ImageView and name it something like DrawableImageView. You'd have to make sure you implement all the basic constructors from ImageView, then override the onTouchEvent method. From that event you can get the touch coordinates and store them in an ArrayList<Point> and use that ArrayList by overriding the onDraw method and "painting" the image.
public class DrawableImageView extends ImageView {
ArrayList<Point> list = new ArrayList<Point>();
//constructors..
#Override
public boolean onTouchEvent (MotionEvent event) {
float x = event.getX();
float y = event.getY();
list.add(new Point(x,y));
invalidate();
}
This is just a very brief overview of how to start your class, and may not be the most accurate way of doing things (depending on your specific code). Now, instead of using <ImageView> tags in your xml (or, loading an ImageView programatically), you refer to your subclass like so:
<your.package.name.DrawableImageView
/>
Edit
In response to your comment, there is no predetermined way to draw over an image. You must implement this yourself, which is why I recommended storing Points in an ArrayList. I'm not really sure what you're trying to achieve here, but to draw (for example) black dots over an image you have to override onDraw:
public void onDraw(Canvas c) {
super.onDraw(c);
for(Point p : list) {
//Draw black point at x and y.. I'm posting from my cell so I can't go into much detail
}
}
Also, to force a View to redraw itself you need to use the invalidate() method in your onTouchEvent() (which I've added above).
It is possible to render a view at a low resolution, and then scale it up to fit the actual size of your view using the setFixedSize() method of a SurfaceHolder. However, the scaling is done with some kind of interpolation, causing everything to blur.
Is there any method for changing the method of interpolation to nearest neighbour or just turning it off?
Here is an example of what I mean, Made with a 4x4 surface in a fullscreen-view:
Left image: This is how I want the result to look (here achieved by drawing a nonfiltered bitmap)
Right image: This is what happens when the 4x4 canvas is scaled to fullscreen.
Sample code for generating the right image if anyone's interested:
public class ScaleView extends SurfaceView implements SurfaceHolder.Callback {
private final static float[] points = {0,0, 2,0, 4,0, 1,1, 3,1, 0,2, 2,2, 4,2, 1,3, 3,3};
private Paint white;
public ScaleView(Context context) {
super(context);
white = new Paint();
white.setColor(0xFFFFFFFF);
getHolder().addCallback(this);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){
Canvas c = holder.lockCanvas();
try{
c.drawPoints(points, white);
}finally{
holder.unlockCanvasAndPost(c);
}
}
#Override
public void surfaceCreated(SurfaceHolder holder){
holder.setFixedSize(4, 4);
}
#Override
public void surfaceDestroyed(SurfaceHolder holder){}
}
Note: The square pattern above is just an example of the effect I want to avoid. I am looking for a general solution that can be applied to any view (with a surfaceholder) with any content.
Sorry, you can't control this. It is not defined what kind of scaling will be done on these surfaces -- it depends on the hardware and how it is configured. Also, this kind of extreme scaling really should be avoided, since in some cases hardware can't do it so you will end up in slower paths. (For example if surfaces are being put into overlays, many hardware overlay engines can't do that kind of extreme scaling.)