I develop tile based game to draw i use function canvas.drawBitmap() in each frame function drawBitmap using 400+ times when i use scroll (Gestures) performance is pretty bad.
Can anyone give me advice how to increase performance to make smooth animation.
public class DiamondIsometric implements Render{
private int MapWidth;
private int MapHeight;
private Bitmap _surface;
private Bitmap tempBitmap;
public DiamondIsometric(int MapWidth,int MapHeight,Bitmap _surface)
{
this.MapWidth=MapWidth;
this.MapHeight=MapHeight;
this._surface = _surface;
}
public MapObject[][] BuildMap()
{
int rx;
int ry;
MapObject[][] MapObjects = new MapObject[MapWidth][MapHeight];
for(int x=0;x<MapHeight;x++)
for(int y=0;y<MapWidth;y++)
{
rx=(x-y)*_surface.getWidth()/2;
ry=(x+y)*_surface.getHeight()/2;
MapObject temp = new MapObject(new Point(rx,ry),_surface);
MapObjects[x][y]=temp;
}
return MapObjects;
}
#Override
public void Render(Canvas canvas) {
}
#Override
public void Render(Canvas canvas,MapObject[][] MapObjects)
{
Paint temp = new Paint();
temp.setColor(Color.BLACK);
canvas.drawPaint(temp);
Bitmap toDraw = Bitmap.createBitmap(MapWidth*_surface.getWidth(), MapHeight*_surface.getHeight(), Config.RGB_565);
int bitmapOffsetX,bitmapOffsetY;
canvas.drawBitmap(this.Render2(canvas,MapObjects),0,0,null);
}
public Bitmap Render2(Canvas canvas, MapObject[][] MapObjects)
{
Paint temp = new Paint();
temp.setColor(Color.BLACK);
tempBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Config.RGB_565);
Canvas wideBMPCanvas = new Canvas(tempBitmap);
int bitmapOffsetX,bitmapOffsetY;
for(int i=0;i<MapObjects.length;i++)
for(int j=0;j<MapObjects[i].length;j++)
{
bitmapOffsetX=(IsometricView.globalAnchor.x % MapObjects[i][j]._bitmap.getWidth());
bitmapOffsetY=(IsometricView.globalAnchor.y % MapObjects[i][j]._bitmap.getHeight());
wideBMPCanvas.drawBitmap(MapObjects[i][j]._bitmap,MapObjects[i][j].coords.x-IsometricView.globalAnchor.x ,MapObjects[i][j].coords.y-IsometricView.globalAnchor.y , null);
}
return tempBitmap;
}
}
Use a game engine like andEngine or libgdx. They use OpenGL rendering which is usually much faster.
Update: If you want not to use OpenGL/game engines you should try to combine tiles into a larger bitmap. Create a larger bitmap and create a new canvas (new Canvas(largeBitmap)) to draw the tile to it. Drawing one larger is faster than drawing multiple smaller ones. For my Game K'UMPA I used a similar approach, which is more complex in detail, because only a small part of the map is visible on the screen.
Maybe you could try to not create a bitmap at each render call.
I assume that you're calling render for each frame:
public class DiamondIsometric implements Render {
private int MapWidth;
private int MapHeight;
private Bitmap _surface;
private Bitmap toDraw;
private Canvas wideBMPCanvas;
public DiamondIsometric(int MapWidth,int MapHeight,Bitmap _surface)
{
this.MapWidth = MapWidth;
this.MapHeight = MapHeight;
this._surface = _surface;
this.toDraw = null;
this.wideBMPCanvas = null;
}
public MapObject[][] BuildMap()
{
int rx;
int ry;
MapObject[][] MapObjects = new MapObject[MapWidth][MapHeight];
for(int x=0;x<MapHeight;x++)
for(int y=0;y<MapWidth;y++)
{
rx=(x-y)*_surface.getWidth()/2;
ry=(x+y)*_surface.getHeight()/2;
MapObject temp = new MapObject(new Point(rx,ry),_surface);
MapObjects[x][y]=temp;
}
return MapObjects;
}
#Override
public void Render(Canvas canvas) { }
#Override
public void Render(Canvas canvas,MapObject[][] MapObjects)
{
Paint temp = new Paint();
temp.setColor(Color.BLACK);
canvas.drawPaint(temp);
if (this.toDraw == null) {
this.toDraw = Bitmap.createBitmap(MapWidth*_surface.getWidth(), MapHeight*_surface.getHeight(), Config.RGB_565);
}
if (this.wideBMPCanvas == null) {
this.wideBMPCanvas = new Canvas(this.toDraw);
}
int bitmapOffsetX,bitmapOffsetY;
for (int i = 0; i < MapObjects.length; i++) {
for(int j = 0; j < MapObjects[i].length; j++)
{
bitmapOffsetX = (IsometricView.globalAnchor.x % MapObjects[i][j]._bitmap.getWidth());
bitmapOffsetY = (IsometricView.globalAnchor.y % MapObjects[i][j]._bitmap.getHeight());
this.wideBMPCanvas.drawBitmap(MapObjects[i][j]._bitmap, MapObjects[i][j].coords.x - IsometricView.globalAnchor.x,
MapObjects[i][j].coords.y - IsometricView.globalAnchor.y, null);
}
}
canvas.drawBitmap(this.toDraw, 0, 0, null);
}
}
Related
--WORKING ON A SHORTER VERSION OF THE QUESTION--
So, this is someting I can't really find that much information on online.
I am making a game together with my friend and we came accross a problem when we wanted to move some objects in a thread. We have one object, GroundBlocks, which is working fine and how it is supposed to.
Then we have the other object, Obstacles, that uses the same "method" of printing and processing but doesn't show up.
I did some troubleshooting myself and I noticed that the paintComponent block in Obstacles isn't beeing called by the .setLocation we added in the thread.
As I mentioned, I didn't find a whole lot online when searching myself but through testing, I know the numbers are correct but it is just not showing.
Any ideas on what the issue might be with the .setLocation not working?
--Relevant code from the thread class--
// Creating objects
public static GroundBlocks[] ground = {new GroundBlocks(), new GroundBlocks(), new GroundBlocks()};
public static Obstacles[] obstacle = {new Obstacles(), new Obstacles(), new Obstacles(), new Obstacles(), new Obstacles()};
// Creating block dimensions
final int GROUND_HEIGHT = resY - GroundBlocks.getGroundHeight();
final int GROUND_WIDTH = ground[1].getGroundWidth();
int[] groundX = {0, GROUND_WIDTH, GROUND_WIDTH*2};
final int OBSTACLE_HEIGHT = obstacle[0].getHeight();
final int OBSTACLE_WIDTH = obstacle[0].getWidth();
int[] obstacleX = {newCoord(0), newCoord(0), newCoord(0), newCoord(0), newCoord(0)};
int[] obstacleY = {newCoord(1), newCoord(1), newCoord(1), newCoord(1), newCoord(1)};
// Setting game animation movement
final int MOVEMENT_SPEED = 7;
// Setting timer object with preferred FPS
Timer time = new Timer(Init.getFps(0), this);
public void run() {
System.out.println("A new MainThread has been initiated");
time.start();
// Setting ground block size, starting location and image
for(int i = 0; i < ground.length; i++) {
ground[i].setLocation(groundX[i], GROUND_HEIGHT);
ground[i].setSize(GROUND_WIDTH, GROUND_HEIGHT);
ground[i].setGroundImage(pickRandomGroundImage());
}
// Setting background image for obstacles
for (int i = 0; i < obstacle.length; i++) {
obstacle[i].setSize(OBSTACLE_WIDTH, OBSTACLE_HEIGHT);
obstacle[i].setLocation(obstacleX[i], obstacleY[i]);
obstacle[i].setObstacleImage(img5);
// System.out.println(obstacle[i].getLocation());
}
}
#Override
public void actionPerformed(ActionEvent arg0) {
for(int i = 0; i < ground.length; i++) {
// Respawning ground block
if(groundX[i] <= -resX) {
groundX[i] = GROUND_WIDTH*2 - MOVEMENT_SPEED;
ground[i].setGroundImage(pickRandomGroundImage());
}
// Animating ground block
ground[i].setLocation(groundX[i] -= MOVEMENT_SPEED, GROUND_HEIGHT);
}
for (int i = 0; i < obstacle.length; i++) {
// Resetting obstacle block
if ((obstacleX[i] + OBSTACLE_WIDTH) <= -10) {
obstacleX[i] = newCoord(0);
obstacleY[i] = newCoord(1);
obstacle[i].setObstacleImage(img5);
}
// Animating obstacle block
obstacle[i].setLocation(obstacleX[i] -= MOVEMENT_SPEED, obstacleY[i]);
if (i == 0) {
System.out.println(obstacle[i].getLocation());
}
}
}
--GroundBlocks class--
public class GroundBlocks extends JPanel{
// Declarations
static int resX = Main._init.getResX();
static int resY = Main._init.getResY();
static String font = Main._init.getOurFont();
private static int groundWidth;
private static int groundHeight;
private Image chosenImage;
public GroundBlocks() {
System.out.println("GroundBlock created");
setScaleIndex();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
//Draw image background
g.drawImage(chosenImage, 0, 0, this);
}
// Applying the scaleIndex to the ground objects X and Y dimensions.
// Size changes can be made manually in Init.
public void setScaleIndex() {
groundWidth = (int) (Init.getGroundSize(0) * Init.getScaleIndex());
groundHeight = (int) (Init.getGroundSize(1) * Init.getScaleIndex());
}
public int getGroundWidth() {
return groundWidth;
}
public static int getGroundHeight() {
return groundHeight;
}
public void setGroundImage(Image image) {
chosenImage = image;
}
}
--Obstacles code--
public class Obstacles extends JPanel{
// Declarations
static int resX = Main._init.getResX();
static int resY = Main._init.getResY();
static String font = Main._init.getOurFont();
private static int obstacleHeight;
private static int obstacleWidth;
private Image chosenImage;
public Obstacles() {
System.out.println("New obstacle object created!");
setScaleIndex();
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("Printed obstacle");
g.drawImage(chosenImage, 0, 0, this);
}
// Applying the scaleIndex to the ground objects X and Y dimensions.
// Size changes can be made manually in Init.
public void setScaleIndex() {
obstacleWidth = (int) (Init.getObstacleSize(0) * Init.getScaleIndex());
obstacleHeight = (int) (Init.getObstacleSize(1) * Init.getScaleIndex());
}
public int getObstacleHeight() {
return obstacleHeight;
}
public int getObstacleWidth() {
return obstacleWidth;
}
public void setObstacleImage(Image image) {
chosenImage = image;
}
}
I currently have the class for my main character "Student", it has no behaviors except the left and right movements. I managed to make it so all the frames of my spritesheet will render, so I need help in drawing the first 3 frames (which are the walk cycle) when I press LEFT / RIGHT keys.
Here's the spritesheet: http://imgur.com/a/HHdm9
Edit: AND 2nd and 3rd rows when pressing UP and Down Keys.
Student Class
public class Student {
private Texture player;
private Animation<TextureRegion> playerAnimation;
private int pX;
private int pY;
private SpriteBatch batch;
private int HP;
public Student(float speed, int x, int y){
player = new Texture("student.png");
TextureRegion[][] tmp= TextureRegion.split(player,450/3,450/3);
TextureRegion[] character = new TextureRegion[9];
int index = 0;
for(int i=0; i <3; i++){
for(int j=0; j < 3; j++){
character[index++] = tmp[i][j];}
}
playerAnimation = new Animation<TextureRegion>(speed,character);
pX=x;
pY=y;
}
public SpriteBatch getBatch() {
return batch;
}
public void setBatch(SpriteBatch batch) {
this.batch = batch;
}
public void goLeft(){
pX-=5;
if(pX < -10){
pX = -10;
}
}
public void goRight(){
pX+=5;
}
public void renderStudent(float stateTime){
TextureRegion currentFrame = playerAnimation.getKeyFrame(stateTime,true);
batch.draw(currentFrame, (float) pX, (float) pY, 0, 0, currentFrame.getRegionWidth(),
currentFrame.getRegionHeight(),1.5f,1.5f,0);
}
public void dispose(){
player.dispose();
}
}
Main Class
public class HaxMain extends ApplicationAdapter {
SpriteBatch batch;
Texture bg;
float stateTime;
private Student student1;
private Guard mguard, fguard;
private Admin madmin, fadmin;
#Override
public void create () {
batch = new SpriteBatch();
bg = new Texture("Level1.png");
student1 = new Student(.5f, 100, 0);
student1.setBatch(batch);
}
#Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stateTime += Gdx.graphics.getDeltaTime();
if(Gdx.input.isKeyPressed(Input.Keys.LEFT)){
student1.goLeft();
//Code to render image to the left
}else if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)){
//Code to render image to the right
student1.goRight();
}
batch.begin(); /*default code*/
batch.draw(bg, 0, 0);
student1.renderStudent(stateTime);
batch.end();
}
#Override
public void dispose () {
batch.dispose();
bg.dispose();
student1.dispose();
}
}
You need to create Animation only for Running and use that animation to show your player is running left or right. You can flip TextureRegion according to direction of your player like this :
TextureRegion[] character;
boolean isRight;
public Student(float speed, int x, int y){
player = new Texture("student.png");
TextureRegion[][] tmp= TextureRegion.split(player,450/3,450/3);
character = new TextureRegion[9];
int index = 0;
for(int i=0; i <3; i++){
for(int j=0; j < 3; j++){
character[index++] = tmp[i][j];}
}
TextureRegion runningFrames[]=new TextureRegion[3];
for (int i=0;i<runningFrames.length;i++)
runningFrames[i]= character[i];
playerAnimation = new Animation<TextureRegion>(speed, runningFrames);
playerAnimation.setPlayMode(Animation.PlayMode.LOOP);
pX=x;
pY=y;
}
public void goLeft(){
pX-=5;
if(pX < -10){
pX = -10;
}
if(isRight){
isRight=false;
for (TextureRegion textureRegion:playerAnimation.getKeyFrames())
if(textureRegion.isFlipX()) textureRegion.flip(true,false);
}
}
public void goRight(){
pX+=5;
if(!isRight){
isRight=true;
for (TextureRegion textureRegion: playerAnimation.getKeyFrames())
if(!textureRegion.isFlipX()) textureRegion.flip(true,false);
}
}
Create another animation of other action and draw frame of animation using flag.
Ive made a class that applies a tiling effect to a bufferedimage and i have to make a JUnit test on the class but im unsure of what to test and how i can test it.
I know i have to use assert and the likes but im not sure how.
I was thinking it would be something with the image being divided in 4.
public class TilesAction extends AbstractSelectedAction {
public static String ID = "edit.Tiles";
SVGImageFigure image;
public TilesAction(DrawingEditor editor) {
super(editor);
}
#Override
public void actionPerformed(ActionEvent ae) {
final DrawingView view = getView();
final LinkedList<Figure> figures = new LinkedList<Figure>(view.getSelectedFigures());
final Figure figure = figures.getFirst();
tiling(figure);
fireUndoableEditHappened(new AbstractUndoableEdit() {
#Override
public String getPresentationName() {
return labels.getTextProperty(ID);
}
#Override
public void redo() throws CannotRedoException {
super.redo();
}
#Override
public void undo() throws CannotUndoException {
super.undo();
}
});
}
private void tiling(Figure figure) {
image = (SVGImageFigure) figure;
BufferedImage tilingImage = image.getBufferedImage();
Graphics g = tilingImage.getGraphics();
DefaultDrawingView ddv = new DefaultDrawingView();
int width = tilingImage.getWidth() / 4;
int height = tilingImage.getHeight() / 4;
Image scaled = tilingImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
// Tile the image to fill our area.
for (int x = 0; x < tilingImage.getWidth(); x += width) {
for (int y = 0; y < tilingImage.getHeight(); y += height) {
g.drawImage(scaled, x, y, null);
}
}
g.dispose();
}
}
I was trying to animate a sprite for an android app and i've encounter a small problem. I'm drawing on a surfaceView that i add on top of already existing layouts. On this surfaceView, i wanted to animate few sprites so they would walk along a path.
So this is the result i'm facing right now :
The walking sprite is leaving a trail. So i decided to google this problem and apparently i had to clear the canvas first before drawing on it.
This was my onDraw method before :
public void onDraw(Canvas canvas) {
update();
int srcX = currentFrame * width;
int srcY = directionX * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
And this was my onDraw method after
public void onDraw(Canvas canvas) {
canvas.drawRGB(0, 0, 0);
update();
int srcX = currentFrame * width;
int srcY = directionX * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
So i now have this as a result
which is great because it leaves no more trail BUT i cant see the layouts underneath. Is there anyway i can get the best of both world ? I thought clearing the canvas would work but it obviously doesnt not work as expected.
I'll post my code below
SurfaceView :
public class MonsterView extends SurfaceView {
private Bitmap monsterImg;
private SurfaceHolder holder;
private MonsterThread mainThread;
private Sprite monsterSprite;
private int x;
private int xSpeed = 1;
public MonsterView(Context context) {
super(context);
this.mainThread = new MonsterThread(this);
this.x = 0;
holder = getHolder();
holder.setFormat(PixelFormat.TRANSPARENT);
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
mainThread.setRunning(true);
mainThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
mainThread.setRunning(false);
while (retry) {
try {
mainThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
});
setZOrderOnTop(true);
monsterImg = BitmapFactory.decodeResource(getResources(), R.drawable.fire);
monsterSprite = new Sprite(this,monsterImg);
}
#Override
public void onDraw(Canvas canvas) {
if (x == getWidth() - monsterImg.getWidth()) {
xSpeed = -1;
}
if (x == 0) {
xSpeed = 1;
}
x = x + xSpeed;
monsterSprite.onDraw(canvas);
}
Thread :
public class MonsterThread extends Thread {
private MonsterView monsterSurface;
private boolean running;
static final long FPS = 35;
public MonsterThread(MonsterView monsterSurface){
this.monsterSurface = monsterSurface;
this.running = false;
}
#Override
public void run() {
long ticksPS = 1000 / FPS;
long startTime;
long sleepTime;
while(running){
Canvas c = null;
startTime = System.currentTimeMillis();
try{
c = monsterSurface.getHolder().lockCanvas();
synchronized (monsterSurface.getHolder()){
monsterSurface.onDraw(c);
}
} finally {
if( c!= null){
monsterSurface.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
try {
if(sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e){}
}
}
public MonsterView getMonsterSurface() {
return monsterSurface;
}
public void setMonsterSurface(MonsterView monsterSurface) {
this.monsterSurface = monsterSurface;
}
public boolean isRunning() {
return running;
}
public void setRunning(boolean running) {
this.running = running;
}
Sprite :
public class Sprite {
private static final int BMP_ROWS = 4;
private static final int BMP_COLUMNS = 3;
private int x = 0;
private int y = 0;
private int xSpeed = 5;
private MonsterView monsterView;
private Bitmap bmp;
private int currentFrame = 0;
private int width;
private int height;
private int directionX;
public Sprite(MonsterView monsterView, Bitmap bmp) {
this.monsterView = monsterView;
this.bmp=bmp;
this.width = bmp.getWidth() / BMP_COLUMNS;
this.height = bmp.getHeight() / BMP_ROWS;
this.directionX = 2;
}
private void update() {
if (x > monsterView.getWidth() - width - xSpeed) {
xSpeed = -5;
directionX = 1;
}
if (x + xSpeed < 0) {
xSpeed = 5;
directionX = 2;
}
x = x + xSpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
Log.d("test", ""+currentFrame);
}
public void onDraw(Canvas canvas) {
update();
int srcX = currentFrame * width;
int srcY = directionX * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
You're using setZOrderOnTop(), which is putting the Surface part of the SurfaceView on a layer above everything else. (By default, it's a separate layer below everything else.) When you clear it with canvas.drawRGB(0, 0, 0) you're setting the entire layer to opaque black, which is going to obscure the View layer beneath it.
If instead you clear it to transparent black, with canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR), you should get the results you want.
FWIW, you shouldn't override onDraw() if you're only drawing on the Surface. The onDraw() method is called by the View hierarchy to draw on the View part of the SurfaceView. If something manages to invalidate the SurfaceView's View, your onDraw() will be called, and you'll end up with a character sprite on the View layer. (Depending on your layout this may not be visible.) Just give the method a different name.
There are a number of ways to handle this, but generally, the way to do this is by maintaining a background layer (which is just another image), and sprite layers. Instead of clearing, at each frame you blit (copy) your background onto the surface (which erases everything), then you blit your sprites.
So you're going to have to draw the background bitmap onto the surface first before drawing your sprite. Right now you're drawing black which is covering your background layouts.
Alternatively you might be able to do canvas.drawRect with a Paint with paint.setColor to Color.Transparent.
I am making my first game using LibGDX on android.
I have a background which is 288*511, Now in my game, I need to repeat that background and then translate over it. I have made that game for desktop using Slick2D, and had the same problem, just a bit lower than on my LG G2 phone (4.0.4), is there a way to fix this lag or I am doing something wrong?
The problem is that when it's translating, its moving fine and sometimes jumps 1-2 pixels forward or just stuck for 0.5 seconds or so.
This is my class:
public class Background {
private class RepeatedBackground implements GameObject {
private int x;
private int y = 0;
Sprite background;
public RepeatedBackground(int x, Sprite s) {
this.x = x;
this.background = s;
}
#Override
public void render() {
}
public float getPreferedWidth() {
int w = Gdx.graphics.getWidth();
return (float) (w / 1.15);
}
public float getPreferedHeight() {
int h = Gdx.graphics.getHeight();
return (float) (h / 1.15);
}
#Override
public int getX() {
return this.x;
}
#Override
public int getY() {
return this.y;
}
public Sprite getSprite() {
return this.background;
}
}
private int tra = 0;
private long traTime = 0;
private List<RepeatedBackground> backgrounds = new ArrayList<RepeatedBackground>();
private Level level;
private SpriteBatch backgroundRenderer;
public Background(Level level) {
this.level = level;
this.backgroundRenderer = new SpriteBatch();
}
public void generateBackgrounds() {
int x = 0;
Sprite background = this.level.getFactory().createBackgroundSprite();
for (int i = 0; i < LevelConfig.MAX_BACKGROUND_REPEATS; i++) {
this.backgrounds.add(new RepeatedBackground(x, background));
x += background.getWidth();
}
}
public void render() {
this.backgroundRenderer.getTransformMatrix().translate(-6, 0, 0);
this.backgroundRenderer.begin();
this.backgroundRenderer.setProjectionMatrix(this.level.getInstance().getCamera().combined);
Iterator<RepeatedBackground> itr = this.backgrounds.iterator();
while (itr.hasNext()) {
RepeatedBackground b = itr.next();
Sprite s = b.getSprite();
if (b.getX() - b.getPreferedHeight() < this.level.getInstance().getCamera().viewportWidth) { // this doesn't work properly, but it doesn't load all backgorunds at once but still lags..
this.backgroundRenderer.draw(s, b.getX(), b.getY(), b.getPreferedWidth(), b.getPreferedHeight());
}
}
this.backgroundRenderer.end();
}
}
My create values for camera:
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera = new OrthographicCamera(w,h);
camera.setToOrtho(false);
batch = new SpriteBatch();
Texture.setEnforcePotImages(false);
You can use ParallaxBackground class from here
http://www.badlogicgames.com/forum/viewtopic.php?f=17&t=1795
It doesn't depends on the size of the image or camera. It just translates your background continuously
source: http://code.google.com/p/libgdx-users/wiki/ParallaxBackgound