I'm trying to make my first android game, just a pong clone really, I have a "PongView" class that extends SurfaceView and is my only view. It has objects of my "Ball" and "Paddle" classes. I just started moving code related to things, like detecting wall collisions, to the Ball and Paddle classes to tidy up my main view a bit and realised that i'd need to give these classes a way to know the views width and height. At the moment my work around is just to intialise a global variable inside the surfaceviews surfaceChanged method that stores the width and height of the view, like so:
//at the top of my class
private int viewWidth;
private int viewHeight;
..
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
//INITIALISE viewWidth and viewHeight here
//so that they can be passed as parameters
viewWidth = getWidth();
viewHeight = getHeight();
//some other irrelevant code here
}
Then I pass them as parameters:
ball.handleWallCollision(viewWidth, viewHeight);
However i'm not sure this is the way to go about it, as i will need to pass them in quite often i imagine. I thought it would be better if i had a copy of the current PongView in each class? But i'm not sure if thats true or how/when to go about getting it.
What would you recommend? Thanks
use object of surface view class that was used to setting view in activity.That object is live and will contain all changes regarding that surface view
SurfaceView sur=new SurfaceView(this); /// you created object
setContentView(sur);
//you do your work
//surface view is running
Now you want to exit from that activity.Then in onDestroy() used
CommonClass.ObjectVraible=sur;
this line will save current state of the surfaceview
Related
I want to apply a simple rotationX animation when a group expands/collapses on an ExpandableListView. The code below works in first two expands but after two/three/five times does not play the defined animation. The strange thing is that the first time that I expand /collapse it works perfect!
ExpandableListview exp = new ExpandableListview(context);
// set adapter code
LayoutTransition transition = new LayoutTransition();
Animator appearAnim = ObjectAnimator.ofFloat(null, "rotationX", 90f,0f).setDuration(transition.getDuration(LayoutTransition.APPEARING));
transition.setAnimator(LayoutTransition.APPEARING, appearAnim); // I also tried first argument equals DISSAPEARING, CHANGING, etc
exp.setLayoutTransition(transition);
Any idea?? Is this approach totally wrong???
I have to notice at this point that this is not a duplicate! I am looking for a solution that will be approached with LayoutTransition class / methods.
Here is some awesome sample which may help you to do animation on expands/collapses on an ExpandableListView, In the android-flip library that uses OpenGL for rendering animation ,if the minimum supported Android version for the app was 4.0 we can use standard Android SDK methods instead of OpenGL: View.setRotationX(), View.setScaleX(), etc. When hardware acceleration is enabled (and it is enabled by default if your target API level is >=14), these methods work quite efficiently using the device GPU.
You can use this FoldableLayout to implement folding animation for expands/collapses on an ExpandableListView.
Layout implementation in FoldableLayout:
The first element to design was a layout that can fold in half. Our
approach was rather bold: the main layout (FoldableItemLayout) simply
contains a specialized layout (BaseLayout). During the animation, the
BaseLayout writes its contents to cache which is a specially created
Bitmap object based on the size of the original layout. view plaincopy
to clipboardprint?
class FoldableItemLayout extends FrameLayout {
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Bitmap cacheBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mBaseLayout.setCacheCanvas(new Canvas(cacheBitmap));
}
}
class BaseLayout extends FrameLayout {
private Canvas mCacheCanvas;
private void setCacheCanvas(Canvas cacheCanvas) {
mCacheCanvas = cacheCanvas;
}
#Override
public void draw(Canvas canvas) {
mCacheCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
super.draw(mCacheCanvas);
}
}
In addition, we needed to use two extra Views (PartView) – for the
upper and lower image halves – which would display the corresponding
data in cache that represents the upper and lower halves of the image
(Bitmap). Both Views encompass the entire area of the main layout, but
display only the required parts. To achieve this effect, we calculated
the Bitmap limits – and in the onDraw() method we made Canvas draw the
required part via the drawBitmap (Bitmap bitmap, Rect src, RectF dst,
Paint paint) method.
Then we managed to rotate these extra Views by setting the
setRotationX() method to the corresponding angle, achieving
independent rotation of the lower and upper parts of the images. To
pull this off, we add a new parameter for the FoldableItemLayout –
with the name FoldRotation.
Source: How to Make a Paper Folding Animation in Android?
Okay, so I have a GameField class, and a GameObject class and a Panel class.
The GameObject class describes an object, which has an x and y position, width and height, and x and y direction (in which it is currently moving). The GameField class has a few different instances of these objects, some stored by themselves, and some stored in primitive arrays.
The Panel class is supposed to display these objects on the screen. I used JPanel for this.
However, when it comes to actually displaying them on the screen, I'm a bit lost. I need to implement a function called paintComponent(Graphics graphics), which takes in a Graphics object.
To start, I want to display all the objects on the screen, and set their colour. Their size, position, etc. are handled elsewhere. How can I use these attributes to set the actual objects to have a size, position and direction?
I may need to override the paintComponent function to display all the objects in GameField.
If you could help me out with some code, that'd be great.
I'm not quite clear on what you mean by "their size, position, etc. are handled elsewhere". For now, let's assume that you have approximately the following structure (fields and other methods ommitted for clarity) :
class GameObject {
java.awt.Color getColor() { ... }
java.awt.Point getPosition() { ... }
java.awt.Point getDirection() { ... }
java.awt.Dimension getSize { ... }
}
class GameField {
List<GameObject> getGameObjects() { ... }
}
class Panel extends JPanel {
private GameField getGameField() { ... }
#Override
public void paintComponent(Graphics g) {
// this is where the GameObjects must be painted
}
}
The paintComponent method is responsible for the screen representation of the Panel class. If you override it, you have just won that responsibility from it. Luckily, drawing is - if tedious - rather simple. You asked about that Graphics parameter. Very simply put, it is set for you by the magic of Java and gives you a toolbox to use for drawing.
First, you will want to have a clean slate whenever the panel is repainted. You cannot delete anything once it is painted, but you can easily paint the entire panel in a background color of your choice.
g.setColor(Color.white); // everything that is now painted will be white
g.fillRect(0, 0, getWidth(), getHeight()); // fills the entire area with the set color
Now, for each GameObject you have, let's place rectangle in the objects' defined color and size on the screen, with it's center on the object's position.
for (GameObject object : getGameField().getGameObjects()) {
g.setColor(object.getColor());
g.fillRect(object.getPosition().x - (object.getSize().x / 2), object.getPosition().y - object.getSize().y / 2, object.getSize().x, object.getSize().y);
}
The fillRect method requires the first two arguments to be the top-left corner of the rectangle. So to have it centered on the object's position, we subtract half the size from the position for the x and y values respectively. Now you have, for every GameObject, a rectangle of the right diameter in the object's color at the right position.
You should read up on the javadoc on java.awt.Graphics to find out how to draw other stuff, maybe image sprites or lines for the direction or something. It is cumbersome but doable.
I'm writing an app that requires getting the mic level to create a sound meter. I have found this: Android Media Player Decibel Reading. I still need to create a meter to display the current level, out of 100% kind of deal. So a bar that the higher it gets it gets redder for example. Just getting the code to display the level is great.
In the link above there is a method for getting the current decibel reading, however it appears to be something that I would need to possibly run in a separate thread and update it constantly. I was reading into a VU meter but have no clue where to start.
Thanks in advance!
Okay I'm assuming your working with the code you linked to in your question.
So this meter will have to change its size and colour on the fly depending on the value of amplitude.
To draw the shape extend the View class and override the onDraw method as shown below
float x,y; //CONSTANTS FOR WHERE YOU WANT YOUR BAR TO BE
float baseWidth; // This is the width of one block.
//Number of blocks together will be your rectangle
float nwidth; //This is the number of blocks varying according to amplitude
float height; //CONSTANT HEIGHT
Paint color=new Paint();
//For drawing meter
public void onDraw(Canvas c){
changeColorAndSize();
Rect rect = new Rect(x, y, x + (baseWidth*nwidth), y + height);
shapeDrawable.setBounds(rect);
shapeDrawable.getPaint().set(paint);
shapeDrawable.draw(canvas);
}
public void changeColorAndSize(){
double amp=getAmplitude();
nWidth=amp;
paint.setARGB (a, r*(Integer.parseInt(amp)), g, b);
//This will change the redness of the bar. a,g and b will have to be set by you
}
public double getAmplitude() {
if (mRecorder != null)
return (mRecorder.getMaxAmplitude());
else
return 0;
}
To make the meter change every 'x' seconds you will have to call postInvalidate() repeatedly
OR
Use an Animation, and call startAnimation() on it from your View.
I have a class that extends View and overrides the onDraw(Canvas canvas) method. This view runs animations, so onDraw will be called many times per second. Consider the following example...
#Override
protected void onDraw(Canvas canvas) {
final int width = getWidth();
final int height = getHeight();
final int padLeft = getPaddingLeft();
final int padTop = getPaddingTop();
final int padRight = getPaddingRight();
final int padBottom = getPaddingBottom();
final RectF oval = new RectF(padLeft, padTop, width - padRight, height - padBottom);
...
}
Should I be worried that there are this many function calls happening each time onDraw is called? Does final tell the compiler that it doesn't need to call these functions each time? Would these variables be better off as member variables so that the functions are only called once?
P.S. I know from running my program that performance is not affected. I am asking this question from a learning standpoint. It makes me feel better when I know exactly what I'm doing.
by saying final here you just saying that this local variable will not be changed in this function and functions will be called each time you call onDraw.
If it is possible it's better to compose all this variables to another class like DisplayProperties and initialise it only once.
I'm trying my app format some images in the screen after the Activity loads. The problem is while inside onCreate(), onResume() methods my ImageView have width and height=0. How can I run some code after the views are resized?
I test onPostResume() but it dont work =(
Views in Android do not have fixed size/position like in Blackberry or iPhone; instead, they are layed out dynamically. Layout happens much later than onCreate/onResume, and theoretically can happen many times. Every view has methods onMeasure and onLayout which are responsible for that. Only after onLayout method returns you can tell the view's size and position. Before that the view's size is 0 and position is 0 (as you've noticed).
So it makes little sense trying to get ImageView's size in onCreate/onResume because onLayout hasn't yet been called at that point.
Instead, override onLayout like this and do your stuff there:
public class MyImageView extends ImageView {
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
// at this point size and position are known
int h = getHeight();
int w = getWidth();
doSomethingCool(h,w);
}
}